1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright 2018 Nexenta Systems, Inc.
  28  */
  29 
  30 /*
  31  * Fibre Channel SCSI ULP Mapping driver
  32  */
  33 
  34 #include <sys/scsi/scsi.h>
  35 #include <sys/types.h>
  36 #include <sys/varargs.h>
  37 #include <sys/devctl.h>
  38 #include <sys/thread.h>
  39 #include <sys/thread.h>
  40 #include <sys/open.h>
  41 #include <sys/file.h>
  42 #include <sys/sunndi.h>
  43 #include <sys/console.h>
  44 #include <sys/proc.h>
  45 #include <sys/time.h>
  46 #include <sys/utsname.h>
  47 #include <sys/scsi/impl/scsi_reset_notify.h>
  48 #include <sys/ndi_impldefs.h>
  49 #include <sys/byteorder.h>
  50 #include <sys/ctype.h>
  51 #include <sys/sunmdi.h>
  52 
  53 #include <sys/fibre-channel/fc.h>
  54 #include <sys/fibre-channel/impl/fc_ulpif.h>
  55 #include <sys/fibre-channel/ulp/fcpvar.h>
  56 
  57 /*
  58  * Discovery Process
  59  * =================
  60  *
  61  *    The discovery process is a major function of FCP.  In order to help
  62  * understand that function a flow diagram is given here.  This diagram
  63  * doesn't claim to cover all the cases and the events that can occur during
  64  * the discovery process nor the subtleties of the code.  The code paths shown
  65  * are simplified.  Its purpose is to help the reader (and potentially bug
  66  * fixer) have an overall view of the logic of the code.  For that reason the
  67  * diagram covers the simple case of the line coming up cleanly or of a new
  68  * port attaching to FCP the link being up.  The reader must keep in mind
  69  * that:
  70  *
  71  *      - There are special cases where bringing devices online and offline
  72  *        is driven by Ioctl.
  73  *
  74  *      - The behavior of the discovery process can be modified through the
  75  *        .conf file.
  76  *
  77  *      - The line can go down and come back up at any time during the
  78  *        discovery process which explains some of the complexity of the code.
  79  *
  80  * ............................................................................
  81  *
  82  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
  83  *
  84  *
  85  *                      +-------------------------+
  86  *   fp/fctl module --->|    fcp_port_attach   |
  87  *                      +-------------------------+
  88  *         |                         |
  89  *         |                         |
  90  *         |                         v
  91  *         |            +-------------------------+
  92  *         |            | fcp_handle_port_attach  |
  93  *         |            +-------------------------+
  94  *         |                            |
  95  *         |                            |
  96  *         +--------------------+       |
  97  *                              |       |
  98  *                              v       v
  99  *                      +-------------------------+
 100  *                      |   fcp_statec_callback   |
 101  *                      +-------------------------+
 102  *                                  |
 103  *                                  |
 104  *                                  v
 105  *                      +-------------------------+
 106  *                      |    fcp_handle_devices   |
 107  *                      +-------------------------+
 108  *                                  |
 109  *                                  |
 110  *                                  v
 111  *                      +-------------------------+
 112  *                      |   fcp_handle_mapflags   |
 113  *                      +-------------------------+
 114  *                                  |
 115  *                                  |
 116  *                                  v
 117  *                      +-------------------------+
 118  *                      |     fcp_send_els        |
 119  *                      |                         |
 120  *                      | PLOGI or PRLI To all the|
 121  *                      | reachable devices.      |
 122  *                      +-------------------------+
 123  *
 124  *
 125  * ............................................................................
 126  *
 127  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
 128  *         STEP 1 are called (it is actually the same function).
 129  *
 130  *
 131  *                      +-------------------------+
 132  *                      |    fcp_icmd_callback    |
 133  *   fp/fctl module --->|                      |
 134  *                      | callback for PLOGI and  |
 135  *                      | PRLI.                   |
 136  *                      +-------------------------+
 137  *                                   |
 138  *                                   |
 139  *          Received PLOGI Accept   /-\   Received PRLI Accept
 140  *                     _ _ _ _ _ _ /   \_ _ _ _ _ _
 141  *                    |            \   /           |
 142  *                    |             \-/            |
 143  *                    |                            |
 144  *                    v                            v
 145  *      +-------------------------+     +-------------------------+
 146  *      |     fcp_send_els        |     |     fcp_send_scsi       |
 147  *      |                         |     |                         |
 148  *      |         PRLI            |     |       REPORT_LUN        |
 149  *      +-------------------------+     +-------------------------+
 150  *
 151  * ............................................................................
 152  *
 153  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
 154  *         (It is actually the same function).
 155  *
 156  *
 157  *                          +-------------------------+
 158  *   fp/fctl module ------->|         fcp_scsi_callback    |
 159  *                          +-------------------------+
 160  *                                      |
 161  *                                      |
 162  *                                      |
 163  *      Receive REPORT_LUN reply       /-\      Receive INQUIRY PAGE83 reply
 164  *                _ _ _ _ _ _ _ _ _ _ /   \_ _ _ _ _ _ _ _ _ _ _ _
 165  *               |                    \   /                       |
 166  *               |                     \-/                        |
 167  *               |                      |                         |
 168  *               | Receive INQUIRY reply|                         |
 169  *               |                      |                         |
 170  *               v                      v                         v
 171  * +------------------------+ +----------------------+ +----------------------+
 172  * |  fcp_handle_reportlun  | |  fcp_handle_inquiry  | |  fcp_handle_page83   |
 173  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
 174  * +------------------------+ +----------------------+ +----------------------+
 175  *               |                      |                         |
 176  *               |                      |                         |
 177  *               |                      |                         |
 178  *               v                      v                         |
 179  *     +-----------------+      +-----------------+               |
 180  *     |  fcp_send_scsi  |      |  fcp_send_scsi  |               |
 181  *     |                 |      |                 |               |
 182  *     |     INQUIRY     |      | INQUIRY PAGE83  |               |
 183  *     |  (To each LUN)  |      +-----------------+               |
 184  *     +-----------------+                                        |
 185  *                                                                |
 186  *                                                                v
 187  *                                                    +------------------------+
 188  *                                                    |  fcp_call_finish_init  |
 189  *                                                    +------------------------+
 190  *                                                                |
 191  *                                                                v
 192  *                                               +-----------------------------+
 193  *                                               |  fcp_call_finish_init_held  |
 194  *                                               +-----------------------------+
 195  *                                                                |
 196  *                                                                |
 197  *                         All LUNs scanned                      /-\
 198  *                             _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
 199  *                            |                                 \   /
 200  *                            |                                  \-/
 201  *                            v                                   |
 202  *                   +------------------+                         |
 203  *                   |  fcp_finish_tgt  |                         |
 204  *                   +------------------+                         |
 205  *                            |   Target Not Offline and          |
 206  *  Target Not Offline and    |   not marked and tgt_node_state   |
 207  *  marked                   /-\  not FCP_TGT_NODE_ON_DEMAND      |
 208  *              _ _ _ _ _ _ /   \_ _ _ _ _ _ _ _                  |
 209  *             |            \   /               |                 |
 210  *             |             \-/                |                 |
 211  *             v                                v                 |
 212  * +----------------------------+     +-------------------+       |
 213  * |     fcp_offline_target     |     |  fcp_create_luns  |       |
 214  * |                            |     +-------------------+       |
 215  * | A structure fcp_tgt_elem   |               |                 |
 216  * | is created and queued in   |               v                 |
 217  * | the FCP port list          |     +-------------------+       |
 218  * | port_offline_tgts.  It     |     |  fcp_pass_to_hp   |       |
 219  * | will be unqueued by the    |     |                   |       |
 220  * | watchdog timer.            |     | Called for each   |       |
 221  * +----------------------------+     | LUN. Dispatches   |       |
 222  *                |                   | fcp_hp_task       |       |
 223  *                |                   +-------------------+       |
 224  *                |                             |                 |
 225  *                |                             |                 |
 226  *                |                             |                 |
 227  *                |                             +---------------->|
 228  *                |                                               |
 229  *                +---------------------------------------------->|
 230  *                                                                |
 231  *                                                                |
 232  *              All the targets (devices) have been scanned      /-\
 233  *                              _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /   \
 234  *                             |                                \   /
 235  *                             |                                 \-/
 236  *          +-------------------------------------+               |
 237  *          |           fcp_finish_init           |               |
 238  *          |                                     |               |
 239  *          | Signal broadcasts the condition     |               |
 240  *          | variable port_config_cv of the FCP  |               |
 241  *          | port.  One potential code sequence  |               |
 242  *          | waiting on the condition variable   |               |
 243  *          | the code sequence handling          |               |
 244  *          | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|               |
 245  *          | The other is in the function        |               |
 246  *          | fcp_reconfig_wait which is called   |               |
 247  *          | in the transmit path preventing IOs |               |
 248  *          | from going through till the disco-  |               |
 249  *          | very process is over.               |               |
 250  *          +-------------------------------------+               |
 251  *                             |                                  |
 252  *                             |                                  |
 253  *                             +--------------------------------->|
 254  *                                                                |
 255  *                                                                v
 256  *                                                              Return
 257  *
 258  * ............................................................................
 259  *
 260  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
 261  *
 262  *
 263  *                      +-------------------------+
 264  *                      |      fcp_hp_task        |
 265  *                      +-------------------------+
 266  *                                   |
 267  *                                   |
 268  *                                   v
 269  *                      +-------------------------+
 270  *                      |     fcp_trigger_lun     |
 271  *                      +-------------------------+
 272  *                                   |
 273  *                                   |
 274  *                                   v
 275  *                 Bring offline    /-\  Bring online
 276  *                _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
 277  *               |                 \   /                   |
 278  *               |                  \-/                    |
 279  *               v                                         v
 280  *    +---------------------+                   +-----------------------+
 281  *    |  fcp_offline_child  |                   |      fcp_get_cip      |
 282  *    +---------------------+                   |                       |
 283  *                                              | Creates a dev_info_t  |
 284  *                                              | or a mdi_pathinfo_t   |
 285  *                                              | depending on whether  |
 286  *                                              | mpxio is on or off.   |
 287  *                                              +-----------------------+
 288  *                                                         |
 289  *                                                         |
 290  *                                                         v
 291  *                                              +-----------------------+
 292  *                                              |  fcp_online_child     |
 293  *                                              |                       |
 294  *                                              | Set device online     |
 295  *                                              | using NDI or MDI.     |
 296  *                                              +-----------------------+
 297  *
 298  * ............................................................................
 299  *
 300  * STEP 5: The watchdog timer expires.  The watch dog timer does much more that
 301  *         what is described here.  We only show the target offline path.
 302  *
 303  *
 304  *                       +--------------------------+
 305  *                       |        fcp_watch         |
 306  *                       +--------------------------+
 307  *                                     |
 308  *                                     |
 309  *                                     v
 310  *                       +--------------------------+
 311  *                       |  fcp_scan_offline_tgts   |
 312  *                       +--------------------------+
 313  *                                     |
 314  *                                     |
 315  *                                     v
 316  *                       +--------------------------+
 317  *                       |  fcp_offline_target_now  |
 318  *                       +--------------------------+
 319  *                                     |
 320  *                                     |
 321  *                                     v
 322  *                       +--------------------------+
 323  *                       |   fcp_offline_tgt_luns   |
 324  *                       +--------------------------+
 325  *                                     |
 326  *                                     |
 327  *                                     v
 328  *                       +--------------------------+
 329  *                       |     fcp_offline_lun      |
 330  *                       +--------------------------+
 331  *                                     |
 332  *                                     |
 333  *                                     v
 334  *                   +----------------------------------+
 335  *                   |       fcp_offline_lun_now        |
 336  *                   |                                  |
 337  *                   | A request (or two if mpxio) is   |
 338  *                   | sent to the hot plug task using  |
 339  *                   | a fcp_hp_elem structure.         |
 340  *                   +----------------------------------+
 341  */
 342 
 343 /*
 344  * Functions registered with DDI framework
 345  */
 346 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
 347 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 348 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
 349 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
 350 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 351     cred_t *credp, int *rval);
 352 
 353 /*
 354  * Functions registered with FC Transport framework
 355  */
 356 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 357     fc_attach_cmd_t cmd,  uint32_t s_id);
 358 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
 359     fc_detach_cmd_t cmd);
 360 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
 361     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
 362     uint32_t claimed);
 363 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
 364     fc_unsol_buf_t *buf, uint32_t claimed);
 365 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
 366     fc_unsol_buf_t *buf, uint32_t claimed);
 367 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
 368     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
 369     uint32_t  dev_cnt, uint32_t port_sid);
 370 
 371 /*
 372  * Functions registered with SCSA framework
 373  */
 374 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 375     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 376 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 377     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 378 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 379     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 380 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 381 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 382 static int fcp_scsi_reset(struct scsi_address *ap, int level);
 383 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
 384 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 385     int whom);
 386 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
 387 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
 388     void (*callback)(caddr_t), caddr_t arg);
 389 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
 390     char *name, ddi_eventcookie_t *event_cookiep);
 391 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
 392     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
 393     ddi_callback_id_t *cb_id);
 394 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
 395     ddi_callback_id_t cb_id);
 396 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
 397     ddi_eventcookie_t eventid, void *impldata);
 398 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
 399     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 400 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
 401     ddi_bus_config_op_t op, void *arg);
 402 
 403 /*
 404  * Internal functions
 405  */
 406 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
 407     int mode, int *rval);
 408 
 409 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
 410     int mode, int *rval);
 411 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
 412     struct fcp_scsi_cmd *fscsi, int mode);
 413 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
 414     caddr_t base_addr, int mode);
 415 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
 416 
 417 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
 418     la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state,
 419     int *fc_pkt_reason, int *fc_pkt_action);
 420 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
 421     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
 422 static int fcp_tgt_send_prli(struct fcp_tgt     *ptgt, int *fc_status,
 423     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
 424 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
 425 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
 426 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
 427 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
 428 
 429 static void fcp_handle_devices(struct fcp_port *pptr,
 430     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
 431     fcp_map_tag_t *map_tag, int cause);
 432 static int fcp_handle_mapflags(struct fcp_port *pptr,
 433     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
 434     int tgt_cnt, int cause);
 435 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
 436 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 437     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
 438 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
 439     int cause);
 440 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
 441     uint32_t state);
 442 static struct fcp_port *fcp_get_port(opaque_t port_handle);
 443 static void fcp_unsol_callback(fc_packet_t *fpkt);
 444 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
 445     uchar_t r_ctl, uchar_t type);
 446 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
 447 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
 448     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
 449     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
 450 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
 451 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
 452     int nodma, int flags);
 453 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
 454 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
 455     uchar_t *wwn);
 456 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
 457     uint32_t d_id);
 458 static void fcp_icmd_callback(fc_packet_t *fpkt);
 459 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
 460     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
 461 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
 462 static void fcp_scsi_callback(fc_packet_t *fpkt);
 463 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
 464 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
 465 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
 466 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
 467     uint16_t lun_num);
 468 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 469     int link_cnt, int tgt_cnt, int cause);
 470 static void fcp_finish_init(struct fcp_port *pptr);
 471 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
 472     int tgt_cnt, int cause);
 473 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
 474     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
 475 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 476     int link_cnt, int tgt_cnt, int nowait, int flags);
 477 static void fcp_offline_target_now(struct fcp_port *pptr,
 478     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
 479 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
 480     int tgt_cnt, int flags);
 481 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
 482     int nowait, int flags);
 483 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
 484     int tgt_cnt);
 485 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
 486     int tgt_cnt, int flags);
 487 static void fcp_scan_offline_luns(struct fcp_port *pptr);
 488 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
 489 static void fcp_update_offline_flags(struct fcp_lun *plun);
 490 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
 491 static void fcp_abort_commands(struct fcp_pkt *head, struct
 492     fcp_port *pptr);
 493 static void fcp_cmd_callback(fc_packet_t *fpkt);
 494 static void fcp_complete_pkt(fc_packet_t *fpkt);
 495 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
 496     struct fcp_port *pptr);
 497 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 498     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
 499 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
 500 static void fcp_dealloc_lun(struct fcp_lun *plun);
 501 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
 502     fc_portmap_t *map_entry, int link_cnt);
 503 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
 504 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
 505 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
 506     int internal);
 507 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
 508 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 509     uint32_t s_id, int instance);
 510 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
 511     int instance);
 512 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
 513 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
 514     int);
 515 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
 516 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
 517 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
 518     int flags);
 519 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
 520 static int fcp_reset_target(struct scsi_address *ap, int level);
 521 static int fcp_commoncap(struct scsi_address *ap, char *cap,
 522     int val, int tgtonly, int doset);
 523 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
 524 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
 525 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
 526     int sleep);
 527 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 528     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
 529 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
 530 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
 531 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
 532     int lcount, int tcount);
 533 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
 534 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
 535 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
 536     int tgt_cnt);
 537 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
 538     dev_info_t *pdip, caddr_t name);
 539 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
 540     int lcount, int tcount, int flags, int *circ);
 541 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
 542     int lcount, int tcount, int flags, int *circ);
 543 static void fcp_remove_child(struct fcp_lun *plun);
 544 static void fcp_watch(void *arg);
 545 static void fcp_check_reset_delay(struct fcp_port *pptr);
 546 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
 547     struct fcp_lun *rlun, int tgt_cnt);
 548 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
 549 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
 550     uchar_t *wwn, uint16_t lun);
 551 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
 552     struct fcp_lun *plun);
 553 static void fcp_post_callback(struct fcp_pkt *cmd);
 554 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
 555 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
 556 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
 557     child_info_t *cip);
 558 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
 559     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
 560     int tgt_cnt, int flags);
 561 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
 562     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
 563     int tgt_cnt, int flags, int wait);
 564 static void fcp_retransport_cmd(struct fcp_port *pptr,
 565     struct fcp_pkt *cmd);
 566 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
 567     uint_t statistics);
 568 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
 569 static void fcp_update_targets(struct fcp_port *pptr,
 570     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
 571 static int fcp_call_finish_init(struct fcp_port *pptr,
 572     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
 573 static int fcp_call_finish_init_held(struct fcp_port *pptr,
 574     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
 575 static void fcp_reconfigure_luns(void * tgt_handle);
 576 static void fcp_free_targets(struct fcp_port *pptr);
 577 static void fcp_free_target(struct fcp_tgt *ptgt);
 578 static int fcp_is_retryable(struct fcp_ipkt *icmd);
 579 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
 580 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
 581 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
 582 static void fcp_print_error(fc_packet_t *fpkt);
 583 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
 584     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
 585 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
 586 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
 587     uint32_t *dev_cnt);
 588 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
 589 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
 590 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
 591     struct fcp_ioctl *, struct fcp_port **);
 592 static char *fcp_get_lun_path(struct fcp_lun *plun);
 593 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
 594     int *rval);
 595 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
 596 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
 597 static char *fcp_get_lun_path(struct fcp_lun *plun);
 598 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
 599     int *rval);
 600 static void fcp_reconfig_wait(struct fcp_port *pptr);
 601 
 602 /*
 603  * New functions added for mpxio support
 604  */
 605 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 606     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 607 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
 608     int tcount);
 609 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
 610     dev_info_t *pdip);
 611 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
 612 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
 613 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
 614 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
 615 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
 616     int what);
 617 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
 618     fc_packet_t *fpkt);
 619 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
 620 
 621 /*
 622  * New functions added for lun masking support
 623  */
 624 static void fcp_read_blacklist(dev_info_t *dip,
 625     struct fcp_black_list_entry **pplun_blacklist);
 626 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
 627     struct fcp_black_list_entry **pplun_blacklist);
 628 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
 629     struct fcp_black_list_entry **pplun_blacklist);
 630 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
 631 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
 632 
 633 /*
 634  * New functions to support software FCA (like fcoei)
 635  */
 636 static struct scsi_pkt *fcp_pseudo_init_pkt(
 637         struct scsi_address *ap, struct scsi_pkt *pkt,
 638         struct buf *bp, int cmdlen, int statuslen,
 639         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 640 static void fcp_pseudo_destroy_pkt(
 641         struct scsi_address *ap, struct scsi_pkt *pkt);
 642 static void fcp_pseudo_sync_pkt(
 643         struct scsi_address *ap, struct scsi_pkt *pkt);
 644 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 645 static void fcp_pseudo_dmafree(
 646         struct scsi_address *ap, struct scsi_pkt *pkt);
 647 
 648 extern struct mod_ops   mod_driverops;
 649 /*
 650  * This variable is defined in modctl.c and set to '1' after the root driver
 651  * and fs are loaded.  It serves as an indication that the root filesystem can
 652  * be used.
 653  */
 654 extern int              modrootloaded;
 655 /*
 656  * This table contains strings associated with the SCSI sense key codes.  It
 657  * is used by FCP to print a clear explanation of the code returned in the
 658  * sense information by a device.
 659  */
 660 extern char             *sense_keys[];
 661 /*
 662  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 663  * under this device that the paths to a physical device are created when
 664  * MPxIO is used.
 665  */
 666 extern dev_info_t       *scsi_vhci_dip;
 667 
 668 /*
 669  * Report lun processing
 670  */
 671 #define FCP_LUN_ADDRESSING              0x80
 672 #define FCP_PD_ADDRESSING               0x00
 673 #define FCP_VOLUME_ADDRESSING           0x40
 674 
 675 #define FCP_SVE_THROTTLE                0x28 /* Vicom */
 676 #define MAX_INT_DMA                     0x7fffffff
 677 /*
 678  * Property definitions
 679  */
 680 #define NODE_WWN_PROP   (char *)fcp_node_wwn_prop
 681 #define PORT_WWN_PROP   (char *)fcp_port_wwn_prop
 682 #define TARGET_PROP     (char *)fcp_target_prop
 683 #define LUN_PROP        (char *)fcp_lun_prop
 684 #define SAM_LUN_PROP    (char *)fcp_sam_lun_prop
 685 #define CONF_WWN_PROP   (char *)fcp_conf_wwn_prop
 686 #define OBP_BOOT_WWN    (char *)fcp_obp_boot_wwn
 687 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only
 688 #define INIT_PORT_PROP  (char *)fcp_init_port_prop
 689 #define TGT_PORT_PROP   (char *)fcp_tgt_port_prop
 690 #define LUN_BLACKLIST_PROP      (char *)fcp_lun_blacklist_prop
 691 /*
 692  * Short hand macros.
 693  */
 694 #define LUN_PORT        (plun->lun_tgt->tgt_port)
 695 #define LUN_TGT         (plun->lun_tgt)
 696 
 697 /*
 698  * Driver private macros
 699  */
 700 #define FCP_ATOB(x)     (((x) >= '0' && (x) <= '9') ? ((x) - '0') :       \
 701                         ((x) >= 'a' && (x) <= 'f') ?                      \
 702                         ((x) - 'a' + 10) : ((x) - 'A' + 10))
 703 
 704 #define FCP_MAX(a, b)   ((a) > (b) ? (a) : (b))
 705 
 706 #define FCP_N_NDI_EVENTS                                                \
 707         (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
 708 
 709 #define FCP_LINK_STATE_CHANGED(p, c)                    \
 710         ((p)->port_link_cnt != (c)->ipkt_link_cnt)
 711 
 712 #define FCP_TGT_STATE_CHANGED(t, c)                     \
 713         ((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
 714 
 715 #define FCP_STATE_CHANGED(p, t, c)              \
 716         (FCP_TGT_STATE_CHANGED(t, c))
 717 
 718 #define FCP_MUST_RETRY(fpkt)                            \
 719         ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||    \
 720         (fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||     \
 721         (fpkt)->pkt_state == FC_PKT_TRAN_BSY ||      \
 722         (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||       \
 723         (fpkt)->pkt_state == FC_PKT_NPORT_BSY ||     \
 724         (fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||    \
 725         (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||  \
 726         (fpkt)->pkt_reason == FC_REASON_OFFLINE)
 727 
 728 #define FCP_SENSE_REPORTLUN_CHANGED(es)         \
 729         ((es)->es_key == KEY_UNIT_ATTENTION &&       \
 730         (es)->es_add_code == 0x3f &&         \
 731         (es)->es_qual_code == 0x0e)
 732 
 733 #define FCP_SENSE_NO_LUN(es)                    \
 734         ((es)->es_key == KEY_ILLEGAL_REQUEST &&      \
 735         (es)->es_add_code == 0x25 &&         \
 736         (es)->es_qual_code == 0x0)
 737 
 738 #define FCP_VERSION             "20091208-1.192"
 739 #define FCP_NAME_VERSION        "SunFC FCP v" FCP_VERSION
 740 
 741 #define FCP_NUM_ELEMENTS(array)                 \
 742         (sizeof (array) / sizeof ((array)[0]))
 743 
 744 /*
 745  * Debugging, Error reporting, and tracing
 746  */
 747 #define FCP_LOG_SIZE            1024 * 1024
 748 
 749 #define FCP_LEVEL_1             0x00001         /* attach/detach PM CPR */
 750 #define FCP_LEVEL_2             0x00002         /* failures/Invalid data */
 751 #define FCP_LEVEL_3             0x00004         /* state change, discovery */
 752 #define FCP_LEVEL_4             0x00008         /* ULP messages */
 753 #define FCP_LEVEL_5             0x00010         /* ELS/SCSI cmds */
 754 #define FCP_LEVEL_6             0x00020         /* Transport failures */
 755 #define FCP_LEVEL_7             0x00040
 756 #define FCP_LEVEL_8             0x00080         /* I/O tracing */
 757 #define FCP_LEVEL_9             0x00100         /* I/O tracing */
 758 
 759 
 760 
 761 /*
 762  * Log contents to system messages file
 763  */
 764 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
 765 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
 766 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
 767 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
 768 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
 769 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
 770 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
 771 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
 772 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
 773 
 774 
 775 /*
 776  * Log contents to trace buffer
 777  */
 778 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
 779 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
 780 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
 781 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
 782 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
 783 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
 784 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
 785 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
 786 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
 787 
 788 
 789 /*
 790  * Log contents to both system messages file and trace buffer
 791  */
 792 #define FCP_MSG_BUF_LEVEL_1     (FCP_LEVEL_1 | FC_TRACE_LOG_BUF |       \
 793                                 FC_TRACE_LOG_MSG)
 794 #define FCP_MSG_BUF_LEVEL_2     (FCP_LEVEL_2 | FC_TRACE_LOG_BUF |       \
 795                                 FC_TRACE_LOG_MSG)
 796 #define FCP_MSG_BUF_LEVEL_3     (FCP_LEVEL_3 | FC_TRACE_LOG_BUF |       \
 797                                 FC_TRACE_LOG_MSG)
 798 #define FCP_MSG_BUF_LEVEL_4     (FCP_LEVEL_4 | FC_TRACE_LOG_BUF |       \
 799                                 FC_TRACE_LOG_MSG)
 800 #define FCP_MSG_BUF_LEVEL_5     (FCP_LEVEL_5 | FC_TRACE_LOG_BUF |       \
 801                                 FC_TRACE_LOG_MSG)
 802 #define FCP_MSG_BUF_LEVEL_6     (FCP_LEVEL_6 | FC_TRACE_LOG_BUF |       \
 803                                 FC_TRACE_LOG_MSG)
 804 #define FCP_MSG_BUF_LEVEL_7     (FCP_LEVEL_7 | FC_TRACE_LOG_BUF |       \
 805                                 FC_TRACE_LOG_MSG)
 806 #define FCP_MSG_BUF_LEVEL_8     (FCP_LEVEL_8 | FC_TRACE_LOG_BUF |       \
 807                                 FC_TRACE_LOG_MSG)
 808 #define FCP_MSG_BUF_LEVEL_9     (FCP_LEVEL_9 | FC_TRACE_LOG_BUF |       \
 809                                 FC_TRACE_LOG_MSG)
 810 #ifdef DEBUG
 811 #define FCP_DTRACE      fc_trace_debug
 812 #else
 813 #define FCP_DTRACE
 814 #endif
 815 
 816 #define FCP_TRACE       fc_trace_debug
 817 
 818 static struct cb_ops fcp_cb_ops = {
 819         fcp_open,                       /* open */
 820         fcp_close,                      /* close */
 821         nodev,                          /* strategy */
 822         nodev,                          /* print */
 823         nodev,                          /* dump */
 824         nodev,                          /* read */
 825         nodev,                          /* write */
 826         fcp_ioctl,                      /* ioctl */
 827         nodev,                          /* devmap */
 828         nodev,                          /* mmap */
 829         nodev,                          /* segmap */
 830         nochpoll,                       /* chpoll */
 831         ddi_prop_op,                    /* cb_prop_op */
 832         0,                              /* streamtab */
 833         D_NEW | D_MP | D_HOTPLUG,       /* cb_flag */
 834         CB_REV,                         /* rev */
 835         nodev,                          /* aread */
 836         nodev                           /* awrite */
 837 };
 838 
 839 
 840 static struct dev_ops fcp_ops = {
 841         DEVO_REV,
 842         0,
 843         ddi_getinfo_1to1,
 844         nulldev,                /* identify */
 845         nulldev,                /* probe */
 846         fcp_attach,             /* attach and detach are mandatory */
 847         fcp_detach,
 848         nodev,                  /* reset */
 849         &fcp_cb_ops,                /* cb_ops */
 850         NULL,                   /* bus_ops */
 851         NULL,                   /* power */
 852 };
 853 
 854 
 855 char *fcp_version = FCP_NAME_VERSION;
 856 
 857 static struct modldrv modldrv = {
 858         &mod_driverops,
 859         FCP_NAME_VERSION,
 860         &fcp_ops
 861 };
 862 
 863 
 864 static struct modlinkage modlinkage = {
 865         MODREV_1,
 866         &modldrv,
 867         NULL
 868 };
 869 
 870 
 871 static fc_ulp_modinfo_t fcp_modinfo = {
 872         &fcp_modinfo,                       /* ulp_handle */
 873         FCTL_ULP_MODREV_4,              /* ulp_rev */
 874         FC4_SCSI_FCP,                   /* ulp_type */
 875         "fcp",                          /* ulp_name */
 876         FCP_STATEC_MASK,                /* ulp_statec_mask */
 877         fcp_port_attach,                /* ulp_port_attach */
 878         fcp_port_detach,                /* ulp_port_detach */
 879         fcp_port_ioctl,                 /* ulp_port_ioctl */
 880         fcp_els_callback,               /* ulp_els_callback */
 881         fcp_data_callback,              /* ulp_data_callback */
 882         fcp_statec_callback             /* ulp_statec_callback */
 883 };
 884 
 885 #ifdef  DEBUG
 886 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 887                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 888                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 889                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 890 #else
 891 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 892                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 893                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 894                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 895 #endif
 896 
 897 /* FCP global variables */
 898 int                     fcp_bus_config_debug = 0;
 899 static int              fcp_log_size = FCP_LOG_SIZE;
 900 static int              fcp_trace = FCP_TRACE_DEFAULT;
 901 static fc_trace_logq_t  *fcp_logq = NULL;
 902 static struct fcp_black_list_entry      *fcp_lun_blacklist = NULL;
 903 /*
 904  * The auto-configuration is set by default.  The only way of disabling it is
 905  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
 906  */
 907 static int              fcp_enable_auto_configuration = 1;
 908 static int              fcp_max_bus_config_retries      = 4;
 909 static int              fcp_lun_ready_retry = 300;
 910 /*
 911  * The value assigned to the following variable has changed several times due
 912  * to a problem with the data underruns reporting of some firmware(s).  The
 913  * current value of 50 gives a timeout value of 25 seconds for a max number
 914  * of 256 LUNs.
 915  */
 916 static int              fcp_max_target_retries = 50;
 917 /*
 918  * Watchdog variables
 919  * ------------------
 920  *
 921  * fcp_watchdog_init
 922  *
 923  *      Indicates if the watchdog timer is running or not.  This is actually
 924  *      a counter of the number of Fibre Channel ports that attached.  When
 925  *      the first port attaches the watchdog is started.  When the last port
 926  *      detaches the watchdog timer is stopped.
 927  *
 928  * fcp_watchdog_time
 929  *
 930  *      This is the watchdog clock counter.  It is incremented by
 931  *      fcp_watchdog_time each time the watchdog timer expires.
 932  *
 933  * fcp_watchdog_timeout
 934  *
 935  *      Increment value of the variable fcp_watchdog_time as well as the
 936  *      the timeout value of the watchdog timer.  The unit is 1 second.  It
 937  *      is strange that this is not a #define   but a variable since the code
 938  *      never changes this value.  The reason why it can be said that the
 939  *      unit is 1 second is because the number of ticks for the watchdog
 940  *      timer is determined like this:
 941  *
 942  *          fcp_watchdog_tick = fcp_watchdog_timeout *
 943  *                                drv_usectohz(1000000);
 944  *
 945  *      The value 1000000 is hard coded in the code.
 946  *
 947  * fcp_watchdog_tick
 948  *
 949  *      Watchdog timer value in ticks.
 950  */
 951 static int              fcp_watchdog_init = 0;
 952 static int              fcp_watchdog_time = 0;
 953 static int              fcp_watchdog_timeout = 1;
 954 static int              fcp_watchdog_tick;
 955 
 956 /*
 957  * fcp_offline_delay is a global variable to enable customisation of
 958  * the timeout on link offlines or RSCNs. The default value is set
 959  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
 960  * specified in FCP4 Chapter 11 (see www.t10.org).
 961  *
 962  * The variable fcp_offline_delay is specified in SECONDS.
 963  *
 964  * If we made this a static var then the user would not be able to
 965  * change it. This variable is set in fcp_attach().
 966  */
 967 unsigned int            fcp_offline_delay = FCP_OFFLINE_DELAY;
 968 
 969 static void             *fcp_softstate = NULL; /* for soft state */
 970 static uchar_t          fcp_oflag = FCP_IDLE; /* open flag */
 971 static kmutex_t         fcp_global_mutex;
 972 static kmutex_t         fcp_ioctl_mutex;
 973 static dev_info_t       *fcp_global_dip = NULL;
 974 static timeout_id_t     fcp_watchdog_id;
 975 const char              *fcp_lun_prop = "lun";
 976 const char              *fcp_sam_lun_prop = "sam-lun";
 977 const char              *fcp_target_prop = "target";
 978 /*
 979  * NOTE: consumers of "node-wwn" property include stmsboot in ON
 980  * consolidation.
 981  */
 982 const char              *fcp_node_wwn_prop = "node-wwn";
 983 const char              *fcp_port_wwn_prop = "port-wwn";
 984 const char              *fcp_conf_wwn_prop = "fc-port-wwn";
 985 const char              *fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
 986 const char              *fcp_manual_config_only = "manual_configuration_only";
 987 const char              *fcp_init_port_prop = "initiator-port";
 988 const char              *fcp_tgt_port_prop = "target-port";
 989 const char              *fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
 990 
 991 static struct fcp_port  *fcp_port_head = NULL;
 992 static ddi_eventcookie_t        fcp_insert_eid;
 993 static ddi_eventcookie_t        fcp_remove_eid;
 994 
 995 static ndi_event_definition_t   fcp_ndi_event_defs[] = {
 996         { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
 997         { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
 998 };
 999 
1000 /*
1001  * List of valid commands for the scsi_ioctl call
1002  */
1003 static uint8_t scsi_ioctl_list[] = {
1004         SCMD_INQUIRY,
1005         SCMD_REPORT_LUN,
1006         SCMD_READ_CAPACITY
1007 };
1008 
1009 /*
1010  * this is used to dummy up a report lun response for cases
1011  * where the target doesn't support it
1012  */
1013 static uchar_t fcp_dummy_lun[] = {
1014         0x00,           /* MSB length (length = no of luns * 8) */
1015         0x00,
1016         0x00,
1017         0x08,           /* LSB length */
1018         0x00,           /* MSB reserved */
1019         0x00,
1020         0x00,
1021         0x00,           /* LSB reserved */
1022         FCP_PD_ADDRESSING,
1023         0x00,           /* LUN is ZERO at the first level */
1024         0x00,
1025         0x00,           /* second level is zero */
1026         0x00,
1027         0x00,           /* third level is zero */
1028         0x00,
1029         0x00            /* fourth level is zero */
1030 };
1031 
1032 static uchar_t fcp_alpa_to_switch[] = {
1033         0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1034         0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1035         0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1036         0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1037         0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1038         0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1039         0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1040         0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1041         0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1042         0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1043         0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1044         0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1045         0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1046         0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1047         0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1048         0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1049         0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1050         0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1051         0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1052         0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1053         0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1054         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1055         0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1056         0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1057 };
1058 
1059 static caddr_t pid = "SESS01          ";
1060 
1061 #if     !defined(lint)
1062 
1063 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1064     fcp_port::fcp_next fcp_watchdog_id))
1065 
1066 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1067 
1068 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1069     fcp_insert_eid
1070     fcp_remove_eid
1071     fcp_watchdog_time))
1072 
1073 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1074     fcp_cb_ops
1075     fcp_ops
1076     callb_cpr))
1077 
1078 #endif /* lint */
1079 
1080 /*
1081  * This table is used to determine whether or not it's safe to copy in
1082  * the target node name for a lun.  Since all luns behind the same target
1083  * have the same wwnn, only tagets that do not support multiple luns are
1084  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1085  */
1086 
1087 char *fcp_symmetric_disk_table[] = {
1088         "SEAGATE ST",
1089         "IBM     DDYFT",
1090         "SUNW    SUNWGS",       /* Daktari enclosure */
1091         "SUN     SENA",         /* SES device */
1092         "SUN     SESS01"        /* VICOM SVE box */
1093 };
1094 
1095 int fcp_symmetric_disk_table_size =
1096         sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1097 
1098 /*
1099  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1100  * will panic if you don't pass this in to the routine, this information.
1101  * Need to determine what the actual impact to the system is by providing
1102  * this information if any. Since dma allocation is done in pkt_init it may
1103  * not have any impact. These values are straight from the Writing Device
1104  * Driver manual.
1105  */
1106 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1107         DMA_ATTR_V0,    /* ddi_dma_attr version */
1108         0,              /* low address */
1109         0xffffffff,     /* high address */
1110         0x00ffffff,     /* counter upper bound */
1111         1,              /* alignment requirements */
1112         0x3f,           /* burst sizes */
1113         1,              /* minimum DMA access */
1114         0xffffffff,     /* maximum DMA access */
1115         (1 << 24) - 1,    /* segment boundary restrictions */
1116         1,              /* scater/gather list length */
1117         512,            /* device granularity */
1118         0               /* DMA flags */
1119 };
1120 
1121 /*
1122  * The _init(9e) return value should be that of mod_install(9f). Under
1123  * some circumstances, a failure may not be related mod_install(9f) and
1124  * one would then require a return value to indicate the failure. Looking
1125  * at mod_install(9f), it is expected to return 0 for success and non-zero
1126  * for failure. mod_install(9f) for device drivers, further goes down the
1127  * calling chain and ends up in ddi_installdrv(), whose return values are
1128  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1129  * calling chain of mod_install(9f) which return values like EINVAL and
1130  * in some even return -1.
1131  *
1132  * To work around the vagaries of the mod_install() calling chain, return
1133  * either 0 or ENODEV depending on the success or failure of mod_install()
1134  */
1135 int
1136 _init(void)
1137 {
1138         int rval;
1139 
1140         /*
1141          * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1142          * before registering with the transport first.
1143          */
1144         if (ddi_soft_state_init(&fcp_softstate,
1145             sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1146                 return (EINVAL);
1147         }
1148 
1149         mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1150         mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1151 
1152         if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1153                 cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1154                 mutex_destroy(&fcp_global_mutex);
1155                 mutex_destroy(&fcp_ioctl_mutex);
1156                 ddi_soft_state_fini(&fcp_softstate);
1157                 return (ENODEV);
1158         }
1159 
1160         fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1161 
1162         if ((rval = mod_install(&modlinkage)) != 0) {
1163                 fc_trace_free_logq(fcp_logq);
1164                 (void) fc_ulp_remove(&fcp_modinfo);
1165                 mutex_destroy(&fcp_global_mutex);
1166                 mutex_destroy(&fcp_ioctl_mutex);
1167                 ddi_soft_state_fini(&fcp_softstate);
1168                 rval = ENODEV;
1169         }
1170 
1171         return (rval);
1172 }
1173 
1174 
1175 /*
1176  * the system is done with us as a driver, so clean up
1177  */
1178 int
1179 _fini(void)
1180 {
1181         int rval;
1182 
1183         /*
1184          * don't start cleaning up until we know that the module remove
1185          * has worked  -- if this works, then we know that each instance
1186          * has successfully been DDI_DETACHed
1187          */
1188         if ((rval = mod_remove(&modlinkage)) != 0) {
1189                 return (rval);
1190         }
1191 
1192         (void) fc_ulp_remove(&fcp_modinfo);
1193 
1194         ddi_soft_state_fini(&fcp_softstate);
1195         mutex_destroy(&fcp_global_mutex);
1196         mutex_destroy(&fcp_ioctl_mutex);
1197         fc_trace_free_logq(fcp_logq);
1198 
1199         return (rval);
1200 }
1201 
1202 
1203 int
1204 _info(struct modinfo *modinfop)
1205 {
1206         return (mod_info(&modlinkage, modinfop));
1207 }
1208 
1209 
1210 /*
1211  * attach the module
1212  */
1213 static int
1214 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1215 {
1216         int rval = DDI_SUCCESS;
1217 
1218         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1219             FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1220 
1221         if (cmd == DDI_ATTACH) {
1222                 /* The FCP pseudo device is created here. */
1223                 mutex_enter(&fcp_global_mutex);
1224                 fcp_global_dip = devi;
1225                 mutex_exit(&fcp_global_mutex);
1226 
1227                 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1228                     0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1229                         ddi_report_dev(fcp_global_dip);
1230                 } else {
1231                         cmn_err(CE_WARN, "FCP: Cannot create minor node");
1232                         mutex_enter(&fcp_global_mutex);
1233                         fcp_global_dip = NULL;
1234                         mutex_exit(&fcp_global_mutex);
1235 
1236                         rval = DDI_FAILURE;
1237                 }
1238                 /*
1239                  * We check the fcp_offline_delay property at this
1240                  * point. This variable is global for the driver,
1241                  * not specific to an instance.
1242                  *
1243                  * We do not recommend setting the value to less
1244                  * than 10 seconds (RA_TOV_els), or greater than
1245                  * 60 seconds.
1246                  */
1247                 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1248                     devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1249                     "fcp_offline_delay", FCP_OFFLINE_DELAY);
1250                 if ((fcp_offline_delay < 10) ||
1251                     (fcp_offline_delay > 60)) {
1252                         cmn_err(CE_WARN, "Setting fcp_offline_delay "
1253                             "to %d second(s). This is outside the "
1254                             "recommended range of 10..60 seconds.",
1255                             fcp_offline_delay);
1256                 }
1257         }
1258 
1259         return (rval);
1260 }
1261 
1262 
1263 /*ARGSUSED*/
1264 static int
1265 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1266 {
1267         int     res = DDI_SUCCESS;
1268 
1269         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1270             FCP_BUF_LEVEL_8, 0,  "module detach: cmd=0x%x", cmd);
1271 
1272         if (cmd == DDI_DETACH) {
1273                 /*
1274                  * Check if there are active ports/threads. If there
1275                  * are any, we will fail, else we will succeed (there
1276                  * should not be much to clean up)
1277                  */
1278                 mutex_enter(&fcp_global_mutex);
1279                 FCP_DTRACE(fcp_logq, "fcp",
1280                     fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1281                     (void *) fcp_port_head);
1282 
1283                 if (fcp_port_head == NULL) {
1284                         ddi_remove_minor_node(fcp_global_dip, NULL);
1285                         fcp_global_dip = NULL;
1286                         mutex_exit(&fcp_global_mutex);
1287                 } else {
1288                         mutex_exit(&fcp_global_mutex);
1289                         res = DDI_FAILURE;
1290                 }
1291         }
1292         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1293             FCP_BUF_LEVEL_8, 0,  "module detach returning %d", res);
1294 
1295         return (res);
1296 }
1297 
1298 
1299 /* ARGSUSED */
1300 static int
1301 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1302 {
1303         if (otype != OTYP_CHR) {
1304                 return (EINVAL);
1305         }
1306 
1307         /*
1308          * Allow only root to talk;
1309          */
1310         if (drv_priv(credp)) {
1311                 return (EPERM);
1312         }
1313 
1314         mutex_enter(&fcp_global_mutex);
1315         if (fcp_oflag & FCP_EXCL) {
1316                 mutex_exit(&fcp_global_mutex);
1317                 return (EBUSY);
1318         }
1319 
1320         if (flag & FEXCL) {
1321                 if (fcp_oflag & FCP_OPEN) {
1322                         mutex_exit(&fcp_global_mutex);
1323                         return (EBUSY);
1324                 }
1325                 fcp_oflag |= FCP_EXCL;
1326         }
1327         fcp_oflag |= FCP_OPEN;
1328         mutex_exit(&fcp_global_mutex);
1329 
1330         return (0);
1331 }
1332 
1333 
1334 /* ARGSUSED */
1335 static int
1336 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1337 {
1338         if (otype != OTYP_CHR) {
1339                 return (EINVAL);
1340         }
1341 
1342         mutex_enter(&fcp_global_mutex);
1343         if (!(fcp_oflag & FCP_OPEN)) {
1344                 mutex_exit(&fcp_global_mutex);
1345                 return (ENODEV);
1346         }
1347         fcp_oflag = FCP_IDLE;
1348         mutex_exit(&fcp_global_mutex);
1349 
1350         return (0);
1351 }
1352 
1353 
1354 /*
1355  * fcp_ioctl
1356  *      Entry point for the FCP ioctls
1357  *
1358  * Input:
1359  *      See ioctl(9E)
1360  *
1361  * Output:
1362  *      See ioctl(9E)
1363  *
1364  * Returns:
1365  *      See ioctl(9E)
1366  *
1367  * Context:
1368  *      Kernel context.
1369  */
1370 /* ARGSUSED */
1371 static int
1372 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1373     int *rval)
1374 {
1375         int                     ret = 0;
1376 
1377         mutex_enter(&fcp_global_mutex);
1378         if (!(fcp_oflag & FCP_OPEN)) {
1379                 mutex_exit(&fcp_global_mutex);
1380                 return (ENXIO);
1381         }
1382         mutex_exit(&fcp_global_mutex);
1383 
1384         switch (cmd) {
1385         case FCP_TGT_INQUIRY:
1386         case FCP_TGT_CREATE:
1387         case FCP_TGT_DELETE:
1388                 ret = fcp_setup_device_data_ioctl(cmd,
1389                     (struct fcp_ioctl *)data, mode, rval);
1390                 break;
1391 
1392         case FCP_TGT_SEND_SCSI:
1393                 mutex_enter(&fcp_ioctl_mutex);
1394                 ret = fcp_setup_scsi_ioctl(
1395                     (struct fcp_scsi_cmd *)data, mode, rval);
1396                 mutex_exit(&fcp_ioctl_mutex);
1397                 break;
1398 
1399         case FCP_STATE_COUNT:
1400                 ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1401                     mode, rval);
1402                 break;
1403         case FCP_GET_TARGET_MAPPINGS:
1404                 ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1405                     mode, rval);
1406                 break;
1407         default:
1408                 fcp_log(CE_WARN, NULL,
1409                     "!Invalid ioctl opcode = 0x%x", cmd);
1410                 ret     = EINVAL;
1411         }
1412 
1413         return (ret);
1414 }
1415 
1416 
1417 /*
1418  * fcp_setup_device_data_ioctl
1419  *      Setup handler for the "device data" style of
1420  *      ioctl for FCP.  See "fcp_util.h" for data structure
1421  *      definition.
1422  *
1423  * Input:
1424  *      cmd     = FCP ioctl command
1425  *      data    = ioctl data
1426  *      mode    = See ioctl(9E)
1427  *
1428  * Output:
1429  *      data    = ioctl data
1430  *      rval    = return value - see ioctl(9E)
1431  *
1432  * Returns:
1433  *      See ioctl(9E)
1434  *
1435  * Context:
1436  *      Kernel context.
1437  */
1438 /* ARGSUSED */
1439 static int
1440 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1441     int *rval)
1442 {
1443         struct fcp_port *pptr;
1444         struct  device_data     *dev_data;
1445         uint32_t                link_cnt;
1446         la_wwn_t                *wwn_ptr = NULL;
1447         struct fcp_tgt          *ptgt = NULL;
1448         struct fcp_lun          *plun = NULL;
1449         int                     i, error;
1450         struct fcp_ioctl        fioctl;
1451 
1452 #ifdef  _MULTI_DATAMODEL
1453         switch (ddi_model_convert_from(mode & FMODELS)) {
1454         case DDI_MODEL_ILP32: {
1455                 struct fcp32_ioctl f32_ioctl;
1456 
1457                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1458                     sizeof (struct fcp32_ioctl), mode)) {
1459                         return (EFAULT);
1460                 }
1461                 fioctl.fp_minor = f32_ioctl.fp_minor;
1462                 fioctl.listlen = f32_ioctl.listlen;
1463                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1464                 break;
1465         }
1466         case DDI_MODEL_NONE:
1467                 if (ddi_copyin((void *)data, (void *)&fioctl,
1468                     sizeof (struct fcp_ioctl), mode)) {
1469                         return (EFAULT);
1470                 }
1471                 break;
1472         }
1473 
1474 #else   /* _MULTI_DATAMODEL */
1475         if (ddi_copyin((void *)data, (void *)&fioctl,
1476             sizeof (struct fcp_ioctl), mode)) {
1477                 return (EFAULT);
1478         }
1479 #endif  /* _MULTI_DATAMODEL */
1480 
1481         /*
1482          * Right now we can assume that the minor number matches with
1483          * this instance of fp. If this changes we will need to
1484          * revisit this logic.
1485          */
1486         mutex_enter(&fcp_global_mutex);
1487         pptr = fcp_port_head;
1488         while (pptr) {
1489                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1490                         break;
1491                 } else {
1492                         pptr = pptr->port_next;
1493                 }
1494         }
1495         mutex_exit(&fcp_global_mutex);
1496         if (pptr == NULL) {
1497                 return (ENXIO);
1498         }
1499         mutex_enter(&pptr->port_mutex);
1500 
1501 
1502         if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1503             fioctl.listlen, KM_NOSLEEP)) == NULL) {
1504                 mutex_exit(&pptr->port_mutex);
1505                 return (ENOMEM);
1506         }
1507 
1508         if (ddi_copyin(fioctl.list, dev_data,
1509             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1510                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1511                 mutex_exit(&pptr->port_mutex);
1512                 return (EFAULT);
1513         }
1514         link_cnt = pptr->port_link_cnt;
1515 
1516         if (cmd == FCP_TGT_INQUIRY) {
1517                 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1518                 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1519                     sizeof (wwn_ptr->raw_wwn)) == 0) {
1520                         /* This ioctl is requesting INQ info of local HBA */
1521                         mutex_exit(&pptr->port_mutex);
1522                         dev_data[0].dev0_type = DTYPE_UNKNOWN;
1523                         dev_data[0].dev_status = 0;
1524                         if (ddi_copyout(dev_data, fioctl.list,
1525                             (sizeof (struct device_data)) * fioctl.listlen,
1526                             mode)) {
1527                                 kmem_free(dev_data,
1528                                     sizeof (*dev_data) * fioctl.listlen);
1529                                 return (EFAULT);
1530                         }
1531                         kmem_free(dev_data,
1532                             sizeof (*dev_data) * fioctl.listlen);
1533 #ifdef  _MULTI_DATAMODEL
1534                         switch (ddi_model_convert_from(mode & FMODELS)) {
1535                         case DDI_MODEL_ILP32: {
1536                                 struct fcp32_ioctl f32_ioctl;
1537                                 f32_ioctl.fp_minor = fioctl.fp_minor;
1538                                 f32_ioctl.listlen = fioctl.listlen;
1539                                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1540                                 if (ddi_copyout((void *)&f32_ioctl,
1541                                     (void *)data,
1542                                     sizeof (struct fcp32_ioctl), mode)) {
1543                                         return (EFAULT);
1544                                 }
1545                                 break;
1546                         }
1547                         case DDI_MODEL_NONE:
1548                                 if (ddi_copyout((void *)&fioctl, (void *)data,
1549                                     sizeof (struct fcp_ioctl), mode)) {
1550                                         return (EFAULT);
1551                                 }
1552                                 break;
1553                         }
1554 #else   /* _MULTI_DATAMODEL */
1555                         if (ddi_copyout((void *)&fioctl, (void *)data,
1556                             sizeof (struct fcp_ioctl), mode)) {
1557                                 return (EFAULT);
1558                         }
1559 #endif  /* _MULTI_DATAMODEL */
1560                         return (0);
1561                 }
1562         }
1563 
1564         if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1565                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1566                 mutex_exit(&pptr->port_mutex);
1567                 return (ENXIO);
1568         }
1569 
1570         for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1571             i++) {
1572                 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1573 
1574                 dev_data[i].dev0_type = DTYPE_UNKNOWN;
1575 
1576 
1577                 dev_data[i].dev_status = ENXIO;
1578 
1579                 if ((ptgt = fcp_lookup_target(pptr,
1580                     (uchar_t *)wwn_ptr)) == NULL) {
1581                         mutex_exit(&pptr->port_mutex);
1582                         if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1583                             wwn_ptr, &error, 0) == NULL) {
1584                                 dev_data[i].dev_status = ENODEV;
1585                                 mutex_enter(&pptr->port_mutex);
1586                                 continue;
1587                         } else {
1588 
1589                                 dev_data[i].dev_status = EAGAIN;
1590 
1591                                 mutex_enter(&pptr->port_mutex);
1592                                 continue;
1593                         }
1594                 } else {
1595                         mutex_enter(&ptgt->tgt_mutex);
1596                         if (ptgt->tgt_state & (FCP_TGT_MARK |
1597                             FCP_TGT_BUSY)) {
1598                                 dev_data[i].dev_status = EAGAIN;
1599                                 mutex_exit(&ptgt->tgt_mutex);
1600                                 continue;
1601                         }
1602 
1603                         if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1604                                 if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1605                                         dev_data[i].dev_status = ENOTSUP;
1606                                 } else {
1607                                         dev_data[i].dev_status = ENXIO;
1608                                 }
1609                                 mutex_exit(&ptgt->tgt_mutex);
1610                                 continue;
1611                         }
1612 
1613                         switch (cmd) {
1614                         case FCP_TGT_INQUIRY:
1615                                 /*
1616                                  * The reason we give device type of
1617                                  * lun 0 only even though in some
1618                                  * cases(like maxstrat) lun 0 device
1619                                  * type may be 0x3f(invalid) is that
1620                                  * for bridge boxes target will appear
1621                                  * as luns and the first lun could be
1622                                  * a device that utility may not care
1623                                  * about (like a tape device).
1624                                  */
1625                                 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1626                                 dev_data[i].dev_status = 0;
1627                                 mutex_exit(&ptgt->tgt_mutex);
1628 
1629                                 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1630                                         dev_data[i].dev0_type = DTYPE_UNKNOWN;
1631                                 } else {
1632                                         dev_data[i].dev0_type = plun->lun_type;
1633                                 }
1634                                 mutex_enter(&ptgt->tgt_mutex);
1635                                 break;
1636 
1637                         case FCP_TGT_CREATE:
1638                                 mutex_exit(&ptgt->tgt_mutex);
1639                                 mutex_exit(&pptr->port_mutex);
1640 
1641                                 /*
1642                                  * serialize state change call backs.
1643                                  * only one call back will be handled
1644                                  * at a time.
1645                                  */
1646                                 mutex_enter(&fcp_global_mutex);
1647                                 if (fcp_oflag & FCP_BUSY) {
1648                                         mutex_exit(&fcp_global_mutex);
1649                                         if (dev_data) {
1650                                                 kmem_free(dev_data,
1651                                                     sizeof (*dev_data) *
1652                                                     fioctl.listlen);
1653                                         }
1654                                         return (EBUSY);
1655                                 }
1656                                 fcp_oflag |= FCP_BUSY;
1657                                 mutex_exit(&fcp_global_mutex);
1658 
1659                                 dev_data[i].dev_status =
1660                                     fcp_create_on_demand(pptr,
1661                                     wwn_ptr->raw_wwn);
1662 
1663                                 if (dev_data[i].dev_status != 0) {
1664                                         char    buf[25];
1665 
1666                                         for (i = 0; i < FC_WWN_SIZE; i++) {
1667                                                 (void) sprintf(&buf[i << 1],
1668                                                     "%02x",
1669                                                     wwn_ptr->raw_wwn[i]);
1670                                         }
1671 
1672                                         fcp_log(CE_WARN, pptr->port_dip,
1673                                             "!Failed to create nodes for"
1674                                             " pwwn=%s; error=%x", buf,
1675                                             dev_data[i].dev_status);
1676                                 }
1677 
1678                                 /* allow state change call backs again */
1679                                 mutex_enter(&fcp_global_mutex);
1680                                 fcp_oflag &= ~FCP_BUSY;
1681                                 mutex_exit(&fcp_global_mutex);
1682 
1683                                 mutex_enter(&pptr->port_mutex);
1684                                 mutex_enter(&ptgt->tgt_mutex);
1685 
1686                                 break;
1687 
1688                         case FCP_TGT_DELETE:
1689                                 break;
1690 
1691                         default:
1692                                 fcp_log(CE_WARN, pptr->port_dip,
1693                                     "!Invalid device data ioctl "
1694                                     "opcode = 0x%x", cmd);
1695                         }
1696                         mutex_exit(&ptgt->tgt_mutex);
1697                 }
1698         }
1699         mutex_exit(&pptr->port_mutex);
1700 
1701         if (ddi_copyout(dev_data, fioctl.list,
1702             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1703                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1704                 return (EFAULT);
1705         }
1706         kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1707 
1708 #ifdef  _MULTI_DATAMODEL
1709         switch (ddi_model_convert_from(mode & FMODELS)) {
1710         case DDI_MODEL_ILP32: {
1711                 struct fcp32_ioctl f32_ioctl;
1712 
1713                 f32_ioctl.fp_minor = fioctl.fp_minor;
1714                 f32_ioctl.listlen = fioctl.listlen;
1715                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1716                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1717                     sizeof (struct fcp32_ioctl), mode)) {
1718                         return (EFAULT);
1719                 }
1720                 break;
1721         }
1722         case DDI_MODEL_NONE:
1723                 if (ddi_copyout((void *)&fioctl, (void *)data,
1724                     sizeof (struct fcp_ioctl), mode)) {
1725                         return (EFAULT);
1726                 }
1727                 break;
1728         }
1729 #else   /* _MULTI_DATAMODEL */
1730 
1731         if (ddi_copyout((void *)&fioctl, (void *)data,
1732             sizeof (struct fcp_ioctl), mode)) {
1733                 return (EFAULT);
1734         }
1735 #endif  /* _MULTI_DATAMODEL */
1736 
1737         return (0);
1738 }
1739 
1740 /*
1741  * Fetch the target mappings (path, etc.) for all LUNs
1742  * on this port.
1743  */
1744 /* ARGSUSED */
1745 static int
1746 fcp_get_target_mappings(struct fcp_ioctl *data,
1747     int mode, int *rval)
1748 {
1749         struct fcp_port     *pptr;
1750         fc_hba_target_mappings_t    *mappings;
1751         fc_hba_mapping_entry_t      *map;
1752         struct fcp_tgt      *ptgt = NULL;
1753         struct fcp_lun      *plun = NULL;
1754         int                         i, mapIndex, mappingSize;
1755         int                         listlen;
1756         struct fcp_ioctl            fioctl;
1757         char                        *path;
1758         fcp_ent_addr_t              sam_lun_addr;
1759 
1760 #ifdef  _MULTI_DATAMODEL
1761         switch (ddi_model_convert_from(mode & FMODELS)) {
1762         case DDI_MODEL_ILP32: {
1763                 struct fcp32_ioctl f32_ioctl;
1764 
1765                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1766                     sizeof (struct fcp32_ioctl), mode)) {
1767                         return (EFAULT);
1768                 }
1769                 fioctl.fp_minor = f32_ioctl.fp_minor;
1770                 fioctl.listlen = f32_ioctl.listlen;
1771                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1772                 break;
1773         }
1774         case DDI_MODEL_NONE:
1775                 if (ddi_copyin((void *)data, (void *)&fioctl,
1776                     sizeof (struct fcp_ioctl), mode)) {
1777                         return (EFAULT);
1778                 }
1779                 break;
1780         }
1781 
1782 #else   /* _MULTI_DATAMODEL */
1783         if (ddi_copyin((void *)data, (void *)&fioctl,
1784             sizeof (struct fcp_ioctl), mode)) {
1785                 return (EFAULT);
1786         }
1787 #endif  /* _MULTI_DATAMODEL */
1788 
1789         /*
1790          * Right now we can assume that the minor number matches with
1791          * this instance of fp. If this changes we will need to
1792          * revisit this logic.
1793          */
1794         mutex_enter(&fcp_global_mutex);
1795         pptr = fcp_port_head;
1796         while (pptr) {
1797                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1798                         break;
1799                 } else {
1800                         pptr = pptr->port_next;
1801                 }
1802         }
1803         mutex_exit(&fcp_global_mutex);
1804         if (pptr == NULL) {
1805                 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1806                     fioctl.fp_minor);
1807                 return (ENXIO);
1808         }
1809 
1810 
1811         /* We use listlen to show the total buffer size */
1812         mappingSize = fioctl.listlen;
1813 
1814         /* Now calculate how many mapping entries will fit */
1815         listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1816             - sizeof (fc_hba_target_mappings_t);
1817         if (listlen <= 0) {
1818                 cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1819                 return (ENXIO);
1820         }
1821         listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1822 
1823         if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1824                 return (ENOMEM);
1825         }
1826         mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1827 
1828         /* Now get to work */
1829         mapIndex = 0;
1830 
1831         mutex_enter(&pptr->port_mutex);
1832         /* Loop through all targets on this port */
1833         for (i = 0; i < FCP_NUM_HASH; i++) {
1834                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1835                     ptgt = ptgt->tgt_next) {
1836 
1837                         mutex_enter(&ptgt->tgt_mutex);
1838 
1839                         /* Loop through all LUNs on this target */
1840                         for (plun = ptgt->tgt_lun; plun != NULL;
1841                             plun = plun->lun_next) {
1842                                 if (plun->lun_state & FCP_LUN_OFFLINE) {
1843                                         continue;
1844                                 }
1845 
1846                                 path = fcp_get_lun_path(plun);
1847                                 if (path == NULL) {
1848                                         continue;
1849                                 }
1850 
1851                                 if (mapIndex >= listlen) {
1852                                         mapIndex ++;
1853                                         kmem_free(path, MAXPATHLEN);
1854                                         continue;
1855                                 }
1856                                 map = &mappings->entries[mapIndex++];
1857                                 bcopy(path, map->targetDriver,
1858                                     sizeof (map->targetDriver));
1859                                 map->d_id = ptgt->tgt_d_id;
1860                                 map->busNumber = 0;
1861                                 map->targetNumber = ptgt->tgt_d_id;
1862                                 map->osLUN = plun->lun_num;
1863 
1864                                 /*
1865                                  * We had swapped lun when we stored it in
1866                                  * lun_addr. We need to swap it back before
1867                                  * returning it to user land
1868                                  */
1869 
1870                                 sam_lun_addr.ent_addr_0 =
1871                                     BE_16(plun->lun_addr.ent_addr_0);
1872                                 sam_lun_addr.ent_addr_1 =
1873                                     BE_16(plun->lun_addr.ent_addr_1);
1874                                 sam_lun_addr.ent_addr_2 =
1875                                     BE_16(plun->lun_addr.ent_addr_2);
1876                                 sam_lun_addr.ent_addr_3 =
1877                                     BE_16(plun->lun_addr.ent_addr_3);
1878 
1879                                 bcopy(&sam_lun_addr, &map->samLUN,
1880                                     FCP_LUN_SIZE);
1881                                 bcopy(ptgt->tgt_node_wwn.raw_wwn,
1882                                     map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1883                                 bcopy(ptgt->tgt_port_wwn.raw_wwn,
1884                                     map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1885 
1886                                 if (plun->lun_guid) {
1887 
1888                                         /* convert ascii wwn to bytes */
1889                                         fcp_ascii_to_wwn(plun->lun_guid,
1890                                             map->guid, sizeof (map->guid));
1891 
1892                                         if ((sizeof (map->guid)) <
1893                                             plun->lun_guid_size / 2) {
1894                                                 cmn_err(CE_WARN,
1895                                                     "fcp_get_target_mappings:"
1896                                                     "guid copy space "
1897                                                     "insufficient."
1898                                                     "Copy Truncation - "
1899                                                     "available %d; need %d",
1900                                                     (int)sizeof (map->guid),
1901                                                     (int)
1902                                                     plun->lun_guid_size / 2);
1903                                         }
1904                                 }
1905                                 kmem_free(path, MAXPATHLEN);
1906                         }
1907                         mutex_exit(&ptgt->tgt_mutex);
1908                 }
1909         }
1910         mutex_exit(&pptr->port_mutex);
1911         mappings->numLuns = mapIndex;
1912 
1913         if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1914                 kmem_free(mappings, mappingSize);
1915                 return (EFAULT);
1916         }
1917         kmem_free(mappings, mappingSize);
1918 
1919 #ifdef  _MULTI_DATAMODEL
1920         switch (ddi_model_convert_from(mode & FMODELS)) {
1921         case DDI_MODEL_ILP32: {
1922                 struct fcp32_ioctl f32_ioctl;
1923 
1924                 f32_ioctl.fp_minor = fioctl.fp_minor;
1925                 f32_ioctl.listlen = fioctl.listlen;
1926                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1927                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1928                     sizeof (struct fcp32_ioctl), mode)) {
1929                         return (EFAULT);
1930                 }
1931                 break;
1932         }
1933         case DDI_MODEL_NONE:
1934                 if (ddi_copyout((void *)&fioctl, (void *)data,
1935                     sizeof (struct fcp_ioctl), mode)) {
1936                         return (EFAULT);
1937                 }
1938                 break;
1939         }
1940 #else   /* _MULTI_DATAMODEL */
1941 
1942         if (ddi_copyout((void *)&fioctl, (void *)data,
1943             sizeof (struct fcp_ioctl), mode)) {
1944                 return (EFAULT);
1945         }
1946 #endif  /* _MULTI_DATAMODEL */
1947 
1948         return (0);
1949 }
1950 
1951 /*
1952  * fcp_setup_scsi_ioctl
1953  *      Setup handler for the "scsi passthru" style of
1954  *      ioctl for FCP.  See "fcp_util.h" for data structure
1955  *      definition.
1956  *
1957  * Input:
1958  *      u_fscsi = ioctl data (user address space)
1959  *      mode    = See ioctl(9E)
1960  *
1961  * Output:
1962  *      u_fscsi = ioctl data (user address space)
1963  *      rval    = return value - see ioctl(9E)
1964  *
1965  * Returns:
1966  *      0       = OK
1967  *      EAGAIN  = See errno.h
1968  *      EBUSY   = See errno.h
1969  *      EFAULT  = See errno.h
1970  *      EINTR   = See errno.h
1971  *      EINVAL  = See errno.h
1972  *      EIO     = See errno.h
1973  *      ENOMEM  = See errno.h
1974  *      ENXIO   = See errno.h
1975  *
1976  * Context:
1977  *      Kernel context.
1978  */
1979 /* ARGSUSED */
1980 static int
1981 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1982     int mode, int *rval)
1983 {
1984         int                     ret             = 0;
1985         int                     temp_ret;
1986         caddr_t                 k_cdbbufaddr    = NULL;
1987         caddr_t                 k_bufaddr       = NULL;
1988         caddr_t                 k_rqbufaddr     = NULL;
1989         caddr_t                 u_cdbbufaddr;
1990         caddr_t                 u_bufaddr;
1991         caddr_t                 u_rqbufaddr;
1992         struct fcp_scsi_cmd     k_fscsi;
1993 
1994         /*
1995          * Get fcp_scsi_cmd array element from user address space
1996          */
1997         if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1998             != 0) {
1999                 return (ret);
2000         }
2001 
2002 
2003         /*
2004          * Even though kmem_alloc() checks the validity of the
2005          * buffer length, this check is needed when the
2006          * kmem_flags set and the zero buffer length is passed.
2007          */
2008         if ((k_fscsi.scsi_cdblen <= 0) ||
2009             (k_fscsi.scsi_buflen <= 0) ||
2010             (k_fscsi.scsi_rqlen <= 0)) {
2011                 return (EINVAL);
2012         }
2013 
2014         /*
2015          * Allocate data for fcp_scsi_cmd pointer fields
2016          */
2017         if (ret == 0) {
2018                 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2019                 k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2020                 k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2021 
2022                 if (k_cdbbufaddr == NULL ||
2023                     k_bufaddr    == NULL ||
2024                     k_rqbufaddr  == NULL) {
2025                         ret = ENOMEM;
2026                 }
2027         }
2028 
2029         /*
2030          * Get fcp_scsi_cmd pointer fields from user
2031          * address space
2032          */
2033         if (ret == 0) {
2034                 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2035                 u_bufaddr    = k_fscsi.scsi_bufaddr;
2036                 u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2037 
2038                 if (ddi_copyin(u_cdbbufaddr,
2039                     k_cdbbufaddr,
2040                     k_fscsi.scsi_cdblen,
2041                     mode)) {
2042                         ret = EFAULT;
2043                 } else if (ddi_copyin(u_bufaddr,
2044                     k_bufaddr,
2045                     k_fscsi.scsi_buflen,
2046                     mode)) {
2047                         ret = EFAULT;
2048                 } else if (ddi_copyin(u_rqbufaddr,
2049                     k_rqbufaddr,
2050                     k_fscsi.scsi_rqlen,
2051                     mode)) {
2052                         ret = EFAULT;
2053                 }
2054         }
2055 
2056         /*
2057          * Send scsi command (blocking)
2058          */
2059         if (ret == 0) {
2060                 /*
2061                  * Prior to sending the scsi command, the
2062                  * fcp_scsi_cmd data structure must contain kernel,
2063                  * not user, addresses.
2064                  */
2065                 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr;
2066                 k_fscsi.scsi_bufaddr    = k_bufaddr;
2067                 k_fscsi.scsi_rqbufaddr  = k_rqbufaddr;
2068 
2069                 ret = fcp_send_scsi_ioctl(&k_fscsi);
2070 
2071                 /*
2072                  * After sending the scsi command, the
2073                  * fcp_scsi_cmd data structure must contain user,
2074                  * not kernel, addresses.
2075                  */
2076                 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr;
2077                 k_fscsi.scsi_bufaddr    = u_bufaddr;
2078                 k_fscsi.scsi_rqbufaddr  = u_rqbufaddr;
2079         }
2080 
2081         /*
2082          * Put fcp_scsi_cmd pointer fields to user address space
2083          */
2084         if (ret == 0) {
2085                 if (ddi_copyout(k_cdbbufaddr,
2086                     u_cdbbufaddr,
2087                     k_fscsi.scsi_cdblen,
2088                     mode)) {
2089                         ret = EFAULT;
2090                 } else if (ddi_copyout(k_bufaddr,
2091                     u_bufaddr,
2092                     k_fscsi.scsi_buflen,
2093                     mode)) {
2094                         ret = EFAULT;
2095                 } else if (ddi_copyout(k_rqbufaddr,
2096                     u_rqbufaddr,
2097                     k_fscsi.scsi_rqlen,
2098                     mode)) {
2099                         ret = EFAULT;
2100                 }
2101         }
2102 
2103         /*
2104          * Free data for fcp_scsi_cmd pointer fields
2105          */
2106         if (k_cdbbufaddr != NULL) {
2107                 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2108         }
2109         if (k_bufaddr != NULL) {
2110                 kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2111         }
2112         if (k_rqbufaddr != NULL) {
2113                 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2114         }
2115 
2116         /*
2117          * Put fcp_scsi_cmd array element to user address space
2118          */
2119         temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2120         if (temp_ret != 0) {
2121                 ret = temp_ret;
2122         }
2123 
2124         /*
2125          * Return status
2126          */
2127         return (ret);
2128 }
2129 
2130 
2131 /*
2132  * fcp_copyin_scsi_cmd
2133  *      Copy in fcp_scsi_cmd data structure from user address space.
2134  *      The data may be in 32 bit or 64 bit modes.
2135  *
2136  * Input:
2137  *      base_addr       = from address (user address space)
2138  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2139  *
2140  * Output:
2141  *      fscsi           = to address (kernel address space)
2142  *
2143  * Returns:
2144  *      0       = OK
2145  *      EFAULT  = Error
2146  *
2147  * Context:
2148  *      Kernel context.
2149  */
2150 static int
2151 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2152 {
2153 #ifdef  _MULTI_DATAMODEL
2154         struct fcp32_scsi_cmd   f32scsi;
2155 
2156         switch (ddi_model_convert_from(mode & FMODELS)) {
2157         case DDI_MODEL_ILP32:
2158                 /*
2159                  * Copy data from user address space
2160                  */
2161                 if (ddi_copyin((void *)base_addr,
2162                     &f32scsi,
2163                     sizeof (struct fcp32_scsi_cmd),
2164                     mode)) {
2165                         return (EFAULT);
2166                 }
2167                 /*
2168                  * Convert from 32 bit to 64 bit
2169                  */
2170                 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2171                 break;
2172         case DDI_MODEL_NONE:
2173                 /*
2174                  * Copy data from user address space
2175                  */
2176                 if (ddi_copyin((void *)base_addr,
2177                     fscsi,
2178                     sizeof (struct fcp_scsi_cmd),
2179                     mode)) {
2180                         return (EFAULT);
2181                 }
2182                 break;
2183         }
2184 #else   /* _MULTI_DATAMODEL */
2185         /*
2186          * Copy data from user address space
2187          */
2188         if (ddi_copyin((void *)base_addr,
2189             fscsi,
2190             sizeof (struct fcp_scsi_cmd),
2191             mode)) {
2192                 return (EFAULT);
2193         }
2194 #endif  /* _MULTI_DATAMODEL */
2195 
2196         return (0);
2197 }
2198 
2199 
2200 /*
2201  * fcp_copyout_scsi_cmd
2202  *      Copy out fcp_scsi_cmd data structure to user address space.
2203  *      The data may be in 32 bit or 64 bit modes.
2204  *
2205  * Input:
2206  *      fscsi           = to address (kernel address space)
2207  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2208  *
2209  * Output:
2210  *      base_addr       = from address (user address space)
2211  *
2212  * Returns:
2213  *      0       = OK
2214  *      EFAULT  = Error
2215  *
2216  * Context:
2217  *      Kernel context.
2218  */
2219 static int
2220 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2221 {
2222 #ifdef  _MULTI_DATAMODEL
2223         struct fcp32_scsi_cmd   f32scsi;
2224 
2225         switch (ddi_model_convert_from(mode & FMODELS)) {
2226         case DDI_MODEL_ILP32:
2227                 /*
2228                  * Convert from 64 bit to 32 bit
2229                  */
2230                 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2231                 /*
2232                  * Copy data to user address space
2233                  */
2234                 if (ddi_copyout(&f32scsi,
2235                     (void *)base_addr,
2236                     sizeof (struct fcp32_scsi_cmd),
2237                     mode)) {
2238                         return (EFAULT);
2239                 }
2240                 break;
2241         case DDI_MODEL_NONE:
2242                 /*
2243                  * Copy data to user address space
2244                  */
2245                 if (ddi_copyout(fscsi,
2246                     (void *)base_addr,
2247                     sizeof (struct fcp_scsi_cmd),
2248                     mode)) {
2249                         return (EFAULT);
2250                 }
2251                 break;
2252         }
2253 #else   /* _MULTI_DATAMODEL */
2254         /*
2255          * Copy data to user address space
2256          */
2257         if (ddi_copyout(fscsi,
2258             (void *)base_addr,
2259             sizeof (struct fcp_scsi_cmd),
2260             mode)) {
2261                 return (EFAULT);
2262         }
2263 #endif  /* _MULTI_DATAMODEL */
2264 
2265         return (0);
2266 }
2267 
2268 
2269 /*
2270  * fcp_send_scsi_ioctl
2271  *      Sends the SCSI command in blocking mode.
2272  *
2273  * Input:
2274  *      fscsi           = SCSI command data structure
2275  *
2276  * Output:
2277  *      fscsi           = SCSI command data structure
2278  *
2279  * Returns:
2280  *      0       = OK
2281  *      EAGAIN  = See errno.h
2282  *      EBUSY   = See errno.h
2283  *      EINTR   = See errno.h
2284  *      EINVAL  = See errno.h
2285  *      EIO     = See errno.h
2286  *      ENOMEM  = See errno.h
2287  *      ENXIO   = See errno.h
2288  *
2289  * Context:
2290  *      Kernel context.
2291  */
2292 static int
2293 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2294 {
2295         struct fcp_lun  *plun           = NULL;
2296         struct fcp_port *pptr           = NULL;
2297         struct fcp_tgt  *ptgt           = NULL;
2298         fc_packet_t             *fpkt           = NULL;
2299         struct fcp_ipkt *icmd           = NULL;
2300         int                     target_created  = FALSE;
2301         fc_frame_hdr_t          *hp;
2302         struct fcp_cmd          fcp_cmd;
2303         struct fcp_cmd          *fcmd;
2304         union scsi_cdb          *scsi_cdb;
2305         la_wwn_t                *wwn_ptr;
2306         int                     nodma;
2307         struct fcp_rsp          *rsp;
2308         struct fcp_rsp_info     *rsp_info;
2309         caddr_t                 rsp_sense;
2310         int                     buf_len;
2311         int                     info_len;
2312         int                     sense_len;
2313         struct scsi_extended_sense      *sense_to = NULL;
2314         timeout_id_t            tid;
2315         uint8_t                 reconfig_lun = FALSE;
2316         uint8_t                 reconfig_pending = FALSE;
2317         uint8_t                 scsi_cmd;
2318         int                     rsp_len;
2319         int                     cmd_index;
2320         int                     fc_status;
2321         int                     pkt_state;
2322         int                     pkt_action;
2323         int                     pkt_reason;
2324         int                     ret, xport_retval = ~FC_SUCCESS;
2325         int                     lcount;
2326         int                     tcount;
2327         int                     reconfig_status;
2328         int                     port_busy = FALSE;
2329         uchar_t                 *lun_string;
2330 
2331         /*
2332          * Check valid SCSI command
2333          */
2334         scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2335         ret = EINVAL;
2336         for (cmd_index = 0;
2337             cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2338             ret != 0;
2339             cmd_index++) {
2340                 /*
2341                  * First byte of CDB is the SCSI command
2342                  */
2343                 if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2344                         ret = 0;
2345                 }
2346         }
2347 
2348         /*
2349          * Check inputs
2350          */
2351         if (fscsi->scsi_flags != FCP_SCSI_READ) {
2352                 ret = EINVAL;
2353         } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2354                 /* no larger than */
2355                 ret = EINVAL;
2356         }
2357 
2358 
2359         /*
2360          * Find FC port
2361          */
2362         if (ret == 0) {
2363                 /*
2364                  * Acquire global mutex
2365                  */
2366                 mutex_enter(&fcp_global_mutex);
2367 
2368                 pptr = fcp_port_head;
2369                 while (pptr) {
2370                         if (pptr->port_instance ==
2371                             (uint32_t)fscsi->scsi_fc_port_num) {
2372                                 break;
2373                         } else {
2374                                 pptr = pptr->port_next;
2375                         }
2376                 }
2377 
2378                 if (pptr == NULL) {
2379                         ret = ENXIO;
2380                 } else {
2381                         /*
2382                          * fc_ulp_busy_port can raise power
2383                          *  so, we must not hold any mutexes involved in PM
2384                          */
2385                         mutex_exit(&fcp_global_mutex);
2386                         ret = fc_ulp_busy_port(pptr->port_fp_handle);
2387                 }
2388 
2389                 if (ret == 0) {
2390 
2391                         /* remember port is busy, so we will release later */
2392                         port_busy = TRUE;
2393 
2394                         /*
2395                          * If there is a reconfiguration in progress, wait
2396                          * for it to complete.
2397                          */
2398 
2399                         fcp_reconfig_wait(pptr);
2400 
2401                         /* reacquire mutexes in order */
2402                         mutex_enter(&fcp_global_mutex);
2403                         mutex_enter(&pptr->port_mutex);
2404 
2405                         /*
2406                          * Will port accept DMA?
2407                          */
2408                         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2409                             ? 1 : 0;
2410 
2411                         /*
2412                          * If init or offline, device not known
2413                          *
2414                          * If we are discovering (onlining), we can
2415                          * NOT obviously provide reliable data about
2416                          * devices until it is complete
2417                          */
2418                         if (pptr->port_state &     (FCP_STATE_INIT |
2419                             FCP_STATE_OFFLINE)) {
2420                                 ret = ENXIO;
2421                         } else if (pptr->port_state & FCP_STATE_ONLINING) {
2422                                 ret = EBUSY;
2423                         } else {
2424                                 /*
2425                                  * Find target from pwwn
2426                                  *
2427                                  * The wwn must be put into a local
2428                                  * variable to ensure alignment.
2429                                  */
2430                                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2431                                 ptgt = fcp_lookup_target(pptr,
2432                                     (uchar_t *)wwn_ptr);
2433 
2434                                 /*
2435                                  * If target not found,
2436                                  */
2437                                 if (ptgt == NULL) {
2438                                         /*
2439                                          * Note: Still have global &
2440                                          * port mutexes
2441                                          */
2442                                         mutex_exit(&pptr->port_mutex);
2443                                         ptgt = fcp_port_create_tgt(pptr,
2444                                             wwn_ptr, &ret, &fc_status,
2445                                             &pkt_state, &pkt_action,
2446                                             &pkt_reason);
2447                                         mutex_enter(&pptr->port_mutex);
2448 
2449                                         fscsi->scsi_fc_status  = fc_status;
2450                                         fscsi->scsi_pkt_state  =
2451                                             (uchar_t)pkt_state;
2452                                         fscsi->scsi_pkt_reason = pkt_reason;
2453                                         fscsi->scsi_pkt_action =
2454                                             (uchar_t)pkt_action;
2455 
2456                                         if (ptgt != NULL) {
2457                                                 target_created = TRUE;
2458                                         } else if (ret == 0) {
2459                                                 ret = ENOMEM;
2460                                         }
2461                                 }
2462 
2463                                 if (ret == 0) {
2464                                         /*
2465                                          * Acquire target
2466                                          */
2467                                         mutex_enter(&ptgt->tgt_mutex);
2468 
2469                                         /*
2470                                          * If target is mark or busy,
2471                                          * then target can not be used
2472                                          */
2473                                         if (ptgt->tgt_state &
2474                                             (FCP_TGT_MARK |
2475                                             FCP_TGT_BUSY)) {
2476                                                 ret = EBUSY;
2477                                         } else {
2478                                                 /*
2479                                                  * Mark target as busy
2480                                                  */
2481                                                 ptgt->tgt_state |=
2482                                                     FCP_TGT_BUSY;
2483                                         }
2484 
2485                                         /*
2486                                          * Release target
2487                                          */
2488                                         lcount = pptr->port_link_cnt;
2489                                         tcount = ptgt->tgt_change_cnt;
2490                                         mutex_exit(&ptgt->tgt_mutex);
2491                                 }
2492                         }
2493 
2494                         /*
2495                          * Release port
2496                          */
2497                         mutex_exit(&pptr->port_mutex);
2498                 }
2499 
2500                 /*
2501                  * Release global mutex
2502                  */
2503                 mutex_exit(&fcp_global_mutex);
2504         }
2505 
2506         if (ret == 0) {
2507                 uint64_t belun = BE_64(fscsi->scsi_lun);
2508 
2509                 /*
2510                  * If it's a target device, find lun from pwwn
2511                  * The wwn must be put into a local
2512                  * variable to ensure alignment.
2513                  */
2514                 mutex_enter(&pptr->port_mutex);
2515                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2516                 if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2517                         /* this is not a target */
2518                         fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2519                         ret = ENXIO;
2520                 } else if ((belun << 16) != 0) {
2521                         /*
2522                          * Since fcp only support PD and LU addressing method
2523                          * so far, the last 6 bytes of a valid LUN are expected
2524                          * to be filled with 00h.
2525                          */
2526                         fscsi->scsi_fc_status = FC_INVALID_LUN;
2527                         cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2528                             " method 0x%02x with LUN number 0x%016" PRIx64,
2529                             (uint8_t)(belun >> 62), belun);
2530                         ret = ENXIO;
2531                 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2532                     (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2533                         /*
2534                          * This is a SCSI target, but no LUN at this
2535                          * address.
2536                          *
2537                          * In the future, we may want to send this to
2538                          * the target, and let it respond
2539                          * appropriately
2540                          */
2541                         ret = ENXIO;
2542                 }
2543                 mutex_exit(&pptr->port_mutex);
2544         }
2545 
2546         /*
2547          * Finished grabbing external resources
2548          * Allocate internal packet (icmd)
2549          */
2550         if (ret == 0) {
2551                 /*
2552                  * Calc rsp len assuming rsp info included
2553                  */
2554                 rsp_len = sizeof (struct fcp_rsp) +
2555                     sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2556 
2557                 icmd = fcp_icmd_alloc(pptr, ptgt,
2558                     sizeof (struct fcp_cmd),
2559                     rsp_len,
2560                     fscsi->scsi_buflen,
2561                     nodma,
2562                     lcount,                     /* ipkt_link_cnt */
2563                     tcount,                     /* ipkt_change_cnt */
2564                     0,                          /* cause */
2565                     FC_INVALID_RSCN_COUNT);     /* invalidate the count */
2566 
2567                 if (icmd == NULL) {
2568                         ret = ENOMEM;
2569                 } else {
2570                         /*
2571                          * Setup internal packet as sema sync
2572                          */
2573                         fcp_ipkt_sema_init(icmd);
2574                 }
2575         }
2576 
2577         if (ret == 0) {
2578                 /*
2579                  * Init fpkt pointer for use.
2580                  */
2581 
2582                 fpkt = icmd->ipkt_fpkt;
2583 
2584                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
2585                 fpkt->pkt_tran_type  = FC_PKT_FCP_READ; /* only rd for now */
2586                 fpkt->pkt_timeout    = fscsi->scsi_timeout;
2587 
2588                 /*
2589                  * Init fcmd pointer for use by SCSI command
2590                  */
2591 
2592                 if (nodma) {
2593                         fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2594                 } else {
2595                         fcmd = &fcp_cmd;
2596                 }
2597                 bzero(fcmd, sizeof (struct fcp_cmd));
2598                 ptgt = plun->lun_tgt;
2599 
2600                 lun_string = (uchar_t *)&fscsi->scsi_lun;
2601 
2602                 fcmd->fcp_ent_addr.ent_addr_0 =
2603                     BE_16(*(uint16_t *)&(lun_string[0]));
2604                 fcmd->fcp_ent_addr.ent_addr_1 =
2605                     BE_16(*(uint16_t *)&(lun_string[2]));
2606                 fcmd->fcp_ent_addr.ent_addr_2 =
2607                     BE_16(*(uint16_t *)&(lun_string[4]));
2608                 fcmd->fcp_ent_addr.ent_addr_3 =
2609                     BE_16(*(uint16_t *)&(lun_string[6]));
2610 
2611                 /*
2612                  * Setup internal packet(icmd)
2613                  */
2614                 icmd->ipkt_lun               = plun;
2615                 icmd->ipkt_restart   = 0;
2616                 icmd->ipkt_retries   = 0;
2617                 icmd->ipkt_opcode    = 0;
2618 
2619                 /*
2620                  * Init the frame HEADER Pointer for use
2621                  */
2622                 hp = &fpkt->pkt_cmd_fhdr;
2623 
2624                 hp->s_id     = pptr->port_id;
2625                 hp->d_id     = ptgt->tgt_d_id;
2626                 hp->r_ctl    = R_CTL_COMMAND;
2627                 hp->type     = FC_TYPE_SCSI_FCP;
2628                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2629                 hp->rsvd     = 0;
2630                 hp->seq_id   = 0;
2631                 hp->seq_cnt  = 0;
2632                 hp->ox_id    = 0xffff;
2633                 hp->rx_id    = 0xffff;
2634                 hp->ro               = 0;
2635 
2636                 fcmd->fcp_cntl.cntl_qtype    = FCP_QTYPE_SIMPLE;
2637                 fcmd->fcp_cntl.cntl_read_data        = 1;    /* only rd for now */
2638                 fcmd->fcp_cntl.cntl_write_data       = 0;
2639                 fcmd->fcp_data_len   = fscsi->scsi_buflen;
2640 
2641                 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2642                 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2643                     fscsi->scsi_cdblen);
2644 
2645                 if (!nodma) {
2646                         FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2647                             fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2648                 }
2649 
2650                 /*
2651                  * Send SCSI command to FC transport
2652                  */
2653 
2654                 if (ret == 0) {
2655                         mutex_enter(&ptgt->tgt_mutex);
2656 
2657                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2658                                 mutex_exit(&ptgt->tgt_mutex);
2659                                 fscsi->scsi_fc_status = xport_retval =
2660                                     fc_ulp_transport(pptr->port_fp_handle,
2661                                     fpkt);
2662                                 if (fscsi->scsi_fc_status != FC_SUCCESS) {
2663                                         ret = EIO;
2664                                 }
2665                         } else {
2666                                 mutex_exit(&ptgt->tgt_mutex);
2667                                 ret = EBUSY;
2668                         }
2669                 }
2670         }
2671 
2672         /*
2673          * Wait for completion only if fc_ulp_transport was called and it
2674          * returned a success. This is the only time callback will happen.
2675          * Otherwise, there is no point in waiting
2676          */
2677         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2678                 ret = fcp_ipkt_sema_wait(icmd);
2679         }
2680 
2681         /*
2682          * Copy data to IOCTL data structures
2683          */
2684         rsp = NULL;
2685         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2686                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2687 
2688                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2689                         fcp_log(CE_WARN, pptr->port_dip,
2690                             "!SCSI command to d_id=0x%x lun=0x%x"
2691                             " failed, Bad FCP response values:"
2692                             " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2693                             " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2694                             ptgt->tgt_d_id, plun->lun_num,
2695                             rsp->reserved_0, rsp->reserved_1,
2696                             rsp->fcp_u.fcp_status.reserved_0,
2697                             rsp->fcp_u.fcp_status.reserved_1,
2698                             rsp->fcp_response_len, rsp->fcp_sense_len);
2699 
2700                         ret = EIO;
2701                 }
2702         }
2703 
2704         if ((ret == 0) && (rsp != NULL)) {
2705                 /*
2706                  * Calc response lengths
2707                  */
2708                 sense_len = 0;
2709                 info_len = 0;
2710 
2711                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
2712                         info_len = rsp->fcp_response_len;
2713                 }
2714 
2715                 rsp_info   = (struct fcp_rsp_info *)
2716                     ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2717 
2718                 /*
2719                  * Get SCSI status
2720                  */
2721                 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2722                 /*
2723                  * If a lun was just added or removed and the next command
2724                  * comes through this interface, we need to capture the check
2725                  * condition so we can discover the new topology.
2726                  */
2727                 if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2728                     rsp->fcp_u.fcp_status.sense_len_set) {
2729                         sense_len = rsp->fcp_sense_len;
2730                         rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2731                         sense_to = (struct scsi_extended_sense *)rsp_sense;
2732                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2733                             (FCP_SENSE_NO_LUN(sense_to))) {
2734                                 reconfig_lun = TRUE;
2735                         }
2736                 }
2737 
2738                 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2739                     (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2740                         if (reconfig_lun == FALSE) {
2741                                 reconfig_status =
2742                                     fcp_is_reconfig_needed(ptgt, fpkt);
2743                         }
2744 
2745                         if ((reconfig_lun == TRUE) ||
2746                             (reconfig_status == TRUE)) {
2747                                 mutex_enter(&ptgt->tgt_mutex);
2748                                 if (ptgt->tgt_tid == NULL) {
2749                                         /*
2750                                          * Either we've been notified the
2751                                          * REPORT_LUN data has changed, or
2752                                          * we've determined on our own that
2753                                          * we're out of date.  Kick off
2754                                          * rediscovery.
2755                                          */
2756                                         tid = timeout(fcp_reconfigure_luns,
2757                                             (caddr_t)ptgt, drv_usectohz(1));
2758 
2759                                         ptgt->tgt_tid = tid;
2760                                         ptgt->tgt_state |= FCP_TGT_BUSY;
2761                                         ret = EBUSY;
2762                                         reconfig_pending = TRUE;
2763                                 }
2764                                 mutex_exit(&ptgt->tgt_mutex);
2765                         }
2766                 }
2767 
2768                 /*
2769                  * Calc residuals and buffer lengths
2770                  */
2771 
2772                 if (ret == 0) {
2773                         buf_len = fscsi->scsi_buflen;
2774                         fscsi->scsi_bufresid = 0;
2775                         if (rsp->fcp_u.fcp_status.resid_under) {
2776                                 if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2777                                         fscsi->scsi_bufresid = rsp->fcp_resid;
2778                                 } else {
2779                                         cmn_err(CE_WARN, "fcp: bad residue %x "
2780                                             "for txfer len %x", rsp->fcp_resid,
2781                                             fscsi->scsi_buflen);
2782                                         fscsi->scsi_bufresid =
2783                                             fscsi->scsi_buflen;
2784                                 }
2785                                 buf_len -= fscsi->scsi_bufresid;
2786                         }
2787                         if (rsp->fcp_u.fcp_status.resid_over) {
2788                                 fscsi->scsi_bufresid = -rsp->fcp_resid;
2789                         }
2790 
2791                         fscsi->scsi_rqresid  = fscsi->scsi_rqlen - sense_len;
2792                         if (fscsi->scsi_rqlen < sense_len) {
2793                                 sense_len = fscsi->scsi_rqlen;
2794                         }
2795 
2796                         fscsi->scsi_fc_rspcode       = 0;
2797                         if (rsp->fcp_u.fcp_status.rsp_len_set) {
2798                                 fscsi->scsi_fc_rspcode       = rsp_info->rsp_code;
2799                         }
2800                         fscsi->scsi_pkt_state        = fpkt->pkt_state;
2801                         fscsi->scsi_pkt_action       = fpkt->pkt_action;
2802                         fscsi->scsi_pkt_reason       = fpkt->pkt_reason;
2803 
2804                         /*
2805                          * Copy data and request sense
2806                          *
2807                          * Data must be copied by using the FCP_CP_IN macro.
2808                          * This will ensure the proper byte order since the data
2809                          * is being copied directly from the memory mapped
2810                          * device register.
2811                          *
2812                          * The response (and request sense) will be in the
2813                          * correct byte order.  No special copy is necessary.
2814                          */
2815 
2816                         if (buf_len) {
2817                                 FCP_CP_IN(fpkt->pkt_data,
2818                                     fscsi->scsi_bufaddr,
2819                                     fpkt->pkt_data_acc,
2820                                     buf_len);
2821                         }
2822                         bcopy((void *)rsp_sense,
2823                             (void *)fscsi->scsi_rqbufaddr,
2824                             sense_len);
2825                 }
2826         }
2827 
2828         /*
2829          * Cleanup transport data structures if icmd was alloc-ed
2830          * So, cleanup happens in the same thread that icmd was alloc-ed
2831          */
2832         if (icmd != NULL) {
2833                 fcp_ipkt_sema_cleanup(icmd);
2834         }
2835 
2836         /* restore pm busy/idle status */
2837         if (port_busy) {
2838                 fc_ulp_idle_port(pptr->port_fp_handle);
2839         }
2840 
2841         /*
2842          * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2843          * flag, it'll be cleared when the reconfig is complete.
2844          */
2845         if ((ptgt != NULL) && !reconfig_pending) {
2846                 /*
2847                  * If target was created,
2848                  */
2849                 if (target_created) {
2850                         mutex_enter(&ptgt->tgt_mutex);
2851                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2852                         mutex_exit(&ptgt->tgt_mutex);
2853                 } else {
2854                         /*
2855                          * De-mark target as busy
2856                          */
2857                         mutex_enter(&ptgt->tgt_mutex);
2858                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2859                         mutex_exit(&ptgt->tgt_mutex);
2860                 }
2861         }
2862         return (ret);
2863 }
2864 
2865 
2866 static int
2867 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2868     fc_packet_t *fpkt)
2869 {
2870         uchar_t                 *lun_string;
2871         uint16_t                lun_num, i;
2872         int                     num_luns;
2873         int                     actual_luns;
2874         int                     num_masked_luns;
2875         int                     lun_buflen;
2876         struct fcp_lun  *plun   = NULL;
2877         struct fcp_reportlun_resp       *report_lun;
2878         uint8_t                 reconfig_needed = FALSE;
2879         uint8_t                 lun_exists = FALSE;
2880         fcp_port_t                      *pptr            = ptgt->tgt_port;
2881 
2882         report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2883 
2884         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2885             fpkt->pkt_datalen);
2886 
2887         /* get number of luns (which is supplied as LUNS * 8) */
2888         num_luns = BE_32(report_lun->num_lun) >> 3;
2889 
2890         /*
2891          * Figure out exactly how many lun strings our response buffer
2892          * can hold.
2893          */
2894         lun_buflen = (fpkt->pkt_datalen -
2895             2 * sizeof (uint32_t)) / sizeof (longlong_t);
2896 
2897         /*
2898          * Is our response buffer full or not? We don't want to
2899          * potentially walk beyond the number of luns we have.
2900          */
2901         if (num_luns <= lun_buflen) {
2902                 actual_luns = num_luns;
2903         } else {
2904                 actual_luns = lun_buflen;
2905         }
2906 
2907         mutex_enter(&ptgt->tgt_mutex);
2908 
2909         /* Scan each lun to see if we have masked it. */
2910         num_masked_luns = 0;
2911         if (fcp_lun_blacklist != NULL) {
2912                 for (i = 0; i < actual_luns; i++) {
2913                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2914                         switch (lun_string[0] & 0xC0) {
2915                         case FCP_LUN_ADDRESSING:
2916                         case FCP_PD_ADDRESSING:
2917                         case FCP_VOLUME_ADDRESSING:
2918                                 lun_num = ((lun_string[0] & 0x3F) << 8)
2919                                     | lun_string[1];
2920                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
2921                                     lun_num) == TRUE) {
2922                                         num_masked_luns++;
2923                                 }
2924                                 break;
2925                         default:
2926                                 break;
2927                         }
2928                 }
2929         }
2930 
2931         /*
2932          * The quick and easy check.  If the number of LUNs reported
2933          * doesn't match the number we currently know about, we need
2934          * to reconfigure.
2935          */
2936         if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2937                 mutex_exit(&ptgt->tgt_mutex);
2938                 kmem_free(report_lun, fpkt->pkt_datalen);
2939                 return (TRUE);
2940         }
2941 
2942         /*
2943          * If the quick and easy check doesn't turn up anything, we walk
2944          * the list of luns from the REPORT_LUN response and look for
2945          * any luns we don't know about.  If we find one, we know we need
2946          * to reconfigure. We will skip LUNs that are masked because of the
2947          * blacklist.
2948          */
2949         for (i = 0; i < actual_luns; i++) {
2950                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2951                 lun_exists = FALSE;
2952                 switch (lun_string[0] & 0xC0) {
2953                 case FCP_LUN_ADDRESSING:
2954                 case FCP_PD_ADDRESSING:
2955                 case FCP_VOLUME_ADDRESSING:
2956                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2957 
2958                         if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2959                             &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2960                                 lun_exists = TRUE;
2961                                 break;
2962                         }
2963 
2964                         for (plun = ptgt->tgt_lun; plun;
2965                             plun = plun->lun_next) {
2966                                 if (plun->lun_num == lun_num) {
2967                                         lun_exists = TRUE;
2968                                         break;
2969                                 }
2970                         }
2971                         break;
2972                 default:
2973                         break;
2974                 }
2975 
2976                 if (lun_exists == FALSE) {
2977                         reconfig_needed = TRUE;
2978                         break;
2979                 }
2980         }
2981 
2982         mutex_exit(&ptgt->tgt_mutex);
2983         kmem_free(report_lun, fpkt->pkt_datalen);
2984 
2985         return (reconfig_needed);
2986 }
2987 
2988 /*
2989  * This function is called by fcp_handle_page83 and uses inquiry response data
2990  * stored in plun->lun_inq to determine whether or not a device is a member of
2991  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2992  * otherwise 1.
2993  */
2994 static int
2995 fcp_symmetric_device_probe(struct fcp_lun *plun)
2996 {
2997         struct scsi_inquiry     *stdinq = &plun->lun_inq;
2998         char                    *devidptr;
2999         int                     i, len;
3000 
3001         for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
3002                 devidptr = fcp_symmetric_disk_table[i];
3003                 len = (int)strlen(devidptr);
3004 
3005                 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3006                         return (0);
3007                 }
3008         }
3009         return (1);
3010 }
3011 
3012 
3013 /*
3014  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3015  * It basically returns the current count of # of state change callbacks
3016  * i.e the value of tgt_change_cnt.
3017  *
3018  * INPUT:
3019  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3020  *   fcp_ioctl.listlen  -> 1
3021  *   fcp_ioctl.list     -> Pointer to a 32 bit integer
3022  */
3023 /*ARGSUSED2*/
3024 static int
3025 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3026 {
3027         int                     ret;
3028         uint32_t                link_cnt;
3029         struct fcp_ioctl        fioctl;
3030         struct fcp_port *pptr = NULL;
3031 
3032         if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3033             &pptr)) != 0) {
3034                 return (ret);
3035         }
3036 
3037         ASSERT(pptr != NULL);
3038 
3039         if (fioctl.listlen != 1) {
3040                 return (EINVAL);
3041         }
3042 
3043         mutex_enter(&pptr->port_mutex);
3044         if (pptr->port_state & FCP_STATE_OFFLINE) {
3045                 mutex_exit(&pptr->port_mutex);
3046                 return (ENXIO);
3047         }
3048 
3049         /*
3050          * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3051          * When the fcp initially attaches to the port and there are nothing
3052          * hanging out of the port or if there was a repeat offline state change
3053          * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3054          * In the latter case, port_tmp_cnt will be non-zero and that is how we
3055          * will differentiate the 2 cases.
3056          */
3057         if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3058                 mutex_exit(&pptr->port_mutex);
3059                 return (ENXIO);
3060         }
3061 
3062         link_cnt = pptr->port_link_cnt;
3063         mutex_exit(&pptr->port_mutex);
3064 
3065         if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3066                 return (EFAULT);
3067         }
3068 
3069 #ifdef  _MULTI_DATAMODEL
3070         switch (ddi_model_convert_from(mode & FMODELS)) {
3071         case DDI_MODEL_ILP32: {
3072                 struct fcp32_ioctl f32_ioctl;
3073 
3074                 f32_ioctl.fp_minor = fioctl.fp_minor;
3075                 f32_ioctl.listlen = fioctl.listlen;
3076                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3077                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3078                     sizeof (struct fcp32_ioctl), mode)) {
3079                         return (EFAULT);
3080                 }
3081                 break;
3082         }
3083         case DDI_MODEL_NONE:
3084                 if (ddi_copyout((void *)&fioctl, (void *)data,
3085                     sizeof (struct fcp_ioctl), mode)) {
3086                         return (EFAULT);
3087                 }
3088                 break;
3089         }
3090 #else   /* _MULTI_DATAMODEL */
3091 
3092         if (ddi_copyout((void *)&fioctl, (void *)data,
3093             sizeof (struct fcp_ioctl), mode)) {
3094                 return (EFAULT);
3095         }
3096 #endif  /* _MULTI_DATAMODEL */
3097 
3098         return (0);
3099 }
3100 
3101 /*
3102  * This function copies the fcp_ioctl structure passed in from user land
3103  * into kernel land. Handles 32 bit applications.
3104  */
3105 /*ARGSUSED*/
3106 static int
3107 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3108     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3109 {
3110         struct fcp_port *t_pptr;
3111 
3112 #ifdef  _MULTI_DATAMODEL
3113         switch (ddi_model_convert_from(mode & FMODELS)) {
3114         case DDI_MODEL_ILP32: {
3115                 struct fcp32_ioctl f32_ioctl;
3116 
3117                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3118                     sizeof (struct fcp32_ioctl), mode)) {
3119                         return (EFAULT);
3120                 }
3121                 fioctl->fp_minor = f32_ioctl.fp_minor;
3122                 fioctl->listlen = f32_ioctl.listlen;
3123                 fioctl->list = (caddr_t)(long)f32_ioctl.list;
3124                 break;
3125         }
3126         case DDI_MODEL_NONE:
3127                 if (ddi_copyin((void *)data, (void *)fioctl,
3128                     sizeof (struct fcp_ioctl), mode)) {
3129                         return (EFAULT);
3130                 }
3131                 break;
3132         }
3133 
3134 #else   /* _MULTI_DATAMODEL */
3135         if (ddi_copyin((void *)data, (void *)fioctl,
3136             sizeof (struct fcp_ioctl), mode)) {
3137                 return (EFAULT);
3138         }
3139 #endif  /* _MULTI_DATAMODEL */
3140 
3141         /*
3142          * Right now we can assume that the minor number matches with
3143          * this instance of fp. If this changes we will need to
3144          * revisit this logic.
3145          */
3146         mutex_enter(&fcp_global_mutex);
3147         t_pptr = fcp_port_head;
3148         while (t_pptr) {
3149                 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3150                         break;
3151                 } else {
3152                         t_pptr = t_pptr->port_next;
3153                 }
3154         }
3155         *pptr = t_pptr;
3156         mutex_exit(&fcp_global_mutex);
3157         if (t_pptr == NULL) {
3158                 return (ENXIO);
3159         }
3160 
3161         return (0);
3162 }
3163 
3164 /*
3165  *     Function: fcp_port_create_tgt
3166  *
3167  *  Description: As the name suggest this function creates the target context
3168  *               specified by the the WWN provided by the caller.  If the
3169  *               creation goes well and the target is known by fp/fctl a PLOGI
3170  *               followed by a PRLI are issued.
3171  *
3172  *     Argument: pptr           fcp port structure
3173  *               pwwn           WWN of the target
3174  *               ret_val        Address of the return code.  It could be:
3175  *                              EIO, ENOMEM or 0.
3176  *               fc_status      PLOGI or PRLI status completion
3177  *               fc_pkt_state   PLOGI or PRLI state completion
3178  *               fc_pkt_reason  PLOGI or PRLI reason completion
3179  *               fc_pkt_action  PLOGI or PRLI action completion
3180  *
3181  * Return Value: NULL if it failed
3182  *               Target structure address if it succeeds
3183  */
3184 static struct fcp_tgt *
3185 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3186     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3187 {
3188         struct fcp_tgt  *ptgt = NULL;
3189         fc_portmap_t            devlist;
3190         int                     lcount;
3191         int                     error;
3192 
3193         *ret_val = 0;
3194 
3195         /*
3196          * Check FC port device & get port map
3197          */
3198         if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3199             &error, 1) == NULL) {
3200                 *ret_val = EIO;
3201         } else {
3202                 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3203                     &devlist) != FC_SUCCESS) {
3204                         *ret_val = EIO;
3205                 }
3206         }
3207 
3208         /* Set port map flags */
3209         devlist.map_type = PORT_DEVICE_USER_CREATE;
3210 
3211         /* Allocate target */
3212         if (*ret_val == 0) {
3213                 lcount = pptr->port_link_cnt;
3214                 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3215                 if (ptgt == NULL) {
3216                         fcp_log(CE_WARN, pptr->port_dip,
3217                             "!FC target allocation failed");
3218                         *ret_val = ENOMEM;
3219                 } else {
3220                         /* Setup target */
3221                         mutex_enter(&ptgt->tgt_mutex);
3222 
3223                         ptgt->tgt_statec_cause       = FCP_CAUSE_TGT_CHANGE;
3224                         ptgt->tgt_tmp_cnt    = 1;
3225                         ptgt->tgt_d_id               = devlist.map_did.port_id;
3226                         ptgt->tgt_hard_addr  =
3227                             devlist.map_hard_addr.hard_addr;
3228                         ptgt->tgt_pd_handle  = devlist.map_pd;
3229                         ptgt->tgt_fca_dev    = NULL;
3230 
3231                         bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3232                             FC_WWN_SIZE);
3233                         bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3234                             FC_WWN_SIZE);
3235 
3236                         mutex_exit(&ptgt->tgt_mutex);
3237                 }
3238         }
3239 
3240         /* Release global mutex for PLOGI and PRLI */
3241         mutex_exit(&fcp_global_mutex);
3242 
3243         /* Send PLOGI (If necessary) */
3244         if (*ret_val == 0) {
3245                 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3246                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3247         }
3248 
3249         /* Send PRLI (If necessary) */
3250         if (*ret_val == 0) {
3251                 *ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3252                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3253         }
3254 
3255         mutex_enter(&fcp_global_mutex);
3256 
3257         return (ptgt);
3258 }
3259 
3260 /*
3261  *     Function: fcp_tgt_send_plogi
3262  *
3263  *  Description: This function sends a PLOGI to the target specified by the
3264  *               caller and waits till it completes.
3265  *
3266  *     Argument: ptgt           Target to send the plogi to.
3267  *               fc_status      Status returned by fp/fctl in the PLOGI request.
3268  *               fc_pkt_state   State returned by fp/fctl in the PLOGI request.
3269  *               fc_pkt_reason  Reason returned by fp/fctl in the PLOGI request.
3270  *               fc_pkt_action  Action returned by fp/fctl in the PLOGI request.
3271  *
3272  * Return Value: 0
3273  *               ENOMEM
3274  *               EIO
3275  *
3276  *      Context: User context.
3277  */
3278 static int
3279 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3280     int *fc_pkt_reason, int *fc_pkt_action)
3281 {
3282         struct fcp_port *pptr;
3283         struct fcp_ipkt *icmd;
3284         struct fc_packet        *fpkt;
3285         fc_frame_hdr_t          *hp;
3286         struct la_els_logi      logi;
3287         int                     tcount;
3288         int                     lcount;
3289         int                     ret, login_retval = ~FC_SUCCESS;
3290 
3291         ret = 0;
3292 
3293         pptr = ptgt->tgt_port;
3294 
3295         lcount = pptr->port_link_cnt;
3296         tcount = ptgt->tgt_change_cnt;
3297 
3298         /* Alloc internal packet */
3299         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3300             sizeof (la_els_logi_t), 0,
3301             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3302             lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3303 
3304         if (icmd == NULL) {
3305                 ret = ENOMEM;
3306         } else {
3307                 /*
3308                  * Setup internal packet as sema sync
3309                  */
3310                 fcp_ipkt_sema_init(icmd);
3311 
3312                 /*
3313                  * Setup internal packet (icmd)
3314                  */
3315                 icmd->ipkt_lun               = NULL;
3316                 icmd->ipkt_restart   = 0;
3317                 icmd->ipkt_retries   = 0;
3318                 icmd->ipkt_opcode    = LA_ELS_PLOGI;
3319 
3320                 /*
3321                  * Setup fc_packet
3322                  */
3323                 fpkt = icmd->ipkt_fpkt;
3324 
3325                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
3326                 fpkt->pkt_tran_type  = FC_PKT_EXCHANGE;
3327                 fpkt->pkt_timeout    = FCP_ELS_TIMEOUT;
3328 
3329                 /*
3330                  * Setup FC frame header
3331                  */
3332                 hp = &fpkt->pkt_cmd_fhdr;
3333 
3334                 hp->s_id     = pptr->port_id;     /* source ID */
3335                 hp->d_id     = ptgt->tgt_d_id;    /* dest ID */
3336                 hp->r_ctl    = R_CTL_ELS_REQ;
3337                 hp->type     = FC_TYPE_EXTENDED_LS;
3338                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3339                 hp->seq_id   = 0;
3340                 hp->rsvd     = 0;
3341                 hp->df_ctl   = 0;
3342                 hp->seq_cnt  = 0;
3343                 hp->ox_id    = 0xffff;               /* i.e. none */
3344                 hp->rx_id    = 0xffff;               /* i.e. none */
3345                 hp->ro               = 0;
3346 
3347                 /*
3348                  * Setup PLOGI
3349                  */
3350                 bzero(&logi, sizeof (struct la_els_logi));
3351                 logi.ls_code.ls_code = LA_ELS_PLOGI;
3352 
3353                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3354                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3355 
3356                 /*
3357                  * Send PLOGI
3358                  */
3359                 *fc_status = login_retval =
3360                     fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3361                 if (*fc_status != FC_SUCCESS) {
3362                         ret = EIO;
3363                 }
3364         }
3365 
3366         /*
3367          * Wait for completion
3368          */
3369         if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3370                 ret = fcp_ipkt_sema_wait(icmd);
3371 
3372                 *fc_pkt_state   = fpkt->pkt_state;
3373                 *fc_pkt_reason  = fpkt->pkt_reason;
3374                 *fc_pkt_action  = fpkt->pkt_action;
3375         }
3376 
3377         /*
3378          * Cleanup transport data structures if icmd was alloc-ed AND if there
3379          * is going to be no callback (i.e if fc_ulp_login() failed).
3380          * Otherwise, cleanup happens in callback routine.
3381          */
3382         if (icmd != NULL) {
3383                 fcp_ipkt_sema_cleanup(icmd);
3384         }
3385 
3386         return (ret);
3387 }
3388 
3389 /*
3390  *     Function: fcp_tgt_send_prli
3391  *
3392  *  Description: Does nothing as of today.
3393  *
3394  *     Argument: ptgt           Target to send the prli to.
3395  *               fc_status      Status returned by fp/fctl in the PRLI request.
3396  *               fc_pkt_state   State returned by fp/fctl in the PRLI request.
3397  *               fc_pkt_reason  Reason returned by fp/fctl in the PRLI request.
3398  *               fc_pkt_action  Action returned by fp/fctl in the PRLI request.
3399  *
3400  * Return Value: 0
3401  */
3402 /*ARGSUSED*/
3403 static int
3404 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3405     int *fc_pkt_reason, int *fc_pkt_action)
3406 {
3407         return (0);
3408 }
3409 
3410 /*
3411  *     Function: fcp_ipkt_sema_init
3412  *
3413  *  Description: Initializes the semaphore contained in the internal packet.
3414  *
3415  *     Argument: icmd   Internal packet the semaphore of which must be
3416  *                      initialized.
3417  *
3418  * Return Value: None
3419  *
3420  *      Context: User context only.
3421  */
3422 static void
3423 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3424 {
3425         struct fc_packet        *fpkt;
3426 
3427         fpkt = icmd->ipkt_fpkt;
3428 
3429         /* Create semaphore for sync */
3430         sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3431 
3432         /* Setup the completion callback */
3433         fpkt->pkt_comp = fcp_ipkt_sema_callback;
3434 }
3435 
3436 /*
3437  *     Function: fcp_ipkt_sema_wait
3438  *
3439  *  Description: Wait on the semaphore embedded in the internal packet.  The
3440  *               semaphore is released in the callback.
3441  *
3442  *     Argument: icmd   Internal packet to wait on for completion.
3443  *
3444  * Return Value: 0
3445  *               EIO
3446  *               EBUSY
3447  *               EAGAIN
3448  *
3449  *      Context: User context only.
3450  *
3451  * This function does a conversion between the field pkt_state of the fc_packet
3452  * embedded in the internal packet (icmd) and the code it returns.
3453  */
3454 static int
3455 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3456 {
3457         struct fc_packet        *fpkt;
3458         int     ret;
3459 
3460         ret = EIO;
3461         fpkt = icmd->ipkt_fpkt;
3462 
3463         /*
3464          * Wait on semaphore
3465          */
3466         sema_p(&(icmd->ipkt_sema));
3467 
3468         /*
3469          * Check the status of the FC packet
3470          */
3471         switch (fpkt->pkt_state) {
3472         case FC_PKT_SUCCESS:
3473                 ret = 0;
3474                 break;
3475         case FC_PKT_LOCAL_RJT:
3476                 switch (fpkt->pkt_reason) {
3477                 case FC_REASON_SEQ_TIMEOUT:
3478                 case FC_REASON_RX_BUF_TIMEOUT:
3479                         ret = EAGAIN;
3480                         break;
3481                 case FC_REASON_PKT_BUSY:
3482                         ret = EBUSY;
3483                         break;
3484                 }
3485                 break;
3486         case FC_PKT_TIMEOUT:
3487                 ret = EAGAIN;
3488                 break;
3489         case FC_PKT_LOCAL_BSY:
3490         case FC_PKT_TRAN_BSY:
3491         case FC_PKT_NPORT_BSY:
3492         case FC_PKT_FABRIC_BSY:
3493                 ret = EBUSY;
3494                 break;
3495         case FC_PKT_LS_RJT:
3496         case FC_PKT_BA_RJT:
3497                 switch (fpkt->pkt_reason) {
3498                 case FC_REASON_LOGICAL_BSY:
3499                         ret = EBUSY;
3500                         break;
3501                 }
3502                 break;
3503         case FC_PKT_FS_RJT:
3504                 switch (fpkt->pkt_reason) {
3505                 case FC_REASON_FS_LOGICAL_BUSY:
3506                         ret = EBUSY;
3507                         break;
3508                 }
3509                 break;
3510         }
3511 
3512         return (ret);
3513 }
3514 
3515 /*
3516  *     Function: fcp_ipkt_sema_callback
3517  *
3518  *  Description: Registered as the completion callback function for the FC
3519  *               transport when the ipkt semaphore is used for sync. This will
3520  *               cleanup the used data structures, if necessary and wake up
3521  *               the user thread to complete the transaction.
3522  *
3523  *     Argument: fpkt   FC packet (points to the icmd)
3524  *
3525  * Return Value: None
3526  *
3527  *      Context: User context only
3528  */
3529 static void
3530 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3531 {
3532         struct fcp_ipkt *icmd;
3533 
3534         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3535 
3536         /*
3537          * Wake up user thread
3538          */
3539         sema_v(&(icmd->ipkt_sema));
3540 }
3541 
3542 /*
3543  *     Function: fcp_ipkt_sema_cleanup
3544  *
3545  *  Description: Called to cleanup (if necessary) the data structures used
3546  *               when ipkt sema is used for sync.  This function will detect
3547  *               whether the caller is the last thread (via counter) and
3548  *               cleanup only if necessary.
3549  *
3550  *     Argument: icmd   Internal command packet
3551  *
3552  * Return Value: None
3553  *
3554  *      Context: User context only
3555  */
3556 static void
3557 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3558 {
3559         struct fcp_tgt  *ptgt;
3560         struct fcp_port *pptr;
3561 
3562         ptgt = icmd->ipkt_tgt;
3563         pptr = icmd->ipkt_port;
3564 
3565         /*
3566          * Acquire data structure
3567          */
3568         mutex_enter(&ptgt->tgt_mutex);
3569 
3570         /*
3571          * Destroy semaphore
3572          */
3573         sema_destroy(&(icmd->ipkt_sema));
3574 
3575         /*
3576          * Cleanup internal packet
3577          */
3578         mutex_exit(&ptgt->tgt_mutex);
3579         fcp_icmd_free(pptr, icmd);
3580 }
3581 
3582 /*
3583  *     Function: fcp_port_attach
3584  *
3585  *  Description: Called by the transport framework to resume, suspend or
3586  *               attach a new port.
3587  *
3588  *     Argument: ulph           Port handle
3589  *               *pinfo         Port information
3590  *               cmd            Command
3591  *               s_id           Port ID
3592  *
3593  * Return Value: FC_FAILURE or FC_SUCCESS
3594  */
3595 /*ARGSUSED*/
3596 static int
3597 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3598     fc_attach_cmd_t cmd, uint32_t s_id)
3599 {
3600         int     instance;
3601         int     res = FC_FAILURE; /* default result */
3602 
3603         ASSERT(pinfo != NULL);
3604 
3605         instance = ddi_get_instance(pinfo->port_dip);
3606 
3607         switch (cmd) {
3608         case FC_CMD_ATTACH:
3609                 /*
3610                  * this port instance attaching for the first time (or after
3611                  * being detached before)
3612                  */
3613                 if (fcp_handle_port_attach(ulph, pinfo, s_id,
3614                     instance) == DDI_SUCCESS) {
3615                         res = FC_SUCCESS;
3616                 } else {
3617                         ASSERT(ddi_get_soft_state(fcp_softstate,
3618                             instance) == NULL);
3619                 }
3620                 break;
3621 
3622         case FC_CMD_RESUME:
3623         case FC_CMD_POWER_UP:
3624                 /*
3625                  * this port instance was attached and the suspended and
3626                  * will now be resumed
3627                  */
3628                 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3629                     instance) == DDI_SUCCESS) {
3630                         res = FC_SUCCESS;
3631                 }
3632                 break;
3633 
3634         default:
3635                 /* shouldn't happen */
3636                 FCP_TRACE(fcp_logq, "fcp",
3637                     fcp_trace, FCP_BUF_LEVEL_2, 0,
3638                     "port_attach: unknown cmdcommand: %d", cmd);
3639                 break;
3640         }
3641 
3642         /* return result */
3643         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3644             FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3645 
3646         return (res);
3647 }
3648 
3649 
3650 /*
3651  * detach or suspend this port instance
3652  *
3653  * acquires and releases the global mutex
3654  *
3655  * acquires and releases the mutex for this port
3656  *
3657  * acquires and releases the hotplug mutex for this port
3658  */
3659 /*ARGSUSED*/
3660 static int
3661 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3662     fc_detach_cmd_t cmd)
3663 {
3664         int                     flag;
3665         int                     instance;
3666         struct fcp_port         *pptr;
3667 
3668         instance = ddi_get_instance(info->port_dip);
3669         pptr = ddi_get_soft_state(fcp_softstate, instance);
3670 
3671         switch (cmd) {
3672         case FC_CMD_SUSPEND:
3673                 FCP_DTRACE(fcp_logq, "fcp",
3674                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3675                     "port suspend called for port %d", instance);
3676                 flag = FCP_STATE_SUSPENDED;
3677                 break;
3678 
3679         case FC_CMD_POWER_DOWN:
3680                 FCP_DTRACE(fcp_logq, "fcp",
3681                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3682                     "port power down called for port %d", instance);
3683                 flag = FCP_STATE_POWER_DOWN;
3684                 break;
3685 
3686         case FC_CMD_DETACH:
3687                 FCP_DTRACE(fcp_logq, "fcp",
3688                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3689                     "port detach called for port %d", instance);
3690                 flag = FCP_STATE_DETACHING;
3691                 break;
3692 
3693         default:
3694                 /* shouldn't happen */
3695                 return (FC_FAILURE);
3696         }
3697         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3698             FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3699 
3700         return (fcp_handle_port_detach(pptr, flag, instance));
3701 }
3702 
3703 
3704 /*
3705  * called for ioctls on the transport's devctl interface, and the transport
3706  * has passed it to us
3707  *
3708  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3709  *
3710  * return FC_SUCCESS if we decide to claim the ioctl,
3711  * else return FC_UNCLAIMED
3712  *
3713  * *rval is set iff we decide to claim the ioctl
3714  */
3715 /*ARGSUSED*/
3716 static int
3717 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3718     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3719 {
3720         int                     retval = FC_UNCLAIMED;  /* return value */
3721         struct fcp_port         *pptr = NULL;           /* our soft state */
3722         struct devctl_iocdata   *dcp = NULL;            /* for devctl */
3723         dev_info_t              *cdip;
3724         mdi_pathinfo_t          *pip = NULL;
3725         char                    *ndi_nm;                /* NDI name */
3726         char                    *ndi_addr;              /* NDI addr */
3727         int                     is_mpxio, circ;
3728         int                     devi_entered = 0;
3729         clock_t                 end_time;
3730 
3731         ASSERT(rval != NULL);
3732 
3733         FCP_DTRACE(fcp_logq, "fcp",
3734             fcp_trace, FCP_BUF_LEVEL_8, 0,
3735             "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3736 
3737         /* if already claimed then forget it */
3738         if (claimed) {
3739                 /*
3740                  * for now, if this ioctl has already been claimed, then
3741                  * we just ignore it
3742                  */
3743                 return (retval);
3744         }
3745 
3746         /* get our port info */
3747         if ((pptr = fcp_get_port(port_handle)) == NULL) {
3748                 fcp_log(CE_WARN, NULL,
3749                     "!fcp:Invalid port handle handle in ioctl");
3750                 *rval = ENXIO;
3751                 return (retval);
3752         }
3753         is_mpxio = pptr->port_mpxio;
3754 
3755         switch (cmd) {
3756         case DEVCTL_BUS_GETSTATE:
3757         case DEVCTL_BUS_QUIESCE:
3758         case DEVCTL_BUS_UNQUIESCE:
3759         case DEVCTL_BUS_RESET:
3760         case DEVCTL_BUS_RESETALL:
3761 
3762         case DEVCTL_BUS_DEV_CREATE:
3763                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3764                         return (retval);
3765                 }
3766                 break;
3767 
3768         case DEVCTL_DEVICE_GETSTATE:
3769         case DEVCTL_DEVICE_OFFLINE:
3770         case DEVCTL_DEVICE_ONLINE:
3771         case DEVCTL_DEVICE_REMOVE:
3772         case DEVCTL_DEVICE_RESET:
3773                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3774                         return (retval);
3775                 }
3776 
3777                 ASSERT(dcp != NULL);
3778 
3779                 /* ensure we have a name and address */
3780                 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3781                     ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3782                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
3783                             fcp_trace, FCP_BUF_LEVEL_2, 0,
3784                             "ioctl: can't get name (%s) or addr (%s)",
3785                             ndi_nm ? ndi_nm : "<null ptr>",
3786                             ndi_addr ? ndi_addr : "<null ptr>");
3787                         ndi_dc_freehdl(dcp);
3788                         return (retval);
3789                 }
3790 
3791 
3792                 /* get our child's DIP */
3793                 ASSERT(pptr != NULL);
3794                 if (is_mpxio) {
3795                         mdi_devi_enter(pptr->port_dip, &circ);
3796                 } else {
3797                         ndi_devi_enter(pptr->port_dip, &circ);
3798                 }
3799                 devi_entered = 1;
3800 
3801                 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3802                     ndi_addr)) == NULL) {
3803                         /* Look for virtually enumerated devices. */
3804                         pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3805                         if (pip == NULL ||
3806                             ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3807                                 *rval = ENXIO;
3808                                 goto out;
3809                         }
3810                 }
3811                 break;
3812 
3813         default:
3814                 *rval = ENOTTY;
3815                 return (retval);
3816         }
3817 
3818         /* this ioctl is ours -- process it */
3819 
3820         retval = FC_SUCCESS;            /* just means we claim the ioctl */
3821 
3822         /* we assume it will be a success; else we'll set error value */
3823         *rval = 0;
3824 
3825 
3826         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3827             fcp_trace, FCP_BUF_LEVEL_8, 0,
3828             "ioctl: claiming this one");
3829 
3830         /* handle ioctls now */
3831         switch (cmd) {
3832         case DEVCTL_DEVICE_GETSTATE:
3833                 ASSERT(cdip != NULL);
3834                 ASSERT(dcp != NULL);
3835                 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3836                         *rval = EFAULT;
3837                 }
3838                 break;
3839 
3840         case DEVCTL_DEVICE_REMOVE:
3841         case DEVCTL_DEVICE_OFFLINE: {
3842                 int                     flag = 0;
3843                 int                     lcount;
3844                 int                     tcount;
3845                 struct fcp_pkt  *head = NULL;
3846                 struct fcp_lun  *plun;
3847                 child_info_t            *cip = CIP(cdip);
3848                 int                     all = 1;
3849                 struct fcp_lun  *tplun;
3850                 struct fcp_tgt  *ptgt;
3851 
3852                 ASSERT(pptr != NULL);
3853                 ASSERT(cdip != NULL);
3854 
3855                 mutex_enter(&pptr->port_mutex);
3856                 if (pip != NULL) {
3857                         cip = CIP(pip);
3858                 }
3859                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3860                         mutex_exit(&pptr->port_mutex);
3861                         *rval = ENXIO;
3862                         break;
3863                 }
3864 
3865                 head = fcp_scan_commands(plun);
3866                 if (head != NULL) {
3867                         fcp_abort_commands(head, LUN_PORT);
3868                 }
3869                 lcount = pptr->port_link_cnt;
3870                 tcount = plun->lun_tgt->tgt_change_cnt;
3871                 mutex_exit(&pptr->port_mutex);
3872 
3873                 if (cmd == DEVCTL_DEVICE_REMOVE) {
3874                         flag = NDI_DEVI_REMOVE;
3875                 }
3876 
3877                 if (is_mpxio) {
3878                         mdi_devi_exit(pptr->port_dip, circ);
3879                 } else {
3880                         ndi_devi_exit(pptr->port_dip, circ);
3881                 }
3882                 devi_entered = 0;
3883 
3884                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3885                     FCP_OFFLINE, lcount, tcount, flag);
3886 
3887                 if (*rval != NDI_SUCCESS) {
3888                         *rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3889                         break;
3890                 }
3891 
3892                 fcp_update_offline_flags(plun);
3893 
3894                 ptgt = plun->lun_tgt;
3895                 mutex_enter(&ptgt->tgt_mutex);
3896                 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3897                     tplun->lun_next) {
3898                         mutex_enter(&tplun->lun_mutex);
3899                         if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3900                                 all = 0;
3901                         }
3902                         mutex_exit(&tplun->lun_mutex);
3903                 }
3904 
3905                 if (all) {
3906                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3907                         /*
3908                          * The user is unconfiguring/offlining the device.
3909                          * If fabric and the auto configuration is set
3910                          * then make sure the user is the only one who
3911                          * can reconfigure the device.
3912                          */
3913                         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3914                             fcp_enable_auto_configuration) {
3915                                 ptgt->tgt_manual_config_only = 1;
3916                         }
3917                 }
3918                 mutex_exit(&ptgt->tgt_mutex);
3919                 break;
3920         }
3921 
3922         case DEVCTL_DEVICE_ONLINE: {
3923                 int                     lcount;
3924                 int                     tcount;
3925                 struct fcp_lun  *plun;
3926                 child_info_t            *cip = CIP(cdip);
3927 
3928                 ASSERT(cdip != NULL);
3929                 ASSERT(pptr != NULL);
3930 
3931                 mutex_enter(&pptr->port_mutex);
3932                 if (pip != NULL) {
3933                         cip = CIP(pip);
3934                 }
3935                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3936                         mutex_exit(&pptr->port_mutex);
3937                         *rval = ENXIO;
3938                         break;
3939                 }
3940                 lcount = pptr->port_link_cnt;
3941                 tcount = plun->lun_tgt->tgt_change_cnt;
3942                 mutex_exit(&pptr->port_mutex);
3943 
3944                 /*
3945                  * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3946                  * to allow the device attach to occur when the device is
3947                  * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3948                  * from the scsi_probe()).
3949                  */
3950                 mutex_enter(&LUN_TGT->tgt_mutex);
3951                 plun->lun_state |= FCP_LUN_ONLINING;
3952                 mutex_exit(&LUN_TGT->tgt_mutex);
3953 
3954                 if (is_mpxio) {
3955                         mdi_devi_exit(pptr->port_dip, circ);
3956                 } else {
3957                         ndi_devi_exit(pptr->port_dip, circ);
3958                 }
3959                 devi_entered = 0;
3960 
3961                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3962                     FCP_ONLINE, lcount, tcount, 0);
3963 
3964                 if (*rval != NDI_SUCCESS) {
3965                         /* Reset the FCP_LUN_ONLINING bit */
3966                         mutex_enter(&LUN_TGT->tgt_mutex);
3967                         plun->lun_state &= ~FCP_LUN_ONLINING;
3968                         mutex_exit(&LUN_TGT->tgt_mutex);
3969                         *rval = EIO;
3970                         break;
3971                 }
3972                 mutex_enter(&LUN_TGT->tgt_mutex);
3973                 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3974                     FCP_LUN_ONLINING);
3975                 mutex_exit(&LUN_TGT->tgt_mutex);
3976                 break;
3977         }
3978 
3979         case DEVCTL_BUS_DEV_CREATE: {
3980                 uchar_t                 *bytes = NULL;
3981                 uint_t                  nbytes;
3982                 struct fcp_tgt          *ptgt = NULL;
3983                 struct fcp_lun          *plun = NULL;
3984                 dev_info_t              *useless_dip = NULL;
3985 
3986                 *rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3987                     DEVCTL_CONSTRUCT, &useless_dip);
3988                 if (*rval != 0 || useless_dip == NULL) {
3989                         break;
3990                 }
3991 
3992                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3993                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3994                     &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3995                         *rval = EINVAL;
3996                         (void) ndi_devi_free(useless_dip);
3997                         if (bytes != NULL) {
3998                                 ddi_prop_free(bytes);
3999                         }
4000                         break;
4001                 }
4002 
4003                 *rval = fcp_create_on_demand(pptr, bytes);
4004                 if (*rval == 0) {
4005                         mutex_enter(&pptr->port_mutex);
4006                         ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4007                         if (ptgt) {
4008                                 /*
4009                                  * We now have a pointer to the target that
4010                                  * was created. Lets point to the first LUN on
4011                                  * this new target.
4012                                  */
4013                                 mutex_enter(&ptgt->tgt_mutex);
4014 
4015                                 plun = ptgt->tgt_lun;
4016                                 /*
4017                                  * There may be stale/offline LUN entries on
4018                                  * this list (this is by design) and so we have
4019                                  * to make sure we point to the first online
4020                                  * LUN
4021                                  */
4022                                 while (plun &&
4023                                     plun->lun_state & FCP_LUN_OFFLINE) {
4024                                         plun = plun->lun_next;
4025                                 }
4026 
4027                                 mutex_exit(&ptgt->tgt_mutex);
4028                         }
4029                         mutex_exit(&pptr->port_mutex);
4030                 }
4031 
4032                 if (*rval == 0 && ptgt && plun) {
4033                         mutex_enter(&plun->lun_mutex);
4034                         /*
4035                          * Allow up to fcp_lun_ready_retry seconds to
4036                          * configure all the luns behind the target.
4037                          *
4038                          * The intent here is to allow targets with long
4039                          * reboot/reset-recovery times to become available
4040                          * while limiting the maximum wait time for an
4041                          * unresponsive target.
4042                          */
4043                         end_time = ddi_get_lbolt() +
4044                             SEC_TO_TICK(fcp_lun_ready_retry);
4045 
4046                         while (ddi_get_lbolt() < end_time) {
4047                                 retval = FC_SUCCESS;
4048 
4049                                 /*
4050                                  * The new ndi interfaces for on-demand creation
4051                                  * are inflexible, Do some more work to pass on
4052                                  * a path name of some LUN (design is broken !)
4053                                  */
4054                                 if (plun->lun_cip) {
4055                                         if (plun->lun_mpxio == 0) {
4056                                                 cdip = DIP(plun->lun_cip);
4057                                         } else {
4058                                                 cdip = mdi_pi_get_client(
4059                                                     PIP(plun->lun_cip));
4060                                         }
4061                                         if (cdip == NULL) {
4062                                                 *rval = ENXIO;
4063                                                 break;
4064                                         }
4065 
4066                                         if (!i_ddi_devi_attached(cdip)) {
4067                                                 mutex_exit(&plun->lun_mutex);
4068                                                 delay(drv_usectohz(1000000));
4069                                                 mutex_enter(&plun->lun_mutex);
4070                                         } else {
4071                                                 /*
4072                                                  * This Lun is ready, lets
4073                                                  * check the next one.
4074                                                  */
4075                                                 mutex_exit(&plun->lun_mutex);
4076                                                 plun = plun->lun_next;
4077                                                 while (plun && (plun->lun_state
4078                                                     & FCP_LUN_OFFLINE)) {
4079                                                         plun = plun->lun_next;
4080                                                 }
4081                                                 if (!plun) {
4082                                                         break;
4083                                                 }
4084                                                 mutex_enter(&plun->lun_mutex);
4085                                         }
4086                                 } else {
4087                                         /*
4088                                          * lun_cip field for a valid lun
4089                                          * should never be NULL. Fail the
4090                                          * command.
4091                                          */
4092                                         *rval = ENXIO;
4093                                         break;
4094                                 }
4095                         }
4096                         if (plun) {
4097                                 mutex_exit(&plun->lun_mutex);
4098                         } else {
4099                                 char devnm[MAXNAMELEN];
4100                                 int nmlen;
4101 
4102                                 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4103                                     ddi_node_name(cdip),
4104                                     ddi_get_name_addr(cdip));
4105 
4106                                 if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4107                                     0) {
4108                                         *rval = EFAULT;
4109                                 }
4110                         }
4111                 } else {
4112                         int     i;
4113                         char    buf[25];
4114 
4115                         for (i = 0; i < FC_WWN_SIZE; i++) {
4116                                 (void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4117                         }
4118 
4119                         fcp_log(CE_WARN, pptr->port_dip,
4120                             "!Failed to create nodes for pwwn=%s; error=%x",
4121                             buf, *rval);
4122                 }
4123 
4124                 (void) ndi_devi_free(useless_dip);
4125                 ddi_prop_free(bytes);
4126                 break;
4127         }
4128 
4129         case DEVCTL_DEVICE_RESET: {
4130                 struct fcp_lun          *plun;
4131                 child_info_t            *cip = CIP(cdip);
4132 
4133                 ASSERT(cdip != NULL);
4134                 ASSERT(pptr != NULL);
4135                 mutex_enter(&pptr->port_mutex);
4136                 if (pip != NULL) {
4137                         cip = CIP(pip);
4138                 }
4139                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4140                         mutex_exit(&pptr->port_mutex);
4141                         *rval = ENXIO;
4142                         break;
4143                 }
4144                 mutex_exit(&pptr->port_mutex);
4145 
4146                 mutex_enter(&plun->lun_tgt->tgt_mutex);
4147                 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4148                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4149 
4150                         *rval = ENXIO;
4151                         break;
4152                 }
4153 
4154                 if (plun->lun_sd == NULL) {
4155                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4156 
4157                         *rval = ENXIO;
4158                         break;
4159                 }
4160                 mutex_exit(&plun->lun_tgt->tgt_mutex);
4161 
4162                 /*
4163                  * set up ap so that fcp_reset can figure out
4164                  * which target to reset
4165                  */
4166                 if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4167                     RESET_TARGET) == FALSE) {
4168                         *rval = EIO;
4169                 }
4170                 break;
4171         }
4172 
4173         case DEVCTL_BUS_GETSTATE:
4174                 ASSERT(dcp != NULL);
4175                 ASSERT(pptr != NULL);
4176                 ASSERT(pptr->port_dip != NULL);
4177                 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4178                     NDI_SUCCESS) {
4179                         *rval = EFAULT;
4180                 }
4181                 break;
4182 
4183         case DEVCTL_BUS_QUIESCE:
4184         case DEVCTL_BUS_UNQUIESCE:
4185                 *rval = ENOTSUP;
4186                 break;
4187 
4188         case DEVCTL_BUS_RESET:
4189         case DEVCTL_BUS_RESETALL:
4190                 ASSERT(pptr != NULL);
4191                 (void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4192                 break;
4193 
4194         default:
4195                 ASSERT(dcp != NULL);
4196                 *rval = ENOTTY;
4197                 break;
4198         }
4199 
4200         /* all done -- clean up and return */
4201 out:    if (devi_entered) {
4202                 if (is_mpxio) {
4203                         mdi_devi_exit(pptr->port_dip, circ);
4204                 } else {
4205                         ndi_devi_exit(pptr->port_dip, circ);
4206                 }
4207         }
4208 
4209         if (dcp != NULL) {
4210                 ndi_dc_freehdl(dcp);
4211         }
4212 
4213         return (retval);
4214 }
4215 
4216 
4217 /*ARGSUSED*/
4218 static int
4219 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4220     uint32_t claimed)
4221 {
4222         uchar_t                 r_ctl;
4223         uchar_t                 ls_code;
4224         struct fcp_port *pptr;
4225 
4226         if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4227                 return (FC_UNCLAIMED);
4228         }
4229 
4230         mutex_enter(&pptr->port_mutex);
4231         if (pptr->port_state & (FCP_STATE_DETACHING |
4232             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4233                 mutex_exit(&pptr->port_mutex);
4234                 return (FC_UNCLAIMED);
4235         }
4236         mutex_exit(&pptr->port_mutex);
4237 
4238         r_ctl = buf->ub_frame.r_ctl;
4239 
4240         switch (r_ctl & R_CTL_ROUTING) {
4241         case R_CTL_EXTENDED_SVC:
4242                 if (r_ctl == R_CTL_ELS_REQ) {
4243                         ls_code = buf->ub_buffer[0];
4244 
4245                         switch (ls_code) {
4246                         case LA_ELS_PRLI:
4247                                 /*
4248                                  * We really don't care if something fails.
4249                                  * If the PRLI was not sent out, then the
4250                                  * other end will time it out.
4251                                  */
4252                                 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4253                                         return (FC_SUCCESS);
4254                                 }
4255                                 return (FC_UNCLAIMED);
4256                                 /* NOTREACHED */
4257 
4258                         default:
4259                                 break;
4260                         }
4261                 }
4262                 /* FALLTHROUGH */
4263 
4264         default:
4265                 return (FC_UNCLAIMED);
4266         }
4267 }
4268 
4269 
4270 /*ARGSUSED*/
4271 static int
4272 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4273     uint32_t claimed)
4274 {
4275         return (FC_UNCLAIMED);
4276 }
4277 
4278 /*
4279  *     Function: fcp_statec_callback
4280  *
4281  *  Description: The purpose of this function is to handle a port state change.
4282  *               It is called from fp/fctl and, in a few instances, internally.
4283  *
4284  *     Argument: ulph           fp/fctl port handle
4285  *               port_handle    fcp_port structure
4286  *               port_state     Physical state of the port
4287  *               port_top       Topology
4288  *               *devlist       Pointer to the first entry of a table
4289  *                              containing the remote ports that can be
4290  *                              reached.
4291  *               dev_cnt        Number of entries pointed by devlist.
4292  *               port_sid       Port ID of the local port.
4293  *
4294  * Return Value: None
4295  */
4296 /*ARGSUSED*/
4297 static void
4298 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4299     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4300     uint32_t dev_cnt, uint32_t port_sid)
4301 {
4302         uint32_t                link_count;
4303         int                     map_len = 0;
4304         struct fcp_port *pptr;
4305         fcp_map_tag_t           *map_tag = NULL;
4306 
4307         if ((pptr = fcp_get_port(port_handle)) == NULL) {
4308                 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4309                 return;                 /* nothing to work with! */
4310         }
4311 
4312         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4313             fcp_trace, FCP_BUF_LEVEL_2, 0,
4314             "fcp_statec_callback: port state/dev_cnt/top ="
4315             "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4316             dev_cnt, port_top);
4317 
4318         mutex_enter(&pptr->port_mutex);
4319 
4320         /*
4321          * If a thread is in detach, don't do anything.
4322          */
4323         if (pptr->port_state & (FCP_STATE_DETACHING |
4324             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4325                 mutex_exit(&pptr->port_mutex);
4326                 return;
4327         }
4328 
4329         /*
4330          * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4331          * init_pkt is called, it knows whether or not the target's status
4332          * (or pd) might be changing.
4333          */
4334 
4335         if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4336                 pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4337         }
4338 
4339         /*
4340          * the transport doesn't allocate or probe unless being
4341          * asked to by either the applications or ULPs
4342          *
4343          * in cases where the port is OFFLINE at the time of port
4344          * attach callback and the link comes ONLINE later, for
4345          * easier automatic node creation (i.e. without you having to
4346          * go out and run the utility to perform LOGINs) the
4347          * following conditional is helpful
4348          */
4349         pptr->port_phys_state = port_state;
4350 
4351         if (dev_cnt) {
4352                 mutex_exit(&pptr->port_mutex);
4353 
4354                 map_len = sizeof (*map_tag) * dev_cnt;
4355                 map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4356                 if (map_tag == NULL) {
4357                         fcp_log(CE_WARN, pptr->port_dip,
4358                             "!fcp%d: failed to allocate for map tags; "
4359                             " state change will not be processed",
4360                             pptr->port_instance);
4361 
4362                         mutex_enter(&pptr->port_mutex);
4363                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4364                         mutex_exit(&pptr->port_mutex);
4365 
4366                         return;
4367                 }
4368 
4369                 mutex_enter(&pptr->port_mutex);
4370         }
4371 
4372         if (pptr->port_id != port_sid) {
4373                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4374                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4375                     "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4376                     port_sid);
4377                 /*
4378                  * The local port changed ID. It is the first time a port ID
4379                  * is assigned or something drastic happened.  We might have
4380                  * been unplugged and replugged on another loop or fabric port
4381                  * or somebody grabbed the AL_PA we had or somebody rezoned
4382                  * the fabric we were plugged into.
4383                  */
4384                 pptr->port_id = port_sid;
4385         }
4386 
4387         switch (FC_PORT_STATE_MASK(port_state)) {
4388         case FC_STATE_OFFLINE:
4389         case FC_STATE_RESET_REQUESTED:
4390                 /*
4391                  * link has gone from online to offline -- just update the
4392                  * state of this port to BUSY and MARKed to go offline
4393                  */
4394                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4395                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4396                     "link went offline");
4397                 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4398                         /*
4399                          * We were offline a while ago and this one
4400                          * seems to indicate that the loop has gone
4401                          * dead forever.
4402                          */
4403                         pptr->port_tmp_cnt += dev_cnt;
4404                         pptr->port_state &= ~FCP_STATE_OFFLINE;
4405                         pptr->port_state |= FCP_STATE_INIT;
4406                         link_count = pptr->port_link_cnt;
4407                         fcp_handle_devices(pptr, devlist, dev_cnt,
4408                             link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4409                 } else {
4410                         pptr->port_link_cnt++;
4411                         ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4412                         fcp_update_state(pptr, (FCP_LUN_BUSY |
4413                             FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4414                         if (pptr->port_mpxio) {
4415                                 fcp_update_mpxio_path_verifybusy(pptr);
4416                         }
4417                         pptr->port_state |= FCP_STATE_OFFLINE;
4418                         pptr->port_state &=
4419                             ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4420                         pptr->port_tmp_cnt = 0;
4421                 }
4422                 mutex_exit(&pptr->port_mutex);
4423                 break;
4424 
4425         case FC_STATE_ONLINE:
4426         case FC_STATE_LIP:
4427         case FC_STATE_LIP_LBIT_SET:
4428                 /*
4429                  * link has gone from offline to online
4430                  */
4431                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4432                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4433                     "link went online");
4434 
4435                 pptr->port_link_cnt++;
4436 
4437                 while (pptr->port_ipkt_cnt) {
4438                         mutex_exit(&pptr->port_mutex);
4439                         delay(drv_usectohz(1000000));
4440                         mutex_enter(&pptr->port_mutex);
4441                 }
4442 
4443                 pptr->port_topology = port_top;
4444 
4445                 /*
4446                  * The state of the targets and luns accessible through this
4447                  * port is updated.
4448                  */
4449                 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4450                     FCP_CAUSE_LINK_CHANGE);
4451 
4452                 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4453                 pptr->port_state |= FCP_STATE_ONLINING;
4454                 pptr->port_tmp_cnt = dev_cnt;
4455                 link_count = pptr->port_link_cnt;
4456 
4457                 pptr->port_deadline = fcp_watchdog_time +
4458                     FCP_ICMD_DEADLINE;
4459 
4460                 if (!dev_cnt) {
4461                         /*
4462                          * We go directly to the online state if no remote
4463                          * ports were discovered.
4464                          */
4465                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4466                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4467                             "No remote ports discovered");
4468 
4469                         pptr->port_state &= ~FCP_STATE_ONLINING;
4470                         pptr->port_state |= FCP_STATE_ONLINE;
4471                 }
4472 
4473                 switch (port_top) {
4474                 case FC_TOP_FABRIC:
4475                 case FC_TOP_PUBLIC_LOOP:
4476                 case FC_TOP_PRIVATE_LOOP:
4477                 case FC_TOP_PT_PT:
4478 
4479                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4480                                 fcp_retry_ns_registry(pptr, port_sid);
4481                         }
4482 
4483                         fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4484                             map_tag, FCP_CAUSE_LINK_CHANGE);
4485                         break;
4486 
4487                 default:
4488                         /*
4489                          * We got here because we were provided with an unknown
4490                          * topology.
4491                          */
4492                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4493                                 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4494                         }
4495 
4496                         pptr->port_tmp_cnt -= dev_cnt;
4497                         fcp_log(CE_WARN, pptr->port_dip,
4498                             "!unknown/unsupported topology (0x%x)", port_top);
4499                         break;
4500                 }
4501                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4502                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4503                     "Notify ssd of the reset to reinstate the reservations");
4504 
4505                 scsi_hba_reset_notify_callback(&pptr->port_mutex,
4506                     &pptr->port_reset_notify_listf);
4507 
4508                 mutex_exit(&pptr->port_mutex);
4509 
4510                 break;
4511 
4512         case FC_STATE_RESET:
4513                 ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4514                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4515                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4516                     "RESET state, waiting for Offline/Online state_cb");
4517                 mutex_exit(&pptr->port_mutex);
4518                 break;
4519 
4520         case FC_STATE_DEVICE_CHANGE:
4521                 /*
4522                  * We come here when an application has requested
4523                  * Dynamic node creation/deletion in Fabric connectivity.
4524                  */
4525                 if (pptr->port_state & (FCP_STATE_OFFLINE |
4526                     FCP_STATE_INIT)) {
4527                         /*
4528                          * This case can happen when the FCTL is in the
4529                          * process of giving us on online and the host on
4530                          * the other side issues a PLOGI/PLOGO. Ideally
4531                          * the state changes should be serialized unless
4532                          * they are opposite (online-offline).
4533                          * The transport will give us a final state change
4534                          * so we can ignore this for the time being.
4535                          */
4536                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4537                         mutex_exit(&pptr->port_mutex);
4538                         break;
4539                 }
4540 
4541                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4542                         fcp_retry_ns_registry(pptr, port_sid);
4543                 }
4544 
4545                 /*
4546                  * Extend the deadline under steady state conditions
4547                  * to provide more time for the device-change-commands
4548                  */
4549                 if (!pptr->port_ipkt_cnt) {
4550                         pptr->port_deadline = fcp_watchdog_time +
4551                             FCP_ICMD_DEADLINE;
4552                 }
4553 
4554                 /*
4555                  * There is another race condition here, where if we were
4556                  * in ONLINEING state and a devices in the map logs out,
4557                  * fp will give another state change as DEVICE_CHANGE
4558                  * and OLD. This will result in that target being offlined.
4559                  * The pd_handle is freed. If from the first statec callback
4560                  * we were going to fire a PLOGI/PRLI, the system will
4561                  * panic in fc_ulp_transport with invalid pd_handle.
4562                  * The fix is to check for the link_cnt before issuing
4563                  * any command down.
4564                  */
4565                 fcp_update_targets(pptr, devlist, dev_cnt,
4566                     FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4567 
4568                 link_count = pptr->port_link_cnt;
4569 
4570                 fcp_handle_devices(pptr, devlist, dev_cnt,
4571                     link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4572 
4573                 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4574 
4575                 mutex_exit(&pptr->port_mutex);
4576                 break;
4577 
4578         case FC_STATE_TARGET_PORT_RESET:
4579                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4580                         fcp_retry_ns_registry(pptr, port_sid);
4581                 }
4582 
4583                 /* Do nothing else */
4584                 mutex_exit(&pptr->port_mutex);
4585                 break;
4586 
4587         default:
4588                 fcp_log(CE_WARN, pptr->port_dip,
4589                     "!Invalid state change=0x%x", port_state);
4590                 mutex_exit(&pptr->port_mutex);
4591                 break;
4592         }
4593 
4594         if (map_tag) {
4595                 kmem_free(map_tag, map_len);
4596         }
4597 }
4598 
4599 /*
4600  *     Function: fcp_handle_devices
4601  *
4602  *  Description: This function updates the devices currently known by
4603  *               walking the list provided by the caller.  The list passed
4604  *               by the caller is supposed to be the list of reachable
4605  *               devices.
4606  *
4607  *     Argument: *pptr          Fcp port structure.
4608  *               *devlist       Pointer to the first entry of a table
4609  *                              containing the remote ports that can be
4610  *                              reached.
4611  *               dev_cnt        Number of entries pointed by devlist.
4612  *               link_cnt       Link state count.
4613  *               *map_tag       Array of fcp_map_tag_t structures.
4614  *               cause          What caused this function to be called.
4615  *
4616  * Return Value: None
4617  *
4618  *        Notes: The pptr->port_mutex must be held.
4619  */
4620 static void
4621 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4622     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4623 {
4624         int                     i;
4625         int                     check_finish_init = 0;
4626         fc_portmap_t            *map_entry;
4627         struct fcp_tgt  *ptgt = NULL;
4628 
4629         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4630             fcp_trace, FCP_BUF_LEVEL_3, 0,
4631             "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4632 
4633         if (dev_cnt) {
4634                 ASSERT(map_tag != NULL);
4635         }
4636 
4637         /*
4638          * The following code goes through the list of remote ports that are
4639          * accessible through this (pptr) local port (The list walked is the
4640          * one provided by the caller which is the list of the remote ports
4641          * currently reachable).  It checks if any of them was already
4642          * known by looking for the corresponding target structure based on
4643          * the world wide name.  If a target is part of the list it is tagged
4644          * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4645          *
4646          * Old comment
4647          * -----------
4648          * Before we drop port mutex; we MUST get the tags updated; This
4649          * two step process is somewhat slow, but more reliable.
4650          */
4651         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4652                 map_entry = &(devlist[i]);
4653 
4654                 /*
4655                  * get ptr to this map entry in our port's
4656                  * list (if any)
4657                  */
4658                 ptgt = fcp_lookup_target(pptr,
4659                     (uchar_t *)&(map_entry->map_pwwn));
4660 
4661                 if (ptgt) {
4662                         map_tag[i] = ptgt->tgt_change_cnt;
4663                         if (cause == FCP_CAUSE_LINK_CHANGE) {
4664                                 ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4665                         }
4666                 }
4667         }
4668 
4669         /*
4670          * At this point we know which devices of the new list were already
4671          * known (The field tgt_aux_state of the target structure has been
4672          * set to FCP_TGT_TAGGED).
4673          *
4674          * The following code goes through the list of targets currently known
4675          * by the local port (the list is actually a hashing table).  If a
4676          * target is found and is not tagged, it means the target cannot
4677          * be reached anymore through the local port (pptr).  It is offlined.
4678          * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4679          */
4680         for (i = 0; i < FCP_NUM_HASH; i++) {
4681                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4682                     ptgt = ptgt->tgt_next) {
4683                         mutex_enter(&ptgt->tgt_mutex);
4684                         if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4685                             (cause == FCP_CAUSE_LINK_CHANGE) &&
4686                             !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4687                                 fcp_offline_target_now(pptr, ptgt,
4688                                     link_cnt, ptgt->tgt_change_cnt, 0);
4689                         }
4690                         mutex_exit(&ptgt->tgt_mutex);
4691                 }
4692         }
4693 
4694         /*
4695          * At this point, the devices that were known but cannot be reached
4696          * anymore, have most likely been offlined.
4697          *
4698          * The following section of code seems to go through the list of
4699          * remote ports that can now be reached.  For every single one it
4700          * checks if it is already known or if it is a new port.
4701          */
4702         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4703 
4704                 if (check_finish_init) {
4705                         ASSERT(i > 0);
4706                         (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4707                             map_tag[i - 1], cause);
4708                         check_finish_init = 0;
4709                 }
4710 
4711                 /* get a pointer to this map entry */
4712                 map_entry = &(devlist[i]);
4713 
4714                 /*
4715                  * Check for the duplicate map entry flag. If we have marked
4716                  * this entry as a duplicate we skip it since the correct
4717                  * (perhaps even same) state change will be encountered
4718                  * later in the list.
4719                  */
4720                 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4721                         continue;
4722                 }
4723 
4724                 /* get ptr to this map entry in our port's list (if any) */
4725                 ptgt = fcp_lookup_target(pptr,
4726                     (uchar_t *)&(map_entry->map_pwwn));
4727 
4728                 if (ptgt) {
4729                         /*
4730                          * This device was already known.  The field
4731                          * tgt_aux_state is reset (was probably set to
4732                          * FCP_TGT_TAGGED previously in this routine).
4733                          */
4734                         ptgt->tgt_aux_state = 0;
4735                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4736                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4737                             "handle_devices: map did/state/type/flags = "
4738                             "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4739                             "tgt_state=%d",
4740                             map_entry->map_did.port_id, map_entry->map_state,
4741                             map_entry->map_type, map_entry->map_flags,
4742                             ptgt->tgt_d_id, ptgt->tgt_state);
4743                 }
4744 
4745                 if (map_entry->map_type == PORT_DEVICE_OLD ||
4746                     map_entry->map_type == PORT_DEVICE_NEW ||
4747                     map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4748                     map_entry->map_type == PORT_DEVICE_CHANGED) {
4749                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4750                             fcp_trace, FCP_BUF_LEVEL_2, 0,
4751                             "map_type=%x, did = %x",
4752                             map_entry->map_type,
4753                             map_entry->map_did.port_id);
4754                 }
4755 
4756                 switch (map_entry->map_type) {
4757                 case PORT_DEVICE_NOCHANGE:
4758                 case PORT_DEVICE_USER_CREATE:
4759                 case PORT_DEVICE_USER_LOGIN:
4760                 case PORT_DEVICE_NEW:
4761                 case PORT_DEVICE_REPORTLUN_CHANGED:
4762                         FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4763 
4764                         if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4765                             link_cnt, (ptgt) ? map_tag[i] : 0,
4766                             cause) == TRUE) {
4767 
4768                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4769                                     FCP_TGT_TRACE_2);
4770                                 check_finish_init++;
4771                         }
4772                         break;
4773 
4774                 case PORT_DEVICE_OLD:
4775                         if (ptgt != NULL) {
4776                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4777                                     FCP_TGT_TRACE_3);
4778 
4779                                 mutex_enter(&ptgt->tgt_mutex);
4780                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4781                                         /*
4782                                          * Must do an in-line wait for I/Os
4783                                          * to get drained
4784                                          */
4785                                         mutex_exit(&ptgt->tgt_mutex);
4786                                         mutex_exit(&pptr->port_mutex);
4787 
4788                                         mutex_enter(&ptgt->tgt_mutex);
4789                                         while (ptgt->tgt_ipkt_cnt ||
4790                                             fcp_outstanding_lun_cmds(ptgt)
4791                                             == FC_SUCCESS) {
4792                                                 mutex_exit(&ptgt->tgt_mutex);
4793                                                 delay(drv_usectohz(1000000));
4794                                                 mutex_enter(&ptgt->tgt_mutex);
4795                                         }
4796                                         mutex_exit(&ptgt->tgt_mutex);
4797 
4798                                         mutex_enter(&pptr->port_mutex);
4799                                         mutex_enter(&ptgt->tgt_mutex);
4800 
4801                                         (void) fcp_offline_target(pptr, ptgt,
4802                                             link_cnt, map_tag[i], 0, 0);
4803                                 }
4804                                 mutex_exit(&ptgt->tgt_mutex);
4805                         }
4806                         check_finish_init++;
4807                         break;
4808 
4809                 case PORT_DEVICE_USER_DELETE:
4810                 case PORT_DEVICE_USER_LOGOUT:
4811                         if (ptgt != NULL) {
4812                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4813                                     FCP_TGT_TRACE_4);
4814 
4815                                 mutex_enter(&ptgt->tgt_mutex);
4816                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4817                                         (void) fcp_offline_target(pptr, ptgt,
4818                                             link_cnt, map_tag[i], 1, 0);
4819                                 }
4820                                 mutex_exit(&ptgt->tgt_mutex);
4821                         }
4822                         check_finish_init++;
4823                         break;
4824 
4825                 case PORT_DEVICE_CHANGED:
4826                         if (ptgt != NULL) {
4827                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4828                                     FCP_TGT_TRACE_5);
4829 
4830                                 if (fcp_device_changed(pptr, ptgt,
4831                                     map_entry, link_cnt, map_tag[i],
4832                                     cause) == TRUE) {
4833                                         check_finish_init++;
4834                                 }
4835                         } else {
4836                                 if (fcp_handle_mapflags(pptr, ptgt,
4837                                     map_entry, link_cnt, 0, cause) == TRUE) {
4838                                         check_finish_init++;
4839                                 }
4840                         }
4841                         break;
4842 
4843                 default:
4844                         fcp_log(CE_WARN, pptr->port_dip,
4845                             "!Invalid map_type=0x%x", map_entry->map_type);
4846                         check_finish_init++;
4847                         break;
4848                 }
4849         }
4850 
4851         if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4852                 ASSERT(i > 0);
4853                 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4854                     map_tag[i-1], cause);
4855         } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4856                 fcp_offline_all(pptr, link_cnt, cause);
4857         }
4858 }
4859 
4860 static int
4861 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4862 {
4863         struct fcp_lun  *plun;
4864         struct fcp_port *pptr;
4865         int              rscn_count;
4866         int              lun0_newalloc;
4867         int              ret  = TRUE;
4868 
4869         ASSERT(ptgt);
4870         pptr = ptgt->tgt_port;
4871         lun0_newalloc = 0;
4872         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4873                 /*
4874                  * no LUN struct for LUN 0 yet exists,
4875                  * so create one
4876                  */
4877                 plun = fcp_alloc_lun(ptgt);
4878                 if (plun == NULL) {
4879                         fcp_log(CE_WARN, pptr->port_dip,
4880                             "!Failed to allocate lun 0 for"
4881                             " D_ID=%x", ptgt->tgt_d_id);
4882                         return (ret);
4883                 }
4884                 lun0_newalloc = 1;
4885         }
4886 
4887         mutex_enter(&ptgt->tgt_mutex);
4888         /*
4889          * consider lun 0 as device not connected if it is
4890          * offlined or newly allocated
4891          */
4892         if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4893                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4894         }
4895         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4896         plun->lun_state &= ~FCP_LUN_OFFLINE;
4897         ptgt->tgt_lun_cnt = 1;
4898         ptgt->tgt_report_lun_cnt = 0;
4899         mutex_exit(&ptgt->tgt_mutex);
4900 
4901         rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4902         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4903             sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4904             ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4905                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4906                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4907                     "to D_ID=%x", ptgt->tgt_d_id);
4908         } else {
4909                 ret = FALSE;
4910         }
4911 
4912         return (ret);
4913 }
4914 
4915 /*
4916  *     Function: fcp_handle_mapflags
4917  *
4918  *  Description: This function creates a target structure if the ptgt passed
4919  *               is NULL.  It also kicks off the PLOGI if we are not logged
4920  *               into the target yet or the PRLI if we are logged into the
4921  *               target already.  The rest of the treatment is done in the
4922  *               callbacks of the PLOGI or PRLI.
4923  *
4924  *     Argument: *pptr          FCP Port structure.
4925  *               *ptgt          Target structure.
4926  *               *map_entry     Array of fc_portmap_t structures.
4927  *               link_cnt       Link state count.
4928  *               tgt_cnt        Target state count.
4929  *               cause          What caused this function to be called.
4930  *
4931  * Return Value: TRUE   Failed
4932  *               FALSE  Succeeded
4933  *
4934  *        Notes: pptr->port_mutex must be owned.
4935  */
4936 static int
4937 fcp_handle_mapflags(struct fcp_port     *pptr, struct fcp_tgt   *ptgt,
4938     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4939 {
4940         int                     lcount;
4941         int                     tcount;
4942         int                     ret = TRUE;
4943         int                     alloc;
4944         struct fcp_ipkt *icmd;
4945         struct fcp_lun  *pseq_lun = NULL;
4946         uchar_t                 opcode;
4947         int                     valid_ptgt_was_passed = FALSE;
4948 
4949         ASSERT(mutex_owned(&pptr->port_mutex));
4950 
4951         /*
4952          * This case is possible where the FCTL has come up and done discovery
4953          * before FCP was loaded and attached. FCTL would have discovered the
4954          * devices and later the ULP came online. In this case ULP's would get
4955          * PORT_DEVICE_NOCHANGE but target would be NULL.
4956          */
4957         if (ptgt == NULL) {
4958                 /* don't already have a target */
4959                 mutex_exit(&pptr->port_mutex);
4960                 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4961                 mutex_enter(&pptr->port_mutex);
4962 
4963                 if (ptgt == NULL) {
4964                         fcp_log(CE_WARN, pptr->port_dip,
4965                             "!FC target allocation failed");
4966                         return (ret);
4967                 }
4968                 mutex_enter(&ptgt->tgt_mutex);
4969                 ptgt->tgt_statec_cause = cause;
4970                 ptgt->tgt_tmp_cnt = 1;
4971                 mutex_exit(&ptgt->tgt_mutex);
4972         } else {
4973                 valid_ptgt_was_passed = TRUE;
4974         }
4975 
4976         /*
4977          * Copy in the target parameters
4978          */
4979         mutex_enter(&ptgt->tgt_mutex);
4980         ptgt->tgt_d_id = map_entry->map_did.port_id;
4981         ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4982         ptgt->tgt_pd_handle = map_entry->map_pd;
4983         ptgt->tgt_fca_dev = NULL;
4984 
4985         /* Copy port and node WWNs */
4986         bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4987             FC_WWN_SIZE);
4988         bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4989             FC_WWN_SIZE);
4990 
4991         if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4992             (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4993             (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4994             valid_ptgt_was_passed) {
4995                 /*
4996                  * determine if there are any tape LUNs on this target
4997                  */
4998                 for (pseq_lun = ptgt->tgt_lun;
4999                     pseq_lun != NULL;
5000                     pseq_lun = pseq_lun->lun_next) {
5001                         if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
5002                             !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
5003                                 fcp_update_tgt_state(ptgt, FCP_RESET,
5004                                     FCP_LUN_MARK);
5005                                 mutex_exit(&ptgt->tgt_mutex);
5006                                 return (ret);
5007                         }
5008                 }
5009         }
5010 
5011         /*
5012          * if UA'REPORT_LUN_CHANGED received,
5013          * send out REPORT LUN promptly, skip PLOGI/PRLI process
5014          */
5015         if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5016                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5017                 mutex_exit(&ptgt->tgt_mutex);
5018                 mutex_exit(&pptr->port_mutex);
5019 
5020                 ret = fcp_handle_reportlun_changed(ptgt, cause);
5021 
5022                 mutex_enter(&pptr->port_mutex);
5023                 return (ret);
5024         }
5025 
5026         /*
5027          * If ptgt was NULL when this function was entered, then tgt_node_state
5028          * was never specifically initialized but zeroed out which means
5029          * FCP_TGT_NODE_NONE.
5030          */
5031         switch (ptgt->tgt_node_state) {
5032         case FCP_TGT_NODE_NONE:
5033         case FCP_TGT_NODE_ON_DEMAND:
5034                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5035                     !fcp_enable_auto_configuration &&
5036                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5037                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5038                 } else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5039                     fcp_enable_auto_configuration &&
5040                     (ptgt->tgt_manual_config_only == 1) &&
5041                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5042                         /*
5043                          * If auto configuration is set and
5044                          * the tgt_manual_config_only flag is set then
5045                          * we only want the user to be able to change
5046                          * the state through create_on_demand.
5047                          */
5048                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5049                 } else {
5050                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5051                 }
5052                 break;
5053 
5054         case FCP_TGT_NODE_PRESENT:
5055                 break;
5056         }
5057         /*
5058          * If we are booting from a fabric device, make sure we
5059          * mark the node state appropriately for this target to be
5060          * enumerated
5061          */
5062         if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5063                 if (bcmp((caddr_t)pptr->port_boot_wwn,
5064                     (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5065                     sizeof (ptgt->tgt_port_wwn)) == 0) {
5066                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5067                 }
5068         }
5069         mutex_exit(&ptgt->tgt_mutex);
5070 
5071         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5072             fcp_trace, FCP_BUF_LEVEL_3, 0,
5073             "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5074             map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5075             map_entry->map_rscn_info.ulp_rscn_count);
5076 
5077         mutex_enter(&ptgt->tgt_mutex);
5078 
5079         /*
5080          * Reset target OFFLINE state and mark the target BUSY
5081          */
5082         ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5083         ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5084 
5085         tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5086         lcount = link_cnt;
5087 
5088         mutex_exit(&ptgt->tgt_mutex);
5089         mutex_exit(&pptr->port_mutex);
5090 
5091         /*
5092          * if we are already logged in, then we do a PRLI, else
5093          * we do a PLOGI first (to get logged in)
5094          *
5095          * We will not check if we are the PLOGI initiator
5096          */
5097         opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5098             map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5099 
5100         alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5101 
5102         icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5103             pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5104             cause, map_entry->map_rscn_info.ulp_rscn_count);
5105 
5106         if (icmd == NULL) {
5107                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5108                 /*
5109                  * We've exited port_mutex before calling fcp_icmd_alloc,
5110                  * we need to make sure we reacquire it before returning.
5111                  */
5112                 mutex_enter(&pptr->port_mutex);
5113                 return (FALSE);
5114         }
5115 
5116         /* TRUE is only returned while target is intended skipped */
5117         ret = FALSE;
5118         /* discover info about this target */
5119         if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5120             lcount, tcount, cause)) == DDI_SUCCESS) {
5121                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5122         } else {
5123                 fcp_icmd_free(pptr, icmd);
5124                 ret = TRUE;
5125         }
5126         mutex_enter(&pptr->port_mutex);
5127 
5128         return (ret);
5129 }
5130 
5131 /*
5132  *     Function: fcp_send_els
5133  *
5134  *  Description: Sends an ELS to the target specified by the caller.  Supports
5135  *               PLOGI and PRLI.
5136  *
5137  *     Argument: *pptr          Fcp port.
5138  *               *ptgt          Target to send the ELS to.
5139  *               *icmd          Internal packet
5140  *               opcode         ELS opcode
5141  *               lcount         Link state change counter
5142  *               tcount         Target state change counter
5143  *               cause          What caused the call
5144  *
5145  * Return Value: DDI_SUCCESS
5146  *               Others
5147  */
5148 static int
5149 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5150     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5151 {
5152         fc_packet_t             *fpkt;
5153         fc_frame_hdr_t          *hp;
5154         int                     internal = 0;
5155         int                     alloc;
5156         int                     cmd_len;
5157         int                     resp_len;
5158         int                     res = DDI_FAILURE; /* default result */
5159         int                     rval = DDI_FAILURE;
5160 
5161         ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5162         ASSERT(ptgt->tgt_port == pptr);
5163 
5164         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5165             fcp_trace, FCP_BUF_LEVEL_5, 0,
5166             "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5167             (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5168 
5169         if (opcode == LA_ELS_PLOGI) {
5170                 cmd_len = sizeof (la_els_logi_t);
5171                 resp_len = sizeof (la_els_logi_t);
5172         } else {
5173                 ASSERT(opcode == LA_ELS_PRLI);
5174                 cmd_len = sizeof (la_els_prli_t);
5175                 resp_len = sizeof (la_els_prli_t);
5176         }
5177 
5178         if (icmd == NULL) {
5179                 alloc = FCP_MAX(sizeof (la_els_logi_t),
5180                     sizeof (la_els_prli_t));
5181                 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5182                     pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5183                     lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5184                 if (icmd == NULL) {
5185                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5186                         return (res);
5187                 }
5188                 internal++;
5189         }
5190         fpkt = icmd->ipkt_fpkt;
5191 
5192         fpkt->pkt_cmdlen = cmd_len;
5193         fpkt->pkt_rsplen = resp_len;
5194         fpkt->pkt_datalen = 0;
5195         icmd->ipkt_retries = 0;
5196 
5197         /* fill in fpkt info */
5198         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5199         fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5200         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5201 
5202         /* get ptr to frame hdr in fpkt */
5203         hp = &fpkt->pkt_cmd_fhdr;
5204 
5205         /*
5206          * fill in frame hdr
5207          */
5208         hp->r_ctl = R_CTL_ELS_REQ;
5209         hp->s_id = pptr->port_id; /* source ID */
5210         hp->d_id = ptgt->tgt_d_id;        /* dest ID */
5211         hp->type = FC_TYPE_EXTENDED_LS;
5212         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5213         hp->seq_id = 0;
5214         hp->rsvd = 0;
5215         hp->df_ctl  = 0;
5216         hp->seq_cnt = 0;
5217         hp->ox_id = 0xffff;          /* i.e. none */
5218         hp->rx_id = 0xffff;          /* i.e. none */
5219         hp->ro = 0;
5220 
5221         /*
5222          * at this point we have a filled in cmd pkt
5223          *
5224          * fill in the respective info, then use the transport to send
5225          * the packet
5226          *
5227          * for a PLOGI call fc_ulp_login(), and
5228          * for a PRLI call fc_ulp_issue_els()
5229          */
5230         switch (opcode) {
5231         case LA_ELS_PLOGI: {
5232                 struct la_els_logi logi;
5233 
5234                 bzero(&logi, sizeof (struct la_els_logi));
5235 
5236                 hp = &fpkt->pkt_cmd_fhdr;
5237                 hp->r_ctl = R_CTL_ELS_REQ;
5238                 logi.ls_code.ls_code = LA_ELS_PLOGI;
5239                 logi.ls_code.mbz = 0;
5240 
5241                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5242                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5243 
5244                 icmd->ipkt_opcode = LA_ELS_PLOGI;
5245 
5246                 mutex_enter(&pptr->port_mutex);
5247                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5248 
5249                         mutex_exit(&pptr->port_mutex);
5250 
5251                         rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5252                         if (rval == FC_SUCCESS) {
5253                                 res = DDI_SUCCESS;
5254                                 break;
5255                         }
5256 
5257                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5258 
5259                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5260                             rval, "PLOGI");
5261                 } else {
5262                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5263                             fcp_trace, FCP_BUF_LEVEL_5, 0,
5264                             "fcp_send_els1: state change occured"
5265                             " for D_ID=0x%x", ptgt->tgt_d_id);
5266                         mutex_exit(&pptr->port_mutex);
5267                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5268                 }
5269                 break;
5270         }
5271 
5272         case LA_ELS_PRLI: {
5273                 struct la_els_prli      prli;
5274                 struct fcp_prli         *fprli;
5275 
5276                 bzero(&prli, sizeof (struct la_els_prli));
5277 
5278                 hp = &fpkt->pkt_cmd_fhdr;
5279                 hp->r_ctl = R_CTL_ELS_REQ;
5280 
5281                 /* fill in PRLI cmd ELS fields */
5282                 prli.ls_code = LA_ELS_PRLI;
5283                 prli.page_length = 0x10;        /* huh? */
5284                 prli.payload_length = sizeof (struct la_els_prli);
5285 
5286                 icmd->ipkt_opcode = LA_ELS_PRLI;
5287 
5288                 /* get ptr to PRLI service params */
5289                 fprli = (struct fcp_prli *)prli.service_params;
5290 
5291                 /* fill in service params */
5292                 fprli->type = 0x08;
5293                 fprli->resvd1 = 0;
5294                 fprli->orig_process_assoc_valid = 0;
5295                 fprli->resp_process_assoc_valid = 0;
5296                 fprli->establish_image_pair = 1;
5297                 fprli->resvd2 = 0;
5298                 fprli->resvd3 = 0;
5299                 fprli->obsolete_1 = 0;
5300                 fprli->obsolete_2 = 0;
5301                 fprli->data_overlay_allowed = 0;
5302                 fprli->initiator_fn = 1;
5303                 fprli->confirmed_compl_allowed = 1;
5304 
5305                 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5306                         fprli->target_fn = 1;
5307                 } else {
5308                         fprli->target_fn = 0;
5309                 }
5310 
5311                 fprli->retry = 1;
5312                 fprli->read_xfer_rdy_disabled = 1;
5313                 fprli->write_xfer_rdy_disabled = 0;
5314 
5315                 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5316                     fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5317 
5318                 /* issue the PRLI request */
5319 
5320                 mutex_enter(&pptr->port_mutex);
5321                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5322 
5323                         mutex_exit(&pptr->port_mutex);
5324 
5325                         rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5326                         if (rval == FC_SUCCESS) {
5327                                 res = DDI_SUCCESS;
5328                                 break;
5329                         }
5330 
5331                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5332 
5333                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5334                             rval, "PRLI");
5335                 } else {
5336                         mutex_exit(&pptr->port_mutex);
5337                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5338                 }
5339                 break;
5340         }
5341 
5342         default:
5343                 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5344                 break;
5345         }
5346 
5347         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5348             fcp_trace, FCP_BUF_LEVEL_5, 0,
5349             "fcp_send_els: returning %d", res);
5350 
5351         if (res != DDI_SUCCESS) {
5352                 if (internal) {
5353                         fcp_icmd_free(pptr, icmd);
5354                 }
5355         }
5356 
5357         return (res);
5358 }
5359 
5360 
5361 /*
5362  * called internally update the state of all of the tgts and each LUN
5363  * for this port (i.e. each target  known to be attached to this port)
5364  * if they are not already offline
5365  *
5366  * must be called with the port mutex owned
5367  *
5368  * acquires and releases the target mutexes for each target attached
5369  * to this port
5370  */
5371 void
5372 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5373 {
5374         int i;
5375         struct fcp_tgt *ptgt;
5376 
5377         ASSERT(mutex_owned(&pptr->port_mutex));
5378 
5379         for (i = 0; i < FCP_NUM_HASH; i++) {
5380                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5381                     ptgt = ptgt->tgt_next) {
5382                         mutex_enter(&ptgt->tgt_mutex);
5383                         fcp_update_tgt_state(ptgt, FCP_SET, state);
5384                         ptgt->tgt_change_cnt++;
5385                         ptgt->tgt_statec_cause = cause;
5386                         ptgt->tgt_tmp_cnt = 1;
5387                         ptgt->tgt_done = 0;
5388                         mutex_exit(&ptgt->tgt_mutex);
5389                 }
5390         }
5391 }
5392 
5393 
5394 static void
5395 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5396 {
5397         int i;
5398         int ndevs;
5399         struct fcp_tgt *ptgt;
5400 
5401         ASSERT(mutex_owned(&pptr->port_mutex));
5402 
5403         for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5404                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5405                     ptgt = ptgt->tgt_next) {
5406                         ndevs++;
5407                 }
5408         }
5409 
5410         if (ndevs == 0) {
5411                 return;
5412         }
5413         pptr->port_tmp_cnt = ndevs;
5414 
5415         for (i = 0; i < FCP_NUM_HASH; i++) {
5416                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5417                     ptgt = ptgt->tgt_next) {
5418                         (void) fcp_call_finish_init_held(pptr, ptgt,
5419                             lcount, ptgt->tgt_change_cnt, cause);
5420                 }
5421         }
5422 }
5423 
5424 /*
5425  *     Function: fcp_update_tgt_state
5426  *
5427  *  Description: This function updates the field tgt_state of a target.  That
5428  *               field is a bitmap and which bit can be set or reset
5429  *               individually.  The action applied to the target state is also
5430  *               applied to all the LUNs belonging to the target (provided the
5431  *               LUN is not offline).  A side effect of applying the state
5432  *               modification to the target and the LUNs is the field tgt_trace
5433  *               of the target and lun_trace of the LUNs is set to zero.
5434  *
5435  *
5436  *     Argument: *ptgt  Target structure.
5437  *               flag   Flag indication what action to apply (set/reset).
5438  *               state  State bits to update.
5439  *
5440  * Return Value: None
5441  *
5442  *      Context: Interrupt, Kernel or User context.
5443  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5444  *               calling this function.
5445  */
5446 void
5447 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5448 {
5449         struct fcp_lun *plun;
5450 
5451         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5452 
5453         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5454                 /* The target is not offline. */
5455                 if (flag == FCP_SET) {
5456                         ptgt->tgt_state |= state;
5457                         ptgt->tgt_trace = 0;
5458                 } else {
5459                         ptgt->tgt_state &= ~state;
5460                 }
5461 
5462                 for (plun = ptgt->tgt_lun; plun != NULL;
5463                     plun = plun->lun_next) {
5464                         if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5465                                 /* The LUN is not offline. */
5466                                 if (flag == FCP_SET) {
5467                                         plun->lun_state |= state;
5468                                         plun->lun_trace = 0;
5469                                 } else {
5470                                         plun->lun_state &= ~state;
5471                                 }
5472                         }
5473                 }
5474         }
5475 }
5476 
5477 /*
5478  *     Function: fcp_update_tgt_state
5479  *
5480  *  Description: This function updates the field lun_state of a LUN.  That
5481  *               field is a bitmap and which bit can be set or reset
5482  *               individually.
5483  *
5484  *     Argument: *plun  LUN structure.
5485  *               flag   Flag indication what action to apply (set/reset).
5486  *               state  State bits to update.
5487  *
5488  * Return Value: None
5489  *
5490  *      Context: Interrupt, Kernel or User context.
5491  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5492  *               calling this function.
5493  */
5494 void
5495 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5496 {
5497         struct fcp_tgt  *ptgt = plun->lun_tgt;
5498 
5499         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5500 
5501         if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5502                 if (flag == FCP_SET) {
5503                         plun->lun_state |= state;
5504                 } else {
5505                         plun->lun_state &= ~state;
5506                 }
5507         }
5508 }
5509 
5510 /*
5511  *     Function: fcp_get_port
5512  *
5513  *  Description: This function returns the fcp_port structure from the opaque
5514  *               handle passed by the caller.  That opaque handle is the handle
5515  *               used by fp/fctl to identify a particular local port.  That
5516  *               handle has been stored in the corresponding fcp_port
5517  *               structure.  This function is going to walk the global list of
5518  *               fcp_port structures till one has a port_fp_handle that matches
5519  *               the handle passed by the caller.  This function enters the
5520  *               mutex fcp_global_mutex while walking the global list and then
5521  *               releases it.
5522  *
5523  *     Argument: port_handle    Opaque handle that fp/fctl uses to identify a
5524  *                              particular port.
5525  *
5526  * Return Value: NULL           Not found.
5527  *               Not NULL       Pointer to the fcp_port structure.
5528  *
5529  *      Context: Interrupt, Kernel or User context.
5530  */
5531 static struct fcp_port *
5532 fcp_get_port(opaque_t port_handle)
5533 {
5534         struct fcp_port *pptr;
5535 
5536         ASSERT(port_handle != NULL);
5537 
5538         mutex_enter(&fcp_global_mutex);
5539         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5540                 if (pptr->port_fp_handle == port_handle) {
5541                         break;
5542                 }
5543         }
5544         mutex_exit(&fcp_global_mutex);
5545 
5546         return (pptr);
5547 }
5548 
5549 
5550 static void
5551 fcp_unsol_callback(fc_packet_t *fpkt)
5552 {
5553         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5554         struct fcp_port *pptr = icmd->ipkt_port;
5555 
5556         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5557                 caddr_t state, reason, action, expln;
5558 
5559                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
5560                     &action, &expln);
5561 
5562                 fcp_log(CE_WARN, pptr->port_dip,
5563                     "!couldn't post response to unsolicited request: "
5564                     " state=%s reason=%s rx_id=%x ox_id=%x",
5565                     state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5566                     fpkt->pkt_cmd_fhdr.rx_id);
5567         }
5568         fcp_icmd_free(pptr, icmd);
5569 }
5570 
5571 
5572 /*
5573  * Perform general purpose preparation of a response to an unsolicited request
5574  */
5575 static void
5576 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5577     uchar_t r_ctl, uchar_t type)
5578 {
5579         pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5580         pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5581         pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5582         pkt->pkt_cmd_fhdr.type = type;
5583         pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5584         pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5585         pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5586         pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5587         pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5588         pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5589         pkt->pkt_cmd_fhdr.ro = 0;
5590         pkt->pkt_cmd_fhdr.rsvd = 0;
5591         pkt->pkt_comp = fcp_unsol_callback;
5592         pkt->pkt_pd = NULL;
5593         pkt->pkt_ub_resp_token = (opaque_t)buf;
5594 }
5595 
5596 
5597 /*ARGSUSED*/
5598 static int
5599 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5600 {
5601         fc_packet_t             *fpkt;
5602         struct la_els_prli      prli;
5603         struct fcp_prli         *fprli;
5604         struct fcp_ipkt *icmd;
5605         struct la_els_prli      *from;
5606         struct fcp_prli         *orig;
5607         struct fcp_tgt  *ptgt;
5608         int                     tcount = 0;
5609         int                     lcount;
5610 
5611         from = (struct la_els_prli *)buf->ub_buffer;
5612         orig = (struct fcp_prli *)from->service_params;
5613         if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5614             NULL) {
5615                 mutex_enter(&ptgt->tgt_mutex);
5616                 tcount = ptgt->tgt_change_cnt;
5617                 mutex_exit(&ptgt->tgt_mutex);
5618         }
5619 
5620         mutex_enter(&pptr->port_mutex);
5621         lcount = pptr->port_link_cnt;
5622         mutex_exit(&pptr->port_mutex);
5623 
5624         if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5625             sizeof (la_els_prli_t), 0,
5626             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5627             lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5628                 return (FC_FAILURE);
5629         }
5630 
5631         fpkt = icmd->ipkt_fpkt;
5632         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5633         fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5634         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5635         fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5636         fpkt->pkt_rsplen = 0;
5637         fpkt->pkt_datalen = 0;
5638 
5639         icmd->ipkt_opcode = LA_ELS_PRLI;
5640 
5641         bzero(&prli, sizeof (struct la_els_prli));
5642         fprli = (struct fcp_prli *)prli.service_params;
5643         prli.ls_code = LA_ELS_ACC;
5644         prli.page_length = 0x10;
5645         prli.payload_length = sizeof (struct la_els_prli);
5646 
5647         /* fill in service params */
5648         fprli->type = 0x08;
5649         fprli->resvd1 = 0;
5650         fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5651         fprli->orig_process_associator = orig->orig_process_associator;
5652         fprli->resp_process_assoc_valid = 0;
5653         fprli->establish_image_pair = 1;
5654         fprli->resvd2 = 0;
5655         fprli->resvd3 = 0;
5656         fprli->obsolete_1 = 0;
5657         fprli->obsolete_2 = 0;
5658         fprli->data_overlay_allowed = 0;
5659         fprli->initiator_fn = 1;
5660         fprli->confirmed_compl_allowed = 1;
5661 
5662         if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5663                 fprli->target_fn = 1;
5664         } else {
5665                 fprli->target_fn = 0;
5666         }
5667 
5668         fprli->retry = 1;
5669         fprli->read_xfer_rdy_disabled = 1;
5670         fprli->write_xfer_rdy_disabled = 0;
5671 
5672         /* save the unsol prli payload first */
5673         FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5674             fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5675 
5676         FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5677             fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5678 
5679         fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5680 
5681         mutex_enter(&pptr->port_mutex);
5682         if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5683                 int rval;
5684                 mutex_exit(&pptr->port_mutex);
5685 
5686                 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5687                     FC_SUCCESS) {
5688                         if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5689                             ptgt != NULL) {
5690                                 fcp_queue_ipkt(pptr, fpkt);
5691                                 return (FC_SUCCESS);
5692                         }
5693                         /* Let it timeout */
5694                         fcp_icmd_free(pptr, icmd);
5695                         return (FC_FAILURE);
5696                 }
5697         } else {
5698                 mutex_exit(&pptr->port_mutex);
5699                 fcp_icmd_free(pptr, icmd);
5700                 return (FC_FAILURE);
5701         }
5702 
5703         (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5704 
5705         return (FC_SUCCESS);
5706 }
5707 
5708 /*
5709  *     Function: fcp_icmd_alloc
5710  *
5711  *  Description: This function allocated a fcp_ipkt structure.  The pkt_comp
5712  *               field is initialized to fcp_icmd_callback.  Sometimes it is
5713  *               modified by the caller (such as fcp_send_scsi).  The
5714  *               structure is also tied to the state of the line and of the
5715  *               target at a particular time.  That link is established by
5716  *               setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5717  *               and tcount which came respectively from pptr->link_cnt and
5718  *               ptgt->tgt_change_cnt.
5719  *
5720  *     Argument: *pptr          Fcp port.
5721  *               *ptgt          Target (destination of the command).
5722  *               cmd_len        Length of the command.
5723  *               resp_len       Length of the expected response.
5724  *               data_len       Length of the data.
5725  *               nodma          Indicates weither the command and response.
5726  *                              will be transfer through DMA or not.
5727  *               lcount         Link state change counter.
5728  *               tcount         Target state change counter.
5729  *               cause          Reason that lead to this call.
5730  *
5731  * Return Value: NULL           Failed.
5732  *               Not NULL       Internal packet address.
5733  */
5734 static struct fcp_ipkt *
5735 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5736     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5737     uint32_t rscn_count)
5738 {
5739         int                     dma_setup = 0;
5740         fc_packet_t             *fpkt;
5741         struct fcp_ipkt *icmd = NULL;
5742 
5743         icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5744             pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5745             KM_NOSLEEP);
5746         if (icmd == NULL) {
5747                 fcp_log(CE_WARN, pptr->port_dip,
5748                     "!internal packet allocation failed");
5749                 return (NULL);
5750         }
5751 
5752         /*
5753          * initialize the allocated packet
5754          */
5755         icmd->ipkt_nodma = nodma;
5756         icmd->ipkt_next = icmd->ipkt_prev = NULL;
5757         icmd->ipkt_lun = NULL;
5758 
5759         icmd->ipkt_link_cnt = lcount;
5760         icmd->ipkt_change_cnt = tcount;
5761         icmd->ipkt_cause = cause;
5762 
5763         mutex_enter(&pptr->port_mutex);
5764         icmd->ipkt_port = pptr;
5765         mutex_exit(&pptr->port_mutex);
5766 
5767         /* keep track of amt of data to be sent in pkt */
5768         icmd->ipkt_cmdlen = cmd_len;
5769         icmd->ipkt_resplen = resp_len;
5770         icmd->ipkt_datalen = data_len;
5771 
5772         /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5773         icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5774 
5775         /* set pkt's private ptr to point to cmd pkt */
5776         icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5777 
5778         /* set FCA private ptr to memory just beyond */
5779         icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5780             ((char *)icmd + sizeof (struct fcp_ipkt) +
5781             pptr->port_dmacookie_sz);
5782 
5783         /* get ptr to fpkt substruct and fill it in */
5784         fpkt = icmd->ipkt_fpkt;
5785         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5786             sizeof (struct fcp_ipkt));
5787 
5788         if (ptgt != NULL) {
5789                 icmd->ipkt_tgt = ptgt;
5790                 fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5791         }
5792 
5793         fpkt->pkt_comp = fcp_icmd_callback;
5794         fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5795         fpkt->pkt_cmdlen = cmd_len;
5796         fpkt->pkt_rsplen = resp_len;
5797         fpkt->pkt_datalen = data_len;
5798 
5799         /*
5800          * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5801          * rscn_count as fcp knows down to the transport. If a valid count was
5802          * passed into this function, we allocate memory to actually pass down
5803          * this info.
5804          *
5805          * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5806          * basically mean that fcp will not be able to help transport
5807          * distinguish if a new RSCN has come after fcp was last informed about
5808          * it. In such cases, it might lead to the problem mentioned in CR/bug #
5809          * 5068068 where the device might end up going offline in case of RSCN
5810          * storms.
5811          */
5812         fpkt->pkt_ulp_rscn_infop = NULL;
5813         if (rscn_count != FC_INVALID_RSCN_COUNT) {
5814                 fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5815                     sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5816                 if (fpkt->pkt_ulp_rscn_infop == NULL) {
5817                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5818                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5819                             "Failed to alloc memory to pass rscn info");
5820                 }
5821         }
5822 
5823         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5824                 fc_ulp_rscn_info_t      *rscnp;
5825 
5826                 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5827                 rscnp->ulp_rscn_count = rscn_count;
5828         }
5829 
5830         if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5831                 goto fail;
5832         }
5833         dma_setup++;
5834 
5835         /*
5836          * Must hold target mutex across setting of pkt_pd and call to
5837          * fc_ulp_init_packet to ensure the handle to the target doesn't go
5838          * away while we're not looking.
5839          */
5840         if (ptgt != NULL) {
5841                 mutex_enter(&ptgt->tgt_mutex);
5842                 fpkt->pkt_pd = ptgt->tgt_pd_handle;
5843 
5844                 /* ask transport to do its initialization on this pkt */
5845                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5846                     != FC_SUCCESS) {
5847                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5848                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5849                             "fc_ulp_init_packet failed");
5850                         mutex_exit(&ptgt->tgt_mutex);
5851                         goto fail;
5852                 }
5853                 mutex_exit(&ptgt->tgt_mutex);
5854         } else {
5855                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5856                     != FC_SUCCESS) {
5857                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5858                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5859                             "fc_ulp_init_packet failed");
5860                         goto fail;
5861                 }
5862         }
5863 
5864         mutex_enter(&pptr->port_mutex);
5865         if (pptr->port_state & (FCP_STATE_DETACHING |
5866             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5867                 int rval;
5868 
5869                 mutex_exit(&pptr->port_mutex);
5870 
5871                 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5872                 ASSERT(rval == FC_SUCCESS);
5873 
5874                 goto fail;
5875         }
5876 
5877         if (ptgt != NULL) {
5878                 mutex_enter(&ptgt->tgt_mutex);
5879                 ptgt->tgt_ipkt_cnt++;
5880                 mutex_exit(&ptgt->tgt_mutex);
5881         }
5882 
5883         pptr->port_ipkt_cnt++;
5884 
5885         mutex_exit(&pptr->port_mutex);
5886 
5887         return (icmd);
5888 
5889 fail:
5890         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5891                 kmem_free(fpkt->pkt_ulp_rscn_infop,
5892                     sizeof (fc_ulp_rscn_info_t));
5893                 fpkt->pkt_ulp_rscn_infop = NULL;
5894         }
5895 
5896         if (dma_setup) {
5897                 fcp_free_dma(pptr, icmd);
5898         }
5899         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5900             (size_t)pptr->port_dmacookie_sz);
5901 
5902         return (NULL);
5903 }
5904 
5905 /*
5906  *     Function: fcp_icmd_free
5907  *
5908  *  Description: Frees the internal command passed by the caller.
5909  *
5910  *     Argument: *pptr          Fcp port.
5911  *               *icmd          Internal packet to free.
5912  *
5913  * Return Value: None
5914  */
5915 static void
5916 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5917 {
5918         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
5919 
5920         /* Let the underlying layers do their cleanup. */
5921         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5922             icmd->ipkt_fpkt);
5923 
5924         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5925                 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5926                     sizeof (fc_ulp_rscn_info_t));
5927         }
5928 
5929         fcp_free_dma(pptr, icmd);
5930 
5931         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5932             (size_t)pptr->port_dmacookie_sz);
5933 
5934         mutex_enter(&pptr->port_mutex);
5935 
5936         if (ptgt) {
5937                 mutex_enter(&ptgt->tgt_mutex);
5938                 ptgt->tgt_ipkt_cnt--;
5939                 mutex_exit(&ptgt->tgt_mutex);
5940         }
5941 
5942         pptr->port_ipkt_cnt--;
5943         mutex_exit(&pptr->port_mutex);
5944 }
5945 
5946 /*
5947  *     Function: fcp_alloc_dma
5948  *
5949  *  Description: Allocated the DMA resources required for the internal
5950  *               packet.
5951  *
5952  *     Argument: *pptr  FCP port.
5953  *               *icmd  Internal FCP packet.
5954  *               nodma  Indicates if the Cmd and Resp will be DMAed.
5955  *               flags  Allocation flags (Sleep or NoSleep).
5956  *
5957  * Return Value: FC_SUCCESS
5958  *               FC_NOMEM
5959  */
5960 static int
5961 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5962     int nodma, int flags)
5963 {
5964         int             rval;
5965         size_t          real_size;
5966         uint_t          ccount;
5967         int             bound = 0;
5968         int             cmd_resp = 0;
5969         fc_packet_t     *fpkt;
5970         ddi_dma_cookie_t        pkt_data_cookie;
5971         ddi_dma_cookie_t        *cp;
5972         uint32_t                cnt;
5973 
5974         fpkt = &icmd->ipkt_fc_packet;
5975 
5976         ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5977             fpkt->pkt_resp_dma == NULL);
5978 
5979         icmd->ipkt_nodma = nodma;
5980 
5981         if (nodma) {
5982                 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5983                 if (fpkt->pkt_cmd == NULL) {
5984                         goto fail;
5985                 }
5986 
5987                 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5988                 if (fpkt->pkt_resp == NULL) {
5989                         goto fail;
5990                 }
5991         } else {
5992                 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5993 
5994                 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5995                 if (rval == FC_FAILURE) {
5996                         ASSERT(fpkt->pkt_cmd_dma == NULL &&
5997                             fpkt->pkt_resp_dma == NULL);
5998                         goto fail;
5999                 }
6000                 cmd_resp++;
6001         }
6002 
6003         if ((fpkt->pkt_datalen != 0) &&
6004             !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
6005                 /*
6006                  * set up DMA handle and memory for the data in this packet
6007                  */
6008                 if (ddi_dma_alloc_handle(pptr->port_dip,
6009                     &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6010                     NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6011                         goto fail;
6012                 }
6013 
6014                 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6015                     &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6016                     DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6017                     &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6018                         goto fail;
6019                 }
6020 
6021                 /* was DMA mem size gotten < size asked for/needed ?? */
6022                 if (real_size < fpkt->pkt_datalen) {
6023                         goto fail;
6024                 }
6025 
6026                 /* bind DMA address and handle together */
6027                 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6028                     NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6029                     DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6030                     &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6031                         goto fail;
6032                 }
6033                 bound++;
6034 
6035                 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6036                         goto fail;
6037                 }
6038 
6039                 fpkt->pkt_data_cookie_cnt = ccount;
6040 
6041                 cp = fpkt->pkt_data_cookie;
6042                 *cp = pkt_data_cookie;
6043                 cp++;
6044 
6045                 for (cnt = 1; cnt < ccount; cnt++, cp++) {
6046                         ddi_dma_nextcookie(fpkt->pkt_data_dma,
6047                             &pkt_data_cookie);
6048                         *cp = pkt_data_cookie;
6049                 }
6050 
6051         } else if (fpkt->pkt_datalen != 0) {
6052                 /*
6053                  * If it's a pseudo FCA, then it can't support DMA even in
6054                  * SCSI data phase.
6055                  */
6056                 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6057                 if (fpkt->pkt_data == NULL) {
6058                         goto fail;
6059                 }
6060 
6061         }
6062 
6063         return (FC_SUCCESS);
6064 
6065 fail:
6066         if (bound) {
6067                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6068         }
6069 
6070         if (fpkt->pkt_data_dma) {
6071                 if (fpkt->pkt_data) {
6072                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6073                 }
6074                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6075         } else {
6076                 if (fpkt->pkt_data) {
6077                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6078                 }
6079         }
6080 
6081         if (nodma) {
6082                 if (fpkt->pkt_cmd) {
6083                         kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6084                 }
6085                 if (fpkt->pkt_resp) {
6086                         kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6087                 }
6088         } else {
6089                 if (cmd_resp) {
6090                         fcp_free_cmd_resp(pptr, fpkt);
6091                 }
6092         }
6093 
6094         return (FC_NOMEM);
6095 }
6096 
6097 
6098 static void
6099 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6100 {
6101         fc_packet_t *fpkt = icmd->ipkt_fpkt;
6102 
6103         if (fpkt->pkt_data_dma) {
6104                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6105                 if (fpkt->pkt_data) {
6106                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6107                 }
6108                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6109         } else {
6110                 if (fpkt->pkt_data) {
6111                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6112                 }
6113                 /*
6114                  * Need we reset pkt_* to zero???
6115                  */
6116         }
6117 
6118         if (icmd->ipkt_nodma) {
6119                 if (fpkt->pkt_cmd) {
6120                         kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6121                 }
6122                 if (fpkt->pkt_resp) {
6123                         kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6124                 }
6125         } else {
6126                 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6127 
6128                 fcp_free_cmd_resp(pptr, fpkt);
6129         }
6130 }
6131 
6132 /*
6133  *     Function: fcp_lookup_target
6134  *
6135  *  Description: Finds a target given a WWN.
6136  *
6137  *     Argument: *pptr  FCP port.
6138  *               *wwn   World Wide Name of the device to look for.
6139  *
6140  * Return Value: NULL           No target found
6141  *               Not NULL       Target structure
6142  *
6143  *      Context: Interrupt context.
6144  *               The mutex pptr->port_mutex must be owned.
6145  */
6146 /* ARGSUSED */
6147 static struct fcp_tgt *
6148 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6149 {
6150         int                     hash;
6151         struct fcp_tgt  *ptgt;
6152 
6153         ASSERT(mutex_owned(&pptr->port_mutex));
6154 
6155         hash = FCP_HASH(wwn);
6156 
6157         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6158             ptgt = ptgt->tgt_next) {
6159                 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6160                     bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6161                     sizeof (ptgt->tgt_port_wwn)) == 0) {
6162                         break;
6163                 }
6164         }
6165 
6166         return (ptgt);
6167 }
6168 
6169 
6170 /*
6171  * Find target structure given a port identifier
6172  */
6173 static struct fcp_tgt *
6174 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6175 {
6176         fc_portid_t             port_id;
6177         la_wwn_t                pwwn;
6178         struct fcp_tgt  *ptgt = NULL;
6179 
6180         port_id.priv_lilp_posit = 0;
6181         port_id.port_id = d_id;
6182         if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6183             &pwwn) == FC_SUCCESS) {
6184                 mutex_enter(&pptr->port_mutex);
6185                 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6186                 mutex_exit(&pptr->port_mutex);
6187         }
6188 
6189         return (ptgt);
6190 }
6191 
6192 
6193 /*
6194  * the packet completion callback routine for info cmd pkts
6195  *
6196  * this means fpkt pts to a response to either a PLOGI or a PRLI
6197  *
6198  * if there is an error an attempt is made to call a routine to resend
6199  * the command that failed
6200  */
6201 static void
6202 fcp_icmd_callback(fc_packet_t *fpkt)
6203 {
6204         struct fcp_ipkt *icmd;
6205         struct fcp_port *pptr;
6206         struct fcp_tgt  *ptgt;
6207         struct la_els_prli      *prli;
6208         struct la_els_prli      prli_s;
6209         struct fcp_prli         *fprli;
6210         struct fcp_lun  *plun;
6211         int             free_pkt = 1;
6212         int             rval;
6213         ls_code_t       resp;
6214         uchar_t         prli_acc = 0;
6215         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
6216         int             lun0_newalloc;
6217 
6218         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6219 
6220         /* get ptrs to the port and target structs for the cmd */
6221         pptr = icmd->ipkt_port;
6222         ptgt = icmd->ipkt_tgt;
6223 
6224         FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6225 
6226         if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6227                 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6228                     sizeof (prli_s));
6229                 prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6230         }
6231 
6232         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6233             fcp_trace, FCP_BUF_LEVEL_2, 0,
6234             "ELS (%x) callback state=0x%x reason=0x%x for %x",
6235             icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6236             ptgt->tgt_d_id);
6237 
6238         if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6239             ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6240 
6241                 mutex_enter(&ptgt->tgt_mutex);
6242                 if (ptgt->tgt_pd_handle == NULL) {
6243                         /*
6244                          * in a fabric environment the port device handles
6245                          * get created only after successful LOGIN into the
6246                          * transport, so the transport makes this port
6247                          * device (pd) handle available in this packet, so
6248                          * save it now
6249                          */
6250                         ASSERT(fpkt->pkt_pd != NULL);
6251                         ptgt->tgt_pd_handle = fpkt->pkt_pd;
6252                 }
6253                 mutex_exit(&ptgt->tgt_mutex);
6254 
6255                 /* which ELS cmd is this response for ?? */
6256                 switch (icmd->ipkt_opcode) {
6257                 case LA_ELS_PLOGI:
6258                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6259                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6260                             "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6261                             ptgt->tgt_d_id,
6262                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6263                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6264 
6265                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6266                             FCP_TGT_TRACE_15);
6267 
6268                         /* Note that we are not allocating a new icmd */
6269                         if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6270                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6271                             icmd->ipkt_cause) != DDI_SUCCESS) {
6272                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6273                                     FCP_TGT_TRACE_16);
6274                                 goto fail;
6275                         }
6276                         break;
6277 
6278                 case LA_ELS_PRLI:
6279                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6280                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6281                             "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6282 
6283                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6284                             FCP_TGT_TRACE_17);
6285 
6286                         prli = &prli_s;
6287 
6288                         FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6289                             sizeof (prli_s));
6290 
6291                         fprli = (struct fcp_prli *)prli->service_params;
6292 
6293                         mutex_enter(&ptgt->tgt_mutex);
6294                         ptgt->tgt_icap = fprli->initiator_fn;
6295                         ptgt->tgt_tcap = fprli->target_fn;
6296                         mutex_exit(&ptgt->tgt_mutex);
6297 
6298                         if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6299                                 /*
6300                                  * this FCP device does not support target mode
6301                                  */
6302                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6303                                     FCP_TGT_TRACE_18);
6304                                 goto fail;
6305                         }
6306                         if (fprli->retry == 1) {
6307                                 fc_ulp_disable_relogin(pptr->port_fp_handle,
6308                                     &ptgt->tgt_port_wwn);
6309                         }
6310 
6311                         /* target is no longer offline */
6312                         mutex_enter(&pptr->port_mutex);
6313                         mutex_enter(&ptgt->tgt_mutex);
6314                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6315                                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6316                                     FCP_TGT_MARK);
6317                         } else {
6318                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6319                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6320                                     "fcp_icmd_callback,1: state change "
6321                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6322                                 mutex_exit(&ptgt->tgt_mutex);
6323                                 mutex_exit(&pptr->port_mutex);
6324                                 goto fail;
6325                         }
6326                         mutex_exit(&ptgt->tgt_mutex);
6327                         mutex_exit(&pptr->port_mutex);
6328 
6329                         /*
6330                          * lun 0 should always respond to inquiry, so
6331                          * get the LUN struct for LUN 0
6332                          *
6333                          * Currently we deal with first level of addressing.
6334                          * If / when we start supporting 0x device types
6335                          * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6336                          * this logic will need revisiting.
6337                          */
6338                         lun0_newalloc = 0;
6339                         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6340                                 /*
6341                                  * no LUN struct for LUN 0 yet exists,
6342                                  * so create one
6343                                  */
6344                                 plun = fcp_alloc_lun(ptgt);
6345                                 if (plun == NULL) {
6346                                         fcp_log(CE_WARN, pptr->port_dip,
6347                                             "!Failed to allocate lun 0 for"
6348                                             " D_ID=%x", ptgt->tgt_d_id);
6349                                         goto fail;
6350                                 }
6351                                 lun0_newalloc = 1;
6352                         }
6353 
6354                         /* fill in LUN info */
6355                         mutex_enter(&ptgt->tgt_mutex);
6356                         /*
6357                          * consider lun 0 as device not connected if it is
6358                          * offlined or newly allocated
6359                          */
6360                         if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6361                             lun0_newalloc) {
6362                                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6363                         }
6364                         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6365                         plun->lun_state &= ~FCP_LUN_OFFLINE;
6366                         ptgt->tgt_lun_cnt = 1;
6367                         ptgt->tgt_report_lun_cnt = 0;
6368                         mutex_exit(&ptgt->tgt_mutex);
6369 
6370                         /* Retrieve the rscn count (if a valid one exists) */
6371                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6372                                 rscn_count = ((fc_ulp_rscn_info_t *)
6373                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6374                                     ->ulp_rscn_count;
6375                         } else {
6376                                 rscn_count = FC_INVALID_RSCN_COUNT;
6377                         }
6378 
6379                         /* send Report Lun request to target */
6380                         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6381                             sizeof (struct fcp_reportlun_resp),
6382                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6383                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6384                                 mutex_enter(&pptr->port_mutex);
6385                                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6386                                         fcp_log(CE_WARN, pptr->port_dip,
6387                                             "!Failed to send REPORT LUN to"
6388                                             "  D_ID=%x", ptgt->tgt_d_id);
6389                                 } else {
6390                                         FCP_TRACE(fcp_logq,
6391                                             pptr->port_instbuf, fcp_trace,
6392                                             FCP_BUF_LEVEL_5, 0,
6393                                             "fcp_icmd_callback,2:state change"
6394                                             " occured for D_ID=0x%x",
6395                                             ptgt->tgt_d_id);
6396                                 }
6397                                 mutex_exit(&pptr->port_mutex);
6398 
6399                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6400                                     FCP_TGT_TRACE_19);
6401 
6402                                 goto fail;
6403                         } else {
6404                                 free_pkt = 0;
6405                                 fcp_icmd_free(pptr, icmd);
6406                         }
6407                         break;
6408 
6409                 default:
6410                         fcp_log(CE_WARN, pptr->port_dip,
6411                             "!fcp_icmd_callback Invalid opcode");
6412                         goto fail;
6413                 }
6414 
6415                 return;
6416         }
6417 
6418 
6419         /*
6420          * Other PLOGI failures are not retried as the
6421          * transport does it already
6422          */
6423         if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6424                 if (fcp_is_retryable(icmd) &&
6425                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6426 
6427                         if (FCP_MUST_RETRY(fpkt)) {
6428                                 fcp_queue_ipkt(pptr, fpkt);
6429                                 return;
6430                         }
6431 
6432                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6433                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6434                             "ELS PRLI is retried for d_id=0x%x, state=%x,"
6435                             " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6436                             fpkt->pkt_reason);
6437 
6438                         /*
6439                          * Retry by recalling the routine that
6440                          * originally queued this packet
6441                          */
6442                         mutex_enter(&pptr->port_mutex);
6443                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6444                                 caddr_t msg;
6445 
6446                                 mutex_exit(&pptr->port_mutex);
6447 
6448                                 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6449 
6450                                 if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6451                                         fpkt->pkt_timeout +=
6452                                             FCP_TIMEOUT_DELTA;
6453                                 }
6454 
6455                                 rval = fc_ulp_issue_els(pptr->port_fp_handle,
6456                                     fpkt);
6457                                 if (rval == FC_SUCCESS) {
6458                                         return;
6459                                 }
6460 
6461                                 if (rval == FC_STATEC_BUSY ||
6462                                     rval == FC_OFFLINE) {
6463                                         fcp_queue_ipkt(pptr, fpkt);
6464                                         return;
6465                                 }
6466                                 (void) fc_ulp_error(rval, &msg);
6467 
6468                                 fcp_log(CE_NOTE, pptr->port_dip,
6469                                     "!ELS 0x%x failed to d_id=0x%x;"
6470                                     " %s", icmd->ipkt_opcode,
6471                                     ptgt->tgt_d_id, msg);
6472                         } else {
6473                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6474                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6475                                     "fcp_icmd_callback,3: state change "
6476                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6477                                 mutex_exit(&pptr->port_mutex);
6478                         }
6479                 }
6480         } else {
6481                 if (fcp_is_retryable(icmd) &&
6482                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6483                         if (FCP_MUST_RETRY(fpkt)) {
6484                                 fcp_queue_ipkt(pptr, fpkt);
6485                                 return;
6486                         }
6487                 }
6488                 mutex_enter(&pptr->port_mutex);
6489                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6490                     fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6491                         mutex_exit(&pptr->port_mutex);
6492                         fcp_print_error(fpkt);
6493                 } else {
6494                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6495                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6496                             "fcp_icmd_callback,4: state change occured"
6497                             " for D_ID=0x%x", ptgt->tgt_d_id);
6498                         mutex_exit(&pptr->port_mutex);
6499                 }
6500         }
6501 
6502 fail:
6503         if (free_pkt) {
6504                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6505                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
6506                 fcp_icmd_free(pptr, icmd);
6507         }
6508 }
6509 
6510 
6511 /*
6512  * called internally to send an info cmd using the transport
6513  *
6514  * sends either an INQ or a REPORT_LUN
6515  *
6516  * when the packet is completed fcp_scsi_callback is called
6517  */
6518 static int
6519 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6520     int lcount, int tcount, int cause, uint32_t rscn_count)
6521 {
6522         int                     nodma;
6523         struct fcp_ipkt         *icmd;
6524         struct fcp_tgt          *ptgt;
6525         struct fcp_port         *pptr;
6526         fc_frame_hdr_t          *hp;
6527         fc_packet_t             *fpkt;
6528         struct fcp_cmd          fcp_cmd;
6529         struct fcp_cmd          *fcmd;
6530         union scsi_cdb          *scsi_cdb;
6531 
6532         ASSERT(plun != NULL);
6533 
6534         ptgt = plun->lun_tgt;
6535         ASSERT(ptgt != NULL);
6536 
6537         pptr = ptgt->tgt_port;
6538         ASSERT(pptr != NULL);
6539 
6540         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6541             fcp_trace, FCP_BUF_LEVEL_5, 0,
6542             "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6543 
6544         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6545         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6546             FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6547             rscn_count);
6548 
6549         if (icmd == NULL) {
6550                 return (DDI_FAILURE);
6551         }
6552 
6553         fpkt = icmd->ipkt_fpkt;
6554         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6555         icmd->ipkt_retries = 0;
6556         icmd->ipkt_opcode = opcode;
6557         icmd->ipkt_lun = plun;
6558 
6559         if (nodma) {
6560                 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6561         } else {
6562                 fcmd = &fcp_cmd;
6563         }
6564         bzero(fcmd, sizeof (struct fcp_cmd));
6565 
6566         fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6567 
6568         hp = &fpkt->pkt_cmd_fhdr;
6569 
6570         hp->s_id = pptr->port_id;
6571         hp->d_id = ptgt->tgt_d_id;
6572         hp->r_ctl = R_CTL_COMMAND;
6573         hp->type = FC_TYPE_SCSI_FCP;
6574         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6575         hp->rsvd = 0;
6576         hp->seq_id = 0;
6577         hp->seq_cnt = 0;
6578         hp->ox_id = 0xffff;
6579         hp->rx_id = 0xffff;
6580         hp->ro = 0;
6581 
6582         bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6583 
6584         /*
6585          * Request SCSI target for expedited processing
6586          */
6587 
6588         /*
6589          * Set up for untagged queuing because we do not
6590          * know if the fibre device supports queuing.
6591          */
6592         fcmd->fcp_cntl.cntl_reserved_0 = 0;
6593         fcmd->fcp_cntl.cntl_reserved_1 = 0;
6594         fcmd->fcp_cntl.cntl_reserved_2 = 0;
6595         fcmd->fcp_cntl.cntl_reserved_3 = 0;
6596         fcmd->fcp_cntl.cntl_reserved_4 = 0;
6597         fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6598         scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6599 
6600         switch (opcode) {
6601         case SCMD_INQUIRY_PAGE83:
6602                 /*
6603                  * Prepare to get the Inquiry VPD page 83 information
6604                  */
6605                 fcmd->fcp_cntl.cntl_read_data = 1;
6606                 fcmd->fcp_cntl.cntl_write_data = 0;
6607                 fcmd->fcp_data_len = alloc_len;
6608 
6609                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6610                 fpkt->pkt_comp = fcp_scsi_callback;
6611 
6612                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6613                 scsi_cdb->g0_addr2 = 0x01;
6614                 scsi_cdb->g0_addr1 = 0x83;
6615                 scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6616                 break;
6617 
6618         case SCMD_INQUIRY:
6619                 fcmd->fcp_cntl.cntl_read_data = 1;
6620                 fcmd->fcp_cntl.cntl_write_data = 0;
6621                 fcmd->fcp_data_len = alloc_len;
6622 
6623                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6624                 fpkt->pkt_comp = fcp_scsi_callback;
6625 
6626                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6627                 scsi_cdb->g0_count0 = SUN_INQSIZE;
6628                 break;
6629 
6630         case SCMD_REPORT_LUN: {
6631                 fc_portid_t     d_id;
6632                 opaque_t        fca_dev;
6633 
6634                 ASSERT(alloc_len >= 16);
6635 
6636                 d_id.priv_lilp_posit = 0;
6637                 d_id.port_id = ptgt->tgt_d_id;
6638 
6639                 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6640 
6641                 mutex_enter(&ptgt->tgt_mutex);
6642                 ptgt->tgt_fca_dev = fca_dev;
6643                 mutex_exit(&ptgt->tgt_mutex);
6644 
6645                 fcmd->fcp_cntl.cntl_read_data = 1;
6646                 fcmd->fcp_cntl.cntl_write_data = 0;
6647                 fcmd->fcp_data_len = alloc_len;
6648 
6649                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6650                 fpkt->pkt_comp = fcp_scsi_callback;
6651 
6652                 scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6653                 scsi_cdb->scc5_count0 = alloc_len & 0xff;
6654                 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6655                 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6656                 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6657                 break;
6658         }
6659 
6660         default:
6661                 fcp_log(CE_WARN, pptr->port_dip,
6662                     "!fcp_send_scsi Invalid opcode");
6663                 break;
6664         }
6665 
6666         if (!nodma) {
6667                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6668                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6669         }
6670 
6671         mutex_enter(&pptr->port_mutex);
6672         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6673 
6674                 mutex_exit(&pptr->port_mutex);
6675                 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6676                     FC_SUCCESS) {
6677                         fcp_icmd_free(pptr, icmd);
6678                         return (DDI_FAILURE);
6679                 }
6680                 return (DDI_SUCCESS);
6681         } else {
6682                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6683                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6684                     "fcp_send_scsi,1: state change occured"
6685                     " for D_ID=0x%x", ptgt->tgt_d_id);
6686                 mutex_exit(&pptr->port_mutex);
6687                 fcp_icmd_free(pptr, icmd);
6688                 return (DDI_FAILURE);
6689         }
6690 }
6691 
6692 
6693 /*
6694  * called by fcp_scsi_callback to check to handle the case where
6695  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6696  */
6697 static int
6698 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6699 {
6700         uchar_t                         rqlen;
6701         int                             rval = DDI_FAILURE;
6702         struct scsi_extended_sense      sense_info, *sense;
6703         struct fcp_ipkt         *icmd = (struct fcp_ipkt *)
6704             fpkt->pkt_ulp_private;
6705         struct fcp_tgt          *ptgt = icmd->ipkt_tgt;
6706         struct fcp_port         *pptr = ptgt->tgt_port;
6707 
6708         ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6709 
6710         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6711                 /*
6712                  * SCSI-II Reserve Release support. Some older FC drives return
6713                  * Reservation conflict for Report Luns command.
6714                  */
6715                 if (icmd->ipkt_nodma) {
6716                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6717                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6718                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6719                 } else {
6720                         fcp_rsp_t       new_resp;
6721 
6722                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6723                             fpkt->pkt_resp_acc, sizeof (new_resp));
6724 
6725                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6726                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6727                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6728 
6729                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6730                             fpkt->pkt_resp_acc, sizeof (new_resp));
6731                 }
6732 
6733                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6734                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6735 
6736                 return (DDI_SUCCESS);
6737         }
6738 
6739         sense = &sense_info;
6740         if (!rsp->fcp_u.fcp_status.sense_len_set) {
6741                 /* no need to continue if sense length is not set */
6742                 return (rval);
6743         }
6744 
6745         /* casting 64-bit integer to 8-bit */
6746         rqlen = (uchar_t)min(rsp->fcp_sense_len,
6747             sizeof (struct scsi_extended_sense));
6748 
6749         if (rqlen < 14) {
6750                 /* no need to continue if request length isn't long enough */
6751                 return (rval);
6752         }
6753 
6754         if (icmd->ipkt_nodma) {
6755                 /*
6756                  * We can safely use fcp_response_len here since the
6757                  * only path that calls fcp_check_reportlun,
6758                  * fcp_scsi_callback, has already called
6759                  * fcp_validate_fcp_response.
6760                  */
6761                 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6762                     sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6763         } else {
6764                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6765                     rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6766                     sizeof (struct scsi_extended_sense));
6767         }
6768 
6769         if (!FCP_SENSE_NO_LUN(sense)) {
6770                 mutex_enter(&ptgt->tgt_mutex);
6771                 /* clear the flag if any */
6772                 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6773                 mutex_exit(&ptgt->tgt_mutex);
6774         }
6775 
6776         if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6777             (sense->es_add_code == 0x20)) {
6778                 if (icmd->ipkt_nodma) {
6779                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6780                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6781                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6782                 } else {
6783                         fcp_rsp_t       new_resp;
6784 
6785                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6786                             fpkt->pkt_resp_acc, sizeof (new_resp));
6787 
6788                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6789                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6790                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6791 
6792                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6793                             fpkt->pkt_resp_acc, sizeof (new_resp));
6794                 }
6795 
6796                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6797                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6798 
6799                 return (DDI_SUCCESS);
6800         }
6801 
6802         /*
6803          * This is for the STK library which returns a check condition,
6804          * to indicate device is not ready, manual assistance needed.
6805          * This is to a report lun command when the door is open.
6806          */
6807         if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6808                 if (icmd->ipkt_nodma) {
6809                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6810                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6811                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6812                 } else {
6813                         fcp_rsp_t       new_resp;
6814 
6815                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6816                             fpkt->pkt_resp_acc, sizeof (new_resp));
6817 
6818                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6819                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6820                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6821 
6822                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6823                             fpkt->pkt_resp_acc, sizeof (new_resp));
6824                 }
6825 
6826                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6827                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6828 
6829                 return (DDI_SUCCESS);
6830         }
6831 
6832         if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6833             (FCP_SENSE_NO_LUN(sense))) {
6834                 mutex_enter(&ptgt->tgt_mutex);
6835                 if ((FCP_SENSE_NO_LUN(sense)) &&
6836                     (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6837                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6838                         mutex_exit(&ptgt->tgt_mutex);
6839                         /*
6840                          * reconfig was triggred by ILLEGAL REQUEST but
6841                          * got ILLEGAL REQUEST again
6842                          */
6843                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6844                             fcp_trace, FCP_BUF_LEVEL_3, 0,
6845                             "!FCP: Unable to obtain Report Lun data"
6846                             " target=%x", ptgt->tgt_d_id);
6847                 } else {
6848                         if (ptgt->tgt_tid == NULL) {
6849                                 timeout_id_t    tid;
6850                                 /*
6851                                  * REPORT LUN data has changed.  Kick off
6852                                  * rediscovery
6853                                  */
6854                                 tid = timeout(fcp_reconfigure_luns,
6855                                     (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6856 
6857                                 ptgt->tgt_tid = tid;
6858                                 ptgt->tgt_state |= FCP_TGT_BUSY;
6859                         }
6860                         if (FCP_SENSE_NO_LUN(sense)) {
6861                                 ptgt->tgt_state |= FCP_TGT_ILLREQ;
6862                         }
6863                         mutex_exit(&ptgt->tgt_mutex);
6864                         if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6865                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6866                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6867                                     "!FCP:Report Lun Has Changed"
6868                                     " target=%x", ptgt->tgt_d_id);
6869                         } else if (FCP_SENSE_NO_LUN(sense)) {
6870                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6871                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6872                                     "!FCP:LU Not Supported"
6873                                     " target=%x", ptgt->tgt_d_id);
6874                         }
6875                 }
6876                 rval = DDI_SUCCESS;
6877         }
6878 
6879         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6880             fcp_trace, FCP_BUF_LEVEL_5, 0,
6881             "D_ID=%x, sense=%x, status=%x",
6882             fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6883             rsp->fcp_u.fcp_status.scsi_status);
6884 
6885         return (rval);
6886 }
6887 
6888 /*
6889  *     Function: fcp_scsi_callback
6890  *
6891  *  Description: This is the callback routine set by fcp_send_scsi() after
6892  *               it calls fcp_icmd_alloc().  The SCSI command completed here
6893  *               and autogenerated by FCP are:  REPORT_LUN, INQUIRY and
6894  *               INQUIRY_PAGE83.
6895  *
6896  *     Argument: *fpkt   FC packet used to convey the command
6897  *
6898  * Return Value: None
6899  */
6900 static void
6901 fcp_scsi_callback(fc_packet_t *fpkt)
6902 {
6903         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
6904             fpkt->pkt_ulp_private;
6905         struct fcp_rsp_info     fcp_rsp_err, *bep;
6906         struct fcp_port *pptr;
6907         struct fcp_tgt  *ptgt;
6908         struct fcp_lun  *plun;
6909         struct fcp_rsp          response, *rsp;
6910 
6911         ptgt = icmd->ipkt_tgt;
6912         pptr = ptgt->tgt_port;
6913         plun = icmd->ipkt_lun;
6914 
6915         if (icmd->ipkt_nodma) {
6916                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6917         } else {
6918                 rsp = &response;
6919                 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6920                     sizeof (struct fcp_rsp));
6921         }
6922 
6923         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6924             fcp_trace, FCP_BUF_LEVEL_2, 0,
6925             "SCSI callback state=0x%x for %x, op_code=0x%x, "
6926             "status=%x, lun num=%x",
6927             fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6928             rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6929 
6930         /*
6931          * Pre-init LUN GUID with NWWN if it is not a device that
6932          * supports multiple luns and we know it's not page83
6933          * compliant.  Although using a NWWN is not lun unique,
6934          * we will be fine since there is only one lun behind the taget
6935          * in this case.
6936          */
6937         if ((plun->lun_guid_size == 0) &&
6938             (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6939             (fcp_symmetric_device_probe(plun) == 0)) {
6940 
6941                 char ascii_wwn[FC_WWN_SIZE*2+1];
6942                 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6943                 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6944         }
6945 
6946         /*
6947          * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6948          * when thay have more data than what is asked in CDB. An overrun
6949          * is really when FCP_DL is smaller than the data length in CDB.
6950          * In the case here we know that REPORT LUN command we formed within
6951          * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6952          * behavior. In reality this is FC_SUCCESS.
6953          */
6954         if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6955             (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6956             (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6957                 fpkt->pkt_state = FC_PKT_SUCCESS;
6958         }
6959 
6960         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6961                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6962                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6963                     "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6964                     ptgt->tgt_d_id);
6965 
6966                 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6967                         /*
6968                          * Inquiry VPD page command on A5K SES devices would
6969                          * result in data CRC errors.
6970                          */
6971                         if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6972                                 (void) fcp_handle_page83(fpkt, icmd, 1);
6973                                 return;
6974                         }
6975                 }
6976                 if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6977                     FCP_MUST_RETRY(fpkt)) {
6978                         fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6979                         fcp_retry_scsi_cmd(fpkt);
6980                         return;
6981                 }
6982 
6983                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6984                     FCP_TGT_TRACE_20);
6985 
6986                 mutex_enter(&pptr->port_mutex);
6987                 mutex_enter(&ptgt->tgt_mutex);
6988                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6989                         mutex_exit(&ptgt->tgt_mutex);
6990                         mutex_exit(&pptr->port_mutex);
6991                         fcp_print_error(fpkt);
6992                 } else {
6993                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6994                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6995                             "fcp_scsi_callback,1: state change occured"
6996                             " for D_ID=0x%x", ptgt->tgt_d_id);
6997                         mutex_exit(&ptgt->tgt_mutex);
6998                         mutex_exit(&pptr->port_mutex);
6999                 }
7000                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7001                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7002                 fcp_icmd_free(pptr, icmd);
7003                 return;
7004         }
7005 
7006         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7007 
7008         mutex_enter(&pptr->port_mutex);
7009         mutex_enter(&ptgt->tgt_mutex);
7010         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7011                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7012                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7013                     "fcp_scsi_callback,2: state change occured"
7014                     " for D_ID=0x%x", ptgt->tgt_d_id);
7015                 mutex_exit(&ptgt->tgt_mutex);
7016                 mutex_exit(&pptr->port_mutex);
7017                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7018                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7019                 fcp_icmd_free(pptr, icmd);
7020                 return;
7021         }
7022         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7023 
7024         mutex_exit(&ptgt->tgt_mutex);
7025         mutex_exit(&pptr->port_mutex);
7026 
7027         if (icmd->ipkt_nodma) {
7028                 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7029                     sizeof (struct fcp_rsp));
7030         } else {
7031                 bep = &fcp_rsp_err;
7032                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7033                     fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7034         }
7035 
7036         if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7037                 fcp_retry_scsi_cmd(fpkt);
7038                 return;
7039         }
7040 
7041         if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7042             FCP_NO_FAILURE) {
7043                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7044                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7045                     "rsp_code=0x%x, rsp_len_set=0x%x",
7046                     bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7047                 fcp_retry_scsi_cmd(fpkt);
7048                 return;
7049         }
7050 
7051         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7052             rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7053                 fcp_queue_ipkt(pptr, fpkt);
7054                 return;
7055         }
7056 
7057         /*
7058          * Devices that do not support INQUIRY_PAGE83, return check condition
7059          * with illegal request as per SCSI spec.
7060          * Crossbridge is one such device and Daktari's SES node is another.
7061          * We want to ideally enumerate these devices as a non-mpxio devices.
7062          * SES nodes (Daktari only currently) are an exception to this.
7063          */
7064         if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7065             (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7066 
7067                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7068                     fcp_trace, FCP_BUF_LEVEL_3, 0,
7069                     "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7070                     "check condition. May enumerate as non-mpxio device",
7071                     ptgt->tgt_d_id, plun->lun_type);
7072 
7073                 /*
7074                  * If we let Daktari's SES be enumerated as a non-mpxio
7075                  * device, there will be a discrepency in that the other
7076                  * internal FC disks will get enumerated as mpxio devices.
7077                  * Applications like luxadm expect this to be consistent.
7078                  *
7079                  * So, we put in a hack here to check if this is an SES device
7080                  * and handle it here.
7081                  */
7082                 if (plun->lun_type == DTYPE_ESI) {
7083                         /*
7084                          * Since, pkt_state is actually FC_PKT_SUCCESS
7085                          * at this stage, we fake a failure here so that
7086                          * fcp_handle_page83 will create a device path using
7087                          * the WWN instead of the GUID which is not there anyway
7088                          */
7089                         fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7090                         (void) fcp_handle_page83(fpkt, icmd, 1);
7091                         return;
7092                 }
7093 
7094                 mutex_enter(&ptgt->tgt_mutex);
7095                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
7096                     FCP_LUN_MARK | FCP_LUN_BUSY);
7097                 mutex_exit(&ptgt->tgt_mutex);
7098 
7099                 (void) fcp_call_finish_init(pptr, ptgt,
7100                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7101                     icmd->ipkt_cause);
7102                 fcp_icmd_free(pptr, icmd);
7103                 return;
7104         }
7105 
7106         if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7107                 int rval = DDI_FAILURE;
7108 
7109                 /*
7110                  * handle cases where report lun isn't supported
7111                  * by faking up our own REPORT_LUN response or
7112                  * UNIT ATTENTION
7113                  */
7114                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7115                         rval = fcp_check_reportlun(rsp, fpkt);
7116 
7117                         /*
7118                          * fcp_check_reportlun might have modified the
7119                          * FCP response. Copy it in again to get an updated
7120                          * FCP response
7121                          */
7122                         if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7123                                 rsp = &response;
7124 
7125                                 FCP_CP_IN(fpkt->pkt_resp, rsp,
7126                                     fpkt->pkt_resp_acc,
7127                                     sizeof (struct fcp_rsp));
7128                         }
7129                 }
7130 
7131                 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7132                         if (rval == DDI_SUCCESS) {
7133                                 (void) fcp_call_finish_init(pptr, ptgt,
7134                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7135                                     icmd->ipkt_cause);
7136                                 fcp_icmd_free(pptr, icmd);
7137                         } else {
7138                                 fcp_retry_scsi_cmd(fpkt);
7139                         }
7140 
7141                         return;
7142                 }
7143         } else {
7144                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7145                         mutex_enter(&ptgt->tgt_mutex);
7146                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7147                         mutex_exit(&ptgt->tgt_mutex);
7148                 }
7149         }
7150 
7151         ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7152         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7153                 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7154                     DDI_DMA_SYNC_FORCPU);
7155         }
7156 
7157         switch (icmd->ipkt_opcode) {
7158         case SCMD_INQUIRY:
7159                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7160                 fcp_handle_inquiry(fpkt, icmd);
7161                 break;
7162 
7163         case SCMD_REPORT_LUN:
7164                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7165                     FCP_TGT_TRACE_22);
7166                 fcp_handle_reportlun(fpkt, icmd);
7167                 break;
7168 
7169         case SCMD_INQUIRY_PAGE83:
7170                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7171                 (void) fcp_handle_page83(fpkt, icmd, 0);
7172                 break;
7173 
7174         default:
7175                 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7176                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7177                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7178                 fcp_icmd_free(pptr, icmd);
7179                 break;
7180         }
7181 }
7182 
7183 
7184 static void
7185 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7186 {
7187         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
7188             fpkt->pkt_ulp_private;
7189         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
7190         struct fcp_port *pptr = ptgt->tgt_port;
7191 
7192         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7193             fcp_is_retryable(icmd)) {
7194                 mutex_enter(&pptr->port_mutex);
7195                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7196                         mutex_exit(&pptr->port_mutex);
7197                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7198                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7199                             "Retrying %s to %x; state=%x, reason=%x",
7200                             (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7201                             "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7202                             fpkt->pkt_state, fpkt->pkt_reason);
7203 
7204                         fcp_queue_ipkt(pptr, fpkt);
7205                 } else {
7206                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7207                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7208                             "fcp_retry_scsi_cmd,1: state change occured"
7209                             " for D_ID=0x%x", ptgt->tgt_d_id);
7210                         mutex_exit(&pptr->port_mutex);
7211                         (void) fcp_call_finish_init(pptr, ptgt,
7212                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7213                             icmd->ipkt_cause);
7214                         fcp_icmd_free(pptr, icmd);
7215                 }
7216         } else {
7217                 fcp_print_error(fpkt);
7218                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7219                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7220                 fcp_icmd_free(pptr, icmd);
7221         }
7222 }
7223 
7224 /*
7225  *     Function: fcp_handle_page83
7226  *
7227  *  Description: Treats the response to INQUIRY_PAGE83.
7228  *
7229  *     Argument: *fpkt  FC packet used to convey the command.
7230  *               *icmd  Original fcp_ipkt structure.
7231  *               ignore_page83_data
7232  *                      if it's 1, that means it's a special devices's
7233  *                      page83 response, it should be enumerated under mpxio
7234  *
7235  * Return Value: None
7236  */
7237 static void
7238 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7239     int ignore_page83_data)
7240 {
7241         struct fcp_port *pptr;
7242         struct fcp_lun  *plun;
7243         struct fcp_tgt  *ptgt;
7244         uchar_t                 dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7245         int                     fail = 0;
7246         ddi_devid_t             devid;
7247         char                    *guid = NULL;
7248         int                     ret;
7249 
7250         ASSERT(icmd != NULL && fpkt != NULL);
7251 
7252         pptr = icmd->ipkt_port;
7253         ptgt = icmd->ipkt_tgt;
7254         plun = icmd->ipkt_lun;
7255 
7256         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7257                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7258 
7259                 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7260                     SCMD_MAX_INQUIRY_PAGE83_SIZE);
7261 
7262                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7263                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7264                     "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7265                     "dtype=0x%x, lun num=%x",
7266                     pptr->port_instance, ptgt->tgt_d_id,
7267                     dev_id_page[0], plun->lun_num);
7268 
7269                 ret = ddi_devid_scsi_encode(
7270                     DEVID_SCSI_ENCODE_VERSION_LATEST,
7271                     NULL,               /* driver name */
7272                     (unsigned char *) &plun->lun_inq, /* standard inquiry */
7273                     sizeof (plun->lun_inq), /* size of standard inquiry */
7274                     NULL,               /* page 80 data */
7275                     0,          /* page 80 len */
7276                     dev_id_page,        /* page 83 data */
7277                     SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7278                     &devid);
7279 
7280                 if (ret == DDI_SUCCESS) {
7281 
7282                         guid = ddi_devid_to_guid(devid);
7283 
7284                         if (guid) {
7285                                 /*
7286                                  * Check our current guid.  If it's non null
7287                                  * and it has changed, we need to copy it into
7288                                  * lun_old_guid since we might still need it.
7289                                  */
7290                                 if (plun->lun_guid &&
7291                                     strcmp(guid, plun->lun_guid)) {
7292                                         unsigned int len;
7293 
7294                                         /*
7295                                          * If the guid of the LUN changes,
7296                                          * reconfiguration should be triggered
7297                                          * to reflect the changes.
7298                                          * i.e. we should offline the LUN with
7299                                          * the old guid, and online the LUN with
7300                                          * the new guid.
7301                                          */
7302                                         plun->lun_state |= FCP_LUN_CHANGED;
7303 
7304                                         if (plun->lun_old_guid) {
7305                                                 kmem_free(plun->lun_old_guid,
7306                                                     plun->lun_old_guid_size);
7307                                         }
7308 
7309                                         len = plun->lun_guid_size;
7310                                         plun->lun_old_guid_size = len;
7311 
7312                                         plun->lun_old_guid = kmem_zalloc(len,
7313                                             KM_NOSLEEP);
7314 
7315                                         if (plun->lun_old_guid) {
7316                                                 /*
7317                                                  * The alloc was successful then
7318                                                  * let's do the copy.
7319                                                  */
7320                                                 bcopy(plun->lun_guid,
7321                                                     plun->lun_old_guid, len);
7322                                         } else {
7323                                                 fail = 1;
7324                                                 plun->lun_old_guid_size = 0;
7325                                         }
7326                                 }
7327                                 if (!fail) {
7328                                         if (fcp_copy_guid_2_lun_block(
7329                                             plun, guid)) {
7330                                                 fail = 1;
7331                                         }
7332                                 }
7333                                 ddi_devid_free_guid(guid);
7334 
7335                         } else {
7336                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7337                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7338                                     "fcp_handle_page83: unable to create "
7339                                     "GUID");
7340 
7341                                 /* couldn't create good guid from devid */
7342                                 fail = 1;
7343                         }
7344                         ddi_devid_free(devid);
7345 
7346                 } else if (ret == DDI_NOT_WELL_FORMED) {
7347                         /* NULL filled data for page 83 */
7348                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7349                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7350                             "fcp_handle_page83: retry GUID");
7351 
7352                         icmd->ipkt_retries = 0;
7353                         fcp_retry_scsi_cmd(fpkt);
7354                         return;
7355                 } else {
7356                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7357                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7358                             "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7359                             ret);
7360                         /*
7361                          * Since the page83 validation
7362                          * introduced late, we are being
7363                          * tolerant to the existing devices
7364                          * that already found to be working
7365                          * under mpxio, like A5200's SES device,
7366                          * its page83 response will not be standard-compliant,
7367                          * but we still want it to be enumerated under mpxio.
7368                          */
7369                         if (fcp_symmetric_device_probe(plun) != 0) {
7370                                 fail = 1;
7371                         }
7372                 }
7373 
7374         } else {
7375                 /* bad packet state */
7376                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7377 
7378                 /*
7379                  * For some special devices (A5K SES and Daktari's SES devices),
7380                  * they should be enumerated under mpxio
7381                  * or "luxadm dis" will fail
7382                  */
7383                 if (ignore_page83_data) {
7384                         fail = 0;
7385                 } else {
7386                         fail = 1;
7387                 }
7388                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7389                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7390                     "!Devid page cmd failed. "
7391                     "fpkt_state: %x fpkt_reason: %x",
7392                     "ignore_page83: %d",
7393                     fpkt->pkt_state, fpkt->pkt_reason,
7394                     ignore_page83_data);
7395         }
7396 
7397         mutex_enter(&pptr->port_mutex);
7398         mutex_enter(&plun->lun_mutex);
7399         /*
7400          * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7401          * mismatch between lun_cip and lun_mpxio.
7402          */
7403         if (plun->lun_cip == NULL) {
7404                 /*
7405                  * If we don't have a guid for this lun it's because we were
7406                  * unable to glean one from the page 83 response.  Set the
7407                  * control flag to 0 here to make sure that we don't attempt to
7408                  * enumerate it under mpxio.
7409                  */
7410                 if (fail || pptr->port_mpxio == 0) {
7411                         plun->lun_mpxio = 0;
7412                 } else {
7413                         plun->lun_mpxio = 1;
7414                 }
7415         }
7416         mutex_exit(&plun->lun_mutex);
7417         mutex_exit(&pptr->port_mutex);
7418 
7419         mutex_enter(&ptgt->tgt_mutex);
7420         plun->lun_state &=
7421             ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7422         mutex_exit(&ptgt->tgt_mutex);
7423 
7424         (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7425             icmd->ipkt_change_cnt, icmd->ipkt_cause);
7426 
7427         fcp_icmd_free(pptr, icmd);
7428 }
7429 
7430 /*
7431  *     Function: fcp_handle_inquiry
7432  *
7433  *  Description: Called by fcp_scsi_callback to handle the response to an
7434  *               INQUIRY request.
7435  *
7436  *     Argument: *fpkt  FC packet used to convey the command.
7437  *               *icmd  Original fcp_ipkt structure.
7438  *
7439  * Return Value: None
7440  */
7441 static void
7442 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7443 {
7444         struct fcp_port *pptr;
7445         struct fcp_lun  *plun;
7446         struct fcp_tgt  *ptgt;
7447         uchar_t         dtype;
7448         uchar_t         pqual;
7449         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
7450 
7451         ASSERT(icmd != NULL && fpkt != NULL);
7452 
7453         pptr = icmd->ipkt_port;
7454         ptgt = icmd->ipkt_tgt;
7455         plun = icmd->ipkt_lun;
7456 
7457         FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7458             sizeof (struct scsi_inquiry));
7459 
7460         dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7461         pqual = plun->lun_inq.inq_dtype >> 5;
7462 
7463         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7464             fcp_trace, FCP_BUF_LEVEL_5, 0,
7465             "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7466             "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7467             plun->lun_num, dtype, pqual);
7468 
7469         if (pqual != 0) {
7470                 /*
7471                  * Non-zero peripheral qualifier
7472                  */
7473                 fcp_log(CE_CONT, pptr->port_dip,
7474                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7475                     "Device type=0x%x Peripheral qual=0x%x\n",
7476                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7477 
7478                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7479                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7480                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7481                     "Device type=0x%x Peripheral qual=0x%x\n",
7482                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7483 
7484                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7485 
7486                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7487                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7488                 fcp_icmd_free(pptr, icmd);
7489                 return;
7490         }
7491 
7492         /*
7493          * If the device is already initialized, check the dtype
7494          * for a change. If it has changed then update the flags
7495          * so the create_luns will offline the old device and
7496          * create the new device. Refer to bug: 4764752
7497          */
7498         if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7499                 plun->lun_state |= FCP_LUN_CHANGED;
7500         }
7501         plun->lun_type = plun->lun_inq.inq_dtype;
7502 
7503         /*
7504          * This code is setting/initializing the throttling in the FCA
7505          * driver.
7506          */
7507         mutex_enter(&pptr->port_mutex);
7508         if (!pptr->port_notify) {
7509                 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7510                         uint32_t cmd = 0;
7511                         cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7512                             ((cmd & 0xFFFFFF00 >> 8) |
7513                             FCP_SVE_THROTTLE << 8));
7514                         pptr->port_notify = 1;
7515                         mutex_exit(&pptr->port_mutex);
7516                         (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7517                         mutex_enter(&pptr->port_mutex);
7518                 }
7519         }
7520 
7521         if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7522                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7523                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7524                     "fcp_handle_inquiry,1:state change occured"
7525                     " for D_ID=0x%x", ptgt->tgt_d_id);
7526                 mutex_exit(&pptr->port_mutex);
7527 
7528                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7529                 (void) fcp_call_finish_init(pptr, ptgt,
7530                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7531                     icmd->ipkt_cause);
7532                 fcp_icmd_free(pptr, icmd);
7533                 return;
7534         }
7535         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7536         mutex_exit(&pptr->port_mutex);
7537 
7538         /* Retrieve the rscn count (if a valid one exists) */
7539         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7540                 rscn_count = ((fc_ulp_rscn_info_t *)
7541                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7542         } else {
7543                 rscn_count = FC_INVALID_RSCN_COUNT;
7544         }
7545 
7546         if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7547             SCMD_MAX_INQUIRY_PAGE83_SIZE,
7548             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7549             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7550                 fcp_log(CE_WARN, NULL, "!failed to send page 83");
7551                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7552                 (void) fcp_call_finish_init(pptr, ptgt,
7553                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7554                     icmd->ipkt_cause);
7555         }
7556 
7557         /*
7558          * Read Inquiry VPD Page 0x83 to uniquely
7559          * identify this logical unit.
7560          */
7561         fcp_icmd_free(pptr, icmd);
7562 }
7563 
7564 /*
7565  *     Function: fcp_handle_reportlun
7566  *
7567  *  Description: Called by fcp_scsi_callback to handle the response to a
7568  *               REPORT_LUN request.
7569  *
7570  *     Argument: *fpkt  FC packet used to convey the command.
7571  *               *icmd  Original fcp_ipkt structure.
7572  *
7573  * Return Value: None
7574  */
7575 static void
7576 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7577 {
7578         int                             i;
7579         int                             nluns_claimed;
7580         int                             nluns_bufmax;
7581         int                             len;
7582         uint16_t                        lun_num;
7583         uint32_t                        rscn_count = FC_INVALID_RSCN_COUNT;
7584         struct fcp_port                 *pptr;
7585         struct fcp_tgt                  *ptgt;
7586         struct fcp_lun                  *plun;
7587         struct fcp_reportlun_resp       *report_lun;
7588 
7589         pptr = icmd->ipkt_port;
7590         ptgt = icmd->ipkt_tgt;
7591         len = fpkt->pkt_datalen;
7592 
7593         if ((len < FCP_LUN_HEADER) ||
7594             ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7595                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7596                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7597                 fcp_icmd_free(pptr, icmd);
7598                 return;
7599         }
7600 
7601         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7602             fpkt->pkt_datalen);
7603 
7604         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7605             fcp_trace, FCP_BUF_LEVEL_5, 0,
7606             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7607             pptr->port_instance, ptgt->tgt_d_id);
7608 
7609         /*
7610          * Get the number of luns (which is supplied as LUNS * 8) the
7611          * device claims it has.
7612          */
7613         nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7614 
7615         /*
7616          * Get the maximum number of luns the buffer submitted can hold.
7617          */
7618         nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7619 
7620         /*
7621          * Due to limitations of certain hardware, we support only 16 bit LUNs
7622          */
7623         if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7624                 kmem_free(report_lun, len);
7625 
7626                 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7627                     " 0x%x number of LUNs for target=%x", nluns_claimed,
7628                     ptgt->tgt_d_id);
7629 
7630                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7631                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7632                 fcp_icmd_free(pptr, icmd);
7633                 return;
7634         }
7635 
7636         /*
7637          * If there are more LUNs than we have allocated memory for,
7638          * allocate more space and send down yet another report lun if
7639          * the maximum number of attempts hasn't been reached.
7640          */
7641         mutex_enter(&ptgt->tgt_mutex);
7642 
7643         if ((nluns_claimed > nluns_bufmax) &&
7644             (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7645 
7646                 struct fcp_lun *plun;
7647 
7648                 ptgt->tgt_report_lun_cnt++;
7649                 plun = ptgt->tgt_lun;
7650                 ASSERT(plun != NULL);
7651                 mutex_exit(&ptgt->tgt_mutex);
7652 
7653                 kmem_free(report_lun, len);
7654 
7655                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7656                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7657                     "!Dynamically discovered %d LUNs for D_ID=%x",
7658                     nluns_claimed, ptgt->tgt_d_id);
7659 
7660                 /* Retrieve the rscn count (if a valid one exists) */
7661                 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7662                         rscn_count = ((fc_ulp_rscn_info_t *)
7663                             (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7664                             ulp_rscn_count;
7665                 } else {
7666                         rscn_count = FC_INVALID_RSCN_COUNT;
7667                 }
7668 
7669                 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7670                     FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7671                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7672                     icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7673                         (void) fcp_call_finish_init(pptr, ptgt,
7674                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7675                             icmd->ipkt_cause);
7676                 }
7677 
7678                 fcp_icmd_free(pptr, icmd);
7679                 return;
7680         }
7681 
7682         if (nluns_claimed > nluns_bufmax) {
7683                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7684                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7685                     "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7686                     "    Number of LUNs lost=%x",
7687                     ptgt->tgt_port_wwn.raw_wwn[0],
7688                     ptgt->tgt_port_wwn.raw_wwn[1],
7689                     ptgt->tgt_port_wwn.raw_wwn[2],
7690                     ptgt->tgt_port_wwn.raw_wwn[3],
7691                     ptgt->tgt_port_wwn.raw_wwn[4],
7692                     ptgt->tgt_port_wwn.raw_wwn[5],
7693                     ptgt->tgt_port_wwn.raw_wwn[6],
7694                     ptgt->tgt_port_wwn.raw_wwn[7],
7695                     nluns_claimed - nluns_bufmax);
7696 
7697                 nluns_claimed = nluns_bufmax;
7698         }
7699         ptgt->tgt_lun_cnt = nluns_claimed;
7700 
7701         /*
7702          * Identify missing LUNs and print warning messages
7703          */
7704         for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7705                 int offline;
7706                 int exists = 0;
7707 
7708                 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7709 
7710                 for (i = 0; i < nluns_claimed && exists == 0; i++) {
7711                         uchar_t         *lun_string;
7712 
7713                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7714 
7715                         switch (lun_string[0] & 0xC0) {
7716                         case FCP_LUN_ADDRESSING:
7717                         case FCP_PD_ADDRESSING:
7718                         case FCP_VOLUME_ADDRESSING:
7719                                 lun_num = ((lun_string[0] & 0x3F) << 8) |
7720                                     lun_string[1];
7721                                 if (plun->lun_num == lun_num) {
7722                                         exists++;
7723                                         break;
7724                                 }
7725                                 break;
7726 
7727                         default:
7728                                 break;
7729                         }
7730                 }
7731 
7732                 if (!exists && !offline) {
7733                         mutex_exit(&ptgt->tgt_mutex);
7734 
7735                         mutex_enter(&pptr->port_mutex);
7736                         mutex_enter(&ptgt->tgt_mutex);
7737                         if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7738                                 /*
7739                                  * set disappear flag when device was connected
7740                                  */
7741                                 if (!(plun->lun_state &
7742                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7743                                         plun->lun_state |= FCP_LUN_DISAPPEARED;
7744                                 }
7745                                 mutex_exit(&ptgt->tgt_mutex);
7746                                 mutex_exit(&pptr->port_mutex);
7747                                 if (!(plun->lun_state &
7748                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7749                                         fcp_log(CE_NOTE, pptr->port_dip,
7750                                             "!Lun=%x for target=%x disappeared",
7751                                             plun->lun_num, ptgt->tgt_d_id);
7752                                 }
7753                                 mutex_enter(&ptgt->tgt_mutex);
7754                         } else {
7755                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7756                                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7757                                     "fcp_handle_reportlun,1: state change"
7758                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
7759                                 mutex_exit(&ptgt->tgt_mutex);
7760                                 mutex_exit(&pptr->port_mutex);
7761                                 kmem_free(report_lun, len);
7762                                 (void) fcp_call_finish_init(pptr, ptgt,
7763                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7764                                     icmd->ipkt_cause);
7765                                 fcp_icmd_free(pptr, icmd);
7766                                 return;
7767                         }
7768                 } else if (exists) {
7769                         /*
7770                          * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7771                          * actually exists in REPORT_LUN response
7772                          */
7773                         if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7774                                 plun->lun_state &=
7775                                     ~FCP_LUN_DEVICE_NOT_CONNECTED;
7776                         }
7777                         if (offline || plun->lun_num == 0) {
7778                                 if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7779                                         plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7780                                         mutex_exit(&ptgt->tgt_mutex);
7781                                         fcp_log(CE_NOTE, pptr->port_dip,
7782                                             "!Lun=%x for target=%x reappeared",
7783                                             plun->lun_num, ptgt->tgt_d_id);
7784                                         mutex_enter(&ptgt->tgt_mutex);
7785                                 }
7786                         }
7787                 }
7788         }
7789 
7790         ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7791         mutex_exit(&ptgt->tgt_mutex);
7792 
7793         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7794             fcp_trace, FCP_BUF_LEVEL_5, 0,
7795             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7796             pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7797 
7798         /* scan each lun */
7799         for (i = 0; i < nluns_claimed; i++) {
7800                 uchar_t *lun_string;
7801 
7802                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7803 
7804                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7805                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7806                     "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7807                     " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7808                     lun_string[0]);
7809 
7810                 switch (lun_string[0] & 0xC0) {
7811                 case FCP_LUN_ADDRESSING:
7812                 case FCP_PD_ADDRESSING:
7813                 case FCP_VOLUME_ADDRESSING:
7814                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7815 
7816                         /* We will skip masked LUNs because of the blacklist. */
7817                         if (fcp_lun_blacklist != NULL) {
7818                                 mutex_enter(&ptgt->tgt_mutex);
7819                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
7820                                     lun_num) == TRUE) {
7821                                         ptgt->tgt_lun_cnt--;
7822                                         mutex_exit(&ptgt->tgt_mutex);
7823                                         break;
7824                                 }
7825                                 mutex_exit(&ptgt->tgt_mutex);
7826                         }
7827 
7828                         /* see if this LUN is already allocated */
7829                         if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7830                                 plun = fcp_alloc_lun(ptgt);
7831                                 if (plun == NULL) {
7832                                         fcp_log(CE_NOTE, pptr->port_dip,
7833                                             "!Lun allocation failed"
7834                                             " target=%x lun=%x",
7835                                             ptgt->tgt_d_id, lun_num);
7836                                         break;
7837                                 }
7838                         }
7839 
7840                         mutex_enter(&plun->lun_tgt->tgt_mutex);
7841                         /* convert to LUN */
7842                         plun->lun_addr.ent_addr_0 =
7843                             BE_16(*(uint16_t *)&(lun_string[0]));
7844                         plun->lun_addr.ent_addr_1 =
7845                             BE_16(*(uint16_t *)&(lun_string[2]));
7846                         plun->lun_addr.ent_addr_2 =
7847                             BE_16(*(uint16_t *)&(lun_string[4]));
7848                         plun->lun_addr.ent_addr_3 =
7849                             BE_16(*(uint16_t *)&(lun_string[6]));
7850 
7851                         plun->lun_num = lun_num;
7852                         plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7853                         plun->lun_state &= ~FCP_LUN_OFFLINE;
7854                         mutex_exit(&plun->lun_tgt->tgt_mutex);
7855 
7856                         /* Retrieve the rscn count (if a valid one exists) */
7857                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7858                                 rscn_count = ((fc_ulp_rscn_info_t *)
7859                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7860                                     ulp_rscn_count;
7861                         } else {
7862                                 rscn_count = FC_INVALID_RSCN_COUNT;
7863                         }
7864 
7865                         if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7866                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7867                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7868                                 mutex_enter(&pptr->port_mutex);
7869                                 mutex_enter(&plun->lun_tgt->tgt_mutex);
7870                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7871                                         fcp_log(CE_NOTE, pptr->port_dip,
7872                                             "!failed to send INQUIRY"
7873                                             " target=%x lun=%x",
7874                                             ptgt->tgt_d_id, plun->lun_num);
7875                                 } else {
7876                                         FCP_TRACE(fcp_logq,
7877                                             pptr->port_instbuf, fcp_trace,
7878                                             FCP_BUF_LEVEL_5, 0,
7879                                             "fcp_handle_reportlun,2: state"
7880                                             " change occured for D_ID=0x%x",
7881                                             ptgt->tgt_d_id);
7882                                 }
7883                                 mutex_exit(&plun->lun_tgt->tgt_mutex);
7884                                 mutex_exit(&pptr->port_mutex);
7885                         } else {
7886                                 continue;
7887                         }
7888                         break;
7889 
7890                 default:
7891                         fcp_log(CE_WARN, NULL,
7892                             "!Unsupported LUN Addressing method %x "
7893                             "in response to REPORT_LUN", lun_string[0]);
7894                         break;
7895                 }
7896 
7897                 /*
7898                  * each time through this loop we should decrement
7899                  * the tmp_cnt by one -- since we go through this loop
7900                  * one time for each LUN, the tmp_cnt should never be <=0
7901                  */
7902                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7903                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7904         }
7905 
7906         if (i == 0) {
7907                 fcp_log(CE_WARN, pptr->port_dip,
7908                     "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7909                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7910                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7911         }
7912 
7913         kmem_free(report_lun, len);
7914         fcp_icmd_free(pptr, icmd);
7915 }
7916 
7917 
7918 /*
7919  * called internally to return a LUN given a target and a LUN number
7920  */
7921 static struct fcp_lun *
7922 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7923 {
7924         struct fcp_lun  *plun;
7925 
7926         mutex_enter(&ptgt->tgt_mutex);
7927         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7928                 if (plun->lun_num == lun_num) {
7929                         mutex_exit(&ptgt->tgt_mutex);
7930                         return (plun);
7931                 }
7932         }
7933         mutex_exit(&ptgt->tgt_mutex);
7934 
7935         return (NULL);
7936 }
7937 
7938 
7939 /*
7940  * handle finishing one target for fcp_finish_init
7941  *
7942  * return true (non-zero) if we want finish_init to continue with the
7943  * next target
7944  *
7945  * called with the port mutex held
7946  */
7947 /*ARGSUSED*/
7948 static int
7949 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7950     int link_cnt, int tgt_cnt, int cause)
7951 {
7952         int     rval = 1;
7953         ASSERT(pptr != NULL);
7954         ASSERT(ptgt != NULL);
7955 
7956         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7957             fcp_trace, FCP_BUF_LEVEL_5, 0,
7958             "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7959             ptgt->tgt_state);
7960 
7961         ASSERT(mutex_owned(&pptr->port_mutex));
7962 
7963         if ((pptr->port_link_cnt != link_cnt) ||
7964             (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7965                 /*
7966                  * oh oh -- another link reset or target change
7967                  * must have occurred while we are in here
7968                  */
7969                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7970 
7971                 return (0);
7972         } else {
7973                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7974         }
7975 
7976         mutex_enter(&ptgt->tgt_mutex);
7977 
7978         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7979                 /*
7980                  * tgt is not offline -- is it marked (i.e. needs
7981                  * to be offlined) ??
7982                  */
7983                 if (ptgt->tgt_state & FCP_TGT_MARK) {
7984                         /*
7985                          * this target not offline *and*
7986                          * marked
7987                          */
7988                         ptgt->tgt_state &= ~FCP_TGT_MARK;
7989                         rval = fcp_offline_target(pptr, ptgt, link_cnt,
7990                             tgt_cnt, 0, 0);
7991                 } else {
7992                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
7993 
7994                         /* create the LUNs */
7995                         if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7996                                 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7997                                 fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7998                                     cause);
7999                                 ptgt->tgt_device_created = 1;
8000                         } else {
8001                                 fcp_update_tgt_state(ptgt, FCP_RESET,
8002                                     FCP_LUN_BUSY);
8003                         }
8004                 }
8005         }
8006 
8007         mutex_exit(&ptgt->tgt_mutex);
8008 
8009         return (rval);
8010 }
8011 
8012 
8013 /*
8014  * this routine is called to finish port initialization
8015  *
8016  * Each port has a "temp" counter -- when a state change happens (e.g.
8017  * port online), the temp count is set to the number of devices in the map.
8018  * Then, as each device gets "discovered", the temp counter is decremented
8019  * by one.  When this count reaches zero we know that all of the devices
8020  * in the map have been discovered (or an error has occurred), so we can
8021  * then finish initialization -- which is done by this routine (well, this
8022  * and fcp-finish_tgt())
8023  *
8024  * acquires and releases the global mutex
8025  *
8026  * called with the port mutex owned
8027  */
8028 static void
8029 fcp_finish_init(struct fcp_port *pptr)
8030 {
8031 #ifdef  DEBUG
8032         bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8033         pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8034             FCP_STACK_DEPTH);
8035 #endif /* DEBUG */
8036 
8037         ASSERT(mutex_owned(&pptr->port_mutex));
8038 
8039         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8040             fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8041             " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8042 
8043         if ((pptr->port_state & FCP_STATE_ONLINING) &&
8044             !(pptr->port_state & (FCP_STATE_SUSPENDED |
8045             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8046                 pptr->port_state &= ~FCP_STATE_ONLINING;
8047                 pptr->port_state |= FCP_STATE_ONLINE;
8048         }
8049 
8050         /* Wake up threads waiting on config done */
8051         cv_broadcast(&pptr->port_config_cv);
8052 }
8053 
8054 
8055 /*
8056  * called from fcp_finish_init to create the LUNs for a target
8057  *
8058  * called with the port mutex owned
8059  */
8060 static void
8061 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8062 {
8063         struct fcp_lun  *plun;
8064         struct fcp_port *pptr;
8065         child_info_t            *cip = NULL;
8066 
8067         ASSERT(ptgt != NULL);
8068         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8069 
8070         pptr = ptgt->tgt_port;
8071 
8072         ASSERT(pptr != NULL);
8073 
8074         /* scan all LUNs for this target */
8075         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8076                 if (plun->lun_state & FCP_LUN_OFFLINE) {
8077                         continue;
8078                 }
8079 
8080                 if (plun->lun_state & FCP_LUN_MARK) {
8081                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8082                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8083                             "fcp_create_luns: offlining marked LUN!");
8084                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8085                         continue;
8086                 }
8087 
8088                 plun->lun_state &= ~FCP_LUN_BUSY;
8089 
8090                 /*
8091                  * There are conditions in which FCP_LUN_INIT flag is cleared
8092                  * but we have a valid plun->lun_cip. To cover this case also
8093                  * CLEAR_BUSY whenever we have a valid lun_cip.
8094                  */
8095                 if (plun->lun_mpxio && plun->lun_cip &&
8096                     (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8097                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8098                     0, 0))) {
8099                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8100                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8101                             "fcp_create_luns: enable lun %p failed!",
8102                             plun);
8103                 }
8104 
8105                 if (plun->lun_state & FCP_LUN_INIT &&
8106                     !(plun->lun_state & FCP_LUN_CHANGED)) {
8107                         continue;
8108                 }
8109 
8110                 if (cause == FCP_CAUSE_USER_CREATE) {
8111                         continue;
8112                 }
8113 
8114                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8115                     fcp_trace, FCP_BUF_LEVEL_6, 0,
8116                     "create_luns: passing ONLINE elem to HP thread");
8117 
8118                 /*
8119                  * If lun has changed, prepare for offlining the old path.
8120                  * Do not offline the old path right now, since it may be
8121                  * still opened.
8122                  */
8123                 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8124                         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8125                 }
8126 
8127                 /* pass an ONLINE element to the hotplug thread */
8128                 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8129                     link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8130 
8131                         /*
8132                          * We can not synchronous attach (i.e pass
8133                          * NDI_ONLINE_ATTACH) here as we might be
8134                          * coming from an interrupt or callback
8135                          * thread.
8136                          */
8137                         if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8138                             link_cnt, tgt_cnt, 0, 0)) {
8139                                 fcp_log(CE_CONT, pptr->port_dip,
8140                                     "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8141                                     plun->lun_tgt->tgt_d_id, plun->lun_num);
8142                         }
8143                 }
8144         }
8145 }
8146 
8147 
8148 /*
8149  * function to online/offline devices
8150  */
8151 static int
8152 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8153     int online, int lcount, int tcount, int flags)
8154 {
8155         int                     rval = NDI_FAILURE;
8156         int                     circ;
8157         child_info_t            *ccip;
8158         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
8159         int                     is_mpxio = pptr->port_mpxio;
8160 
8161         if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8162                 /*
8163                  * When this event gets serviced, lun_cip and lun_mpxio
8164                  * has changed, so it should be invalidated now.
8165                  */
8166                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8167                     FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8168                     "plun: %p, cip: %p, what:%d", plun, cip, online);
8169                 return (rval);
8170         }
8171 
8172         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8173             fcp_trace, FCP_BUF_LEVEL_2, 0,
8174             "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8175             "flags=%x mpxio=%x\n",
8176             plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8177             plun->lun_mpxio);
8178 
8179         /*
8180          * lun_mpxio needs checking here because we can end up in a race
8181          * condition where this task has been dispatched while lun_mpxio is
8182          * set, but an earlier FCP_ONLINE task for the same LUN tried to
8183          * enable MPXIO for the LUN, but was unable to, and hence cleared
8184          * the flag. We rely on the serialization of the tasks here. We return
8185          * NDI_SUCCESS so any callers continue without reporting spurious
8186          * errors, and the still think we're an MPXIO LUN.
8187          */
8188 
8189         if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8190             online == FCP_MPXIO_PATH_SET_BUSY) {
8191                 if (plun->lun_mpxio) {
8192                         rval = fcp_update_mpxio_path(plun, cip, online);
8193                 } else {
8194                         rval = NDI_SUCCESS;
8195                 }
8196                 return (rval);
8197         }
8198 
8199         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8200                 return (NDI_FAILURE);
8201         }
8202 
8203         if (is_mpxio) {
8204                 mdi_devi_enter(pptr->port_dip, &circ);
8205         } else {
8206                 ndi_devi_enter(pptr->port_dip, &circ);
8207         }
8208 
8209         mutex_enter(&pptr->port_mutex);
8210         mutex_enter(&plun->lun_mutex);
8211 
8212         if (online == FCP_ONLINE) {
8213                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8214                 if (ccip == NULL) {
8215                         goto fail;
8216                 }
8217         } else {
8218                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8219                         goto fail;
8220                 }
8221                 ccip = cip;
8222         }
8223 
8224         if (online == FCP_ONLINE) {
8225                 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8226                     &circ);
8227                 fc_ulp_log_device_event(pptr->port_fp_handle,
8228                     FC_ULP_DEVICE_ONLINE);
8229         } else {
8230                 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8231                     &circ);
8232                 fc_ulp_log_device_event(pptr->port_fp_handle,
8233                     FC_ULP_DEVICE_OFFLINE);
8234         }
8235 
8236 fail:   mutex_exit(&plun->lun_mutex);
8237         mutex_exit(&pptr->port_mutex);
8238 
8239         if (is_mpxio) {
8240                 mdi_devi_exit(pptr->port_dip, circ);
8241         } else {
8242                 ndi_devi_exit(pptr->port_dip, circ);
8243         }
8244 
8245         fc_ulp_idle_port(pptr->port_fp_handle);
8246 
8247         return (rval);
8248 }
8249 
8250 
8251 /*
8252  * take a target offline by taking all of its LUNs offline
8253  */
8254 /*ARGSUSED*/
8255 static int
8256 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8257     int link_cnt, int tgt_cnt, int nowait, int flags)
8258 {
8259         struct fcp_tgt_elem     *elem;
8260 
8261         ASSERT(mutex_owned(&pptr->port_mutex));
8262         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8263 
8264         ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8265 
8266         if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8267             ptgt->tgt_change_cnt)) {
8268                 mutex_exit(&ptgt->tgt_mutex);
8269                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8270                 mutex_enter(&ptgt->tgt_mutex);
8271 
8272                 return (0);
8273         }
8274 
8275         ptgt->tgt_pd_handle = NULL;
8276         mutex_exit(&ptgt->tgt_mutex);
8277         FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8278         mutex_enter(&ptgt->tgt_mutex);
8279 
8280         tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8281 
8282         if (ptgt->tgt_tcap &&
8283             (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8284                 elem->flags = flags;
8285                 elem->time = fcp_watchdog_time;
8286                 if (nowait == 0) {
8287                         elem->time += fcp_offline_delay;
8288                 }
8289                 elem->ptgt = ptgt;
8290                 elem->link_cnt = link_cnt;
8291                 elem->tgt_cnt = tgt_cnt;
8292                 elem->next = pptr->port_offline_tgts;
8293                 pptr->port_offline_tgts = elem;
8294         } else {
8295                 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8296         }
8297 
8298         return (1);
8299 }
8300 
8301 
8302 static void
8303 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8304     int link_cnt, int tgt_cnt, int flags)
8305 {
8306         ASSERT(mutex_owned(&pptr->port_mutex));
8307         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8308 
8309         fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8310         ptgt->tgt_state = FCP_TGT_OFFLINE;
8311         ptgt->tgt_pd_handle = NULL;
8312         fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8313 }
8314 
8315 
8316 static void
8317 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8318     int flags)
8319 {
8320         struct  fcp_lun *plun;
8321 
8322         ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8323         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8324 
8325         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8326                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8327                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8328                 }
8329         }
8330 }
8331 
8332 
8333 /*
8334  * take a LUN offline
8335  *
8336  * enters and leaves with the target mutex held, releasing it in the process
8337  *
8338  * allocates memory in non-sleep mode
8339  */
8340 static void
8341 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8342     int nowait, int flags)
8343 {
8344         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
8345         struct fcp_lun_elem     *elem;
8346 
8347         ASSERT(plun != NULL);
8348         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8349 
8350         if (nowait) {
8351                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8352                 return;
8353         }
8354 
8355         if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8356                 elem->flags = flags;
8357                 elem->time = fcp_watchdog_time;
8358                 if (nowait == 0) {
8359                         elem->time += fcp_offline_delay;
8360                 }
8361                 elem->plun = plun;
8362                 elem->link_cnt = link_cnt;
8363                 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8364                 elem->next = pptr->port_offline_luns;
8365                 pptr->port_offline_luns = elem;
8366         } else {
8367                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8368         }
8369 }
8370 
8371 
8372 static void
8373 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8374 {
8375         struct fcp_pkt  *head = NULL;
8376 
8377         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8378 
8379         mutex_exit(&LUN_TGT->tgt_mutex);
8380 
8381         head = fcp_scan_commands(plun);
8382         if (head != NULL) {
8383                 fcp_abort_commands(head, LUN_PORT);
8384         }
8385 
8386         mutex_enter(&LUN_TGT->tgt_mutex);
8387 
8388         if (plun->lun_cip && plun->lun_mpxio) {
8389                 /*
8390                  * Intimate MPxIO lun busy is cleared
8391                  */
8392                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8393                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8394                     0, 0)) {
8395                         fcp_log(CE_NOTE, LUN_PORT->port_dip,
8396                             "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8397                             LUN_TGT->tgt_d_id, plun->lun_num);
8398                 }
8399                 /*
8400                  * Intimate MPxIO that the lun is now marked for offline
8401                  */
8402                 mutex_exit(&LUN_TGT->tgt_mutex);
8403                 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8404                 mutex_enter(&LUN_TGT->tgt_mutex);
8405         }
8406 }
8407 
8408 static void
8409 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8410     int flags)
8411 {
8412         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8413 
8414         mutex_exit(&LUN_TGT->tgt_mutex);
8415         fcp_update_offline_flags(plun);
8416         mutex_enter(&LUN_TGT->tgt_mutex);
8417 
8418         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8419 
8420         FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8421             fcp_trace, FCP_BUF_LEVEL_4, 0,
8422             "offline_lun: passing OFFLINE elem to HP thread");
8423 
8424         if (plun->lun_cip) {
8425                 fcp_log(CE_NOTE, LUN_PORT->port_dip,
8426                     "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8427                     plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8428                     LUN_TGT->tgt_trace);
8429 
8430                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8431                     link_cnt, tgt_cnt, flags, 0)) {
8432                         fcp_log(CE_CONT, LUN_PORT->port_dip,
8433                             "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8434                             LUN_TGT->tgt_d_id, plun->lun_num);
8435                 }
8436         }
8437 }
8438 
8439 static void
8440 fcp_scan_offline_luns(struct fcp_port *pptr)
8441 {
8442         struct fcp_lun_elem     *elem;
8443         struct fcp_lun_elem     *prev;
8444         struct fcp_lun_elem     *next;
8445 
8446         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8447 
8448         prev = NULL;
8449         elem = pptr->port_offline_luns;
8450         while (elem) {
8451                 next = elem->next;
8452                 if (elem->time <= fcp_watchdog_time) {
8453                         int                     changed = 1;
8454                         struct fcp_tgt  *ptgt = elem->plun->lun_tgt;
8455 
8456                         mutex_enter(&ptgt->tgt_mutex);
8457                         if (pptr->port_link_cnt == elem->link_cnt &&
8458                             ptgt->tgt_change_cnt == elem->tgt_cnt) {
8459                                 changed = 0;
8460                         }
8461 
8462                         if (!changed &&
8463                             !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8464                                 fcp_offline_lun_now(elem->plun,
8465                                     elem->link_cnt, elem->tgt_cnt, elem->flags);
8466                         }
8467                         mutex_exit(&ptgt->tgt_mutex);
8468 
8469                         kmem_free(elem, sizeof (*elem));
8470 
8471                         if (prev) {
8472                                 prev->next = next;
8473                         } else {
8474                                 pptr->port_offline_luns = next;
8475                         }
8476                 } else {
8477                         prev = elem;
8478                 }
8479                 elem = next;
8480         }
8481 }
8482 
8483 
8484 static void
8485 fcp_scan_offline_tgts(struct fcp_port *pptr)
8486 {
8487         struct fcp_tgt_elem     *elem;
8488         struct fcp_tgt_elem     *prev;
8489         struct fcp_tgt_elem     *next;
8490 
8491         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8492 
8493         prev = NULL;
8494         elem = pptr->port_offline_tgts;
8495         while (elem) {
8496                 next = elem->next;
8497                 if (elem->time <= fcp_watchdog_time) {
8498                         int             outdated = 1;
8499                         struct fcp_tgt  *ptgt = elem->ptgt;
8500 
8501                         mutex_enter(&ptgt->tgt_mutex);
8502 
8503                         if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8504                                 /* No change on tgt since elem was created. */
8505                                 outdated = 0;
8506                         } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8507                             pptr->port_link_cnt == elem->link_cnt + 1 &&
8508                             ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8509                                 /*
8510                                  * Exactly one thing happened to the target
8511                                  * inbetween: the local port went offline.
8512                                  * For fp the remote port is already gone so
8513                                  * it will not tell us again to offline the
8514                                  * target. We must offline it now.
8515                                  */
8516                                 outdated = 0;
8517                         }
8518 
8519                         if (!outdated && !(ptgt->tgt_state &
8520                             FCP_TGT_OFFLINE)) {
8521                                 fcp_offline_target_now(pptr,
8522                                     ptgt, elem->link_cnt, elem->tgt_cnt,
8523                                     elem->flags);
8524                         }
8525 
8526                         mutex_exit(&ptgt->tgt_mutex);
8527 
8528                         kmem_free(elem, sizeof (*elem));
8529 
8530                         if (prev) {
8531                                 prev->next = next;
8532                         } else {
8533                                 pptr->port_offline_tgts = next;
8534                         }
8535                 } else {
8536                         prev = elem;
8537                 }
8538                 elem = next;
8539         }
8540 }
8541 
8542 
8543 static void
8544 fcp_update_offline_flags(struct fcp_lun *plun)
8545 {
8546         struct fcp_port *pptr = LUN_PORT;
8547         ASSERT(plun != NULL);
8548 
8549         mutex_enter(&LUN_TGT->tgt_mutex);
8550         plun->lun_state |= FCP_LUN_OFFLINE;
8551         plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8552 
8553         mutex_enter(&plun->lun_mutex);
8554         if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8555                 dev_info_t *cdip = NULL;
8556 
8557                 mutex_exit(&LUN_TGT->tgt_mutex);
8558 
8559                 if (plun->lun_mpxio == 0) {
8560                         cdip = DIP(plun->lun_cip);
8561                 } else if (plun->lun_cip) {
8562                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8563                 }
8564 
8565                 mutex_exit(&plun->lun_mutex);
8566                 if (cdip) {
8567                         (void) ndi_event_retrieve_cookie(
8568                             pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8569                             &fcp_remove_eid, NDI_EVENT_NOPASS);
8570                         (void) ndi_event_run_callbacks(
8571                             pptr->port_ndi_event_hdl, cdip,
8572                             fcp_remove_eid, NULL);
8573                 }
8574         } else {
8575                 mutex_exit(&plun->lun_mutex);
8576                 mutex_exit(&LUN_TGT->tgt_mutex);
8577         }
8578 }
8579 
8580 
8581 /*
8582  * Scan all of the command pkts for this port, moving pkts that
8583  * match our LUN onto our own list (headed by "head")
8584  */
8585 static struct fcp_pkt *
8586 fcp_scan_commands(struct fcp_lun *plun)
8587 {
8588         struct fcp_port *pptr = LUN_PORT;
8589 
8590         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8591         struct fcp_pkt  *ncmd = NULL;   /* next pkt ptr */
8592         struct fcp_pkt  *pcmd = NULL;   /* the previous command */
8593 
8594         struct fcp_pkt  *head = NULL;   /* head of our list */
8595         struct fcp_pkt  *tail = NULL;   /* tail of our list */
8596 
8597         int                     cmds_found = 0;
8598 
8599         mutex_enter(&pptr->port_pkt_mutex);
8600         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8601                 struct fcp_lun *tlun =
8602                     ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8603 
8604                 ncmd = cmd->cmd_next;        /* set next command */
8605 
8606                 /*
8607                  * if this pkt is for a different LUN  or the
8608                  * command is sent down, skip it.
8609                  */
8610                 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8611                     (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8612                         pcmd = cmd;
8613                         continue;
8614                 }
8615                 cmds_found++;
8616                 if (pcmd != NULL) {
8617                         ASSERT(pptr->port_pkt_head != cmd);
8618                         pcmd->cmd_next = cmd->cmd_next;
8619                 } else {
8620                         ASSERT(cmd == pptr->port_pkt_head);
8621                         pptr->port_pkt_head = cmd->cmd_next;
8622                 }
8623 
8624                 if (cmd == pptr->port_pkt_tail) {
8625                         pptr->port_pkt_tail = pcmd;
8626                         if (pcmd) {
8627                                 pcmd->cmd_next = NULL;
8628                         }
8629                 }
8630 
8631                 if (head == NULL) {
8632                         head = tail = cmd;
8633                 } else {
8634                         ASSERT(tail != NULL);
8635 
8636                         tail->cmd_next = cmd;
8637                         tail = cmd;
8638                 }
8639                 cmd->cmd_next = NULL;
8640         }
8641         mutex_exit(&pptr->port_pkt_mutex);
8642 
8643         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8644             fcp_trace, FCP_BUF_LEVEL_8, 0,
8645             "scan commands: %d cmd(s) found", cmds_found);
8646 
8647         return (head);
8648 }
8649 
8650 
8651 /*
8652  * Abort all the commands in the command queue
8653  */
8654 static void
8655 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8656 {
8657         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8658         struct  fcp_pkt *ncmd = NULL;   /* next pkt ptr */
8659 
8660         ASSERT(mutex_owned(&pptr->port_mutex));
8661 
8662         /* scan through the pkts and invalid them */
8663         for (cmd = head; cmd != NULL; cmd = ncmd) {
8664                 struct scsi_pkt *pkt = cmd->cmd_pkt;
8665 
8666                 ncmd = cmd->cmd_next;
8667                 ASSERT(pkt != NULL);
8668 
8669                 /*
8670                  * The lun is going to be marked offline. Indicate
8671                  * the target driver not to requeue or retry this command
8672                  * as the device is going to be offlined pretty soon.
8673                  */
8674                 pkt->pkt_reason = CMD_DEV_GONE;
8675                 pkt->pkt_statistics = 0;
8676                 pkt->pkt_state = 0;
8677 
8678                 /* reset cmd flags/state */
8679                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8680                 cmd->cmd_state = FCP_PKT_IDLE;
8681 
8682                 /*
8683                  * ensure we have a packet completion routine,
8684                  * then call it.
8685                  */
8686                 ASSERT(pkt->pkt_comp != NULL);
8687 
8688                 mutex_exit(&pptr->port_mutex);
8689                 fcp_post_callback(cmd);
8690                 mutex_enter(&pptr->port_mutex);
8691         }
8692 }
8693 
8694 
8695 /*
8696  * the pkt_comp callback for command packets
8697  */
8698 static void
8699 fcp_cmd_callback(fc_packet_t *fpkt)
8700 {
8701         struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8702         struct scsi_pkt *pkt = cmd->cmd_pkt;
8703         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8704 
8705         ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8706 
8707         if (cmd->cmd_state == FCP_PKT_IDLE) {
8708                 cmn_err(CE_PANIC, "Packet already completed %p",
8709                     (void *)cmd);
8710         }
8711 
8712         /*
8713          * Watch thread should be freeing the packet, ignore the pkt.
8714          */
8715         if (cmd->cmd_state == FCP_PKT_ABORTING) {
8716                 fcp_log(CE_CONT, pptr->port_dip,
8717                     "!FCP: Pkt completed while aborting\n");
8718                 return;
8719         }
8720         cmd->cmd_state = FCP_PKT_IDLE;
8721 
8722         fcp_complete_pkt(fpkt);
8723 
8724 #ifdef  DEBUG
8725         mutex_enter(&pptr->port_pkt_mutex);
8726         pptr->port_npkts--;
8727         mutex_exit(&pptr->port_pkt_mutex);
8728 #endif /* DEBUG */
8729 
8730         fcp_post_callback(cmd);
8731 }
8732 
8733 
8734 static void
8735 fcp_complete_pkt(fc_packet_t *fpkt)
8736 {
8737         int                     error = 0;
8738         struct fcp_pkt  *cmd = (struct fcp_pkt *)
8739             fpkt->pkt_ulp_private;
8740         struct scsi_pkt         *pkt = cmd->cmd_pkt;
8741         struct fcp_port         *pptr = ADDR2FCP(&pkt->pkt_address);
8742         struct fcp_lun  *plun;
8743         struct fcp_tgt  *ptgt;
8744         struct fcp_rsp          *rsp;
8745         struct scsi_address     save;
8746 
8747 #ifdef  DEBUG
8748         save = pkt->pkt_address;
8749 #endif /* DEBUG */
8750 
8751         rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8752 
8753         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8754                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8755                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8756                             sizeof (struct fcp_rsp));
8757                 }
8758 
8759                 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8760                     STATE_SENT_CMD | STATE_GOT_STATUS;
8761 
8762                 pkt->pkt_resid = 0;
8763 
8764                 if (fpkt->pkt_datalen) {
8765                         pkt->pkt_state |= STATE_XFERRED_DATA;
8766                         if (fpkt->pkt_data_resid) {
8767                                 error++;
8768                         }
8769                 }
8770 
8771                 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8772                     rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8773                         /*
8774                          * The next two checks make sure that if there
8775                          * is no sense data or a valid response and
8776                          * the command came back with check condition,
8777                          * the command should be retried.
8778                          */
8779                         if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8780                             !rsp->fcp_u.fcp_status.sense_len_set) {
8781                                 pkt->pkt_state &= ~STATE_XFERRED_DATA;
8782                                 pkt->pkt_resid = cmd->cmd_dmacount;
8783                         }
8784                 }
8785 
8786                 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8787                         return;
8788                 }
8789 
8790                 plun = ADDR2LUN(&pkt->pkt_address);
8791                 ptgt = plun->lun_tgt;
8792                 ASSERT(ptgt != NULL);
8793 
8794                 /*
8795                  * Update the transfer resid, if appropriate
8796                  */
8797                 if (rsp->fcp_u.fcp_status.resid_over ||
8798                     rsp->fcp_u.fcp_status.resid_under) {
8799                         pkt->pkt_resid = rsp->fcp_resid;
8800                 }
8801 
8802                 /*
8803                  * First see if we got a FCP protocol error.
8804                  */
8805                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
8806                         struct fcp_rsp_info     *bep;
8807                         bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8808                             sizeof (struct fcp_rsp));
8809 
8810                         if (fcp_validate_fcp_response(rsp, pptr) !=
8811                             FC_SUCCESS) {
8812                                 pkt->pkt_reason = CMD_CMPLT;
8813                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8814 
8815                                 fcp_log(CE_WARN, pptr->port_dip,
8816                                     "!SCSI command to d_id=0x%x lun=0x%x"
8817                                     " failed, Bad FCP response values:"
8818                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8819                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8820                                     ptgt->tgt_d_id, plun->lun_num,
8821                                     rsp->reserved_0, rsp->reserved_1,
8822                                     rsp->fcp_u.fcp_status.reserved_0,
8823                                     rsp->fcp_u.fcp_status.reserved_1,
8824                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8825 
8826                                 return;
8827                         }
8828 
8829                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8830                                 FCP_CP_IN(fpkt->pkt_resp +
8831                                     sizeof (struct fcp_rsp), bep,
8832                                     fpkt->pkt_resp_acc,
8833                                     sizeof (struct fcp_rsp_info));
8834                         }
8835 
8836                         if (bep->rsp_code != FCP_NO_FAILURE) {
8837                                 child_info_t    *cip;
8838 
8839                                 pkt->pkt_reason = CMD_TRAN_ERR;
8840 
8841                                 mutex_enter(&plun->lun_mutex);
8842                                 cip = plun->lun_cip;
8843                                 mutex_exit(&plun->lun_mutex);
8844 
8845                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8846                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
8847                                     "FCP response error on cmd=%p"
8848                                     " target=0x%x, cip=%p", cmd,
8849                                     ptgt->tgt_d_id, cip);
8850                         }
8851                 }
8852 
8853                 /*
8854                  * See if we got a SCSI error with sense data
8855                  */
8856                 if (rsp->fcp_u.fcp_status.sense_len_set) {
8857                         uchar_t                         rqlen;
8858                         caddr_t                         sense_from;
8859                         child_info_t                    *cip;
8860                         timeout_id_t                    tid;
8861                         struct scsi_arq_status          *arq;
8862                         struct scsi_extended_sense      *sense_to;
8863 
8864                         arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8865                         sense_to = &arq->sts_sensedata;
8866 
8867                         rqlen = (uchar_t)min(rsp->fcp_sense_len,
8868                             sizeof (struct scsi_extended_sense));
8869 
8870                         sense_from = (caddr_t)fpkt->pkt_resp +
8871                             sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8872 
8873                         if (fcp_validate_fcp_response(rsp, pptr) !=
8874                             FC_SUCCESS) {
8875                                 pkt->pkt_reason = CMD_CMPLT;
8876                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8877 
8878                                 fcp_log(CE_WARN, pptr->port_dip,
8879                                     "!SCSI command to d_id=0x%x lun=0x%x"
8880                                     " failed, Bad FCP response values:"
8881                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8882                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8883                                     ptgt->tgt_d_id, plun->lun_num,
8884                                     rsp->reserved_0, rsp->reserved_1,
8885                                     rsp->fcp_u.fcp_status.reserved_0,
8886                                     rsp->fcp_u.fcp_status.reserved_1,
8887                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8888 
8889                                 return;
8890                         }
8891 
8892                         /*
8893                          * copy in sense information
8894                          */
8895                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8896                                 FCP_CP_IN(sense_from, sense_to,
8897                                     fpkt->pkt_resp_acc, rqlen);
8898                         } else {
8899                                 bcopy(sense_from, sense_to, rqlen);
8900                         }
8901 
8902                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8903                             (FCP_SENSE_NO_LUN(sense_to))) {
8904                                 mutex_enter(&ptgt->tgt_mutex);
8905                                 if (ptgt->tgt_tid == NULL) {
8906                                         /*
8907                                          * Kick off rediscovery
8908                                          */
8909                                         tid = timeout(fcp_reconfigure_luns,
8910                                             (caddr_t)ptgt, drv_usectohz(1));
8911 
8912                                         ptgt->tgt_tid = tid;
8913                                         ptgt->tgt_state |= FCP_TGT_BUSY;
8914                                 }
8915                                 mutex_exit(&ptgt->tgt_mutex);
8916                                 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8917                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8918                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8919                                             "!FCP: Report Lun Has Changed"
8920                                             " target=%x", ptgt->tgt_d_id);
8921                                 } else if (FCP_SENSE_NO_LUN(sense_to)) {
8922                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8923                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8924                                             "!FCP: LU Not Supported"
8925                                             " target=%x", ptgt->tgt_d_id);
8926                                 }
8927                         }
8928                         ASSERT(pkt->pkt_scbp != NULL);
8929 
8930                         pkt->pkt_state |= STATE_ARQ_DONE;
8931 
8932                         arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8933 
8934                         *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8935                         arq->sts_rqpkt_reason = 0;
8936                         arq->sts_rqpkt_statistics = 0;
8937 
8938                         arq->sts_rqpkt_state = STATE_GOT_BUS |
8939                             STATE_GOT_TARGET | STATE_SENT_CMD |
8940                             STATE_GOT_STATUS | STATE_ARQ_DONE |
8941                             STATE_XFERRED_DATA;
8942 
8943                         mutex_enter(&plun->lun_mutex);
8944                         cip = plun->lun_cip;
8945                         mutex_exit(&plun->lun_mutex);
8946 
8947                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8948                             fcp_trace, FCP_BUF_LEVEL_8, 0,
8949                             "SCSI Check condition on cmd=%p target=0x%x"
8950                             " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
8951                             " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
8952                             cmd->cmd_fcp_cmd.fcp_cdb[0],
8953                             rsp->fcp_u.fcp_status.scsi_status,
8954                             sense_to->es_key, sense_to->es_add_code,
8955                             sense_to->es_qual_code);
8956                 }
8957         } else {
8958                 plun = ADDR2LUN(&pkt->pkt_address);
8959                 ptgt = plun->lun_tgt;
8960                 ASSERT(ptgt != NULL);
8961 
8962                 /*
8963                  * Work harder to translate errors into target driver
8964                  * understandable ones. Note with despair that the target
8965                  * drivers don't decode pkt_state and pkt_reason exhaustively
8966                  * They resort to using the big hammer most often, which
8967                  * may not get fixed in the life time of this driver.
8968                  */
8969                 pkt->pkt_state = 0;
8970                 pkt->pkt_statistics = 0;
8971 
8972                 switch (fpkt->pkt_state) {
8973                 case FC_PKT_TRAN_ERROR:
8974                         switch (fpkt->pkt_reason) {
8975                         case FC_REASON_OVERRUN:
8976                                 pkt->pkt_reason = CMD_CMD_OVR;
8977                                 pkt->pkt_statistics |= STAT_ABORTED;
8978                                 break;
8979 
8980                         case FC_REASON_XCHG_BSY: {
8981                                 caddr_t ptr;
8982 
8983                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
8984 
8985                                 ptr = (caddr_t)pkt->pkt_scbp;
8986                                 if (ptr) {
8987                                         *ptr = STATUS_BUSY;
8988                                 }
8989                                 break;
8990                         }
8991 
8992                         case FC_REASON_ABORTED:
8993                                 pkt->pkt_reason = CMD_TRAN_ERR;
8994                                 pkt->pkt_statistics |= STAT_ABORTED;
8995                                 break;
8996 
8997                         case FC_REASON_ABORT_FAILED:
8998                                 pkt->pkt_reason = CMD_ABORT_FAIL;
8999                                 break;
9000 
9001                         case FC_REASON_NO_SEQ_INIT:
9002                         case FC_REASON_CRC_ERROR:
9003                                 pkt->pkt_reason = CMD_TRAN_ERR;
9004                                 pkt->pkt_statistics |= STAT_ABORTED;
9005                                 break;
9006                         default:
9007                                 pkt->pkt_reason = CMD_TRAN_ERR;
9008                                 break;
9009                         }
9010                         break;
9011 
9012                 case FC_PKT_PORT_OFFLINE: {
9013                         dev_info_t      *cdip = NULL;
9014                         caddr_t         ptr;
9015 
9016                         if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9017                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9018                                     fcp_trace, FCP_BUF_LEVEL_8, 0,
9019                                     "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9020                                     ptgt->tgt_d_id);
9021                         }
9022 
9023                         mutex_enter(&plun->lun_mutex);
9024                         if (plun->lun_mpxio == 0) {
9025                                 cdip = DIP(plun->lun_cip);
9026                         } else if (plun->lun_cip) {
9027                                 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9028                         }
9029 
9030                         mutex_exit(&plun->lun_mutex);
9031 
9032                         if (cdip) {
9033                                 (void) ndi_event_retrieve_cookie(
9034                                     pptr->port_ndi_event_hdl, cdip,
9035                                     FCAL_REMOVE_EVENT, &fcp_remove_eid,
9036                                     NDI_EVENT_NOPASS);
9037                                 (void) ndi_event_run_callbacks(
9038                                     pptr->port_ndi_event_hdl, cdip,
9039                                     fcp_remove_eid, NULL);
9040                         }
9041 
9042                         /*
9043                          * If the link goes off-line for a lip,
9044                          * this will cause a error to the ST SG
9045                          * SGEN drivers. By setting BUSY we will
9046                          * give the drivers the chance to retry
9047                          * before it blows of the job. ST will
9048                          * remember how many times it has retried.
9049                          */
9050 
9051                         if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9052                             (plun->lun_type == DTYPE_CHANGER)) {
9053                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9054                                 ptr = (caddr_t)pkt->pkt_scbp;
9055                                 if (ptr) {
9056                                         *ptr = STATUS_BUSY;
9057                                 }
9058                         } else {
9059                                 pkt->pkt_reason = CMD_TRAN_ERR;
9060                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9061                         }
9062                         break;
9063                 }
9064 
9065                 case FC_PKT_TRAN_BSY:
9066                         /*
9067                          * Use the ssd Qfull handling here.
9068                          */
9069                         *pkt->pkt_scbp = STATUS_INTERMEDIATE;
9070                         pkt->pkt_state = STATE_GOT_BUS;
9071                         break;
9072 
9073                 case FC_PKT_TIMEOUT:
9074                         pkt->pkt_reason = CMD_TIMEOUT;
9075                         if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9076                                 pkt->pkt_statistics |= STAT_TIMEOUT;
9077                         } else {
9078                                 pkt->pkt_statistics |= STAT_ABORTED;
9079                         }
9080                         break;
9081 
9082                 case FC_PKT_LOCAL_RJT:
9083                         switch (fpkt->pkt_reason) {
9084                         case FC_REASON_OFFLINE: {
9085                                 dev_info_t      *cdip = NULL;
9086 
9087                                 mutex_enter(&plun->lun_mutex);
9088                                 if (plun->lun_mpxio == 0) {
9089                                         cdip = DIP(plun->lun_cip);
9090                                 } else if (plun->lun_cip) {
9091                                         cdip = mdi_pi_get_client(
9092                                             PIP(plun->lun_cip));
9093                                 }
9094                                 mutex_exit(&plun->lun_mutex);
9095 
9096                                 if (cdip) {
9097                                         (void) ndi_event_retrieve_cookie(
9098                                             pptr->port_ndi_event_hdl, cdip,
9099                                             FCAL_REMOVE_EVENT,
9100                                             &fcp_remove_eid,
9101                                             NDI_EVENT_NOPASS);
9102                                         (void) ndi_event_run_callbacks(
9103                                             pptr->port_ndi_event_hdl,
9104                                             cdip, fcp_remove_eid, NULL);
9105                                 }
9106 
9107                                 pkt->pkt_reason = CMD_TRAN_ERR;
9108                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9109 
9110                                 break;
9111                         }
9112 
9113                         case FC_REASON_NOMEM:
9114                         case FC_REASON_QFULL: {
9115                                 caddr_t ptr;
9116 
9117                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9118                                 ptr = (caddr_t)pkt->pkt_scbp;
9119                                 if (ptr) {
9120                                         *ptr = STATUS_BUSY;
9121                                 }
9122                                 break;
9123                         }
9124 
9125                         case FC_REASON_DMA_ERROR:
9126                                 pkt->pkt_reason = CMD_DMA_DERR;
9127                                 pkt->pkt_statistics |= STAT_ABORTED;
9128                                 break;
9129 
9130                         case FC_REASON_CRC_ERROR:
9131                         case FC_REASON_UNDERRUN: {
9132                                 uchar_t         status;
9133                                 /*
9134                                  * Work around for Bugid: 4240945.
9135                                  * IB on A5k doesn't set the Underrun bit
9136                                  * in the fcp status, when it is transferring
9137                                  * less than requested amount of data. Work
9138                                  * around the ses problem to keep luxadm
9139                                  * happy till ibfirmware is fixed.
9140                                  */
9141                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9142                                         FCP_CP_IN(fpkt->pkt_resp, rsp,
9143                                             fpkt->pkt_resp_acc,
9144                                             sizeof (struct fcp_rsp));
9145                                 }
9146                                 status = rsp->fcp_u.fcp_status.scsi_status;
9147                                 if (((plun->lun_type & DTYPE_MASK) ==
9148                                     DTYPE_ESI) && (status == STATUS_GOOD)) {
9149                                         pkt->pkt_reason = CMD_CMPLT;
9150                                         *pkt->pkt_scbp = status;
9151                                         pkt->pkt_resid = 0;
9152                                 } else {
9153                                         pkt->pkt_reason = CMD_TRAN_ERR;
9154                                         pkt->pkt_statistics |= STAT_ABORTED;
9155                                 }
9156                                 break;
9157                         }
9158 
9159                         case FC_REASON_NO_CONNECTION:
9160                         case FC_REASON_UNSUPPORTED:
9161                         case FC_REASON_ILLEGAL_REQ:
9162                         case FC_REASON_BAD_SID:
9163                         case FC_REASON_DIAG_BUSY:
9164                         case FC_REASON_FCAL_OPN_FAIL:
9165                         case FC_REASON_BAD_XID:
9166                         default:
9167                                 pkt->pkt_reason = CMD_TRAN_ERR;
9168                                 pkt->pkt_statistics |= STAT_ABORTED;
9169                                 break;
9170 
9171                         }
9172                         break;
9173 
9174                 case FC_PKT_NPORT_RJT:
9175                 case FC_PKT_FABRIC_RJT:
9176                 case FC_PKT_NPORT_BSY:
9177                 case FC_PKT_FABRIC_BSY:
9178                 default:
9179                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9180                             fcp_trace, FCP_BUF_LEVEL_8, 0,
9181                             "FC Status 0x%x, reason 0x%x",
9182                             fpkt->pkt_state, fpkt->pkt_reason);
9183                         pkt->pkt_reason = CMD_TRAN_ERR;
9184                         pkt->pkt_statistics |= STAT_ABORTED;
9185                         break;
9186                 }
9187 
9188                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9189                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9190                     "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9191                     " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9192                     fpkt->pkt_reason);
9193         }
9194 
9195         ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9196 }
9197 
9198 
9199 static int
9200 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9201 {
9202         if (rsp->reserved_0 || rsp->reserved_1 ||
9203             rsp->fcp_u.fcp_status.reserved_0 ||
9204             rsp->fcp_u.fcp_status.reserved_1) {
9205                 /*
9206                  * These reserved fields should ideally be zero. FCP-2 does say
9207                  * that the recipient need not check for reserved fields to be
9208                  * zero. If they are not zero, we will not make a fuss about it
9209                  * - just log it (in debug to both trace buffer and messages
9210                  * file and to trace buffer only in non-debug) and move on.
9211                  *
9212                  * Non-zero reserved fields were seen with minnows.
9213                  *
9214                  * qlc takes care of some of this but we cannot assume that all
9215                  * FCAs will do so.
9216                  */
9217                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9218                     FCP_BUF_LEVEL_5, 0,
9219                     "Got fcp response packet with non-zero reserved fields "
9220                     "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9221                     "status.reserved_0:0x%x, status.reserved_1:0x%x",
9222                     rsp->reserved_0, rsp->reserved_1,
9223                     rsp->fcp_u.fcp_status.reserved_0,
9224                     rsp->fcp_u.fcp_status.reserved_1);
9225         }
9226 
9227         if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9228             (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9229                 return (FC_FAILURE);
9230         }
9231 
9232         if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9233             (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9234             sizeof (struct fcp_rsp))) {
9235                 return (FC_FAILURE);
9236         }
9237 
9238         return (FC_SUCCESS);
9239 }
9240 
9241 
9242 /*
9243  * This is called when there is a change the in device state. The case we're
9244  * handling here is, if the d_id s does not match, offline this tgt and online
9245  * a new tgt with the new d_id.  called from fcp_handle_devices with
9246  * port_mutex held.
9247  */
9248 static int
9249 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9250     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9251 {
9252         ASSERT(mutex_owned(&pptr->port_mutex));
9253 
9254         FCP_TRACE(fcp_logq, pptr->port_instbuf,
9255             fcp_trace, FCP_BUF_LEVEL_3, 0,
9256             "Starting fcp_device_changed...");
9257 
9258         /*
9259          * The two cases where the port_device_changed is called is
9260          * either it changes it's d_id or it's hard address.
9261          */
9262         if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9263             (FC_TOP_EXTERNAL(pptr->port_topology) &&
9264             (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9265 
9266                 /* offline this target */
9267                 mutex_enter(&ptgt->tgt_mutex);
9268                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9269                         (void) fcp_offline_target(pptr, ptgt, link_cnt,
9270                             0, 1, NDI_DEVI_REMOVE);
9271                 }
9272                 mutex_exit(&ptgt->tgt_mutex);
9273 
9274                 fcp_log(CE_NOTE, pptr->port_dip,
9275                     "Change in target properties: Old D_ID=%x New D_ID=%x"
9276                     " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9277                     map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9278                     map_entry->map_hard_addr.hard_addr);
9279         }
9280 
9281         return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9282             link_cnt, tgt_cnt, cause));
9283 }
9284 
9285 /*
9286  *     Function: fcp_alloc_lun
9287  *
9288  *  Description: Creates a new lun structure and adds it to the list
9289  *               of luns of the target.
9290  *
9291  *     Argument: ptgt           Target the lun will belong to.
9292  *
9293  * Return Value: NULL           Failed
9294  *               Not NULL       Succeeded
9295  *
9296  *      Context: Kernel context
9297  */
9298 static struct fcp_lun *
9299 fcp_alloc_lun(struct fcp_tgt *ptgt)
9300 {
9301         struct fcp_lun *plun;
9302 
9303         plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9304         if (plun != NULL) {
9305                 /*
9306                  * Initialize the mutex before putting in the target list
9307                  * especially before releasing the target mutex.
9308                  */
9309                 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9310                 plun->lun_tgt = ptgt;
9311 
9312                 mutex_enter(&ptgt->tgt_mutex);
9313                 plun->lun_next = ptgt->tgt_lun;
9314                 ptgt->tgt_lun = plun;
9315                 plun->lun_old_guid = NULL;
9316                 plun->lun_old_guid_size = 0;
9317                 mutex_exit(&ptgt->tgt_mutex);
9318         }
9319 
9320         return (plun);
9321 }
9322 
9323 /*
9324  *     Function: fcp_dealloc_lun
9325  *
9326  *  Description: Frees the LUN structure passed by the caller.
9327  *
9328  *     Argument: plun           LUN structure to free.
9329  *
9330  * Return Value: None
9331  *
9332  *      Context: Kernel context.
9333  */
9334 static void
9335 fcp_dealloc_lun(struct fcp_lun *plun)
9336 {
9337         mutex_enter(&plun->lun_mutex);
9338         if (plun->lun_cip) {
9339                 fcp_remove_child(plun);
9340         }
9341         mutex_exit(&plun->lun_mutex);
9342 
9343         mutex_destroy(&plun->lun_mutex);
9344         if (plun->lun_guid) {
9345                 kmem_free(plun->lun_guid, plun->lun_guid_size);
9346         }
9347         if (plun->lun_old_guid) {
9348                 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9349         }
9350         kmem_free(plun, sizeof (*plun));
9351 }
9352 
9353 /*
9354  *     Function: fcp_alloc_tgt
9355  *
9356  *  Description: Creates a new target structure and adds it to the port
9357  *               hash list.
9358  *
9359  *     Argument: pptr           fcp port structure
9360  *               *map_entry     entry describing the target to create
9361  *               link_cnt       Link state change counter
9362  *
9363  * Return Value: NULL           Failed
9364  *               Not NULL       Succeeded
9365  *
9366  *      Context: Kernel context.
9367  */
9368 static struct fcp_tgt *
9369 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9370 {
9371         int                     hash;
9372         uchar_t                 *wwn;
9373         struct fcp_tgt  *ptgt;
9374 
9375         ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9376         if (ptgt != NULL) {
9377                 mutex_enter(&pptr->port_mutex);
9378                 if (link_cnt != pptr->port_link_cnt) {
9379                         /*
9380                          * oh oh -- another link reset
9381                          * in progress -- give up
9382                          */
9383                         mutex_exit(&pptr->port_mutex);
9384                         kmem_free(ptgt, sizeof (*ptgt));
9385                         ptgt = NULL;
9386                 } else {
9387                         /*
9388                          * initialize the mutex before putting in the port
9389                          * wwn list, especially before releasing the port
9390                          * mutex.
9391                          */
9392                         mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9393 
9394                         /* add new target entry to the port's hash list */
9395                         wwn = (uchar_t *)&map_entry->map_pwwn;
9396                         hash = FCP_HASH(wwn);
9397 
9398                         ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9399                         pptr->port_tgt_hash_table[hash] = ptgt;
9400 
9401                         /* save cross-ptr */
9402                         ptgt->tgt_port = pptr;
9403 
9404                         ptgt->tgt_change_cnt = 1;
9405 
9406                         /* initialize the target manual_config_only flag */
9407                         if (fcp_enable_auto_configuration) {
9408                                 ptgt->tgt_manual_config_only = 0;
9409                         } else {
9410                                 ptgt->tgt_manual_config_only = 1;
9411                         }
9412 
9413                         mutex_exit(&pptr->port_mutex);
9414                 }
9415         }
9416 
9417         return (ptgt);
9418 }
9419 
9420 /*
9421  *     Function: fcp_dealloc_tgt
9422  *
9423  *  Description: Frees the target structure passed by the caller.
9424  *
9425  *     Argument: ptgt           Target structure to free.
9426  *
9427  * Return Value: None
9428  *
9429  *      Context: Kernel context.
9430  */
9431 static void
9432 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9433 {
9434         mutex_destroy(&ptgt->tgt_mutex);
9435         kmem_free(ptgt, sizeof (*ptgt));
9436 }
9437 
9438 
9439 /*
9440  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9441  *
9442  *      Device discovery commands will not be retried for-ever as
9443  *      this will have repercussions on other devices that need to
9444  *      be submitted to the hotplug thread. After a quick glance
9445  *      at the SCSI-3 spec, it was found that the spec doesn't
9446  *      mandate a forever retry, rather recommends a delayed retry.
9447  *
9448  *      Since Photon IB is single threaded, STATUS_BUSY is common
9449  *      in a 4+initiator environment. Make sure the total time
9450  *      spent on retries (including command timeout) does not
9451  *      60 seconds
9452  */
9453 static void
9454 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9455 {
9456         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9457         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9458 
9459         mutex_enter(&pptr->port_mutex);
9460         mutex_enter(&ptgt->tgt_mutex);
9461         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9462                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
9463                     fcp_trace, FCP_BUF_LEVEL_2, 0,
9464                     "fcp_queue_ipkt,1:state change occured"
9465                     " for D_ID=0x%x", ptgt->tgt_d_id);
9466                 mutex_exit(&ptgt->tgt_mutex);
9467                 mutex_exit(&pptr->port_mutex);
9468                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9469                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
9470                 fcp_icmd_free(pptr, icmd);
9471                 return;
9472         }
9473         mutex_exit(&ptgt->tgt_mutex);
9474 
9475         icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9476 
9477         if (pptr->port_ipkt_list != NULL) {
9478                 /* add pkt to front of doubly-linked list */
9479                 pptr->port_ipkt_list->ipkt_prev = icmd;
9480                 icmd->ipkt_next = pptr->port_ipkt_list;
9481                 pptr->port_ipkt_list = icmd;
9482                 icmd->ipkt_prev = NULL;
9483         } else {
9484                 /* this is the first/only pkt on the list */
9485                 pptr->port_ipkt_list = icmd;
9486                 icmd->ipkt_next = NULL;
9487                 icmd->ipkt_prev = NULL;
9488         }
9489         mutex_exit(&pptr->port_mutex);
9490 }
9491 
9492 /*
9493  *     Function: fcp_transport
9494  *
9495  *  Description: This function submits the Fibre Channel packet to the transort
9496  *               layer by calling fc_ulp_transport().  If fc_ulp_transport()
9497  *               fails the submission, the treatment depends on the value of
9498  *               the variable internal.
9499  *
9500  *     Argument: port_handle    fp/fctl port handle.
9501  *               *fpkt          Packet to submit to the transport layer.
9502  *               internal       Not zero when it's an internal packet.
9503  *
9504  * Return Value: FC_TRAN_BUSY
9505  *               FC_STATEC_BUSY
9506  *               FC_OFFLINE
9507  *               FC_LOGINREQ
9508  *               FC_DEVICE_BUSY
9509  *               FC_SUCCESS
9510  */
9511 static int
9512 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9513 {
9514         int     rval;
9515 
9516         rval = fc_ulp_transport(port_handle, fpkt);
9517         if (rval == FC_SUCCESS) {
9518                 return (rval);
9519         }
9520 
9521         /*
9522          * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9523          * a command, if the underlying modules see that there is a state
9524          * change, or if a port is OFFLINE, that means, that state change
9525          * hasn't reached FCP yet, so re-queue the command for deferred
9526          * submission.
9527          */
9528         if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9529             (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9530             (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9531                 /*
9532                  * Defer packet re-submission. Life hang is possible on
9533                  * internal commands if the port driver sends FC_STATEC_BUSY
9534                  * for ever, but that shouldn't happen in a good environment.
9535                  * Limiting re-transport for internal commands is probably a
9536                  * good idea..
9537                  * A race condition can happen when a port sees barrage of
9538                  * link transitions offline to online. If the FCTL has
9539                  * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9540                  * internal commands should be queued to do the discovery.
9541                  * The race condition is when an online comes and FCP starts
9542                  * its internal discovery and the link goes offline. It is
9543                  * possible that the statec_callback has not reached FCP
9544                  * and FCP is carrying on with its internal discovery.
9545                  * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9546                  * that the link has gone offline. At this point FCP should
9547                  * drop all the internal commands and wait for the
9548                  * statec_callback. It will be facilitated by incrementing
9549                  * port_link_cnt.
9550                  *
9551                  * For external commands, the (FC)pkt_timeout is decremented
9552                  * by the QUEUE Delay added by our driver, Care is taken to
9553                  * ensure that it doesn't become zero (zero means no timeout)
9554                  * If the time expires right inside driver queue itself,
9555                  * the watch thread will return it to the original caller
9556                  * indicating that the command has timed-out.
9557                  */
9558                 if (internal) {
9559                         char                    *op;
9560                         struct fcp_ipkt *icmd;
9561 
9562                         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9563                         switch (icmd->ipkt_opcode) {
9564                         case SCMD_REPORT_LUN:
9565                                 op = "REPORT LUN";
9566                                 break;
9567 
9568                         case SCMD_INQUIRY:
9569                                 op = "INQUIRY";
9570                                 break;
9571 
9572                         case SCMD_INQUIRY_PAGE83:
9573                                 op = "INQUIRY-83";
9574                                 break;
9575 
9576                         default:
9577                                 op = "Internal SCSI COMMAND";
9578                                 break;
9579                         }
9580 
9581                         if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9582                             icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9583                                 rval = FC_SUCCESS;
9584                         }
9585                 } else {
9586                         struct fcp_pkt *cmd;
9587                         struct fcp_port *pptr;
9588 
9589                         cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9590                         cmd->cmd_state = FCP_PKT_IDLE;
9591                         pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9592 
9593                         if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9594                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9595                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9596                                     "fcp_transport: xport busy for pkt %p",
9597                                     cmd->cmd_pkt);
9598                                 rval = FC_TRAN_BUSY;
9599                         } else {
9600                                 fcp_queue_pkt(pptr, cmd);
9601                                 rval = FC_SUCCESS;
9602                         }
9603                 }
9604         }
9605 
9606         return (rval);
9607 }
9608 
9609 /*VARARGS3*/
9610 static void
9611 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9612 {
9613         char            buf[256];
9614         va_list         ap;
9615 
9616         if (dip == NULL) {
9617                 dip = fcp_global_dip;
9618         }
9619 
9620         va_start(ap, fmt);
9621         (void) vsprintf(buf, fmt, ap);
9622         va_end(ap);
9623 
9624         scsi_log(dip, "fcp", level, buf);
9625 }
9626 
9627 /*
9628  * This function retries NS registry of FC4 type.
9629  * It assumes that fcp_mutex is held.
9630  * The function does nothing if topology is not fabric
9631  * So, the topology has to be set before this function can be called
9632  */
9633 static void
9634 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9635 {
9636         int     rval;
9637 
9638         ASSERT(MUTEX_HELD(&pptr->port_mutex));
9639 
9640         if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9641             ((pptr->port_topology != FC_TOP_FABRIC) &&
9642             (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9643                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9644                         pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9645                 }
9646                 return;
9647         }
9648         mutex_exit(&pptr->port_mutex);
9649         rval = fcp_do_ns_registry(pptr, s_id);
9650         mutex_enter(&pptr->port_mutex);
9651 
9652         if (rval == 0) {
9653                 /* Registry successful. Reset flag */
9654                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9655         }
9656 }
9657 
9658 /*
9659  * This function registers the ULP with the switch by calling transport i/f
9660  */
9661 static int
9662 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9663 {
9664         fc_ns_cmd_t             ns_cmd;
9665         ns_rfc_type_t           rfc;
9666         uint32_t                types[8];
9667 
9668         /*
9669          * Prepare the Name server structure to
9670          * register with the transport in case of
9671          * Fabric configuration.
9672          */
9673         bzero(&rfc, sizeof (rfc));
9674         bzero(types, sizeof (types));
9675 
9676         types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9677             (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9678 
9679         rfc.rfc_port_id.port_id = s_id;
9680         bcopy(types, rfc.rfc_types, sizeof (types));
9681 
9682         ns_cmd.ns_flags = 0;
9683         ns_cmd.ns_cmd = NS_RFT_ID;
9684         ns_cmd.ns_req_len = sizeof (rfc);
9685         ns_cmd.ns_req_payload = (caddr_t)&rfc;
9686         ns_cmd.ns_resp_len = 0;
9687         ns_cmd.ns_resp_payload = NULL;
9688 
9689         /*
9690          * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9691          */
9692         if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9693                 fcp_log(CE_WARN, pptr->port_dip,
9694                     "!ns_registry: failed name server registration");
9695                 return (1);
9696         }
9697 
9698         return (0);
9699 }
9700 
9701 /*
9702  *     Function: fcp_handle_port_attach
9703  *
9704  *  Description: This function is called from fcp_port_attach() to attach a
9705  *               new port. This routine does the following:
9706  *
9707  *              1) Allocates an fcp_port structure and initializes it.
9708  *              2) Tries to register the new FC-4 (FCP) capablity with the name
9709  *                 server.
9710  *              3) Kicks off the enumeration of the targets/luns visible
9711  *                 through this new port.  That is done by calling
9712  *                 fcp_statec_callback() if the port is online.
9713  *
9714  *     Argument: ulph           fp/fctl port handle.
9715  *               *pinfo         Port information.
9716  *               s_id           Port ID.
9717  *               instance       Device instance number for the local port
9718  *                              (returned by ddi_get_instance()).
9719  *
9720  * Return Value: DDI_SUCCESS
9721  *               DDI_FAILURE
9722  *
9723  *      Context: User and Kernel context.
9724  */
9725 /*ARGSUSED*/
9726 int
9727 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9728     uint32_t s_id, int instance)
9729 {
9730         int                     res = DDI_FAILURE;
9731         scsi_hba_tran_t         *tran;
9732         int                     mutex_initted = FALSE;
9733         int                     hba_attached = FALSE;
9734         int                     soft_state_linked = FALSE;
9735         int                     event_bind = FALSE;
9736         struct fcp_port         *pptr;
9737         fc_portmap_t            *tmp_list = NULL;
9738         uint32_t                max_cnt, alloc_cnt;
9739         uchar_t                 *boot_wwn = NULL;
9740         uint_t                  nbytes;
9741         int                     manual_cfg;
9742 
9743         /*
9744          * this port instance attaching for the first time (or after
9745          * being detached before)
9746          */
9747         FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9748             FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9749 
9750         if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9751                 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9752                     "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9753                     instance);
9754                 return (res);
9755         }
9756 
9757         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9758                 /* this shouldn't happen */
9759                 ddi_soft_state_free(fcp_softstate, instance);
9760                 cmn_err(CE_WARN, "fcp: bad soft state");
9761                 return (res);
9762         }
9763 
9764         (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9765 
9766         /*
9767          * Make a copy of ulp_port_info as fctl allocates
9768          * a temp struct.
9769          */
9770         (void) fcp_cp_pinfo(pptr, pinfo);
9771 
9772         /*
9773          * Check for manual_configuration_only property.
9774          * Enable manual configurtion if the property is
9775          * set to 1, otherwise disable manual configuration.
9776          */
9777         if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9778             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9779             MANUAL_CFG_ONLY,
9780             -1)) != -1) {
9781                 if (manual_cfg == 1) {
9782                         char    *pathname;
9783                         pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9784                         (void) ddi_pathname(pptr->port_dip, pathname);
9785                         cmn_err(CE_NOTE,
9786                             "%s (%s%d) %s is enabled via %s.conf.",
9787                             pathname,
9788                             ddi_driver_name(pptr->port_dip),
9789                             ddi_get_instance(pptr->port_dip),
9790                             MANUAL_CFG_ONLY,
9791                             ddi_driver_name(pptr->port_dip));
9792                         fcp_enable_auto_configuration = 0;
9793                         kmem_free(pathname, MAXPATHLEN);
9794                 }
9795         }
9796         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9797         pptr->port_link_cnt = 1;
9798         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9799         pptr->port_id = s_id;
9800         pptr->port_instance = instance;
9801         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9802         pptr->port_state = FCP_STATE_INIT;
9803         if (pinfo->port_acc_attr == NULL) {
9804                 /*
9805                  * The corresponding FCA doesn't support DMA at all
9806                  */
9807                 pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9808         }
9809 
9810         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9811 
9812         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9813                 /*
9814                  * If FCA supports DMA in SCSI data phase, we need preallocate
9815                  * dma cookie, so stash the cookie size
9816                  */
9817                 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9818                     pptr->port_data_dma_attr.dma_attr_sgllen;
9819         }
9820 
9821         /*
9822          * The two mutexes of fcp_port are initialized.  The variable
9823          * mutex_initted is incremented to remember that fact.  That variable
9824          * is checked when the routine fails and the mutexes have to be
9825          * destroyed.
9826          */
9827         mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9828         mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9829         mutex_initted++;
9830 
9831         /*
9832          * The SCSI tran structure is allocate and initialized now.
9833          */
9834         if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9835                 fcp_log(CE_WARN, pptr->port_dip,
9836                     "!fcp%d: scsi_hba_tran_alloc failed", instance);
9837                 goto fail;
9838         }
9839 
9840         /* link in the transport structure then fill it in */
9841         pptr->port_tran = tran;
9842         tran->tran_hba_private               = pptr;
9843         tran->tran_tgt_init          = fcp_scsi_tgt_init;
9844         tran->tran_tgt_probe         = NULL;
9845         tran->tran_tgt_free          = fcp_scsi_tgt_free;
9846         tran->tran_start             = fcp_scsi_start;
9847         tran->tran_reset             = fcp_scsi_reset;
9848         tran->tran_abort             = fcp_scsi_abort;
9849         tran->tran_getcap            = fcp_scsi_getcap;
9850         tran->tran_setcap            = fcp_scsi_setcap;
9851         tran->tran_init_pkt          = NULL;
9852         tran->tran_destroy_pkt               = NULL;
9853         tran->tran_dmafree           = NULL;
9854         tran->tran_sync_pkt          = NULL;
9855         tran->tran_reset_notify              = fcp_scsi_reset_notify;
9856         tran->tran_get_bus_addr              = fcp_scsi_get_bus_addr;
9857         tran->tran_get_name          = fcp_scsi_get_name;
9858         tran->tran_clear_aca         = NULL;
9859         tran->tran_clear_task_set    = NULL;
9860         tran->tran_terminate_task    = NULL;
9861         tran->tran_get_eventcookie   = fcp_scsi_bus_get_eventcookie;
9862         tran->tran_add_eventcall     = fcp_scsi_bus_add_eventcall;
9863         tran->tran_remove_eventcall  = fcp_scsi_bus_remove_eventcall;
9864         tran->tran_post_event                = fcp_scsi_bus_post_event;
9865         tran->tran_quiesce           = NULL;
9866         tran->tran_unquiesce         = NULL;
9867         tran->tran_bus_reset         = NULL;
9868         tran->tran_bus_config                = fcp_scsi_bus_config;
9869         tran->tran_bus_unconfig              = fcp_scsi_bus_unconfig;
9870         tran->tran_bus_power         = NULL;
9871         tran->tran_interconnect_type = INTERCONNECT_FABRIC;
9872 
9873         tran->tran_pkt_constructor   = fcp_kmem_cache_constructor;
9874         tran->tran_pkt_destructor    = fcp_kmem_cache_destructor;
9875         tran->tran_setup_pkt         = fcp_pkt_setup;
9876         tran->tran_teardown_pkt              = fcp_pkt_teardown;
9877         tran->tran_hba_len           = pptr->port_priv_pkt_len +
9878             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9879         if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9880                 /*
9881                  * If FCA don't support DMA, then we use different vectors to
9882                  * minimize the effects on DMA code flow path
9883                  */
9884                 tran->tran_start        = fcp_pseudo_start;
9885                 tran->tran_init_pkt     = fcp_pseudo_init_pkt;
9886                 tran->tran_destroy_pkt          = fcp_pseudo_destroy_pkt;
9887                 tran->tran_sync_pkt     = fcp_pseudo_sync_pkt;
9888                 tran->tran_dmafree      = fcp_pseudo_dmafree;
9889                 tran->tran_setup_pkt    = NULL;
9890                 tran->tran_teardown_pkt         = NULL;
9891                 tran->tran_pkt_constructor = NULL;
9892                 tran->tran_pkt_destructor  = NULL;
9893                 pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9894         }
9895 
9896         /*
9897          * Allocate an ndi event handle
9898          */
9899         pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9900             kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9901 
9902         bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9903             sizeof (fcp_ndi_event_defs));
9904 
9905         (void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9906             &pptr->port_ndi_event_hdl, NDI_SLEEP);
9907 
9908         pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9909         pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9910         pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9911 
9912         if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9913             (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9914             &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9915                 goto fail;
9916         }
9917         event_bind++;   /* Checked in fail case */
9918 
9919         if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9920             tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9921             != DDI_SUCCESS) {
9922                 fcp_log(CE_WARN, pptr->port_dip,
9923                     "!fcp%d: scsi_hba_attach_setup failed", instance);
9924                 goto fail;
9925         }
9926         hba_attached++; /* Checked in fail case */
9927 
9928         pptr->port_mpxio = 0;
9929         if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9930             MDI_SUCCESS) {
9931                 pptr->port_mpxio++;
9932         }
9933 
9934         /*
9935          * The following code is putting the new port structure in the global
9936          * list of ports and, if it is the first port to attach, it start the
9937          * fcp_watchdog_tick.
9938          *
9939          * Why put this new port in the global before we are done attaching it?
9940          * We are actually making the structure globally known before we are
9941          * done attaching it.  The reason for that is: because of the code that
9942          * follows.  At this point the resources to handle the port are
9943          * allocated.  This function is now going to do the following:
9944          *
9945          *   1) It is going to try to register with the name server advertizing
9946          *      the new FCP capability of the port.
9947          *   2) It is going to play the role of the fp/fctl layer by building
9948          *      a list of worlwide names reachable through this port and call
9949          *      itself on fcp_statec_callback().  That requires the port to
9950          *      be part of the global list.
9951          */
9952         mutex_enter(&fcp_global_mutex);
9953         if (fcp_port_head == NULL) {
9954                 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
9955         }
9956         pptr->port_next = fcp_port_head;
9957         fcp_port_head = pptr;
9958         soft_state_linked++;
9959 
9960         if (fcp_watchdog_init++ == 0) {
9961                 fcp_watchdog_tick = fcp_watchdog_timeout *
9962                     drv_usectohz(1000000);
9963                 fcp_watchdog_id = timeout(fcp_watch, NULL,
9964                     fcp_watchdog_tick);
9965         }
9966         mutex_exit(&fcp_global_mutex);
9967 
9968         /*
9969          * Here an attempt is made to register with the name server, the new
9970          * FCP capability.  That is done using an RTF_ID to the name server.
9971          * It is done synchronously.  The function fcp_do_ns_registry()
9972          * doesn't return till the name server responded.
9973          * On failures, just ignore it for now and it will get retried during
9974          * state change callbacks. We'll set a flag to show this failure
9975          */
9976         if (fcp_do_ns_registry(pptr, s_id)) {
9977                 mutex_enter(&pptr->port_mutex);
9978                 pptr->port_state |= FCP_STATE_NS_REG_FAILED;
9979                 mutex_exit(&pptr->port_mutex);
9980         } else {
9981                 mutex_enter(&pptr->port_mutex);
9982                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9983                 mutex_exit(&pptr->port_mutex);
9984         }
9985 
9986         /*
9987          * Lookup for boot WWN property
9988          */
9989         if (modrootloaded != 1) {
9990                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
9991                     ddi_get_parent(pinfo->port_dip),
9992                     DDI_PROP_DONTPASS, OBP_BOOT_WWN,
9993                     &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
9994                     (nbytes == FC_WWN_SIZE)) {
9995                         bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
9996                 }
9997                 if (boot_wwn) {
9998                         ddi_prop_free(boot_wwn);
9999                 }
10000         }
10001 
10002         /*
10003          * Handle various topologies and link states.
10004          */
10005         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10006         case FC_STATE_OFFLINE:
10007 
10008                 /*
10009                  * we're attaching a port where the link is offline
10010                  *
10011                  * Wait for ONLINE, at which time a state
10012                  * change will cause a statec_callback
10013                  *
10014                  * in the mean time, do not do anything
10015                  */
10016                 res = DDI_SUCCESS;
10017                 pptr->port_state |= FCP_STATE_OFFLINE;
10018                 break;
10019 
10020         case FC_STATE_ONLINE: {
10021                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
10022                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10023                         res = DDI_SUCCESS;
10024                         break;
10025                 }
10026                 /*
10027                  * discover devices and create nodes (a private
10028                  * loop or point-to-point)
10029                  */
10030                 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10031 
10032                 /*
10033                  * At this point we are going to build a list of all the ports
10034                  * that can be reached through this local port.  It looks like
10035                  * we cannot handle more than FCP_MAX_DEVICES per local port
10036                  * (128).
10037                  */
10038                 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10039                     sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10040                     KM_NOSLEEP)) == NULL) {
10041                         fcp_log(CE_WARN, pptr->port_dip,
10042                             "!fcp%d: failed to allocate portmap",
10043                             instance);
10044                         goto fail;
10045                 }
10046 
10047                 /*
10048                  * fc_ulp_getportmap() is going to provide us with the list of
10049                  * remote ports in the buffer we just allocated.  The way the
10050                  * list is going to be retrieved depends on the topology.
10051                  * However, if we are connected to a Fabric, a name server
10052                  * request may be sent to get the list of FCP capable ports.
10053                  * It should be noted that is the case the request is
10054                  * synchronous.  This means we are stuck here till the name
10055                  * server replies.  A lot of things can change during that time
10056                  * and including, may be, being called on
10057                  * fcp_statec_callback() for different reasons. I'm not sure
10058                  * the code can handle that.
10059                  */
10060                 max_cnt = FCP_MAX_DEVICES;
10061                 alloc_cnt = FCP_MAX_DEVICES;
10062                 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10063                     &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10064                     FC_SUCCESS) {
10065                         caddr_t msg;
10066 
10067                         (void) fc_ulp_error(res, &msg);
10068 
10069                         /*
10070                          * this  just means the transport is
10071                          * busy perhaps building a portmap so,
10072                          * for now, succeed this port attach
10073                          * when the transport has a new map,
10074                          * it'll send us a state change then
10075                          */
10076                         fcp_log(CE_WARN, pptr->port_dip,
10077                             "!failed to get port map : %s", msg);
10078 
10079                         res = DDI_SUCCESS;
10080                         break;  /* go return result */
10081                 }
10082                 if (max_cnt > alloc_cnt) {
10083                         alloc_cnt = max_cnt;
10084                 }
10085 
10086                 /*
10087                  * We are now going to call fcp_statec_callback() ourselves.
10088                  * By issuing this call we are trying to kick off the enumera-
10089                  * tion process.
10090                  */
10091                 /*
10092                  * let the state change callback do the SCSI device
10093                  * discovery and create the devinfos
10094                  */
10095                 fcp_statec_callback(ulph, pptr->port_fp_handle,
10096                     pptr->port_phys_state, pptr->port_topology, tmp_list,
10097                     max_cnt, pptr->port_id);
10098 
10099                 res = DDI_SUCCESS;
10100                 break;
10101         }
10102 
10103         default:
10104                 /* unknown port state */
10105                 fcp_log(CE_WARN, pptr->port_dip,
10106                     "!fcp%d: invalid port state at attach=0x%x",
10107                     instance, pptr->port_phys_state);
10108 
10109                 mutex_enter(&pptr->port_mutex);
10110                 pptr->port_phys_state = FCP_STATE_OFFLINE;
10111                 mutex_exit(&pptr->port_mutex);
10112 
10113                 res = DDI_SUCCESS;
10114                 break;
10115         }
10116 
10117         /* free temp list if used */
10118         if (tmp_list != NULL) {
10119                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10120         }
10121 
10122         /* note the attach time */
10123         pptr->port_attach_time = ddi_get_lbolt64();
10124 
10125         /* all done */
10126         return (res);
10127 
10128         /* a failure we have to clean up after */
10129 fail:
10130         fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10131 
10132         if (soft_state_linked) {
10133                 /* remove this fcp_port from the linked list */
10134                 (void) fcp_soft_state_unlink(pptr);
10135         }
10136 
10137         /* unbind and free event set */
10138         if (pptr->port_ndi_event_hdl) {
10139                 if (event_bind) {
10140                         (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10141                             &pptr->port_ndi_events, NDI_SLEEP);
10142                 }
10143                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10144         }
10145 
10146         if (pptr->port_ndi_event_defs) {
10147                 (void) kmem_free(pptr->port_ndi_event_defs,
10148                     sizeof (fcp_ndi_event_defs));
10149         }
10150 
10151         /*
10152          * Clean up mpxio stuff
10153          */
10154         if (pptr->port_mpxio) {
10155                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10156                 pptr->port_mpxio--;
10157         }
10158 
10159         /* undo SCSI HBA setup */
10160         if (hba_attached) {
10161                 (void) scsi_hba_detach(pptr->port_dip);
10162         }
10163         if (pptr->port_tran != NULL) {
10164                 scsi_hba_tran_free(pptr->port_tran);
10165         }
10166 
10167         mutex_enter(&fcp_global_mutex);
10168 
10169         /*
10170          * We check soft_state_linked, because it is incremented right before
10171          * we call increment fcp_watchdog_init.  Therefore, we know if
10172          * soft_state_linked is still FALSE, we do not want to decrement
10173          * fcp_watchdog_init or possibly call untimeout.
10174          */
10175 
10176         if (soft_state_linked) {
10177                 if (--fcp_watchdog_init == 0) {
10178                         timeout_id_t    tid = fcp_watchdog_id;
10179 
10180                         mutex_exit(&fcp_global_mutex);
10181                         (void) untimeout(tid);
10182                 } else {
10183                         mutex_exit(&fcp_global_mutex);
10184                 }
10185         } else {
10186                 mutex_exit(&fcp_global_mutex);
10187         }
10188 
10189         if (mutex_initted) {
10190                 mutex_destroy(&pptr->port_mutex);
10191                 mutex_destroy(&pptr->port_pkt_mutex);
10192         }
10193 
10194         if (tmp_list != NULL) {
10195                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10196         }
10197 
10198         /* this makes pptr invalid */
10199         ddi_soft_state_free(fcp_softstate, instance);
10200 
10201         return (DDI_FAILURE);
10202 }
10203 
10204 
10205 static int
10206 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10207 {
10208         int count = 0;
10209 
10210         mutex_enter(&pptr->port_mutex);
10211 
10212         /*
10213          * if the port is powered down or suspended, nothing else
10214          * to do; just return.
10215          */
10216         if (flag != FCP_STATE_DETACHING) {
10217                 if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10218                     FCP_STATE_SUSPENDED)) {
10219                         pptr->port_state |= flag;
10220                         mutex_exit(&pptr->port_mutex);
10221                         return (FC_SUCCESS);
10222                 }
10223         }
10224 
10225         if (pptr->port_state & FCP_STATE_IN_MDI) {
10226                 mutex_exit(&pptr->port_mutex);
10227                 return (FC_FAILURE);
10228         }
10229 
10230         FCP_TRACE(fcp_logq, pptr->port_instbuf,
10231             fcp_trace, FCP_BUF_LEVEL_2, 0,
10232             "fcp_handle_port_detach: port is detaching");
10233 
10234         pptr->port_state |= flag;
10235 
10236         /*
10237          * Wait for any ongoing reconfig/ipkt to complete, that
10238          * ensures the freeing to targets/luns is safe.
10239          * No more ref to this port should happen from statec/ioctl
10240          * after that as it was removed from the global port list.
10241          */
10242         while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10243             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10244                 /*
10245                  * Let's give sufficient time for reconfig/ipkt
10246                  * to complete.
10247                  */
10248                 if (count++ >= FCP_ICMD_DEADLINE) {
10249                         break;
10250                 }
10251                 mutex_exit(&pptr->port_mutex);
10252                 delay(drv_usectohz(1000000));
10253                 mutex_enter(&pptr->port_mutex);
10254         }
10255 
10256         /*
10257          * if the driver is still busy then fail to
10258          * suspend/power down.
10259          */
10260         if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10261             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10262                 pptr->port_state &= ~flag;
10263                 mutex_exit(&pptr->port_mutex);
10264                 return (FC_FAILURE);
10265         }
10266 
10267         if (flag == FCP_STATE_DETACHING) {
10268                 pptr = fcp_soft_state_unlink(pptr);
10269                 ASSERT(pptr != NULL);
10270         }
10271 
10272         pptr->port_link_cnt++;
10273         pptr->port_state |= FCP_STATE_OFFLINE;
10274         pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10275 
10276         fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10277             FCP_CAUSE_LINK_DOWN);
10278         mutex_exit(&pptr->port_mutex);
10279 
10280         /* kill watch dog timer if we're the last */
10281         mutex_enter(&fcp_global_mutex);
10282         if (--fcp_watchdog_init == 0) {
10283                 timeout_id_t    tid = fcp_watchdog_id;
10284                 mutex_exit(&fcp_global_mutex);
10285                 (void) untimeout(tid);
10286         } else {
10287                 mutex_exit(&fcp_global_mutex);
10288         }
10289 
10290         /* clean up the port structures */
10291         if (flag == FCP_STATE_DETACHING) {
10292                 fcp_cleanup_port(pptr, instance);
10293         }
10294 
10295         return (FC_SUCCESS);
10296 }
10297 
10298 
10299 static void
10300 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10301 {
10302         ASSERT(pptr != NULL);
10303 
10304         /* unbind and free event set */
10305         if (pptr->port_ndi_event_hdl) {
10306                 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10307                     &pptr->port_ndi_events, NDI_SLEEP);
10308                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10309         }
10310 
10311         if (pptr->port_ndi_event_defs) {
10312                 (void) kmem_free(pptr->port_ndi_event_defs,
10313                     sizeof (fcp_ndi_event_defs));
10314         }
10315 
10316         /* free the lun/target structures and devinfos */
10317         fcp_free_targets(pptr);
10318 
10319         /*
10320          * Clean up mpxio stuff
10321          */
10322         if (pptr->port_mpxio) {
10323                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10324                 pptr->port_mpxio--;
10325         }
10326 
10327         /* clean up SCSA stuff */
10328         (void) scsi_hba_detach(pptr->port_dip);
10329         if (pptr->port_tran != NULL) {
10330                 scsi_hba_tran_free(pptr->port_tran);
10331         }
10332 
10333 #ifdef  KSTATS_CODE
10334         /* clean up kstats */
10335         if (pptr->fcp_ksp != NULL) {
10336                 kstat_delete(pptr->fcp_ksp);
10337         }
10338 #endif
10339 
10340         /* clean up soft state mutexes/condition variables */
10341         mutex_destroy(&pptr->port_mutex);
10342         mutex_destroy(&pptr->port_pkt_mutex);
10343 
10344         /* all done with soft state */
10345         ddi_soft_state_free(fcp_softstate, instance);
10346 }
10347 
10348 /*
10349  *     Function: fcp_kmem_cache_constructor
10350  *
10351  *  Description: This function allocates and initializes the resources required
10352  *               to build a scsi_pkt structure the target driver.  The result
10353  *               of the allocation and initialization will be cached in the
10354  *               memory cache.  As DMA resources may be allocated here, that
10355  *               means DMA resources will be tied up in the cache manager.
10356  *               This is a tradeoff that has been made for performance reasons.
10357  *
10358  *     Argument: *buf           Memory to preinitialize.
10359  *               *arg           FCP port structure (fcp_port).
10360  *               kmflags        Value passed to kmem_cache_alloc() and
10361  *                              propagated to the constructor.
10362  *
10363  * Return Value: 0      Allocation/Initialization was successful.
10364  *               -1     Allocation or Initialization failed.
10365  *
10366  *
10367  * If the returned value is 0, the buffer is initialized like this:
10368  *
10369  *                  +================================+
10370  *           +----> |              struct scsi_pkt        |
10371  *           |      |                                |
10372  *           | +--- | pkt_ha_private                 |
10373  *           | |    |                                |
10374  *           | |    +================================+
10375  *           | |
10376  *           | |    +================================+
10377  *           | +--> |            struct fcp_pkt           | <---------+
10378  *           |      |                                |           |
10379  *           +----- | cmd_pkt                        |           |
10380  *                  |                     cmd_fp_pkt | ---+      |
10381  *        +-------->| cmd_fcp_rsp[]               |    |      |
10382  *        |    +--->| cmd_fcp_cmd[]               |    |      |
10383  *        |    |    |--------------------------------|    |      |
10384  *        |    |    |         struct fc_packet       | <--+   |
10385  *        |    |    |                                |           |
10386  *        |    |    |                pkt_ulp_private | ----------+
10387  *        |    |    |                pkt_fca_private | -----+
10388  *        |    |    |                pkt_data_cookie | ---+ |
10389  *        |    |    | pkt_cmdlen                     |    | |
10390  *        |    |(a) | pkt_rsplen                     |    | |
10391  *        |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10392  *        |     (b) |                 pkt_cmd_cookie | ---|-|----------+    |
10393  *        +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10394  *                  |                pkt_resp_cookie | ---|-|--+   |   |    |
10395  *                  | pkt_cmd_dma                    |    | |  |   |   |    |
10396  *                  | pkt_cmd_acc                    |    | |  |   |   |    |
10397  *                  +================================+    | |  |   |   |    |
10398  *                  |         dma_cookies            | <--+ |  |   |   |    |
10399  *                  |                                |      |  |   |   |    |
10400  *                  +================================+      |  |   |   |    |
10401  *                  |         fca_private            | <----+  |   |   |    |
10402  *                  |                                |         |   |   |    |
10403  *                  +================================+         |   |   |    |
10404  *                                                             |   |   |    |
10405  *                                                             |   |   |    |
10406  *                  +================================+   (d)   |   |   |    |
10407  *                  |        fcp_resp cookies        | <-------+   |   |    |
10408  *                  |                                |             |   |    |
10409  *                  +================================+             |   |    |
10410  *                                                                 |   |    |
10411  *                  +================================+   (d)       |   |    |
10412  *                  |           fcp_resp             | <-----------+   |    |
10413  *                  |   (DMA resources associated)   |                 |    |
10414  *                  +================================+                 |    |
10415  *                                                                     |    |
10416  *                                                                     |    |
10417  *                                                                     |    |
10418  *                  +================================+   (c)           |    |
10419  *                  |        fcp_cmd cookies         | <---------------+    |
10420  *                  |                                |                      |
10421  *                  +================================+                      |
10422  *                                                                          |
10423  *                  +================================+   (c)                |
10424  *                  |            fcp_cmd             | <--------------------+
10425  *                  |   (DMA resources associated)   |
10426  *                  +================================+
10427  *
10428  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10429  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10430  * (c) Only if DMA is used for the FCP_CMD buffer.
10431  * (d) Only if DMA is used for the FCP_RESP buffer
10432  */
10433 static int
10434 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10435     int kmflags)
10436 {
10437         struct fcp_pkt  *cmd;
10438         struct fcp_port *pptr;
10439         fc_packet_t     *fpkt;
10440 
10441         pptr = (struct fcp_port *)tran->tran_hba_private;
10442         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10443         bzero(cmd, tran->tran_hba_len);
10444 
10445         cmd->cmd_pkt = pkt;
10446         pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10447         fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10448         cmd->cmd_fp_pkt = fpkt;
10449 
10450         cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10451         cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10452         cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10453             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10454 
10455         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10456             sizeof (struct fcp_pkt));
10457 
10458         fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10459         fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10460 
10461         if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10462                 /*
10463                  * The underlying HBA doesn't want to DMA the fcp_cmd or
10464                  * fcp_resp.  The transfer of information will be done by
10465                  * bcopy.
10466                  * The naming of the flags (that is actually a value) is
10467                  * unfortunate.  FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10468                  * DMA" but instead "NO DMA".
10469                  */
10470                 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10471                 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10472                 fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10473         } else {
10474                 /*
10475                  * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10476                  * buffer.  A buffer is allocated for each one the ddi_dma_*
10477                  * interfaces.
10478                  */
10479                 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10480                         return (-1);
10481                 }
10482         }
10483 
10484         return (0);
10485 }
10486 
10487 /*
10488  *     Function: fcp_kmem_cache_destructor
10489  *
10490  *  Description: Called by the destructor of the cache managed by SCSA.
10491  *               All the resources pre-allocated in fcp_pkt_constructor
10492  *               and the data also pre-initialized in fcp_pkt_constructor
10493  *               are freed and uninitialized here.
10494  *
10495  *     Argument: *buf           Memory to uninitialize.
10496  *               *arg           FCP port structure (fcp_port).
10497  *
10498  * Return Value: None
10499  *
10500  *      Context: kernel
10501  */
10502 static void
10503 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10504 {
10505         struct fcp_pkt  *cmd;
10506         struct fcp_port *pptr;
10507 
10508         pptr = (struct fcp_port *)(tran->tran_hba_private);
10509         cmd = pkt->pkt_ha_private;
10510 
10511         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10512                 /*
10513                  * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10514                  * buffer and DMA resources allocated to do so are released.
10515                  */
10516                 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10517         }
10518 }
10519 
10520 /*
10521  *     Function: fcp_alloc_cmd_resp
10522  *
10523  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10524  *               will be DMAed by the HBA.  The buffer is allocated applying
10525  *               the DMA requirements for the HBA.  The buffers allocated will
10526  *               also be bound.  DMA resources are allocated in the process.
10527  *               They will be released by fcp_free_cmd_resp().
10528  *
10529  *     Argument: *pptr  FCP port.
10530  *               *fpkt  fc packet for which the cmd and resp packet should be
10531  *                      allocated.
10532  *               flags  Allocation flags.
10533  *
10534  * Return Value: FC_FAILURE
10535  *               FC_SUCCESS
10536  *
10537  *      Context: User or Kernel context only if flags == KM_SLEEP.
10538  *               Interrupt context if the KM_SLEEP is not specified.
10539  */
10540 static int
10541 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10542 {
10543         int                     rval;
10544         int                     cmd_len;
10545         int                     resp_len;
10546         ulong_t                 real_len;
10547         int                     (*cb) (caddr_t);
10548         ddi_dma_cookie_t        pkt_cookie;
10549         ddi_dma_cookie_t        *cp;
10550         uint32_t                cnt;
10551 
10552         cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10553 
10554         cmd_len = fpkt->pkt_cmdlen;
10555         resp_len = fpkt->pkt_rsplen;
10556 
10557         ASSERT(fpkt->pkt_cmd_dma == NULL);
10558 
10559         /* Allocation of a DMA handle used in subsequent calls. */
10560         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10561             cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10562                 return (FC_FAILURE);
10563         }
10564 
10565         /* A buffer is allocated that satisfies the DMA requirements. */
10566         rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10567             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10568             (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10569 
10570         if (rval != DDI_SUCCESS) {
10571                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10572                 return (FC_FAILURE);
10573         }
10574 
10575         if (real_len < cmd_len) {
10576                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10577                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10578                 return (FC_FAILURE);
10579         }
10580 
10581         /* The buffer allocated is DMA bound. */
10582         rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10583             fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10584             cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10585 
10586         if (rval != DDI_DMA_MAPPED) {
10587                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10588                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10589                 return (FC_FAILURE);
10590         }
10591 
10592         if (fpkt->pkt_cmd_cookie_cnt >
10593             pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10594                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10595                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10596                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10597                 return (FC_FAILURE);
10598         }
10599 
10600         ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10601 
10602         /*
10603          * The buffer where the scatter/gather list is going to be built is
10604          * allocated.
10605          */
10606         cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10607             fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10608             KM_NOSLEEP);
10609 
10610         if (cp == NULL) {
10611                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10612                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10613                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10614                 return (FC_FAILURE);
10615         }
10616 
10617         /*
10618          * The scatter/gather list for the buffer we just allocated is built
10619          * here.
10620          */
10621         *cp = pkt_cookie;
10622         cp++;
10623 
10624         for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10625                 ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10626                     &pkt_cookie);
10627                 *cp = pkt_cookie;
10628         }
10629 
10630         ASSERT(fpkt->pkt_resp_dma == NULL);
10631         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10632             cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10633                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10634                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10635                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10636                 return (FC_FAILURE);
10637         }
10638 
10639         rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10640             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10641             (caddr_t *)&fpkt->pkt_resp, &real_len,
10642             &fpkt->pkt_resp_acc);
10643 
10644         if (rval != DDI_SUCCESS) {
10645                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10646                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10647                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10648                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10649                 kmem_free(fpkt->pkt_cmd_cookie,
10650                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10651                 return (FC_FAILURE);
10652         }
10653 
10654         if (real_len < resp_len) {
10655                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10656                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10657                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10658                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10659                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10660                 kmem_free(fpkt->pkt_cmd_cookie,
10661                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10662                 return (FC_FAILURE);
10663         }
10664 
10665         rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10666             fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10667             cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10668 
10669         if (rval != DDI_DMA_MAPPED) {
10670                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10671                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10672                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10673                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10674                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10675                 kmem_free(fpkt->pkt_cmd_cookie,
10676                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10677                 return (FC_FAILURE);
10678         }
10679 
10680         if (fpkt->pkt_resp_cookie_cnt >
10681             pptr->port_resp_dma_attr.dma_attr_sgllen) {
10682                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10683                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10684                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10685                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10686                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10687                 kmem_free(fpkt->pkt_cmd_cookie,
10688                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10689                 return (FC_FAILURE);
10690         }
10691 
10692         ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10693 
10694         cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10695             fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10696             KM_NOSLEEP);
10697 
10698         if (cp == NULL) {
10699                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10700                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10701                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10702                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10703                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10704                 kmem_free(fpkt->pkt_cmd_cookie,
10705                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10706                 return (FC_FAILURE);
10707         }
10708 
10709         *cp = pkt_cookie;
10710         cp++;
10711 
10712         for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10713                 ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10714                     &pkt_cookie);
10715                 *cp = pkt_cookie;
10716         }
10717 
10718         return (FC_SUCCESS);
10719 }
10720 
10721 /*
10722  *     Function: fcp_free_cmd_resp
10723  *
10724  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10725  *               allocated by fcp_alloc_cmd_resp() and all the resources
10726  *               associated with them.  That includes the DMA resources and the
10727  *               buffer allocated for the cookies of each one of them.
10728  *
10729  *     Argument: *pptr          FCP port context.
10730  *               *fpkt          fc packet containing the cmd and resp packet
10731  *                              to be released.
10732  *
10733  * Return Value: None
10734  *
10735  *      Context: Interrupt, User and Kernel context.
10736  */
10737 /* ARGSUSED */
10738 static void
10739 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10740 {
10741         ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10742 
10743         if (fpkt->pkt_resp_dma) {
10744                 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10745                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10746                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10747         }
10748 
10749         if (fpkt->pkt_resp_cookie) {
10750                 kmem_free(fpkt->pkt_resp_cookie,
10751                     fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10752                 fpkt->pkt_resp_cookie = NULL;
10753         }
10754 
10755         if (fpkt->pkt_cmd_dma) {
10756                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10757                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10758                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10759         }
10760 
10761         if (fpkt->pkt_cmd_cookie) {
10762                 kmem_free(fpkt->pkt_cmd_cookie,
10763                     fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10764                 fpkt->pkt_cmd_cookie = NULL;
10765         }
10766 }
10767 
10768 
10769 /*
10770  * called by the transport to do our own target initialization
10771  *
10772  * can acquire and release the global mutex
10773  */
10774 /* ARGSUSED */
10775 static int
10776 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10777     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10778 {
10779         uchar_t                 *bytes;
10780         uint_t                  nbytes;
10781         uint16_t                lun_num;
10782         struct fcp_tgt  *ptgt;
10783         struct fcp_lun  *plun;
10784         struct fcp_port *pptr = (struct fcp_port *)
10785             hba_tran->tran_hba_private;
10786 
10787         ASSERT(pptr != NULL);
10788 
10789         FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10790             FCP_BUF_LEVEL_8, 0,
10791             "fcp_phys_tgt_init: called for %s (instance %d)",
10792             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10793 
10794         /* get our port WWN property */
10795         bytes = NULL;
10796         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10797             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10798             (nbytes != FC_WWN_SIZE)) {
10799                 /* no port WWN property */
10800                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10801                     FCP_BUF_LEVEL_8, 0,
10802                     "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10803                     " for %s (instance %d): bytes=%p nbytes=%x",
10804                     ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10805                     nbytes);
10806 
10807                 if (bytes != NULL) {
10808                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10809                 }
10810 
10811                 return (DDI_NOT_WELL_FORMED);
10812         }
10813         ASSERT(bytes != NULL);
10814 
10815         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10816             LUN_PROP, 0xFFFF);
10817         if (lun_num == 0xFFFF) {
10818                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10819                     FCP_BUF_LEVEL_8, 0,
10820                     "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10821                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10822                     ddi_get_instance(tgt_dip));
10823 
10824                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10825                 return (DDI_NOT_WELL_FORMED);
10826         }
10827 
10828         mutex_enter(&pptr->port_mutex);
10829         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10830                 mutex_exit(&pptr->port_mutex);
10831                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10832                     FCP_BUF_LEVEL_8, 0,
10833                     "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10834                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10835                     ddi_get_instance(tgt_dip));
10836 
10837                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10838                 return (DDI_FAILURE);
10839         }
10840 
10841         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10842             FC_WWN_SIZE) == 0);
10843         ASSERT(plun->lun_num == lun_num);
10844 
10845         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10846 
10847         ptgt = plun->lun_tgt;
10848 
10849         mutex_enter(&ptgt->tgt_mutex);
10850         plun->lun_tgt_count++;
10851         scsi_device_hba_private_set(sd, plun);
10852         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10853         plun->lun_sd = sd;
10854         mutex_exit(&ptgt->tgt_mutex);
10855         mutex_exit(&pptr->port_mutex);
10856 
10857         return (DDI_SUCCESS);
10858 }
10859 
10860 /*ARGSUSED*/
10861 static int
10862 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10863     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10864 {
10865         uchar_t                 *bytes;
10866         uint_t                  nbytes;
10867         uint16_t                lun_num;
10868         struct fcp_tgt  *ptgt;
10869         struct fcp_lun  *plun;
10870         struct fcp_port *pptr = (struct fcp_port *)
10871             hba_tran->tran_hba_private;
10872         child_info_t            *cip;
10873 
10874         ASSERT(pptr != NULL);
10875 
10876         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10877             fcp_trace, FCP_BUF_LEVEL_8, 0,
10878             "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10879             " (tgt_dip %p)", ddi_get_name(tgt_dip),
10880             ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10881 
10882         cip = (child_info_t *)sd->sd_pathinfo;
10883         if (cip == NULL) {
10884                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10885                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10886                     "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10887                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10888                     ddi_get_instance(tgt_dip));
10889 
10890                 return (DDI_NOT_WELL_FORMED);
10891         }
10892 
10893         /* get our port WWN property */
10894         bytes = NULL;
10895         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10896             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10897             (nbytes != FC_WWN_SIZE)) {
10898                 if (bytes) {
10899                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10900                 }
10901                 return (DDI_NOT_WELL_FORMED);
10902         }
10903 
10904         ASSERT(bytes != NULL);
10905 
10906         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10907             LUN_PROP, 0xFFFF);
10908         if (lun_num == 0xFFFF) {
10909                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10910                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10911                     "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10912                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10913                     ddi_get_instance(tgt_dip));
10914 
10915                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10916                 return (DDI_NOT_WELL_FORMED);
10917         }
10918 
10919         mutex_enter(&pptr->port_mutex);
10920         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10921                 mutex_exit(&pptr->port_mutex);
10922                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10923                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10924                     "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10925                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10926                     ddi_get_instance(tgt_dip));
10927 
10928                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10929                 return (DDI_FAILURE);
10930         }
10931 
10932         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10933             FC_WWN_SIZE) == 0);
10934         ASSERT(plun->lun_num == lun_num);
10935 
10936         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10937 
10938         ptgt = plun->lun_tgt;
10939 
10940         mutex_enter(&ptgt->tgt_mutex);
10941         plun->lun_tgt_count++;
10942         scsi_device_hba_private_set(sd, plun);
10943         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10944         plun->lun_sd = sd;
10945         mutex_exit(&ptgt->tgt_mutex);
10946         mutex_exit(&pptr->port_mutex);
10947 
10948         return (DDI_SUCCESS);
10949 }
10950 
10951 
10952 /*
10953  * called by the transport to do our own target initialization
10954  *
10955  * can acquire and release the global mutex
10956  */
10957 /* ARGSUSED */
10958 static int
10959 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10960     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10961 {
10962         struct fcp_port *pptr = (struct fcp_port *)
10963             hba_tran->tran_hba_private;
10964         int                     rval;
10965 
10966         ASSERT(pptr != NULL);
10967 
10968         /*
10969          * Child node is getting initialized.  Look at the mpxio component
10970          * type on the child device to see if this device is mpxio managed
10971          * or not.
10972          */
10973         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
10974                 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
10975         } else {
10976                 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
10977         }
10978 
10979         return (rval);
10980 }
10981 
10982 
10983 /* ARGSUSED */
10984 static void
10985 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10986     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10987 {
10988         struct fcp_lun  *plun = scsi_device_hba_private_get(sd);
10989         struct fcp_tgt  *ptgt;
10990 
10991         FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
10992             fcp_trace, FCP_BUF_LEVEL_8, 0,
10993             "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
10994             ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
10995             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10996 
10997         if (plun == NULL) {
10998                 return;
10999         }
11000         ptgt = plun->lun_tgt;
11001 
11002         ASSERT(ptgt != NULL);
11003 
11004         mutex_enter(&ptgt->tgt_mutex);
11005         ASSERT(plun->lun_tgt_count > 0);
11006 
11007         if (--plun->lun_tgt_count == 0) {
11008                 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11009         }
11010         plun->lun_sd = NULL;
11011         mutex_exit(&ptgt->tgt_mutex);
11012 }
11013 
11014 /*
11015  *     Function: fcp_scsi_start
11016  *
11017  *  Description: This function is called by the target driver to request a
11018  *               command to be sent.
11019  *
11020  *     Argument: *ap            SCSI address of the device.
11021  *               *pkt           SCSI packet containing the cmd to send.
11022  *
11023  * Return Value: TRAN_ACCEPT
11024  *               TRAN_BUSY
11025  *               TRAN_BADPKT
11026  *               TRAN_FATAL_ERROR
11027  */
11028 static int
11029 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11030 {
11031         struct fcp_port *pptr = ADDR2FCP(ap);
11032         struct fcp_lun  *plun = ADDR2LUN(ap);
11033         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11034         struct fcp_tgt  *ptgt = plun->lun_tgt;
11035         int                     rval;
11036 
11037         /* ensure command isn't already issued */
11038         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11039 
11040         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11041             fcp_trace, FCP_BUF_LEVEL_9, 0,
11042             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11043 
11044         /*
11045          * It is strange that we enter the fcp_port mutex and the target
11046          * mutex to check the lun state (which has a mutex of its own).
11047          */
11048         mutex_enter(&pptr->port_mutex);
11049         mutex_enter(&ptgt->tgt_mutex);
11050 
11051         /*
11052          * If the device is offline and is not in the process of coming
11053          * online, fail the request.
11054          */
11055 
11056         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11057             !(plun->lun_state & FCP_LUN_ONLINING)) {
11058                 mutex_exit(&ptgt->tgt_mutex);
11059                 mutex_exit(&pptr->port_mutex);
11060 
11061                 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11062                         pkt->pkt_reason = CMD_DEV_GONE;
11063                 }
11064 
11065                 return (TRAN_FATAL_ERROR);
11066         }
11067         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11068 
11069         /*
11070          * If we are suspended, kernel is trying to dump, so don't
11071          * block, fail or defer requests - send them down right away.
11072          * NOTE: If we are in panic (i.e. trying to dump), we can't
11073          * assume we have been suspended.  There is hardware such as
11074          * the v880 that doesn't do PM.  Thus, the check for
11075          * ddi_in_panic.
11076          *
11077          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11078          * of changing.  So, if we can queue the packet, do it.  Eventually,
11079          * either the device will have gone away or changed and we can fail
11080          * the request, or we can proceed if the device didn't change.
11081          *
11082          * If the pd in the target or the packet is NULL it's probably
11083          * because the device has gone away, we allow the request to be
11084          * put on the internal queue here in case the device comes back within
11085          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11086          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11087          * could be NULL because the device was disappearing during or since
11088          * packet initialization.
11089          */
11090 
11091         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11092             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11093             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11094             (ptgt->tgt_pd_handle == NULL) ||
11095             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11096                 /*
11097                  * If ((LUN is busy AND
11098                  *      LUN not suspended AND
11099                  *      The system is not in panic state) OR
11100                  *      (The port is coming up))
11101                  *
11102                  * We check to see if the any of the flags FLAG_NOINTR or
11103                  * FLAG_NOQUEUE is set.  If one of them is set the value
11104                  * returned will be TRAN_BUSY.  If not, the request is queued.
11105                  */
11106                 mutex_exit(&ptgt->tgt_mutex);
11107                 mutex_exit(&pptr->port_mutex);
11108 
11109                 /* see if using interrupts is allowed (so queueing'll work) */
11110                 if (pkt->pkt_flags & FLAG_NOINTR) {
11111                         pkt->pkt_resid = 0;
11112                         return (TRAN_BUSY);
11113                 }
11114                 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11115                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11116                             fcp_trace, FCP_BUF_LEVEL_9, 0,
11117                             "fcp_scsi_start: lun busy for pkt %p", pkt);
11118                         return (TRAN_BUSY);
11119                 }
11120 #ifdef  DEBUG
11121                 mutex_enter(&pptr->port_pkt_mutex);
11122                 pptr->port_npkts++;
11123                 mutex_exit(&pptr->port_pkt_mutex);
11124 #endif /* DEBUG */
11125 
11126                 /* got queue up the pkt for later */
11127                 fcp_queue_pkt(pptr, cmd);
11128                 return (TRAN_ACCEPT);
11129         }
11130         cmd->cmd_state = FCP_PKT_ISSUED;
11131 
11132         mutex_exit(&ptgt->tgt_mutex);
11133         mutex_exit(&pptr->port_mutex);
11134 
11135         /*
11136          * Now that we released the mutexes, what was protected by them can
11137          * change.
11138          */
11139 
11140         /*
11141          * If there is a reconfiguration in progress, wait for it to complete.
11142          */
11143         fcp_reconfig_wait(pptr);
11144 
11145         cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11146             pkt->pkt_time : 0;
11147 
11148         /* prepare the packet */
11149 
11150         fcp_prepare_pkt(pptr, cmd, plun);
11151 
11152         if (cmd->cmd_pkt->pkt_time) {
11153                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11154         } else {
11155                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11156         }
11157 
11158         /*
11159          * if interrupts aren't allowed (e.g. at dump time) then we'll
11160          * have to do polled I/O
11161          */
11162         if (pkt->pkt_flags & FLAG_NOINTR) {
11163                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
11164                 return (fcp_dopoll(pptr, cmd));
11165         }
11166 
11167 #ifdef  DEBUG
11168         mutex_enter(&pptr->port_pkt_mutex);
11169         pptr->port_npkts++;
11170         mutex_exit(&pptr->port_pkt_mutex);
11171 #endif /* DEBUG */
11172 
11173         rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11174         if (rval == FC_SUCCESS) {
11175                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11176                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11177                     "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11178                 return (TRAN_ACCEPT);
11179         }
11180 
11181         cmd->cmd_state = FCP_PKT_IDLE;
11182 
11183 #ifdef  DEBUG
11184         mutex_enter(&pptr->port_pkt_mutex);
11185         pptr->port_npkts--;
11186         mutex_exit(&pptr->port_pkt_mutex);
11187 #endif /* DEBUG */
11188 
11189         /*
11190          * For lack of clearer definitions, choose
11191          * between TRAN_BUSY and TRAN_FATAL_ERROR.
11192          */
11193 
11194         if (rval == FC_TRAN_BUSY) {
11195                 pkt->pkt_resid = 0;
11196                 rval = TRAN_BUSY;
11197         } else {
11198                 mutex_enter(&ptgt->tgt_mutex);
11199                 if (plun->lun_state & FCP_LUN_OFFLINE) {
11200                         child_info_t    *cip;
11201 
11202                         mutex_enter(&plun->lun_mutex);
11203                         cip = plun->lun_cip;
11204                         mutex_exit(&plun->lun_mutex);
11205 
11206                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11207                             fcp_trace, FCP_BUF_LEVEL_6, 0,
11208                             "fcp_transport failed 2 for %x: %x; dip=%p",
11209                             plun->lun_tgt->tgt_d_id, rval, cip);
11210 
11211                         rval = TRAN_FATAL_ERROR;
11212                 } else {
11213                         if (pkt->pkt_flags & FLAG_NOQUEUE) {
11214                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11215                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11216                                     "fcp_scsi_start: FC_BUSY for pkt %p",
11217                                     pkt);
11218                                 rval = TRAN_BUSY;
11219                         } else {
11220                                 rval = TRAN_ACCEPT;
11221                                 fcp_queue_pkt(pptr, cmd);
11222                         }
11223                 }
11224                 mutex_exit(&ptgt->tgt_mutex);
11225         }
11226 
11227         return (rval);
11228 }
11229 
11230 /*
11231  * called by the transport to abort a packet
11232  */
11233 /*ARGSUSED*/
11234 static int
11235 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11236 {
11237         int tgt_cnt;
11238         struct fcp_port         *pptr = ADDR2FCP(ap);
11239         struct fcp_lun  *plun = ADDR2LUN(ap);
11240         struct fcp_tgt  *ptgt = plun->lun_tgt;
11241 
11242         if (pkt == NULL) {
11243                 if (ptgt) {
11244                         mutex_enter(&ptgt->tgt_mutex);
11245                         tgt_cnt = ptgt->tgt_change_cnt;
11246                         mutex_exit(&ptgt->tgt_mutex);
11247                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11248                         return (TRUE);
11249                 }
11250         }
11251         return (FALSE);
11252 }
11253 
11254 
11255 /*
11256  * Perform reset
11257  */
11258 int
11259 fcp_scsi_reset(struct scsi_address *ap, int level)
11260 {
11261         int                     rval = 0;
11262         struct fcp_port         *pptr = ADDR2FCP(ap);
11263         struct fcp_lun  *plun = ADDR2LUN(ap);
11264         struct fcp_tgt  *ptgt = plun->lun_tgt;
11265 
11266         if (level == RESET_ALL) {
11267                 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11268                         rval = 1;
11269                 }
11270         } else if (level == RESET_TARGET || level == RESET_LUN) {
11271                 /*
11272                  * If we are in the middle of discovery, return
11273                  * SUCCESS as this target will be rediscovered
11274                  * anyway
11275                  */
11276                 mutex_enter(&ptgt->tgt_mutex);
11277                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11278                         mutex_exit(&ptgt->tgt_mutex);
11279                         return (1);
11280                 }
11281                 mutex_exit(&ptgt->tgt_mutex);
11282 
11283                 if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11284                         rval = 1;
11285                 }
11286         }
11287         return (rval);
11288 }
11289 
11290 
11291 /*
11292  * called by the framework to get a SCSI capability
11293  */
11294 static int
11295 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11296 {
11297         return (fcp_commoncap(ap, cap, 0, whom, 0));
11298 }
11299 
11300 
11301 /*
11302  * called by the framework to set a SCSI capability
11303  */
11304 static int
11305 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11306 {
11307         return (fcp_commoncap(ap, cap, value, whom, 1));
11308 }
11309 
11310 /*
11311  *     Function: fcp_pkt_setup
11312  *
11313  *  Description: This function sets up the scsi_pkt structure passed by the
11314  *               caller. This function assumes fcp_pkt_constructor has been
11315  *               called previously for the packet passed by the caller.  If
11316  *               successful this call will have the following results:
11317  *
11318  *                 - The resources needed that will be constant through out
11319  *                   the whole transaction are allocated.
11320  *                 - The fields that will be constant through out the whole
11321  *                   transaction are initialized.
11322  *                 - The scsi packet will be linked to the LUN structure
11323  *                   addressed by the transaction.
11324  *
11325  *     Argument:
11326  *               *pkt           Pointer to a scsi_pkt structure.
11327  *               callback
11328  *               arg
11329  *
11330  * Return Value: 0      Success
11331  *               !0     Failure
11332  *
11333  *      Context: Kernel context or interrupt context
11334  */
11335 /* ARGSUSED */
11336 static int
11337 fcp_pkt_setup(struct scsi_pkt *pkt,
11338     int (*callback)(caddr_t arg),
11339     caddr_t arg)
11340 {
11341         struct fcp_pkt  *cmd;
11342         struct fcp_port *pptr;
11343         struct fcp_lun  *plun;
11344         struct fcp_tgt  *ptgt;
11345         int             kf;
11346         fc_packet_t     *fpkt;
11347         fc_frame_hdr_t  *hp;
11348 
11349         pptr = ADDR2FCP(&pkt->pkt_address);
11350         plun = ADDR2LUN(&pkt->pkt_address);
11351         ptgt = plun->lun_tgt;
11352 
11353         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11354         fpkt = cmd->cmd_fp_pkt;
11355 
11356         /*
11357          * this request is for dma allocation only
11358          */
11359         /*
11360          * First step of fcp_scsi_init_pkt: pkt allocation
11361          * We determine if the caller is willing to wait for the
11362          * resources.
11363          */
11364         kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11365 
11366         /*
11367          * Selective zeroing of the pkt.
11368          */
11369         cmd->cmd_back = NULL;
11370         cmd->cmd_next = NULL;
11371 
11372         /*
11373          * Zero out fcp command
11374          */
11375         bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11376 
11377         cmd->cmd_state = FCP_PKT_IDLE;
11378 
11379         fpkt = cmd->cmd_fp_pkt;
11380         fpkt->pkt_data_acc = NULL;
11381 
11382         /*
11383          * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11384          * could be destroyed.  We need fail pkt_setup.
11385          */
11386         if (pptr->port_state & FCP_STATE_OFFLINE) {
11387                 return (-1);
11388         }
11389 
11390         mutex_enter(&ptgt->tgt_mutex);
11391         fpkt->pkt_pd = ptgt->tgt_pd_handle;
11392 
11393         if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11394             != FC_SUCCESS) {
11395                 mutex_exit(&ptgt->tgt_mutex);
11396                 return (-1);
11397         }
11398 
11399         mutex_exit(&ptgt->tgt_mutex);
11400 
11401         /* Fill in the Fabric Channel Header */
11402         hp = &fpkt->pkt_cmd_fhdr;
11403         hp->r_ctl = R_CTL_COMMAND;
11404         hp->rsvd = 0;
11405         hp->type = FC_TYPE_SCSI_FCP;
11406         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11407         hp->seq_id = 0;
11408         hp->df_ctl  = 0;
11409         hp->seq_cnt = 0;
11410         hp->ox_id = 0xffff;
11411         hp->rx_id = 0xffff;
11412         hp->ro = 0;
11413 
11414         /*
11415          * A doubly linked list (cmd_forw, cmd_back) is built
11416          * out of every allocated packet on a per-lun basis
11417          *
11418          * The packets are maintained in the list so as to satisfy
11419          * scsi_abort() requests. At present (which is unlikely to
11420          * change in the future) nobody performs a real scsi_abort
11421          * in the SCSI target drivers (as they don't keep the packets
11422          * after doing scsi_transport - so they don't know how to
11423          * abort a packet other than sending a NULL to abort all
11424          * outstanding packets)
11425          */
11426         mutex_enter(&plun->lun_mutex);
11427         if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11428                 plun->lun_pkt_head->cmd_back = cmd;
11429         } else {
11430                 plun->lun_pkt_tail = cmd;
11431         }
11432         plun->lun_pkt_head = cmd;
11433         mutex_exit(&plun->lun_mutex);
11434         return (0);
11435 }
11436 
11437 /*
11438  *     Function: fcp_pkt_teardown
11439  *
11440  *  Description: This function releases a scsi_pkt structure and all the
11441  *               resources attached to it.
11442  *
11443  *     Argument: *pkt           Pointer to a scsi_pkt structure.
11444  *
11445  * Return Value: None
11446  *
11447  *      Context: User, Kernel or Interrupt context.
11448  */
11449 static void
11450 fcp_pkt_teardown(struct scsi_pkt *pkt)
11451 {
11452         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
11453         struct fcp_lun  *plun = ADDR2LUN(&pkt->pkt_address);
11454         struct fcp_pkt  *cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11455 
11456         /*
11457          * Remove the packet from the per-lun list
11458          */
11459         mutex_enter(&plun->lun_mutex);
11460         if (cmd->cmd_back) {
11461                 ASSERT(cmd != plun->lun_pkt_head);
11462                 cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11463         } else {
11464                 ASSERT(cmd == plun->lun_pkt_head);
11465                 plun->lun_pkt_head = cmd->cmd_forw;
11466         }
11467 
11468         if (cmd->cmd_forw) {
11469                 cmd->cmd_forw->cmd_back = cmd->cmd_back;
11470         } else {
11471                 ASSERT(cmd == plun->lun_pkt_tail);
11472                 plun->lun_pkt_tail = cmd->cmd_back;
11473         }
11474 
11475         mutex_exit(&plun->lun_mutex);
11476 
11477         (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11478 }
11479 
11480 /*
11481  * Routine for reset notification setup, to register or cancel.
11482  * This function is called by SCSA
11483  */
11484 /*ARGSUSED*/
11485 static int
11486 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11487     void (*callback)(caddr_t), caddr_t arg)
11488 {
11489         struct fcp_port *pptr = ADDR2FCP(ap);
11490 
11491         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11492             &pptr->port_mutex, &pptr->port_reset_notify_listf));
11493 }
11494 
11495 
11496 static int
11497 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11498     ddi_eventcookie_t *event_cookiep)
11499 {
11500         struct fcp_port *pptr = fcp_dip2port(dip);
11501 
11502         if (pptr == NULL) {
11503                 return (DDI_FAILURE);
11504         }
11505 
11506         return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11507             event_cookiep, NDI_EVENT_NOPASS));
11508 }
11509 
11510 
11511 static int
11512 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11513     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11514     ddi_callback_id_t *cb_id)
11515 {
11516         struct fcp_port *pptr = fcp_dip2port(dip);
11517 
11518         if (pptr == NULL) {
11519                 return (DDI_FAILURE);
11520         }
11521 
11522         return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11523             eventid, callback, arg, NDI_SLEEP, cb_id));
11524 }
11525 
11526 
11527 static int
11528 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11529 {
11530 
11531         struct fcp_port *pptr = fcp_dip2port(dip);
11532 
11533         if (pptr == NULL) {
11534                 return (DDI_FAILURE);
11535         }
11536         return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11537 }
11538 
11539 
11540 /*
11541  * called by the transport to post an event
11542  */
11543 static int
11544 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11545     ddi_eventcookie_t eventid, void *impldata)
11546 {
11547         struct fcp_port *pptr = fcp_dip2port(dip);
11548 
11549         if (pptr == NULL) {
11550                 return (DDI_FAILURE);
11551         }
11552 
11553         return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11554             eventid, impldata));
11555 }
11556 
11557 
11558 /*
11559  * A target in in many cases in Fibre Channel has a one to one relation
11560  * with a port identifier (which is also known as D_ID and also as AL_PA
11561  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11562  * will most likely result in resetting all LUNs (which means a reset will
11563  * occur on all the SCSI devices connected at the other end of the bridge)
11564  * That is the latest favorite topic for discussion, for, one can debate as
11565  * hot as one likes and come up with arguably a best solution to one's
11566  * satisfaction
11567  *
11568  * To stay on track and not digress much, here are the problems stated
11569  * briefly:
11570  *
11571  *      SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11572  *      target drivers use RESET_TARGET even if their instance is on a
11573  *      LUN. Doesn't that sound a bit broken ?
11574  *
11575  *      FCP SCSI (the current spec) only defines RESET TARGET in the
11576  *      control fields of an FCP_CMND structure. It should have been
11577  *      fixed right there, giving flexibility to the initiators to
11578  *      minimize havoc that could be caused by resetting a target.
11579  */
11580 static int
11581 fcp_reset_target(struct scsi_address *ap, int level)
11582 {
11583         int                     rval = FC_FAILURE;
11584         char                    lun_id[25];
11585         struct fcp_port         *pptr = ADDR2FCP(ap);
11586         struct fcp_lun  *plun = ADDR2LUN(ap);
11587         struct fcp_tgt  *ptgt = plun->lun_tgt;
11588         struct scsi_pkt         *pkt;
11589         struct fcp_pkt  *cmd;
11590         struct fcp_rsp          *rsp;
11591         uint32_t                tgt_cnt;
11592         struct fcp_rsp_info     *rsp_info;
11593         struct fcp_reset_elem   *p;
11594         int                     bval;
11595 
11596         if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11597             KM_NOSLEEP)) == NULL) {
11598                 return (rval);
11599         }
11600 
11601         mutex_enter(&ptgt->tgt_mutex);
11602         if (level == RESET_TARGET) {
11603                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11604                         mutex_exit(&ptgt->tgt_mutex);
11605                         kmem_free(p, sizeof (struct fcp_reset_elem));
11606                         return (rval);
11607                 }
11608                 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11609                 (void) strcpy(lun_id, " ");
11610         } else {
11611                 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11612                         mutex_exit(&ptgt->tgt_mutex);
11613                         kmem_free(p, sizeof (struct fcp_reset_elem));
11614                         return (rval);
11615                 }
11616                 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11617 
11618                 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11619         }
11620         tgt_cnt = ptgt->tgt_change_cnt;
11621 
11622         mutex_exit(&ptgt->tgt_mutex);
11623 
11624         if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11625             0, 0, NULL, 0)) == NULL) {
11626                 kmem_free(p, sizeof (struct fcp_reset_elem));
11627                 mutex_enter(&ptgt->tgt_mutex);
11628                 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11629                 mutex_exit(&ptgt->tgt_mutex);
11630                 return (rval);
11631         }
11632         pkt->pkt_time = FCP_POLL_TIMEOUT;
11633 
11634         /* fill in cmd part of packet */
11635         cmd = PKT2CMD(pkt);
11636         if (level == RESET_TARGET) {
11637                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11638         } else {
11639                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11640         }
11641         cmd->cmd_fp_pkt->pkt_comp = NULL;
11642         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11643 
11644         /* prepare a packet for transport */
11645         fcp_prepare_pkt(pptr, cmd, plun);
11646 
11647         if (cmd->cmd_pkt->pkt_time) {
11648                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11649         } else {
11650                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11651         }
11652 
11653         (void) fc_ulp_busy_port(pptr->port_fp_handle);
11654         bval = fcp_dopoll(pptr, cmd);
11655         fc_ulp_idle_port(pptr->port_fp_handle);
11656 
11657         /* submit the packet */
11658         if (bval == TRAN_ACCEPT) {
11659                 int error = 3;
11660 
11661                 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11662                 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11663                     sizeof (struct fcp_rsp));
11664 
11665                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
11666                         if (fcp_validate_fcp_response(rsp, pptr) ==
11667                             FC_SUCCESS) {
11668                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11669                                         FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11670                                             sizeof (struct fcp_rsp), rsp_info,
11671                                             cmd->cmd_fp_pkt->pkt_resp_acc,
11672                                             sizeof (struct fcp_rsp_info));
11673                                 }
11674                                 if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11675                                         rval = FC_SUCCESS;
11676                                         error = 0;
11677                                 } else {
11678                                         error = 1;
11679                                 }
11680                         } else {
11681                                 error = 2;
11682                         }
11683                 }
11684 
11685                 switch (error) {
11686                 case 0:
11687                         fcp_log(CE_WARN, pptr->port_dip,
11688                             "!FCP: WWN 0x%08x%08x %s reset successfully",
11689                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11690                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11691                         break;
11692 
11693                 case 1:
11694                         fcp_log(CE_WARN, pptr->port_dip,
11695                             "!FCP: Reset to WWN  0x%08x%08x %s failed,"
11696                             " response code=%x",
11697                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11698                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11699                             rsp_info->rsp_code);
11700                         break;
11701 
11702                 case 2:
11703                         fcp_log(CE_WARN, pptr->port_dip,
11704                             "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11705                             " Bad FCP response values: rsvd1=%x,"
11706                             " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11707                             " rsplen=%x, senselen=%x",
11708                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11709                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11710                             rsp->reserved_0, rsp->reserved_1,
11711                             rsp->fcp_u.fcp_status.reserved_0,
11712                             rsp->fcp_u.fcp_status.reserved_1,
11713                             rsp->fcp_response_len, rsp->fcp_sense_len);
11714                         break;
11715 
11716                 default:
11717                         fcp_log(CE_WARN, pptr->port_dip,
11718                             "!FCP: Reset to WWN  0x%08x%08x %s failed",
11719                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11720                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11721                         break;
11722                 }
11723         }
11724         scsi_destroy_pkt(pkt);
11725 
11726         if (rval == FC_FAILURE) {
11727                 mutex_enter(&ptgt->tgt_mutex);
11728                 if (level == RESET_TARGET) {
11729                         fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11730                 } else {
11731                         fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11732                 }
11733                 mutex_exit(&ptgt->tgt_mutex);
11734                 kmem_free(p, sizeof (struct fcp_reset_elem));
11735                 return (rval);
11736         }
11737 
11738         mutex_enter(&pptr->port_mutex);
11739         if (level == RESET_TARGET) {
11740                 p->tgt = ptgt;
11741                 p->lun = NULL;
11742         } else {
11743                 p->tgt = NULL;
11744                 p->lun = plun;
11745         }
11746         p->tgt = ptgt;
11747         p->tgt_cnt = tgt_cnt;
11748         p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11749         p->next = pptr->port_reset_list;
11750         pptr->port_reset_list = p;
11751 
11752         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11753             fcp_trace, FCP_BUF_LEVEL_3, 0,
11754             "Notify ssd of the reset to reinstate the reservations");
11755 
11756         scsi_hba_reset_notify_callback(&pptr->port_mutex,
11757             &pptr->port_reset_notify_listf);
11758 
11759         mutex_exit(&pptr->port_mutex);
11760 
11761         return (rval);
11762 }
11763 
11764 
11765 /*
11766  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11767  * SCSI capabilities
11768  */
11769 /* ARGSUSED */
11770 static int
11771 fcp_commoncap(struct scsi_address *ap, char *cap,
11772     int val, int tgtonly, int doset)
11773 {
11774         struct fcp_port         *pptr = ADDR2FCP(ap);
11775         struct fcp_lun  *plun = ADDR2LUN(ap);
11776         struct fcp_tgt  *ptgt = plun->lun_tgt;
11777         int                     cidx;
11778         int                     rval = FALSE;
11779 
11780         if (cap == (char *)0) {
11781                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11782                     fcp_trace, FCP_BUF_LEVEL_3, 0,
11783                     "fcp_commoncap: invalid arg");
11784                 return (rval);
11785         }
11786 
11787         if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11788                 return (UNDEFINED);
11789         }
11790 
11791         /*
11792          * Process setcap request.
11793          */
11794         if (doset) {
11795                 /*
11796                  * At present, we can only set binary (0/1) values
11797                  */
11798                 switch (cidx) {
11799                 case SCSI_CAP_ARQ:
11800                         if (val == 0) {
11801                                 rval = FALSE;
11802                         } else {
11803                                 rval = TRUE;
11804                         }
11805                         break;
11806 
11807                 case SCSI_CAP_LUN_RESET:
11808                         if (val) {
11809                                 plun->lun_cap |= FCP_LUN_CAP_RESET;
11810                         } else {
11811                                 plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11812                         }
11813                         rval = TRUE;
11814                         break;
11815 
11816                 case SCSI_CAP_SECTOR_SIZE:
11817                         rval = TRUE;
11818                         break;
11819                 default:
11820                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11821                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11822                             "fcp_setcap: unsupported %d", cidx);
11823                         rval = UNDEFINED;
11824                         break;
11825                 }
11826 
11827                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11828                     fcp_trace, FCP_BUF_LEVEL_5, 0,
11829                     "set cap: cap=%s, val/tgtonly/doset/rval = "
11830                     "0x%x/0x%x/0x%x/%d",
11831                     cap, val, tgtonly, doset, rval);
11832 
11833         } else {
11834                 /*
11835                  * Process getcap request.
11836                  */
11837                 switch (cidx) {
11838                 case SCSI_CAP_DMA_MAX:
11839                         rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11840 
11841                         /*
11842                          * Need to make an adjustment qlc is uint_t 64
11843                          * st is int, so we will make the adjustment here
11844                          * being as nobody wants to touch this.
11845                          * It still leaves the max single block length
11846                          * of 2 gig. This should last .
11847                          */
11848 
11849                         if (rval == -1) {
11850                                 rval = MAX_INT_DMA;
11851                         }
11852 
11853                         break;
11854 
11855                 case SCSI_CAP_INITIATOR_ID:
11856                         rval = pptr->port_id;
11857                         break;
11858 
11859                 case SCSI_CAP_ARQ:
11860                 case SCSI_CAP_RESET_NOTIFICATION:
11861                 case SCSI_CAP_TAGGED_QING:
11862                         rval = TRUE;
11863                         break;
11864 
11865                 case SCSI_CAP_SCSI_VERSION:
11866                         rval = 3;
11867                         break;
11868 
11869                 case SCSI_CAP_INTERCONNECT_TYPE:
11870                         if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11871                             (ptgt->tgt_hard_addr == 0)) {
11872                                 rval = INTERCONNECT_FABRIC;
11873                         } else {
11874                                 rval = INTERCONNECT_FIBRE;
11875                         }
11876                         break;
11877 
11878                 case SCSI_CAP_LUN_RESET:
11879                         rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11880                             TRUE : FALSE;
11881                         break;
11882 
11883                 default:
11884                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11885                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11886                             "fcp_getcap: unsupported %d", cidx);
11887                         rval = UNDEFINED;
11888                         break;
11889                 }
11890 
11891                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11892                     fcp_trace, FCP_BUF_LEVEL_8, 0,
11893                     "get cap: cap=%s, val/tgtonly/doset/rval = "
11894                     "0x%x/0x%x/0x%x/%d",
11895                     cap, val, tgtonly, doset, rval);
11896         }
11897 
11898         return (rval);
11899 }
11900 
11901 /*
11902  * called by the transport to get the port-wwn and lun
11903  * properties of this device, and to create a "name" based on them
11904  *
11905  * these properties don't exist on sun4m
11906  *
11907  * return 1 for success else return 0
11908  */
11909 /* ARGSUSED */
11910 static int
11911 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11912 {
11913         int                     i;
11914         int                     *lun;
11915         int                     numChars;
11916         uint_t                  nlun;
11917         uint_t                  count;
11918         uint_t                  nbytes;
11919         uchar_t                 *bytes;
11920         uint16_t                lun_num;
11921         uint32_t                tgt_id;
11922         char                    **conf_wwn;
11923         char                    tbuf[(FC_WWN_SIZE << 1) + 1];
11924         uchar_t                 barray[FC_WWN_SIZE];
11925         dev_info_t              *tgt_dip;
11926         struct fcp_tgt  *ptgt;
11927         struct fcp_port *pptr;
11928         struct fcp_lun  *plun;
11929 
11930         ASSERT(sd != NULL);
11931         ASSERT(name != NULL);
11932 
11933         tgt_dip = sd->sd_dev;
11934         pptr = ddi_get_soft_state(fcp_softstate,
11935             ddi_get_instance(ddi_get_parent(tgt_dip)));
11936         if (pptr == NULL) {
11937                 return (0);
11938         }
11939 
11940         ASSERT(tgt_dip != NULL);
11941 
11942         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11943             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11944             LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11945                 name[0] = '\0';
11946                 return (0);
11947         }
11948 
11949         if (nlun == 0) {
11950                 ddi_prop_free(lun);
11951                 return (0);
11952         }
11953 
11954         lun_num = lun[0];
11955         ddi_prop_free(lun);
11956 
11957         /*
11958          * Lookup for .conf WWN property
11959          */
11960         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
11961             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
11962             &conf_wwn, &count) == DDI_PROP_SUCCESS) {
11963                 ASSERT(count >= 1);
11964 
11965                 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
11966                 ddi_prop_free(conf_wwn);
11967                 mutex_enter(&pptr->port_mutex);
11968                 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
11969                         mutex_exit(&pptr->port_mutex);
11970                         return (0);
11971                 }
11972                 ptgt = plun->lun_tgt;
11973                 mutex_exit(&pptr->port_mutex);
11974 
11975                 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
11976                     tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
11977 
11978                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
11979                     ptgt->tgt_hard_addr != 0) {
11980                         tgt_id = (uint32_t)fcp_alpa_to_switch[
11981                             ptgt->tgt_hard_addr];
11982                 } else {
11983                         tgt_id = ptgt->tgt_d_id;
11984                 }
11985 
11986                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
11987                     TARGET_PROP, tgt_id);
11988         }
11989 
11990         /* get the our port-wwn property */
11991         bytes = NULL;
11992         if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
11993             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
11994             &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
11995                 if (bytes != NULL) {
11996                         ddi_prop_free(bytes);
11997                 }
11998                 return (0);
11999         }
12000 
12001         for (i = 0; i < FC_WWN_SIZE; i++) {
12002                 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12003         }
12004 
12005         /* Stick in the address of the form "wWWN,LUN" */
12006         numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12007 
12008         ASSERT(numChars < len);
12009         if (numChars >= len) {
12010                 fcp_log(CE_WARN, pptr->port_dip,
12011                     "!fcp_scsi_get_name: "
12012                     "name parameter length too small, it needs to be %d",
12013                     numChars+1);
12014         }
12015 
12016         ddi_prop_free(bytes);
12017 
12018         return (1);
12019 }
12020 
12021 
12022 /*
12023  * called by the transport to get the SCSI target id value, returning
12024  * it in "name"
12025  *
12026  * this isn't needed/used on sun4m
12027  *
12028  * return 1 for success else return 0
12029  */
12030 /* ARGSUSED */
12031 static int
12032 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12033 {
12034         struct fcp_lun  *plun = ADDR2LUN(&sd->sd_address);
12035         struct fcp_tgt  *ptgt;
12036         int    numChars;
12037 
12038         if (plun == NULL) {
12039                 return (0);
12040         }
12041 
12042         if ((ptgt = plun->lun_tgt) == NULL) {
12043                 return (0);
12044         }
12045 
12046         numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12047 
12048         ASSERT(numChars < len);
12049         if (numChars >= len) {
12050                 fcp_log(CE_WARN, NULL,
12051                     "!fcp_scsi_get_bus_addr: "
12052                     "name parameter length too small, it needs to be %d",
12053                     numChars+1);
12054         }
12055 
12056         return (1);
12057 }
12058 
12059 
12060 /*
12061  * called internally to reset the link where the specified port lives
12062  */
12063 static int
12064 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12065 {
12066         la_wwn_t                wwn;
12067         struct fcp_lun  *plun;
12068         struct fcp_tgt  *ptgt;
12069 
12070         /* disable restart of lip if we're suspended */
12071         mutex_enter(&pptr->port_mutex);
12072 
12073         if (pptr->port_state & (FCP_STATE_SUSPENDED |
12074             FCP_STATE_POWER_DOWN)) {
12075                 mutex_exit(&pptr->port_mutex);
12076                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12077                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12078                     "fcp_linkreset, fcp%d: link reset "
12079                     "disabled due to DDI_SUSPEND",
12080                     ddi_get_instance(pptr->port_dip));
12081                 return (FC_FAILURE);
12082         }
12083 
12084         if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12085                 mutex_exit(&pptr->port_mutex);
12086                 return (FC_SUCCESS);
12087         }
12088 
12089         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12090             fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12091 
12092         /*
12093          * If ap == NULL assume local link reset.
12094          */
12095         if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12096                 plun = ADDR2LUN(ap);
12097                 ptgt = plun->lun_tgt;
12098                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12099         } else {
12100                 bzero((caddr_t)&wwn, sizeof (wwn));
12101         }
12102         mutex_exit(&pptr->port_mutex);
12103 
12104         return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12105 }
12106 
12107 
12108 /*
12109  * called from fcp_port_attach() to resume a port
12110  * return DDI_* success/failure status
12111  * acquires and releases the global mutex
12112  * acquires and releases the port mutex
12113  */
12114 /*ARGSUSED*/
12115 
12116 static int
12117 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12118     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12119 {
12120         int                     res = DDI_FAILURE; /* default result */
12121         struct fcp_port *pptr;          /* port state ptr */
12122         uint32_t                alloc_cnt;
12123         uint32_t                max_cnt;
12124         fc_portmap_t            *tmp_list = NULL;
12125 
12126         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12127             FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12128             instance);
12129 
12130         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12131                 cmn_err(CE_WARN, "fcp: bad soft state");
12132                 return (res);
12133         }
12134 
12135         mutex_enter(&pptr->port_mutex);
12136         switch (cmd) {
12137         case FC_CMD_RESUME:
12138                 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12139                 pptr->port_state &= ~FCP_STATE_SUSPENDED;
12140                 break;
12141 
12142         case FC_CMD_POWER_UP:
12143                 /*
12144                  * If the port is DDI_SUSPENded, defer rediscovery
12145                  * until DDI_RESUME occurs
12146                  */
12147                 if (pptr->port_state & FCP_STATE_SUSPENDED) {
12148                         pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12149                         mutex_exit(&pptr->port_mutex);
12150                         return (DDI_SUCCESS);
12151                 }
12152                 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12153         }
12154         pptr->port_id = s_id;
12155         pptr->port_state = FCP_STATE_INIT;
12156         mutex_exit(&pptr->port_mutex);
12157 
12158         /*
12159          * Make a copy of ulp_port_info as fctl allocates
12160          * a temp struct.
12161          */
12162         (void) fcp_cp_pinfo(pptr, pinfo);
12163 
12164         mutex_enter(&fcp_global_mutex);
12165         if (fcp_watchdog_init++ == 0) {
12166                 fcp_watchdog_tick = fcp_watchdog_timeout *
12167                     drv_usectohz(1000000);
12168                 fcp_watchdog_id = timeout(fcp_watch,
12169                     NULL, fcp_watchdog_tick);
12170         }
12171         mutex_exit(&fcp_global_mutex);
12172 
12173         /*
12174          * Handle various topologies and link states.
12175          */
12176         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12177         case FC_STATE_OFFLINE:
12178                 /*
12179                  * Wait for ONLINE, at which time a state
12180                  * change will cause a statec_callback
12181                  */
12182                 res = DDI_SUCCESS;
12183                 break;
12184 
12185         case FC_STATE_ONLINE:
12186 
12187                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
12188                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12189                         res = DDI_SUCCESS;
12190                         break;
12191                 }
12192 
12193                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12194                     !fcp_enable_auto_configuration) {
12195                         tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12196                         if (tmp_list == NULL) {
12197                                 if (!alloc_cnt) {
12198                                         res = DDI_SUCCESS;
12199                                 }
12200                                 break;
12201                         }
12202                         max_cnt = alloc_cnt;
12203                 } else {
12204                         ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12205 
12206                         alloc_cnt = FCP_MAX_DEVICES;
12207 
12208                         if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12209                             (sizeof (fc_portmap_t)) * alloc_cnt,
12210                             KM_NOSLEEP)) == NULL) {
12211                                 fcp_log(CE_WARN, pptr->port_dip,
12212                                     "!fcp%d: failed to allocate portmap",
12213                                     instance);
12214                                 break;
12215                         }
12216 
12217                         max_cnt = alloc_cnt;
12218                         if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12219                             &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12220                             FC_SUCCESS) {
12221                                 caddr_t msg;
12222 
12223                                 (void) fc_ulp_error(res, &msg);
12224 
12225                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12226                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12227                                     "resume failed getportmap: reason=0x%x",
12228                                     res);
12229 
12230                                 fcp_log(CE_WARN, pptr->port_dip,
12231                                     "!failed to get port map : %s", msg);
12232                                 break;
12233                         }
12234                         if (max_cnt > alloc_cnt) {
12235                                 alloc_cnt = max_cnt;
12236                         }
12237                 }
12238 
12239                 /*
12240                  * do the SCSI device discovery and create
12241                  * the devinfos
12242                  */
12243                 fcp_statec_callback(ulph, pptr->port_fp_handle,
12244                     pptr->port_phys_state, pptr->port_topology, tmp_list,
12245                     max_cnt, pptr->port_id);
12246 
12247                 res = DDI_SUCCESS;
12248                 break;
12249 
12250         default:
12251                 fcp_log(CE_WARN, pptr->port_dip,
12252                     "!fcp%d: invalid port state at attach=0x%x",
12253                     instance, pptr->port_phys_state);
12254 
12255                 mutex_enter(&pptr->port_mutex);
12256                 pptr->port_phys_state = FCP_STATE_OFFLINE;
12257                 mutex_exit(&pptr->port_mutex);
12258                 res = DDI_SUCCESS;
12259 
12260                 break;
12261         }
12262 
12263         if (tmp_list != NULL) {
12264                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12265         }
12266 
12267         return (res);
12268 }
12269 
12270 
12271 static void
12272 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12273 {
12274         pptr->port_fp_modlinkage = *pinfo->port_linkage;
12275         pptr->port_dip = pinfo->port_dip;
12276         pptr->port_fp_handle = pinfo->port_handle;
12277         if (pinfo->port_acc_attr != NULL) {
12278                 /*
12279                  * FCA supports DMA
12280                  */
12281                 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12282                 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12283                 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12284                 pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12285         }
12286         pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12287         pptr->port_max_exch = pinfo->port_fca_max_exch;
12288         pptr->port_phys_state = pinfo->port_state;
12289         pptr->port_topology = pinfo->port_flags;
12290         pptr->port_reset_action = pinfo->port_reset_action;
12291         pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12292         pptr->port_fcp_dma = pinfo->port_fcp_dma;
12293         bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12294         bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12295 
12296         /* Clear FMA caps to avoid fm-capability ereport */
12297         if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12298                 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12299         if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12300                 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12301         if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12302                 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12303 }
12304 
12305 /*
12306  * If the elements wait field is set to 1 then
12307  * another thread is waiting for the operation to complete. Once
12308  * it is complete, the waiting thread is signaled and the element is
12309  * freed by the waiting thread. If the elements wait field is set to 0
12310  * the element is freed.
12311  */
12312 static void
12313 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12314 {
12315         ASSERT(elem != NULL);
12316         mutex_enter(&elem->mutex);
12317         elem->result = result;
12318         if (elem->wait) {
12319                 elem->wait = 0;
12320                 cv_signal(&elem->cv);
12321                 mutex_exit(&elem->mutex);
12322         } else {
12323                 mutex_exit(&elem->mutex);
12324                 cv_destroy(&elem->cv);
12325                 mutex_destroy(&elem->mutex);
12326                 kmem_free(elem, sizeof (struct fcp_hp_elem));
12327         }
12328 }
12329 
12330 /*
12331  * This function is invoked from the taskq thread to allocate
12332  * devinfo nodes and to online/offline them.
12333  */
12334 static void
12335 fcp_hp_task(void *arg)
12336 {
12337         struct fcp_hp_elem      *elem = (struct fcp_hp_elem *)arg;
12338         struct fcp_lun  *plun = elem->lun;
12339         struct fcp_port         *pptr = elem->port;
12340         int                     result;
12341 
12342         ASSERT(elem->what == FCP_ONLINE ||
12343             elem->what == FCP_OFFLINE ||
12344             elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12345             elem->what == FCP_MPXIO_PATH_SET_BUSY);
12346 
12347         mutex_enter(&pptr->port_mutex);
12348         mutex_enter(&plun->lun_mutex);
12349         if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12350             plun->lun_event_count != elem->event_cnt) ||
12351             pptr->port_state & (FCP_STATE_SUSPENDED |
12352             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12353                 mutex_exit(&plun->lun_mutex);
12354                 mutex_exit(&pptr->port_mutex);
12355                 fcp_process_elem(elem, NDI_FAILURE);
12356                 return;
12357         }
12358         mutex_exit(&plun->lun_mutex);
12359         mutex_exit(&pptr->port_mutex);
12360 
12361         result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12362             elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12363         fcp_process_elem(elem, result);
12364 }
12365 
12366 
12367 static child_info_t *
12368 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12369     int tcount)
12370 {
12371         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12372 
12373         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12374                 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12375 
12376                 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12377                 /*
12378                  * Child has not been created yet. Create the child device
12379                  * based on the per-Lun flags.
12380                  */
12381                 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12382                         plun->lun_cip =
12383                             CIP(fcp_create_dip(plun, lcount, tcount));
12384                         plun->lun_mpxio = 0;
12385                 } else {
12386                         plun->lun_cip =
12387                             CIP(fcp_create_pip(plun, lcount, tcount));
12388                         plun->lun_mpxio = 1;
12389                 }
12390         } else {
12391                 plun->lun_cip = cip;
12392         }
12393 
12394         return (plun->lun_cip);
12395 }
12396 
12397 
12398 static int
12399 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12400 {
12401         int             rval = FC_FAILURE;
12402         dev_info_t      *pdip;
12403         struct dev_info *dip;
12404         int             circular;
12405 
12406         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12407 
12408         pdip = plun->lun_tgt->tgt_port->port_dip;
12409 
12410         if (plun->lun_cip == NULL) {
12411                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12412                     fcp_trace, FCP_BUF_LEVEL_3, 0,
12413                     "fcp_is_dip_present: plun->lun_cip is NULL: "
12414                     "plun: %p lun state: %x num: %d target state: %x",
12415                     plun, plun->lun_state, plun->lun_num,
12416                     plun->lun_tgt->tgt_port->port_state);
12417                 return (rval);
12418         }
12419         ndi_devi_enter(pdip, &circular);
12420         dip = DEVI(pdip)->devi_child;
12421         while (dip) {
12422                 if (dip == DEVI(cdip)) {
12423                         rval = FC_SUCCESS;
12424                         break;
12425                 }
12426                 dip = dip->devi_sibling;
12427         }
12428         ndi_devi_exit(pdip, circular);
12429         return (rval);
12430 }
12431 
12432 static int
12433 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12434 {
12435         int             rval = FC_FAILURE;
12436 
12437         ASSERT(plun != NULL);
12438         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12439 
12440         if (plun->lun_mpxio == 0) {
12441                 rval = fcp_is_dip_present(plun, DIP(cip));
12442         } else {
12443                 rval = fcp_is_pip_present(plun, PIP(cip));
12444         }
12445 
12446         return (rval);
12447 }
12448 
12449 /*
12450  *     Function: fcp_create_dip
12451  *
12452  *  Description: Creates a dev_info_t structure for the LUN specified by the
12453  *               caller.
12454  *
12455  *     Argument: plun           Lun structure
12456  *               link_cnt       Link state count.
12457  *               tgt_cnt        Target state change count.
12458  *
12459  * Return Value: NULL if it failed
12460  *               dev_info_t structure address if it succeeded
12461  *
12462  *      Context: Kernel context
12463  */
12464 static dev_info_t *
12465 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12466 {
12467         int                     failure = 0;
12468         uint32_t                tgt_id;
12469         uint64_t                sam_lun;
12470         struct fcp_tgt  *ptgt = plun->lun_tgt;
12471         struct fcp_port *pptr = ptgt->tgt_port;
12472         dev_info_t              *pdip = pptr->port_dip;
12473         dev_info_t              *cdip = NULL;
12474         dev_info_t              *old_dip = DIP(plun->lun_cip);
12475         char                    *nname = NULL;
12476         char                    **compatible = NULL;
12477         int                     ncompatible;
12478         char                    *scsi_binding_set;
12479         char                    t_pwwn[17];
12480 
12481         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12482         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12483 
12484         /* get the 'scsi-binding-set' property */
12485         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12486             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12487             &scsi_binding_set) != DDI_PROP_SUCCESS) {
12488                 scsi_binding_set = NULL;
12489         }
12490 
12491         /* determine the node name and compatible */
12492         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12493             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12494         if (scsi_binding_set) {
12495                 ddi_prop_free(scsi_binding_set);
12496         }
12497 
12498         if (nname == NULL) {
12499 #ifdef  DEBUG
12500                 cmn_err(CE_WARN, "%s%d: no driver for "
12501                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12502                     "    compatible: %s",
12503                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12504                     ptgt->tgt_port_wwn.raw_wwn[0],
12505                     ptgt->tgt_port_wwn.raw_wwn[1],
12506                     ptgt->tgt_port_wwn.raw_wwn[2],
12507                     ptgt->tgt_port_wwn.raw_wwn[3],
12508                     ptgt->tgt_port_wwn.raw_wwn[4],
12509                     ptgt->tgt_port_wwn.raw_wwn[5],
12510                     ptgt->tgt_port_wwn.raw_wwn[6],
12511                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12512                     *compatible);
12513 #endif  /* DEBUG */
12514                 failure++;
12515                 goto end_of_fcp_create_dip;
12516         }
12517 
12518         cdip = fcp_find_existing_dip(plun, pdip, nname);
12519 
12520         /*
12521          * if the old_dip does not match the cdip, that means there is
12522          * some property change. since we'll be using the cdip, we need
12523          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12524          * then the dtype for the device has been updated. Offline the
12525          * the old device and create a new device with the new device type
12526          * Refer to bug: 4764752
12527          */
12528         if (old_dip && (cdip != old_dip ||
12529             plun->lun_state & FCP_LUN_CHANGED)) {
12530                 plun->lun_state &= ~(FCP_LUN_INIT);
12531                 mutex_exit(&plun->lun_mutex);
12532                 mutex_exit(&pptr->port_mutex);
12533 
12534                 mutex_enter(&ptgt->tgt_mutex);
12535                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12536                     link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12537                 mutex_exit(&ptgt->tgt_mutex);
12538 
12539 #ifdef DEBUG
12540                 if (cdip != NULL) {
12541                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12542                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12543                             "Old dip=%p; New dip=%p don't match", old_dip,
12544                             cdip);
12545                 } else {
12546                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12547                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12548                             "Old dip=%p; New dip=NULL don't match", old_dip);
12549                 }
12550 #endif
12551 
12552                 mutex_enter(&pptr->port_mutex);
12553                 mutex_enter(&plun->lun_mutex);
12554         }
12555 
12556         if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12557                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12558                 if (ndi_devi_alloc(pptr->port_dip, nname,
12559                     DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12560                         failure++;
12561                         goto end_of_fcp_create_dip;
12562                 }
12563         }
12564 
12565         /*
12566          * Previously all the properties for the devinfo were destroyed here
12567          * with a call to ndi_prop_remove_all(). Since this may cause loss of
12568          * the devid property (and other properties established by the target
12569          * driver or framework) which the code does not always recreate, this
12570          * call was removed.
12571          * This opens a theoretical possibility that we may return with a
12572          * stale devid on the node if the scsi entity behind the fibre channel
12573          * lun has changed.
12574          */
12575 
12576         /* decorate the node with compatible */
12577         if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12578             "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12579                 failure++;
12580                 goto end_of_fcp_create_dip;
12581         }
12582 
12583         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12584             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12585                 failure++;
12586                 goto end_of_fcp_create_dip;
12587         }
12588 
12589         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12590             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12591                 failure++;
12592                 goto end_of_fcp_create_dip;
12593         }
12594 
12595         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12596         t_pwwn[16] = '\0';
12597         if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12598             != DDI_PROP_SUCCESS) {
12599                 failure++;
12600                 goto end_of_fcp_create_dip;
12601         }
12602 
12603         /*
12604          * If there is no hard address - We might have to deal with
12605          * that by using WWN - Having said that it is important to
12606          * recognize this problem early so ssd can be informed of
12607          * the right interconnect type.
12608          */
12609         if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12610                 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12611         } else {
12612                 tgt_id = ptgt->tgt_d_id;
12613         }
12614 
12615         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12616             tgt_id) != DDI_PROP_SUCCESS) {
12617                 failure++;
12618                 goto end_of_fcp_create_dip;
12619         }
12620 
12621         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12622             (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12623                 failure++;
12624                 goto end_of_fcp_create_dip;
12625         }
12626         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12627         if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12628             sam_lun) != DDI_PROP_SUCCESS) {
12629                 failure++;
12630                 goto end_of_fcp_create_dip;
12631         }
12632 
12633 end_of_fcp_create_dip:
12634         scsi_hba_nodename_compatible_free(nname, compatible);
12635 
12636         if (cdip != NULL && failure) {
12637                 (void) ndi_prop_remove_all(cdip);
12638                 (void) ndi_devi_free(cdip);
12639                 cdip = NULL;
12640         }
12641 
12642         return (cdip);
12643 }
12644 
12645 /*
12646  *     Function: fcp_create_pip
12647  *
12648  *  Description: Creates a Path Id for the LUN specified by the caller.
12649  *
12650  *     Argument: plun           Lun structure
12651  *               link_cnt       Link state count.
12652  *               tgt_cnt        Target state count.
12653  *
12654  * Return Value: NULL if it failed
12655  *               mdi_pathinfo_t structure address if it succeeded
12656  *
12657  *      Context: Kernel context
12658  */
12659 static mdi_pathinfo_t *
12660 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12661 {
12662         int                     i;
12663         char                    buf[MAXNAMELEN];
12664         char                    uaddr[MAXNAMELEN];
12665         int                     failure = 0;
12666         uint32_t                tgt_id;
12667         uint64_t                sam_lun;
12668         struct fcp_tgt  *ptgt = plun->lun_tgt;
12669         struct fcp_port *pptr = ptgt->tgt_port;
12670         dev_info_t              *pdip = pptr->port_dip;
12671         mdi_pathinfo_t          *pip = NULL;
12672         mdi_pathinfo_t          *old_pip = PIP(plun->lun_cip);
12673         char                    *nname = NULL;
12674         char                    **compatible = NULL;
12675         int                     ncompatible;
12676         char                    *scsi_binding_set;
12677         char                    t_pwwn[17];
12678 
12679         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12680         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12681 
12682         scsi_binding_set = "vhci";
12683 
12684         /* determine the node name and compatible */
12685         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12686             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12687 
12688         if (nname == NULL) {
12689 #ifdef  DEBUG
12690                 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12691                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12692                     "    compatible: %s",
12693                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12694                     ptgt->tgt_port_wwn.raw_wwn[0],
12695                     ptgt->tgt_port_wwn.raw_wwn[1],
12696                     ptgt->tgt_port_wwn.raw_wwn[2],
12697                     ptgt->tgt_port_wwn.raw_wwn[3],
12698                     ptgt->tgt_port_wwn.raw_wwn[4],
12699                     ptgt->tgt_port_wwn.raw_wwn[5],
12700                     ptgt->tgt_port_wwn.raw_wwn[6],
12701                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12702                     *compatible);
12703 #endif  /* DEBUG */
12704                 failure++;
12705                 goto end_of_fcp_create_pip;
12706         }
12707 
12708         pip = fcp_find_existing_pip(plun, pdip);
12709 
12710         /*
12711          * if the old_dip does not match the cdip, that means there is
12712          * some property change. since we'll be using the cdip, we need
12713          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12714          * then the dtype for the device has been updated. Offline the
12715          * the old device and create a new device with the new device type
12716          * Refer to bug: 4764752
12717          */
12718         if (old_pip && (pip != old_pip ||
12719             plun->lun_state & FCP_LUN_CHANGED)) {
12720                 plun->lun_state &= ~(FCP_LUN_INIT);
12721                 mutex_exit(&plun->lun_mutex);
12722                 mutex_exit(&pptr->port_mutex);
12723 
12724                 mutex_enter(&ptgt->tgt_mutex);
12725                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12726                     FCP_OFFLINE, lcount, tcount,
12727                     NDI_DEVI_REMOVE, 0);
12728                 mutex_exit(&ptgt->tgt_mutex);
12729 
12730                 if (pip != NULL) {
12731                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12732                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12733                             "Old pip=%p; New pip=%p don't match",
12734                             old_pip, pip);
12735                 } else {
12736                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12737                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12738                             "Old pip=%p; New pip=NULL don't match",
12739                             old_pip);
12740                 }
12741 
12742                 mutex_enter(&pptr->port_mutex);
12743                 mutex_enter(&plun->lun_mutex);
12744         }
12745 
12746         /*
12747          * Since FC_WWN_SIZE is 8 bytes and its not like the
12748          * lun_guid_size which is dependent on the target, I don't
12749          * believe the same trancation happens here UNLESS the standards
12750          * change the FC_WWN_SIZE value to something larger than
12751          * MAXNAMELEN(currently 255 bytes).
12752          */
12753 
12754         for (i = 0; i < FC_WWN_SIZE; i++) {
12755                 (void) sprintf(&buf[i << 1], "%02x",
12756                     ptgt->tgt_port_wwn.raw_wwn[i]);
12757         }
12758 
12759         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12760             buf, plun->lun_num);
12761 
12762         if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12763                 /*
12764                  * Release the locks before calling into
12765                  * mdi_pi_alloc_compatible() since this can result in a
12766                  * callback into fcp which can result in a deadlock
12767                  * (see bug # 4870272).
12768                  *
12769                  * Basically, what we are trying to avoid is the scenario where
12770                  * one thread does ndi_devi_enter() and tries to grab
12771                  * fcp_mutex and another does it the other way round.
12772                  *
12773                  * But before we do that, make sure that nobody releases the
12774                  * port in the meantime. We can do this by setting a flag.
12775                  */
12776                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12777                 pptr->port_state |= FCP_STATE_IN_MDI;
12778                 mutex_exit(&plun->lun_mutex);
12779                 mutex_exit(&pptr->port_mutex);
12780                 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12781                     uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12782                         fcp_log(CE_WARN, pptr->port_dip,
12783                             "!path alloc failed:0x%x", plun);
12784                         mutex_enter(&pptr->port_mutex);
12785                         mutex_enter(&plun->lun_mutex);
12786                         pptr->port_state &= ~FCP_STATE_IN_MDI;
12787                         failure++;
12788                         goto end_of_fcp_create_pip;
12789                 }
12790                 mutex_enter(&pptr->port_mutex);
12791                 mutex_enter(&plun->lun_mutex);
12792                 pptr->port_state &= ~FCP_STATE_IN_MDI;
12793         } else {
12794                 (void) mdi_prop_remove(pip, NULL);
12795         }
12796 
12797         mdi_pi_set_phci_private(pip, (caddr_t)plun);
12798 
12799         if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12800             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12801             != DDI_PROP_SUCCESS) {
12802                 failure++;
12803                 goto end_of_fcp_create_pip;
12804         }
12805 
12806         if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12807             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12808             != DDI_PROP_SUCCESS) {
12809                 failure++;
12810                 goto end_of_fcp_create_pip;
12811         }
12812 
12813         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12814         t_pwwn[16] = '\0';
12815         if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12816             != DDI_PROP_SUCCESS) {
12817                 failure++;
12818                 goto end_of_fcp_create_pip;
12819         }
12820 
12821         /*
12822          * If there is no hard address - We might have to deal with
12823          * that by using WWN - Having said that it is important to
12824          * recognize this problem early so ssd can be informed of
12825          * the right interconnect type.
12826          */
12827         if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12828             ptgt->tgt_hard_addr != 0) {
12829                 tgt_id = (uint32_t)
12830                     fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12831         } else {
12832                 tgt_id = ptgt->tgt_d_id;
12833         }
12834 
12835         if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12836             != DDI_PROP_SUCCESS) {
12837                 failure++;
12838                 goto end_of_fcp_create_pip;
12839         }
12840 
12841         if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12842             != DDI_PROP_SUCCESS) {
12843                 failure++;
12844                 goto end_of_fcp_create_pip;
12845         }
12846         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12847         if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12848             != DDI_PROP_SUCCESS) {
12849                 failure++;
12850                 goto end_of_fcp_create_pip;
12851         }
12852 
12853 end_of_fcp_create_pip:
12854         scsi_hba_nodename_compatible_free(nname, compatible);
12855 
12856         if (pip != NULL && failure) {
12857                 (void) mdi_prop_remove(pip, NULL);
12858                 mutex_exit(&plun->lun_mutex);
12859                 mutex_exit(&pptr->port_mutex);
12860                 (void) mdi_pi_free(pip, 0);
12861                 mutex_enter(&pptr->port_mutex);
12862                 mutex_enter(&plun->lun_mutex);
12863                 pip = NULL;
12864         }
12865 
12866         return (pip);
12867 }
12868 
12869 static dev_info_t *
12870 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12871 {
12872         uint_t                  nbytes;
12873         uchar_t                 *bytes;
12874         uint_t                  nwords;
12875         uint32_t                tgt_id;
12876         int                     *words;
12877         dev_info_t              *cdip;
12878         dev_info_t              *ndip;
12879         struct fcp_tgt  *ptgt = plun->lun_tgt;
12880         struct fcp_port *pptr = ptgt->tgt_port;
12881         int                     circular;
12882 
12883         ndi_devi_enter(pdip, &circular);
12884 
12885         ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12886         while ((cdip = ndip) != NULL) {
12887                 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12888 
12889                 if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12890                         continue;
12891                 }
12892 
12893                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12894                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12895                     &nbytes) != DDI_PROP_SUCCESS) {
12896                         continue;
12897                 }
12898 
12899                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12900                         if (bytes != NULL) {
12901                                 ddi_prop_free(bytes);
12902                         }
12903                         continue;
12904                 }
12905                 ASSERT(bytes != NULL);
12906 
12907                 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12908                         ddi_prop_free(bytes);
12909                         continue;
12910                 }
12911 
12912                 ddi_prop_free(bytes);
12913 
12914                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12915                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12916                     &nbytes) != DDI_PROP_SUCCESS) {
12917                         continue;
12918                 }
12919 
12920                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12921                         if (bytes != NULL) {
12922                                 ddi_prop_free(bytes);
12923                         }
12924                         continue;
12925                 }
12926                 ASSERT(bytes != NULL);
12927 
12928                 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12929                         ddi_prop_free(bytes);
12930                         continue;
12931                 }
12932 
12933                 ddi_prop_free(bytes);
12934 
12935                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12936                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12937                     &nwords) != DDI_PROP_SUCCESS) {
12938                         continue;
12939                 }
12940 
12941                 if (nwords != 1 || words == NULL) {
12942                         if (words != NULL) {
12943                                 ddi_prop_free(words);
12944                         }
12945                         continue;
12946                 }
12947                 ASSERT(words != NULL);
12948 
12949                 /*
12950                  * If there is no hard address - We might have to deal with
12951                  * that by using WWN - Having said that it is important to
12952                  * recognize this problem early so ssd can be informed of
12953                  * the right interconnect type.
12954                  */
12955                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12956                     ptgt->tgt_hard_addr != 0) {
12957                         tgt_id =
12958                             (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12959                 } else {
12960                         tgt_id = ptgt->tgt_d_id;
12961                 }
12962 
12963                 if (tgt_id != (uint32_t)*words) {
12964                         ddi_prop_free(words);
12965                         continue;
12966                 }
12967                 ddi_prop_free(words);
12968 
12969                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12970                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
12971                     &nwords) != DDI_PROP_SUCCESS) {
12972                         continue;
12973                 }
12974 
12975                 if (nwords != 1 || words == NULL) {
12976                         if (words != NULL) {
12977                                 ddi_prop_free(words);
12978                         }
12979                         continue;
12980                 }
12981                 ASSERT(words != NULL);
12982 
12983                 if (plun->lun_num == (uint16_t)*words) {
12984                         ddi_prop_free(words);
12985                         break;
12986                 }
12987                 ddi_prop_free(words);
12988         }
12989         ndi_devi_exit(pdip, circular);
12990 
12991         return (cdip);
12992 }
12993 
12994 
12995 static int
12996 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
12997 {
12998         dev_info_t      *pdip;
12999         char            buf[MAXNAMELEN];
13000         char            uaddr[MAXNAMELEN];
13001         int             rval = FC_FAILURE;
13002 
13003         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13004 
13005         pdip = plun->lun_tgt->tgt_port->port_dip;
13006 
13007         /*
13008          * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13009          * non-NULL even when the LUN is not there as in the case when a LUN is
13010          * configured and then deleted on the device end (for T3/T4 case). In
13011          * such cases, pip will be NULL.
13012          *
13013          * If the device generates an RSCN, it will end up getting offlined when
13014          * it disappeared and a new LUN will get created when it is rediscovered
13015          * on the device. If we check for lun_cip here, the LUN will not end
13016          * up getting onlined since this function will end up returning a
13017          * FC_SUCCESS.
13018          *
13019          * The behavior is different on other devices. For instance, on a HDS,
13020          * there was no RSCN generated by the device but the next I/O generated
13021          * a check condition and rediscovery got triggered that way. So, in
13022          * such cases, this path will not be exercised
13023          */
13024         if (pip == NULL) {
13025                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13026                     fcp_trace, FCP_BUF_LEVEL_4, 0,
13027                     "fcp_is_pip_present: plun->lun_cip is NULL: "
13028                     "plun: %p lun state: %x num: %d target state: %x",
13029                     plun, plun->lun_state, plun->lun_num,
13030                     plun->lun_tgt->tgt_port->port_state);
13031                 return (rval);
13032         }
13033 
13034         fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13035 
13036         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13037 
13038         if (plun->lun_old_guid) {
13039                 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13040                         rval = FC_SUCCESS;
13041                 }
13042         } else {
13043                 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13044                         rval = FC_SUCCESS;
13045                 }
13046         }
13047         return (rval);
13048 }
13049 
13050 static mdi_pathinfo_t *
13051 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13052 {
13053         char                    buf[MAXNAMELEN];
13054         char                    uaddr[MAXNAMELEN];
13055         mdi_pathinfo_t          *pip;
13056         struct fcp_tgt  *ptgt = plun->lun_tgt;
13057         struct fcp_port *pptr = ptgt->tgt_port;
13058 
13059         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13060 
13061         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13062         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13063 
13064         pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13065 
13066         return (pip);
13067 }
13068 
13069 
13070 static int
13071 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13072     int tcount, int flags, int *circ)
13073 {
13074         int                     rval;
13075         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
13076         struct fcp_tgt  *ptgt = plun->lun_tgt;
13077         dev_info_t              *cdip = NULL;
13078 
13079         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13080         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13081 
13082         if (plun->lun_cip == NULL) {
13083                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13084                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13085                     "fcp_online_child: plun->lun_cip is NULL: "
13086                     "plun: %p state: %x num: %d target state: %x",
13087                     plun, plun->lun_state, plun->lun_num,
13088                     plun->lun_tgt->tgt_port->port_state);
13089                 return (NDI_FAILURE);
13090         }
13091 again:
13092         if (plun->lun_mpxio == 0) {
13093                 cdip = DIP(cip);
13094                 mutex_exit(&plun->lun_mutex);
13095                 mutex_exit(&pptr->port_mutex);
13096 
13097                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13098                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13099                     "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13100                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13101 
13102                 /*
13103                  * We could check for FCP_LUN_INIT here but chances
13104                  * of getting here when it's already in FCP_LUN_INIT
13105                  * is rare and a duplicate ndi_devi_online wouldn't
13106                  * hurt either (as the node would already have been
13107                  * in CF2)
13108                  */
13109                 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13110                         rval = ndi_devi_bind_driver(cdip, flags);
13111                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13112                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13113                             "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13114                 } else {
13115                         rval = ndi_devi_online(cdip, flags);
13116                 }
13117 
13118                 /*
13119                  * We log the message into trace buffer if the device
13120                  * is "ses" and into syslog for any other device
13121                  * type. This is to prevent the ndi_devi_online failure
13122                  * message that appears for V880/A5K ses devices.
13123                  */
13124                 if (rval == NDI_SUCCESS) {
13125                         mutex_enter(&ptgt->tgt_mutex);
13126                         plun->lun_state |= FCP_LUN_INIT;
13127                         mutex_exit(&ptgt->tgt_mutex);
13128                 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13129                         fcp_log(CE_NOTE, pptr->port_dip,
13130                             "!ndi_devi_online:"
13131                             " failed for %s: target=%x lun=%x %x",
13132                             ddi_get_name(cdip), ptgt->tgt_d_id,
13133                             plun->lun_num, rval);
13134                 } else {
13135                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13136                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13137                             " !ndi_devi_online:"
13138                             " failed for %s: target=%x lun=%x %x",
13139                             ddi_get_name(cdip), ptgt->tgt_d_id,
13140                             plun->lun_num, rval);
13141                 }
13142         } else {
13143                 cdip = mdi_pi_get_client(PIP(cip));
13144                 mutex_exit(&plun->lun_mutex);
13145                 mutex_exit(&pptr->port_mutex);
13146 
13147                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13148                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13149                     "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13150                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13151 
13152                 /*
13153                  * Hold path and exit phci to avoid deadlock with power
13154                  * management code during mdi_pi_online.
13155                  */
13156                 mdi_hold_path(PIP(cip));
13157                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13158 
13159                 rval = mdi_pi_online(PIP(cip), flags);
13160 
13161                 mdi_devi_enter_phci(pptr->port_dip, circ);
13162                 mdi_rele_path(PIP(cip));
13163 
13164                 if (rval == MDI_SUCCESS) {
13165                         mutex_enter(&ptgt->tgt_mutex);
13166                         plun->lun_state |= FCP_LUN_INIT;
13167                         mutex_exit(&ptgt->tgt_mutex);
13168 
13169                         /*
13170                          * Clear MPxIO path permanent disable in case
13171                          * fcp hotplug dropped the offline event.
13172                          */
13173                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13174 
13175                 } else if (rval == MDI_NOT_SUPPORTED) {
13176                         child_info_t    *old_cip = cip;
13177 
13178                         /*
13179                          * MPxIO does not support this device yet.
13180                          * Enumerate in legacy mode.
13181                          */
13182                         mutex_enter(&pptr->port_mutex);
13183                         mutex_enter(&plun->lun_mutex);
13184                         plun->lun_mpxio = 0;
13185                         plun->lun_cip = NULL;
13186                         cdip = fcp_create_dip(plun, lcount, tcount);
13187                         plun->lun_cip = cip = CIP(cdip);
13188                         if (cip == NULL) {
13189                                 fcp_log(CE_WARN, pptr->port_dip,
13190                                     "!fcp_online_child: "
13191                                     "Create devinfo failed for LU=%p", plun);
13192                                 mutex_exit(&plun->lun_mutex);
13193 
13194                                 mutex_enter(&ptgt->tgt_mutex);
13195                                 plun->lun_state |= FCP_LUN_OFFLINE;
13196                                 mutex_exit(&ptgt->tgt_mutex);
13197 
13198                                 mutex_exit(&pptr->port_mutex);
13199 
13200                                 /*
13201                                  * free the mdi_pathinfo node
13202                                  */
13203                                 (void) mdi_pi_free(PIP(old_cip), 0);
13204                         } else {
13205                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13206                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13207                                     "fcp_online_child: creating devinfo "
13208                                     "node 0x%p for plun 0x%p",
13209                                     cip, plun);
13210                                 mutex_exit(&plun->lun_mutex);
13211                                 mutex_exit(&pptr->port_mutex);
13212                                 /*
13213                                  * free the mdi_pathinfo node
13214                                  */
13215                                 (void) mdi_pi_free(PIP(old_cip), 0);
13216                                 mutex_enter(&pptr->port_mutex);
13217                                 mutex_enter(&plun->lun_mutex);
13218                                 goto again;
13219                         }
13220                 } else {
13221                         if (cdip) {
13222                                 fcp_log(CE_NOTE, pptr->port_dip,
13223                                     "!fcp_online_child: mdi_pi_online:"
13224                                     " failed for %s: target=%x lun=%x %x",
13225                                     ddi_get_name(cdip), ptgt->tgt_d_id,
13226                                     plun->lun_num, rval);
13227                         }
13228                 }
13229                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13230         }
13231 
13232         if (rval == NDI_SUCCESS) {
13233                 if (cdip) {
13234                         (void) ndi_event_retrieve_cookie(
13235                             pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13236                             &fcp_insert_eid, NDI_EVENT_NOPASS);
13237                         (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13238                             cdip, fcp_insert_eid, NULL);
13239                 }
13240         }
13241         mutex_enter(&pptr->port_mutex);
13242         mutex_enter(&plun->lun_mutex);
13243         return (rval);
13244 }
13245 
13246 /* ARGSUSED */
13247 static int
13248 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13249     int tcount, int flags, int *circ)
13250 {
13251         int             rval;
13252         int             lun_mpxio;
13253         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13254         struct fcp_tgt  *ptgt = plun->lun_tgt;
13255         dev_info_t      *cdip;
13256 
13257         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13258         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13259 
13260         if (plun->lun_cip == NULL) {
13261                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13262                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13263                     "fcp_offline_child: plun->lun_cip is NULL: "
13264                     "plun: %p lun state: %x num: %d target state: %x",
13265                     plun, plun->lun_state, plun->lun_num,
13266                     plun->lun_tgt->tgt_port->port_state);
13267                 return (NDI_FAILURE);
13268         }
13269 
13270         /*
13271          * We will use this value twice. Make a copy to be sure we use
13272          * the same value in both places.
13273          */
13274         lun_mpxio = plun->lun_mpxio;
13275 
13276         if (lun_mpxio == 0) {
13277                 cdip = DIP(cip);
13278                 mutex_exit(&plun->lun_mutex);
13279                 mutex_exit(&pptr->port_mutex);
13280                 rval = ndi_devi_offline(DIP(cip), NDI_DEVFS_CLEAN | flags);
13281                 if (rval != NDI_SUCCESS) {
13282                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13283                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13284                             "fcp_offline_child: ndi_devi_offline failed "
13285                             "rval=%x cip=%p", rval, cip);
13286                 }
13287         } else {
13288                 cdip = mdi_pi_get_client(PIP(cip));
13289                 mutex_exit(&plun->lun_mutex);
13290                 mutex_exit(&pptr->port_mutex);
13291 
13292                 /*
13293                  * Exit phci to avoid deadlock with power management code
13294                  * during mdi_pi_offline
13295                  */
13296                 mdi_hold_path(PIP(cip));
13297                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13298 
13299                 rval = mdi_pi_offline(PIP(cip), flags);
13300 
13301                 mdi_devi_enter_phci(pptr->port_dip, circ);
13302                 mdi_rele_path(PIP(cip));
13303 
13304                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13305         }
13306 
13307         mutex_enter(&ptgt->tgt_mutex);
13308         plun->lun_state &= ~FCP_LUN_INIT;
13309         mutex_exit(&ptgt->tgt_mutex);
13310 
13311         if (rval == NDI_SUCCESS) {
13312                 cdip = NULL;
13313                 if (flags & NDI_DEVI_REMOVE) {
13314                         mutex_enter(&plun->lun_mutex);
13315                         /*
13316                          * If the guid of the LUN changes, lun_cip will not
13317                          * equal to cip, and after offlining the LUN with the
13318                          * old guid, we should keep lun_cip since it's the cip
13319                          * of the LUN with the new guid.
13320                          * Otherwise remove our reference to child node.
13321                          *
13322                          * This must be done before the child node is freed,
13323                          * otherwise other threads could see a stale lun_cip
13324                          * pointer.
13325                          */
13326                         if (plun->lun_cip == cip) {
13327                                 plun->lun_cip = NULL;
13328                         }
13329                         if (plun->lun_old_guid) {
13330                                 kmem_free(plun->lun_old_guid,
13331                                     plun->lun_old_guid_size);
13332                                 plun->lun_old_guid = NULL;
13333                                 plun->lun_old_guid_size = 0;
13334                         }
13335                         mutex_exit(&plun->lun_mutex);
13336                 }
13337         }
13338 
13339         if (lun_mpxio != 0) {
13340                 if (rval == NDI_SUCCESS) {
13341                         /*
13342                          * Clear MPxIO path permanent disable as the path is
13343                          * already offlined.
13344                          */
13345                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13346 
13347                         if (flags & NDI_DEVI_REMOVE) {
13348                                 (void) mdi_pi_free(PIP(cip), 0);
13349                         }
13350                 } else {
13351                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13352                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13353                             "fcp_offline_child: mdi_pi_offline failed "
13354                             "rval=%x cip=%p", rval, cip);
13355                 }
13356         }
13357 
13358         mutex_enter(&pptr->port_mutex);
13359         mutex_enter(&plun->lun_mutex);
13360 
13361         if (cdip) {
13362                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13363                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13364                     " target=%x lun=%x", "ndi_offline",
13365                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13366         }
13367 
13368         return (rval);
13369 }
13370 
13371 static void
13372 fcp_remove_child(struct fcp_lun *plun)
13373 {
13374         child_info_t *cip;
13375         int circ;
13376 
13377         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13378 
13379         if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13380                 if (plun->lun_mpxio == 0) {
13381                         (void) ndi_prop_remove_all(DIP(plun->lun_cip));
13382                         (void) ndi_devi_free(DIP(plun->lun_cip));
13383                         plun->lun_cip = NULL;
13384                 } else {
13385                         /*
13386                          * Clear reference to the child node in the lun.
13387                          * This must be done before freeing it with mdi_pi_free
13388                          * and with lun_mutex held so that other threads always
13389                          * see either valid lun_cip or NULL when holding
13390                          * lun_mutex. We keep a copy in cip.
13391                          */
13392                         cip = plun->lun_cip;
13393                         plun->lun_cip = NULL;
13394 
13395                         mutex_exit(&plun->lun_mutex);
13396                         mutex_exit(&plun->lun_tgt->tgt_mutex);
13397                         mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13398 
13399                         mdi_devi_enter(
13400                             plun->lun_tgt->tgt_port->port_dip, &circ);
13401 
13402                         /*
13403                          * Exit phci to avoid deadlock with power management
13404                          * code during mdi_pi_offline
13405                          */
13406                         mdi_hold_path(PIP(cip));
13407                         mdi_devi_exit_phci(
13408                             plun->lun_tgt->tgt_port->port_dip, circ);
13409                         (void) mdi_pi_offline(PIP(cip),
13410                             NDI_DEVI_REMOVE);
13411                         mdi_devi_enter_phci(
13412                             plun->lun_tgt->tgt_port->port_dip, &circ);
13413                         mdi_rele_path(PIP(cip));
13414 
13415                         mdi_devi_exit(
13416                             plun->lun_tgt->tgt_port->port_dip, circ);
13417 
13418                         FCP_TRACE(fcp_logq,
13419                             plun->lun_tgt->tgt_port->port_instbuf,
13420                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13421                             "lun=%p pip freed %p", plun, cip);
13422 
13423                         (void) mdi_prop_remove(PIP(cip), NULL);
13424                         (void) mdi_pi_free(PIP(cip), 0);
13425 
13426                         mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13427                         mutex_enter(&plun->lun_tgt->tgt_mutex);
13428                         mutex_enter(&plun->lun_mutex);
13429                 }
13430         } else {
13431                 plun->lun_cip = NULL;
13432         }
13433 }
13434 
13435 /*
13436  * called when a timeout occurs
13437  *
13438  * can be scheduled during an attach or resume (if not already running)
13439  *
13440  * one timeout is set up for all ports
13441  *
13442  * acquires and releases the global mutex
13443  */
13444 /*ARGSUSED*/
13445 static void
13446 fcp_watch(void *arg)
13447 {
13448         struct fcp_port *pptr;
13449         struct fcp_ipkt *icmd;
13450         struct fcp_ipkt *nicmd;
13451         struct fcp_pkt  *cmd;
13452         struct fcp_pkt  *ncmd;
13453         struct fcp_pkt  *tail;
13454         struct fcp_pkt  *pcmd;
13455         struct fcp_pkt  *save_head;
13456         struct fcp_port *save_port;
13457 
13458         /* increment global watchdog time */
13459         fcp_watchdog_time += fcp_watchdog_timeout;
13460 
13461         mutex_enter(&fcp_global_mutex);
13462 
13463         /* scan each port in our list */
13464         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13465                 save_port = fcp_port_head;
13466                 pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13467                 mutex_exit(&fcp_global_mutex);
13468 
13469                 mutex_enter(&pptr->port_mutex);
13470                 if (pptr->port_ipkt_list == NULL &&
13471                     (pptr->port_state & (FCP_STATE_SUSPENDED |
13472                     FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13473                         pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13474                         mutex_exit(&pptr->port_mutex);
13475                         mutex_enter(&fcp_global_mutex);
13476                         goto end_of_watchdog;
13477                 }
13478 
13479                 /*
13480                  * We check if a list of targets need to be offlined.
13481                  */
13482                 if (pptr->port_offline_tgts) {
13483                         fcp_scan_offline_tgts(pptr);
13484                 }
13485 
13486                 /*
13487                  * We check if a list of luns need to be offlined.
13488                  */
13489                 if (pptr->port_offline_luns) {
13490                         fcp_scan_offline_luns(pptr);
13491                 }
13492 
13493                 /*
13494                  * We check if a list of targets or luns need to be reset.
13495                  */
13496                 if (pptr->port_reset_list) {
13497                         fcp_check_reset_delay(pptr);
13498                 }
13499 
13500                 mutex_exit(&pptr->port_mutex);
13501 
13502                 /*
13503                  * This is where the pending commands (pkt) are checked for
13504                  * timeout.
13505                  */
13506                 mutex_enter(&pptr->port_pkt_mutex);
13507                 tail = pptr->port_pkt_tail;
13508 
13509                 for (pcmd = NULL, cmd = pptr->port_pkt_head;
13510                     cmd != NULL; cmd = ncmd) {
13511                         ncmd = cmd->cmd_next;
13512                         /*
13513                          * If a command is in this queue the bit CFLAG_IN_QUEUE
13514                          * must be set.
13515                          */
13516                         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13517                         /*
13518                          * FCP_INVALID_TIMEOUT will be set for those
13519                          * command that need to be failed. Mostly those
13520                          * cmds that could not be queued down for the
13521                          * "timeout" value. cmd->cmd_timeout is used
13522                          * to try and requeue the command regularly.
13523                          */
13524                         if (cmd->cmd_timeout >= fcp_watchdog_time) {
13525                                 /*
13526                                  * This command hasn't timed out yet.  Let's
13527                                  * go to the next one.
13528                                  */
13529                                 pcmd = cmd;
13530                                 goto end_of_loop;
13531                         }
13532 
13533                         if (cmd == pptr->port_pkt_head) {
13534                                 ASSERT(pcmd == NULL);
13535                                 pptr->port_pkt_head = cmd->cmd_next;
13536                         } else {
13537                                 ASSERT(pcmd != NULL);
13538                                 pcmd->cmd_next = cmd->cmd_next;
13539                         }
13540 
13541                         if (cmd == pptr->port_pkt_tail) {
13542                                 ASSERT(cmd->cmd_next == NULL);
13543                                 pptr->port_pkt_tail = pcmd;
13544                                 if (pcmd) {
13545                                         pcmd->cmd_next = NULL;
13546                                 }
13547                         }
13548                         cmd->cmd_next = NULL;
13549 
13550                         /*
13551                          * save the current head before dropping the
13552                          * mutex - If the head doesn't remain the
13553                          * same after re acquiring the mutex, just
13554                          * bail out and revisit on next tick.
13555                          *
13556                          * PS: The tail pointer can change as the commands
13557                          * get requeued after failure to retransport
13558                          */
13559                         save_head = pptr->port_pkt_head;
13560                         mutex_exit(&pptr->port_pkt_mutex);
13561 
13562                         if (cmd->cmd_fp_pkt->pkt_timeout ==
13563                             FCP_INVALID_TIMEOUT) {
13564                                 struct scsi_pkt         *pkt = cmd->cmd_pkt;
13565                                 struct fcp_lun  *plun;
13566                                 struct fcp_tgt  *ptgt;
13567 
13568                                 plun = ADDR2LUN(&pkt->pkt_address);
13569                                 ptgt = plun->lun_tgt;
13570 
13571                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13572                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13573                                     "SCSI cmd 0x%x to D_ID=%x timed out",
13574                                     pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13575 
13576                                 cmd->cmd_state == FCP_PKT_ABORTING ?
13577                                     fcp_fail_cmd(cmd, CMD_RESET,
13578                                     STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13579                                     CMD_TIMEOUT, STAT_ABORTED);
13580                         } else {
13581                                 fcp_retransport_cmd(pptr, cmd);
13582                         }
13583                         mutex_enter(&pptr->port_pkt_mutex);
13584                         if (save_head && save_head != pptr->port_pkt_head) {
13585                                 /*
13586                                  * Looks like linked list got changed (mostly
13587                                  * happens when an an OFFLINE LUN code starts
13588                                  * returning overflow queue commands in
13589                                  * parallel. So bail out and revisit during
13590                                  * next tick
13591                                  */
13592                                 break;
13593                         }
13594                 end_of_loop:
13595                         /*
13596                          * Scan only upto the previously known tail pointer
13597                          * to avoid excessive processing - lots of new packets
13598                          * could have been added to the tail or the old ones
13599                          * re-queued.
13600                          */
13601                         if (cmd == tail) {
13602                                 break;
13603                         }
13604                 }
13605                 mutex_exit(&pptr->port_pkt_mutex);
13606 
13607                 mutex_enter(&pptr->port_mutex);
13608                 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13609                         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13610 
13611                         nicmd = icmd->ipkt_next;
13612                         if ((icmd->ipkt_restart != 0) &&
13613                             (icmd->ipkt_restart >= fcp_watchdog_time)) {
13614                                 /* packet has not timed out */
13615                                 continue;
13616                         }
13617 
13618                         /* time for packet re-transport */
13619                         if (icmd == pptr->port_ipkt_list) {
13620                                 pptr->port_ipkt_list = icmd->ipkt_next;
13621                                 if (pptr->port_ipkt_list) {
13622                                         pptr->port_ipkt_list->ipkt_prev =
13623                                             NULL;
13624                                 }
13625                         } else {
13626                                 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13627                                 if (icmd->ipkt_next) {
13628                                         icmd->ipkt_next->ipkt_prev =
13629                                             icmd->ipkt_prev;
13630                                 }
13631                         }
13632                         icmd->ipkt_next = NULL;
13633                         icmd->ipkt_prev = NULL;
13634                         mutex_exit(&pptr->port_mutex);
13635 
13636                         if (fcp_is_retryable(icmd)) {
13637                                 fc_ulp_rscn_info_t *rscnp =
13638                                     (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13639                                     pkt_ulp_rscn_infop;
13640 
13641                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13642                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13643                                     "%x to D_ID=%x Retrying..",
13644                                     icmd->ipkt_opcode,
13645                                     icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13646 
13647                                 /*
13648                                  * Update the RSCN count in the packet
13649                                  * before resending.
13650                                  */
13651 
13652                                 if (rscnp != NULL) {
13653                                         rscnp->ulp_rscn_count =
13654                                             fc_ulp_get_rscn_count(pptr->
13655                                             port_fp_handle);
13656                                 }
13657 
13658                                 mutex_enter(&pptr->port_mutex);
13659                                 mutex_enter(&ptgt->tgt_mutex);
13660                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13661                                         mutex_exit(&ptgt->tgt_mutex);
13662                                         mutex_exit(&pptr->port_mutex);
13663                                         switch (icmd->ipkt_opcode) {
13664                                                 int rval;
13665                                         case LA_ELS_PLOGI:
13666                                                 if ((rval = fc_ulp_login(
13667                                                     pptr->port_fp_handle,
13668                                                     &icmd->ipkt_fpkt, 1)) ==
13669                                                     FC_SUCCESS) {
13670                                                         mutex_enter(
13671                                                             &pptr->port_mutex);
13672                                                         continue;
13673                                                 }
13674                                                 if (fcp_handle_ipkt_errors(
13675                                                     pptr, ptgt, icmd, rval,
13676                                                     "PLOGI") == DDI_SUCCESS) {
13677                                                         mutex_enter(
13678                                                             &pptr->port_mutex);
13679                                                         continue;
13680                                                 }
13681                                                 break;
13682 
13683                                         case LA_ELS_PRLI:
13684                                                 if ((rval = fc_ulp_issue_els(
13685                                                     pptr->port_fp_handle,
13686                                                     icmd->ipkt_fpkt)) ==
13687                                                     FC_SUCCESS) {
13688                                                         mutex_enter(
13689                                                             &pptr->port_mutex);
13690                                                         continue;
13691                                                 }
13692                                                 if (fcp_handle_ipkt_errors(
13693                                                     pptr, ptgt, icmd, rval,
13694                                                     "PRLI") == DDI_SUCCESS) {
13695                                                         mutex_enter(
13696                                                             &pptr->port_mutex);
13697                                                         continue;
13698                                                 }
13699                                                 break;
13700 
13701                                         default:
13702                                                 if ((rval = fcp_transport(
13703                                                     pptr->port_fp_handle,
13704                                                     icmd->ipkt_fpkt, 1)) ==
13705                                                     FC_SUCCESS) {
13706                                                         mutex_enter(
13707                                                             &pptr->port_mutex);
13708                                                         continue;
13709                                                 }
13710                                                 if (fcp_handle_ipkt_errors(
13711                                                     pptr, ptgt, icmd, rval,
13712                                                     "PRLI") == DDI_SUCCESS) {
13713                                                         mutex_enter(
13714                                                             &pptr->port_mutex);
13715                                                         continue;
13716                                                 }
13717                                                 break;
13718                                         }
13719                                 } else {
13720                                         mutex_exit(&ptgt->tgt_mutex);
13721                                         mutex_exit(&pptr->port_mutex);
13722                                 }
13723                         } else {
13724                                 fcp_print_error(icmd->ipkt_fpkt);
13725                         }
13726 
13727                         (void) fcp_call_finish_init(pptr, ptgt,
13728                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13729                             icmd->ipkt_cause);
13730                         fcp_icmd_free(pptr, icmd);
13731                         mutex_enter(&pptr->port_mutex);
13732                 }
13733 
13734                 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13735                 mutex_exit(&pptr->port_mutex);
13736                 mutex_enter(&fcp_global_mutex);
13737 
13738         end_of_watchdog:
13739                 /*
13740                  * Bail out early before getting into trouble
13741                  */
13742                 if (save_port != fcp_port_head) {
13743                         break;
13744                 }
13745         }
13746 
13747         if (fcp_watchdog_init > 0) {
13748                 /* reschedule timeout to go again */
13749                 fcp_watchdog_id =
13750                     timeout(fcp_watch, NULL, fcp_watchdog_tick);
13751         }
13752         mutex_exit(&fcp_global_mutex);
13753 }
13754 
13755 
13756 static void
13757 fcp_check_reset_delay(struct fcp_port *pptr)
13758 {
13759         uint32_t                tgt_cnt;
13760         int                     level;
13761         struct fcp_tgt  *ptgt;
13762         struct fcp_lun  *plun;
13763         struct fcp_reset_elem *cur = NULL;
13764         struct fcp_reset_elem *next = NULL;
13765         struct fcp_reset_elem *prev = NULL;
13766 
13767         ASSERT(mutex_owned(&pptr->port_mutex));
13768 
13769         next = pptr->port_reset_list;
13770         while ((cur = next) != NULL) {
13771                 next = cur->next;
13772 
13773                 if (cur->timeout < fcp_watchdog_time) {
13774                         prev = cur;
13775                         continue;
13776                 }
13777 
13778                 ptgt = cur->tgt;
13779                 plun = cur->lun;
13780                 tgt_cnt = cur->tgt_cnt;
13781 
13782                 if (ptgt) {
13783                         level = RESET_TARGET;
13784                 } else {
13785                         ASSERT(plun != NULL);
13786                         level = RESET_LUN;
13787                         ptgt = plun->lun_tgt;
13788                 }
13789                 if (prev) {
13790                         prev->next = next;
13791                 } else {
13792                         /*
13793                          * Because we drop port mutex while doing aborts for
13794                          * packets, we can't rely on reset_list pointing to
13795                          * our head
13796                          */
13797                         if (cur == pptr->port_reset_list) {
13798                                 pptr->port_reset_list = next;
13799                         } else {
13800                                 struct fcp_reset_elem *which;
13801 
13802                                 which = pptr->port_reset_list;
13803                                 while (which && which->next != cur) {
13804                                         which = which->next;
13805                                 }
13806                                 ASSERT(which != NULL);
13807 
13808                                 which->next = next;
13809                                 prev = which;
13810                         }
13811                 }
13812 
13813                 kmem_free(cur, sizeof (*cur));
13814 
13815                 if (tgt_cnt == ptgt->tgt_change_cnt) {
13816                         mutex_enter(&ptgt->tgt_mutex);
13817                         if (level == RESET_TARGET) {
13818                                 fcp_update_tgt_state(ptgt,
13819                                     FCP_RESET, FCP_LUN_BUSY);
13820                         } else {
13821                                 fcp_update_lun_state(plun,
13822                                     FCP_RESET, FCP_LUN_BUSY);
13823                         }
13824                         mutex_exit(&ptgt->tgt_mutex);
13825 
13826                         mutex_exit(&pptr->port_mutex);
13827                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13828                         mutex_enter(&pptr->port_mutex);
13829                 }
13830         }
13831 }
13832 
13833 
13834 static void
13835 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13836     struct fcp_lun *rlun, int tgt_cnt)
13837 {
13838         int                     rval;
13839         struct fcp_lun  *tlun, *nlun;
13840         struct fcp_pkt  *pcmd = NULL, *ncmd = NULL,
13841             *cmd = NULL, *head = NULL,
13842             *tail = NULL;
13843 
13844         mutex_enter(&pptr->port_pkt_mutex);
13845         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13846                 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13847                 struct fcp_tgt *ptgt = plun->lun_tgt;
13848 
13849                 ncmd = cmd->cmd_next;
13850 
13851                 if (ptgt != ttgt && plun != rlun) {
13852                         pcmd = cmd;
13853                         continue;
13854                 }
13855 
13856                 if (pcmd != NULL) {
13857                         ASSERT(pptr->port_pkt_head != cmd);
13858                         pcmd->cmd_next = ncmd;
13859                 } else {
13860                         ASSERT(cmd == pptr->port_pkt_head);
13861                         pptr->port_pkt_head = ncmd;
13862                 }
13863                 if (pptr->port_pkt_tail == cmd) {
13864                         ASSERT(cmd->cmd_next == NULL);
13865                         pptr->port_pkt_tail = pcmd;
13866                         if (pcmd != NULL) {
13867                                 pcmd->cmd_next = NULL;
13868                         }
13869                 }
13870 
13871                 if (head == NULL) {
13872                         head = tail = cmd;
13873                 } else {
13874                         ASSERT(tail != NULL);
13875                         tail->cmd_next = cmd;
13876                         tail = cmd;
13877                 }
13878                 cmd->cmd_next = NULL;
13879         }
13880         mutex_exit(&pptr->port_pkt_mutex);
13881 
13882         for (cmd = head; cmd != NULL; cmd = ncmd) {
13883                 struct scsi_pkt *pkt = cmd->cmd_pkt;
13884 
13885                 ncmd = cmd->cmd_next;
13886                 ASSERT(pkt != NULL);
13887 
13888                 mutex_enter(&pptr->port_mutex);
13889                 if (ttgt->tgt_change_cnt == tgt_cnt) {
13890                         mutex_exit(&pptr->port_mutex);
13891                         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13892                         pkt->pkt_reason = CMD_RESET;
13893                         pkt->pkt_statistics |= STAT_DEV_RESET;
13894                         cmd->cmd_state = FCP_PKT_IDLE;
13895                         fcp_post_callback(cmd);
13896                 } else {
13897                         mutex_exit(&pptr->port_mutex);
13898                 }
13899         }
13900 
13901         /*
13902          * If the FCA will return all the commands in its queue then our
13903          * work is easy, just return.
13904          */
13905 
13906         if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13907                 return;
13908         }
13909 
13910         /*
13911          * For RESET_LUN get hold of target pointer
13912          */
13913         if (ttgt == NULL) {
13914                 ASSERT(rlun != NULL);
13915 
13916                 ttgt = rlun->lun_tgt;
13917 
13918                 ASSERT(ttgt != NULL);
13919         }
13920 
13921         /*
13922          * There are some severe race conditions here.
13923          * While we are trying to abort the pkt, it might be completing
13924          * so mark it aborted and if the abort does not succeed then
13925          * handle it in the watch thread.
13926          */
13927         mutex_enter(&ttgt->tgt_mutex);
13928         nlun = ttgt->tgt_lun;
13929         mutex_exit(&ttgt->tgt_mutex);
13930         while ((tlun = nlun) != NULL) {
13931                 int restart = 0;
13932                 if (rlun && rlun != tlun) {
13933                         mutex_enter(&ttgt->tgt_mutex);
13934                         nlun = tlun->lun_next;
13935                         mutex_exit(&ttgt->tgt_mutex);
13936                         continue;
13937                 }
13938                 mutex_enter(&tlun->lun_mutex);
13939                 cmd = tlun->lun_pkt_head;
13940                 while (cmd != NULL) {
13941                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
13942                                 struct scsi_pkt *pkt;
13943 
13944                                 restart = 1;
13945                                 cmd->cmd_state = FCP_PKT_ABORTING;
13946                                 mutex_exit(&tlun->lun_mutex);
13947                                 rval = fc_ulp_abort(pptr->port_fp_handle,
13948                                     cmd->cmd_fp_pkt, KM_SLEEP);
13949                                 if (rval == FC_SUCCESS) {
13950                                         pkt = cmd->cmd_pkt;
13951                                         pkt->pkt_reason = CMD_RESET;
13952                                         pkt->pkt_statistics |= STAT_DEV_RESET;
13953                                         cmd->cmd_state = FCP_PKT_IDLE;
13954                                         fcp_post_callback(cmd);
13955                                 } else {
13956                                         caddr_t msg;
13957 
13958                                         (void) fc_ulp_error(rval, &msg);
13959 
13960                                         /*
13961                                          * This part is tricky. The abort
13962                                          * failed and now the command could
13963                                          * be completing.  The cmd_state ==
13964                                          * FCP_PKT_ABORTING should save
13965                                          * us in fcp_cmd_callback. If we
13966                                          * are already aborting ignore the
13967                                          * command in fcp_cmd_callback.
13968                                          * Here we leave this packet for 20
13969                                          * sec to be aborted in the
13970                                          * fcp_watch thread.
13971                                          */
13972                                         fcp_log(CE_WARN, pptr->port_dip,
13973                                             "!Abort failed after reset %s",
13974                                             msg);
13975 
13976                                         cmd->cmd_timeout =
13977                                             fcp_watchdog_time +
13978                                             cmd->cmd_pkt->pkt_time +
13979                                             FCP_FAILED_DELAY;
13980 
13981                                         cmd->cmd_fp_pkt->pkt_timeout =
13982                                             FCP_INVALID_TIMEOUT;
13983                                         /*
13984                                          * This is a hack, cmd is put in the
13985                                          * overflow queue so that it can be
13986                                          * timed out finally
13987                                          */
13988                                         cmd->cmd_flags |= CFLAG_IN_QUEUE;
13989 
13990                                         mutex_enter(&pptr->port_pkt_mutex);
13991                                         if (pptr->port_pkt_head) {
13992                                                 ASSERT(pptr->port_pkt_tail
13993                                                     != NULL);
13994                                                 pptr->port_pkt_tail->cmd_next
13995                                                     = cmd;
13996                                                 pptr->port_pkt_tail = cmd;
13997                                         } else {
13998                                                 ASSERT(pptr->port_pkt_tail
13999                                                     == NULL);
14000                                                 pptr->port_pkt_head =
14001                                                     pptr->port_pkt_tail
14002                                                     = cmd;
14003                                         }
14004                                         cmd->cmd_next = NULL;
14005                                         mutex_exit(&pptr->port_pkt_mutex);
14006                                 }
14007                                 mutex_enter(&tlun->lun_mutex);
14008                                 cmd = tlun->lun_pkt_head;
14009                         } else {
14010                                 cmd = cmd->cmd_forw;
14011                         }
14012                 }
14013                 mutex_exit(&tlun->lun_mutex);
14014 
14015                 mutex_enter(&ttgt->tgt_mutex);
14016                 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14017                 mutex_exit(&ttgt->tgt_mutex);
14018 
14019                 mutex_enter(&pptr->port_mutex);
14020                 if (tgt_cnt != ttgt->tgt_change_cnt) {
14021                         mutex_exit(&pptr->port_mutex);
14022                         return;
14023                 } else {
14024                         mutex_exit(&pptr->port_mutex);
14025                 }
14026         }
14027 }
14028 
14029 
14030 /*
14031  * unlink the soft state, returning the soft state found (if any)
14032  *
14033  * acquires and releases the global mutex
14034  */
14035 struct fcp_port *
14036 fcp_soft_state_unlink(struct fcp_port *pptr)
14037 {
14038         struct fcp_port *hptr;          /* ptr index */
14039         struct fcp_port *tptr;          /* prev hptr */
14040 
14041         mutex_enter(&fcp_global_mutex);
14042         for (hptr = fcp_port_head, tptr = NULL;
14043             hptr != NULL;
14044             tptr = hptr, hptr = hptr->port_next) {
14045                 if (hptr == pptr) {
14046                         /* we found a match -- remove this item */
14047                         if (tptr == NULL) {
14048                                 /* we're at the head of the list */
14049                                 fcp_port_head = hptr->port_next;
14050                         } else {
14051                                 tptr->port_next = hptr->port_next;
14052                         }
14053                         break;                  /* success */
14054                 }
14055         }
14056         if (fcp_port_head == NULL) {
14057                 fcp_cleanup_blacklist(&fcp_lun_blacklist);
14058         }
14059         mutex_exit(&fcp_global_mutex);
14060         return (hptr);
14061 }
14062 
14063 
14064 /*
14065  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14066  * WWN and a LUN number
14067  */
14068 /* ARGSUSED */
14069 static struct fcp_lun *
14070 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14071 {
14072         int hash;
14073         struct fcp_tgt *ptgt;
14074         struct fcp_lun *plun;
14075 
14076         ASSERT(mutex_owned(&pptr->port_mutex));
14077 
14078         hash = FCP_HASH(wwn);
14079         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14080             ptgt = ptgt->tgt_next) {
14081                 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14082                     sizeof (ptgt->tgt_port_wwn)) == 0) {
14083                         mutex_enter(&ptgt->tgt_mutex);
14084                         for (plun = ptgt->tgt_lun;
14085                             plun != NULL;
14086                             plun = plun->lun_next) {
14087                                 if (plun->lun_num == lun) {
14088                                         mutex_exit(&ptgt->tgt_mutex);
14089                                         return (plun);
14090                                 }
14091                         }
14092                         mutex_exit(&ptgt->tgt_mutex);
14093                         return (NULL);
14094                 }
14095         }
14096         return (NULL);
14097 }
14098 
14099 /*
14100  *     Function: fcp_prepare_pkt
14101  *
14102  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14103  *               for fcp_start(). It binds the data or partially maps it.
14104  *               Builds the FCP header and starts the initialization of the
14105  *               Fibre Channel header.
14106  *
14107  *     Argument: *pptr          FCP port.
14108  *               *cmd           FCP packet.
14109  *               *plun          LUN the command will be sent to.
14110  *
14111  *      Context: User, Kernel and Interrupt context.
14112  */
14113 static void
14114 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14115     struct fcp_lun *plun)
14116 {
14117         fc_packet_t             *fpkt = cmd->cmd_fp_pkt;
14118         struct fcp_tgt          *ptgt = plun->lun_tgt;
14119         struct fcp_cmd          *fcmd = &cmd->cmd_fcp_cmd;
14120 
14121         ASSERT(cmd->cmd_pkt->pkt_comp ||
14122             (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14123 
14124         if (cmd->cmd_pkt->pkt_numcookies) {
14125                 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14126                         fcmd->fcp_cntl.cntl_read_data = 1;
14127                         fcmd->fcp_cntl.cntl_write_data = 0;
14128                         fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14129                 } else {
14130                         fcmd->fcp_cntl.cntl_read_data = 0;
14131                         fcmd->fcp_cntl.cntl_write_data = 1;
14132                         fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14133                 }
14134 
14135                 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14136 
14137                 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14138                 ASSERT(fpkt->pkt_data_cookie_cnt <=
14139                     pptr->port_data_dma_attr.dma_attr_sgllen);
14140 
14141                 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14142 
14143                 /* FCA needs pkt_datalen to be set */
14144                 fpkt->pkt_datalen = cmd->cmd_dmacount;
14145                 fcmd->fcp_data_len = cmd->cmd_dmacount;
14146         } else {
14147                 fcmd->fcp_cntl.cntl_read_data = 0;
14148                 fcmd->fcp_cntl.cntl_write_data = 0;
14149                 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14150                 fpkt->pkt_datalen = 0;
14151                 fcmd->fcp_data_len = 0;
14152         }
14153 
14154         /* set up the Tagged Queuing type */
14155         if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14156                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14157         } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14158                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14159         } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14160                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14161         } else {
14162                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14163         }
14164 
14165         fcmd->fcp_ent_addr = plun->lun_addr;
14166 
14167         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14168                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14169                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14170         } else {
14171                 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14172         }
14173 
14174         cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14175         cmd->cmd_pkt->pkt_state = 0;
14176         cmd->cmd_pkt->pkt_statistics = 0;
14177         cmd->cmd_pkt->pkt_resid = 0;
14178 
14179         cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14180 
14181         if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14182                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14183                 fpkt->pkt_comp = NULL;
14184         } else {
14185                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14186                 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14187                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14188                 }
14189                 fpkt->pkt_comp = fcp_cmd_callback;
14190         }
14191 
14192         mutex_enter(&pptr->port_mutex);
14193         if (pptr->port_state & FCP_STATE_SUSPENDED) {
14194                 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14195         }
14196         mutex_exit(&pptr->port_mutex);
14197 
14198         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14199         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14200 
14201         /*
14202          * Save a few kernel cycles here
14203          */
14204 #ifndef __lock_lint
14205         fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14206 #endif /* __lock_lint */
14207 }
14208 
14209 static void
14210 fcp_post_callback(struct fcp_pkt *cmd)
14211 {
14212         scsi_hba_pkt_comp(cmd->cmd_pkt);
14213 }
14214 
14215 
14216 /*
14217  * called to do polled I/O by fcp_start()
14218  *
14219  * return a transport status value, i.e. TRAN_ACCECPT for success
14220  */
14221 static int
14222 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14223 {
14224         int     rval;
14225 
14226 #ifdef  DEBUG
14227         mutex_enter(&pptr->port_pkt_mutex);
14228         pptr->port_npkts++;
14229         mutex_exit(&pptr->port_pkt_mutex);
14230 #endif /* DEBUG */
14231 
14232         if (cmd->cmd_fp_pkt->pkt_timeout) {
14233                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14234         } else {
14235                 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14236         }
14237 
14238         ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14239 
14240         cmd->cmd_state = FCP_PKT_ISSUED;
14241 
14242         rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14243 
14244 #ifdef  DEBUG
14245         mutex_enter(&pptr->port_pkt_mutex);
14246         pptr->port_npkts--;
14247         mutex_exit(&pptr->port_pkt_mutex);
14248 #endif /* DEBUG */
14249 
14250         cmd->cmd_state = FCP_PKT_IDLE;
14251 
14252         switch (rval) {
14253         case FC_SUCCESS:
14254                 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14255                         fcp_complete_pkt(cmd->cmd_fp_pkt);
14256                         rval = TRAN_ACCEPT;
14257                 } else {
14258                         rval = TRAN_FATAL_ERROR;
14259                 }
14260                 break;
14261 
14262         case FC_TRAN_BUSY:
14263                 rval = TRAN_BUSY;
14264                 cmd->cmd_pkt->pkt_resid = 0;
14265                 break;
14266 
14267         case FC_BADPACKET:
14268                 rval = TRAN_BADPKT;
14269                 break;
14270 
14271         default:
14272                 rval = TRAN_FATAL_ERROR;
14273                 break;
14274         }
14275 
14276         return (rval);
14277 }
14278 
14279 
14280 /*
14281  * called by some of the following transport-called routines to convert
14282  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14283  */
14284 static struct fcp_port *
14285 fcp_dip2port(dev_info_t *dip)
14286 {
14287         int     instance;
14288 
14289         instance = ddi_get_instance(dip);
14290         return (ddi_get_soft_state(fcp_softstate, instance));
14291 }
14292 
14293 
14294 /*
14295  * called internally to return a LUN given a dip
14296  */
14297 struct fcp_lun *
14298 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14299 {
14300         struct fcp_tgt *ptgt;
14301         struct fcp_lun *plun;
14302         int i;
14303 
14304 
14305         ASSERT(mutex_owned(&pptr->port_mutex));
14306 
14307         for (i = 0; i < FCP_NUM_HASH; i++) {
14308                 for (ptgt = pptr->port_tgt_hash_table[i];
14309                     ptgt != NULL;
14310                     ptgt = ptgt->tgt_next) {
14311                         mutex_enter(&ptgt->tgt_mutex);
14312                         for (plun = ptgt->tgt_lun; plun != NULL;
14313                             plun = plun->lun_next) {
14314                                 mutex_enter(&plun->lun_mutex);
14315                                 if (plun->lun_cip == cip) {
14316                                         mutex_exit(&plun->lun_mutex);
14317                                         mutex_exit(&ptgt->tgt_mutex);
14318                                         return (plun); /* match found */
14319                                 }
14320                                 mutex_exit(&plun->lun_mutex);
14321                         }
14322                         mutex_exit(&ptgt->tgt_mutex);
14323                 }
14324         }
14325         return (NULL);                          /* no LUN found */
14326 }
14327 
14328 /*
14329  * pass an element to the hotplug list, kick the hotplug thread
14330  * and wait for the element to get processed by the hotplug thread.
14331  * on return the element is freed.
14332  *
14333  * return zero success and non-zero on failure
14334  *
14335  * acquires/releases the target mutex
14336  *
14337  */
14338 static int
14339 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14340     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14341 {
14342         struct fcp_hp_elem      *elem;
14343         int                     rval;
14344 
14345         mutex_enter(&plun->lun_tgt->tgt_mutex);
14346         if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14347             what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14348                 mutex_exit(&plun->lun_tgt->tgt_mutex);
14349                 fcp_log(CE_CONT, pptr->port_dip,
14350                     "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14351                     what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14352                 return (NDI_FAILURE);
14353         }
14354         mutex_exit(&plun->lun_tgt->tgt_mutex);
14355         mutex_enter(&elem->mutex);
14356         if (elem->wait) {
14357                 while (elem->wait) {
14358                         cv_wait(&elem->cv, &elem->mutex);
14359                 }
14360         }
14361         rval = (elem->result);
14362         mutex_exit(&elem->mutex);
14363         mutex_destroy(&elem->mutex);
14364         cv_destroy(&elem->cv);
14365         kmem_free(elem, sizeof (struct fcp_hp_elem));
14366         return (rval);
14367 }
14368 
14369 /*
14370  * pass an element to the hotplug list, and then
14371  * kick the hotplug thread
14372  *
14373  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14374  *
14375  * acquires/releases the hotplug mutex
14376  *
14377  * called with the target mutex owned
14378  *
14379  * memory acquired in NOSLEEP mode
14380  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14381  *       for the hp daemon to process the request and is responsible for
14382  *       freeing the element
14383  */
14384 static struct fcp_hp_elem *
14385 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14386     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14387 {
14388         struct fcp_hp_elem      *elem;
14389         dev_info_t *pdip;
14390 
14391         ASSERT(pptr != NULL);
14392         ASSERT(plun != NULL);
14393         ASSERT(plun->lun_tgt != NULL);
14394         ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14395 
14396         /* create space for a hotplug element */
14397         if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14398             == NULL) {
14399                 fcp_log(CE_WARN, NULL,
14400                     "!can't allocate memory for hotplug element");
14401                 return (NULL);
14402         }
14403 
14404         /* fill in hotplug element */
14405         elem->port = pptr;
14406         elem->lun = plun;
14407         elem->cip = cip;
14408         elem->old_lun_mpxio = plun->lun_mpxio;
14409         elem->what = what;
14410         elem->flags = flags;
14411         elem->link_cnt = link_cnt;
14412         elem->tgt_cnt = tgt_cnt;
14413         elem->wait = wait;
14414         mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14415         cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14416 
14417         /* schedule the hotplug task */
14418         pdip = pptr->port_dip;
14419         mutex_enter(&plun->lun_mutex);
14420         if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14421                 plun->lun_event_count++;
14422                 elem->event_cnt = plun->lun_event_count;
14423         }
14424         mutex_exit(&plun->lun_mutex);
14425         if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14426             (void *)elem, KM_NOSLEEP) == NULL) {
14427                 mutex_enter(&plun->lun_mutex);
14428                 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14429                         plun->lun_event_count--;
14430                 }
14431                 mutex_exit(&plun->lun_mutex);
14432                 kmem_free(elem, sizeof (*elem));
14433                 return (0);
14434         }
14435 
14436         return (elem);
14437 }
14438 
14439 
14440 static void
14441 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14442 {
14443         int                     rval;
14444         struct scsi_address     *ap;
14445         struct fcp_lun  *plun;
14446         struct fcp_tgt  *ptgt;
14447         fc_packet_t     *fpkt;
14448 
14449         ap = &cmd->cmd_pkt->pkt_address;
14450         plun = ADDR2LUN(ap);
14451         ptgt = plun->lun_tgt;
14452 
14453         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14454 
14455         cmd->cmd_state = FCP_PKT_IDLE;
14456 
14457         mutex_enter(&pptr->port_mutex);
14458         mutex_enter(&ptgt->tgt_mutex);
14459         if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14460             (!(pptr->port_state & FCP_STATE_ONLINING))) {
14461                 fc_ulp_rscn_info_t *rscnp;
14462 
14463                 cmd->cmd_state = FCP_PKT_ISSUED;
14464 
14465                 /*
14466                  * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14467                  * originally NULL, hence we try to set it to the pd pointed
14468                  * to by the SCSI device we're trying to get to.
14469                  */
14470 
14471                 fpkt = cmd->cmd_fp_pkt;
14472                 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14473                         fpkt->pkt_pd = ptgt->tgt_pd_handle;
14474                         /*
14475                          * We need to notify the transport that we now have a
14476                          * reference to the remote port handle.
14477                          */
14478                         fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14479                 }
14480 
14481                 mutex_exit(&ptgt->tgt_mutex);
14482                 mutex_exit(&pptr->port_mutex);
14483 
14484                 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14485 
14486                 /* prepare the packet */
14487 
14488                 fcp_prepare_pkt(pptr, cmd, plun);
14489 
14490                 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14491                     pkt_ulp_rscn_infop;
14492 
14493                 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14494                     fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14495 
14496                 if (rscnp != NULL) {
14497                         rscnp->ulp_rscn_count =
14498                             fc_ulp_get_rscn_count(pptr->
14499                             port_fp_handle);
14500                 }
14501 
14502                 rval = fcp_transport(pptr->port_fp_handle,
14503                     cmd->cmd_fp_pkt, 0);
14504 
14505                 if (rval == FC_SUCCESS) {
14506                         return;
14507                 }
14508                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
14509         } else {
14510                 mutex_exit(&ptgt->tgt_mutex);
14511                 mutex_exit(&pptr->port_mutex);
14512         }
14513 
14514         fcp_queue_pkt(pptr, cmd);
14515 }
14516 
14517 
14518 static void
14519 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14520 {
14521         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14522 
14523         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14524         cmd->cmd_state = FCP_PKT_IDLE;
14525 
14526         cmd->cmd_pkt->pkt_reason = reason;
14527         cmd->cmd_pkt->pkt_state = 0;
14528         cmd->cmd_pkt->pkt_statistics = statistics;
14529 
14530         fcp_post_callback(cmd);
14531 }
14532 
14533 /*
14534  *     Function: fcp_queue_pkt
14535  *
14536  *  Description: This function queues the packet passed by the caller into
14537  *               the list of packets of the FCP port.
14538  *
14539  *     Argument: *pptr          FCP port.
14540  *               *cmd           FCP packet to queue.
14541  *
14542  * Return Value: None
14543  *
14544  *      Context: User, Kernel and Interrupt context.
14545  */
14546 static void
14547 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14548 {
14549         ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14550 
14551         mutex_enter(&pptr->port_pkt_mutex);
14552         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14553         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14554         cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14555 
14556         /*
14557          * zero pkt_time means hang around for ever
14558          */
14559         if (cmd->cmd_pkt->pkt_time) {
14560                 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14561                         cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14562                 } else {
14563                         /*
14564                          * Indicate the watch thread to fail the
14565                          * command by setting it to highest value
14566                          */
14567                         cmd->cmd_timeout = fcp_watchdog_time;
14568                         cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14569                 }
14570         }
14571 
14572         if (pptr->port_pkt_head) {
14573                 ASSERT(pptr->port_pkt_tail != NULL);
14574 
14575                 pptr->port_pkt_tail->cmd_next = cmd;
14576                 pptr->port_pkt_tail = cmd;
14577         } else {
14578                 ASSERT(pptr->port_pkt_tail == NULL);
14579 
14580                 pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14581         }
14582         cmd->cmd_next = NULL;
14583         mutex_exit(&pptr->port_pkt_mutex);
14584 }
14585 
14586 /*
14587  *     Function: fcp_update_targets
14588  *
14589  *  Description: This function applies the specified change of state to all
14590  *               the targets listed.  The operation applied is 'set'.
14591  *
14592  *     Argument: *pptr          FCP port.
14593  *               *dev_list      Array of fc_portmap_t structures.
14594  *               count          Length of dev_list.
14595  *               state          State bits to update.
14596  *               cause          Reason for the update.
14597  *
14598  * Return Value: None
14599  *
14600  *      Context: User, Kernel and Interrupt context.
14601  *               The mutex pptr->port_mutex must be held.
14602  */
14603 static void
14604 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14605     uint32_t count, uint32_t state, int cause)
14606 {
14607         fc_portmap_t            *map_entry;
14608         struct fcp_tgt  *ptgt;
14609 
14610         ASSERT(MUTEX_HELD(&pptr->port_mutex));
14611 
14612         while (count--) {
14613                 map_entry = &(dev_list[count]);
14614                 ptgt = fcp_lookup_target(pptr,
14615                     (uchar_t *)&(map_entry->map_pwwn));
14616                 if (ptgt == NULL) {
14617                         continue;
14618                 }
14619 
14620                 mutex_enter(&ptgt->tgt_mutex);
14621                 ptgt->tgt_trace = 0;
14622                 ptgt->tgt_change_cnt++;
14623                 ptgt->tgt_statec_cause = cause;
14624                 ptgt->tgt_tmp_cnt = 1;
14625                 fcp_update_tgt_state(ptgt, FCP_SET, state);
14626                 mutex_exit(&ptgt->tgt_mutex);
14627         }
14628 }
14629 
14630 static int
14631 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14632     int lcount, int tcount, int cause)
14633 {
14634         int rval;
14635 
14636         mutex_enter(&pptr->port_mutex);
14637         rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14638         mutex_exit(&pptr->port_mutex);
14639 
14640         return (rval);
14641 }
14642 
14643 
14644 static int
14645 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14646     int lcount, int tcount, int cause)
14647 {
14648         int     finish_init = 0;
14649         int     finish_tgt = 0;
14650         int     do_finish_init = 0;
14651         int     rval = FCP_NO_CHANGE;
14652 
14653         if (cause == FCP_CAUSE_LINK_CHANGE ||
14654             cause == FCP_CAUSE_LINK_DOWN) {
14655                 do_finish_init = 1;
14656         }
14657 
14658         if (ptgt != NULL) {
14659                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14660                     FCP_BUF_LEVEL_2, 0,
14661                     "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14662                     " cause = %d, d_id = 0x%x, tgt_done = %d",
14663                     pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14664                     pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14665                     ptgt->tgt_d_id, ptgt->tgt_done);
14666 
14667                 mutex_enter(&ptgt->tgt_mutex);
14668 
14669                 if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14670                         rval = FCP_DEV_CHANGE;
14671                         if (do_finish_init && ptgt->tgt_done == 0) {
14672                                 ptgt->tgt_done++;
14673                                 finish_init = 1;
14674                         }
14675                 } else {
14676                         if (--ptgt->tgt_tmp_cnt <= 0) {
14677                                 ptgt->tgt_tmp_cnt = 0;
14678                                 finish_tgt = 1;
14679 
14680                                 if (do_finish_init) {
14681                                         finish_init = 1;
14682                                 }
14683                         }
14684                 }
14685                 mutex_exit(&ptgt->tgt_mutex);
14686         } else {
14687                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14688                     FCP_BUF_LEVEL_2, 0,
14689                     "Call Finish Init for NO target");
14690 
14691                 if (do_finish_init) {
14692                         finish_init = 1;
14693                 }
14694         }
14695 
14696         if (finish_tgt) {
14697                 ASSERT(ptgt != NULL);
14698 
14699                 mutex_enter(&ptgt->tgt_mutex);
14700 #ifdef  DEBUG
14701                 bzero(ptgt->tgt_tmp_cnt_stack,
14702                     sizeof (ptgt->tgt_tmp_cnt_stack));
14703 
14704                 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14705                     FCP_STACK_DEPTH);
14706 #endif /* DEBUG */
14707                 mutex_exit(&ptgt->tgt_mutex);
14708 
14709                 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14710         }
14711 
14712         if (finish_init && lcount == pptr->port_link_cnt) {
14713                 ASSERT(pptr->port_tmp_cnt > 0);
14714                 if (--pptr->port_tmp_cnt == 0) {
14715                         fcp_finish_init(pptr);
14716                 }
14717         } else if (lcount != pptr->port_link_cnt) {
14718                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
14719                     fcp_trace, FCP_BUF_LEVEL_2, 0,
14720                     "fcp_call_finish_init_held,1: state change occured"
14721                     " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14722         }
14723 
14724         return (rval);
14725 }
14726 
14727 static void
14728 fcp_reconfigure_luns(void * tgt_handle)
14729 {
14730         uint32_t                dev_cnt;
14731         fc_portmap_t            *devlist;
14732         struct fcp_tgt  *ptgt = (struct fcp_tgt *)tgt_handle;
14733         struct fcp_port         *pptr = ptgt->tgt_port;
14734 
14735         /*
14736          * If the timer that fires this off got canceled too late, the
14737          * target could have been destroyed.
14738          */
14739 
14740         if (ptgt->tgt_tid == NULL) {
14741                 return;
14742         }
14743 
14744         devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14745         if (devlist == NULL) {
14746                 fcp_log(CE_WARN, pptr->port_dip,
14747                     "!fcp%d: failed to allocate for portmap",
14748                     pptr->port_instance);
14749                 return;
14750         }
14751 
14752         dev_cnt = 1;
14753         devlist->map_pd = ptgt->tgt_pd_handle;
14754         devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14755         devlist->map_did.port_id = ptgt->tgt_d_id;
14756 
14757         bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14758         bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14759 
14760         devlist->map_state = PORT_DEVICE_LOGGED_IN;
14761         devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14762         devlist->map_flags = 0;
14763 
14764         fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14765             pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14766 
14767         /*
14768          * Clear the tgt_tid after no more references to
14769          * the fcp_tgt
14770          */
14771         mutex_enter(&ptgt->tgt_mutex);
14772         ptgt->tgt_tid = NULL;
14773         mutex_exit(&ptgt->tgt_mutex);
14774 
14775         kmem_free(devlist, sizeof (*devlist));
14776 }
14777 
14778 
14779 static void
14780 fcp_free_targets(struct fcp_port *pptr)
14781 {
14782         int                     i;
14783         struct fcp_tgt  *ptgt;
14784 
14785         mutex_enter(&pptr->port_mutex);
14786         for (i = 0; i < FCP_NUM_HASH; i++) {
14787                 ptgt = pptr->port_tgt_hash_table[i];
14788                 while (ptgt != NULL) {
14789                         struct fcp_tgt *next_tgt = ptgt->tgt_next;
14790 
14791                         fcp_free_target(ptgt);
14792                         ptgt = next_tgt;
14793                 }
14794         }
14795         mutex_exit(&pptr->port_mutex);
14796 }
14797 
14798 
14799 static void
14800 fcp_free_target(struct fcp_tgt *ptgt)
14801 {
14802         struct fcp_lun  *plun;
14803         timeout_id_t            tid;
14804 
14805         mutex_enter(&ptgt->tgt_mutex);
14806         tid = ptgt->tgt_tid;
14807 
14808         /*
14809          * Cancel any pending timeouts for this target.
14810          */
14811 
14812         if (tid != NULL) {
14813                 /*
14814                  * Set tgt_tid to NULL first to avoid a race in the callback.
14815                  * If tgt_tid is NULL, the callback will simply return.
14816                  */
14817                 ptgt->tgt_tid = NULL;
14818                 mutex_exit(&ptgt->tgt_mutex);
14819                 (void) untimeout(tid);
14820                 mutex_enter(&ptgt->tgt_mutex);
14821         }
14822 
14823         plun = ptgt->tgt_lun;
14824         while (plun != NULL) {
14825                 struct fcp_lun *next_lun = plun->lun_next;
14826 
14827                 fcp_dealloc_lun(plun);
14828                 plun = next_lun;
14829         }
14830 
14831         mutex_exit(&ptgt->tgt_mutex);
14832         fcp_dealloc_tgt(ptgt);
14833 }
14834 
14835 /*
14836  *     Function: fcp_is_retryable
14837  *
14838  *  Description: Indicates if the internal packet is retryable.
14839  *
14840  *     Argument: *icmd          FCP internal packet.
14841  *
14842  * Return Value: 0      Not retryable
14843  *               1      Retryable
14844  *
14845  *      Context: User, Kernel and Interrupt context
14846  */
14847 static int
14848 fcp_is_retryable(struct fcp_ipkt *icmd)
14849 {
14850         if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14851             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14852                 return (0);
14853         }
14854 
14855         return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14856             icmd->ipkt_port->port_deadline) ? 1 : 0);
14857 }
14858 
14859 /*
14860  *     Function: fcp_create_on_demand
14861  *
14862  *     Argument: *pptr          FCP port.
14863  *               *pwwn          Port WWN.
14864  *
14865  * Return Value: 0      Success
14866  *               EIO
14867  *               ENOMEM
14868  *               EBUSY
14869  *               EINVAL
14870  *
14871  *      Context: User and Kernel context
14872  */
14873 static int
14874 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14875 {
14876         int                     wait_ms;
14877         int                     tcount;
14878         int                     lcount;
14879         int                     ret;
14880         int                     error;
14881         int                     rval = EIO;
14882         int                     ntries;
14883         fc_portmap_t            *devlist;
14884         opaque_t                pd;
14885         struct fcp_lun          *plun;
14886         struct fcp_tgt          *ptgt;
14887         int                     old_manual = 0;
14888 
14889         /* Allocates the fc_portmap_t structure. */
14890         devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14891 
14892         /*
14893          * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14894          * in the commented statement below:
14895          *
14896          * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14897          *
14898          * Below, the deadline for the discovery process is set.
14899          */
14900         mutex_enter(&pptr->port_mutex);
14901         pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14902         mutex_exit(&pptr->port_mutex);
14903 
14904         /*
14905          * We try to find the remote port based on the WWN provided by the
14906          * caller.  We actually ask fp/fctl if it has it.
14907          */
14908         pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14909             (la_wwn_t *)pwwn, &error, 1);
14910 
14911         if (pd == NULL) {
14912                 kmem_free(devlist, sizeof (*devlist));
14913                 return (rval);
14914         }
14915 
14916         /*
14917          * The remote port was found.  We ask fp/fctl to update our
14918          * fc_portmap_t structure.
14919          */
14920         ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14921             (la_wwn_t *)pwwn, devlist);
14922         if (ret != FC_SUCCESS) {
14923                 kmem_free(devlist, sizeof (*devlist));
14924                 return (rval);
14925         }
14926 
14927         /*
14928          * The map flag field is set to indicates that the creation is being
14929          * done at the user request (Ioclt probably luxadm or cfgadm).
14930          */
14931         devlist->map_type = PORT_DEVICE_USER_CREATE;
14932 
14933         mutex_enter(&pptr->port_mutex);
14934 
14935         /*
14936          * We check to see if fcp already has a target that describes the
14937          * device being created.  If not it is created.
14938          */
14939         ptgt = fcp_lookup_target(pptr, pwwn);
14940         if (ptgt == NULL) {
14941                 lcount = pptr->port_link_cnt;
14942                 mutex_exit(&pptr->port_mutex);
14943 
14944                 ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14945                 if (ptgt == NULL) {
14946                         fcp_log(CE_WARN, pptr->port_dip,
14947                             "!FC target allocation failed");
14948                         return (ENOMEM);
14949                 }
14950 
14951                 mutex_enter(&pptr->port_mutex);
14952         }
14953 
14954         mutex_enter(&ptgt->tgt_mutex);
14955         ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
14956         ptgt->tgt_tmp_cnt = 1;
14957         ptgt->tgt_device_created = 0;
14958         /*
14959          * If fabric and auto config is set but the target was
14960          * manually unconfigured then reset to the manual_config_only to
14961          * 0 so the device will get configured.
14962          */
14963         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14964             fcp_enable_auto_configuration &&
14965             ptgt->tgt_manual_config_only == 1) {
14966                 old_manual = 1;
14967                 ptgt->tgt_manual_config_only = 0;
14968         }
14969         mutex_exit(&ptgt->tgt_mutex);
14970 
14971         fcp_update_targets(pptr, devlist, 1,
14972             FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
14973 
14974         lcount = pptr->port_link_cnt;
14975         tcount = ptgt->tgt_change_cnt;
14976 
14977         if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
14978             tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
14979                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
14980                     fcp_enable_auto_configuration && old_manual) {
14981                         mutex_enter(&ptgt->tgt_mutex);
14982                         ptgt->tgt_manual_config_only = 1;
14983                         mutex_exit(&ptgt->tgt_mutex);
14984                 }
14985 
14986                 if (pptr->port_link_cnt != lcount ||
14987                     ptgt->tgt_change_cnt != tcount) {
14988                         rval = EBUSY;
14989                 }
14990                 mutex_exit(&pptr->port_mutex);
14991 
14992                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14993                     FCP_BUF_LEVEL_3, 0,
14994                     "fcp_create_on_demand: mapflags ptgt=%x, "
14995                     "lcount=%x::port_link_cnt=%x, "
14996                     "tcount=%x: tgt_change_cnt=%x, rval=%x",
14997                     ptgt, lcount, pptr->port_link_cnt,
14998                     tcount, ptgt->tgt_change_cnt, rval);
14999                 return (rval);
15000         }
15001 
15002         /*
15003          * Due to lack of synchronization mechanisms, we perform
15004          * periodic monitoring of our request; Because requests
15005          * get dropped when another one supercedes (either because
15006          * of a link change or a target change), it is difficult to
15007          * provide a clean synchronization mechanism (such as a
15008          * semaphore or a conditional variable) without exhaustively
15009          * rewriting the mainline discovery code of this driver.
15010          */
15011         wait_ms = 500;
15012 
15013         ntries = fcp_max_target_retries;
15014 
15015         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15016             FCP_BUF_LEVEL_3, 0,
15017             "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15018             "lcount=%x::port_link_cnt=%x, "
15019             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15020             "tgt_tmp_cnt =%x",
15021             ntries, ptgt, lcount, pptr->port_link_cnt,
15022             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15023             ptgt->tgt_tmp_cnt);
15024 
15025         mutex_enter(&ptgt->tgt_mutex);
15026         while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15027             ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15028                 mutex_exit(&ptgt->tgt_mutex);
15029                 mutex_exit(&pptr->port_mutex);
15030 
15031                 delay(drv_usectohz(wait_ms * 1000));
15032 
15033                 mutex_enter(&pptr->port_mutex);
15034                 mutex_enter(&ptgt->tgt_mutex);
15035         }
15036 
15037 
15038         if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15039                 rval = EBUSY;
15040         } else {
15041                 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15042                     FCP_TGT_NODE_PRESENT) {
15043                         rval = 0;
15044                 }
15045         }
15046 
15047         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15048             FCP_BUF_LEVEL_3, 0,
15049             "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15050             "lcount=%x::port_link_cnt=%x, "
15051             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15052             "tgt_tmp_cnt =%x",
15053             ntries, ptgt, lcount, pptr->port_link_cnt,
15054             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15055             ptgt->tgt_tmp_cnt);
15056 
15057         if (rval) {
15058                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15059                     fcp_enable_auto_configuration && old_manual) {
15060                         ptgt->tgt_manual_config_only = 1;
15061                 }
15062                 mutex_exit(&ptgt->tgt_mutex);
15063                 mutex_exit(&pptr->port_mutex);
15064                 kmem_free(devlist, sizeof (*devlist));
15065 
15066                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15067                     FCP_BUF_LEVEL_3, 0,
15068                     "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15069                     "lcount=%x::port_link_cnt=%x, "
15070                     "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15071                     "tgt_device_created=%x, tgt D_ID=%x",
15072                     ntries, ptgt, lcount, pptr->port_link_cnt,
15073                     tcount, ptgt->tgt_change_cnt, rval,
15074                     ptgt->tgt_device_created, ptgt->tgt_d_id);
15075                 return (rval);
15076         }
15077 
15078         if ((plun = ptgt->tgt_lun) != NULL) {
15079                 tcount = plun->lun_tgt->tgt_change_cnt;
15080         } else {
15081                 rval = EINVAL;
15082         }
15083         lcount = pptr->port_link_cnt;
15084 
15085         /*
15086          * Configuring the target with no LUNs will fail. We
15087          * should reset the node state so that it is not
15088          * automatically configured when the LUNs are added
15089          * to this target.
15090          */
15091         if (ptgt->tgt_lun_cnt == 0) {
15092                 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15093         }
15094         mutex_exit(&ptgt->tgt_mutex);
15095         mutex_exit(&pptr->port_mutex);
15096 
15097         while (plun) {
15098                 child_info_t    *cip;
15099 
15100                 mutex_enter(&plun->lun_mutex);
15101                 cip = plun->lun_cip;
15102                 mutex_exit(&plun->lun_mutex);
15103 
15104                 mutex_enter(&ptgt->tgt_mutex);
15105                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15106                         mutex_exit(&ptgt->tgt_mutex);
15107 
15108                         rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15109                             FCP_ONLINE, lcount, tcount,
15110                             NDI_ONLINE_ATTACH);
15111                         if (rval != NDI_SUCCESS) {
15112                                 FCP_TRACE(fcp_logq,
15113                                     pptr->port_instbuf, fcp_trace,
15114                                     FCP_BUF_LEVEL_3, 0,
15115                                     "fcp_create_on_demand: "
15116                                     "pass_to_hp_and_wait failed "
15117                                     "rval=%x", rval);
15118                                 rval = EIO;
15119                         } else {
15120                                 mutex_enter(&LUN_TGT->tgt_mutex);
15121                                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
15122                                     FCP_LUN_BUSY);
15123                                 mutex_exit(&LUN_TGT->tgt_mutex);
15124                         }
15125                         mutex_enter(&ptgt->tgt_mutex);
15126                 }
15127 
15128                 plun = plun->lun_next;
15129                 mutex_exit(&ptgt->tgt_mutex);
15130         }
15131 
15132         kmem_free(devlist, sizeof (*devlist));
15133 
15134         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15135             fcp_enable_auto_configuration && old_manual) {
15136                 mutex_enter(&ptgt->tgt_mutex);
15137                 /* if successful then set manual to 0 */
15138                 if (rval == 0) {
15139                         ptgt->tgt_manual_config_only = 0;
15140                 } else {
15141                         /* reset to 1 so the user has to do the config */
15142                         ptgt->tgt_manual_config_only = 1;
15143                 }
15144                 mutex_exit(&ptgt->tgt_mutex);
15145         }
15146 
15147         return (rval);
15148 }
15149 
15150 
15151 static void
15152 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15153 {
15154         int             count;
15155         uchar_t         byte;
15156 
15157         count = 0;
15158         while (*string) {
15159                 byte = FCP_ATOB(*string); string++;
15160                 byte = byte << 4 | FCP_ATOB(*string); string++;
15161                 bytes[count++] = byte;
15162 
15163                 if (count >= byte_len) {
15164                         break;
15165                 }
15166         }
15167 }
15168 
15169 static void
15170 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15171 {
15172         int             i;
15173 
15174         for (i = 0; i < FC_WWN_SIZE; i++) {
15175                 (void) sprintf(string + (i * 2),
15176                     "%02x", wwn[i]);
15177         }
15178 
15179 }
15180 
15181 static void
15182 fcp_print_error(fc_packet_t *fpkt)
15183 {
15184         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
15185             fpkt->pkt_ulp_private;
15186         struct fcp_port *pptr;
15187         struct fcp_tgt  *ptgt;
15188         struct fcp_lun  *plun;
15189         caddr_t                 buf;
15190         int                     scsi_cmd = 0;
15191 
15192         ptgt = icmd->ipkt_tgt;
15193         plun = icmd->ipkt_lun;
15194         pptr = ptgt->tgt_port;
15195 
15196         buf = kmem_zalloc(256, KM_NOSLEEP);
15197         if (buf == NULL) {
15198                 return;
15199         }
15200 
15201         switch (icmd->ipkt_opcode) {
15202         case SCMD_REPORT_LUN:
15203                 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15204                     " lun=0x%%x failed");
15205                 scsi_cmd++;
15206                 break;
15207 
15208         case SCMD_INQUIRY_PAGE83:
15209                 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15210                     " lun=0x%%x failed");
15211                 scsi_cmd++;
15212                 break;
15213 
15214         case SCMD_INQUIRY:
15215                 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15216                     " lun=0x%%x failed");
15217                 scsi_cmd++;
15218                 break;
15219 
15220         case LA_ELS_PLOGI:
15221                 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15222                 break;
15223 
15224         case LA_ELS_PRLI:
15225                 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15226                 break;
15227         }
15228 
15229         if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15230                 struct fcp_rsp          response, *rsp;
15231                 uchar_t                 asc, ascq;
15232                 caddr_t                 sense_key = NULL;
15233                 struct fcp_rsp_info     fcp_rsp_err, *bep;
15234 
15235                 if (icmd->ipkt_nodma) {
15236                         rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15237                         bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15238                             sizeof (struct fcp_rsp));
15239                 } else {
15240                         rsp = &response;
15241                         bep = &fcp_rsp_err;
15242 
15243                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15244                             sizeof (struct fcp_rsp));
15245 
15246                         FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15247                             bep, fpkt->pkt_resp_acc,
15248                             sizeof (struct fcp_rsp_info));
15249                 }
15250 
15251 
15252                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15253                         (void) sprintf(buf + strlen(buf),
15254                             " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15255                             " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15256                             " senselen=%%x. Giving up");
15257 
15258                         fcp_log(CE_WARN, pptr->port_dip, buf,
15259                             ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15260                             rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15261                             rsp->fcp_u.fcp_status.reserved_1,
15262                             rsp->fcp_response_len, rsp->fcp_sense_len);
15263 
15264                         kmem_free(buf, 256);
15265                         return;
15266                 }
15267 
15268                 if (rsp->fcp_u.fcp_status.rsp_len_set &&
15269                     bep->rsp_code != FCP_NO_FAILURE) {
15270                         (void) sprintf(buf + strlen(buf),
15271                             " FCP Response code = 0x%x", bep->rsp_code);
15272                 }
15273 
15274                 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15275                         struct scsi_extended_sense sense_info, *sense_ptr;
15276 
15277                         if (icmd->ipkt_nodma) {
15278                                 sense_ptr = (struct scsi_extended_sense *)
15279                                     ((caddr_t)fpkt->pkt_resp +
15280                                     sizeof (struct fcp_rsp) +
15281                                     rsp->fcp_response_len);
15282                         } else {
15283                                 sense_ptr = &sense_info;
15284 
15285                                 FCP_CP_IN(fpkt->pkt_resp +
15286                                     sizeof (struct fcp_rsp) +
15287                                     rsp->fcp_response_len, &sense_info,
15288                                     fpkt->pkt_resp_acc,
15289                                     sizeof (struct scsi_extended_sense));
15290                         }
15291 
15292                         if (sense_ptr->es_key < NUM_SENSE_KEYS +
15293                             NUM_IMPL_SENSE_KEYS) {
15294                                 sense_key = sense_keys[sense_ptr->es_key];
15295                         } else {
15296                                 sense_key = "Undefined";
15297                         }
15298 
15299                         asc = sense_ptr->es_add_code;
15300                         ascq = sense_ptr->es_qual_code;
15301 
15302                         (void) sprintf(buf + strlen(buf),
15303                             ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15304                             " Giving up");
15305 
15306                         fcp_log(CE_WARN, pptr->port_dip, buf,
15307                             ptgt->tgt_d_id, plun->lun_num, sense_key,
15308                             asc, ascq);
15309                 } else {
15310                         (void) sprintf(buf + strlen(buf),
15311                             " : SCSI status=%%x. Giving up");
15312 
15313                         fcp_log(CE_WARN, pptr->port_dip, buf,
15314                             ptgt->tgt_d_id, plun->lun_num,
15315                             rsp->fcp_u.fcp_status.scsi_status);
15316                 }
15317         } else {
15318                 caddr_t state, reason, action, expln;
15319 
15320                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
15321                     &action, &expln);
15322 
15323                 (void) sprintf(buf + strlen(buf), ": State:%%s,"
15324                     " Reason:%%s. Giving up");
15325 
15326                 if (scsi_cmd) {
15327                         fcp_log(CE_WARN, pptr->port_dip, buf,
15328                             ptgt->tgt_d_id, plun->lun_num, state, reason);
15329                 } else {
15330                         fcp_log(CE_WARN, pptr->port_dip, buf,
15331                             ptgt->tgt_d_id, state, reason);
15332                 }
15333         }
15334 
15335         kmem_free(buf, 256);
15336 }
15337 
15338 
15339 static int
15340 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15341     struct fcp_ipkt *icmd, int rval, caddr_t op)
15342 {
15343         int     ret = DDI_FAILURE;
15344         char    *error;
15345 
15346         switch (rval) {
15347         case FC_DEVICE_BUSY_NEW_RSCN:
15348                 /*
15349                  * This means that there was a new RSCN that the transport
15350                  * knows about (which the ULP *may* know about too) but the
15351                  * pkt that was sent down was related to an older RSCN. So, we
15352                  * are just going to reset the retry count and deadline and
15353                  * continue to retry. The idea is that transport is currently
15354                  * working on the new RSCN and will soon let the ULPs know
15355                  * about it and when it does the existing logic will kick in
15356                  * where it will change the tcount to indicate that something
15357                  * changed on the target. So, rediscovery will start and there
15358                  * will not be an infinite retry.
15359                  *
15360                  * For a full flow of how the RSCN info is transferred back and
15361                  * forth, see fp.c
15362                  */
15363                 icmd->ipkt_retries = 0;
15364                 icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15365                     FCP_ICMD_DEADLINE;
15366 
15367                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15368                     FCP_BUF_LEVEL_3, 0,
15369                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15370                     rval, ptgt->tgt_d_id);
15371                 /* FALLTHROUGH */
15372 
15373         case FC_STATEC_BUSY:
15374         case FC_DEVICE_BUSY:
15375         case FC_PBUSY:
15376         case FC_FBUSY:
15377         case FC_TRAN_BUSY:
15378         case FC_OFFLINE:
15379                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15380                     FCP_BUF_LEVEL_3, 0,
15381                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15382                     rval, ptgt->tgt_d_id);
15383                 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15384                     fcp_is_retryable(icmd)) {
15385                         fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15386                         ret = DDI_SUCCESS;
15387                 }
15388                 break;
15389 
15390         case FC_LOGINREQ:
15391                 /*
15392                  * FC_LOGINREQ used to be handled just like all the cases
15393                  * above. It has been changed to handled a PRLI that fails
15394                  * with FC_LOGINREQ different than other ipkts that fail
15395                  * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15396                  * a simple matter to turn it into a PLOGI instead, so that's
15397                  * exactly what we do here.
15398                  */
15399                 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15400                         ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15401                             icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15402                             icmd->ipkt_change_cnt, icmd->ipkt_cause);
15403                 } else {
15404                         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15405                             FCP_BUF_LEVEL_3, 0,
15406                             "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15407                             rval, ptgt->tgt_d_id);
15408                         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15409                             fcp_is_retryable(icmd)) {
15410                                 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15411                                 ret = DDI_SUCCESS;
15412                         }
15413                 }
15414                 break;
15415 
15416         default:
15417                 mutex_enter(&pptr->port_mutex);
15418                 mutex_enter(&ptgt->tgt_mutex);
15419                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15420                         mutex_exit(&ptgt->tgt_mutex);
15421                         mutex_exit(&pptr->port_mutex);
15422 
15423                         (void) fc_ulp_error(rval, &error);
15424                         fcp_log(CE_WARN, pptr->port_dip,
15425                             "!Failed to send %s to D_ID=%x error=%s",
15426                             op, ptgt->tgt_d_id, error);
15427                 } else {
15428                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
15429                             fcp_trace, FCP_BUF_LEVEL_2, 0,
15430                             "fcp_handle_ipkt_errors,1: state change occured"
15431                             " for D_ID=0x%x", ptgt->tgt_d_id);
15432                         mutex_exit(&ptgt->tgt_mutex);
15433                         mutex_exit(&pptr->port_mutex);
15434                 }
15435                 break;
15436         }
15437 
15438         return (ret);
15439 }
15440 
15441 
15442 /*
15443  * Check of outstanding commands on any LUN for this target
15444  */
15445 static int
15446 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15447 {
15448         struct  fcp_lun *plun;
15449         struct  fcp_pkt *cmd;
15450 
15451         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15452                 mutex_enter(&plun->lun_mutex);
15453                 for (cmd = plun->lun_pkt_head; cmd != NULL;
15454                     cmd = cmd->cmd_forw) {
15455                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
15456                                 mutex_exit(&plun->lun_mutex);
15457                                 return (FC_SUCCESS);
15458                         }
15459                 }
15460                 mutex_exit(&plun->lun_mutex);
15461         }
15462 
15463         return (FC_FAILURE);
15464 }
15465 
15466 static fc_portmap_t *
15467 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15468 {
15469         int                     i;
15470         fc_portmap_t            *devlist;
15471         fc_portmap_t            *devptr = NULL;
15472         struct fcp_tgt  *ptgt;
15473 
15474         mutex_enter(&pptr->port_mutex);
15475         for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15476                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15477                     ptgt = ptgt->tgt_next) {
15478                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15479                                 ++*dev_cnt;
15480                         }
15481                 }
15482         }
15483 
15484         devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15485             KM_NOSLEEP);
15486         if (devlist == NULL) {
15487                 mutex_exit(&pptr->port_mutex);
15488                 fcp_log(CE_WARN, pptr->port_dip,
15489                     "!fcp%d: failed to allocate for portmap for construct map",
15490                     pptr->port_instance);
15491                 return (devptr);
15492         }
15493 
15494         for (i = 0; i < FCP_NUM_HASH; i++) {
15495                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15496                     ptgt = ptgt->tgt_next) {
15497                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15498                                 int ret;
15499 
15500                                 ret = fc_ulp_pwwn_to_portmap(
15501                                     pptr->port_fp_handle,
15502                                     (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15503                                     devlist);
15504 
15505                                 if (ret == FC_SUCCESS) {
15506                                         devlist++;
15507                                         continue;
15508                                 }
15509 
15510                                 devlist->map_pd = NULL;
15511                                 devlist->map_did.port_id = ptgt->tgt_d_id;
15512                                 devlist->map_hard_addr.hard_addr =
15513                                     ptgt->tgt_hard_addr;
15514 
15515                                 devlist->map_state = PORT_DEVICE_INVALID;
15516                                 devlist->map_type = PORT_DEVICE_OLD;
15517 
15518                                 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15519                                     &devlist->map_nwwn, FC_WWN_SIZE);
15520 
15521                                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15522                                     &devlist->map_pwwn, FC_WWN_SIZE);
15523 
15524                                 devlist++;
15525                         }
15526                 }
15527         }
15528 
15529         mutex_exit(&pptr->port_mutex);
15530 
15531         return (devptr);
15532 }
15533 /*
15534  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15535  */
15536 static void
15537 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15538 {
15539         int i;
15540         struct fcp_tgt  *ptgt;
15541         struct fcp_lun  *plun;
15542 
15543         for (i = 0; i < FCP_NUM_HASH; i++) {
15544                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15545                     ptgt = ptgt->tgt_next) {
15546                         mutex_enter(&ptgt->tgt_mutex);
15547                         for (plun = ptgt->tgt_lun; plun != NULL;
15548                             plun = plun->lun_next) {
15549                                 if (plun->lun_mpxio &&
15550                                     plun->lun_state & FCP_LUN_BUSY) {
15551                                         if (!fcp_pass_to_hp(pptr, plun,
15552                                             plun->lun_cip,
15553                                             FCP_MPXIO_PATH_SET_BUSY,
15554                                             pptr->port_link_cnt,
15555                                             ptgt->tgt_change_cnt, 0, 0)) {
15556                                                 FCP_TRACE(fcp_logq,
15557                                                     pptr->port_instbuf,
15558                                                     fcp_trace,
15559                                                     FCP_BUF_LEVEL_2, 0,
15560                                                     "path_verifybusy: "
15561                                                     "disable lun %p failed!",
15562                                                     plun);
15563                                         }
15564                                 }
15565                         }
15566                         mutex_exit(&ptgt->tgt_mutex);
15567                 }
15568         }
15569 }
15570 
15571 static int
15572 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15573 {
15574         dev_info_t              *cdip = NULL;
15575         dev_info_t              *pdip = NULL;
15576 
15577         ASSERT(plun);
15578 
15579         mutex_enter(&plun->lun_mutex);
15580         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15581                 mutex_exit(&plun->lun_mutex);
15582                 return (NDI_FAILURE);
15583         }
15584         mutex_exit(&plun->lun_mutex);
15585         cdip = mdi_pi_get_client(PIP(cip));
15586         pdip = mdi_pi_get_phci(PIP(cip));
15587 
15588         ASSERT(cdip != NULL);
15589         ASSERT(pdip != NULL);
15590 
15591         if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15592                 /* LUN ready for IO */
15593                 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15594         } else {
15595                 /* LUN busy to accept IO */
15596                 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15597         }
15598         return (NDI_SUCCESS);
15599 }
15600 
15601 /*
15602  * Caller must free the returned string of MAXPATHLEN len
15603  * If the device is offline (-1 instance number) NULL
15604  * will be returned.
15605  */
15606 static char *
15607 fcp_get_lun_path(struct fcp_lun *plun)
15608 {
15609         dev_info_t      *dip = NULL;
15610         char            *path = NULL;
15611         mdi_pathinfo_t  *pip = NULL;
15612 
15613         if (plun == NULL) {
15614                 return (NULL);
15615         }
15616 
15617         mutex_enter(&plun->lun_mutex);
15618         if (plun->lun_mpxio == 0) {
15619                 dip = DIP(plun->lun_cip);
15620                 mutex_exit(&plun->lun_mutex);
15621         } else {
15622                 /*
15623                  * lun_cip must be accessed with lun_mutex held. Here
15624                  * plun->lun_cip either points to a valid node or it is NULL.
15625                  * Make a copy so that we can release lun_mutex.
15626                  */
15627                 pip = PIP(plun->lun_cip);
15628 
15629                 /*
15630                  * Increase ref count on the path so that we can release
15631                  * lun_mutex and still be sure that the pathinfo node (and thus
15632                  * also the client) is not deallocated. If pip is NULL, this
15633                  * has no effect.
15634                  */
15635                 mdi_hold_path(pip);
15636 
15637                 mutex_exit(&plun->lun_mutex);
15638 
15639                 /* Get the client. If pip is NULL, we get NULL. */
15640                 dip = mdi_pi_get_client(pip);
15641         }
15642 
15643         if (dip == NULL)
15644                 goto out;
15645         if (ddi_get_instance(dip) < 0)
15646                 goto out;
15647 
15648         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15649         if (path == NULL)
15650                 goto out;
15651 
15652         (void) ddi_pathname(dip, path);
15653 
15654         /* Clean up. */
15655 out:
15656         if (pip != NULL)
15657                 mdi_rele_path(pip);
15658 
15659         /*
15660          * In reality, the user wants a fully valid path (one they can open)
15661          * but this string is lacking the mount point, and the minor node.
15662          * It would be nice if we could "figure these out" somehow
15663          * and fill them in.  Otherwise, the userland code has to understand
15664          * driver specific details of which minor node is the "best" or
15665          * "right" one to expose.  (Ex: which slice is the whole disk, or
15666          * which tape doesn't rewind)
15667          */
15668         return (path);
15669 }
15670 
15671 static int
15672 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15673     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15674 {
15675         int64_t reset_delay;
15676         int rval, retry = 0;
15677         struct fcp_port *pptr = fcp_dip2port(parent);
15678 
15679         reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15680             (ddi_get_lbolt64() - pptr->port_attach_time);
15681         if (reset_delay < 0) {
15682                 reset_delay = 0;
15683         }
15684 
15685         if (fcp_bus_config_debug) {
15686                 flag |= NDI_DEVI_DEBUG;
15687         }
15688 
15689         switch (op) {
15690         case BUS_CONFIG_ONE:
15691                 /*
15692                  * Retry the command since we need to ensure
15693                  * the fabric devices are available for root
15694                  */
15695                 while (retry++ < fcp_max_bus_config_retries) {
15696                         rval =  (ndi_busop_bus_config(parent,
15697                             flag | NDI_MDI_FALLBACK, op,
15698                             arg, childp, (clock_t)reset_delay));
15699                         if (rval == 0) {
15700                                 return (rval);
15701                         }
15702                 }
15703 
15704                 /*
15705                  * drain taskq to make sure nodes are created and then
15706                  * try again.
15707                  */
15708                 taskq_wait(DEVI(parent)->devi_taskq);
15709                 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15710                     op, arg, childp, 0));
15711 
15712         case BUS_CONFIG_DRIVER:
15713         case BUS_CONFIG_ALL: {
15714                 /*
15715                  * delay till all devices report in (port_tmp_cnt == 0)
15716                  * or FCP_INIT_WAIT_TIMEOUT
15717                  */
15718                 mutex_enter(&pptr->port_mutex);
15719                 while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15720                         (void) cv_timedwait(&pptr->port_config_cv,
15721                             &pptr->port_mutex,
15722                             ddi_get_lbolt() + (clock_t)reset_delay);
15723                         reset_delay =
15724                             (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15725                             (ddi_get_lbolt64() - pptr->port_attach_time);
15726                 }
15727                 mutex_exit(&pptr->port_mutex);
15728                 /* drain taskq to make sure nodes are created */
15729                 taskq_wait(DEVI(parent)->devi_taskq);
15730                 return (ndi_busop_bus_config(parent, flag, op,
15731                     arg, childp, 0));
15732         }
15733 
15734         default:
15735                 return (NDI_FAILURE);
15736         }
15737         /*NOTREACHED*/
15738 }
15739 
15740 static int
15741 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15742     ddi_bus_config_op_t op, void *arg)
15743 {
15744         if (fcp_bus_config_debug) {
15745                 flag |= NDI_DEVI_DEBUG;
15746         }
15747 
15748         return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15749 }
15750 
15751 
15752 /*
15753  * Routine to copy GUID into the lun structure.
15754  * returns 0 if copy was successful and 1 if encountered a
15755  * failure and did not copy the guid.
15756  */
15757 static int
15758 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15759 {
15760 
15761         int retval = 0;
15762 
15763         /* add one for the null terminator */
15764         const unsigned int len = strlen(guidp) + 1;
15765 
15766         if ((guidp == NULL) || (plun == NULL)) {
15767                 return (1);
15768         }
15769 
15770         /*
15771          * if the plun->lun_guid already has been allocated,
15772          * then check the size. if the size is exact, reuse
15773          * it....if not free it an allocate the required size.
15774          * The reallocation should NOT typically happen
15775          * unless the GUIDs reported changes between passes.
15776          * We free up and alloc again even if the
15777          * size was more than required. This is due to the
15778          * fact that the field lun_guid_size - serves
15779          * dual role of indicating the size of the wwn
15780          * size and ALSO the allocation size.
15781          */
15782         if (plun->lun_guid) {
15783                 if (plun->lun_guid_size != len) {
15784                         /*
15785                          * free the allocated memory and
15786                          * initialize the field
15787                          * lun_guid_size to 0.
15788                          */
15789                         kmem_free(plun->lun_guid, plun->lun_guid_size);
15790                         plun->lun_guid = NULL;
15791                         plun->lun_guid_size = 0;
15792                 }
15793         }
15794         /*
15795          * alloc only if not already done.
15796          */
15797         if (plun->lun_guid == NULL) {
15798                 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15799                 if (plun->lun_guid == NULL) {
15800                         cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15801                             "Unable to allocate"
15802                             "Memory for GUID!!! size %d", len);
15803                         retval = 1;
15804                 } else {
15805                         plun->lun_guid_size = len;
15806                 }
15807         }
15808         if (plun->lun_guid) {
15809                 /*
15810                  * now copy the GUID
15811                  */
15812                 bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15813         }
15814         return (retval);
15815 }
15816 
15817 /*
15818  * fcp_reconfig_wait
15819  *
15820  * Wait for a rediscovery/reconfiguration to complete before continuing.
15821  */
15822 
15823 static void
15824 fcp_reconfig_wait(struct fcp_port *pptr)
15825 {
15826         clock_t         reconfig_start, wait_timeout;
15827 
15828         /*
15829          * Quick check.  If pptr->port_tmp_cnt is 0, there is no
15830          * reconfiguration in progress.
15831          */
15832 
15833         mutex_enter(&pptr->port_mutex);
15834         if (pptr->port_tmp_cnt == 0) {
15835                 mutex_exit(&pptr->port_mutex);
15836                 return;
15837         }
15838         mutex_exit(&pptr->port_mutex);
15839 
15840         /*
15841          * If we cause a reconfig by raising power, delay until all devices
15842          * report in (port_tmp_cnt returns to 0)
15843          */
15844 
15845         reconfig_start = ddi_get_lbolt();
15846         wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15847 
15848         mutex_enter(&pptr->port_mutex);
15849 
15850         while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15851             pptr->port_tmp_cnt) {
15852 
15853                 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15854                     reconfig_start + wait_timeout);
15855         }
15856 
15857         mutex_exit(&pptr->port_mutex);
15858 
15859         /*
15860          * Even if fcp_tmp_count isn't 0, continue without error.  The port
15861          * we want may still be ok.  If not, it will error out later
15862          */
15863 }
15864 
15865 /*
15866  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15867  * We rely on the fcp_global_mutex to provide protection against changes to
15868  * the fcp_lun_blacklist.
15869  *
15870  * You can describe a list of target port WWNs and LUN numbers which will
15871  * not be configured. LUN numbers will be interpreted as decimal. White
15872  * spaces and ',' can be used in the list of LUN numbers.
15873  *
15874  * To prevent LUNs 1 and 2 from being configured for target
15875  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15876  *
15877  * pwwn-lun-blacklist=
15878  * "510000f010fd92a1,1,2",
15879  * "510000e012079df1,1,2";
15880  */
15881 static void
15882 fcp_read_blacklist(dev_info_t *dip,
15883     struct fcp_black_list_entry **pplun_blacklist)
15884 {
15885         char **prop_array       = NULL;
15886         char *curr_pwwn         = NULL;
15887         char *curr_lun          = NULL;
15888         uint32_t prop_item      = 0;
15889         int idx                 = 0;
15890         int len                 = 0;
15891 
15892         ASSERT(mutex_owned(&fcp_global_mutex));
15893         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15894             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15895             LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15896                 return;
15897         }
15898 
15899         for (idx = 0; idx < prop_item; idx++) {
15900 
15901                 curr_pwwn = prop_array[idx];
15902                 while (*curr_pwwn == ' ') {
15903                         curr_pwwn++;
15904                 }
15905                 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15906                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15907                             ", please check.", curr_pwwn);
15908                         continue;
15909                 }
15910                 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15911                     (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15912                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15913                             ", please check.", curr_pwwn);
15914                         continue;
15915                 }
15916                 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15917                         if (isxdigit(curr_pwwn[len]) != TRUE) {
15918                                 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15919                                     "blacklist, please check.", curr_pwwn);
15920                                 break;
15921                         }
15922                 }
15923                 if (len != sizeof (la_wwn_t) * 2) {
15924                         continue;
15925                 }
15926 
15927                 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15928                 *(curr_lun - 1) = '\0';
15929                 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15930         }
15931 
15932         ddi_prop_free(prop_array);
15933 }
15934 
15935 /*
15936  * Get the masking info about one remote target port designated by wwn.
15937  * Lun ids could be separated by ',' or white spaces.
15938  */
15939 static void
15940 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15941     struct fcp_black_list_entry **pplun_blacklist)
15942 {
15943         int             idx                     = 0;
15944         uint32_t        offset                  = 0;
15945         unsigned long   lun_id                  = 0;
15946         char            lunid_buf[16];
15947         char            *pend                   = NULL;
15948         int             illegal_digit           = 0;
15949 
15950         while (offset < strlen(curr_lun)) {
15951                 while ((curr_lun[offset + idx] != ',') &&
15952                     (curr_lun[offset + idx] != '\0') &&
15953                     (curr_lun[offset + idx] != ' ')) {
15954                         if (isdigit(curr_lun[offset + idx]) == 0) {
15955                                 illegal_digit++;
15956                         }
15957                         idx++;
15958                 }
15959                 if (illegal_digit > 0) {
15960                         offset += (idx+1);      /* To the start of next lun */
15961                         idx = 0;
15962                         illegal_digit = 0;
15963                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15964                             "the blacklist, please check digits.",
15965                             curr_lun, curr_pwwn);
15966                         continue;
15967                 }
15968                 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
15969                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15970                             "the blacklist, please check the length of LUN#.",
15971                             curr_lun, curr_pwwn);
15972                         break;
15973                 }
15974                 if (idx == 0) { /* ignore ' ' or ',' or '\0' */
15975                         offset++;
15976                         continue;
15977                 }
15978 
15979                 bcopy(curr_lun + offset, lunid_buf, idx);
15980                 lunid_buf[idx] = '\0';
15981                 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
15982                         fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
15983                 } else {
15984                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
15985                             "the blacklist, please check %s.",
15986                             curr_lun, curr_pwwn, lunid_buf);
15987                 }
15988                 offset += (idx+1);      /* To the start of next lun */
15989                 idx = 0;
15990         }
15991 }
15992 
15993 /*
15994  * Add one masking record
15995  */
15996 static void
15997 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
15998     struct fcp_black_list_entry **pplun_blacklist)
15999 {
16000         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16001         struct fcp_black_list_entry     *new_entry      = NULL;
16002         la_wwn_t                        wwn;
16003 
16004         fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16005         while (tmp_entry) {
16006                 if ((bcmp(&tmp_entry->wwn, &wwn,
16007                     sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16008                         return;
16009                 }
16010 
16011                 tmp_entry = tmp_entry->next;
16012         }
16013 
16014         /* add to black list */
16015         new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16016             (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16017         bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16018         new_entry->lun = lun_id;
16019         new_entry->masked = 0;
16020         new_entry->next = *pplun_blacklist;
16021         *pplun_blacklist = new_entry;
16022 }
16023 
16024 /*
16025  * Check if we should mask the specified lun of this fcp_tgt
16026  */
16027 static int
16028 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id)
16029 {
16030         struct fcp_black_list_entry *remote_port;
16031 
16032         remote_port = fcp_lun_blacklist;
16033         while (remote_port != NULL) {
16034                 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16035                         if (remote_port->lun == lun_id) {
16036                                 remote_port->masked++;
16037                                 if (remote_port->masked == 1) {
16038                                         fcp_log(CE_NOTE, NULL, "LUN %d of port "
16039                                             "%02x%02x%02x%02x%02x%02x%02x%02x "
16040                                             "is masked due to black listing.\n",
16041                                             lun_id, wwn->raw_wwn[0],
16042                                             wwn->raw_wwn[1], wwn->raw_wwn[2],
16043                                             wwn->raw_wwn[3], wwn->raw_wwn[4],
16044                                             wwn->raw_wwn[5], wwn->raw_wwn[6],
16045                                             wwn->raw_wwn[7]);
16046                                 }
16047                                 return (TRUE);
16048                         }
16049                 }
16050                 remote_port = remote_port->next;
16051         }
16052         return (FALSE);
16053 }
16054 
16055 /*
16056  * Release all allocated resources
16057  */
16058 static void
16059 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist)
16060 {
16061         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16062         struct fcp_black_list_entry     *current_entry  = NULL;
16063 
16064         ASSERT(mutex_owned(&fcp_global_mutex));
16065         /*
16066          * Traverse all luns
16067          */
16068         while (tmp_entry) {
16069                 current_entry = tmp_entry;
16070                 tmp_entry = tmp_entry->next;
16071                 kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16072         }
16073         *pplun_blacklist = NULL;
16074 }
16075 
16076 /*
16077  * In fcp module,
16078  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16079  */
16080 static struct scsi_pkt *
16081 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16082     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16083     int flags, int (*callback)(), caddr_t arg)
16084 {
16085         fcp_port_t      *pptr = ADDR2FCP(ap);
16086         fcp_pkt_t       *cmd  = NULL;
16087         fc_frame_hdr_t  *hp;
16088 
16089         /*
16090          * First step: get the packet
16091          */
16092         if (pkt == NULL) {
16093                 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16094                     tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16095                     callback, arg);
16096                 if (pkt == NULL) {
16097                         return (NULL);
16098                 }
16099 
16100                 /*
16101                  * All fields in scsi_pkt will be initialized properly or
16102                  * set to zero. We need do nothing for scsi_pkt.
16103                  */
16104                 /*
16105                  * But it's our responsibility to link other related data
16106                  * structures. Their initialization will be done, just
16107                  * before the scsi_pkt will be sent to FCA.
16108                  */
16109                 cmd             = PKT2CMD(pkt);
16110                 cmd->cmd_pkt = pkt;
16111                 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16112                 /*
16113                  * fc_packet_t
16114                  */
16115                 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16116                 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16117                     sizeof (struct fcp_pkt));
16118                 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16119                 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16120                 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16121                 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16122                 /*
16123                  * Fill in the Fabric Channel Header
16124                  */
16125                 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16126                 hp->r_ctl = R_CTL_COMMAND;
16127                 hp->rsvd = 0;
16128                 hp->type = FC_TYPE_SCSI_FCP;
16129                 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16130                 hp->seq_id = 0;
16131                 hp->df_ctl  = 0;
16132                 hp->seq_cnt = 0;
16133                 hp->ox_id = 0xffff;
16134                 hp->rx_id = 0xffff;
16135                 hp->ro = 0;
16136         } else {
16137                 /*
16138                  * We need think if we should reset any elements in
16139                  * related data structures.
16140                  */
16141                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
16142                     fcp_trace, FCP_BUF_LEVEL_6, 0,
16143                     "reusing pkt, flags %d", flags);
16144                 cmd = PKT2CMD(pkt);
16145                 if (cmd->cmd_fp_pkt->pkt_pd) {
16146                         cmd->cmd_fp_pkt->pkt_pd = NULL;
16147                 }
16148         }
16149 
16150         /*
16151          * Second step:  dma allocation/move
16152          */
16153         if (bp && bp->b_bcount != 0) {
16154                 /*
16155                  * Mark if it's read or write
16156                  */
16157                 if (bp->b_flags & B_READ) {
16158                         cmd->cmd_flags |= CFLAG_IS_READ;
16159                 } else {
16160                         cmd->cmd_flags &= ~CFLAG_IS_READ;
16161                 }
16162 
16163                 bp_mapin(bp);
16164                 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16165                 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16166                 cmd->cmd_fp_pkt->pkt_data_resid = 0;
16167         } else {
16168                 /*
16169                  * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16170                  * to send zero-length read/write.
16171                  */
16172                 cmd->cmd_fp_pkt->pkt_data = NULL;
16173                 cmd->cmd_fp_pkt->pkt_datalen = 0;
16174         }
16175 
16176         return (pkt);
16177 }
16178 
16179 static void
16180 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16181 {
16182         fcp_port_t      *pptr = ADDR2FCP(ap);
16183 
16184         /*
16185          * First we let FCA to uninitilize private part.
16186          */
16187         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16188             PKT2CMD(pkt)->cmd_fp_pkt);
16189 
16190         /*
16191          * Then we uninitialize fc_packet.
16192          */
16193 
16194         /*
16195          * Thirdly, we uninitializae fcp_pkt.
16196          */
16197 
16198         /*
16199          * In the end, we free scsi_pkt.
16200          */
16201         scsi_hba_pkt_free(ap, pkt);
16202 }
16203 
16204 static int
16205 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16206 {
16207         fcp_port_t      *pptr = ADDR2FCP(ap);
16208         fcp_lun_t       *plun = ADDR2LUN(ap);
16209         fcp_tgt_t       *ptgt = plun->lun_tgt;
16210         fcp_pkt_t       *cmd  = PKT2CMD(pkt);
16211         fcp_cmd_t       *fcmd = &cmd->cmd_fcp_cmd;
16212         fc_packet_t     *fpkt = cmd->cmd_fp_pkt;
16213         int              rval;
16214 
16215         fpkt->pkt_pd = ptgt->tgt_pd_handle;
16216         (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16217 
16218         /*
16219          * Firstly, we need initialize fcp_pkt_t
16220          * Secondly, we need initialize fcp_cmd_t.
16221          */
16222         bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16223         fcmd->fcp_data_len = fpkt->pkt_datalen;
16224         fcmd->fcp_ent_addr = plun->lun_addr;
16225         if (pkt->pkt_flags & FLAG_HTAG) {
16226                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16227         } else if (pkt->pkt_flags & FLAG_OTAG) {
16228                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16229         } else if (pkt->pkt_flags & FLAG_STAG) {
16230                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16231         } else {
16232                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16233         }
16234 
16235         if (cmd->cmd_flags & CFLAG_IS_READ) {
16236                 fcmd->fcp_cntl.cntl_read_data = 1;
16237                 fcmd->fcp_cntl.cntl_write_data = 0;
16238         } else {
16239                 fcmd->fcp_cntl.cntl_read_data = 0;
16240                 fcmd->fcp_cntl.cntl_write_data = 1;
16241         }
16242 
16243         /*
16244          * Then we need initialize fc_packet_t too.
16245          */
16246         fpkt->pkt_timeout = pkt->pkt_time + 2;
16247         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16248         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16249         if (cmd->cmd_flags & CFLAG_IS_READ) {
16250                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16251         } else {
16252                 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16253         }
16254 
16255         if (pkt->pkt_flags & FLAG_NOINTR) {
16256                 fpkt->pkt_comp = NULL;
16257                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16258         } else {
16259                 fpkt->pkt_comp = fcp_cmd_callback;
16260                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16261                 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16262                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16263                 }
16264         }
16265 
16266         /*
16267          * Lastly, we need initialize scsi_pkt
16268          */
16269         pkt->pkt_reason = CMD_CMPLT;
16270         pkt->pkt_state = 0;
16271         pkt->pkt_statistics = 0;
16272         pkt->pkt_resid = 0;
16273 
16274         /*
16275          * if interrupts aren't allowed (e.g. at dump time) then we'll
16276          * have to do polled I/O
16277          */
16278         if (pkt->pkt_flags & FLAG_NOINTR) {
16279                 return (fcp_dopoll(pptr, cmd));
16280         }
16281 
16282         cmd->cmd_state = FCP_PKT_ISSUED;
16283         rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16284         if (rval == FC_SUCCESS) {
16285                 return (TRAN_ACCEPT);
16286         }
16287 
16288         /*
16289          * Need more consideration
16290          *
16291          * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16292          */
16293         cmd->cmd_state = FCP_PKT_IDLE;
16294         if (rval == FC_TRAN_BUSY) {
16295                 return (TRAN_BUSY);
16296         } else {
16297                 return (TRAN_FATAL_ERROR);
16298         }
16299 }
16300 
16301 /*
16302  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16303  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16304  */
16305 static void
16306 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16307 {
16308         FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16309             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16310 }
16311 
16312 /*
16313  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16314  */
16315 static void
16316 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16317 {
16318         FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16319             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16320 }