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  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  23  *
  24  * Fibre Channel SCSI ULP Mapping driver
  25  */
  26 
  27 #include <sys/scsi/scsi.h>
  28 #include <sys/types.h>
  29 #include <sys/varargs.h>
  30 #include <sys/devctl.h>
  31 #include <sys/thread.h>
  32 #include <sys/thread.h>
  33 #include <sys/open.h>
  34 #include <sys/file.h>
  35 #include <sys/sunndi.h>
  36 #include <sys/console.h>
  37 #include <sys/proc.h>
  38 #include <sys/time.h>
  39 #include <sys/utsname.h>
  40 #include <sys/scsi/impl/scsi_reset_notify.h>
  41 #include <sys/ndi_impldefs.h>
  42 #include <sys/byteorder.h>
  43 #include <sys/fs/dv_node.h>
  44 #include <sys/ctype.h>
  45 #include <sys/sunmdi.h>
  46 
  47 #include <sys/fibre-channel/fc.h>
  48 #include <sys/fibre-channel/impl/fc_ulpif.h>
  49 #include <sys/fibre-channel/ulp/fcpvar.h>
  50 
  51 /*
  52  * Discovery Process
  53  * =================
  54  *
  55  *    The discovery process is a major function of FCP.  In order to help
  56  * understand that function a flow diagram is given here.  This diagram
  57  * doesn't claim to cover all the cases and the events that can occur during
  58  * the discovery process nor the subtleties of the code.  The code paths shown
  59  * are simplified.  Its purpose is to help the reader (and potentially bug
  60  * fixer) have an overall view of the logic of the code.  For that reason the
  61  * diagram covers the simple case of the line coming up cleanly or of a new
  62  * port attaching to FCP the link being up.  The reader must keep in mind
  63  * that:
  64  *
  65  *      - There are special cases where bringing devices online and offline
  66  *        is driven by Ioctl.
  67  *
  68  *      - The behavior of the discovery process can be modified through the
  69  *        .conf file.
  70  *
  71  *      - The line can go down and come back up at any time during the
  72  *        discovery process which explains some of the complexity of the code.
  73  *
  74  * ............................................................................
  75  *
  76  * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP.
  77  *
  78  *
  79  *                      +-------------------------+
  80  *   fp/fctl module --->|    fcp_port_attach   |
  81  *                      +-------------------------+
  82  *         |                         |
  83  *         |                         |
  84  *         |                         v
  85  *         |            +-------------------------+
  86  *         |            | fcp_handle_port_attach  |
  87  *         |            +-------------------------+
  88  *         |                            |
  89  *         |                            |
  90  *         +--------------------+       |
  91  *                              |       |
  92  *                              v       v
  93  *                      +-------------------------+
  94  *                      |   fcp_statec_callback   |
  95  *                      +-------------------------+
  96  *                                  |
  97  *                                  |
  98  *                                  v
  99  *                      +-------------------------+
 100  *                      |    fcp_handle_devices   |
 101  *                      +-------------------------+
 102  *                                  |
 103  *                                  |
 104  *                                  v
 105  *                      +-------------------------+
 106  *                      |   fcp_handle_mapflags   |
 107  *                      +-------------------------+
 108  *                                  |
 109  *                                  |
 110  *                                  v
 111  *                      +-------------------------+
 112  *                      |     fcp_send_els        |
 113  *                      |                         |
 114  *                      | PLOGI or PRLI To all the|
 115  *                      | reachable devices.      |
 116  *                      +-------------------------+
 117  *
 118  *
 119  * ............................................................................
 120  *
 121  * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during
 122  *         STEP 1 are called (it is actually the same function).
 123  *
 124  *
 125  *                      +-------------------------+
 126  *                      |    fcp_icmd_callback    |
 127  *   fp/fctl module --->|                      |
 128  *                      | callback for PLOGI and  |
 129  *                      | PRLI.                   |
 130  *                      +-------------------------+
 131  *                                   |
 132  *                                   |
 133  *          Received PLOGI Accept   /-\   Received PRLI Accept
 134  *                     _ _ _ _ _ _ /   \_ _ _ _ _ _
 135  *                    |            \   /           |
 136  *                    |             \-/            |
 137  *                    |                            |
 138  *                    v                            v
 139  *      +-------------------------+     +-------------------------+
 140  *      |     fcp_send_els        |     |     fcp_send_scsi       |
 141  *      |                         |     |                         |
 142  *      |         PRLI            |     |       REPORT_LUN        |
 143  *      +-------------------------+     +-------------------------+
 144  *
 145  * ............................................................................
 146  *
 147  * STEP 3: The callback functions of the SCSI commands issued by FCP are called
 148  *         (It is actually the same function).
 149  *
 150  *
 151  *                          +-------------------------+
 152  *   fp/fctl module ------->|         fcp_scsi_callback    |
 153  *                          +-------------------------+
 154  *                                      |
 155  *                                      |
 156  *                                      |
 157  *      Receive REPORT_LUN reply       /-\      Receive INQUIRY PAGE83 reply
 158  *                _ _ _ _ _ _ _ _ _ _ /   \_ _ _ _ _ _ _ _ _ _ _ _
 159  *               |                    \   /                       |
 160  *               |                     \-/                        |
 161  *               |                      |                         |
 162  *               | Receive INQUIRY reply|                         |
 163  *               |                      |                         |
 164  *               v                      v                         v
 165  * +------------------------+ +----------------------+ +----------------------+
 166  * |  fcp_handle_reportlun  | |  fcp_handle_inquiry  | |  fcp_handle_page83   |
 167  * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) |
 168  * +------------------------+ +----------------------+ +----------------------+
 169  *               |                      |                         |
 170  *               |                      |                         |
 171  *               |                      |                         |
 172  *               v                      v                         |
 173  *     +-----------------+      +-----------------+               |
 174  *     |  fcp_send_scsi  |      |  fcp_send_scsi  |               |
 175  *     |                 |      |                 |               |
 176  *     |     INQUIRY     |      | INQUIRY PAGE83  |               |
 177  *     |  (To each LUN)  |      +-----------------+               |
 178  *     +-----------------+                                        |
 179  *                                                                |
 180  *                                                                v
 181  *                                                    +------------------------+
 182  *                                                    |  fcp_call_finish_init  |
 183  *                                                    +------------------------+
 184  *                                                                |
 185  *                                                                v
 186  *                                               +-----------------------------+
 187  *                                               |  fcp_call_finish_init_held  |
 188  *                                               +-----------------------------+
 189  *                                                                |
 190  *                                                                |
 191  *                         All LUNs scanned                      /-\
 192  *                             _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ /   \
 193  *                            |                                 \   /
 194  *                            |                                  \-/
 195  *                            v                                   |
 196  *                   +------------------+                         |
 197  *                   |  fcp_finish_tgt  |                         |
 198  *                   +------------------+                         |
 199  *                            |   Target Not Offline and          |
 200  *  Target Not Offline and    |   not marked and tgt_node_state   |
 201  *  marked                   /-\  not FCP_TGT_NODE_ON_DEMAND      |
 202  *              _ _ _ _ _ _ /   \_ _ _ _ _ _ _ _                  |
 203  *             |            \   /               |                 |
 204  *             |             \-/                |                 |
 205  *             v                                v                 |
 206  * +----------------------------+     +-------------------+       |
 207  * |     fcp_offline_target     |     |  fcp_create_luns  |       |
 208  * |                            |     +-------------------+       |
 209  * | A structure fcp_tgt_elem   |               |                 |
 210  * | is created and queued in   |               v                 |
 211  * | the FCP port list          |     +-------------------+       |
 212  * | port_offline_tgts.  It     |     |  fcp_pass_to_hp   |       |
 213  * | will be unqueued by the    |     |                   |       |
 214  * | watchdog timer.            |     | Called for each   |       |
 215  * +----------------------------+     | LUN. Dispatches   |       |
 216  *                |                   | fcp_hp_task       |       |
 217  *                |                   +-------------------+       |
 218  *                |                             |                 |
 219  *                |                             |                 |
 220  *                |                             |                 |
 221  *                |                             +---------------->|
 222  *                |                                               |
 223  *                +---------------------------------------------->|
 224  *                                                                |
 225  *                                                                |
 226  *              All the targets (devices) have been scanned      /-\
 227  *                              _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /   \
 228  *                             |                                \   /
 229  *                             |                                 \-/
 230  *          +-------------------------------------+               |
 231  *          |           fcp_finish_init           |               |
 232  *          |                                     |               |
 233  *          | Signal broadcasts the condition     |               |
 234  *          | variable port_config_cv of the FCP  |               |
 235  *          | port.  One potential code sequence  |               |
 236  *          | waiting on the condition variable   |               |
 237  *          | the code sequence handling          |               |
 238  *          | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER|               |
 239  *          | The other is in the function        |               |
 240  *          | fcp_reconfig_wait which is called   |               |
 241  *          | in the transmit path preventing IOs |               |
 242  *          | from going through till the disco-  |               |
 243  *          | very process is over.               |               |
 244  *          +-------------------------------------+               |
 245  *                             |                                  |
 246  *                             |                                  |
 247  *                             +--------------------------------->|
 248  *                                                                |
 249  *                                                                v
 250  *                                                              Return
 251  *
 252  * ............................................................................
 253  *
 254  * STEP 4: The hot plug task is called (for each fcp_hp_elem).
 255  *
 256  *
 257  *                      +-------------------------+
 258  *                      |      fcp_hp_task        |
 259  *                      +-------------------------+
 260  *                                   |
 261  *                                   |
 262  *                                   v
 263  *                      +-------------------------+
 264  *                      |     fcp_trigger_lun     |
 265  *                      +-------------------------+
 266  *                                   |
 267  *                                   |
 268  *                                   v
 269  *                 Bring offline    /-\  Bring online
 270  *                _ _ _ _ _ _ _ _ _/   \_ _ _ _ _ _ _ _ _ _
 271  *               |                 \   /                   |
 272  *               |                  \-/                    |
 273  *               v                                         v
 274  *    +---------------------+                   +-----------------------+
 275  *    |  fcp_offline_child  |                   |      fcp_get_cip      |
 276  *    +---------------------+                   |                       |
 277  *                                              | Creates a dev_info_t  |
 278  *                                              | or a mdi_pathinfo_t   |
 279  *                                              | depending on whether  |
 280  *                                              | mpxio is on or off.   |
 281  *                                              +-----------------------+
 282  *                                                         |
 283  *                                                         |
 284  *                                                         v
 285  *                                              +-----------------------+
 286  *                                              |  fcp_online_child     |
 287  *                                              |                       |
 288  *                                              | Set device online     |
 289  *                                              | using NDI or MDI.     |
 290  *                                              +-----------------------+
 291  *
 292  * ............................................................................
 293  *
 294  * STEP 5: The watchdog timer expires.  The watch dog timer does much more that
 295  *         what is described here.  We only show the target offline path.
 296  *
 297  *
 298  *                       +--------------------------+
 299  *                       |        fcp_watch         |
 300  *                       +--------------------------+
 301  *                                     |
 302  *                                     |
 303  *                                     v
 304  *                       +--------------------------+
 305  *                       |  fcp_scan_offline_tgts   |
 306  *                       +--------------------------+
 307  *                                     |
 308  *                                     |
 309  *                                     v
 310  *                       +--------------------------+
 311  *                       |  fcp_offline_target_now  |
 312  *                       +--------------------------+
 313  *                                     |
 314  *                                     |
 315  *                                     v
 316  *                       +--------------------------+
 317  *                       |   fcp_offline_tgt_luns   |
 318  *                       +--------------------------+
 319  *                                     |
 320  *                                     |
 321  *                                     v
 322  *                       +--------------------------+
 323  *                       |     fcp_offline_lun      |
 324  *                       +--------------------------+
 325  *                                     |
 326  *                                     |
 327  *                                     v
 328  *                   +----------------------------------+
 329  *                   |       fcp_offline_lun_now        |
 330  *                   |                                  |
 331  *                   | A request (or two if mpxio) is   |
 332  *                   | sent to the hot plug task using  |
 333  *                   | a fcp_hp_elem structure.         |
 334  *                   +----------------------------------+
 335  */
 336 
 337 /*
 338  * Functions registered with DDI framework
 339  */
 340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
 341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
 342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp);
 343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp);
 344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
 345     cred_t *credp, int *rval);
 346 
 347 /*
 348  * Functions registered with FC Transport framework
 349  */
 350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 351     fc_attach_cmd_t cmd,  uint32_t s_id);
 352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
 353     fc_detach_cmd_t cmd);
 354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev,
 355     int cmd, intptr_t data, int mode, cred_t *credp, int *rval,
 356     uint32_t claimed);
 357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle,
 358     fc_unsol_buf_t *buf, uint32_t claimed);
 359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle,
 360     fc_unsol_buf_t *buf, uint32_t claimed);
 361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
 362     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
 363     uint32_t  dev_cnt, uint32_t port_sid);
 364 
 365 /*
 366  * Functions registered with SCSA framework
 367  */
 368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 369     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 371     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 373     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
 376 static int fcp_scsi_reset(struct scsi_address *ap, int level);
 377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
 378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value,
 379     int whom);
 380 static void fcp_pkt_teardown(struct scsi_pkt *pkt);
 381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
 382     void (*callback)(caddr_t), caddr_t arg);
 383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip,
 384     char *name, ddi_eventcookie_t *event_cookiep);
 385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
 386     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
 387     ddi_callback_id_t *cb_id);
 388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi,
 389     ddi_callback_id_t cb_id);
 390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
 391     ddi_eventcookie_t eventid, void *impldata);
 392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
 393     ddi_bus_config_op_t op, void *arg, dev_info_t **childp);
 394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
 395     ddi_bus_config_op_t op, void *arg);
 396 
 397 /*
 398  * Internal functions
 399  */
 400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data,
 401     int mode, int *rval);
 402 
 403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
 404     int mode, int *rval);
 405 static int fcp_copyin_scsi_cmd(caddr_t base_addr,
 406     struct fcp_scsi_cmd *fscsi, int mode);
 407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi,
 408     caddr_t base_addr, int mode);
 409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi);
 410 
 411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr,
 412     la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state,
 413     int *fc_pkt_reason, int *fc_pkt_action);
 414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status,
 415     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
 416 static int fcp_tgt_send_prli(struct fcp_tgt     *ptgt, int *fc_status,
 417     int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action);
 418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd);
 419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd);
 420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt);
 421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd);
 422 
 423 static void fcp_handle_devices(struct fcp_port *pptr,
 424     fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt,
 425     fcp_map_tag_t *map_tag, int cause);
 426 static int fcp_handle_mapflags(struct fcp_port *pptr,
 427     struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt,
 428     int tgt_cnt, int cause);
 429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause);
 430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 431     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause);
 432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state,
 433     int cause);
 434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag,
 435     uint32_t state);
 436 static struct fcp_port *fcp_get_port(opaque_t port_handle);
 437 static void fcp_unsol_callback(fc_packet_t *fpkt);
 438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
 439     uchar_t r_ctl, uchar_t type);
 440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf);
 441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr,
 442     struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len,
 443     int nodma, int lcount, int tcount, int cause, uint32_t rscn_count);
 444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd);
 445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
 446     int nodma, int flags);
 447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd);
 448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr,
 449     uchar_t *wwn);
 450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr,
 451     uint32_t d_id);
 452 static void fcp_icmd_callback(fc_packet_t *fpkt);
 453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode,
 454     int len, int lcount, int tcount, int cause, uint32_t rscn_count);
 455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt);
 456 static void fcp_scsi_callback(fc_packet_t *fpkt);
 457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt);
 458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
 459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd);
 460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt,
 461     uint16_t lun_num);
 462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 463     int link_cnt, int tgt_cnt, int cause);
 464 static void fcp_finish_init(struct fcp_port *pptr);
 465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt,
 466     int tgt_cnt, int cause);
 467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip,
 468     int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags);
 469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 470     int link_cnt, int tgt_cnt, int nowait, int flags);
 471 static void fcp_offline_target_now(struct fcp_port *pptr,
 472     struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags);
 473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt,
 474     int tgt_cnt, int flags);
 475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
 476     int nowait, int flags);
 477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt,
 478     int tgt_cnt);
 479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt,
 480     int tgt_cnt, int flags);
 481 static void fcp_scan_offline_luns(struct fcp_port *pptr);
 482 static void fcp_scan_offline_tgts(struct fcp_port *pptr);
 483 static void fcp_update_offline_flags(struct fcp_lun *plun);
 484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun);
 485 static void fcp_abort_commands(struct fcp_pkt *head, struct
 486     fcp_port *pptr);
 487 static void fcp_cmd_callback(fc_packet_t *fpkt);
 488 static void fcp_complete_pkt(fc_packet_t *fpkt);
 489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp,
 490     struct fcp_port *pptr);
 491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
 492     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause);
 493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt);
 494 static void fcp_dealloc_lun(struct fcp_lun *plun);
 495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr,
 496     fc_portmap_t *map_entry, int link_cnt);
 497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt);
 498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt);
 499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt,
 500     int internal);
 501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...);
 502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 503     uint32_t s_id, int instance);
 504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag,
 505     int instance);
 506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance);
 507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *,
 508     int);
 509 static void fcp_kmem_cache_destructor(struct  scsi_pkt *, scsi_hba_tran_t *);
 510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t);
 511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt,
 512     int flags);
 513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt);
 514 static int fcp_reset_target(struct scsi_address *ap, int level);
 515 static int fcp_commoncap(struct scsi_address *ap, char *cap,
 516     int val, int tgtonly, int doset);
 517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len);
 518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len);
 519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap,
 520     int sleep);
 521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
 522     uint32_t s_id, fc_attach_cmd_t cmd, int instance);
 523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo);
 524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result);
 525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip,
 526     int lcount, int tcount);
 527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip);
 528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip);
 529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt,
 530     int tgt_cnt);
 531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun,
 532     dev_info_t *pdip, caddr_t name);
 533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip,
 534     int lcount, int tcount, int flags, int *circ);
 535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip,
 536     int lcount, int tcount, int flags, int *circ);
 537 static void fcp_remove_child(struct fcp_lun *plun);
 538 static void fcp_watch(void *arg);
 539 static void fcp_check_reset_delay(struct fcp_port *pptr);
 540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
 541     struct fcp_lun *rlun, int tgt_cnt);
 542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr);
 543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr,
 544     uchar_t *wwn, uint16_t lun);
 545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
 546     struct fcp_lun *plun);
 547 static void fcp_post_callback(struct fcp_pkt *cmd);
 548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd);
 549 static struct fcp_port *fcp_dip2port(dev_info_t *dip);
 550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr,
 551     child_info_t *cip);
 552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr,
 553     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
 554     int tgt_cnt, int flags);
 555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr,
 556     struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt,
 557     int tgt_cnt, int flags, int wait);
 558 static void fcp_retransport_cmd(struct fcp_port *pptr,
 559     struct fcp_pkt *cmd);
 560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason,
 561     uint_t statistics);
 562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd);
 563 static void fcp_update_targets(struct fcp_port *pptr,
 564     fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause);
 565 static int fcp_call_finish_init(struct fcp_port *pptr,
 566     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
 567 static int fcp_call_finish_init_held(struct fcp_port *pptr,
 568     struct fcp_tgt *ptgt, int lcount, int tcount, int cause);
 569 static void fcp_reconfigure_luns(void * tgt_handle);
 570 static void fcp_free_targets(struct fcp_port *pptr);
 571 static void fcp_free_target(struct fcp_tgt *ptgt);
 572 static int fcp_is_retryable(struct fcp_ipkt *icmd);
 573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn);
 574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int);
 575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string);
 576 static void fcp_print_error(fc_packet_t *fpkt);
 577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr,
 578     struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op);
 579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt);
 580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr,
 581     uint32_t *dev_cnt);
 582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause);
 583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval);
 584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *,
 585     struct fcp_ioctl *, struct fcp_port **);
 586 static char *fcp_get_lun_path(struct fcp_lun *plun);
 587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
 588     int *rval);
 589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id);
 590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id);
 591 static char *fcp_get_lun_path(struct fcp_lun *plun);
 592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode,
 593     int *rval);
 594 static void fcp_reconfig_wait(struct fcp_port *pptr);
 595 
 596 /*
 597  * New functions added for mpxio support
 598  */
 599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 600     scsi_hba_tran_t *hba_tran, struct scsi_device *sd);
 601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount,
 602     int tcount);
 603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun,
 604     dev_info_t *pdip);
 605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip);
 606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int);
 607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr);
 608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp);
 609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip,
 610     int what);
 611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
 612     fc_packet_t *fpkt);
 613 static int fcp_symmetric_device_probe(struct fcp_lun *plun);
 614 
 615 /*
 616  * New functions added for lun masking support
 617  */
 618 static void fcp_read_blacklist(dev_info_t *dip,
 619     struct fcp_black_list_entry **pplun_blacklist);
 620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
 621     struct fcp_black_list_entry **pplun_blacklist);
 622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
 623     struct fcp_black_list_entry **pplun_blacklist);
 624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id);
 625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist);
 626 
 627 /*
 628  * New functions to support software FCA (like fcoei)
 629  */
 630 static struct scsi_pkt *fcp_pseudo_init_pkt(
 631         struct scsi_address *ap, struct scsi_pkt *pkt,
 632         struct buf *bp, int cmdlen, int statuslen,
 633         int tgtlen, int flags, int (*callback)(), caddr_t arg);
 634 static void fcp_pseudo_destroy_pkt(
 635         struct scsi_address *ap, struct scsi_pkt *pkt);
 636 static void fcp_pseudo_sync_pkt(
 637         struct scsi_address *ap, struct scsi_pkt *pkt);
 638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt);
 639 static void fcp_pseudo_dmafree(
 640         struct scsi_address *ap, struct scsi_pkt *pkt);
 641 
 642 extern struct mod_ops   mod_driverops;
 643 /*
 644  * This variable is defined in modctl.c and set to '1' after the root driver
 645  * and fs are loaded.  It serves as an indication that the root filesystem can
 646  * be used.
 647  */
 648 extern int              modrootloaded;
 649 /*
 650  * This table contains strings associated with the SCSI sense key codes.  It
 651  * is used by FCP to print a clear explanation of the code returned in the
 652  * sense information by a device.
 653  */
 654 extern char             *sense_keys[];
 655 /*
 656  * This device is created by the SCSI pseudo nexus driver (SCSI vHCI).  It is
 657  * under this device that the paths to a physical device are created when
 658  * MPxIO is used.
 659  */
 660 extern dev_info_t       *scsi_vhci_dip;
 661 
 662 /*
 663  * Report lun processing
 664  */
 665 #define FCP_LUN_ADDRESSING              0x80
 666 #define FCP_PD_ADDRESSING               0x00
 667 #define FCP_VOLUME_ADDRESSING           0x40
 668 
 669 #define FCP_SVE_THROTTLE                0x28 /* Vicom */
 670 #define MAX_INT_DMA                     0x7fffffff
 671 /*
 672  * Property definitions
 673  */
 674 #define NODE_WWN_PROP   (char *)fcp_node_wwn_prop
 675 #define PORT_WWN_PROP   (char *)fcp_port_wwn_prop
 676 #define TARGET_PROP     (char *)fcp_target_prop
 677 #define LUN_PROP        (char *)fcp_lun_prop
 678 #define SAM_LUN_PROP    (char *)fcp_sam_lun_prop
 679 #define CONF_WWN_PROP   (char *)fcp_conf_wwn_prop
 680 #define OBP_BOOT_WWN    (char *)fcp_obp_boot_wwn
 681 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only
 682 #define INIT_PORT_PROP  (char *)fcp_init_port_prop
 683 #define TGT_PORT_PROP   (char *)fcp_tgt_port_prop
 684 #define LUN_BLACKLIST_PROP      (char *)fcp_lun_blacklist_prop
 685 /*
 686  * Short hand macros.
 687  */
 688 #define LUN_PORT        (plun->lun_tgt->tgt_port)
 689 #define LUN_TGT         (plun->lun_tgt)
 690 
 691 /*
 692  * Driver private macros
 693  */
 694 #define FCP_ATOB(x)     (((x) >= '0' && (x) <= '9') ? ((x) - '0') :       \
 695                         ((x) >= 'a' && (x) <= 'f') ?                      \
 696                         ((x) - 'a' + 10) : ((x) - 'A' + 10))
 697 
 698 #define FCP_MAX(a, b)   ((a) > (b) ? (a) : (b))
 699 
 700 #define FCP_N_NDI_EVENTS                                                \
 701         (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t))
 702 
 703 #define FCP_LINK_STATE_CHANGED(p, c)                    \
 704         ((p)->port_link_cnt != (c)->ipkt_link_cnt)
 705 
 706 #define FCP_TGT_STATE_CHANGED(t, c)                     \
 707         ((t)->tgt_change_cnt != (c)->ipkt_change_cnt)
 708 
 709 #define FCP_STATE_CHANGED(p, t, c)              \
 710         (FCP_TGT_STATE_CHANGED(t, c))
 711 
 712 #define FCP_MUST_RETRY(fpkt)                            \
 713         ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||    \
 714         (fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||     \
 715         (fpkt)->pkt_state == FC_PKT_TRAN_BSY ||      \
 716         (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||       \
 717         (fpkt)->pkt_state == FC_PKT_NPORT_BSY ||     \
 718         (fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||    \
 719         (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||  \
 720         (fpkt)->pkt_reason == FC_REASON_OFFLINE)
 721 
 722 #define FCP_SENSE_REPORTLUN_CHANGED(es)         \
 723         ((es)->es_key == KEY_UNIT_ATTENTION &&       \
 724         (es)->es_add_code == 0x3f &&         \
 725         (es)->es_qual_code == 0x0e)
 726 
 727 #define FCP_SENSE_NO_LUN(es)                    \
 728         ((es)->es_key == KEY_ILLEGAL_REQUEST &&      \
 729         (es)->es_add_code == 0x25 &&         \
 730         (es)->es_qual_code == 0x0)
 731 
 732 #define FCP_VERSION             "20091208-1.192"
 733 #define FCP_NAME_VERSION        "SunFC FCP v" FCP_VERSION
 734 
 735 #define FCP_NUM_ELEMENTS(array)                 \
 736         (sizeof (array) / sizeof ((array)[0]))
 737 
 738 /*
 739  * Debugging, Error reporting, and tracing
 740  */
 741 #define FCP_LOG_SIZE            1024 * 1024
 742 
 743 #define FCP_LEVEL_1             0x00001         /* attach/detach PM CPR */
 744 #define FCP_LEVEL_2             0x00002         /* failures/Invalid data */
 745 #define FCP_LEVEL_3             0x00004         /* state change, discovery */
 746 #define FCP_LEVEL_4             0x00008         /* ULP messages */
 747 #define FCP_LEVEL_5             0x00010         /* ELS/SCSI cmds */
 748 #define FCP_LEVEL_6             0x00020         /* Transport failures */
 749 #define FCP_LEVEL_7             0x00040
 750 #define FCP_LEVEL_8             0x00080         /* I/O tracing */
 751 #define FCP_LEVEL_9             0x00100         /* I/O tracing */
 752 
 753 
 754 
 755 /*
 756  * Log contents to system messages file
 757  */
 758 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG)
 759 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG)
 760 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG)
 761 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG)
 762 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG)
 763 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG)
 764 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG)
 765 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG)
 766 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG)
 767 
 768 
 769 /*
 770  * Log contents to trace buffer
 771  */
 772 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF)
 773 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF)
 774 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF)
 775 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF)
 776 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF)
 777 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF)
 778 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF)
 779 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF)
 780 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF)
 781 
 782 
 783 /*
 784  * Log contents to both system messages file and trace buffer
 785  */
 786 #define FCP_MSG_BUF_LEVEL_1     (FCP_LEVEL_1 | FC_TRACE_LOG_BUF |       \
 787                                 FC_TRACE_LOG_MSG)
 788 #define FCP_MSG_BUF_LEVEL_2     (FCP_LEVEL_2 | FC_TRACE_LOG_BUF |       \
 789                                 FC_TRACE_LOG_MSG)
 790 #define FCP_MSG_BUF_LEVEL_3     (FCP_LEVEL_3 | FC_TRACE_LOG_BUF |       \
 791                                 FC_TRACE_LOG_MSG)
 792 #define FCP_MSG_BUF_LEVEL_4     (FCP_LEVEL_4 | FC_TRACE_LOG_BUF |       \
 793                                 FC_TRACE_LOG_MSG)
 794 #define FCP_MSG_BUF_LEVEL_5     (FCP_LEVEL_5 | FC_TRACE_LOG_BUF |       \
 795                                 FC_TRACE_LOG_MSG)
 796 #define FCP_MSG_BUF_LEVEL_6     (FCP_LEVEL_6 | FC_TRACE_LOG_BUF |       \
 797                                 FC_TRACE_LOG_MSG)
 798 #define FCP_MSG_BUF_LEVEL_7     (FCP_LEVEL_7 | FC_TRACE_LOG_BUF |       \
 799                                 FC_TRACE_LOG_MSG)
 800 #define FCP_MSG_BUF_LEVEL_8     (FCP_LEVEL_8 | FC_TRACE_LOG_BUF |       \
 801                                 FC_TRACE_LOG_MSG)
 802 #define FCP_MSG_BUF_LEVEL_9     (FCP_LEVEL_9 | FC_TRACE_LOG_BUF |       \
 803                                 FC_TRACE_LOG_MSG)
 804 #ifdef DEBUG
 805 #define FCP_DTRACE      fc_trace_debug
 806 #else
 807 #define FCP_DTRACE
 808 #endif
 809 
 810 #define FCP_TRACE       fc_trace_debug
 811 
 812 static struct cb_ops fcp_cb_ops = {
 813         fcp_open,                       /* open */
 814         fcp_close,                      /* close */
 815         nodev,                          /* strategy */
 816         nodev,                          /* print */
 817         nodev,                          /* dump */
 818         nodev,                          /* read */
 819         nodev,                          /* write */
 820         fcp_ioctl,                      /* ioctl */
 821         nodev,                          /* devmap */
 822         nodev,                          /* mmap */
 823         nodev,                          /* segmap */
 824         nochpoll,                       /* chpoll */
 825         ddi_prop_op,                    /* cb_prop_op */
 826         0,                              /* streamtab */
 827         D_NEW | D_MP | D_HOTPLUG,       /* cb_flag */
 828         CB_REV,                         /* rev */
 829         nodev,                          /* aread */
 830         nodev                           /* awrite */
 831 };
 832 
 833 
 834 static struct dev_ops fcp_ops = {
 835         DEVO_REV,
 836         0,
 837         ddi_getinfo_1to1,
 838         nulldev,                /* identify */
 839         nulldev,                /* probe */
 840         fcp_attach,             /* attach and detach are mandatory */
 841         fcp_detach,
 842         nodev,                  /* reset */
 843         &fcp_cb_ops,                /* cb_ops */
 844         NULL,                   /* bus_ops */
 845         NULL,                   /* power */
 846 };
 847 
 848 
 849 char *fcp_version = FCP_NAME_VERSION;
 850 
 851 static struct modldrv modldrv = {
 852         &mod_driverops,
 853         FCP_NAME_VERSION,
 854         &fcp_ops
 855 };
 856 
 857 
 858 static struct modlinkage modlinkage = {
 859         MODREV_1,
 860         { &modldrv, NULL }
 861 };
 862 
 863 
 864 static fc_ulp_modinfo_t fcp_modinfo = {
 865         &fcp_modinfo,                       /* ulp_handle */
 866         FCTL_ULP_MODREV_4,              /* ulp_rev */
 867         FC4_SCSI_FCP,                   /* ulp_type */
 868         "fcp",                          /* ulp_name */
 869         FCP_STATEC_MASK,                /* ulp_statec_mask */
 870         fcp_port_attach,                /* ulp_port_attach */
 871         fcp_port_detach,                /* ulp_port_detach */
 872         fcp_port_ioctl,                 /* ulp_port_ioctl */
 873         fcp_els_callback,               /* ulp_els_callback */
 874         fcp_data_callback,              /* ulp_data_callback */
 875         fcp_statec_callback             /* ulp_statec_callback */
 876 };
 877 
 878 #ifdef  DEBUG
 879 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 880                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 881                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 882                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 883 #else
 884 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 885                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 886                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 887                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 888 #endif
 889 
 890 /* FCP global variables */
 891 int                     fcp_bus_config_debug = 0;
 892 static int              fcp_log_size = FCP_LOG_SIZE;
 893 static int              fcp_trace = FCP_TRACE_DEFAULT;
 894 static fc_trace_logq_t  *fcp_logq = NULL;
 895 static struct fcp_black_list_entry      *fcp_lun_blacklist = NULL;
 896 /*
 897  * The auto-configuration is set by default.  The only way of disabling it is
 898  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
 899  */
 900 static int              fcp_enable_auto_configuration = 1;
 901 static int              fcp_max_bus_config_retries      = 4;
 902 static int              fcp_lun_ready_retry = 300;
 903 /*
 904  * The value assigned to the following variable has changed several times due
 905  * to a problem with the data underruns reporting of some firmware(s).  The
 906  * current value of 50 gives a timeout value of 25 seconds for a max number
 907  * of 256 LUNs.
 908  */
 909 static int              fcp_max_target_retries = 50;
 910 /*
 911  * Watchdog variables
 912  * ------------------
 913  *
 914  * fcp_watchdog_init
 915  *
 916  *      Indicates if the watchdog timer is running or not.  This is actually
 917  *      a counter of the number of Fibre Channel ports that attached.  When
 918  *      the first port attaches the watchdog is started.  When the last port
 919  *      detaches the watchdog timer is stopped.
 920  *
 921  * fcp_watchdog_time
 922  *
 923  *      This is the watchdog clock counter.  It is incremented by
 924  *      fcp_watchdog_time each time the watchdog timer expires.
 925  *
 926  * fcp_watchdog_timeout
 927  *
 928  *      Increment value of the variable fcp_watchdog_time as well as the
 929  *      the timeout value of the watchdog timer.  The unit is 1 second.  It
 930  *      is strange that this is not a #define   but a variable since the code
 931  *      never changes this value.  The reason why it can be said that the
 932  *      unit is 1 second is because the number of ticks for the watchdog
 933  *      timer is determined like this:
 934  *
 935  *          fcp_watchdog_tick = fcp_watchdog_timeout *
 936  *                                drv_usectohz(1000000);
 937  *
 938  *      The value 1000000 is hard coded in the code.
 939  *
 940  * fcp_watchdog_tick
 941  *
 942  *      Watchdog timer value in ticks.
 943  */
 944 static int              fcp_watchdog_init = 0;
 945 static int              fcp_watchdog_time = 0;
 946 static int              fcp_watchdog_timeout = 1;
 947 static int              fcp_watchdog_tick;
 948 
 949 /*
 950  * fcp_offline_delay is a global variable to enable customisation of
 951  * the timeout on link offlines or RSCNs. The default value is set
 952  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
 953  * specified in FCP4 Chapter 11 (see www.t10.org).
 954  *
 955  * The variable fcp_offline_delay is specified in SECONDS.
 956  *
 957  * If we made this a static var then the user would not be able to
 958  * change it. This variable is set in fcp_attach().
 959  */
 960 unsigned int            fcp_offline_delay = FCP_OFFLINE_DELAY;
 961 
 962 static void             *fcp_softstate = NULL; /* for soft state */
 963 static uchar_t          fcp_oflag = FCP_IDLE; /* open flag */
 964 static kmutex_t         fcp_global_mutex;
 965 static kmutex_t         fcp_ioctl_mutex;
 966 static dev_info_t       *fcp_global_dip = NULL;
 967 static timeout_id_t     fcp_watchdog_id;
 968 const char              *fcp_lun_prop = "lun";
 969 const char              *fcp_sam_lun_prop = "sam-lun";
 970 const char              *fcp_target_prop = "target";
 971 /*
 972  * NOTE: consumers of "node-wwn" property include stmsboot in ON
 973  * consolidation.
 974  */
 975 const char              *fcp_node_wwn_prop = "node-wwn";
 976 const char              *fcp_port_wwn_prop = "port-wwn";
 977 const char              *fcp_conf_wwn_prop = "fc-port-wwn";
 978 const char              *fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
 979 const char              *fcp_manual_config_only = "manual_configuration_only";
 980 const char              *fcp_init_port_prop = "initiator-port";
 981 const char              *fcp_tgt_port_prop = "target-port";
 982 const char              *fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
 983 
 984 static struct fcp_port  *fcp_port_head = NULL;
 985 static ddi_eventcookie_t        fcp_insert_eid;
 986 static ddi_eventcookie_t        fcp_remove_eid;
 987 
 988 static ndi_event_definition_t   fcp_ndi_event_defs[] = {
 989         { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
 990         { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
 991 };
 992 
 993 /*
 994  * List of valid commands for the scsi_ioctl call
 995  */
 996 static uint8_t scsi_ioctl_list[] = {
 997         SCMD_INQUIRY,
 998         SCMD_REPORT_LUN,
 999         SCMD_READ_CAPACITY
1000 };
1001 
1002 /*
1003  * this is used to dummy up a report lun response for cases
1004  * where the target doesn't support it
1005  */
1006 static uchar_t fcp_dummy_lun[] = {
1007         0x00,           /* MSB length (length = no of luns * 8) */
1008         0x00,
1009         0x00,
1010         0x08,           /* LSB length */
1011         0x00,           /* MSB reserved */
1012         0x00,
1013         0x00,
1014         0x00,           /* LSB reserved */
1015         FCP_PD_ADDRESSING,
1016         0x00,           /* LUN is ZERO at the first level */
1017         0x00,
1018         0x00,           /* second level is zero */
1019         0x00,
1020         0x00,           /* third level is zero */
1021         0x00,
1022         0x00            /* fourth level is zero */
1023 };
1024 
1025 static uchar_t fcp_alpa_to_switch[] = {
1026         0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1027         0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1028         0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1029         0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1030         0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1031         0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1032         0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1033         0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1034         0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1035         0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1036         0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1037         0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1038         0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1039         0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1040         0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1041         0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1042         0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1043         0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1044         0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1045         0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1046         0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1047         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1048         0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1049         0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1050 };
1051 
1052 static caddr_t pid = "SESS01          ";
1053 
1054 #if     !defined(lint)
1055 
1056 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1057     fcp_port::fcp_next fcp_watchdog_id))
1058 
1059 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1060 
1061 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1062     fcp_insert_eid
1063     fcp_remove_eid
1064     fcp_watchdog_time))
1065 
1066 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1067     fcp_cb_ops
1068     fcp_ops
1069     callb_cpr))
1070 
1071 #endif /* lint */
1072 
1073 /*
1074  * This table is used to determine whether or not it's safe to copy in
1075  * the target node name for a lun.  Since all luns behind the same target
1076  * have the same wwnn, only tagets that do not support multiple luns are
1077  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1078  */
1079 
1080 char *fcp_symmetric_disk_table[] = {
1081         "SEAGATE ST",
1082         "IBM     DDYFT",
1083         "SUNW    SUNWGS",       /* Daktari enclosure */
1084         "SUN     SENA",         /* SES device */
1085         "SUN     SESS01"        /* VICOM SVE box */
1086 };
1087 
1088 int fcp_symmetric_disk_table_size =
1089         sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1090 
1091 /*
1092  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1093  * will panic if you don't pass this in to the routine, this information.
1094  * Need to determine what the actual impact to the system is by providing
1095  * this information if any. Since dma allocation is done in pkt_init it may
1096  * not have any impact. These values are straight from the Writing Device
1097  * Driver manual.
1098  */
1099 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1100         DMA_ATTR_V0,    /* ddi_dma_attr version */
1101         0,              /* low address */
1102         0xffffffff,     /* high address */
1103         0x00ffffff,     /* counter upper bound */
1104         1,              /* alignment requirements */
1105         0x3f,           /* burst sizes */
1106         1,              /* minimum DMA access */
1107         0xffffffff,     /* maximum DMA access */
1108         (1 << 24) - 1,    /* segment boundary restrictions */
1109         1,              /* scater/gather list length */
1110         512,            /* device granularity */
1111         0               /* DMA flags */
1112 };
1113 
1114 /*
1115  * The _init(9e) return value should be that of mod_install(9f). Under
1116  * some circumstances, a failure may not be related mod_install(9f) and
1117  * one would then require a return value to indicate the failure. Looking
1118  * at mod_install(9f), it is expected to return 0 for success and non-zero
1119  * for failure. mod_install(9f) for device drivers, further goes down the
1120  * calling chain and ends up in ddi_installdrv(), whose return values are
1121  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1122  * calling chain of mod_install(9f) which return values like EINVAL and
1123  * in some even return -1.
1124  *
1125  * To work around the vagaries of the mod_install() calling chain, return
1126  * either 0 or ENODEV depending on the success or failure of mod_install()
1127  */
1128 int
1129 _init(void)
1130 {
1131         int rval;
1132 
1133         /*
1134          * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1135          * before registering with the transport first.
1136          */
1137         if (ddi_soft_state_init(&fcp_softstate,
1138             sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1139                 return (EINVAL);
1140         }
1141 
1142         mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1143         mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1144 
1145         if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1146                 cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1147                 mutex_destroy(&fcp_global_mutex);
1148                 mutex_destroy(&fcp_ioctl_mutex);
1149                 ddi_soft_state_fini(&fcp_softstate);
1150                 return (ENODEV);
1151         }
1152 
1153         fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1154 
1155         if ((rval = mod_install(&modlinkage)) != 0) {
1156                 fc_trace_free_logq(fcp_logq);
1157                 (void) fc_ulp_remove(&fcp_modinfo);
1158                 mutex_destroy(&fcp_global_mutex);
1159                 mutex_destroy(&fcp_ioctl_mutex);
1160                 ddi_soft_state_fini(&fcp_softstate);
1161                 rval = ENODEV;
1162         }
1163 
1164         return (rval);
1165 }
1166 
1167 
1168 /*
1169  * the system is done with us as a driver, so clean up
1170  */
1171 int
1172 _fini(void)
1173 {
1174         int rval;
1175 
1176         /*
1177          * don't start cleaning up until we know that the module remove
1178          * has worked  -- if this works, then we know that each instance
1179          * has successfully been DDI_DETACHed
1180          */
1181         if ((rval = mod_remove(&modlinkage)) != 0) {
1182                 return (rval);
1183         }
1184 
1185         (void) fc_ulp_remove(&fcp_modinfo);
1186 
1187         ddi_soft_state_fini(&fcp_softstate);
1188         mutex_destroy(&fcp_global_mutex);
1189         mutex_destroy(&fcp_ioctl_mutex);
1190         fc_trace_free_logq(fcp_logq);
1191 
1192         return (rval);
1193 }
1194 
1195 
1196 int
1197 _info(struct modinfo *modinfop)
1198 {
1199         return (mod_info(&modlinkage, modinfop));
1200 }
1201 
1202 
1203 /*
1204  * attach the module
1205  */
1206 static int
1207 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1208 {
1209         int rval = DDI_SUCCESS;
1210 
1211         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1212             FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1213 
1214         if (cmd == DDI_ATTACH) {
1215                 /* The FCP pseudo device is created here. */
1216                 mutex_enter(&fcp_global_mutex);
1217                 fcp_global_dip = devi;
1218                 mutex_exit(&fcp_global_mutex);
1219 
1220                 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1221                     0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1222                         ddi_report_dev(fcp_global_dip);
1223                 } else {
1224                         cmn_err(CE_WARN, "FCP: Cannot create minor node");
1225                         mutex_enter(&fcp_global_mutex);
1226                         fcp_global_dip = NULL;
1227                         mutex_exit(&fcp_global_mutex);
1228 
1229                         rval = DDI_FAILURE;
1230                 }
1231                 /*
1232                  * We check the fcp_offline_delay property at this
1233                  * point. This variable is global for the driver,
1234                  * not specific to an instance.
1235                  *
1236                  * We do not recommend setting the value to less
1237                  * than 10 seconds (RA_TOV_els), or greater than
1238                  * 60 seconds.
1239                  */
1240                 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1241                     devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1242                     "fcp_offline_delay", FCP_OFFLINE_DELAY);
1243                 if ((fcp_offline_delay < 10) ||
1244                     (fcp_offline_delay > 60)) {
1245                         cmn_err(CE_WARN, "Setting fcp_offline_delay "
1246                             "to %d second(s). This is outside the "
1247                             "recommended range of 10..60 seconds.",
1248                             fcp_offline_delay);
1249                 }
1250         }
1251 
1252         return (rval);
1253 }
1254 
1255 
1256 /*ARGSUSED*/
1257 static int
1258 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1259 {
1260         int     res = DDI_SUCCESS;
1261 
1262         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1263             FCP_BUF_LEVEL_8, 0,  "module detach: cmd=0x%x", cmd);
1264 
1265         if (cmd == DDI_DETACH) {
1266                 /*
1267                  * Check if there are active ports/threads. If there
1268                  * are any, we will fail, else we will succeed (there
1269                  * should not be much to clean up)
1270                  */
1271                 mutex_enter(&fcp_global_mutex);
1272                 FCP_DTRACE(fcp_logq, "fcp",
1273                     fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1274                     (void *) fcp_port_head);
1275 
1276                 if (fcp_port_head == NULL) {
1277                         ddi_remove_minor_node(fcp_global_dip, NULL);
1278                         fcp_global_dip = NULL;
1279                         mutex_exit(&fcp_global_mutex);
1280                 } else {
1281                         mutex_exit(&fcp_global_mutex);
1282                         res = DDI_FAILURE;
1283                 }
1284         }
1285         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1286             FCP_BUF_LEVEL_8, 0,  "module detach returning %d", res);
1287 
1288         return (res);
1289 }
1290 
1291 
1292 /* ARGSUSED */
1293 static int
1294 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1295 {
1296         if (otype != OTYP_CHR) {
1297                 return (EINVAL);
1298         }
1299 
1300         /*
1301          * Allow only root to talk;
1302          */
1303         if (drv_priv(credp)) {
1304                 return (EPERM);
1305         }
1306 
1307         mutex_enter(&fcp_global_mutex);
1308         if (fcp_oflag & FCP_EXCL) {
1309                 mutex_exit(&fcp_global_mutex);
1310                 return (EBUSY);
1311         }
1312 
1313         if (flag & FEXCL) {
1314                 if (fcp_oflag & FCP_OPEN) {
1315                         mutex_exit(&fcp_global_mutex);
1316                         return (EBUSY);
1317                 }
1318                 fcp_oflag |= FCP_EXCL;
1319         }
1320         fcp_oflag |= FCP_OPEN;
1321         mutex_exit(&fcp_global_mutex);
1322 
1323         return (0);
1324 }
1325 
1326 
1327 /* ARGSUSED */
1328 static int
1329 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1330 {
1331         if (otype != OTYP_CHR) {
1332                 return (EINVAL);
1333         }
1334 
1335         mutex_enter(&fcp_global_mutex);
1336         if (!(fcp_oflag & FCP_OPEN)) {
1337                 mutex_exit(&fcp_global_mutex);
1338                 return (ENODEV);
1339         }
1340         fcp_oflag = FCP_IDLE;
1341         mutex_exit(&fcp_global_mutex);
1342 
1343         return (0);
1344 }
1345 
1346 
1347 /*
1348  * fcp_ioctl
1349  *      Entry point for the FCP ioctls
1350  *
1351  * Input:
1352  *      See ioctl(9E)
1353  *
1354  * Output:
1355  *      See ioctl(9E)
1356  *
1357  * Returns:
1358  *      See ioctl(9E)
1359  *
1360  * Context:
1361  *      Kernel context.
1362  */
1363 /* ARGSUSED */
1364 static int
1365 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1366     int *rval)
1367 {
1368         int                     ret = 0;
1369 
1370         mutex_enter(&fcp_global_mutex);
1371         if (!(fcp_oflag & FCP_OPEN)) {
1372                 mutex_exit(&fcp_global_mutex);
1373                 return (ENXIO);
1374         }
1375         mutex_exit(&fcp_global_mutex);
1376 
1377         switch (cmd) {
1378         case FCP_TGT_INQUIRY:
1379         case FCP_TGT_CREATE:
1380         case FCP_TGT_DELETE:
1381                 ret = fcp_setup_device_data_ioctl(cmd,
1382                     (struct fcp_ioctl *)data, mode, rval);
1383                 break;
1384 
1385         case FCP_TGT_SEND_SCSI:
1386                 mutex_enter(&fcp_ioctl_mutex);
1387                 ret = fcp_setup_scsi_ioctl(
1388                     (struct fcp_scsi_cmd *)data, mode, rval);
1389                 mutex_exit(&fcp_ioctl_mutex);
1390                 break;
1391 
1392         case FCP_STATE_COUNT:
1393                 ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1394                     mode, rval);
1395                 break;
1396         case FCP_GET_TARGET_MAPPINGS:
1397                 ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1398                     mode, rval);
1399                 break;
1400         default:
1401                 fcp_log(CE_WARN, NULL,
1402                     "!Invalid ioctl opcode = 0x%x", cmd);
1403                 ret     = EINVAL;
1404         }
1405 
1406         return (ret);
1407 }
1408 
1409 
1410 /*
1411  * fcp_setup_device_data_ioctl
1412  *      Setup handler for the "device data" style of
1413  *      ioctl for FCP.  See "fcp_util.h" for data structure
1414  *      definition.
1415  *
1416  * Input:
1417  *      cmd     = FCP ioctl command
1418  *      data    = ioctl data
1419  *      mode    = See ioctl(9E)
1420  *
1421  * Output:
1422  *      data    = ioctl data
1423  *      rval    = return value - see ioctl(9E)
1424  *
1425  * Returns:
1426  *      See ioctl(9E)
1427  *
1428  * Context:
1429  *      Kernel context.
1430  */
1431 /* ARGSUSED */
1432 static int
1433 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1434     int *rval)
1435 {
1436         struct fcp_port *pptr;
1437         struct  device_data     *dev_data;
1438         uint32_t                link_cnt;
1439         la_wwn_t                *wwn_ptr = NULL;
1440         struct fcp_tgt          *ptgt = NULL;
1441         struct fcp_lun          *plun = NULL;
1442         int                     i, error;
1443         struct fcp_ioctl        fioctl;
1444 
1445 #ifdef  _MULTI_DATAMODEL
1446         switch (ddi_model_convert_from(mode & FMODELS)) {
1447         case DDI_MODEL_ILP32: {
1448                 struct fcp32_ioctl f32_ioctl;
1449 
1450                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1451                     sizeof (struct fcp32_ioctl), mode)) {
1452                         return (EFAULT);
1453                 }
1454                 fioctl.fp_minor = f32_ioctl.fp_minor;
1455                 fioctl.listlen = f32_ioctl.listlen;
1456                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1457                 break;
1458         }
1459         case DDI_MODEL_NONE:
1460                 if (ddi_copyin((void *)data, (void *)&fioctl,
1461                     sizeof (struct fcp_ioctl), mode)) {
1462                         return (EFAULT);
1463                 }
1464                 break;
1465         }
1466 
1467 #else   /* _MULTI_DATAMODEL */
1468         if (ddi_copyin((void *)data, (void *)&fioctl,
1469             sizeof (struct fcp_ioctl), mode)) {
1470                 return (EFAULT);
1471         }
1472 #endif  /* _MULTI_DATAMODEL */
1473 
1474         /*
1475          * Right now we can assume that the minor number matches with
1476          * this instance of fp. If this changes we will need to
1477          * revisit this logic.
1478          */
1479         mutex_enter(&fcp_global_mutex);
1480         pptr = fcp_port_head;
1481         while (pptr) {
1482                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1483                         break;
1484                 } else {
1485                         pptr = pptr->port_next;
1486                 }
1487         }
1488         mutex_exit(&fcp_global_mutex);
1489         if (pptr == NULL) {
1490                 return (ENXIO);
1491         }
1492         mutex_enter(&pptr->port_mutex);
1493 
1494 
1495         if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1496             fioctl.listlen, KM_NOSLEEP)) == NULL) {
1497                 mutex_exit(&pptr->port_mutex);
1498                 return (ENOMEM);
1499         }
1500 
1501         if (ddi_copyin(fioctl.list, dev_data,
1502             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1503                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1504                 mutex_exit(&pptr->port_mutex);
1505                 return (EFAULT);
1506         }
1507         link_cnt = pptr->port_link_cnt;
1508 
1509         if (cmd == FCP_TGT_INQUIRY) {
1510                 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1511                 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1512                     sizeof (wwn_ptr->raw_wwn)) == 0) {
1513                         /* This ioctl is requesting INQ info of local HBA */
1514                         mutex_exit(&pptr->port_mutex);
1515                         dev_data[0].dev0_type = DTYPE_UNKNOWN;
1516                         dev_data[0].dev_status = 0;
1517                         if (ddi_copyout(dev_data, fioctl.list,
1518                             (sizeof (struct device_data)) * fioctl.listlen,
1519                             mode)) {
1520                                 kmem_free(dev_data,
1521                                     sizeof (*dev_data) * fioctl.listlen);
1522                                 return (EFAULT);
1523                         }
1524                         kmem_free(dev_data,
1525                             sizeof (*dev_data) * fioctl.listlen);
1526 #ifdef  _MULTI_DATAMODEL
1527                         switch (ddi_model_convert_from(mode & FMODELS)) {
1528                         case DDI_MODEL_ILP32: {
1529                                 struct fcp32_ioctl f32_ioctl;
1530                                 f32_ioctl.fp_minor = fioctl.fp_minor;
1531                                 f32_ioctl.listlen = fioctl.listlen;
1532                                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1533                                 if (ddi_copyout((void *)&f32_ioctl,
1534                                     (void *)data,
1535                                     sizeof (struct fcp32_ioctl), mode)) {
1536                                         return (EFAULT);
1537                                 }
1538                                 break;
1539                         }
1540                         case DDI_MODEL_NONE:
1541                                 if (ddi_copyout((void *)&fioctl, (void *)data,
1542                                     sizeof (struct fcp_ioctl), mode)) {
1543                                         return (EFAULT);
1544                                 }
1545                                 break;
1546                         }
1547 #else   /* _MULTI_DATAMODEL */
1548                         if (ddi_copyout((void *)&fioctl, (void *)data,
1549                             sizeof (struct fcp_ioctl), mode)) {
1550                                 return (EFAULT);
1551                         }
1552 #endif  /* _MULTI_DATAMODEL */
1553                         return (0);
1554                 }
1555         }
1556 
1557         if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1558                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1559                 mutex_exit(&pptr->port_mutex);
1560                 return (ENXIO);
1561         }
1562 
1563         for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1564             i++) {
1565                 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1566 
1567                 dev_data[i].dev0_type = DTYPE_UNKNOWN;
1568 
1569 
1570                 dev_data[i].dev_status = ENXIO;
1571 
1572                 if ((ptgt = fcp_lookup_target(pptr,
1573                     (uchar_t *)wwn_ptr)) == NULL) {
1574                         mutex_exit(&pptr->port_mutex);
1575                         if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1576                             wwn_ptr, &error, 0) == NULL) {
1577                                 dev_data[i].dev_status = ENODEV;
1578                                 mutex_enter(&pptr->port_mutex);
1579                                 continue;
1580                         } else {
1581 
1582                                 dev_data[i].dev_status = EAGAIN;
1583 
1584                                 mutex_enter(&pptr->port_mutex);
1585                                 continue;
1586                         }
1587                 } else {
1588                         mutex_enter(&ptgt->tgt_mutex);
1589                         if (ptgt->tgt_state & (FCP_TGT_MARK |
1590                             FCP_TGT_BUSY)) {
1591                                 dev_data[i].dev_status = EAGAIN;
1592                                 mutex_exit(&ptgt->tgt_mutex);
1593                                 continue;
1594                         }
1595 
1596                         if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1597                                 if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1598                                         dev_data[i].dev_status = ENOTSUP;
1599                                 } else {
1600                                         dev_data[i].dev_status = ENXIO;
1601                                 }
1602                                 mutex_exit(&ptgt->tgt_mutex);
1603                                 continue;
1604                         }
1605 
1606                         switch (cmd) {
1607                         case FCP_TGT_INQUIRY:
1608                                 /*
1609                                  * The reason we give device type of
1610                                  * lun 0 only even though in some
1611                                  * cases(like maxstrat) lun 0 device
1612                                  * type may be 0x3f(invalid) is that
1613                                  * for bridge boxes target will appear
1614                                  * as luns and the first lun could be
1615                                  * a device that utility may not care
1616                                  * about (like a tape device).
1617                                  */
1618                                 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1619                                 dev_data[i].dev_status = 0;
1620                                 mutex_exit(&ptgt->tgt_mutex);
1621 
1622                                 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1623                                         dev_data[i].dev0_type = DTYPE_UNKNOWN;
1624                                 } else {
1625                                         dev_data[i].dev0_type = plun->lun_type;
1626                                 }
1627                                 mutex_enter(&ptgt->tgt_mutex);
1628                                 break;
1629 
1630                         case FCP_TGT_CREATE:
1631                                 mutex_exit(&ptgt->tgt_mutex);
1632                                 mutex_exit(&pptr->port_mutex);
1633 
1634                                 /*
1635                                  * serialize state change call backs.
1636                                  * only one call back will be handled
1637                                  * at a time.
1638                                  */
1639                                 mutex_enter(&fcp_global_mutex);
1640                                 if (fcp_oflag & FCP_BUSY) {
1641                                         mutex_exit(&fcp_global_mutex);
1642                                         if (dev_data) {
1643                                                 kmem_free(dev_data,
1644                                                     sizeof (*dev_data) *
1645                                                     fioctl.listlen);
1646                                         }
1647                                         return (EBUSY);
1648                                 }
1649                                 fcp_oflag |= FCP_BUSY;
1650                                 mutex_exit(&fcp_global_mutex);
1651 
1652                                 dev_data[i].dev_status =
1653                                     fcp_create_on_demand(pptr,
1654                                     wwn_ptr->raw_wwn);
1655 
1656                                 if (dev_data[i].dev_status != 0) {
1657                                         char    buf[25];
1658 
1659                                         for (i = 0; i < FC_WWN_SIZE; i++) {
1660                                                 (void) sprintf(&buf[i << 1],
1661                                                     "%02x",
1662                                                     wwn_ptr->raw_wwn[i]);
1663                                         }
1664 
1665                                         fcp_log(CE_WARN, pptr->port_dip,
1666                                             "!Failed to create nodes for"
1667                                             " pwwn=%s; error=%x", buf,
1668                                             dev_data[i].dev_status);
1669                                 }
1670 
1671                                 /* allow state change call backs again */
1672                                 mutex_enter(&fcp_global_mutex);
1673                                 fcp_oflag &= ~FCP_BUSY;
1674                                 mutex_exit(&fcp_global_mutex);
1675 
1676                                 mutex_enter(&pptr->port_mutex);
1677                                 mutex_enter(&ptgt->tgt_mutex);
1678 
1679                                 break;
1680 
1681                         case FCP_TGT_DELETE:
1682                                 break;
1683 
1684                         default:
1685                                 fcp_log(CE_WARN, pptr->port_dip,
1686                                     "!Invalid device data ioctl "
1687                                     "opcode = 0x%x", cmd);
1688                         }
1689                         mutex_exit(&ptgt->tgt_mutex);
1690                 }
1691         }
1692         mutex_exit(&pptr->port_mutex);
1693 
1694         if (ddi_copyout(dev_data, fioctl.list,
1695             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1696                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1697                 return (EFAULT);
1698         }
1699         kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1700 
1701 #ifdef  _MULTI_DATAMODEL
1702         switch (ddi_model_convert_from(mode & FMODELS)) {
1703         case DDI_MODEL_ILP32: {
1704                 struct fcp32_ioctl f32_ioctl;
1705 
1706                 f32_ioctl.fp_minor = fioctl.fp_minor;
1707                 f32_ioctl.listlen = fioctl.listlen;
1708                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1709                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1710                     sizeof (struct fcp32_ioctl), mode)) {
1711                         return (EFAULT);
1712                 }
1713                 break;
1714         }
1715         case DDI_MODEL_NONE:
1716                 if (ddi_copyout((void *)&fioctl, (void *)data,
1717                     sizeof (struct fcp_ioctl), mode)) {
1718                         return (EFAULT);
1719                 }
1720                 break;
1721         }
1722 #else   /* _MULTI_DATAMODEL */
1723 
1724         if (ddi_copyout((void *)&fioctl, (void *)data,
1725             sizeof (struct fcp_ioctl), mode)) {
1726                 return (EFAULT);
1727         }
1728 #endif  /* _MULTI_DATAMODEL */
1729 
1730         return (0);
1731 }
1732 
1733 /*
1734  * Fetch the target mappings (path, etc.) for all LUNs
1735  * on this port.
1736  */
1737 /* ARGSUSED */
1738 static int
1739 fcp_get_target_mappings(struct fcp_ioctl *data,
1740     int mode, int *rval)
1741 {
1742         struct fcp_port     *pptr;
1743         fc_hba_target_mappings_t    *mappings;
1744         fc_hba_mapping_entry_t      *map;
1745         struct fcp_tgt      *ptgt = NULL;
1746         struct fcp_lun      *plun = NULL;
1747         int                         i, mapIndex, mappingSize;
1748         int                         listlen;
1749         struct fcp_ioctl            fioctl;
1750         char                        *path;
1751         fcp_ent_addr_t              sam_lun_addr;
1752 
1753 #ifdef  _MULTI_DATAMODEL
1754         switch (ddi_model_convert_from(mode & FMODELS)) {
1755         case DDI_MODEL_ILP32: {
1756                 struct fcp32_ioctl f32_ioctl;
1757 
1758                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1759                     sizeof (struct fcp32_ioctl), mode)) {
1760                         return (EFAULT);
1761                 }
1762                 fioctl.fp_minor = f32_ioctl.fp_minor;
1763                 fioctl.listlen = f32_ioctl.listlen;
1764                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1765                 break;
1766         }
1767         case DDI_MODEL_NONE:
1768                 if (ddi_copyin((void *)data, (void *)&fioctl,
1769                     sizeof (struct fcp_ioctl), mode)) {
1770                         return (EFAULT);
1771                 }
1772                 break;
1773         }
1774 
1775 #else   /* _MULTI_DATAMODEL */
1776         if (ddi_copyin((void *)data, (void *)&fioctl,
1777             sizeof (struct fcp_ioctl), mode)) {
1778                 return (EFAULT);
1779         }
1780 #endif  /* _MULTI_DATAMODEL */
1781 
1782         /*
1783          * Right now we can assume that the minor number matches with
1784          * this instance of fp. If this changes we will need to
1785          * revisit this logic.
1786          */
1787         mutex_enter(&fcp_global_mutex);
1788         pptr = fcp_port_head;
1789         while (pptr) {
1790                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1791                         break;
1792                 } else {
1793                         pptr = pptr->port_next;
1794                 }
1795         }
1796         mutex_exit(&fcp_global_mutex);
1797         if (pptr == NULL) {
1798                 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1799                     fioctl.fp_minor);
1800                 return (ENXIO);
1801         }
1802 
1803 
1804         /* We use listlen to show the total buffer size */
1805         mappingSize = fioctl.listlen;
1806 
1807         /* Now calculate how many mapping entries will fit */
1808         listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1809             - sizeof (fc_hba_target_mappings_t);
1810         if (listlen <= 0) {
1811                 cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1812                 return (ENXIO);
1813         }
1814         listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1815 
1816         if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1817                 return (ENOMEM);
1818         }
1819         mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1820 
1821         /* Now get to work */
1822         mapIndex = 0;
1823 
1824         mutex_enter(&pptr->port_mutex);
1825         /* Loop through all targets on this port */
1826         for (i = 0; i < FCP_NUM_HASH; i++) {
1827                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1828                     ptgt = ptgt->tgt_next) {
1829 
1830                         mutex_enter(&ptgt->tgt_mutex);
1831 
1832                         /* Loop through all LUNs on this target */
1833                         for (plun = ptgt->tgt_lun; plun != NULL;
1834                             plun = plun->lun_next) {
1835                                 if (plun->lun_state & FCP_LUN_OFFLINE) {
1836                                         continue;
1837                                 }
1838 
1839                                 path = fcp_get_lun_path(plun);
1840                                 if (path == NULL) {
1841                                         continue;
1842                                 }
1843 
1844                                 if (mapIndex >= listlen) {
1845                                         mapIndex ++;
1846                                         kmem_free(path, MAXPATHLEN);
1847                                         continue;
1848                                 }
1849                                 map = &mappings->entries[mapIndex++];
1850                                 bcopy(path, map->targetDriver,
1851                                     sizeof (map->targetDriver));
1852                                 map->d_id = ptgt->tgt_d_id;
1853                                 map->busNumber = 0;
1854                                 map->targetNumber = ptgt->tgt_d_id;
1855                                 map->osLUN = plun->lun_num;
1856 
1857                                 /*
1858                                  * We had swapped lun when we stored it in
1859                                  * lun_addr. We need to swap it back before
1860                                  * returning it to user land
1861                                  */
1862 
1863                                 sam_lun_addr.ent_addr_0 =
1864                                     BE_16(plun->lun_addr.ent_addr_0);
1865                                 sam_lun_addr.ent_addr_1 =
1866                                     BE_16(plun->lun_addr.ent_addr_1);
1867                                 sam_lun_addr.ent_addr_2 =
1868                                     BE_16(plun->lun_addr.ent_addr_2);
1869                                 sam_lun_addr.ent_addr_3 =
1870                                     BE_16(plun->lun_addr.ent_addr_3);
1871 
1872                                 bcopy(&sam_lun_addr, &map->samLUN,
1873                                     FCP_LUN_SIZE);
1874                                 bcopy(ptgt->tgt_node_wwn.raw_wwn,
1875                                     map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1876                                 bcopy(ptgt->tgt_port_wwn.raw_wwn,
1877                                     map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1878 
1879                                 if (plun->lun_guid) {
1880 
1881                                         /* convert ascii wwn to bytes */
1882                                         fcp_ascii_to_wwn(plun->lun_guid,
1883                                             map->guid, sizeof (map->guid));
1884 
1885                                         if ((sizeof (map->guid)) <
1886                                             plun->lun_guid_size / 2) {
1887                                                 cmn_err(CE_WARN,
1888                                                     "fcp_get_target_mappings:"
1889                                                     "guid copy space "
1890                                                     "insufficient."
1891                                                     "Copy Truncation - "
1892                                                     "available %d; need %d",
1893                                                     (int)sizeof (map->guid),
1894                                                     (int)
1895                                                     plun->lun_guid_size / 2);
1896                                         }
1897                                 }
1898                                 kmem_free(path, MAXPATHLEN);
1899                         }
1900                         mutex_exit(&ptgt->tgt_mutex);
1901                 }
1902         }
1903         mutex_exit(&pptr->port_mutex);
1904         mappings->numLuns = mapIndex;
1905 
1906         if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1907                 kmem_free(mappings, mappingSize);
1908                 return (EFAULT);
1909         }
1910         kmem_free(mappings, mappingSize);
1911 
1912 #ifdef  _MULTI_DATAMODEL
1913         switch (ddi_model_convert_from(mode & FMODELS)) {
1914         case DDI_MODEL_ILP32: {
1915                 struct fcp32_ioctl f32_ioctl;
1916 
1917                 f32_ioctl.fp_minor = fioctl.fp_minor;
1918                 f32_ioctl.listlen = fioctl.listlen;
1919                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1920                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1921                     sizeof (struct fcp32_ioctl), mode)) {
1922                         return (EFAULT);
1923                 }
1924                 break;
1925         }
1926         case DDI_MODEL_NONE:
1927                 if (ddi_copyout((void *)&fioctl, (void *)data,
1928                     sizeof (struct fcp_ioctl), mode)) {
1929                         return (EFAULT);
1930                 }
1931                 break;
1932         }
1933 #else   /* _MULTI_DATAMODEL */
1934 
1935         if (ddi_copyout((void *)&fioctl, (void *)data,
1936             sizeof (struct fcp_ioctl), mode)) {
1937                 return (EFAULT);
1938         }
1939 #endif  /* _MULTI_DATAMODEL */
1940 
1941         return (0);
1942 }
1943 
1944 /*
1945  * fcp_setup_scsi_ioctl
1946  *      Setup handler for the "scsi passthru" style of
1947  *      ioctl for FCP.  See "fcp_util.h" for data structure
1948  *      definition.
1949  *
1950  * Input:
1951  *      u_fscsi = ioctl data (user address space)
1952  *      mode    = See ioctl(9E)
1953  *
1954  * Output:
1955  *      u_fscsi = ioctl data (user address space)
1956  *      rval    = return value - see ioctl(9E)
1957  *
1958  * Returns:
1959  *      0       = OK
1960  *      EAGAIN  = See errno.h
1961  *      EBUSY   = See errno.h
1962  *      EFAULT  = See errno.h
1963  *      EINTR   = See errno.h
1964  *      EINVAL  = See errno.h
1965  *      EIO     = See errno.h
1966  *      ENOMEM  = See errno.h
1967  *      ENXIO   = See errno.h
1968  *
1969  * Context:
1970  *      Kernel context.
1971  */
1972 /* ARGSUSED */
1973 static int
1974 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1975     int mode, int *rval)
1976 {
1977         int                     ret             = 0;
1978         int                     temp_ret;
1979         caddr_t                 k_cdbbufaddr    = NULL;
1980         caddr_t                 k_bufaddr       = NULL;
1981         caddr_t                 k_rqbufaddr     = NULL;
1982         caddr_t                 u_cdbbufaddr;
1983         caddr_t                 u_bufaddr;
1984         caddr_t                 u_rqbufaddr;
1985         struct fcp_scsi_cmd     k_fscsi;
1986 
1987         /*
1988          * Get fcp_scsi_cmd array element from user address space
1989          */
1990         if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1991             != 0) {
1992                 return (ret);
1993         }
1994 
1995 
1996         /*
1997          * Even though kmem_alloc() checks the validity of the
1998          * buffer length, this check is needed when the
1999          * kmem_flags set and the zero buffer length is passed.
2000          */
2001         if ((k_fscsi.scsi_cdblen <= 0) ||
2002             (k_fscsi.scsi_buflen <= 0) ||
2003             (k_fscsi.scsi_rqlen <= 0)) {
2004                 return (EINVAL);
2005         }
2006 
2007         /*
2008          * Allocate data for fcp_scsi_cmd pointer fields
2009          */
2010         if (ret == 0) {
2011                 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2012                 k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2013                 k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2014 
2015                 if (k_cdbbufaddr == NULL ||
2016                     k_bufaddr    == NULL ||
2017                     k_rqbufaddr  == NULL) {
2018                         ret = ENOMEM;
2019                 }
2020         }
2021 
2022         /*
2023          * Get fcp_scsi_cmd pointer fields from user
2024          * address space
2025          */
2026         if (ret == 0) {
2027                 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2028                 u_bufaddr    = k_fscsi.scsi_bufaddr;
2029                 u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2030 
2031                 if (ddi_copyin(u_cdbbufaddr,
2032                     k_cdbbufaddr,
2033                     k_fscsi.scsi_cdblen,
2034                     mode)) {
2035                         ret = EFAULT;
2036                 } else if (ddi_copyin(u_bufaddr,
2037                     k_bufaddr,
2038                     k_fscsi.scsi_buflen,
2039                     mode)) {
2040                         ret = EFAULT;
2041                 } else if (ddi_copyin(u_rqbufaddr,
2042                     k_rqbufaddr,
2043                     k_fscsi.scsi_rqlen,
2044                     mode)) {
2045                         ret = EFAULT;
2046                 }
2047         }
2048 
2049         /*
2050          * Send scsi command (blocking)
2051          */
2052         if (ret == 0) {
2053                 /*
2054                  * Prior to sending the scsi command, the
2055                  * fcp_scsi_cmd data structure must contain kernel,
2056                  * not user, addresses.
2057                  */
2058                 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr;
2059                 k_fscsi.scsi_bufaddr    = k_bufaddr;
2060                 k_fscsi.scsi_rqbufaddr  = k_rqbufaddr;
2061 
2062                 ret = fcp_send_scsi_ioctl(&k_fscsi);
2063 
2064                 /*
2065                  * After sending the scsi command, the
2066                  * fcp_scsi_cmd data structure must contain user,
2067                  * not kernel, addresses.
2068                  */
2069                 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr;
2070                 k_fscsi.scsi_bufaddr    = u_bufaddr;
2071                 k_fscsi.scsi_rqbufaddr  = u_rqbufaddr;
2072         }
2073 
2074         /*
2075          * Put fcp_scsi_cmd pointer fields to user address space
2076          */
2077         if (ret == 0) {
2078                 if (ddi_copyout(k_cdbbufaddr,
2079                     u_cdbbufaddr,
2080                     k_fscsi.scsi_cdblen,
2081                     mode)) {
2082                         ret = EFAULT;
2083                 } else if (ddi_copyout(k_bufaddr,
2084                     u_bufaddr,
2085                     k_fscsi.scsi_buflen,
2086                     mode)) {
2087                         ret = EFAULT;
2088                 } else if (ddi_copyout(k_rqbufaddr,
2089                     u_rqbufaddr,
2090                     k_fscsi.scsi_rqlen,
2091                     mode)) {
2092                         ret = EFAULT;
2093                 }
2094         }
2095 
2096         /*
2097          * Free data for fcp_scsi_cmd pointer fields
2098          */
2099         if (k_cdbbufaddr != NULL) {
2100                 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2101         }
2102         if (k_bufaddr != NULL) {
2103                 kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2104         }
2105         if (k_rqbufaddr != NULL) {
2106                 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2107         }
2108 
2109         /*
2110          * Put fcp_scsi_cmd array element to user address space
2111          */
2112         temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2113         if (temp_ret != 0) {
2114                 ret = temp_ret;
2115         }
2116 
2117         /*
2118          * Return status
2119          */
2120         return (ret);
2121 }
2122 
2123 
2124 /*
2125  * fcp_copyin_scsi_cmd
2126  *      Copy in fcp_scsi_cmd data structure from user address space.
2127  *      The data may be in 32 bit or 64 bit modes.
2128  *
2129  * Input:
2130  *      base_addr       = from address (user address space)
2131  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2132  *
2133  * Output:
2134  *      fscsi           = to address (kernel address space)
2135  *
2136  * Returns:
2137  *      0       = OK
2138  *      EFAULT  = Error
2139  *
2140  * Context:
2141  *      Kernel context.
2142  */
2143 static int
2144 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2145 {
2146 #ifdef  _MULTI_DATAMODEL
2147         struct fcp32_scsi_cmd   f32scsi;
2148 
2149         switch (ddi_model_convert_from(mode & FMODELS)) {
2150         case DDI_MODEL_ILP32:
2151                 /*
2152                  * Copy data from user address space
2153                  */
2154                 if (ddi_copyin((void *)base_addr,
2155                     &f32scsi,
2156                     sizeof (struct fcp32_scsi_cmd),
2157                     mode)) {
2158                         return (EFAULT);
2159                 }
2160                 /*
2161                  * Convert from 32 bit to 64 bit
2162                  */
2163                 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2164                 break;
2165         case DDI_MODEL_NONE:
2166                 /*
2167                  * Copy data from user address space
2168                  */
2169                 if (ddi_copyin((void *)base_addr,
2170                     fscsi,
2171                     sizeof (struct fcp_scsi_cmd),
2172                     mode)) {
2173                         return (EFAULT);
2174                 }
2175                 break;
2176         }
2177 #else   /* _MULTI_DATAMODEL */
2178         /*
2179          * Copy data from user address space
2180          */
2181         if (ddi_copyin((void *)base_addr,
2182             fscsi,
2183             sizeof (struct fcp_scsi_cmd),
2184             mode)) {
2185                 return (EFAULT);
2186         }
2187 #endif  /* _MULTI_DATAMODEL */
2188 
2189         return (0);
2190 }
2191 
2192 
2193 /*
2194  * fcp_copyout_scsi_cmd
2195  *      Copy out fcp_scsi_cmd data structure to user address space.
2196  *      The data may be in 32 bit or 64 bit modes.
2197  *
2198  * Input:
2199  *      fscsi           = to address (kernel address space)
2200  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2201  *
2202  * Output:
2203  *      base_addr       = from address (user address space)
2204  *
2205  * Returns:
2206  *      0       = OK
2207  *      EFAULT  = Error
2208  *
2209  * Context:
2210  *      Kernel context.
2211  */
2212 static int
2213 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2214 {
2215 #ifdef  _MULTI_DATAMODEL
2216         struct fcp32_scsi_cmd   f32scsi;
2217 
2218         switch (ddi_model_convert_from(mode & FMODELS)) {
2219         case DDI_MODEL_ILP32:
2220                 /*
2221                  * Convert from 64 bit to 32 bit
2222                  */
2223                 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2224                 /*
2225                  * Copy data to user address space
2226                  */
2227                 if (ddi_copyout(&f32scsi,
2228                     (void *)base_addr,
2229                     sizeof (struct fcp32_scsi_cmd),
2230                     mode)) {
2231                         return (EFAULT);
2232                 }
2233                 break;
2234         case DDI_MODEL_NONE:
2235                 /*
2236                  * Copy data to user address space
2237                  */
2238                 if (ddi_copyout(fscsi,
2239                     (void *)base_addr,
2240                     sizeof (struct fcp_scsi_cmd),
2241                     mode)) {
2242                         return (EFAULT);
2243                 }
2244                 break;
2245         }
2246 #else   /* _MULTI_DATAMODEL */
2247         /*
2248          * Copy data to user address space
2249          */
2250         if (ddi_copyout(fscsi,
2251             (void *)base_addr,
2252             sizeof (struct fcp_scsi_cmd),
2253             mode)) {
2254                 return (EFAULT);
2255         }
2256 #endif  /* _MULTI_DATAMODEL */
2257 
2258         return (0);
2259 }
2260 
2261 
2262 /*
2263  * fcp_send_scsi_ioctl
2264  *      Sends the SCSI command in blocking mode.
2265  *
2266  * Input:
2267  *      fscsi           = SCSI command data structure
2268  *
2269  * Output:
2270  *      fscsi           = SCSI command data structure
2271  *
2272  * Returns:
2273  *      0       = OK
2274  *      EAGAIN  = See errno.h
2275  *      EBUSY   = See errno.h
2276  *      EINTR   = See errno.h
2277  *      EINVAL  = See errno.h
2278  *      EIO     = See errno.h
2279  *      ENOMEM  = See errno.h
2280  *      ENXIO   = See errno.h
2281  *
2282  * Context:
2283  *      Kernel context.
2284  */
2285 static int
2286 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2287 {
2288         struct fcp_lun  *plun           = NULL;
2289         struct fcp_port *pptr           = NULL;
2290         struct fcp_tgt  *ptgt           = NULL;
2291         fc_packet_t             *fpkt           = NULL;
2292         struct fcp_ipkt *icmd           = NULL;
2293         int                     target_created  = FALSE;
2294         fc_frame_hdr_t          *hp;
2295         struct fcp_cmd          fcp_cmd;
2296         struct fcp_cmd          *fcmd;
2297         union scsi_cdb          *scsi_cdb;
2298         la_wwn_t                *wwn_ptr;
2299         int                     nodma;
2300         struct fcp_rsp          *rsp;
2301         struct fcp_rsp_info     *rsp_info;
2302         caddr_t                 rsp_sense;
2303         int                     buf_len;
2304         int                     info_len;
2305         int                     sense_len;
2306         struct scsi_extended_sense      *sense_to = NULL;
2307         timeout_id_t            tid;
2308         uint8_t                 reconfig_lun = FALSE;
2309         uint8_t                 reconfig_pending = FALSE;
2310         uint8_t                 scsi_cmd;
2311         int                     rsp_len;
2312         int                     cmd_index;
2313         int                     fc_status;
2314         int                     pkt_state;
2315         int                     pkt_action;
2316         int                     pkt_reason;
2317         int                     ret, xport_retval = ~FC_SUCCESS;
2318         int                     lcount;
2319         int                     tcount;
2320         int                     reconfig_status;
2321         int                     port_busy = FALSE;
2322         uchar_t                 *lun_string;
2323 
2324         /*
2325          * Check valid SCSI command
2326          */
2327         scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2328         ret = EINVAL;
2329         for (cmd_index = 0;
2330             cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2331             ret != 0;
2332             cmd_index++) {
2333                 /*
2334                  * First byte of CDB is the SCSI command
2335                  */
2336                 if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2337                         ret = 0;
2338                 }
2339         }
2340 
2341         /*
2342          * Check inputs
2343          */
2344         if (fscsi->scsi_flags != FCP_SCSI_READ) {
2345                 ret = EINVAL;
2346         } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2347                 /* no larger than */
2348                 ret = EINVAL;
2349         }
2350 
2351 
2352         /*
2353          * Find FC port
2354          */
2355         if (ret == 0) {
2356                 /*
2357                  * Acquire global mutex
2358                  */
2359                 mutex_enter(&fcp_global_mutex);
2360 
2361                 pptr = fcp_port_head;
2362                 while (pptr) {
2363                         if (pptr->port_instance ==
2364                             (uint32_t)fscsi->scsi_fc_port_num) {
2365                                 break;
2366                         } else {
2367                                 pptr = pptr->port_next;
2368                         }
2369                 }
2370 
2371                 if (pptr == NULL) {
2372                         ret = ENXIO;
2373                 } else {
2374                         /*
2375                          * fc_ulp_busy_port can raise power
2376                          *  so, we must not hold any mutexes involved in PM
2377                          */
2378                         mutex_exit(&fcp_global_mutex);
2379                         ret = fc_ulp_busy_port(pptr->port_fp_handle);
2380                 }
2381 
2382                 if (ret == 0) {
2383 
2384                         /* remember port is busy, so we will release later */
2385                         port_busy = TRUE;
2386 
2387                         /*
2388                          * If there is a reconfiguration in progress, wait
2389                          * for it to complete.
2390                          */
2391 
2392                         fcp_reconfig_wait(pptr);
2393 
2394                         /* reacquire mutexes in order */
2395                         mutex_enter(&fcp_global_mutex);
2396                         mutex_enter(&pptr->port_mutex);
2397 
2398                         /*
2399                          * Will port accept DMA?
2400                          */
2401                         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2402                             ? 1 : 0;
2403 
2404                         /*
2405                          * If init or offline, device not known
2406                          *
2407                          * If we are discovering (onlining), we can
2408                          * NOT obviously provide reliable data about
2409                          * devices until it is complete
2410                          */
2411                         if (pptr->port_state &     (FCP_STATE_INIT |
2412                             FCP_STATE_OFFLINE)) {
2413                                 ret = ENXIO;
2414                         } else if (pptr->port_state & FCP_STATE_ONLINING) {
2415                                 ret = EBUSY;
2416                         } else {
2417                                 /*
2418                                  * Find target from pwwn
2419                                  *
2420                                  * The wwn must be put into a local
2421                                  * variable to ensure alignment.
2422                                  */
2423                                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2424                                 ptgt = fcp_lookup_target(pptr,
2425                                     (uchar_t *)wwn_ptr);
2426 
2427                                 /*
2428                                  * If target not found,
2429                                  */
2430                                 if (ptgt == NULL) {
2431                                         /*
2432                                          * Note: Still have global &
2433                                          * port mutexes
2434                                          */
2435                                         mutex_exit(&pptr->port_mutex);
2436                                         ptgt = fcp_port_create_tgt(pptr,
2437                                             wwn_ptr, &ret, &fc_status,
2438                                             &pkt_state, &pkt_action,
2439                                             &pkt_reason);
2440                                         mutex_enter(&pptr->port_mutex);
2441 
2442                                         fscsi->scsi_fc_status  = fc_status;
2443                                         fscsi->scsi_pkt_state  =
2444                                             (uchar_t)pkt_state;
2445                                         fscsi->scsi_pkt_reason = pkt_reason;
2446                                         fscsi->scsi_pkt_action =
2447                                             (uchar_t)pkt_action;
2448 
2449                                         if (ptgt != NULL) {
2450                                                 target_created = TRUE;
2451                                         } else if (ret == 0) {
2452                                                 ret = ENOMEM;
2453                                         }
2454                                 }
2455 
2456                                 if (ret == 0) {
2457                                         /*
2458                                          * Acquire target
2459                                          */
2460                                         mutex_enter(&ptgt->tgt_mutex);
2461 
2462                                         /*
2463                                          * If target is mark or busy,
2464                                          * then target can not be used
2465                                          */
2466                                         if (ptgt->tgt_state &
2467                                             (FCP_TGT_MARK |
2468                                             FCP_TGT_BUSY)) {
2469                                                 ret = EBUSY;
2470                                         } else {
2471                                                 /*
2472                                                  * Mark target as busy
2473                                                  */
2474                                                 ptgt->tgt_state |=
2475                                                     FCP_TGT_BUSY;
2476                                         }
2477 
2478                                         /*
2479                                          * Release target
2480                                          */
2481                                         lcount = pptr->port_link_cnt;
2482                                         tcount = ptgt->tgt_change_cnt;
2483                                         mutex_exit(&ptgt->tgt_mutex);
2484                                 }
2485                         }
2486 
2487                         /*
2488                          * Release port
2489                          */
2490                         mutex_exit(&pptr->port_mutex);
2491                 }
2492 
2493                 /*
2494                  * Release global mutex
2495                  */
2496                 mutex_exit(&fcp_global_mutex);
2497         }
2498 
2499         if (ret == 0) {
2500                 uint64_t belun = BE_64(fscsi->scsi_lun);
2501 
2502                 /*
2503                  * If it's a target device, find lun from pwwn
2504                  * The wwn must be put into a local
2505                  * variable to ensure alignment.
2506                  */
2507                 mutex_enter(&pptr->port_mutex);
2508                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2509                 if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2510                         /* this is not a target */
2511                         fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2512                         ret = ENXIO;
2513                 } else if ((belun << 16) != 0) {
2514                         /*
2515                          * Since fcp only support PD and LU addressing method
2516                          * so far, the last 6 bytes of a valid LUN are expected
2517                          * to be filled with 00h.
2518                          */
2519                         fscsi->scsi_fc_status = FC_INVALID_LUN;
2520                         cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2521                             " method 0x%02x with LUN number 0x%016" PRIx64,
2522                             (uint8_t)(belun >> 62), belun);
2523                         ret = ENXIO;
2524                 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2525                     (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2526                         /*
2527                          * This is a SCSI target, but no LUN at this
2528                          * address.
2529                          *
2530                          * In the future, we may want to send this to
2531                          * the target, and let it respond
2532                          * appropriately
2533                          */
2534                         ret = ENXIO;
2535                 }
2536                 mutex_exit(&pptr->port_mutex);
2537         }
2538 
2539         /*
2540          * Finished grabbing external resources
2541          * Allocate internal packet (icmd)
2542          */
2543         if (ret == 0) {
2544                 /*
2545                  * Calc rsp len assuming rsp info included
2546                  */
2547                 rsp_len = sizeof (struct fcp_rsp) +
2548                     sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2549 
2550                 icmd = fcp_icmd_alloc(pptr, ptgt,
2551                     sizeof (struct fcp_cmd),
2552                     rsp_len,
2553                     fscsi->scsi_buflen,
2554                     nodma,
2555                     lcount,                     /* ipkt_link_cnt */
2556                     tcount,                     /* ipkt_change_cnt */
2557                     0,                          /* cause */
2558                     FC_INVALID_RSCN_COUNT);     /* invalidate the count */
2559 
2560                 if (icmd == NULL) {
2561                         ret = ENOMEM;
2562                 } else {
2563                         /*
2564                          * Setup internal packet as sema sync
2565                          */
2566                         fcp_ipkt_sema_init(icmd);
2567                 }
2568         }
2569 
2570         if (ret == 0) {
2571                 /*
2572                  * Init fpkt pointer for use.
2573                  */
2574 
2575                 fpkt = icmd->ipkt_fpkt;
2576 
2577                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
2578                 fpkt->pkt_tran_type  = FC_PKT_FCP_READ; /* only rd for now */
2579                 fpkt->pkt_timeout    = fscsi->scsi_timeout;
2580 
2581                 /*
2582                  * Init fcmd pointer for use by SCSI command
2583                  */
2584 
2585                 if (nodma) {
2586                         fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2587                 } else {
2588                         fcmd = &fcp_cmd;
2589                 }
2590                 bzero(fcmd, sizeof (struct fcp_cmd));
2591                 ptgt = plun->lun_tgt;
2592 
2593                 lun_string = (uchar_t *)&fscsi->scsi_lun;
2594 
2595                 fcmd->fcp_ent_addr.ent_addr_0 =
2596                     BE_16(*(uint16_t *)&(lun_string[0]));
2597                 fcmd->fcp_ent_addr.ent_addr_1 =
2598                     BE_16(*(uint16_t *)&(lun_string[2]));
2599                 fcmd->fcp_ent_addr.ent_addr_2 =
2600                     BE_16(*(uint16_t *)&(lun_string[4]));
2601                 fcmd->fcp_ent_addr.ent_addr_3 =
2602                     BE_16(*(uint16_t *)&(lun_string[6]));
2603 
2604                 /*
2605                  * Setup internal packet(icmd)
2606                  */
2607                 icmd->ipkt_lun               = plun;
2608                 icmd->ipkt_restart   = 0;
2609                 icmd->ipkt_retries   = 0;
2610                 icmd->ipkt_opcode    = 0;
2611 
2612                 /*
2613                  * Init the frame HEADER Pointer for use
2614                  */
2615                 hp = &fpkt->pkt_cmd_fhdr;
2616 
2617                 hp->s_id     = pptr->port_id;
2618                 hp->d_id     = ptgt->tgt_d_id;
2619                 hp->r_ctl    = R_CTL_COMMAND;
2620                 hp->type     = FC_TYPE_SCSI_FCP;
2621                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2622                 hp->rsvd     = 0;
2623                 hp->seq_id   = 0;
2624                 hp->seq_cnt  = 0;
2625                 hp->ox_id    = 0xffff;
2626                 hp->rx_id    = 0xffff;
2627                 hp->ro               = 0;
2628 
2629                 fcmd->fcp_cntl.cntl_qtype    = FCP_QTYPE_SIMPLE;
2630                 fcmd->fcp_cntl.cntl_read_data        = 1;    /* only rd for now */
2631                 fcmd->fcp_cntl.cntl_write_data       = 0;
2632                 fcmd->fcp_data_len   = fscsi->scsi_buflen;
2633 
2634                 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2635                 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2636                     fscsi->scsi_cdblen);
2637 
2638                 if (!nodma) {
2639                         FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2640                             fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2641                 }
2642 
2643                 /*
2644                  * Send SCSI command to FC transport
2645                  */
2646 
2647                 if (ret == 0) {
2648                         mutex_enter(&ptgt->tgt_mutex);
2649 
2650                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2651                                 mutex_exit(&ptgt->tgt_mutex);
2652                                 fscsi->scsi_fc_status = xport_retval =
2653                                     fc_ulp_transport(pptr->port_fp_handle,
2654                                     fpkt);
2655                                 if (fscsi->scsi_fc_status != FC_SUCCESS) {
2656                                         ret = EIO;
2657                                 }
2658                         } else {
2659                                 mutex_exit(&ptgt->tgt_mutex);
2660                                 ret = EBUSY;
2661                         }
2662                 }
2663         }
2664 
2665         /*
2666          * Wait for completion only if fc_ulp_transport was called and it
2667          * returned a success. This is the only time callback will happen.
2668          * Otherwise, there is no point in waiting
2669          */
2670         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2671                 ret = fcp_ipkt_sema_wait(icmd);
2672         }
2673 
2674         /*
2675          * Copy data to IOCTL data structures
2676          */
2677         rsp = NULL;
2678         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2679                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2680 
2681                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2682                         fcp_log(CE_WARN, pptr->port_dip,
2683                             "!SCSI command to d_id=0x%x lun=0x%x"
2684                             " failed, Bad FCP response values:"
2685                             " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2686                             " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2687                             ptgt->tgt_d_id, plun->lun_num,
2688                             rsp->reserved_0, rsp->reserved_1,
2689                             rsp->fcp_u.fcp_status.reserved_0,
2690                             rsp->fcp_u.fcp_status.reserved_1,
2691                             rsp->fcp_response_len, rsp->fcp_sense_len);
2692 
2693                         ret = EIO;
2694                 }
2695         }
2696 
2697         if ((ret == 0) && (rsp != NULL)) {
2698                 /*
2699                  * Calc response lengths
2700                  */
2701                 sense_len = 0;
2702                 info_len = 0;
2703 
2704                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
2705                         info_len = rsp->fcp_response_len;
2706                 }
2707 
2708                 rsp_info   = (struct fcp_rsp_info *)
2709                     ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2710 
2711                 /*
2712                  * Get SCSI status
2713                  */
2714                 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2715                 /*
2716                  * If a lun was just added or removed and the next command
2717                  * comes through this interface, we need to capture the check
2718                  * condition so we can discover the new topology.
2719                  */
2720                 if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2721                     rsp->fcp_u.fcp_status.sense_len_set) {
2722                         sense_len = rsp->fcp_sense_len;
2723                         rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2724                         sense_to = (struct scsi_extended_sense *)rsp_sense;
2725                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2726                             (FCP_SENSE_NO_LUN(sense_to))) {
2727                                 reconfig_lun = TRUE;
2728                         }
2729                 }
2730 
2731                 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2732                     (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2733                         if (reconfig_lun == FALSE) {
2734                                 reconfig_status =
2735                                     fcp_is_reconfig_needed(ptgt, fpkt);
2736                         }
2737 
2738                         if ((reconfig_lun == TRUE) ||
2739                             (reconfig_status == TRUE)) {
2740                                 mutex_enter(&ptgt->tgt_mutex);
2741                                 if (ptgt->tgt_tid == NULL) {
2742                                         /*
2743                                          * Either we've been notified the
2744                                          * REPORT_LUN data has changed, or
2745                                          * we've determined on our own that
2746                                          * we're out of date.  Kick off
2747                                          * rediscovery.
2748                                          */
2749                                         tid = timeout(fcp_reconfigure_luns,
2750                                             (caddr_t)ptgt, drv_usectohz(1));
2751 
2752                                         ptgt->tgt_tid = tid;
2753                                         ptgt->tgt_state |= FCP_TGT_BUSY;
2754                                         ret = EBUSY;
2755                                         reconfig_pending = TRUE;
2756                                 }
2757                                 mutex_exit(&ptgt->tgt_mutex);
2758                         }
2759                 }
2760 
2761                 /*
2762                  * Calc residuals and buffer lengths
2763                  */
2764 
2765                 if (ret == 0) {
2766                         buf_len = fscsi->scsi_buflen;
2767                         fscsi->scsi_bufresid = 0;
2768                         if (rsp->fcp_u.fcp_status.resid_under) {
2769                                 if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2770                                         fscsi->scsi_bufresid = rsp->fcp_resid;
2771                                 } else {
2772                                         cmn_err(CE_WARN, "fcp: bad residue %x "
2773                                             "for txfer len %x", rsp->fcp_resid,
2774                                             fscsi->scsi_buflen);
2775                                         fscsi->scsi_bufresid =
2776                                             fscsi->scsi_buflen;
2777                                 }
2778                                 buf_len -= fscsi->scsi_bufresid;
2779                         }
2780                         if (rsp->fcp_u.fcp_status.resid_over) {
2781                                 fscsi->scsi_bufresid = -rsp->fcp_resid;
2782                         }
2783 
2784                         fscsi->scsi_rqresid  = fscsi->scsi_rqlen - sense_len;
2785                         if (fscsi->scsi_rqlen < sense_len) {
2786                                 sense_len = fscsi->scsi_rqlen;
2787                         }
2788 
2789                         fscsi->scsi_fc_rspcode       = 0;
2790                         if (rsp->fcp_u.fcp_status.rsp_len_set) {
2791                                 fscsi->scsi_fc_rspcode       = rsp_info->rsp_code;
2792                         }
2793                         fscsi->scsi_pkt_state        = fpkt->pkt_state;
2794                         fscsi->scsi_pkt_action       = fpkt->pkt_action;
2795                         fscsi->scsi_pkt_reason       = fpkt->pkt_reason;
2796 
2797                         /*
2798                          * Copy data and request sense
2799                          *
2800                          * Data must be copied by using the FCP_CP_IN macro.
2801                          * This will ensure the proper byte order since the data
2802                          * is being copied directly from the memory mapped
2803                          * device register.
2804                          *
2805                          * The response (and request sense) will be in the
2806                          * correct byte order.  No special copy is necessary.
2807                          */
2808 
2809                         if (buf_len) {
2810                                 FCP_CP_IN(fpkt->pkt_data,
2811                                     fscsi->scsi_bufaddr,
2812                                     fpkt->pkt_data_acc,
2813                                     buf_len);
2814                         }
2815                         bcopy((void *)rsp_sense,
2816                             (void *)fscsi->scsi_rqbufaddr,
2817                             sense_len);
2818                 }
2819         }
2820 
2821         /*
2822          * Cleanup transport data structures if icmd was alloc-ed
2823          * So, cleanup happens in the same thread that icmd was alloc-ed
2824          */
2825         if (icmd != NULL) {
2826                 fcp_ipkt_sema_cleanup(icmd);
2827         }
2828 
2829         /* restore pm busy/idle status */
2830         if (port_busy) {
2831                 fc_ulp_idle_port(pptr->port_fp_handle);
2832         }
2833 
2834         /*
2835          * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2836          * flag, it'll be cleared when the reconfig is complete.
2837          */
2838         if ((ptgt != NULL) && !reconfig_pending) {
2839                 /*
2840                  * If target was created,
2841                  */
2842                 if (target_created) {
2843                         mutex_enter(&ptgt->tgt_mutex);
2844                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2845                         mutex_exit(&ptgt->tgt_mutex);
2846                 } else {
2847                         /*
2848                          * De-mark target as busy
2849                          */
2850                         mutex_enter(&ptgt->tgt_mutex);
2851                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2852                         mutex_exit(&ptgt->tgt_mutex);
2853                 }
2854         }
2855         return (ret);
2856 }
2857 
2858 
2859 static int
2860 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2861     fc_packet_t *fpkt)
2862 {
2863         uchar_t                 *lun_string;
2864         uint16_t                lun_num, i;
2865         int                     num_luns;
2866         int                     actual_luns;
2867         int                     num_masked_luns;
2868         int                     lun_buflen;
2869         struct fcp_lun  *plun   = NULL;
2870         struct fcp_reportlun_resp       *report_lun;
2871         uint8_t                 reconfig_needed = FALSE;
2872         uint8_t                 lun_exists = FALSE;
2873         fcp_port_t                      *pptr            = ptgt->tgt_port;
2874 
2875         report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2876 
2877         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2878             fpkt->pkt_datalen);
2879 
2880         /* get number of luns (which is supplied as LUNS * 8) */
2881         num_luns = BE_32(report_lun->num_lun) >> 3;
2882 
2883         /*
2884          * Figure out exactly how many lun strings our response buffer
2885          * can hold.
2886          */
2887         lun_buflen = (fpkt->pkt_datalen -
2888             2 * sizeof (uint32_t)) / sizeof (longlong_t);
2889 
2890         /*
2891          * Is our response buffer full or not? We don't want to
2892          * potentially walk beyond the number of luns we have.
2893          */
2894         if (num_luns <= lun_buflen) {
2895                 actual_luns = num_luns;
2896         } else {
2897                 actual_luns = lun_buflen;
2898         }
2899 
2900         mutex_enter(&ptgt->tgt_mutex);
2901 
2902         /* Scan each lun to see if we have masked it. */
2903         num_masked_luns = 0;
2904         if (fcp_lun_blacklist != NULL) {
2905                 for (i = 0; i < actual_luns; i++) {
2906                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2907                         switch (lun_string[0] & 0xC0) {
2908                         case FCP_LUN_ADDRESSING:
2909                         case FCP_PD_ADDRESSING:
2910                         case FCP_VOLUME_ADDRESSING:
2911                                 lun_num = ((lun_string[0] & 0x3F) << 8)
2912                                     | lun_string[1];
2913                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
2914                                     lun_num) == TRUE) {
2915                                         num_masked_luns++;
2916                                 }
2917                                 break;
2918                         default:
2919                                 break;
2920                         }
2921                 }
2922         }
2923 
2924         /*
2925          * The quick and easy check.  If the number of LUNs reported
2926          * doesn't match the number we currently know about, we need
2927          * to reconfigure.
2928          */
2929         if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2930                 mutex_exit(&ptgt->tgt_mutex);
2931                 kmem_free(report_lun, fpkt->pkt_datalen);
2932                 return (TRUE);
2933         }
2934 
2935         /*
2936          * If the quick and easy check doesn't turn up anything, we walk
2937          * the list of luns from the REPORT_LUN response and look for
2938          * any luns we don't know about.  If we find one, we know we need
2939          * to reconfigure. We will skip LUNs that are masked because of the
2940          * blacklist.
2941          */
2942         for (i = 0; i < actual_luns; i++) {
2943                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2944                 lun_exists = FALSE;
2945                 switch (lun_string[0] & 0xC0) {
2946                 case FCP_LUN_ADDRESSING:
2947                 case FCP_PD_ADDRESSING:
2948                 case FCP_VOLUME_ADDRESSING:
2949                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2950 
2951                         if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2952                             &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2953                                 lun_exists = TRUE;
2954                                 break;
2955                         }
2956 
2957                         for (plun = ptgt->tgt_lun; plun;
2958                             plun = plun->lun_next) {
2959                                 if (plun->lun_num == lun_num) {
2960                                         lun_exists = TRUE;
2961                                         break;
2962                                 }
2963                         }
2964                         break;
2965                 default:
2966                         break;
2967                 }
2968 
2969                 if (lun_exists == FALSE) {
2970                         reconfig_needed = TRUE;
2971                         break;
2972                 }
2973         }
2974 
2975         mutex_exit(&ptgt->tgt_mutex);
2976         kmem_free(report_lun, fpkt->pkt_datalen);
2977 
2978         return (reconfig_needed);
2979 }
2980 
2981 /*
2982  * This function is called by fcp_handle_page83 and uses inquiry response data
2983  * stored in plun->lun_inq to determine whether or not a device is a member of
2984  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2985  * otherwise 1.
2986  */
2987 static int
2988 fcp_symmetric_device_probe(struct fcp_lun *plun)
2989 {
2990         struct scsi_inquiry     *stdinq = &plun->lun_inq;
2991         char                    *devidptr;
2992         int                     i, len;
2993 
2994         for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2995                 devidptr = fcp_symmetric_disk_table[i];
2996                 len = (int)strlen(devidptr);
2997 
2998                 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
2999                         return (0);
3000                 }
3001         }
3002         return (1);
3003 }
3004 
3005 
3006 /*
3007  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3008  * It basically returns the current count of # of state change callbacks
3009  * i.e the value of tgt_change_cnt.
3010  *
3011  * INPUT:
3012  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3013  *   fcp_ioctl.listlen  -> 1
3014  *   fcp_ioctl.list     -> Pointer to a 32 bit integer
3015  */
3016 /*ARGSUSED2*/
3017 static int
3018 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3019 {
3020         int                     ret;
3021         uint32_t                link_cnt;
3022         struct fcp_ioctl        fioctl;
3023         struct fcp_port *pptr = NULL;
3024 
3025         if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3026             &pptr)) != 0) {
3027                 return (ret);
3028         }
3029 
3030         ASSERT(pptr != NULL);
3031 
3032         if (fioctl.listlen != 1) {
3033                 return (EINVAL);
3034         }
3035 
3036         mutex_enter(&pptr->port_mutex);
3037         if (pptr->port_state & FCP_STATE_OFFLINE) {
3038                 mutex_exit(&pptr->port_mutex);
3039                 return (ENXIO);
3040         }
3041 
3042         /*
3043          * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3044          * When the fcp initially attaches to the port and there are nothing
3045          * hanging out of the port or if there was a repeat offline state change
3046          * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3047          * In the latter case, port_tmp_cnt will be non-zero and that is how we
3048          * will differentiate the 2 cases.
3049          */
3050         if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3051                 mutex_exit(&pptr->port_mutex);
3052                 return (ENXIO);
3053         }
3054 
3055         link_cnt = pptr->port_link_cnt;
3056         mutex_exit(&pptr->port_mutex);
3057 
3058         if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3059                 return (EFAULT);
3060         }
3061 
3062 #ifdef  _MULTI_DATAMODEL
3063         switch (ddi_model_convert_from(mode & FMODELS)) {
3064         case DDI_MODEL_ILP32: {
3065                 struct fcp32_ioctl f32_ioctl;
3066 
3067                 f32_ioctl.fp_minor = fioctl.fp_minor;
3068                 f32_ioctl.listlen = fioctl.listlen;
3069                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3070                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3071                     sizeof (struct fcp32_ioctl), mode)) {
3072                         return (EFAULT);
3073                 }
3074                 break;
3075         }
3076         case DDI_MODEL_NONE:
3077                 if (ddi_copyout((void *)&fioctl, (void *)data,
3078                     sizeof (struct fcp_ioctl), mode)) {
3079                         return (EFAULT);
3080                 }
3081                 break;
3082         }
3083 #else   /* _MULTI_DATAMODEL */
3084 
3085         if (ddi_copyout((void *)&fioctl, (void *)data,
3086             sizeof (struct fcp_ioctl), mode)) {
3087                 return (EFAULT);
3088         }
3089 #endif  /* _MULTI_DATAMODEL */
3090 
3091         return (0);
3092 }
3093 
3094 /*
3095  * This function copies the fcp_ioctl structure passed in from user land
3096  * into kernel land. Handles 32 bit applications.
3097  */
3098 /*ARGSUSED*/
3099 static int
3100 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3101     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3102 {
3103         struct fcp_port *t_pptr;
3104 
3105 #ifdef  _MULTI_DATAMODEL
3106         switch (ddi_model_convert_from(mode & FMODELS)) {
3107         case DDI_MODEL_ILP32: {
3108                 struct fcp32_ioctl f32_ioctl;
3109 
3110                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3111                     sizeof (struct fcp32_ioctl), mode)) {
3112                         return (EFAULT);
3113                 }
3114                 fioctl->fp_minor = f32_ioctl.fp_minor;
3115                 fioctl->listlen = f32_ioctl.listlen;
3116                 fioctl->list = (caddr_t)(long)f32_ioctl.list;
3117                 break;
3118         }
3119         case DDI_MODEL_NONE:
3120                 if (ddi_copyin((void *)data, (void *)fioctl,
3121                     sizeof (struct fcp_ioctl), mode)) {
3122                         return (EFAULT);
3123                 }
3124                 break;
3125         }
3126 
3127 #else   /* _MULTI_DATAMODEL */
3128         if (ddi_copyin((void *)data, (void *)fioctl,
3129             sizeof (struct fcp_ioctl), mode)) {
3130                 return (EFAULT);
3131         }
3132 #endif  /* _MULTI_DATAMODEL */
3133 
3134         /*
3135          * Right now we can assume that the minor number matches with
3136          * this instance of fp. If this changes we will need to
3137          * revisit this logic.
3138          */
3139         mutex_enter(&fcp_global_mutex);
3140         t_pptr = fcp_port_head;
3141         while (t_pptr) {
3142                 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3143                         break;
3144                 } else {
3145                         t_pptr = t_pptr->port_next;
3146                 }
3147         }
3148         *pptr = t_pptr;
3149         mutex_exit(&fcp_global_mutex);
3150         if (t_pptr == NULL) {
3151                 return (ENXIO);
3152         }
3153 
3154         return (0);
3155 }
3156 
3157 /*
3158  *     Function: fcp_port_create_tgt
3159  *
3160  *  Description: As the name suggest this function creates the target context
3161  *               specified by the the WWN provided by the caller.  If the
3162  *               creation goes well and the target is known by fp/fctl a PLOGI
3163  *               followed by a PRLI are issued.
3164  *
3165  *     Argument: pptr           fcp port structure
3166  *               pwwn           WWN of the target
3167  *               ret_val        Address of the return code.  It could be:
3168  *                              EIO, ENOMEM or 0.
3169  *               fc_status      PLOGI or PRLI status completion
3170  *               fc_pkt_state   PLOGI or PRLI state completion
3171  *               fc_pkt_reason  PLOGI or PRLI reason completion
3172  *               fc_pkt_action  PLOGI or PRLI action completion
3173  *
3174  * Return Value: NULL if it failed
3175  *               Target structure address if it succeeds
3176  */
3177 static struct fcp_tgt *
3178 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3179     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3180 {
3181         struct fcp_tgt  *ptgt = NULL;
3182         fc_portmap_t            devlist;
3183         int                     lcount;
3184         int                     error;
3185 
3186         *ret_val = 0;
3187 
3188         /*
3189          * Check FC port device & get port map
3190          */
3191         if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3192             &error, 1) == NULL) {
3193                 *ret_val = EIO;
3194         } else {
3195                 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3196                     &devlist) != FC_SUCCESS) {
3197                         *ret_val = EIO;
3198                 }
3199         }
3200 
3201         /* Set port map flags */
3202         devlist.map_type = PORT_DEVICE_USER_CREATE;
3203 
3204         /* Allocate target */
3205         if (*ret_val == 0) {
3206                 lcount = pptr->port_link_cnt;
3207                 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3208                 if (ptgt == NULL) {
3209                         fcp_log(CE_WARN, pptr->port_dip,
3210                             "!FC target allocation failed");
3211                         *ret_val = ENOMEM;
3212                 } else {
3213                         /* Setup target */
3214                         mutex_enter(&ptgt->tgt_mutex);
3215 
3216                         ptgt->tgt_statec_cause       = FCP_CAUSE_TGT_CHANGE;
3217                         ptgt->tgt_tmp_cnt    = 1;
3218                         ptgt->tgt_d_id               = devlist.map_did.port_id;
3219                         ptgt->tgt_hard_addr  =
3220                             devlist.map_hard_addr.hard_addr;
3221                         ptgt->tgt_pd_handle  = devlist.map_pd;
3222                         ptgt->tgt_fca_dev    = NULL;
3223 
3224                         bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3225                             FC_WWN_SIZE);
3226                         bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3227                             FC_WWN_SIZE);
3228 
3229                         mutex_exit(&ptgt->tgt_mutex);
3230                 }
3231         }
3232 
3233         /* Release global mutex for PLOGI and PRLI */
3234         mutex_exit(&fcp_global_mutex);
3235 
3236         /* Send PLOGI (If necessary) */
3237         if (*ret_val == 0) {
3238                 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3239                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3240         }
3241 
3242         /* Send PRLI (If necessary) */
3243         if (*ret_val == 0) {
3244                 *ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3245                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3246         }
3247 
3248         mutex_enter(&fcp_global_mutex);
3249 
3250         return (ptgt);
3251 }
3252 
3253 /*
3254  *     Function: fcp_tgt_send_plogi
3255  *
3256  *  Description: This function sends a PLOGI to the target specified by the
3257  *               caller and waits till it completes.
3258  *
3259  *     Argument: ptgt           Target to send the plogi to.
3260  *               fc_status      Status returned by fp/fctl in the PLOGI request.
3261  *               fc_pkt_state   State returned by fp/fctl in the PLOGI request.
3262  *               fc_pkt_reason  Reason returned by fp/fctl in the PLOGI request.
3263  *               fc_pkt_action  Action returned by fp/fctl in the PLOGI request.
3264  *
3265  * Return Value: 0
3266  *               ENOMEM
3267  *               EIO
3268  *
3269  *      Context: User context.
3270  */
3271 static int
3272 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3273     int *fc_pkt_reason, int *fc_pkt_action)
3274 {
3275         struct fcp_port *pptr;
3276         struct fcp_ipkt *icmd;
3277         struct fc_packet        *fpkt;
3278         fc_frame_hdr_t          *hp;
3279         struct la_els_logi      logi;
3280         int                     tcount;
3281         int                     lcount;
3282         int                     ret, login_retval = ~FC_SUCCESS;
3283 
3284         ret = 0;
3285 
3286         pptr = ptgt->tgt_port;
3287 
3288         lcount = pptr->port_link_cnt;
3289         tcount = ptgt->tgt_change_cnt;
3290 
3291         /* Alloc internal packet */
3292         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3293             sizeof (la_els_logi_t), 0,
3294             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3295             lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3296 
3297         if (icmd == NULL) {
3298                 ret = ENOMEM;
3299         } else {
3300                 /*
3301                  * Setup internal packet as sema sync
3302                  */
3303                 fcp_ipkt_sema_init(icmd);
3304 
3305                 /*
3306                  * Setup internal packet (icmd)
3307                  */
3308                 icmd->ipkt_lun               = NULL;
3309                 icmd->ipkt_restart   = 0;
3310                 icmd->ipkt_retries   = 0;
3311                 icmd->ipkt_opcode    = LA_ELS_PLOGI;
3312 
3313                 /*
3314                  * Setup fc_packet
3315                  */
3316                 fpkt = icmd->ipkt_fpkt;
3317 
3318                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
3319                 fpkt->pkt_tran_type  = FC_PKT_EXCHANGE;
3320                 fpkt->pkt_timeout    = FCP_ELS_TIMEOUT;
3321 
3322                 /*
3323                  * Setup FC frame header
3324                  */
3325                 hp = &fpkt->pkt_cmd_fhdr;
3326 
3327                 hp->s_id     = pptr->port_id;     /* source ID */
3328                 hp->d_id     = ptgt->tgt_d_id;    /* dest ID */
3329                 hp->r_ctl    = R_CTL_ELS_REQ;
3330                 hp->type     = FC_TYPE_EXTENDED_LS;
3331                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3332                 hp->seq_id   = 0;
3333                 hp->rsvd     = 0;
3334                 hp->df_ctl   = 0;
3335                 hp->seq_cnt  = 0;
3336                 hp->ox_id    = 0xffff;               /* i.e. none */
3337                 hp->rx_id    = 0xffff;               /* i.e. none */
3338                 hp->ro               = 0;
3339 
3340                 /*
3341                  * Setup PLOGI
3342                  */
3343                 bzero(&logi, sizeof (struct la_els_logi));
3344                 logi.ls_code.ls_code = LA_ELS_PLOGI;
3345 
3346                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3347                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3348 
3349                 /*
3350                  * Send PLOGI
3351                  */
3352                 *fc_status = login_retval =
3353                     fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3354                 if (*fc_status != FC_SUCCESS) {
3355                         ret = EIO;
3356                 }
3357         }
3358 
3359         /*
3360          * Wait for completion
3361          */
3362         if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3363                 ret = fcp_ipkt_sema_wait(icmd);
3364 
3365                 *fc_pkt_state   = fpkt->pkt_state;
3366                 *fc_pkt_reason  = fpkt->pkt_reason;
3367                 *fc_pkt_action  = fpkt->pkt_action;
3368         }
3369 
3370         /*
3371          * Cleanup transport data structures if icmd was alloc-ed AND if there
3372          * is going to be no callback (i.e if fc_ulp_login() failed).
3373          * Otherwise, cleanup happens in callback routine.
3374          */
3375         if (icmd != NULL) {
3376                 fcp_ipkt_sema_cleanup(icmd);
3377         }
3378 
3379         return (ret);
3380 }
3381 
3382 /*
3383  *     Function: fcp_tgt_send_prli
3384  *
3385  *  Description: Does nothing as of today.
3386  *
3387  *     Argument: ptgt           Target to send the prli to.
3388  *               fc_status      Status returned by fp/fctl in the PRLI request.
3389  *               fc_pkt_state   State returned by fp/fctl in the PRLI request.
3390  *               fc_pkt_reason  Reason returned by fp/fctl in the PRLI request.
3391  *               fc_pkt_action  Action returned by fp/fctl in the PRLI request.
3392  *
3393  * Return Value: 0
3394  */
3395 /*ARGSUSED*/
3396 static int
3397 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3398     int *fc_pkt_reason, int *fc_pkt_action)
3399 {
3400         return (0);
3401 }
3402 
3403 /*
3404  *     Function: fcp_ipkt_sema_init
3405  *
3406  *  Description: Initializes the semaphore contained in the internal packet.
3407  *
3408  *     Argument: icmd   Internal packet the semaphore of which must be
3409  *                      initialized.
3410  *
3411  * Return Value: None
3412  *
3413  *      Context: User context only.
3414  */
3415 static void
3416 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3417 {
3418         struct fc_packet        *fpkt;
3419 
3420         fpkt = icmd->ipkt_fpkt;
3421 
3422         /* Create semaphore for sync */
3423         sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3424 
3425         /* Setup the completion callback */
3426         fpkt->pkt_comp = fcp_ipkt_sema_callback;
3427 }
3428 
3429 /*
3430  *     Function: fcp_ipkt_sema_wait
3431  *
3432  *  Description: Wait on the semaphore embedded in the internal packet.  The
3433  *               semaphore is released in the callback.
3434  *
3435  *     Argument: icmd   Internal packet to wait on for completion.
3436  *
3437  * Return Value: 0
3438  *               EIO
3439  *               EBUSY
3440  *               EAGAIN
3441  *
3442  *      Context: User context only.
3443  *
3444  * This function does a conversion between the field pkt_state of the fc_packet
3445  * embedded in the internal packet (icmd) and the code it returns.
3446  */
3447 static int
3448 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3449 {
3450         struct fc_packet        *fpkt;
3451         int     ret;
3452 
3453         ret = EIO;
3454         fpkt = icmd->ipkt_fpkt;
3455 
3456         /*
3457          * Wait on semaphore
3458          */
3459         sema_p(&(icmd->ipkt_sema));
3460 
3461         /*
3462          * Check the status of the FC packet
3463          */
3464         switch (fpkt->pkt_state) {
3465         case FC_PKT_SUCCESS:
3466                 ret = 0;
3467                 break;
3468         case FC_PKT_LOCAL_RJT:
3469                 switch (fpkt->pkt_reason) {
3470                 case FC_REASON_SEQ_TIMEOUT:
3471                 case FC_REASON_RX_BUF_TIMEOUT:
3472                         ret = EAGAIN;
3473                         break;
3474                 case FC_REASON_PKT_BUSY:
3475                         ret = EBUSY;
3476                         break;
3477                 }
3478                 break;
3479         case FC_PKT_TIMEOUT:
3480                 ret = EAGAIN;
3481                 break;
3482         case FC_PKT_LOCAL_BSY:
3483         case FC_PKT_TRAN_BSY:
3484         case FC_PKT_NPORT_BSY:
3485         case FC_PKT_FABRIC_BSY:
3486                 ret = EBUSY;
3487                 break;
3488         case FC_PKT_LS_RJT:
3489         case FC_PKT_BA_RJT:
3490                 switch (fpkt->pkt_reason) {
3491                 case FC_REASON_LOGICAL_BSY:
3492                         ret = EBUSY;
3493                         break;
3494                 }
3495                 break;
3496         case FC_PKT_FS_RJT:
3497                 switch (fpkt->pkt_reason) {
3498                 case FC_REASON_FS_LOGICAL_BUSY:
3499                         ret = EBUSY;
3500                         break;
3501                 }
3502                 break;
3503         }
3504 
3505         return (ret);
3506 }
3507 
3508 /*
3509  *     Function: fcp_ipkt_sema_callback
3510  *
3511  *  Description: Registered as the completion callback function for the FC
3512  *               transport when the ipkt semaphore is used for sync. This will
3513  *               cleanup the used data structures, if necessary and wake up
3514  *               the user thread to complete the transaction.
3515  *
3516  *     Argument: fpkt   FC packet (points to the icmd)
3517  *
3518  * Return Value: None
3519  *
3520  *      Context: User context only
3521  */
3522 static void
3523 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3524 {
3525         struct fcp_ipkt *icmd;
3526 
3527         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3528 
3529         /*
3530          * Wake up user thread
3531          */
3532         sema_v(&(icmd->ipkt_sema));
3533 }
3534 
3535 /*
3536  *     Function: fcp_ipkt_sema_cleanup
3537  *
3538  *  Description: Called to cleanup (if necessary) the data structures used
3539  *               when ipkt sema is used for sync.  This function will detect
3540  *               whether the caller is the last thread (via counter) and
3541  *               cleanup only if necessary.
3542  *
3543  *     Argument: icmd   Internal command packet
3544  *
3545  * Return Value: None
3546  *
3547  *      Context: User context only
3548  */
3549 static void
3550 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3551 {
3552         struct fcp_tgt  *ptgt;
3553         struct fcp_port *pptr;
3554 
3555         ptgt = icmd->ipkt_tgt;
3556         pptr = icmd->ipkt_port;
3557 
3558         /*
3559          * Acquire data structure
3560          */
3561         mutex_enter(&ptgt->tgt_mutex);
3562 
3563         /*
3564          * Destroy semaphore
3565          */
3566         sema_destroy(&(icmd->ipkt_sema));
3567 
3568         /*
3569          * Cleanup internal packet
3570          */
3571         mutex_exit(&ptgt->tgt_mutex);
3572         fcp_icmd_free(pptr, icmd);
3573 }
3574 
3575 /*
3576  *     Function: fcp_port_attach
3577  *
3578  *  Description: Called by the transport framework to resume, suspend or
3579  *               attach a new port.
3580  *
3581  *     Argument: ulph           Port handle
3582  *               *pinfo         Port information
3583  *               cmd            Command
3584  *               s_id           Port ID
3585  *
3586  * Return Value: FC_FAILURE or FC_SUCCESS
3587  */
3588 /*ARGSUSED*/
3589 static int
3590 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3591     fc_attach_cmd_t cmd, uint32_t s_id)
3592 {
3593         int     instance;
3594         int     res = FC_FAILURE; /* default result */
3595 
3596         ASSERT(pinfo != NULL);
3597 
3598         instance = ddi_get_instance(pinfo->port_dip);
3599 
3600         switch (cmd) {
3601         case FC_CMD_ATTACH:
3602                 /*
3603                  * this port instance attaching for the first time (or after
3604                  * being detached before)
3605                  */
3606                 if (fcp_handle_port_attach(ulph, pinfo, s_id,
3607                     instance) == DDI_SUCCESS) {
3608                         res = FC_SUCCESS;
3609                 } else {
3610                         ASSERT(ddi_get_soft_state(fcp_softstate,
3611                             instance) == NULL);
3612                 }
3613                 break;
3614 
3615         case FC_CMD_RESUME:
3616         case FC_CMD_POWER_UP:
3617                 /*
3618                  * this port instance was attached and the suspended and
3619                  * will now be resumed
3620                  */
3621                 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3622                     instance) == DDI_SUCCESS) {
3623                         res = FC_SUCCESS;
3624                 }
3625                 break;
3626 
3627         default:
3628                 /* shouldn't happen */
3629                 FCP_TRACE(fcp_logq, "fcp",
3630                     fcp_trace, FCP_BUF_LEVEL_2, 0,
3631                     "port_attach: unknown cmdcommand: %d", cmd);
3632                 break;
3633         }
3634 
3635         /* return result */
3636         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3637             FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3638 
3639         return (res);
3640 }
3641 
3642 
3643 /*
3644  * detach or suspend this port instance
3645  *
3646  * acquires and releases the global mutex
3647  *
3648  * acquires and releases the mutex for this port
3649  *
3650  * acquires and releases the hotplug mutex for this port
3651  */
3652 /*ARGSUSED*/
3653 static int
3654 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3655     fc_detach_cmd_t cmd)
3656 {
3657         int                     flag;
3658         int                     instance;
3659         struct fcp_port         *pptr;
3660 
3661         instance = ddi_get_instance(info->port_dip);
3662         pptr = ddi_get_soft_state(fcp_softstate, instance);
3663 
3664         switch (cmd) {
3665         case FC_CMD_SUSPEND:
3666                 FCP_DTRACE(fcp_logq, "fcp",
3667                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3668                     "port suspend called for port %d", instance);
3669                 flag = FCP_STATE_SUSPENDED;
3670                 break;
3671 
3672         case FC_CMD_POWER_DOWN:
3673                 FCP_DTRACE(fcp_logq, "fcp",
3674                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3675                     "port power down called for port %d", instance);
3676                 flag = FCP_STATE_POWER_DOWN;
3677                 break;
3678 
3679         case FC_CMD_DETACH:
3680                 FCP_DTRACE(fcp_logq, "fcp",
3681                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3682                     "port detach called for port %d", instance);
3683                 flag = FCP_STATE_DETACHING;
3684                 break;
3685 
3686         default:
3687                 /* shouldn't happen */
3688                 return (FC_FAILURE);
3689         }
3690         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3691             FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3692 
3693         return (fcp_handle_port_detach(pptr, flag, instance));
3694 }
3695 
3696 
3697 /*
3698  * called for ioctls on the transport's devctl interface, and the transport
3699  * has passed it to us
3700  *
3701  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3702  *
3703  * return FC_SUCCESS if we decide to claim the ioctl,
3704  * else return FC_UNCLAIMED
3705  *
3706  * *rval is set iff we decide to claim the ioctl
3707  */
3708 /*ARGSUSED*/
3709 static int
3710 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3711     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3712 {
3713         int                     retval = FC_UNCLAIMED;  /* return value */
3714         struct fcp_port         *pptr = NULL;           /* our soft state */
3715         struct devctl_iocdata   *dcp = NULL;            /* for devctl */
3716         dev_info_t              *cdip;
3717         mdi_pathinfo_t          *pip = NULL;
3718         char                    *ndi_nm;                /* NDI name */
3719         char                    *ndi_addr;              /* NDI addr */
3720         int                     is_mpxio, circ;
3721         int                     devi_entered = 0;
3722         clock_t                 end_time;
3723 
3724         ASSERT(rval != NULL);
3725 
3726         FCP_DTRACE(fcp_logq, "fcp",
3727             fcp_trace, FCP_BUF_LEVEL_8, 0,
3728             "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3729 
3730         /* if already claimed then forget it */
3731         if (claimed) {
3732                 /*
3733                  * for now, if this ioctl has already been claimed, then
3734                  * we just ignore it
3735                  */
3736                 return (retval);
3737         }
3738 
3739         /* get our port info */
3740         if ((pptr = fcp_get_port(port_handle)) == NULL) {
3741                 fcp_log(CE_WARN, NULL,
3742                     "!fcp:Invalid port handle handle in ioctl");
3743                 *rval = ENXIO;
3744                 return (retval);
3745         }
3746         is_mpxio = pptr->port_mpxio;
3747 
3748         switch (cmd) {
3749         case DEVCTL_BUS_GETSTATE:
3750         case DEVCTL_BUS_QUIESCE:
3751         case DEVCTL_BUS_UNQUIESCE:
3752         case DEVCTL_BUS_RESET:
3753         case DEVCTL_BUS_RESETALL:
3754 
3755         case DEVCTL_BUS_DEV_CREATE:
3756                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3757                         return (retval);
3758                 }
3759                 break;
3760 
3761         case DEVCTL_DEVICE_GETSTATE:
3762         case DEVCTL_DEVICE_OFFLINE:
3763         case DEVCTL_DEVICE_ONLINE:
3764         case DEVCTL_DEVICE_REMOVE:
3765         case DEVCTL_DEVICE_RESET:
3766                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3767                         return (retval);
3768                 }
3769 
3770                 ASSERT(dcp != NULL);
3771 
3772                 /* ensure we have a name and address */
3773                 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3774                     ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3775                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
3776                             fcp_trace, FCP_BUF_LEVEL_2, 0,
3777                             "ioctl: can't get name (%s) or addr (%s)",
3778                             ndi_nm ? ndi_nm : "<null ptr>",
3779                             ndi_addr ? ndi_addr : "<null ptr>");
3780                         ndi_dc_freehdl(dcp);
3781                         return (retval);
3782                 }
3783 
3784 
3785                 /* get our child's DIP */
3786                 ASSERT(pptr != NULL);
3787                 if (is_mpxio) {
3788                         mdi_devi_enter(pptr->port_dip, &circ);
3789                 } else {
3790                         ndi_devi_enter(pptr->port_dip, &circ);
3791                 }
3792                 devi_entered = 1;
3793 
3794                 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3795                     ndi_addr)) == NULL) {
3796                         /* Look for virtually enumerated devices. */
3797                         pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3798                         if (pip == NULL ||
3799                             ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3800                                 *rval = ENXIO;
3801                                 goto out;
3802                         }
3803                 }
3804                 break;
3805 
3806         default:
3807                 *rval = ENOTTY;
3808                 return (retval);
3809         }
3810 
3811         /* this ioctl is ours -- process it */
3812 
3813         retval = FC_SUCCESS;            /* just means we claim the ioctl */
3814 
3815         /* we assume it will be a success; else we'll set error value */
3816         *rval = 0;
3817 
3818 
3819         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3820             fcp_trace, FCP_BUF_LEVEL_8, 0,
3821             "ioctl: claiming this one");
3822 
3823         /* handle ioctls now */
3824         switch (cmd) {
3825         case DEVCTL_DEVICE_GETSTATE:
3826                 ASSERT(cdip != NULL);
3827                 ASSERT(dcp != NULL);
3828                 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3829                         *rval = EFAULT;
3830                 }
3831                 break;
3832 
3833         case DEVCTL_DEVICE_REMOVE:
3834         case DEVCTL_DEVICE_OFFLINE: {
3835                 int                     flag = 0;
3836                 int                     lcount;
3837                 int                     tcount;
3838                 struct fcp_pkt  *head = NULL;
3839                 struct fcp_lun  *plun;
3840                 child_info_t            *cip = CIP(cdip);
3841                 int                     all = 1;
3842                 struct fcp_lun  *tplun;
3843                 struct fcp_tgt  *ptgt;
3844 
3845                 ASSERT(pptr != NULL);
3846                 ASSERT(cdip != NULL);
3847 
3848                 mutex_enter(&pptr->port_mutex);
3849                 if (pip != NULL) {
3850                         cip = CIP(pip);
3851                 }
3852                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3853                         mutex_exit(&pptr->port_mutex);
3854                         *rval = ENXIO;
3855                         break;
3856                 }
3857 
3858                 head = fcp_scan_commands(plun);
3859                 if (head != NULL) {
3860                         fcp_abort_commands(head, LUN_PORT);
3861                 }
3862                 lcount = pptr->port_link_cnt;
3863                 tcount = plun->lun_tgt->tgt_change_cnt;
3864                 mutex_exit(&pptr->port_mutex);
3865 
3866                 if (cmd == DEVCTL_DEVICE_REMOVE) {
3867                         flag = NDI_DEVI_REMOVE;
3868                 }
3869 
3870                 if (is_mpxio) {
3871                         mdi_devi_exit(pptr->port_dip, circ);
3872                 } else {
3873                         ndi_devi_exit(pptr->port_dip, circ);
3874                 }
3875                 devi_entered = 0;
3876 
3877                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3878                     FCP_OFFLINE, lcount, tcount, flag);
3879 
3880                 if (*rval != NDI_SUCCESS) {
3881                         *rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3882                         break;
3883                 }
3884 
3885                 fcp_update_offline_flags(plun);
3886 
3887                 ptgt = plun->lun_tgt;
3888                 mutex_enter(&ptgt->tgt_mutex);
3889                 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3890                     tplun->lun_next) {
3891                         mutex_enter(&tplun->lun_mutex);
3892                         if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3893                                 all = 0;
3894                         }
3895                         mutex_exit(&tplun->lun_mutex);
3896                 }
3897 
3898                 if (all) {
3899                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3900                         /*
3901                          * The user is unconfiguring/offlining the device.
3902                          * If fabric and the auto configuration is set
3903                          * then make sure the user is the only one who
3904                          * can reconfigure the device.
3905                          */
3906                         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3907                             fcp_enable_auto_configuration) {
3908                                 ptgt->tgt_manual_config_only = 1;
3909                         }
3910                 }
3911                 mutex_exit(&ptgt->tgt_mutex);
3912                 break;
3913         }
3914 
3915         case DEVCTL_DEVICE_ONLINE: {
3916                 int                     lcount;
3917                 int                     tcount;
3918                 struct fcp_lun  *plun;
3919                 child_info_t            *cip = CIP(cdip);
3920 
3921                 ASSERT(cdip != NULL);
3922                 ASSERT(pptr != NULL);
3923 
3924                 mutex_enter(&pptr->port_mutex);
3925                 if (pip != NULL) {
3926                         cip = CIP(pip);
3927                 }
3928                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3929                         mutex_exit(&pptr->port_mutex);
3930                         *rval = ENXIO;
3931                         break;
3932                 }
3933                 lcount = pptr->port_link_cnt;
3934                 tcount = plun->lun_tgt->tgt_change_cnt;
3935                 mutex_exit(&pptr->port_mutex);
3936 
3937                 /*
3938                  * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3939                  * to allow the device attach to occur when the device is
3940                  * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3941                  * from the scsi_probe()).
3942                  */
3943                 mutex_enter(&LUN_TGT->tgt_mutex);
3944                 plun->lun_state |= FCP_LUN_ONLINING;
3945                 mutex_exit(&LUN_TGT->tgt_mutex);
3946 
3947                 if (is_mpxio) {
3948                         mdi_devi_exit(pptr->port_dip, circ);
3949                 } else {
3950                         ndi_devi_exit(pptr->port_dip, circ);
3951                 }
3952                 devi_entered = 0;
3953 
3954                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3955                     FCP_ONLINE, lcount, tcount, 0);
3956 
3957                 if (*rval != NDI_SUCCESS) {
3958                         /* Reset the FCP_LUN_ONLINING bit */
3959                         mutex_enter(&LUN_TGT->tgt_mutex);
3960                         plun->lun_state &= ~FCP_LUN_ONLINING;
3961                         mutex_exit(&LUN_TGT->tgt_mutex);
3962                         *rval = EIO;
3963                         break;
3964                 }
3965                 mutex_enter(&LUN_TGT->tgt_mutex);
3966                 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3967                     FCP_LUN_ONLINING);
3968                 mutex_exit(&LUN_TGT->tgt_mutex);
3969                 break;
3970         }
3971 
3972         case DEVCTL_BUS_DEV_CREATE: {
3973                 uchar_t                 *bytes = NULL;
3974                 uint_t                  nbytes;
3975                 struct fcp_tgt          *ptgt = NULL;
3976                 struct fcp_lun          *plun = NULL;
3977                 dev_info_t              *useless_dip = NULL;
3978 
3979                 *rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3980                     DEVCTL_CONSTRUCT, &useless_dip);
3981                 if (*rval != 0 || useless_dip == NULL) {
3982                         break;
3983                 }
3984 
3985                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3986                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3987                     &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3988                         *rval = EINVAL;
3989                         (void) ndi_devi_free(useless_dip);
3990                         if (bytes != NULL) {
3991                                 ddi_prop_free(bytes);
3992                         }
3993                         break;
3994                 }
3995 
3996                 *rval = fcp_create_on_demand(pptr, bytes);
3997                 if (*rval == 0) {
3998                         mutex_enter(&pptr->port_mutex);
3999                         ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4000                         if (ptgt) {
4001                                 /*
4002                                  * We now have a pointer to the target that
4003                                  * was created. Lets point to the first LUN on
4004                                  * this new target.
4005                                  */
4006                                 mutex_enter(&ptgt->tgt_mutex);
4007 
4008                                 plun = ptgt->tgt_lun;
4009                                 /*
4010                                  * There may be stale/offline LUN entries on
4011                                  * this list (this is by design) and so we have
4012                                  * to make sure we point to the first online
4013                                  * LUN
4014                                  */
4015                                 while (plun &&
4016                                     plun->lun_state & FCP_LUN_OFFLINE) {
4017                                         plun = plun->lun_next;
4018                                 }
4019 
4020                                 mutex_exit(&ptgt->tgt_mutex);
4021                         }
4022                         mutex_exit(&pptr->port_mutex);
4023                 }
4024 
4025                 if (*rval == 0 && ptgt && plun) {
4026                         mutex_enter(&plun->lun_mutex);
4027                         /*
4028                          * Allow up to fcp_lun_ready_retry seconds to
4029                          * configure all the luns behind the target.
4030                          *
4031                          * The intent here is to allow targets with long
4032                          * reboot/reset-recovery times to become available
4033                          * while limiting the maximum wait time for an
4034                          * unresponsive target.
4035                          */
4036                         end_time = ddi_get_lbolt() +
4037                             SEC_TO_TICK(fcp_lun_ready_retry);
4038 
4039                         while (ddi_get_lbolt() < end_time) {
4040                                 retval = FC_SUCCESS;
4041 
4042                                 /*
4043                                  * The new ndi interfaces for on-demand creation
4044                                  * are inflexible, Do some more work to pass on
4045                                  * a path name of some LUN (design is broken !)
4046                                  */
4047                                 if (plun->lun_cip) {
4048                                         if (plun->lun_mpxio == 0) {
4049                                                 cdip = DIP(plun->lun_cip);
4050                                         } else {
4051                                                 cdip = mdi_pi_get_client(
4052                                                     PIP(plun->lun_cip));
4053                                         }
4054                                         if (cdip == NULL) {
4055                                                 *rval = ENXIO;
4056                                                 break;
4057                                         }
4058 
4059                                         if (!i_ddi_devi_attached(cdip)) {
4060                                                 mutex_exit(&plun->lun_mutex);
4061                                                 delay(drv_usectohz(1000000));
4062                                                 mutex_enter(&plun->lun_mutex);
4063                                         } else {
4064                                                 /*
4065                                                  * This Lun is ready, lets
4066                                                  * check the next one.
4067                                                  */
4068                                                 mutex_exit(&plun->lun_mutex);
4069                                                 plun = plun->lun_next;
4070                                                 while (plun && (plun->lun_state
4071                                                     & FCP_LUN_OFFLINE)) {
4072                                                         plun = plun->lun_next;
4073                                                 }
4074                                                 if (!plun) {
4075                                                         break;
4076                                                 }
4077                                                 mutex_enter(&plun->lun_mutex);
4078                                         }
4079                                 } else {
4080                                         /*
4081                                          * lun_cip field for a valid lun
4082                                          * should never be NULL. Fail the
4083                                          * command.
4084                                          */
4085                                         *rval = ENXIO;
4086                                         break;
4087                                 }
4088                         }
4089                         if (plun) {
4090                                 mutex_exit(&plun->lun_mutex);
4091                         } else {
4092                                 char devnm[MAXNAMELEN];
4093                                 int nmlen;
4094 
4095                                 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4096                                     ddi_node_name(cdip),
4097                                     ddi_get_name_addr(cdip));
4098 
4099                                 if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4100                                     0) {
4101                                         *rval = EFAULT;
4102                                 }
4103                         }
4104                 } else {
4105                         int     i;
4106                         char    buf[25];
4107 
4108                         for (i = 0; i < FC_WWN_SIZE; i++) {
4109                                 (void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4110                         }
4111 
4112                         fcp_log(CE_WARN, pptr->port_dip,
4113                             "!Failed to create nodes for pwwn=%s; error=%x",
4114                             buf, *rval);
4115                 }
4116 
4117                 (void) ndi_devi_free(useless_dip);
4118                 ddi_prop_free(bytes);
4119                 break;
4120         }
4121 
4122         case DEVCTL_DEVICE_RESET: {
4123                 struct fcp_lun          *plun;
4124                 child_info_t            *cip = CIP(cdip);
4125 
4126                 ASSERT(cdip != NULL);
4127                 ASSERT(pptr != NULL);
4128                 mutex_enter(&pptr->port_mutex);
4129                 if (pip != NULL) {
4130                         cip = CIP(pip);
4131                 }
4132                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4133                         mutex_exit(&pptr->port_mutex);
4134                         *rval = ENXIO;
4135                         break;
4136                 }
4137                 mutex_exit(&pptr->port_mutex);
4138 
4139                 mutex_enter(&plun->lun_tgt->tgt_mutex);
4140                 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4141                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4142 
4143                         *rval = ENXIO;
4144                         break;
4145                 }
4146 
4147                 if (plun->lun_sd == NULL) {
4148                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4149 
4150                         *rval = ENXIO;
4151                         break;
4152                 }
4153                 mutex_exit(&plun->lun_tgt->tgt_mutex);
4154 
4155                 /*
4156                  * set up ap so that fcp_reset can figure out
4157                  * which target to reset
4158                  */
4159                 if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4160                     RESET_TARGET) == FALSE) {
4161                         *rval = EIO;
4162                 }
4163                 break;
4164         }
4165 
4166         case DEVCTL_BUS_GETSTATE:
4167                 ASSERT(dcp != NULL);
4168                 ASSERT(pptr != NULL);
4169                 ASSERT(pptr->port_dip != NULL);
4170                 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4171                     NDI_SUCCESS) {
4172                         *rval = EFAULT;
4173                 }
4174                 break;
4175 
4176         case DEVCTL_BUS_QUIESCE:
4177         case DEVCTL_BUS_UNQUIESCE:
4178                 *rval = ENOTSUP;
4179                 break;
4180 
4181         case DEVCTL_BUS_RESET:
4182         case DEVCTL_BUS_RESETALL:
4183                 ASSERT(pptr != NULL);
4184                 (void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4185                 break;
4186 
4187         default:
4188                 ASSERT(dcp != NULL);
4189                 *rval = ENOTTY;
4190                 break;
4191         }
4192 
4193         /* all done -- clean up and return */
4194 out:    if (devi_entered) {
4195                 if (is_mpxio) {
4196                         mdi_devi_exit(pptr->port_dip, circ);
4197                 } else {
4198                         ndi_devi_exit(pptr->port_dip, circ);
4199                 }
4200         }
4201 
4202         if (dcp != NULL) {
4203                 ndi_dc_freehdl(dcp);
4204         }
4205 
4206         return (retval);
4207 }
4208 
4209 
4210 /*ARGSUSED*/
4211 static int
4212 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4213     uint32_t claimed)
4214 {
4215         uchar_t                 r_ctl;
4216         uchar_t                 ls_code;
4217         struct fcp_port *pptr;
4218 
4219         if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4220                 return (FC_UNCLAIMED);
4221         }
4222 
4223         mutex_enter(&pptr->port_mutex);
4224         if (pptr->port_state & (FCP_STATE_DETACHING |
4225             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4226                 mutex_exit(&pptr->port_mutex);
4227                 return (FC_UNCLAIMED);
4228         }
4229         mutex_exit(&pptr->port_mutex);
4230 
4231         r_ctl = buf->ub_frame.r_ctl;
4232 
4233         switch (r_ctl & R_CTL_ROUTING) {
4234         case R_CTL_EXTENDED_SVC:
4235                 if (r_ctl == R_CTL_ELS_REQ) {
4236                         ls_code = buf->ub_buffer[0];
4237 
4238                         switch (ls_code) {
4239                         case LA_ELS_PRLI:
4240                                 /*
4241                                  * We really don't care if something fails.
4242                                  * If the PRLI was not sent out, then the
4243                                  * other end will time it out.
4244                                  */
4245                                 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4246                                         return (FC_SUCCESS);
4247                                 }
4248                                 return (FC_UNCLAIMED);
4249                                 /* NOTREACHED */
4250 
4251                         default:
4252                                 break;
4253                         }
4254                 }
4255                 /* FALLTHROUGH */
4256 
4257         default:
4258                 return (FC_UNCLAIMED);
4259         }
4260 }
4261 
4262 
4263 /*ARGSUSED*/
4264 static int
4265 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4266     uint32_t claimed)
4267 {
4268         return (FC_UNCLAIMED);
4269 }
4270 
4271 /*
4272  *     Function: fcp_statec_callback
4273  *
4274  *  Description: The purpose of this function is to handle a port state change.
4275  *               It is called from fp/fctl and, in a few instances, internally.
4276  *
4277  *     Argument: ulph           fp/fctl port handle
4278  *               port_handle    fcp_port structure
4279  *               port_state     Physical state of the port
4280  *               port_top       Topology
4281  *               *devlist       Pointer to the first entry of a table
4282  *                              containing the remote ports that can be
4283  *                              reached.
4284  *               dev_cnt        Number of entries pointed by devlist.
4285  *               port_sid       Port ID of the local port.
4286  *
4287  * Return Value: None
4288  */
4289 /*ARGSUSED*/
4290 static void
4291 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4292     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4293     uint32_t dev_cnt, uint32_t port_sid)
4294 {
4295         uint32_t                link_count;
4296         int                     map_len = 0;
4297         struct fcp_port *pptr;
4298         fcp_map_tag_t           *map_tag = NULL;
4299 
4300         if ((pptr = fcp_get_port(port_handle)) == NULL) {
4301                 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4302                 return;                 /* nothing to work with! */
4303         }
4304 
4305         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4306             fcp_trace, FCP_BUF_LEVEL_2, 0,
4307             "fcp_statec_callback: port state/dev_cnt/top ="
4308             "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4309             dev_cnt, port_top);
4310 
4311         mutex_enter(&pptr->port_mutex);
4312 
4313         /*
4314          * If a thread is in detach, don't do anything.
4315          */
4316         if (pptr->port_state & (FCP_STATE_DETACHING |
4317             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4318                 mutex_exit(&pptr->port_mutex);
4319                 return;
4320         }
4321 
4322         /*
4323          * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4324          * init_pkt is called, it knows whether or not the target's status
4325          * (or pd) might be changing.
4326          */
4327 
4328         if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4329                 pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4330         }
4331 
4332         /*
4333          * the transport doesn't allocate or probe unless being
4334          * asked to by either the applications or ULPs
4335          *
4336          * in cases where the port is OFFLINE at the time of port
4337          * attach callback and the link comes ONLINE later, for
4338          * easier automatic node creation (i.e. without you having to
4339          * go out and run the utility to perform LOGINs) the
4340          * following conditional is helpful
4341          */
4342         pptr->port_phys_state = port_state;
4343 
4344         if (dev_cnt) {
4345                 mutex_exit(&pptr->port_mutex);
4346 
4347                 map_len = sizeof (*map_tag) * dev_cnt;
4348                 map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4349                 if (map_tag == NULL) {
4350                         fcp_log(CE_WARN, pptr->port_dip,
4351                             "!fcp%d: failed to allocate for map tags; "
4352                             " state change will not be processed",
4353                             pptr->port_instance);
4354 
4355                         mutex_enter(&pptr->port_mutex);
4356                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4357                         mutex_exit(&pptr->port_mutex);
4358 
4359                         return;
4360                 }
4361 
4362                 mutex_enter(&pptr->port_mutex);
4363         }
4364 
4365         if (pptr->port_id != port_sid) {
4366                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4367                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4368                     "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4369                     port_sid);
4370                 /*
4371                  * The local port changed ID. It is the first time a port ID
4372                  * is assigned or something drastic happened.  We might have
4373                  * been unplugged and replugged on another loop or fabric port
4374                  * or somebody grabbed the AL_PA we had or somebody rezoned
4375                  * the fabric we were plugged into.
4376                  */
4377                 pptr->port_id = port_sid;
4378         }
4379 
4380         switch (FC_PORT_STATE_MASK(port_state)) {
4381         case FC_STATE_OFFLINE:
4382         case FC_STATE_RESET_REQUESTED:
4383                 /*
4384                  * link has gone from online to offline -- just update the
4385                  * state of this port to BUSY and MARKed to go offline
4386                  */
4387                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4388                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4389                     "link went offline");
4390                 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4391                         /*
4392                          * We were offline a while ago and this one
4393                          * seems to indicate that the loop has gone
4394                          * dead forever.
4395                          */
4396                         pptr->port_tmp_cnt += dev_cnt;
4397                         pptr->port_state &= ~FCP_STATE_OFFLINE;
4398                         pptr->port_state |= FCP_STATE_INIT;
4399                         link_count = pptr->port_link_cnt;
4400                         fcp_handle_devices(pptr, devlist, dev_cnt,
4401                             link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4402                 } else {
4403                         pptr->port_link_cnt++;
4404                         ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4405                         fcp_update_state(pptr, (FCP_LUN_BUSY |
4406                             FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4407                         if (pptr->port_mpxio) {
4408                                 fcp_update_mpxio_path_verifybusy(pptr);
4409                         }
4410                         pptr->port_state |= FCP_STATE_OFFLINE;
4411                         pptr->port_state &=
4412                             ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4413                         pptr->port_tmp_cnt = 0;
4414                 }
4415                 mutex_exit(&pptr->port_mutex);
4416                 break;
4417 
4418         case FC_STATE_ONLINE:
4419         case FC_STATE_LIP:
4420         case FC_STATE_LIP_LBIT_SET:
4421                 /*
4422                  * link has gone from offline to online
4423                  */
4424                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4425                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4426                     "link went online");
4427 
4428                 pptr->port_link_cnt++;
4429 
4430                 while (pptr->port_ipkt_cnt) {
4431                         mutex_exit(&pptr->port_mutex);
4432                         delay(drv_usectohz(1000000));
4433                         mutex_enter(&pptr->port_mutex);
4434                 }
4435 
4436                 pptr->port_topology = port_top;
4437 
4438                 /*
4439                  * The state of the targets and luns accessible through this
4440                  * port is updated.
4441                  */
4442                 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4443                     FCP_CAUSE_LINK_CHANGE);
4444 
4445                 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4446                 pptr->port_state |= FCP_STATE_ONLINING;
4447                 pptr->port_tmp_cnt = dev_cnt;
4448                 link_count = pptr->port_link_cnt;
4449 
4450                 pptr->port_deadline = fcp_watchdog_time +
4451                     FCP_ICMD_DEADLINE;
4452 
4453                 if (!dev_cnt) {
4454                         /*
4455                          * We go directly to the online state if no remote
4456                          * ports were discovered.
4457                          */
4458                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4459                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4460                             "No remote ports discovered");
4461 
4462                         pptr->port_state &= ~FCP_STATE_ONLINING;
4463                         pptr->port_state |= FCP_STATE_ONLINE;
4464                 }
4465 
4466                 switch (port_top) {
4467                 case FC_TOP_FABRIC:
4468                 case FC_TOP_PUBLIC_LOOP:
4469                 case FC_TOP_PRIVATE_LOOP:
4470                 case FC_TOP_PT_PT:
4471 
4472                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4473                                 fcp_retry_ns_registry(pptr, port_sid);
4474                         }
4475 
4476                         fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4477                             map_tag, FCP_CAUSE_LINK_CHANGE);
4478                         break;
4479 
4480                 default:
4481                         /*
4482                          * We got here because we were provided with an unknown
4483                          * topology.
4484                          */
4485                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4486                                 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4487                         }
4488 
4489                         pptr->port_tmp_cnt -= dev_cnt;
4490                         fcp_log(CE_WARN, pptr->port_dip,
4491                             "!unknown/unsupported topology (0x%x)", port_top);
4492                         break;
4493                 }
4494                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4495                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4496                     "Notify ssd of the reset to reinstate the reservations");
4497 
4498                 scsi_hba_reset_notify_callback(&pptr->port_mutex,
4499                     &pptr->port_reset_notify_listf);
4500 
4501                 mutex_exit(&pptr->port_mutex);
4502 
4503                 break;
4504 
4505         case FC_STATE_RESET:
4506                 ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4507                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4508                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4509                     "RESET state, waiting for Offline/Online state_cb");
4510                 mutex_exit(&pptr->port_mutex);
4511                 break;
4512 
4513         case FC_STATE_DEVICE_CHANGE:
4514                 /*
4515                  * We come here when an application has requested
4516                  * Dynamic node creation/deletion in Fabric connectivity.
4517                  */
4518                 if (pptr->port_state & (FCP_STATE_OFFLINE |
4519                     FCP_STATE_INIT)) {
4520                         /*
4521                          * This case can happen when the FCTL is in the
4522                          * process of giving us on online and the host on
4523                          * the other side issues a PLOGI/PLOGO. Ideally
4524                          * the state changes should be serialized unless
4525                          * they are opposite (online-offline).
4526                          * The transport will give us a final state change
4527                          * so we can ignore this for the time being.
4528                          */
4529                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4530                         mutex_exit(&pptr->port_mutex);
4531                         break;
4532                 }
4533 
4534                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4535                         fcp_retry_ns_registry(pptr, port_sid);
4536                 }
4537 
4538                 /*
4539                  * Extend the deadline under steady state conditions
4540                  * to provide more time for the device-change-commands
4541                  */
4542                 if (!pptr->port_ipkt_cnt) {
4543                         pptr->port_deadline = fcp_watchdog_time +
4544                             FCP_ICMD_DEADLINE;
4545                 }
4546 
4547                 /*
4548                  * There is another race condition here, where if we were
4549                  * in ONLINEING state and a devices in the map logs out,
4550                  * fp will give another state change as DEVICE_CHANGE
4551                  * and OLD. This will result in that target being offlined.
4552                  * The pd_handle is freed. If from the first statec callback
4553                  * we were going to fire a PLOGI/PRLI, the system will
4554                  * panic in fc_ulp_transport with invalid pd_handle.
4555                  * The fix is to check for the link_cnt before issuing
4556                  * any command down.
4557                  */
4558                 fcp_update_targets(pptr, devlist, dev_cnt,
4559                     FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4560 
4561                 link_count = pptr->port_link_cnt;
4562 
4563                 fcp_handle_devices(pptr, devlist, dev_cnt,
4564                     link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4565 
4566                 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4567 
4568                 mutex_exit(&pptr->port_mutex);
4569                 break;
4570 
4571         case FC_STATE_TARGET_PORT_RESET:
4572                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4573                         fcp_retry_ns_registry(pptr, port_sid);
4574                 }
4575 
4576                 /* Do nothing else */
4577                 mutex_exit(&pptr->port_mutex);
4578                 break;
4579 
4580         default:
4581                 fcp_log(CE_WARN, pptr->port_dip,
4582                     "!Invalid state change=0x%x", port_state);
4583                 mutex_exit(&pptr->port_mutex);
4584                 break;
4585         }
4586 
4587         if (map_tag) {
4588                 kmem_free(map_tag, map_len);
4589         }
4590 }
4591 
4592 /*
4593  *     Function: fcp_handle_devices
4594  *
4595  *  Description: This function updates the devices currently known by
4596  *               walking the list provided by the caller.  The list passed
4597  *               by the caller is supposed to be the list of reachable
4598  *               devices.
4599  *
4600  *     Argument: *pptr          Fcp port structure.
4601  *               *devlist       Pointer to the first entry of a table
4602  *                              containing the remote ports that can be
4603  *                              reached.
4604  *               dev_cnt        Number of entries pointed by devlist.
4605  *               link_cnt       Link state count.
4606  *               *map_tag       Array of fcp_map_tag_t structures.
4607  *               cause          What caused this function to be called.
4608  *
4609  * Return Value: None
4610  *
4611  *        Notes: The pptr->port_mutex must be held.
4612  */
4613 static void
4614 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4615     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4616 {
4617         int                     i;
4618         int                     check_finish_init = 0;
4619         fc_portmap_t            *map_entry;
4620         struct fcp_tgt  *ptgt = NULL;
4621 
4622         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4623             fcp_trace, FCP_BUF_LEVEL_3, 0,
4624             "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4625 
4626         if (dev_cnt) {
4627                 ASSERT(map_tag != NULL);
4628         }
4629 
4630         /*
4631          * The following code goes through the list of remote ports that are
4632          * accessible through this (pptr) local port (The list walked is the
4633          * one provided by the caller which is the list of the remote ports
4634          * currently reachable).  It checks if any of them was already
4635          * known by looking for the corresponding target structure based on
4636          * the world wide name.  If a target is part of the list it is tagged
4637          * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4638          *
4639          * Old comment
4640          * -----------
4641          * Before we drop port mutex; we MUST get the tags updated; This
4642          * two step process is somewhat slow, but more reliable.
4643          */
4644         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4645                 map_entry = &(devlist[i]);
4646 
4647                 /*
4648                  * get ptr to this map entry in our port's
4649                  * list (if any)
4650                  */
4651                 ptgt = fcp_lookup_target(pptr,
4652                     (uchar_t *)&(map_entry->map_pwwn));
4653 
4654                 if (ptgt) {
4655                         map_tag[i] = ptgt->tgt_change_cnt;
4656                         if (cause == FCP_CAUSE_LINK_CHANGE) {
4657                                 ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4658                         }
4659                 }
4660         }
4661 
4662         /*
4663          * At this point we know which devices of the new list were already
4664          * known (The field tgt_aux_state of the target structure has been
4665          * set to FCP_TGT_TAGGED).
4666          *
4667          * The following code goes through the list of targets currently known
4668          * by the local port (the list is actually a hashing table).  If a
4669          * target is found and is not tagged, it means the target cannot
4670          * be reached anymore through the local port (pptr).  It is offlined.
4671          * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4672          */
4673         for (i = 0; i < FCP_NUM_HASH; i++) {
4674                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4675                     ptgt = ptgt->tgt_next) {
4676                         mutex_enter(&ptgt->tgt_mutex);
4677                         if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4678                             (cause == FCP_CAUSE_LINK_CHANGE) &&
4679                             !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4680                                 fcp_offline_target_now(pptr, ptgt,
4681                                     link_cnt, ptgt->tgt_change_cnt, 0);
4682                         }
4683                         mutex_exit(&ptgt->tgt_mutex);
4684                 }
4685         }
4686 
4687         /*
4688          * At this point, the devices that were known but cannot be reached
4689          * anymore, have most likely been offlined.
4690          *
4691          * The following section of code seems to go through the list of
4692          * remote ports that can now be reached.  For every single one it
4693          * checks if it is already known or if it is a new port.
4694          */
4695         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4696 
4697                 if (check_finish_init) {
4698                         ASSERT(i > 0);
4699                         (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4700                             map_tag[i - 1], cause);
4701                         check_finish_init = 0;
4702                 }
4703 
4704                 /* get a pointer to this map entry */
4705                 map_entry = &(devlist[i]);
4706 
4707                 /*
4708                  * Check for the duplicate map entry flag. If we have marked
4709                  * this entry as a duplicate we skip it since the correct
4710                  * (perhaps even same) state change will be encountered
4711                  * later in the list.
4712                  */
4713                 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4714                         continue;
4715                 }
4716 
4717                 /* get ptr to this map entry in our port's list (if any) */
4718                 ptgt = fcp_lookup_target(pptr,
4719                     (uchar_t *)&(map_entry->map_pwwn));
4720 
4721                 if (ptgt) {
4722                         /*
4723                          * This device was already known.  The field
4724                          * tgt_aux_state is reset (was probably set to
4725                          * FCP_TGT_TAGGED previously in this routine).
4726                          */
4727                         ptgt->tgt_aux_state = 0;
4728                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4729                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4730                             "handle_devices: map did/state/type/flags = "
4731                             "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4732                             "tgt_state=%d",
4733                             map_entry->map_did.port_id, map_entry->map_state,
4734                             map_entry->map_type, map_entry->map_flags,
4735                             ptgt->tgt_d_id, ptgt->tgt_state);
4736                 }
4737 
4738                 if (map_entry->map_type == PORT_DEVICE_OLD ||
4739                     map_entry->map_type == PORT_DEVICE_NEW ||
4740                     map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4741                     map_entry->map_type == PORT_DEVICE_CHANGED) {
4742                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4743                             fcp_trace, FCP_BUF_LEVEL_2, 0,
4744                             "map_type=%x, did = %x",
4745                             map_entry->map_type,
4746                             map_entry->map_did.port_id);
4747                 }
4748 
4749                 switch (map_entry->map_type) {
4750                 case PORT_DEVICE_NOCHANGE:
4751                 case PORT_DEVICE_USER_CREATE:
4752                 case PORT_DEVICE_USER_LOGIN:
4753                 case PORT_DEVICE_NEW:
4754                 case PORT_DEVICE_REPORTLUN_CHANGED:
4755                         FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4756 
4757                         if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4758                             link_cnt, (ptgt) ? map_tag[i] : 0,
4759                             cause) == TRUE) {
4760 
4761                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4762                                     FCP_TGT_TRACE_2);
4763                                 check_finish_init++;
4764                         }
4765                         break;
4766 
4767                 case PORT_DEVICE_OLD:
4768                         if (ptgt != NULL) {
4769                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4770                                     FCP_TGT_TRACE_3);
4771 
4772                                 mutex_enter(&ptgt->tgt_mutex);
4773                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4774                                         /*
4775                                          * Must do an in-line wait for I/Os
4776                                          * to get drained
4777                                          */
4778                                         mutex_exit(&ptgt->tgt_mutex);
4779                                         mutex_exit(&pptr->port_mutex);
4780 
4781                                         mutex_enter(&ptgt->tgt_mutex);
4782                                         while (ptgt->tgt_ipkt_cnt ||
4783                                             fcp_outstanding_lun_cmds(ptgt)
4784                                             == FC_SUCCESS) {
4785                                                 mutex_exit(&ptgt->tgt_mutex);
4786                                                 delay(drv_usectohz(1000000));
4787                                                 mutex_enter(&ptgt->tgt_mutex);
4788                                         }
4789                                         mutex_exit(&ptgt->tgt_mutex);
4790 
4791                                         mutex_enter(&pptr->port_mutex);
4792                                         mutex_enter(&ptgt->tgt_mutex);
4793 
4794                                         (void) fcp_offline_target(pptr, ptgt,
4795                                             link_cnt, map_tag[i], 0, 0);
4796                                 }
4797                                 mutex_exit(&ptgt->tgt_mutex);
4798                         }
4799                         check_finish_init++;
4800                         break;
4801 
4802                 case PORT_DEVICE_USER_DELETE:
4803                 case PORT_DEVICE_USER_LOGOUT:
4804                         if (ptgt != NULL) {
4805                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4806                                     FCP_TGT_TRACE_4);
4807 
4808                                 mutex_enter(&ptgt->tgt_mutex);
4809                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4810                                         (void) fcp_offline_target(pptr, ptgt,
4811                                             link_cnt, map_tag[i], 1, 0);
4812                                 }
4813                                 mutex_exit(&ptgt->tgt_mutex);
4814                         }
4815                         check_finish_init++;
4816                         break;
4817 
4818                 case PORT_DEVICE_CHANGED:
4819                         if (ptgt != NULL) {
4820                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4821                                     FCP_TGT_TRACE_5);
4822 
4823                                 if (fcp_device_changed(pptr, ptgt,
4824                                     map_entry, link_cnt, map_tag[i],
4825                                     cause) == TRUE) {
4826                                         check_finish_init++;
4827                                 }
4828                         } else {
4829                                 if (fcp_handle_mapflags(pptr, ptgt,
4830                                     map_entry, link_cnt, 0, cause) == TRUE) {
4831                                         check_finish_init++;
4832                                 }
4833                         }
4834                         break;
4835 
4836                 default:
4837                         fcp_log(CE_WARN, pptr->port_dip,
4838                             "!Invalid map_type=0x%x", map_entry->map_type);
4839                         check_finish_init++;
4840                         break;
4841                 }
4842         }
4843 
4844         if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4845                 ASSERT(i > 0);
4846                 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4847                     map_tag[i-1], cause);
4848         } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4849                 fcp_offline_all(pptr, link_cnt, cause);
4850         }
4851 }
4852 
4853 static int
4854 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4855 {
4856         struct fcp_lun  *plun;
4857         struct fcp_port *pptr;
4858         int              rscn_count;
4859         int              lun0_newalloc;
4860         int              ret  = TRUE;
4861 
4862         ASSERT(ptgt);
4863         pptr = ptgt->tgt_port;
4864         lun0_newalloc = 0;
4865         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4866                 /*
4867                  * no LUN struct for LUN 0 yet exists,
4868                  * so create one
4869                  */
4870                 plun = fcp_alloc_lun(ptgt);
4871                 if (plun == NULL) {
4872                         fcp_log(CE_WARN, pptr->port_dip,
4873                             "!Failed to allocate lun 0 for"
4874                             " D_ID=%x", ptgt->tgt_d_id);
4875                         return (ret);
4876                 }
4877                 lun0_newalloc = 1;
4878         }
4879 
4880         mutex_enter(&ptgt->tgt_mutex);
4881         /*
4882          * consider lun 0 as device not connected if it is
4883          * offlined or newly allocated
4884          */
4885         if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4886                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4887         }
4888         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4889         plun->lun_state &= ~FCP_LUN_OFFLINE;
4890         ptgt->tgt_lun_cnt = 1;
4891         ptgt->tgt_report_lun_cnt = 0;
4892         mutex_exit(&ptgt->tgt_mutex);
4893 
4894         rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4895         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4896             sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4897             ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4898                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4899                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4900                     "to D_ID=%x", ptgt->tgt_d_id);
4901         } else {
4902                 ret = FALSE;
4903         }
4904 
4905         return (ret);
4906 }
4907 
4908 /*
4909  *     Function: fcp_handle_mapflags
4910  *
4911  *  Description: This function creates a target structure if the ptgt passed
4912  *               is NULL.  It also kicks off the PLOGI if we are not logged
4913  *               into the target yet or the PRLI if we are logged into the
4914  *               target already.  The rest of the treatment is done in the
4915  *               callbacks of the PLOGI or PRLI.
4916  *
4917  *     Argument: *pptr          FCP Port structure.
4918  *               *ptgt          Target structure.
4919  *               *map_entry     Array of fc_portmap_t structures.
4920  *               link_cnt       Link state count.
4921  *               tgt_cnt        Target state count.
4922  *               cause          What caused this function to be called.
4923  *
4924  * Return Value: TRUE   Failed
4925  *               FALSE  Succeeded
4926  *
4927  *        Notes: pptr->port_mutex must be owned.
4928  */
4929 static int
4930 fcp_handle_mapflags(struct fcp_port     *pptr, struct fcp_tgt   *ptgt,
4931     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4932 {
4933         int                     lcount;
4934         int                     tcount;
4935         int                     ret = TRUE;
4936         int                     alloc;
4937         struct fcp_ipkt *icmd;
4938         struct fcp_lun  *pseq_lun = NULL;
4939         uchar_t                 opcode;
4940         int                     valid_ptgt_was_passed = FALSE;
4941 
4942         ASSERT(mutex_owned(&pptr->port_mutex));
4943 
4944         /*
4945          * This case is possible where the FCTL has come up and done discovery
4946          * before FCP was loaded and attached. FCTL would have discovered the
4947          * devices and later the ULP came online. In this case ULP's would get
4948          * PORT_DEVICE_NOCHANGE but target would be NULL.
4949          */
4950         if (ptgt == NULL) {
4951                 /* don't already have a target */
4952                 mutex_exit(&pptr->port_mutex);
4953                 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4954                 mutex_enter(&pptr->port_mutex);
4955 
4956                 if (ptgt == NULL) {
4957                         fcp_log(CE_WARN, pptr->port_dip,
4958                             "!FC target allocation failed");
4959                         return (ret);
4960                 }
4961                 mutex_enter(&ptgt->tgt_mutex);
4962                 ptgt->tgt_statec_cause = cause;
4963                 ptgt->tgt_tmp_cnt = 1;
4964                 mutex_exit(&ptgt->tgt_mutex);
4965         } else {
4966                 valid_ptgt_was_passed = TRUE;
4967         }
4968 
4969         /*
4970          * Copy in the target parameters
4971          */
4972         mutex_enter(&ptgt->tgt_mutex);
4973         ptgt->tgt_d_id = map_entry->map_did.port_id;
4974         ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4975         ptgt->tgt_pd_handle = map_entry->map_pd;
4976         ptgt->tgt_fca_dev = NULL;
4977 
4978         /* Copy port and node WWNs */
4979         bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4980             FC_WWN_SIZE);
4981         bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4982             FC_WWN_SIZE);
4983 
4984         if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4985             (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4986             (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4987             valid_ptgt_was_passed) {
4988                 /*
4989                  * determine if there are any tape LUNs on this target
4990                  */
4991                 for (pseq_lun = ptgt->tgt_lun;
4992                     pseq_lun != NULL;
4993                     pseq_lun = pseq_lun->lun_next) {
4994                         if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4995                             !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4996                                 fcp_update_tgt_state(ptgt, FCP_RESET,
4997                                     FCP_LUN_MARK);
4998                                 mutex_exit(&ptgt->tgt_mutex);
4999                                 return (ret);
5000                         }
5001                 }
5002         }
5003 
5004         /*
5005          * if UA'REPORT_LUN_CHANGED received,
5006          * send out REPORT LUN promptly, skip PLOGI/PRLI process
5007          */
5008         if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5009                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5010                 mutex_exit(&ptgt->tgt_mutex);
5011                 mutex_exit(&pptr->port_mutex);
5012 
5013                 ret = fcp_handle_reportlun_changed(ptgt, cause);
5014 
5015                 mutex_enter(&pptr->port_mutex);
5016                 return (ret);
5017         }
5018 
5019         /*
5020          * If ptgt was NULL when this function was entered, then tgt_node_state
5021          * was never specifically initialized but zeroed out which means
5022          * FCP_TGT_NODE_NONE.
5023          */
5024         switch (ptgt->tgt_node_state) {
5025         case FCP_TGT_NODE_NONE:
5026         case FCP_TGT_NODE_ON_DEMAND:
5027                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5028                     !fcp_enable_auto_configuration &&
5029                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5030                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5031                 } else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5032                     fcp_enable_auto_configuration &&
5033                     (ptgt->tgt_manual_config_only == 1) &&
5034                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5035                         /*
5036                          * If auto configuration is set and
5037                          * the tgt_manual_config_only flag is set then
5038                          * we only want the user to be able to change
5039                          * the state through create_on_demand.
5040                          */
5041                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5042                 } else {
5043                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5044                 }
5045                 break;
5046 
5047         case FCP_TGT_NODE_PRESENT:
5048                 break;
5049         }
5050         /*
5051          * If we are booting from a fabric device, make sure we
5052          * mark the node state appropriately for this target to be
5053          * enumerated
5054          */
5055         if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5056                 if (bcmp((caddr_t)pptr->port_boot_wwn,
5057                     (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5058                     sizeof (ptgt->tgt_port_wwn)) == 0) {
5059                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5060                 }
5061         }
5062         mutex_exit(&ptgt->tgt_mutex);
5063 
5064         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5065             fcp_trace, FCP_BUF_LEVEL_3, 0,
5066             "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5067             map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5068             map_entry->map_rscn_info.ulp_rscn_count);
5069 
5070         mutex_enter(&ptgt->tgt_mutex);
5071 
5072         /*
5073          * Reset target OFFLINE state and mark the target BUSY
5074          */
5075         ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5076         ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5077 
5078         tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5079         lcount = link_cnt;
5080 
5081         mutex_exit(&ptgt->tgt_mutex);
5082         mutex_exit(&pptr->port_mutex);
5083 
5084         /*
5085          * if we are already logged in, then we do a PRLI, else
5086          * we do a PLOGI first (to get logged in)
5087          *
5088          * We will not check if we are the PLOGI initiator
5089          */
5090         opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5091             map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5092 
5093         alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5094 
5095         icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5096             pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5097             cause, map_entry->map_rscn_info.ulp_rscn_count);
5098 
5099         if (icmd == NULL) {
5100                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5101                 /*
5102                  * We've exited port_mutex before calling fcp_icmd_alloc,
5103                  * we need to make sure we reacquire it before returning.
5104                  */
5105                 mutex_enter(&pptr->port_mutex);
5106                 return (FALSE);
5107         }
5108 
5109         /* TRUE is only returned while target is intended skipped */
5110         ret = FALSE;
5111         /* discover info about this target */
5112         if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5113             lcount, tcount, cause)) == DDI_SUCCESS) {
5114                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5115         } else {
5116                 fcp_icmd_free(pptr, icmd);
5117                 ret = TRUE;
5118         }
5119         mutex_enter(&pptr->port_mutex);
5120 
5121         return (ret);
5122 }
5123 
5124 /*
5125  *     Function: fcp_send_els
5126  *
5127  *  Description: Sends an ELS to the target specified by the caller.  Supports
5128  *               PLOGI and PRLI.
5129  *
5130  *     Argument: *pptr          Fcp port.
5131  *               *ptgt          Target to send the ELS to.
5132  *               *icmd          Internal packet
5133  *               opcode         ELS opcode
5134  *               lcount         Link state change counter
5135  *               tcount         Target state change counter
5136  *               cause          What caused the call
5137  *
5138  * Return Value: DDI_SUCCESS
5139  *               Others
5140  */
5141 static int
5142 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5143     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5144 {
5145         fc_packet_t             *fpkt;
5146         fc_frame_hdr_t          *hp;
5147         int                     internal = 0;
5148         int                     alloc;
5149         int                     cmd_len;
5150         int                     resp_len;
5151         int                     res = DDI_FAILURE; /* default result */
5152         int                     rval = DDI_FAILURE;
5153 
5154         ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5155         ASSERT(ptgt->tgt_port == pptr);
5156 
5157         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5158             fcp_trace, FCP_BUF_LEVEL_5, 0,
5159             "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5160             (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5161 
5162         if (opcode == LA_ELS_PLOGI) {
5163                 cmd_len = sizeof (la_els_logi_t);
5164                 resp_len = sizeof (la_els_logi_t);
5165         } else {
5166                 ASSERT(opcode == LA_ELS_PRLI);
5167                 cmd_len = sizeof (la_els_prli_t);
5168                 resp_len = sizeof (la_els_prli_t);
5169         }
5170 
5171         if (icmd == NULL) {
5172                 alloc = FCP_MAX(sizeof (la_els_logi_t),
5173                     sizeof (la_els_prli_t));
5174                 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5175                     pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5176                     lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5177                 if (icmd == NULL) {
5178                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5179                         return (res);
5180                 }
5181                 internal++;
5182         }
5183         fpkt = icmd->ipkt_fpkt;
5184 
5185         fpkt->pkt_cmdlen = cmd_len;
5186         fpkt->pkt_rsplen = resp_len;
5187         fpkt->pkt_datalen = 0;
5188         icmd->ipkt_retries = 0;
5189 
5190         /* fill in fpkt info */
5191         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5192         fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5193         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5194 
5195         /* get ptr to frame hdr in fpkt */
5196         hp = &fpkt->pkt_cmd_fhdr;
5197 
5198         /*
5199          * fill in frame hdr
5200          */
5201         hp->r_ctl = R_CTL_ELS_REQ;
5202         hp->s_id = pptr->port_id; /* source ID */
5203         hp->d_id = ptgt->tgt_d_id;        /* dest ID */
5204         hp->type = FC_TYPE_EXTENDED_LS;
5205         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5206         hp->seq_id = 0;
5207         hp->rsvd = 0;
5208         hp->df_ctl  = 0;
5209         hp->seq_cnt = 0;
5210         hp->ox_id = 0xffff;          /* i.e. none */
5211         hp->rx_id = 0xffff;          /* i.e. none */
5212         hp->ro = 0;
5213 
5214         /*
5215          * at this point we have a filled in cmd pkt
5216          *
5217          * fill in the respective info, then use the transport to send
5218          * the packet
5219          *
5220          * for a PLOGI call fc_ulp_login(), and
5221          * for a PRLI call fc_ulp_issue_els()
5222          */
5223         switch (opcode) {
5224         case LA_ELS_PLOGI: {
5225                 struct la_els_logi logi;
5226 
5227                 bzero(&logi, sizeof (struct la_els_logi));
5228 
5229                 hp = &fpkt->pkt_cmd_fhdr;
5230                 hp->r_ctl = R_CTL_ELS_REQ;
5231                 logi.ls_code.ls_code = LA_ELS_PLOGI;
5232                 logi.ls_code.mbz = 0;
5233 
5234                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5235                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5236 
5237                 icmd->ipkt_opcode = LA_ELS_PLOGI;
5238 
5239                 mutex_enter(&pptr->port_mutex);
5240                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5241 
5242                         mutex_exit(&pptr->port_mutex);
5243 
5244                         rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5245                         if (rval == FC_SUCCESS) {
5246                                 res = DDI_SUCCESS;
5247                                 break;
5248                         }
5249 
5250                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5251 
5252                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5253                             rval, "PLOGI");
5254                 } else {
5255                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5256                             fcp_trace, FCP_BUF_LEVEL_5, 0,
5257                             "fcp_send_els1: state change occured"
5258                             " for D_ID=0x%x", ptgt->tgt_d_id);
5259                         mutex_exit(&pptr->port_mutex);
5260                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5261                 }
5262                 break;
5263         }
5264 
5265         case LA_ELS_PRLI: {
5266                 struct la_els_prli      prli;
5267                 struct fcp_prli         *fprli;
5268 
5269                 bzero(&prli, sizeof (struct la_els_prli));
5270 
5271                 hp = &fpkt->pkt_cmd_fhdr;
5272                 hp->r_ctl = R_CTL_ELS_REQ;
5273 
5274                 /* fill in PRLI cmd ELS fields */
5275                 prli.ls_code = LA_ELS_PRLI;
5276                 prli.page_length = 0x10;        /* huh? */
5277                 prli.payload_length = sizeof (struct la_els_prli);
5278 
5279                 icmd->ipkt_opcode = LA_ELS_PRLI;
5280 
5281                 /* get ptr to PRLI service params */
5282                 fprli = (struct fcp_prli *)prli.service_params;
5283 
5284                 /* fill in service params */
5285                 fprli->type = 0x08;
5286                 fprli->resvd1 = 0;
5287                 fprli->orig_process_assoc_valid = 0;
5288                 fprli->resp_process_assoc_valid = 0;
5289                 fprli->establish_image_pair = 1;
5290                 fprli->resvd2 = 0;
5291                 fprli->resvd3 = 0;
5292                 fprli->obsolete_1 = 0;
5293                 fprli->obsolete_2 = 0;
5294                 fprli->data_overlay_allowed = 0;
5295                 fprli->initiator_fn = 1;
5296                 fprli->confirmed_compl_allowed = 1;
5297 
5298                 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5299                         fprli->target_fn = 1;
5300                 } else {
5301                         fprli->target_fn = 0;
5302                 }
5303 
5304                 fprli->retry = 1;
5305                 fprli->read_xfer_rdy_disabled = 1;
5306                 fprli->write_xfer_rdy_disabled = 0;
5307 
5308                 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5309                     fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5310 
5311                 /* issue the PRLI request */
5312 
5313                 mutex_enter(&pptr->port_mutex);
5314                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5315 
5316                         mutex_exit(&pptr->port_mutex);
5317 
5318                         rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5319                         if (rval == FC_SUCCESS) {
5320                                 res = DDI_SUCCESS;
5321                                 break;
5322                         }
5323 
5324                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5325 
5326                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5327                             rval, "PRLI");
5328                 } else {
5329                         mutex_exit(&pptr->port_mutex);
5330                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5331                 }
5332                 break;
5333         }
5334 
5335         default:
5336                 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5337                 break;
5338         }
5339 
5340         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5341             fcp_trace, FCP_BUF_LEVEL_5, 0,
5342             "fcp_send_els: returning %d", res);
5343 
5344         if (res != DDI_SUCCESS) {
5345                 if (internal) {
5346                         fcp_icmd_free(pptr, icmd);
5347                 }
5348         }
5349 
5350         return (res);
5351 }
5352 
5353 
5354 /*
5355  * called internally update the state of all of the tgts and each LUN
5356  * for this port (i.e. each target  known to be attached to this port)
5357  * if they are not already offline
5358  *
5359  * must be called with the port mutex owned
5360  *
5361  * acquires and releases the target mutexes for each target attached
5362  * to this port
5363  */
5364 void
5365 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5366 {
5367         int i;
5368         struct fcp_tgt *ptgt;
5369 
5370         ASSERT(mutex_owned(&pptr->port_mutex));
5371 
5372         for (i = 0; i < FCP_NUM_HASH; i++) {
5373                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5374                     ptgt = ptgt->tgt_next) {
5375                         mutex_enter(&ptgt->tgt_mutex);
5376                         fcp_update_tgt_state(ptgt, FCP_SET, state);
5377                         ptgt->tgt_change_cnt++;
5378                         ptgt->tgt_statec_cause = cause;
5379                         ptgt->tgt_tmp_cnt = 1;
5380                         ptgt->tgt_done = 0;
5381                         mutex_exit(&ptgt->tgt_mutex);
5382                 }
5383         }
5384 }
5385 
5386 
5387 static void
5388 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5389 {
5390         int i;
5391         int ndevs;
5392         struct fcp_tgt *ptgt;
5393 
5394         ASSERT(mutex_owned(&pptr->port_mutex));
5395 
5396         for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5397                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5398                     ptgt = ptgt->tgt_next) {
5399                         ndevs++;
5400                 }
5401         }
5402 
5403         if (ndevs == 0) {
5404                 return;
5405         }
5406         pptr->port_tmp_cnt = ndevs;
5407 
5408         for (i = 0; i < FCP_NUM_HASH; i++) {
5409                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5410                     ptgt = ptgt->tgt_next) {
5411                         (void) fcp_call_finish_init_held(pptr, ptgt,
5412                             lcount, ptgt->tgt_change_cnt, cause);
5413                 }
5414         }
5415 }
5416 
5417 /*
5418  *     Function: fcp_update_tgt_state
5419  *
5420  *  Description: This function updates the field tgt_state of a target.  That
5421  *               field is a bitmap and which bit can be set or reset
5422  *               individually.  The action applied to the target state is also
5423  *               applied to all the LUNs belonging to the target (provided the
5424  *               LUN is not offline).  A side effect of applying the state
5425  *               modification to the target and the LUNs is the field tgt_trace
5426  *               of the target and lun_trace of the LUNs is set to zero.
5427  *
5428  *
5429  *     Argument: *ptgt  Target structure.
5430  *               flag   Flag indication what action to apply (set/reset).
5431  *               state  State bits to update.
5432  *
5433  * Return Value: None
5434  *
5435  *      Context: Interrupt, Kernel or User context.
5436  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5437  *               calling this function.
5438  */
5439 void
5440 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5441 {
5442         struct fcp_lun *plun;
5443 
5444         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5445 
5446         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5447                 /* The target is not offline. */
5448                 if (flag == FCP_SET) {
5449                         ptgt->tgt_state |= state;
5450                         ptgt->tgt_trace = 0;
5451                 } else {
5452                         ptgt->tgt_state &= ~state;
5453                 }
5454 
5455                 for (plun = ptgt->tgt_lun; plun != NULL;
5456                     plun = plun->lun_next) {
5457                         if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5458                                 /* The LUN is not offline. */
5459                                 if (flag == FCP_SET) {
5460                                         plun->lun_state |= state;
5461                                         plun->lun_trace = 0;
5462                                 } else {
5463                                         plun->lun_state &= ~state;
5464                                 }
5465                         }
5466                 }
5467         }
5468 }
5469 
5470 /*
5471  *     Function: fcp_update_tgt_state
5472  *
5473  *  Description: This function updates the field lun_state of a LUN.  That
5474  *               field is a bitmap and which bit can be set or reset
5475  *               individually.
5476  *
5477  *     Argument: *plun  LUN structure.
5478  *               flag   Flag indication what action to apply (set/reset).
5479  *               state  State bits to update.
5480  *
5481  * Return Value: None
5482  *
5483  *      Context: Interrupt, Kernel or User context.
5484  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5485  *               calling this function.
5486  */
5487 void
5488 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5489 {
5490         struct fcp_tgt  *ptgt = plun->lun_tgt;
5491 
5492         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5493 
5494         if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5495                 if (flag == FCP_SET) {
5496                         plun->lun_state |= state;
5497                 } else {
5498                         plun->lun_state &= ~state;
5499                 }
5500         }
5501 }
5502 
5503 /*
5504  *     Function: fcp_get_port
5505  *
5506  *  Description: This function returns the fcp_port structure from the opaque
5507  *               handle passed by the caller.  That opaque handle is the handle
5508  *               used by fp/fctl to identify a particular local port.  That
5509  *               handle has been stored in the corresponding fcp_port
5510  *               structure.  This function is going to walk the global list of
5511  *               fcp_port structures till one has a port_fp_handle that matches
5512  *               the handle passed by the caller.  This function enters the
5513  *               mutex fcp_global_mutex while walking the global list and then
5514  *               releases it.
5515  *
5516  *     Argument: port_handle    Opaque handle that fp/fctl uses to identify a
5517  *                              particular port.
5518  *
5519  * Return Value: NULL           Not found.
5520  *               Not NULL       Pointer to the fcp_port structure.
5521  *
5522  *      Context: Interrupt, Kernel or User context.
5523  */
5524 static struct fcp_port *
5525 fcp_get_port(opaque_t port_handle)
5526 {
5527         struct fcp_port *pptr;
5528 
5529         ASSERT(port_handle != NULL);
5530 
5531         mutex_enter(&fcp_global_mutex);
5532         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5533                 if (pptr->port_fp_handle == port_handle) {
5534                         break;
5535                 }
5536         }
5537         mutex_exit(&fcp_global_mutex);
5538 
5539         return (pptr);
5540 }
5541 
5542 
5543 static void
5544 fcp_unsol_callback(fc_packet_t *fpkt)
5545 {
5546         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5547         struct fcp_port *pptr = icmd->ipkt_port;
5548 
5549         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5550                 caddr_t state, reason, action, expln;
5551 
5552                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
5553                     &action, &expln);
5554 
5555                 fcp_log(CE_WARN, pptr->port_dip,
5556                     "!couldn't post response to unsolicited request: "
5557                     " state=%s reason=%s rx_id=%x ox_id=%x",
5558                     state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5559                     fpkt->pkt_cmd_fhdr.rx_id);
5560         }
5561         fcp_icmd_free(pptr, icmd);
5562 }
5563 
5564 
5565 /*
5566  * Perform general purpose preparation of a response to an unsolicited request
5567  */
5568 static void
5569 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5570     uchar_t r_ctl, uchar_t type)
5571 {
5572         pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5573         pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5574         pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5575         pkt->pkt_cmd_fhdr.type = type;
5576         pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5577         pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5578         pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5579         pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5580         pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5581         pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5582         pkt->pkt_cmd_fhdr.ro = 0;
5583         pkt->pkt_cmd_fhdr.rsvd = 0;
5584         pkt->pkt_comp = fcp_unsol_callback;
5585         pkt->pkt_pd = NULL;
5586         pkt->pkt_ub_resp_token = (opaque_t)buf;
5587 }
5588 
5589 
5590 /*ARGSUSED*/
5591 static int
5592 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5593 {
5594         fc_packet_t             *fpkt;
5595         struct la_els_prli      prli;
5596         struct fcp_prli         *fprli;
5597         struct fcp_ipkt *icmd;
5598         struct la_els_prli      *from;
5599         struct fcp_prli         *orig;
5600         struct fcp_tgt  *ptgt;
5601         int                     tcount = 0;
5602         int                     lcount;
5603 
5604         from = (struct la_els_prli *)buf->ub_buffer;
5605         orig = (struct fcp_prli *)from->service_params;
5606         if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5607             NULL) {
5608                 mutex_enter(&ptgt->tgt_mutex);
5609                 tcount = ptgt->tgt_change_cnt;
5610                 mutex_exit(&ptgt->tgt_mutex);
5611         }
5612 
5613         mutex_enter(&pptr->port_mutex);
5614         lcount = pptr->port_link_cnt;
5615         mutex_exit(&pptr->port_mutex);
5616 
5617         if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5618             sizeof (la_els_prli_t), 0,
5619             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5620             lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5621                 return (FC_FAILURE);
5622         }
5623 
5624         fpkt = icmd->ipkt_fpkt;
5625         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5626         fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5627         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5628         fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5629         fpkt->pkt_rsplen = 0;
5630         fpkt->pkt_datalen = 0;
5631 
5632         icmd->ipkt_opcode = LA_ELS_PRLI;
5633 
5634         bzero(&prli, sizeof (struct la_els_prli));
5635         fprli = (struct fcp_prli *)prli.service_params;
5636         prli.ls_code = LA_ELS_ACC;
5637         prli.page_length = 0x10;
5638         prli.payload_length = sizeof (struct la_els_prli);
5639 
5640         /* fill in service params */
5641         fprli->type = 0x08;
5642         fprli->resvd1 = 0;
5643         fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5644         fprli->orig_process_associator = orig->orig_process_associator;
5645         fprli->resp_process_assoc_valid = 0;
5646         fprli->establish_image_pair = 1;
5647         fprli->resvd2 = 0;
5648         fprli->resvd3 = 0;
5649         fprli->obsolete_1 = 0;
5650         fprli->obsolete_2 = 0;
5651         fprli->data_overlay_allowed = 0;
5652         fprli->initiator_fn = 1;
5653         fprli->confirmed_compl_allowed = 1;
5654 
5655         if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5656                 fprli->target_fn = 1;
5657         } else {
5658                 fprli->target_fn = 0;
5659         }
5660 
5661         fprli->retry = 1;
5662         fprli->read_xfer_rdy_disabled = 1;
5663         fprli->write_xfer_rdy_disabled = 0;
5664 
5665         /* save the unsol prli payload first */
5666         FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5667             fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5668 
5669         FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5670             fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5671 
5672         fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5673 
5674         mutex_enter(&pptr->port_mutex);
5675         if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5676                 int rval;
5677                 mutex_exit(&pptr->port_mutex);
5678 
5679                 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5680                     FC_SUCCESS) {
5681                         if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5682                             ptgt != NULL) {
5683                                 fcp_queue_ipkt(pptr, fpkt);
5684                                 return (FC_SUCCESS);
5685                         }
5686                         /* Let it timeout */
5687                         fcp_icmd_free(pptr, icmd);
5688                         return (FC_FAILURE);
5689                 }
5690         } else {
5691                 mutex_exit(&pptr->port_mutex);
5692                 fcp_icmd_free(pptr, icmd);
5693                 return (FC_FAILURE);
5694         }
5695 
5696         (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5697 
5698         return (FC_SUCCESS);
5699 }
5700 
5701 /*
5702  *     Function: fcp_icmd_alloc
5703  *
5704  *  Description: This function allocated a fcp_ipkt structure.  The pkt_comp
5705  *               field is initialized to fcp_icmd_callback.  Sometimes it is
5706  *               modified by the caller (such as fcp_send_scsi).  The
5707  *               structure is also tied to the state of the line and of the
5708  *               target at a particular time.  That link is established by
5709  *               setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5710  *               and tcount which came respectively from pptr->link_cnt and
5711  *               ptgt->tgt_change_cnt.
5712  *
5713  *     Argument: *pptr          Fcp port.
5714  *               *ptgt          Target (destination of the command).
5715  *               cmd_len        Length of the command.
5716  *               resp_len       Length of the expected response.
5717  *               data_len       Length of the data.
5718  *               nodma          Indicates weither the command and response.
5719  *                              will be transfer through DMA or not.
5720  *               lcount         Link state change counter.
5721  *               tcount         Target state change counter.
5722  *               cause          Reason that lead to this call.
5723  *
5724  * Return Value: NULL           Failed.
5725  *               Not NULL       Internal packet address.
5726  */
5727 static struct fcp_ipkt *
5728 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5729     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5730     uint32_t rscn_count)
5731 {
5732         int                     dma_setup = 0;
5733         fc_packet_t             *fpkt;
5734         struct fcp_ipkt *icmd = NULL;
5735 
5736         icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5737             pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5738             KM_NOSLEEP);
5739         if (icmd == NULL) {
5740                 fcp_log(CE_WARN, pptr->port_dip,
5741                     "!internal packet allocation failed");
5742                 return (NULL);
5743         }
5744 
5745         /*
5746          * initialize the allocated packet
5747          */
5748         icmd->ipkt_nodma = nodma;
5749         icmd->ipkt_next = icmd->ipkt_prev = NULL;
5750         icmd->ipkt_lun = NULL;
5751 
5752         icmd->ipkt_link_cnt = lcount;
5753         icmd->ipkt_change_cnt = tcount;
5754         icmd->ipkt_cause = cause;
5755 
5756         mutex_enter(&pptr->port_mutex);
5757         icmd->ipkt_port = pptr;
5758         mutex_exit(&pptr->port_mutex);
5759 
5760         /* keep track of amt of data to be sent in pkt */
5761         icmd->ipkt_cmdlen = cmd_len;
5762         icmd->ipkt_resplen = resp_len;
5763         icmd->ipkt_datalen = data_len;
5764 
5765         /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5766         icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5767 
5768         /* set pkt's private ptr to point to cmd pkt */
5769         icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5770 
5771         /* set FCA private ptr to memory just beyond */
5772         icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5773             ((char *)icmd + sizeof (struct fcp_ipkt) +
5774             pptr->port_dmacookie_sz);
5775 
5776         /* get ptr to fpkt substruct and fill it in */
5777         fpkt = icmd->ipkt_fpkt;
5778         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5779             sizeof (struct fcp_ipkt));
5780 
5781         if (ptgt != NULL) {
5782                 icmd->ipkt_tgt = ptgt;
5783                 fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5784         }
5785 
5786         fpkt->pkt_comp = fcp_icmd_callback;
5787         fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5788         fpkt->pkt_cmdlen = cmd_len;
5789         fpkt->pkt_rsplen = resp_len;
5790         fpkt->pkt_datalen = data_len;
5791 
5792         /*
5793          * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5794          * rscn_count as fcp knows down to the transport. If a valid count was
5795          * passed into this function, we allocate memory to actually pass down
5796          * this info.
5797          *
5798          * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5799          * basically mean that fcp will not be able to help transport
5800          * distinguish if a new RSCN has come after fcp was last informed about
5801          * it. In such cases, it might lead to the problem mentioned in CR/bug #
5802          * 5068068 where the device might end up going offline in case of RSCN
5803          * storms.
5804          */
5805         fpkt->pkt_ulp_rscn_infop = NULL;
5806         if (rscn_count != FC_INVALID_RSCN_COUNT) {
5807                 fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5808                     sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5809                 if (fpkt->pkt_ulp_rscn_infop == NULL) {
5810                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5811                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5812                             "Failed to alloc memory to pass rscn info");
5813                 }
5814         }
5815 
5816         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5817                 fc_ulp_rscn_info_t      *rscnp;
5818 
5819                 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5820                 rscnp->ulp_rscn_count = rscn_count;
5821         }
5822 
5823         if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5824                 goto fail;
5825         }
5826         dma_setup++;
5827 
5828         /*
5829          * Must hold target mutex across setting of pkt_pd and call to
5830          * fc_ulp_init_packet to ensure the handle to the target doesn't go
5831          * away while we're not looking.
5832          */
5833         if (ptgt != NULL) {
5834                 mutex_enter(&ptgt->tgt_mutex);
5835                 fpkt->pkt_pd = ptgt->tgt_pd_handle;
5836 
5837                 /* ask transport to do its initialization on this pkt */
5838                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5839                     != FC_SUCCESS) {
5840                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5841                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5842                             "fc_ulp_init_packet failed");
5843                         mutex_exit(&ptgt->tgt_mutex);
5844                         goto fail;
5845                 }
5846                 mutex_exit(&ptgt->tgt_mutex);
5847         } else {
5848                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5849                     != FC_SUCCESS) {
5850                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5851                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5852                             "fc_ulp_init_packet failed");
5853                         goto fail;
5854                 }
5855         }
5856 
5857         mutex_enter(&pptr->port_mutex);
5858         if (pptr->port_state & (FCP_STATE_DETACHING |
5859             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5860                 int rval;
5861 
5862                 mutex_exit(&pptr->port_mutex);
5863 
5864                 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5865                 ASSERT(rval == FC_SUCCESS);
5866 
5867                 goto fail;
5868         }
5869 
5870         if (ptgt != NULL) {
5871                 mutex_enter(&ptgt->tgt_mutex);
5872                 ptgt->tgt_ipkt_cnt++;
5873                 mutex_exit(&ptgt->tgt_mutex);
5874         }
5875 
5876         pptr->port_ipkt_cnt++;
5877 
5878         mutex_exit(&pptr->port_mutex);
5879 
5880         return (icmd);
5881 
5882 fail:
5883         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5884                 kmem_free(fpkt->pkt_ulp_rscn_infop,
5885                     sizeof (fc_ulp_rscn_info_t));
5886                 fpkt->pkt_ulp_rscn_infop = NULL;
5887         }
5888 
5889         if (dma_setup) {
5890                 fcp_free_dma(pptr, icmd);
5891         }
5892         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5893             (size_t)pptr->port_dmacookie_sz);
5894 
5895         return (NULL);
5896 }
5897 
5898 /*
5899  *     Function: fcp_icmd_free
5900  *
5901  *  Description: Frees the internal command passed by the caller.
5902  *
5903  *     Argument: *pptr          Fcp port.
5904  *               *icmd          Internal packet to free.
5905  *
5906  * Return Value: None
5907  */
5908 static void
5909 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5910 {
5911         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
5912 
5913         /* Let the underlying layers do their cleanup. */
5914         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5915             icmd->ipkt_fpkt);
5916 
5917         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5918                 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5919                     sizeof (fc_ulp_rscn_info_t));
5920         }
5921 
5922         fcp_free_dma(pptr, icmd);
5923 
5924         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5925             (size_t)pptr->port_dmacookie_sz);
5926 
5927         mutex_enter(&pptr->port_mutex);
5928 
5929         if (ptgt) {
5930                 mutex_enter(&ptgt->tgt_mutex);
5931                 ptgt->tgt_ipkt_cnt--;
5932                 mutex_exit(&ptgt->tgt_mutex);
5933         }
5934 
5935         pptr->port_ipkt_cnt--;
5936         mutex_exit(&pptr->port_mutex);
5937 }
5938 
5939 /*
5940  *     Function: fcp_alloc_dma
5941  *
5942  *  Description: Allocated the DMA resources required for the internal
5943  *               packet.
5944  *
5945  *     Argument: *pptr  FCP port.
5946  *               *icmd  Internal FCP packet.
5947  *               nodma  Indicates if the Cmd and Resp will be DMAed.
5948  *               flags  Allocation flags (Sleep or NoSleep).
5949  *
5950  * Return Value: FC_SUCCESS
5951  *               FC_NOMEM
5952  */
5953 static int
5954 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5955     int nodma, int flags)
5956 {
5957         int             rval;
5958         size_t          real_size;
5959         uint_t          ccount;
5960         int             bound = 0;
5961         int             cmd_resp = 0;
5962         fc_packet_t     *fpkt;
5963         ddi_dma_cookie_t        pkt_data_cookie;
5964         ddi_dma_cookie_t        *cp;
5965         uint32_t                cnt;
5966 
5967         fpkt = &icmd->ipkt_fc_packet;
5968 
5969         ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5970             fpkt->pkt_resp_dma == NULL);
5971 
5972         icmd->ipkt_nodma = nodma;
5973 
5974         if (nodma) {
5975                 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5976                 if (fpkt->pkt_cmd == NULL) {
5977                         goto fail;
5978                 }
5979 
5980                 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5981                 if (fpkt->pkt_resp == NULL) {
5982                         goto fail;
5983                 }
5984         } else {
5985                 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5986 
5987                 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5988                 if (rval == FC_FAILURE) {
5989                         ASSERT(fpkt->pkt_cmd_dma == NULL &&
5990                             fpkt->pkt_resp_dma == NULL);
5991                         goto fail;
5992                 }
5993                 cmd_resp++;
5994         }
5995 
5996         if ((fpkt->pkt_datalen != 0) &&
5997             !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
5998                 /*
5999                  * set up DMA handle and memory for the data in this packet
6000                  */
6001                 if (ddi_dma_alloc_handle(pptr->port_dip,
6002                     &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6003                     NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6004                         goto fail;
6005                 }
6006 
6007                 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6008                     &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6009                     DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6010                     &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6011                         goto fail;
6012                 }
6013 
6014                 /* was DMA mem size gotten < size asked for/needed ?? */
6015                 if (real_size < fpkt->pkt_datalen) {
6016                         goto fail;
6017                 }
6018 
6019                 /* bind DMA address and handle together */
6020                 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6021                     NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6022                     DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6023                     &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6024                         goto fail;
6025                 }
6026                 bound++;
6027 
6028                 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6029                         goto fail;
6030                 }
6031 
6032                 fpkt->pkt_data_cookie_cnt = ccount;
6033 
6034                 cp = fpkt->pkt_data_cookie;
6035                 *cp = pkt_data_cookie;
6036                 cp++;
6037 
6038                 for (cnt = 1; cnt < ccount; cnt++, cp++) {
6039                         ddi_dma_nextcookie(fpkt->pkt_data_dma,
6040                             &pkt_data_cookie);
6041                         *cp = pkt_data_cookie;
6042                 }
6043 
6044         } else if (fpkt->pkt_datalen != 0) {
6045                 /*
6046                  * If it's a pseudo FCA, then it can't support DMA even in
6047                  * SCSI data phase.
6048                  */
6049                 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6050                 if (fpkt->pkt_data == NULL) {
6051                         goto fail;
6052                 }
6053 
6054         }
6055 
6056         return (FC_SUCCESS);
6057 
6058 fail:
6059         if (bound) {
6060                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6061         }
6062 
6063         if (fpkt->pkt_data_dma) {
6064                 if (fpkt->pkt_data) {
6065                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6066                 }
6067                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6068         } else {
6069                 if (fpkt->pkt_data) {
6070                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6071                 }
6072         }
6073 
6074         if (nodma) {
6075                 if (fpkt->pkt_cmd) {
6076                         kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6077                 }
6078                 if (fpkt->pkt_resp) {
6079                         kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6080                 }
6081         } else {
6082                 if (cmd_resp) {
6083                         fcp_free_cmd_resp(pptr, fpkt);
6084                 }
6085         }
6086 
6087         return (FC_NOMEM);
6088 }
6089 
6090 
6091 static void
6092 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6093 {
6094         fc_packet_t *fpkt = icmd->ipkt_fpkt;
6095 
6096         if (fpkt->pkt_data_dma) {
6097                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6098                 if (fpkt->pkt_data) {
6099                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6100                 }
6101                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6102         } else {
6103                 if (fpkt->pkt_data) {
6104                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6105                 }
6106                 /*
6107                  * Need we reset pkt_* to zero???
6108                  */
6109         }
6110 
6111         if (icmd->ipkt_nodma) {
6112                 if (fpkt->pkt_cmd) {
6113                         kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6114                 }
6115                 if (fpkt->pkt_resp) {
6116                         kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6117                 }
6118         } else {
6119                 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6120 
6121                 fcp_free_cmd_resp(pptr, fpkt);
6122         }
6123 }
6124 
6125 /*
6126  *     Function: fcp_lookup_target
6127  *
6128  *  Description: Finds a target given a WWN.
6129  *
6130  *     Argument: *pptr  FCP port.
6131  *               *wwn   World Wide Name of the device to look for.
6132  *
6133  * Return Value: NULL           No target found
6134  *               Not NULL       Target structure
6135  *
6136  *      Context: Interrupt context.
6137  *               The mutex pptr->port_mutex must be owned.
6138  */
6139 /* ARGSUSED */
6140 static struct fcp_tgt *
6141 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6142 {
6143         int                     hash;
6144         struct fcp_tgt  *ptgt;
6145 
6146         ASSERT(mutex_owned(&pptr->port_mutex));
6147 
6148         hash = FCP_HASH(wwn);
6149 
6150         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6151             ptgt = ptgt->tgt_next) {
6152                 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6153                     bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6154                     sizeof (ptgt->tgt_port_wwn)) == 0) {
6155                         break;
6156                 }
6157         }
6158 
6159         return (ptgt);
6160 }
6161 
6162 
6163 /*
6164  * Find target structure given a port identifier
6165  */
6166 static struct fcp_tgt *
6167 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6168 {
6169         fc_portid_t             port_id;
6170         la_wwn_t                pwwn;
6171         struct fcp_tgt  *ptgt = NULL;
6172 
6173         port_id.priv_lilp_posit = 0;
6174         port_id.port_id = d_id;
6175         if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6176             &pwwn) == FC_SUCCESS) {
6177                 mutex_enter(&pptr->port_mutex);
6178                 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6179                 mutex_exit(&pptr->port_mutex);
6180         }
6181 
6182         return (ptgt);
6183 }
6184 
6185 
6186 /*
6187  * the packet completion callback routine for info cmd pkts
6188  *
6189  * this means fpkt pts to a response to either a PLOGI or a PRLI
6190  *
6191  * if there is an error an attempt is made to call a routine to resend
6192  * the command that failed
6193  */
6194 static void
6195 fcp_icmd_callback(fc_packet_t *fpkt)
6196 {
6197         struct fcp_ipkt *icmd;
6198         struct fcp_port *pptr;
6199         struct fcp_tgt  *ptgt;
6200         struct la_els_prli      *prli;
6201         struct la_els_prli      prli_s;
6202         struct fcp_prli         *fprli;
6203         struct fcp_lun  *plun;
6204         int             free_pkt = 1;
6205         int             rval;
6206         ls_code_t       resp;
6207         uchar_t         prli_acc = 0;
6208         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
6209         int             lun0_newalloc;
6210 
6211         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6212 
6213         /* get ptrs to the port and target structs for the cmd */
6214         pptr = icmd->ipkt_port;
6215         ptgt = icmd->ipkt_tgt;
6216 
6217         FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6218 
6219         if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6220                 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6221                     sizeof (prli_s));
6222                 prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6223         }
6224 
6225         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6226             fcp_trace, FCP_BUF_LEVEL_2, 0,
6227             "ELS (%x) callback state=0x%x reason=0x%x for %x",
6228             icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6229             ptgt->tgt_d_id);
6230 
6231         if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6232             ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6233 
6234                 mutex_enter(&ptgt->tgt_mutex);
6235                 if (ptgt->tgt_pd_handle == NULL) {
6236                         /*
6237                          * in a fabric environment the port device handles
6238                          * get created only after successful LOGIN into the
6239                          * transport, so the transport makes this port
6240                          * device (pd) handle available in this packet, so
6241                          * save it now
6242                          */
6243                         ASSERT(fpkt->pkt_pd != NULL);
6244                         ptgt->tgt_pd_handle = fpkt->pkt_pd;
6245                 }
6246                 mutex_exit(&ptgt->tgt_mutex);
6247 
6248                 /* which ELS cmd is this response for ?? */
6249                 switch (icmd->ipkt_opcode) {
6250                 case LA_ELS_PLOGI:
6251                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6252                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6253                             "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6254                             ptgt->tgt_d_id,
6255                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6256                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6257 
6258                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6259                             FCP_TGT_TRACE_15);
6260 
6261                         /* Note that we are not allocating a new icmd */
6262                         if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6263                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6264                             icmd->ipkt_cause) != DDI_SUCCESS) {
6265                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6266                                     FCP_TGT_TRACE_16);
6267                                 goto fail;
6268                         }
6269                         break;
6270 
6271                 case LA_ELS_PRLI:
6272                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6273                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6274                             "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6275 
6276                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6277                             FCP_TGT_TRACE_17);
6278 
6279                         prli = &prli_s;
6280 
6281                         FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6282                             sizeof (prli_s));
6283 
6284                         fprli = (struct fcp_prli *)prli->service_params;
6285 
6286                         mutex_enter(&ptgt->tgt_mutex);
6287                         ptgt->tgt_icap = fprli->initiator_fn;
6288                         ptgt->tgt_tcap = fprli->target_fn;
6289                         mutex_exit(&ptgt->tgt_mutex);
6290 
6291                         if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6292                                 /*
6293                                  * this FCP device does not support target mode
6294                                  */
6295                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6296                                     FCP_TGT_TRACE_18);
6297                                 goto fail;
6298                         }
6299                         if (fprli->retry == 1) {
6300                                 fc_ulp_disable_relogin(pptr->port_fp_handle,
6301                                     &ptgt->tgt_port_wwn);
6302                         }
6303 
6304                         /* target is no longer offline */
6305                         mutex_enter(&pptr->port_mutex);
6306                         mutex_enter(&ptgt->tgt_mutex);
6307                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6308                                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6309                                     FCP_TGT_MARK);
6310                         } else {
6311                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6312                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6313                                     "fcp_icmd_callback,1: state change "
6314                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6315                                 mutex_exit(&ptgt->tgt_mutex);
6316                                 mutex_exit(&pptr->port_mutex);
6317                                 goto fail;
6318                         }
6319                         mutex_exit(&ptgt->tgt_mutex);
6320                         mutex_exit(&pptr->port_mutex);
6321 
6322                         /*
6323                          * lun 0 should always respond to inquiry, so
6324                          * get the LUN struct for LUN 0
6325                          *
6326                          * Currently we deal with first level of addressing.
6327                          * If / when we start supporting 0x device types
6328                          * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6329                          * this logic will need revisiting.
6330                          */
6331                         lun0_newalloc = 0;
6332                         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6333                                 /*
6334                                  * no LUN struct for LUN 0 yet exists,
6335                                  * so create one
6336                                  */
6337                                 plun = fcp_alloc_lun(ptgt);
6338                                 if (plun == NULL) {
6339                                         fcp_log(CE_WARN, pptr->port_dip,
6340                                             "!Failed to allocate lun 0 for"
6341                                             " D_ID=%x", ptgt->tgt_d_id);
6342                                         goto fail;
6343                                 }
6344                                 lun0_newalloc = 1;
6345                         }
6346 
6347                         /* fill in LUN info */
6348                         mutex_enter(&ptgt->tgt_mutex);
6349                         /*
6350                          * consider lun 0 as device not connected if it is
6351                          * offlined or newly allocated
6352                          */
6353                         if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6354                             lun0_newalloc) {
6355                                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6356                         }
6357                         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6358                         plun->lun_state &= ~FCP_LUN_OFFLINE;
6359                         ptgt->tgt_lun_cnt = 1;
6360                         ptgt->tgt_report_lun_cnt = 0;
6361                         mutex_exit(&ptgt->tgt_mutex);
6362 
6363                         /* Retrieve the rscn count (if a valid one exists) */
6364                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6365                                 rscn_count = ((fc_ulp_rscn_info_t *)
6366                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6367                                     ->ulp_rscn_count;
6368                         } else {
6369                                 rscn_count = FC_INVALID_RSCN_COUNT;
6370                         }
6371 
6372                         /* send Report Lun request to target */
6373                         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6374                             sizeof (struct fcp_reportlun_resp),
6375                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6376                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6377                                 mutex_enter(&pptr->port_mutex);
6378                                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6379                                         fcp_log(CE_WARN, pptr->port_dip,
6380                                             "!Failed to send REPORT LUN to"
6381                                             "  D_ID=%x", ptgt->tgt_d_id);
6382                                 } else {
6383                                         FCP_TRACE(fcp_logq,
6384                                             pptr->port_instbuf, fcp_trace,
6385                                             FCP_BUF_LEVEL_5, 0,
6386                                             "fcp_icmd_callback,2:state change"
6387                                             " occured for D_ID=0x%x",
6388                                             ptgt->tgt_d_id);
6389                                 }
6390                                 mutex_exit(&pptr->port_mutex);
6391 
6392                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6393                                     FCP_TGT_TRACE_19);
6394 
6395                                 goto fail;
6396                         } else {
6397                                 free_pkt = 0;
6398                                 fcp_icmd_free(pptr, icmd);
6399                         }
6400                         break;
6401 
6402                 default:
6403                         fcp_log(CE_WARN, pptr->port_dip,
6404                             "!fcp_icmd_callback Invalid opcode");
6405                         goto fail;
6406                 }
6407 
6408                 return;
6409         }
6410 
6411 
6412         /*
6413          * Other PLOGI failures are not retried as the
6414          * transport does it already
6415          */
6416         if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6417                 if (fcp_is_retryable(icmd) &&
6418                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6419 
6420                         if (FCP_MUST_RETRY(fpkt)) {
6421                                 fcp_queue_ipkt(pptr, fpkt);
6422                                 return;
6423                         }
6424 
6425                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6426                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6427                             "ELS PRLI is retried for d_id=0x%x, state=%x,"
6428                             " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6429                             fpkt->pkt_reason);
6430 
6431                         /*
6432                          * Retry by recalling the routine that
6433                          * originally queued this packet
6434                          */
6435                         mutex_enter(&pptr->port_mutex);
6436                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6437                                 caddr_t msg;
6438 
6439                                 mutex_exit(&pptr->port_mutex);
6440 
6441                                 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6442 
6443                                 if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6444                                         fpkt->pkt_timeout +=
6445                                             FCP_TIMEOUT_DELTA;
6446                                 }
6447 
6448                                 rval = fc_ulp_issue_els(pptr->port_fp_handle,
6449                                     fpkt);
6450                                 if (rval == FC_SUCCESS) {
6451                                         return;
6452                                 }
6453 
6454                                 if (rval == FC_STATEC_BUSY ||
6455                                     rval == FC_OFFLINE) {
6456                                         fcp_queue_ipkt(pptr, fpkt);
6457                                         return;
6458                                 }
6459                                 (void) fc_ulp_error(rval, &msg);
6460 
6461                                 fcp_log(CE_NOTE, pptr->port_dip,
6462                                     "!ELS 0x%x failed to d_id=0x%x;"
6463                                     " %s", icmd->ipkt_opcode,
6464                                     ptgt->tgt_d_id, msg);
6465                         } else {
6466                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6467                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6468                                     "fcp_icmd_callback,3: state change "
6469                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6470                                 mutex_exit(&pptr->port_mutex);
6471                         }
6472                 }
6473         } else {
6474                 if (fcp_is_retryable(icmd) &&
6475                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6476                         if (FCP_MUST_RETRY(fpkt)) {
6477                                 fcp_queue_ipkt(pptr, fpkt);
6478                                 return;
6479                         }
6480                 }
6481                 mutex_enter(&pptr->port_mutex);
6482                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6483                     fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6484                         mutex_exit(&pptr->port_mutex);
6485                         fcp_print_error(fpkt);
6486                 } else {
6487                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6488                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6489                             "fcp_icmd_callback,4: state change occured"
6490                             " for D_ID=0x%x", ptgt->tgt_d_id);
6491                         mutex_exit(&pptr->port_mutex);
6492                 }
6493         }
6494 
6495 fail:
6496         if (free_pkt) {
6497                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6498                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
6499                 fcp_icmd_free(pptr, icmd);
6500         }
6501 }
6502 
6503 
6504 /*
6505  * called internally to send an info cmd using the transport
6506  *
6507  * sends either an INQ or a REPORT_LUN
6508  *
6509  * when the packet is completed fcp_scsi_callback is called
6510  */
6511 static int
6512 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6513     int lcount, int tcount, int cause, uint32_t rscn_count)
6514 {
6515         int                     nodma;
6516         struct fcp_ipkt         *icmd;
6517         struct fcp_tgt          *ptgt;
6518         struct fcp_port         *pptr;
6519         fc_frame_hdr_t          *hp;
6520         fc_packet_t             *fpkt;
6521         struct fcp_cmd          fcp_cmd;
6522         struct fcp_cmd          *fcmd;
6523         union scsi_cdb          *scsi_cdb;
6524 
6525         ASSERT(plun != NULL);
6526 
6527         ptgt = plun->lun_tgt;
6528         ASSERT(ptgt != NULL);
6529 
6530         pptr = ptgt->tgt_port;
6531         ASSERT(pptr != NULL);
6532 
6533         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6534             fcp_trace, FCP_BUF_LEVEL_5, 0,
6535             "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6536 
6537         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6538         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6539             FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6540             rscn_count);
6541 
6542         if (icmd == NULL) {
6543                 return (DDI_FAILURE);
6544         }
6545 
6546         fpkt = icmd->ipkt_fpkt;
6547         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6548         icmd->ipkt_retries = 0;
6549         icmd->ipkt_opcode = opcode;
6550         icmd->ipkt_lun = plun;
6551 
6552         if (nodma) {
6553                 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6554         } else {
6555                 fcmd = &fcp_cmd;
6556         }
6557         bzero(fcmd, sizeof (struct fcp_cmd));
6558 
6559         fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6560 
6561         hp = &fpkt->pkt_cmd_fhdr;
6562 
6563         hp->s_id = pptr->port_id;
6564         hp->d_id = ptgt->tgt_d_id;
6565         hp->r_ctl = R_CTL_COMMAND;
6566         hp->type = FC_TYPE_SCSI_FCP;
6567         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6568         hp->rsvd = 0;
6569         hp->seq_id = 0;
6570         hp->seq_cnt = 0;
6571         hp->ox_id = 0xffff;
6572         hp->rx_id = 0xffff;
6573         hp->ro = 0;
6574 
6575         bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6576 
6577         /*
6578          * Request SCSI target for expedited processing
6579          */
6580 
6581         /*
6582          * Set up for untagged queuing because we do not
6583          * know if the fibre device supports queuing.
6584          */
6585         fcmd->fcp_cntl.cntl_reserved_0 = 0;
6586         fcmd->fcp_cntl.cntl_reserved_1 = 0;
6587         fcmd->fcp_cntl.cntl_reserved_2 = 0;
6588         fcmd->fcp_cntl.cntl_reserved_3 = 0;
6589         fcmd->fcp_cntl.cntl_reserved_4 = 0;
6590         fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6591         scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6592 
6593         switch (opcode) {
6594         case SCMD_INQUIRY_PAGE83:
6595                 /*
6596                  * Prepare to get the Inquiry VPD page 83 information
6597                  */
6598                 fcmd->fcp_cntl.cntl_read_data = 1;
6599                 fcmd->fcp_cntl.cntl_write_data = 0;
6600                 fcmd->fcp_data_len = alloc_len;
6601 
6602                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6603                 fpkt->pkt_comp = fcp_scsi_callback;
6604 
6605                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6606                 scsi_cdb->g0_addr2 = 0x01;
6607                 scsi_cdb->g0_addr1 = 0x83;
6608                 scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6609                 break;
6610 
6611         case SCMD_INQUIRY:
6612                 fcmd->fcp_cntl.cntl_read_data = 1;
6613                 fcmd->fcp_cntl.cntl_write_data = 0;
6614                 fcmd->fcp_data_len = alloc_len;
6615 
6616                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6617                 fpkt->pkt_comp = fcp_scsi_callback;
6618 
6619                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6620                 scsi_cdb->g0_count0 = SUN_INQSIZE;
6621                 break;
6622 
6623         case SCMD_REPORT_LUN: {
6624                 fc_portid_t     d_id;
6625                 opaque_t        fca_dev;
6626 
6627                 ASSERT(alloc_len >= 16);
6628 
6629                 d_id.priv_lilp_posit = 0;
6630                 d_id.port_id = ptgt->tgt_d_id;
6631 
6632                 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6633 
6634                 mutex_enter(&ptgt->tgt_mutex);
6635                 ptgt->tgt_fca_dev = fca_dev;
6636                 mutex_exit(&ptgt->tgt_mutex);
6637 
6638                 fcmd->fcp_cntl.cntl_read_data = 1;
6639                 fcmd->fcp_cntl.cntl_write_data = 0;
6640                 fcmd->fcp_data_len = alloc_len;
6641 
6642                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6643                 fpkt->pkt_comp = fcp_scsi_callback;
6644 
6645                 scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6646                 scsi_cdb->scc5_count0 = alloc_len & 0xff;
6647                 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6648                 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6649                 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6650                 break;
6651         }
6652 
6653         default:
6654                 fcp_log(CE_WARN, pptr->port_dip,
6655                     "!fcp_send_scsi Invalid opcode");
6656                 break;
6657         }
6658 
6659         if (!nodma) {
6660                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6661                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6662         }
6663 
6664         mutex_enter(&pptr->port_mutex);
6665         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6666 
6667                 mutex_exit(&pptr->port_mutex);
6668                 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6669                     FC_SUCCESS) {
6670                         fcp_icmd_free(pptr, icmd);
6671                         return (DDI_FAILURE);
6672                 }
6673                 return (DDI_SUCCESS);
6674         } else {
6675                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6676                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6677                     "fcp_send_scsi,1: state change occured"
6678                     " for D_ID=0x%x", ptgt->tgt_d_id);
6679                 mutex_exit(&pptr->port_mutex);
6680                 fcp_icmd_free(pptr, icmd);
6681                 return (DDI_FAILURE);
6682         }
6683 }
6684 
6685 
6686 /*
6687  * called by fcp_scsi_callback to check to handle the case where
6688  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6689  */
6690 static int
6691 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6692 {
6693         uchar_t                         rqlen;
6694         int                             rval = DDI_FAILURE;
6695         struct scsi_extended_sense      sense_info, *sense;
6696         struct fcp_ipkt         *icmd = (struct fcp_ipkt *)
6697             fpkt->pkt_ulp_private;
6698         struct fcp_tgt          *ptgt = icmd->ipkt_tgt;
6699         struct fcp_port         *pptr = ptgt->tgt_port;
6700 
6701         ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6702 
6703         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6704                 /*
6705                  * SCSI-II Reserve Release support. Some older FC drives return
6706                  * Reservation conflict for Report Luns command.
6707                  */
6708                 if (icmd->ipkt_nodma) {
6709                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6710                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6711                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6712                 } else {
6713                         fcp_rsp_t       new_resp;
6714 
6715                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6716                             fpkt->pkt_resp_acc, sizeof (new_resp));
6717 
6718                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6719                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6720                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6721 
6722                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6723                             fpkt->pkt_resp_acc, sizeof (new_resp));
6724                 }
6725 
6726                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6727                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6728 
6729                 return (DDI_SUCCESS);
6730         }
6731 
6732         sense = &sense_info;
6733         if (!rsp->fcp_u.fcp_status.sense_len_set) {
6734                 /* no need to continue if sense length is not set */
6735                 return (rval);
6736         }
6737 
6738         /* casting 64-bit integer to 8-bit */
6739         rqlen = (uchar_t)min(rsp->fcp_sense_len,
6740             sizeof (struct scsi_extended_sense));
6741 
6742         if (rqlen < 14) {
6743                 /* no need to continue if request length isn't long enough */
6744                 return (rval);
6745         }
6746 
6747         if (icmd->ipkt_nodma) {
6748                 /*
6749                  * We can safely use fcp_response_len here since the
6750                  * only path that calls fcp_check_reportlun,
6751                  * fcp_scsi_callback, has already called
6752                  * fcp_validate_fcp_response.
6753                  */
6754                 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6755                     sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6756         } else {
6757                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6758                     rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6759                     sizeof (struct scsi_extended_sense));
6760         }
6761 
6762         if (!FCP_SENSE_NO_LUN(sense)) {
6763                 mutex_enter(&ptgt->tgt_mutex);
6764                 /* clear the flag if any */
6765                 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6766                 mutex_exit(&ptgt->tgt_mutex);
6767         }
6768 
6769         if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6770             (sense->es_add_code == 0x20)) {
6771                 if (icmd->ipkt_nodma) {
6772                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6773                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6774                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6775                 } else {
6776                         fcp_rsp_t       new_resp;
6777 
6778                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6779                             fpkt->pkt_resp_acc, sizeof (new_resp));
6780 
6781                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6782                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6783                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6784 
6785                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6786                             fpkt->pkt_resp_acc, sizeof (new_resp));
6787                 }
6788 
6789                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6790                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6791 
6792                 return (DDI_SUCCESS);
6793         }
6794 
6795         /*
6796          * This is for the STK library which returns a check condition,
6797          * to indicate device is not ready, manual assistance needed.
6798          * This is to a report lun command when the door is open.
6799          */
6800         if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6801                 if (icmd->ipkt_nodma) {
6802                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6803                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6804                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6805                 } else {
6806                         fcp_rsp_t       new_resp;
6807 
6808                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6809                             fpkt->pkt_resp_acc, sizeof (new_resp));
6810 
6811                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6812                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6813                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6814 
6815                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6816                             fpkt->pkt_resp_acc, sizeof (new_resp));
6817                 }
6818 
6819                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6820                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6821 
6822                 return (DDI_SUCCESS);
6823         }
6824 
6825         if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6826             (FCP_SENSE_NO_LUN(sense))) {
6827                 mutex_enter(&ptgt->tgt_mutex);
6828                 if ((FCP_SENSE_NO_LUN(sense)) &&
6829                     (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6830                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6831                         mutex_exit(&ptgt->tgt_mutex);
6832                         /*
6833                          * reconfig was triggred by ILLEGAL REQUEST but
6834                          * got ILLEGAL REQUEST again
6835                          */
6836                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6837                             fcp_trace, FCP_BUF_LEVEL_3, 0,
6838                             "!FCP: Unable to obtain Report Lun data"
6839                             " target=%x", ptgt->tgt_d_id);
6840                 } else {
6841                         if (ptgt->tgt_tid == NULL) {
6842                                 timeout_id_t    tid;
6843                                 /*
6844                                  * REPORT LUN data has changed.  Kick off
6845                                  * rediscovery
6846                                  */
6847                                 tid = timeout(fcp_reconfigure_luns,
6848                                     (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6849 
6850                                 ptgt->tgt_tid = tid;
6851                                 ptgt->tgt_state |= FCP_TGT_BUSY;
6852                         }
6853                         if (FCP_SENSE_NO_LUN(sense)) {
6854                                 ptgt->tgt_state |= FCP_TGT_ILLREQ;
6855                         }
6856                         mutex_exit(&ptgt->tgt_mutex);
6857                         if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6858                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6859                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6860                                     "!FCP:Report Lun Has Changed"
6861                                     " target=%x", ptgt->tgt_d_id);
6862                         } else if (FCP_SENSE_NO_LUN(sense)) {
6863                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6864                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6865                                     "!FCP:LU Not Supported"
6866                                     " target=%x", ptgt->tgt_d_id);
6867                         }
6868                 }
6869                 rval = DDI_SUCCESS;
6870         }
6871 
6872         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6873             fcp_trace, FCP_BUF_LEVEL_5, 0,
6874             "D_ID=%x, sense=%x, status=%x",
6875             fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6876             rsp->fcp_u.fcp_status.scsi_status);
6877 
6878         return (rval);
6879 }
6880 
6881 /*
6882  *     Function: fcp_scsi_callback
6883  *
6884  *  Description: This is the callback routine set by fcp_send_scsi() after
6885  *               it calls fcp_icmd_alloc().  The SCSI command completed here
6886  *               and autogenerated by FCP are:  REPORT_LUN, INQUIRY and
6887  *               INQUIRY_PAGE83.
6888  *
6889  *     Argument: *fpkt   FC packet used to convey the command
6890  *
6891  * Return Value: None
6892  */
6893 static void
6894 fcp_scsi_callback(fc_packet_t *fpkt)
6895 {
6896         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
6897             fpkt->pkt_ulp_private;
6898         struct fcp_rsp_info     fcp_rsp_err, *bep;
6899         struct fcp_port *pptr;
6900         struct fcp_tgt  *ptgt;
6901         struct fcp_lun  *plun;
6902         struct fcp_rsp          response, *rsp;
6903 
6904         ptgt = icmd->ipkt_tgt;
6905         pptr = ptgt->tgt_port;
6906         plun = icmd->ipkt_lun;
6907 
6908         if (icmd->ipkt_nodma) {
6909                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6910         } else {
6911                 rsp = &response;
6912                 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6913                     sizeof (struct fcp_rsp));
6914         }
6915 
6916         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6917             fcp_trace, FCP_BUF_LEVEL_2, 0,
6918             "SCSI callback state=0x%x for %x, op_code=0x%x, "
6919             "status=%x, lun num=%x",
6920             fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6921             rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6922 
6923         /*
6924          * Pre-init LUN GUID with NWWN if it is not a device that
6925          * supports multiple luns and we know it's not page83
6926          * compliant.  Although using a NWWN is not lun unique,
6927          * we will be fine since there is only one lun behind the taget
6928          * in this case.
6929          */
6930         if ((plun->lun_guid_size == 0) &&
6931             (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6932             (fcp_symmetric_device_probe(plun) == 0)) {
6933 
6934                 char ascii_wwn[FC_WWN_SIZE*2+1];
6935                 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6936                 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6937         }
6938 
6939         /*
6940          * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6941          * when thay have more data than what is asked in CDB. An overrun
6942          * is really when FCP_DL is smaller than the data length in CDB.
6943          * In the case here we know that REPORT LUN command we formed within
6944          * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6945          * behavior. In reality this is FC_SUCCESS.
6946          */
6947         if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6948             (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6949             (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6950                 fpkt->pkt_state = FC_PKT_SUCCESS;
6951         }
6952 
6953         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6954                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6955                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6956                     "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6957                     ptgt->tgt_d_id);
6958 
6959                 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6960                         /*
6961                          * Inquiry VPD page command on A5K SES devices would
6962                          * result in data CRC errors.
6963                          */
6964                         if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6965                                 (void) fcp_handle_page83(fpkt, icmd, 1);
6966                                 return;
6967                         }
6968                 }
6969                 if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6970                     FCP_MUST_RETRY(fpkt)) {
6971                         fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6972                         fcp_retry_scsi_cmd(fpkt);
6973                         return;
6974                 }
6975 
6976                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6977                     FCP_TGT_TRACE_20);
6978 
6979                 mutex_enter(&pptr->port_mutex);
6980                 mutex_enter(&ptgt->tgt_mutex);
6981                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6982                         mutex_exit(&ptgt->tgt_mutex);
6983                         mutex_exit(&pptr->port_mutex);
6984                         fcp_print_error(fpkt);
6985                 } else {
6986                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6987                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6988                             "fcp_scsi_callback,1: state change occured"
6989                             " for D_ID=0x%x", ptgt->tgt_d_id);
6990                         mutex_exit(&ptgt->tgt_mutex);
6991                         mutex_exit(&pptr->port_mutex);
6992                 }
6993                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6994                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
6995                 fcp_icmd_free(pptr, icmd);
6996                 return;
6997         }
6998 
6999         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7000 
7001         mutex_enter(&pptr->port_mutex);
7002         mutex_enter(&ptgt->tgt_mutex);
7003         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7004                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7005                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7006                     "fcp_scsi_callback,2: state change occured"
7007                     " for D_ID=0x%x", ptgt->tgt_d_id);
7008                 mutex_exit(&ptgt->tgt_mutex);
7009                 mutex_exit(&pptr->port_mutex);
7010                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7011                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7012                 fcp_icmd_free(pptr, icmd);
7013                 return;
7014         }
7015         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7016 
7017         mutex_exit(&ptgt->tgt_mutex);
7018         mutex_exit(&pptr->port_mutex);
7019 
7020         if (icmd->ipkt_nodma) {
7021                 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7022                     sizeof (struct fcp_rsp));
7023         } else {
7024                 bep = &fcp_rsp_err;
7025                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7026                     fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7027         }
7028 
7029         if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7030                 fcp_retry_scsi_cmd(fpkt);
7031                 return;
7032         }
7033 
7034         if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7035             FCP_NO_FAILURE) {
7036                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7037                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7038                     "rsp_code=0x%x, rsp_len_set=0x%x",
7039                     bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7040                 fcp_retry_scsi_cmd(fpkt);
7041                 return;
7042         }
7043 
7044         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7045             rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7046                 fcp_queue_ipkt(pptr, fpkt);
7047                 return;
7048         }
7049 
7050         /*
7051          * Devices that do not support INQUIRY_PAGE83, return check condition
7052          * with illegal request as per SCSI spec.
7053          * Crossbridge is one such device and Daktari's SES node is another.
7054          * We want to ideally enumerate these devices as a non-mpxio devices.
7055          * SES nodes (Daktari only currently) are an exception to this.
7056          */
7057         if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7058             (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7059 
7060                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7061                     fcp_trace, FCP_BUF_LEVEL_3, 0,
7062                     "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7063                     "check condition. May enumerate as non-mpxio device",
7064                     ptgt->tgt_d_id, plun->lun_type);
7065 
7066                 /*
7067                  * If we let Daktari's SES be enumerated as a non-mpxio
7068                  * device, there will be a discrepency in that the other
7069                  * internal FC disks will get enumerated as mpxio devices.
7070                  * Applications like luxadm expect this to be consistent.
7071                  *
7072                  * So, we put in a hack here to check if this is an SES device
7073                  * and handle it here.
7074                  */
7075                 if (plun->lun_type == DTYPE_ESI) {
7076                         /*
7077                          * Since, pkt_state is actually FC_PKT_SUCCESS
7078                          * at this stage, we fake a failure here so that
7079                          * fcp_handle_page83 will create a device path using
7080                          * the WWN instead of the GUID which is not there anyway
7081                          */
7082                         fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7083                         (void) fcp_handle_page83(fpkt, icmd, 1);
7084                         return;
7085                 }
7086 
7087                 mutex_enter(&ptgt->tgt_mutex);
7088                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
7089                     FCP_LUN_MARK | FCP_LUN_BUSY);
7090                 mutex_exit(&ptgt->tgt_mutex);
7091 
7092                 (void) fcp_call_finish_init(pptr, ptgt,
7093                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7094                     icmd->ipkt_cause);
7095                 fcp_icmd_free(pptr, icmd);
7096                 return;
7097         }
7098 
7099         if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7100                 int rval = DDI_FAILURE;
7101 
7102                 /*
7103                  * handle cases where report lun isn't supported
7104                  * by faking up our own REPORT_LUN response or
7105                  * UNIT ATTENTION
7106                  */
7107                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7108                         rval = fcp_check_reportlun(rsp, fpkt);
7109 
7110                         /*
7111                          * fcp_check_reportlun might have modified the
7112                          * FCP response. Copy it in again to get an updated
7113                          * FCP response
7114                          */
7115                         if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7116                                 rsp = &response;
7117 
7118                                 FCP_CP_IN(fpkt->pkt_resp, rsp,
7119                                     fpkt->pkt_resp_acc,
7120                                     sizeof (struct fcp_rsp));
7121                         }
7122                 }
7123 
7124                 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7125                         if (rval == DDI_SUCCESS) {
7126                                 (void) fcp_call_finish_init(pptr, ptgt,
7127                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7128                                     icmd->ipkt_cause);
7129                                 fcp_icmd_free(pptr, icmd);
7130                         } else {
7131                                 fcp_retry_scsi_cmd(fpkt);
7132                         }
7133 
7134                         return;
7135                 }
7136         } else {
7137                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7138                         mutex_enter(&ptgt->tgt_mutex);
7139                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7140                         mutex_exit(&ptgt->tgt_mutex);
7141                 }
7142         }
7143 
7144         ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7145         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7146                 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7147                     DDI_DMA_SYNC_FORCPU);
7148         }
7149 
7150         switch (icmd->ipkt_opcode) {
7151         case SCMD_INQUIRY:
7152                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7153                 fcp_handle_inquiry(fpkt, icmd);
7154                 break;
7155 
7156         case SCMD_REPORT_LUN:
7157                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7158                     FCP_TGT_TRACE_22);
7159                 fcp_handle_reportlun(fpkt, icmd);
7160                 break;
7161 
7162         case SCMD_INQUIRY_PAGE83:
7163                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7164                 (void) fcp_handle_page83(fpkt, icmd, 0);
7165                 break;
7166 
7167         default:
7168                 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7169                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7170                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7171                 fcp_icmd_free(pptr, icmd);
7172                 break;
7173         }
7174 }
7175 
7176 
7177 static void
7178 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7179 {
7180         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
7181             fpkt->pkt_ulp_private;
7182         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
7183         struct fcp_port *pptr = ptgt->tgt_port;
7184 
7185         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7186             fcp_is_retryable(icmd)) {
7187                 mutex_enter(&pptr->port_mutex);
7188                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7189                         mutex_exit(&pptr->port_mutex);
7190                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7191                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7192                             "Retrying %s to %x; state=%x, reason=%x",
7193                             (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7194                             "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7195                             fpkt->pkt_state, fpkt->pkt_reason);
7196 
7197                         fcp_queue_ipkt(pptr, fpkt);
7198                 } else {
7199                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7200                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7201                             "fcp_retry_scsi_cmd,1: state change occured"
7202                             " for D_ID=0x%x", ptgt->tgt_d_id);
7203                         mutex_exit(&pptr->port_mutex);
7204                         (void) fcp_call_finish_init(pptr, ptgt,
7205                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7206                             icmd->ipkt_cause);
7207                         fcp_icmd_free(pptr, icmd);
7208                 }
7209         } else {
7210                 fcp_print_error(fpkt);
7211                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7212                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7213                 fcp_icmd_free(pptr, icmd);
7214         }
7215 }
7216 
7217 /*
7218  *     Function: fcp_handle_page83
7219  *
7220  *  Description: Treats the response to INQUIRY_PAGE83.
7221  *
7222  *     Argument: *fpkt  FC packet used to convey the command.
7223  *               *icmd  Original fcp_ipkt structure.
7224  *               ignore_page83_data
7225  *                      if it's 1, that means it's a special devices's
7226  *                      page83 response, it should be enumerated under mpxio
7227  *
7228  * Return Value: None
7229  */
7230 static void
7231 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7232     int ignore_page83_data)
7233 {
7234         struct fcp_port *pptr;
7235         struct fcp_lun  *plun;
7236         struct fcp_tgt  *ptgt;
7237         uchar_t                 dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7238         int                     fail = 0;
7239         ddi_devid_t             devid;
7240         char                    *guid = NULL;
7241         int                     ret;
7242 
7243         ASSERT(icmd != NULL && fpkt != NULL);
7244 
7245         pptr = icmd->ipkt_port;
7246         ptgt = icmd->ipkt_tgt;
7247         plun = icmd->ipkt_lun;
7248 
7249         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7250                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7251 
7252                 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7253                     SCMD_MAX_INQUIRY_PAGE83_SIZE);
7254 
7255                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7256                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7257                     "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7258                     "dtype=0x%x, lun num=%x",
7259                     pptr->port_instance, ptgt->tgt_d_id,
7260                     dev_id_page[0], plun->lun_num);
7261 
7262                 ret = ddi_devid_scsi_encode(
7263                     DEVID_SCSI_ENCODE_VERSION_LATEST,
7264                     NULL,               /* driver name */
7265                     (unsigned char *) &plun->lun_inq, /* standard inquiry */
7266                     sizeof (plun->lun_inq), /* size of standard inquiry */
7267                     NULL,               /* page 80 data */
7268                     0,          /* page 80 len */
7269                     dev_id_page,        /* page 83 data */
7270                     SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7271                     &devid);
7272 
7273                 if (ret == DDI_SUCCESS) {
7274 
7275                         guid = ddi_devid_to_guid(devid);
7276 
7277                         if (guid) {
7278                                 /*
7279                                  * Check our current guid.  If it's non null
7280                                  * and it has changed, we need to copy it into
7281                                  * lun_old_guid since we might still need it.
7282                                  */
7283                                 if (plun->lun_guid &&
7284                                     strcmp(guid, plun->lun_guid)) {
7285                                         unsigned int len;
7286 
7287                                         /*
7288                                          * If the guid of the LUN changes,
7289                                          * reconfiguration should be triggered
7290                                          * to reflect the changes.
7291                                          * i.e. we should offline the LUN with
7292                                          * the old guid, and online the LUN with
7293                                          * the new guid.
7294                                          */
7295                                         plun->lun_state |= FCP_LUN_CHANGED;
7296 
7297                                         if (plun->lun_old_guid) {
7298                                                 kmem_free(plun->lun_old_guid,
7299                                                     plun->lun_old_guid_size);
7300                                         }
7301 
7302                                         len = plun->lun_guid_size;
7303                                         plun->lun_old_guid_size = len;
7304 
7305                                         plun->lun_old_guid = kmem_zalloc(len,
7306                                             KM_NOSLEEP);
7307 
7308                                         if (plun->lun_old_guid) {
7309                                                 /*
7310                                                  * The alloc was successful then
7311                                                  * let's do the copy.
7312                                                  */
7313                                                 bcopy(plun->lun_guid,
7314                                                     plun->lun_old_guid, len);
7315                                         } else {
7316                                                 fail = 1;
7317                                                 plun->lun_old_guid_size = 0;
7318                                         }
7319                                 }
7320                                 if (!fail) {
7321                                         if (fcp_copy_guid_2_lun_block(
7322                                             plun, guid)) {
7323                                                 fail = 1;
7324                                         }
7325                                 }
7326                                 ddi_devid_free_guid(guid);
7327 
7328                         } else {
7329                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7330                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7331                                     "fcp_handle_page83: unable to create "
7332                                     "GUID");
7333 
7334                                 /* couldn't create good guid from devid */
7335                                 fail = 1;
7336                         }
7337                         ddi_devid_free(devid);
7338 
7339                 } else if (ret == DDI_NOT_WELL_FORMED) {
7340                         /* NULL filled data for page 83 */
7341                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7342                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7343                             "fcp_handle_page83: retry GUID");
7344 
7345                         icmd->ipkt_retries = 0;
7346                         fcp_retry_scsi_cmd(fpkt);
7347                         return;
7348                 } else {
7349                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7350                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7351                             "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7352                             ret);
7353                         /*
7354                          * Since the page83 validation
7355                          * introduced late, we are being
7356                          * tolerant to the existing devices
7357                          * that already found to be working
7358                          * under mpxio, like A5200's SES device,
7359                          * its page83 response will not be standard-compliant,
7360                          * but we still want it to be enumerated under mpxio.
7361                          */
7362                         if (fcp_symmetric_device_probe(plun) != 0) {
7363                                 fail = 1;
7364                         }
7365                 }
7366 
7367         } else {
7368                 /* bad packet state */
7369                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7370 
7371                 /*
7372                  * For some special devices (A5K SES and Daktari's SES devices),
7373                  * they should be enumerated under mpxio
7374                  * or "luxadm dis" will fail
7375                  */
7376                 if (ignore_page83_data) {
7377                         fail = 0;
7378                 } else {
7379                         fail = 1;
7380                 }
7381                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7382                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7383                     "!Devid page cmd failed. "
7384                     "fpkt_state: %x fpkt_reason: %x",
7385                     "ignore_page83: %d",
7386                     fpkt->pkt_state, fpkt->pkt_reason,
7387                     ignore_page83_data);
7388         }
7389 
7390         mutex_enter(&pptr->port_mutex);
7391         mutex_enter(&plun->lun_mutex);
7392         /*
7393          * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7394          * mismatch between lun_cip and lun_mpxio.
7395          */
7396         if (plun->lun_cip == NULL) {
7397                 /*
7398                  * If we don't have a guid for this lun it's because we were
7399                  * unable to glean one from the page 83 response.  Set the
7400                  * control flag to 0 here to make sure that we don't attempt to
7401                  * enumerate it under mpxio.
7402                  */
7403                 if (fail || pptr->port_mpxio == 0) {
7404                         plun->lun_mpxio = 0;
7405                 } else {
7406                         plun->lun_mpxio = 1;
7407                 }
7408         }
7409         mutex_exit(&plun->lun_mutex);
7410         mutex_exit(&pptr->port_mutex);
7411 
7412         mutex_enter(&ptgt->tgt_mutex);
7413         plun->lun_state &=
7414             ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7415         mutex_exit(&ptgt->tgt_mutex);
7416 
7417         (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7418             icmd->ipkt_change_cnt, icmd->ipkt_cause);
7419 
7420         fcp_icmd_free(pptr, icmd);
7421 }
7422 
7423 /*
7424  *     Function: fcp_handle_inquiry
7425  *
7426  *  Description: Called by fcp_scsi_callback to handle the response to an
7427  *               INQUIRY request.
7428  *
7429  *     Argument: *fpkt  FC packet used to convey the command.
7430  *               *icmd  Original fcp_ipkt structure.
7431  *
7432  * Return Value: None
7433  */
7434 static void
7435 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7436 {
7437         struct fcp_port *pptr;
7438         struct fcp_lun  *plun;
7439         struct fcp_tgt  *ptgt;
7440         uchar_t         dtype;
7441         uchar_t         pqual;
7442         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
7443 
7444         ASSERT(icmd != NULL && fpkt != NULL);
7445 
7446         pptr = icmd->ipkt_port;
7447         ptgt = icmd->ipkt_tgt;
7448         plun = icmd->ipkt_lun;
7449 
7450         FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7451             sizeof (struct scsi_inquiry));
7452 
7453         dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7454         pqual = plun->lun_inq.inq_dtype >> 5;
7455 
7456         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7457             fcp_trace, FCP_BUF_LEVEL_5, 0,
7458             "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7459             "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7460             plun->lun_num, dtype, pqual);
7461 
7462         if (pqual != 0) {
7463                 /*
7464                  * Non-zero peripheral qualifier
7465                  */
7466                 fcp_log(CE_CONT, pptr->port_dip,
7467                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7468                     "Device type=0x%x Peripheral qual=0x%x\n",
7469                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7470 
7471                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7472                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7473                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7474                     "Device type=0x%x Peripheral qual=0x%x\n",
7475                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7476 
7477                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7478 
7479                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7480                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7481                 fcp_icmd_free(pptr, icmd);
7482                 return;
7483         }
7484 
7485         /*
7486          * If the device is already initialized, check the dtype
7487          * for a change. If it has changed then update the flags
7488          * so the create_luns will offline the old device and
7489          * create the new device. Refer to bug: 4764752
7490          */
7491         if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7492                 plun->lun_state |= FCP_LUN_CHANGED;
7493         }
7494         plun->lun_type = plun->lun_inq.inq_dtype;
7495 
7496         /*
7497          * This code is setting/initializing the throttling in the FCA
7498          * driver.
7499          */
7500         mutex_enter(&pptr->port_mutex);
7501         if (!pptr->port_notify) {
7502                 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7503                         uint32_t cmd = 0;
7504                         cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7505                             ((cmd & 0xFFFFFF00 >> 8) |
7506                             FCP_SVE_THROTTLE << 8));
7507                         pptr->port_notify = 1;
7508                         mutex_exit(&pptr->port_mutex);
7509                         (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7510                         mutex_enter(&pptr->port_mutex);
7511                 }
7512         }
7513 
7514         if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7515                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7516                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7517                     "fcp_handle_inquiry,1:state change occured"
7518                     " for D_ID=0x%x", ptgt->tgt_d_id);
7519                 mutex_exit(&pptr->port_mutex);
7520 
7521                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7522                 (void) fcp_call_finish_init(pptr, ptgt,
7523                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7524                     icmd->ipkt_cause);
7525                 fcp_icmd_free(pptr, icmd);
7526                 return;
7527         }
7528         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7529         mutex_exit(&pptr->port_mutex);
7530 
7531         /* Retrieve the rscn count (if a valid one exists) */
7532         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7533                 rscn_count = ((fc_ulp_rscn_info_t *)
7534                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7535         } else {
7536                 rscn_count = FC_INVALID_RSCN_COUNT;
7537         }
7538 
7539         if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7540             SCMD_MAX_INQUIRY_PAGE83_SIZE,
7541             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7542             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7543                 fcp_log(CE_WARN, NULL, "!failed to send page 83");
7544                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7545                 (void) fcp_call_finish_init(pptr, ptgt,
7546                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7547                     icmd->ipkt_cause);
7548         }
7549 
7550         /*
7551          * Read Inquiry VPD Page 0x83 to uniquely
7552          * identify this logical unit.
7553          */
7554         fcp_icmd_free(pptr, icmd);
7555 }
7556 
7557 /*
7558  *     Function: fcp_handle_reportlun
7559  *
7560  *  Description: Called by fcp_scsi_callback to handle the response to a
7561  *               REPORT_LUN request.
7562  *
7563  *     Argument: *fpkt  FC packet used to convey the command.
7564  *               *icmd  Original fcp_ipkt structure.
7565  *
7566  * Return Value: None
7567  */
7568 static void
7569 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7570 {
7571         int                             i;
7572         int                             nluns_claimed;
7573         int                             nluns_bufmax;
7574         int                             len;
7575         uint16_t                        lun_num;
7576         uint32_t                        rscn_count = FC_INVALID_RSCN_COUNT;
7577         struct fcp_port                 *pptr;
7578         struct fcp_tgt                  *ptgt;
7579         struct fcp_lun                  *plun;
7580         struct fcp_reportlun_resp       *report_lun;
7581 
7582         pptr = icmd->ipkt_port;
7583         ptgt = icmd->ipkt_tgt;
7584         len = fpkt->pkt_datalen;
7585 
7586         if ((len < FCP_LUN_HEADER) ||
7587             ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7588                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7589                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7590                 fcp_icmd_free(pptr, icmd);
7591                 return;
7592         }
7593 
7594         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7595             fpkt->pkt_datalen);
7596 
7597         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7598             fcp_trace, FCP_BUF_LEVEL_5, 0,
7599             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7600             pptr->port_instance, ptgt->tgt_d_id);
7601 
7602         /*
7603          * Get the number of luns (which is supplied as LUNS * 8) the
7604          * device claims it has.
7605          */
7606         nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7607 
7608         /*
7609          * Get the maximum number of luns the buffer submitted can hold.
7610          */
7611         nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7612 
7613         /*
7614          * Due to limitations of certain hardware, we support only 16 bit LUNs
7615          */
7616         if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7617                 kmem_free(report_lun, len);
7618 
7619                 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7620                     " 0x%x number of LUNs for target=%x", nluns_claimed,
7621                     ptgt->tgt_d_id);
7622 
7623                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7624                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7625                 fcp_icmd_free(pptr, icmd);
7626                 return;
7627         }
7628 
7629         /*
7630          * If there are more LUNs than we have allocated memory for,
7631          * allocate more space and send down yet another report lun if
7632          * the maximum number of attempts hasn't been reached.
7633          */
7634         mutex_enter(&ptgt->tgt_mutex);
7635 
7636         if ((nluns_claimed > nluns_bufmax) &&
7637             (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7638 
7639                 struct fcp_lun *plun;
7640 
7641                 ptgt->tgt_report_lun_cnt++;
7642                 plun = ptgt->tgt_lun;
7643                 ASSERT(plun != NULL);
7644                 mutex_exit(&ptgt->tgt_mutex);
7645 
7646                 kmem_free(report_lun, len);
7647 
7648                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7649                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7650                     "!Dynamically discovered %d LUNs for D_ID=%x",
7651                     nluns_claimed, ptgt->tgt_d_id);
7652 
7653                 /* Retrieve the rscn count (if a valid one exists) */
7654                 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7655                         rscn_count = ((fc_ulp_rscn_info_t *)
7656                             (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7657                             ulp_rscn_count;
7658                 } else {
7659                         rscn_count = FC_INVALID_RSCN_COUNT;
7660                 }
7661 
7662                 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7663                     FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7664                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7665                     icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7666                         (void) fcp_call_finish_init(pptr, ptgt,
7667                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7668                             icmd->ipkt_cause);
7669                 }
7670 
7671                 fcp_icmd_free(pptr, icmd);
7672                 return;
7673         }
7674 
7675         if (nluns_claimed > nluns_bufmax) {
7676                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7677                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7678                     "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7679                     "    Number of LUNs lost=%x",
7680                     ptgt->tgt_port_wwn.raw_wwn[0],
7681                     ptgt->tgt_port_wwn.raw_wwn[1],
7682                     ptgt->tgt_port_wwn.raw_wwn[2],
7683                     ptgt->tgt_port_wwn.raw_wwn[3],
7684                     ptgt->tgt_port_wwn.raw_wwn[4],
7685                     ptgt->tgt_port_wwn.raw_wwn[5],
7686                     ptgt->tgt_port_wwn.raw_wwn[6],
7687                     ptgt->tgt_port_wwn.raw_wwn[7],
7688                     nluns_claimed - nluns_bufmax);
7689 
7690                 nluns_claimed = nluns_bufmax;
7691         }
7692         ptgt->tgt_lun_cnt = nluns_claimed;
7693 
7694         /*
7695          * Identify missing LUNs and print warning messages
7696          */
7697         for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7698                 int offline;
7699                 int exists = 0;
7700 
7701                 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7702 
7703                 for (i = 0; i < nluns_claimed && exists == 0; i++) {
7704                         uchar_t         *lun_string;
7705 
7706                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7707 
7708                         switch (lun_string[0] & 0xC0) {
7709                         case FCP_LUN_ADDRESSING:
7710                         case FCP_PD_ADDRESSING:
7711                         case FCP_VOLUME_ADDRESSING:
7712                                 lun_num = ((lun_string[0] & 0x3F) << 8) |
7713                                     lun_string[1];
7714                                 if (plun->lun_num == lun_num) {
7715                                         exists++;
7716                                         break;
7717                                 }
7718                                 break;
7719 
7720                         default:
7721                                 break;
7722                         }
7723                 }
7724 
7725                 if (!exists && !offline) {
7726                         mutex_exit(&ptgt->tgt_mutex);
7727 
7728                         mutex_enter(&pptr->port_mutex);
7729                         mutex_enter(&ptgt->tgt_mutex);
7730                         if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7731                                 /*
7732                                  * set disappear flag when device was connected
7733                                  */
7734                                 if (!(plun->lun_state &
7735                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7736                                         plun->lun_state |= FCP_LUN_DISAPPEARED;
7737                                 }
7738                                 mutex_exit(&ptgt->tgt_mutex);
7739                                 mutex_exit(&pptr->port_mutex);
7740                                 if (!(plun->lun_state &
7741                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7742                                         fcp_log(CE_NOTE, pptr->port_dip,
7743                                             "!Lun=%x for target=%x disappeared",
7744                                             plun->lun_num, ptgt->tgt_d_id);
7745                                 }
7746                                 mutex_enter(&ptgt->tgt_mutex);
7747                         } else {
7748                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7749                                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7750                                     "fcp_handle_reportlun,1: state change"
7751                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
7752                                 mutex_exit(&ptgt->tgt_mutex);
7753                                 mutex_exit(&pptr->port_mutex);
7754                                 kmem_free(report_lun, len);
7755                                 (void) fcp_call_finish_init(pptr, ptgt,
7756                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7757                                     icmd->ipkt_cause);
7758                                 fcp_icmd_free(pptr, icmd);
7759                                 return;
7760                         }
7761                 } else if (exists) {
7762                         /*
7763                          * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7764                          * actually exists in REPORT_LUN response
7765                          */
7766                         if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7767                                 plun->lun_state &=
7768                                     ~FCP_LUN_DEVICE_NOT_CONNECTED;
7769                         }
7770                         if (offline || plun->lun_num == 0) {
7771                                 if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7772                                         plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7773                                         mutex_exit(&ptgt->tgt_mutex);
7774                                         fcp_log(CE_NOTE, pptr->port_dip,
7775                                             "!Lun=%x for target=%x reappeared",
7776                                             plun->lun_num, ptgt->tgt_d_id);
7777                                         mutex_enter(&ptgt->tgt_mutex);
7778                                 }
7779                         }
7780                 }
7781         }
7782 
7783         ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7784         mutex_exit(&ptgt->tgt_mutex);
7785 
7786         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7787             fcp_trace, FCP_BUF_LEVEL_5, 0,
7788             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7789             pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7790 
7791         /* scan each lun */
7792         for (i = 0; i < nluns_claimed; i++) {
7793                 uchar_t *lun_string;
7794 
7795                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7796 
7797                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7798                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7799                     "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7800                     " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7801                     lun_string[0]);
7802 
7803                 switch (lun_string[0] & 0xC0) {
7804                 case FCP_LUN_ADDRESSING:
7805                 case FCP_PD_ADDRESSING:
7806                 case FCP_VOLUME_ADDRESSING:
7807                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7808 
7809                         /* We will skip masked LUNs because of the blacklist. */
7810                         if (fcp_lun_blacklist != NULL) {
7811                                 mutex_enter(&ptgt->tgt_mutex);
7812                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
7813                                     lun_num) == TRUE) {
7814                                         ptgt->tgt_lun_cnt--;
7815                                         mutex_exit(&ptgt->tgt_mutex);
7816                                         break;
7817                                 }
7818                                 mutex_exit(&ptgt->tgt_mutex);
7819                         }
7820 
7821                         /* see if this LUN is already allocated */
7822                         if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7823                                 plun = fcp_alloc_lun(ptgt);
7824                                 if (plun == NULL) {
7825                                         fcp_log(CE_NOTE, pptr->port_dip,
7826                                             "!Lun allocation failed"
7827                                             " target=%x lun=%x",
7828                                             ptgt->tgt_d_id, lun_num);
7829                                         break;
7830                                 }
7831                         }
7832 
7833                         mutex_enter(&plun->lun_tgt->tgt_mutex);
7834                         /* convert to LUN */
7835                         plun->lun_addr.ent_addr_0 =
7836                             BE_16(*(uint16_t *)&(lun_string[0]));
7837                         plun->lun_addr.ent_addr_1 =
7838                             BE_16(*(uint16_t *)&(lun_string[2]));
7839                         plun->lun_addr.ent_addr_2 =
7840                             BE_16(*(uint16_t *)&(lun_string[4]));
7841                         plun->lun_addr.ent_addr_3 =
7842                             BE_16(*(uint16_t *)&(lun_string[6]));
7843 
7844                         plun->lun_num = lun_num;
7845                         plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7846                         plun->lun_state &= ~FCP_LUN_OFFLINE;
7847                         mutex_exit(&plun->lun_tgt->tgt_mutex);
7848 
7849                         /* Retrieve the rscn count (if a valid one exists) */
7850                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7851                                 rscn_count = ((fc_ulp_rscn_info_t *)
7852                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7853                                     ulp_rscn_count;
7854                         } else {
7855                                 rscn_count = FC_INVALID_RSCN_COUNT;
7856                         }
7857 
7858                         if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7859                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7860                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7861                                 mutex_enter(&pptr->port_mutex);
7862                                 mutex_enter(&plun->lun_tgt->tgt_mutex);
7863                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7864                                         fcp_log(CE_NOTE, pptr->port_dip,
7865                                             "!failed to send INQUIRY"
7866                                             " target=%x lun=%x",
7867                                             ptgt->tgt_d_id, plun->lun_num);
7868                                 } else {
7869                                         FCP_TRACE(fcp_logq,
7870                                             pptr->port_instbuf, fcp_trace,
7871                                             FCP_BUF_LEVEL_5, 0,
7872                                             "fcp_handle_reportlun,2: state"
7873                                             " change occured for D_ID=0x%x",
7874                                             ptgt->tgt_d_id);
7875                                 }
7876                                 mutex_exit(&plun->lun_tgt->tgt_mutex);
7877                                 mutex_exit(&pptr->port_mutex);
7878                         } else {
7879                                 continue;
7880                         }
7881                         break;
7882 
7883                 default:
7884                         fcp_log(CE_WARN, NULL,
7885                             "!Unsupported LUN Addressing method %x "
7886                             "in response to REPORT_LUN", lun_string[0]);
7887                         break;
7888                 }
7889 
7890                 /*
7891                  * each time through this loop we should decrement
7892                  * the tmp_cnt by one -- since we go through this loop
7893                  * one time for each LUN, the tmp_cnt should never be <=0
7894                  */
7895                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7896                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7897         }
7898 
7899         if (i == 0) {
7900                 fcp_log(CE_WARN, pptr->port_dip,
7901                     "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7902                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7903                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7904         }
7905 
7906         kmem_free(report_lun, len);
7907         fcp_icmd_free(pptr, icmd);
7908 }
7909 
7910 
7911 /*
7912  * called internally to return a LUN given a target and a LUN number
7913  */
7914 static struct fcp_lun *
7915 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7916 {
7917         struct fcp_lun  *plun;
7918 
7919         mutex_enter(&ptgt->tgt_mutex);
7920         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7921                 if (plun->lun_num == lun_num) {
7922                         mutex_exit(&ptgt->tgt_mutex);
7923                         return (plun);
7924                 }
7925         }
7926         mutex_exit(&ptgt->tgt_mutex);
7927 
7928         return (NULL);
7929 }
7930 
7931 
7932 /*
7933  * handle finishing one target for fcp_finish_init
7934  *
7935  * return true (non-zero) if we want finish_init to continue with the
7936  * next target
7937  *
7938  * called with the port mutex held
7939  */
7940 /*ARGSUSED*/
7941 static int
7942 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7943     int link_cnt, int tgt_cnt, int cause)
7944 {
7945         int     rval = 1;
7946         ASSERT(pptr != NULL);
7947         ASSERT(ptgt != NULL);
7948 
7949         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7950             fcp_trace, FCP_BUF_LEVEL_5, 0,
7951             "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7952             ptgt->tgt_state);
7953 
7954         ASSERT(mutex_owned(&pptr->port_mutex));
7955 
7956         if ((pptr->port_link_cnt != link_cnt) ||
7957             (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7958                 /*
7959                  * oh oh -- another link reset or target change
7960                  * must have occurred while we are in here
7961                  */
7962                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7963 
7964                 return (0);
7965         } else {
7966                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7967         }
7968 
7969         mutex_enter(&ptgt->tgt_mutex);
7970 
7971         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7972                 /*
7973                  * tgt is not offline -- is it marked (i.e. needs
7974                  * to be offlined) ??
7975                  */
7976                 if (ptgt->tgt_state & FCP_TGT_MARK) {
7977                         /*
7978                          * this target not offline *and*
7979                          * marked
7980                          */
7981                         ptgt->tgt_state &= ~FCP_TGT_MARK;
7982                         rval = fcp_offline_target(pptr, ptgt, link_cnt,
7983                             tgt_cnt, 0, 0);
7984                 } else {
7985                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
7986 
7987                         /* create the LUNs */
7988                         if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7989                                 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7990                                 fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7991                                     cause);
7992                                 ptgt->tgt_device_created = 1;
7993                         } else {
7994                                 fcp_update_tgt_state(ptgt, FCP_RESET,
7995                                     FCP_LUN_BUSY);
7996                         }
7997                 }
7998         }
7999 
8000         mutex_exit(&ptgt->tgt_mutex);
8001 
8002         return (rval);
8003 }
8004 
8005 
8006 /*
8007  * this routine is called to finish port initialization
8008  *
8009  * Each port has a "temp" counter -- when a state change happens (e.g.
8010  * port online), the temp count is set to the number of devices in the map.
8011  * Then, as each device gets "discovered", the temp counter is decremented
8012  * by one.  When this count reaches zero we know that all of the devices
8013  * in the map have been discovered (or an error has occurred), so we can
8014  * then finish initialization -- which is done by this routine (well, this
8015  * and fcp-finish_tgt())
8016  *
8017  * acquires and releases the global mutex
8018  *
8019  * called with the port mutex owned
8020  */
8021 static void
8022 fcp_finish_init(struct fcp_port *pptr)
8023 {
8024 #ifdef  DEBUG
8025         bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8026         pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8027             FCP_STACK_DEPTH);
8028 #endif /* DEBUG */
8029 
8030         ASSERT(mutex_owned(&pptr->port_mutex));
8031 
8032         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8033             fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8034             " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8035 
8036         if ((pptr->port_state & FCP_STATE_ONLINING) &&
8037             !(pptr->port_state & (FCP_STATE_SUSPENDED |
8038             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8039                 pptr->port_state &= ~FCP_STATE_ONLINING;
8040                 pptr->port_state |= FCP_STATE_ONLINE;
8041         }
8042 
8043         /* Wake up threads waiting on config done */
8044         cv_broadcast(&pptr->port_config_cv);
8045 }
8046 
8047 
8048 /*
8049  * called from fcp_finish_init to create the LUNs for a target
8050  *
8051  * called with the port mutex owned
8052  */
8053 static void
8054 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8055 {
8056         struct fcp_lun  *plun;
8057         struct fcp_port *pptr;
8058         child_info_t            *cip = NULL;
8059 
8060         ASSERT(ptgt != NULL);
8061         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8062 
8063         pptr = ptgt->tgt_port;
8064 
8065         ASSERT(pptr != NULL);
8066 
8067         /* scan all LUNs for this target */
8068         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8069                 if (plun->lun_state & FCP_LUN_OFFLINE) {
8070                         continue;
8071                 }
8072 
8073                 if (plun->lun_state & FCP_LUN_MARK) {
8074                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8075                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8076                             "fcp_create_luns: offlining marked LUN!");
8077                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8078                         continue;
8079                 }
8080 
8081                 plun->lun_state &= ~FCP_LUN_BUSY;
8082 
8083                 /*
8084                  * There are conditions in which FCP_LUN_INIT flag is cleared
8085                  * but we have a valid plun->lun_cip. To cover this case also
8086                  * CLEAR_BUSY whenever we have a valid lun_cip.
8087                  */
8088                 if (plun->lun_mpxio && plun->lun_cip &&
8089                     (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8090                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8091                     0, 0))) {
8092                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8093                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8094                             "fcp_create_luns: enable lun %p failed!",
8095                             plun);
8096                 }
8097 
8098                 if (plun->lun_state & FCP_LUN_INIT &&
8099                     !(plun->lun_state & FCP_LUN_CHANGED)) {
8100                         continue;
8101                 }
8102 
8103                 if (cause == FCP_CAUSE_USER_CREATE) {
8104                         continue;
8105                 }
8106 
8107                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8108                     fcp_trace, FCP_BUF_LEVEL_6, 0,
8109                     "create_luns: passing ONLINE elem to HP thread");
8110 
8111                 /*
8112                  * If lun has changed, prepare for offlining the old path.
8113                  * Do not offline the old path right now, since it may be
8114                  * still opened.
8115                  */
8116                 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8117                         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8118                 }
8119 
8120                 /* pass an ONLINE element to the hotplug thread */
8121                 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8122                     link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8123 
8124                         /*
8125                          * We can not synchronous attach (i.e pass
8126                          * NDI_ONLINE_ATTACH) here as we might be
8127                          * coming from an interrupt or callback
8128                          * thread.
8129                          */
8130                         if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8131                             link_cnt, tgt_cnt, 0, 0)) {
8132                                 fcp_log(CE_CONT, pptr->port_dip,
8133                                     "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8134                                     plun->lun_tgt->tgt_d_id, plun->lun_num);
8135                         }
8136                 }
8137         }
8138 }
8139 
8140 
8141 /*
8142  * function to online/offline devices
8143  */
8144 static int
8145 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8146     int online, int lcount, int tcount, int flags)
8147 {
8148         int                     rval = NDI_FAILURE;
8149         int                     circ;
8150         child_info_t            *ccip;
8151         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
8152         int                     is_mpxio = pptr->port_mpxio;
8153         dev_info_t              *cdip, *pdip;
8154         char                    *devname;
8155 
8156         if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8157                 /*
8158                  * When this event gets serviced, lun_cip and lun_mpxio
8159                  * has changed, so it should be invalidated now.
8160                  */
8161                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8162                     FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8163                     "plun: %p, cip: %p, what:%d", plun, cip, online);
8164                 return (rval);
8165         }
8166 
8167         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8168             fcp_trace, FCP_BUF_LEVEL_2, 0,
8169             "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8170             "flags=%x mpxio=%x\n",
8171             plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8172             plun->lun_mpxio);
8173 
8174         /*
8175          * lun_mpxio needs checking here because we can end up in a race
8176          * condition where this task has been dispatched while lun_mpxio is
8177          * set, but an earlier FCP_ONLINE task for the same LUN tried to
8178          * enable MPXIO for the LUN, but was unable to, and hence cleared
8179          * the flag. We rely on the serialization of the tasks here. We return
8180          * NDI_SUCCESS so any callers continue without reporting spurious
8181          * errors, and the still think we're an MPXIO LUN.
8182          */
8183 
8184         if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8185             online == FCP_MPXIO_PATH_SET_BUSY) {
8186                 if (plun->lun_mpxio) {
8187                         rval = fcp_update_mpxio_path(plun, cip, online);
8188                 } else {
8189                         rval = NDI_SUCCESS;
8190                 }
8191                 return (rval);
8192         }
8193 
8194         /*
8195          * Explicit devfs_clean() due to ndi_devi_offline() not
8196          * executing devfs_clean() if parent lock is held.
8197          */
8198         ASSERT(!servicing_interrupt());
8199         if (online == FCP_OFFLINE) {
8200                 if (plun->lun_mpxio == 0) {
8201                         if (plun->lun_cip == cip) {
8202                                 cdip = DIP(plun->lun_cip);
8203                         } else {
8204                                 cdip = DIP(cip);
8205                         }
8206                 } else if ((plun->lun_cip == cip) && plun->lun_cip) {
8207                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8208                 } else if ((plun->lun_cip != cip) && cip) {
8209                         /*
8210                          * This means a DTYPE/GUID change, we shall get the
8211                          * dip of the old cip instead of the current lun_cip.
8212                          */
8213                         cdip = mdi_pi_get_client(PIP(cip));
8214                 }
8215                 if (cdip) {
8216                         if (i_ddi_devi_attached(cdip)) {
8217                                 pdip = ddi_get_parent(cdip);
8218                                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8219                                 ndi_devi_enter(pdip, &circ);
8220                                 (void) ddi_deviname(cdip, devname);
8221                                 ndi_devi_exit(pdip, circ);
8222                                 /*
8223                                  * Release parent lock before calling
8224                                  * devfs_clean().
8225                                  */
8226                                 rval = devfs_clean(pdip, devname + 1,
8227                                     DV_CLEAN_FORCE);
8228                                 kmem_free(devname, MAXNAMELEN + 1);
8229                                 /*
8230                                  * Return if devfs_clean() fails for
8231                                  * non-MPXIO case.
8232                                  * For MPXIO case, another path could be
8233                                  * offlined.
8234                                  */
8235                                 if (rval && plun->lun_mpxio == 0) {
8236                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8237                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8238                                             "fcp_trigger_lun: devfs_clean "
8239                                             "failed rval=%x  dip=%p",
8240                                             rval, pdip);
8241                                         return (NDI_FAILURE);
8242                                 }
8243                         }
8244                 }
8245         }
8246 
8247         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8248                 return (NDI_FAILURE);
8249         }
8250 
8251         if (is_mpxio) {
8252                 mdi_devi_enter(pptr->port_dip, &circ);
8253         } else {
8254                 ndi_devi_enter(pptr->port_dip, &circ);
8255         }
8256 
8257         mutex_enter(&pptr->port_mutex);
8258         mutex_enter(&plun->lun_mutex);
8259 
8260         if (online == FCP_ONLINE) {
8261                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8262                 if (ccip == NULL) {
8263                         goto fail;
8264                 }
8265         } else {
8266                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8267                         goto fail;
8268                 }
8269                 ccip = cip;
8270         }
8271 
8272         if (online == FCP_ONLINE) {
8273                 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8274                     &circ);
8275                 fc_ulp_log_device_event(pptr->port_fp_handle,
8276                     FC_ULP_DEVICE_ONLINE);
8277         } else {
8278                 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8279                     &circ);
8280                 fc_ulp_log_device_event(pptr->port_fp_handle,
8281                     FC_ULP_DEVICE_OFFLINE);
8282         }
8283 
8284 fail:   mutex_exit(&plun->lun_mutex);
8285         mutex_exit(&pptr->port_mutex);
8286 
8287         if (is_mpxio) {
8288                 mdi_devi_exit(pptr->port_dip, circ);
8289         } else {
8290                 ndi_devi_exit(pptr->port_dip, circ);
8291         }
8292 
8293         fc_ulp_idle_port(pptr->port_fp_handle);
8294 
8295         return (rval);
8296 }
8297 
8298 
8299 /*
8300  * take a target offline by taking all of its LUNs offline
8301  */
8302 /*ARGSUSED*/
8303 static int
8304 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8305     int link_cnt, int tgt_cnt, int nowait, int flags)
8306 {
8307         struct fcp_tgt_elem     *elem;
8308 
8309         ASSERT(mutex_owned(&pptr->port_mutex));
8310         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8311 
8312         ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8313 
8314         if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8315             ptgt->tgt_change_cnt)) {
8316                 mutex_exit(&ptgt->tgt_mutex);
8317                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8318                 mutex_enter(&ptgt->tgt_mutex);
8319 
8320                 return (0);
8321         }
8322 
8323         ptgt->tgt_pd_handle = NULL;
8324         mutex_exit(&ptgt->tgt_mutex);
8325         FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8326         mutex_enter(&ptgt->tgt_mutex);
8327 
8328         tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8329 
8330         if (ptgt->tgt_tcap &&
8331             (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8332                 elem->flags = flags;
8333                 elem->time = fcp_watchdog_time;
8334                 if (nowait == 0) {
8335                         elem->time += fcp_offline_delay;
8336                 }
8337                 elem->ptgt = ptgt;
8338                 elem->link_cnt = link_cnt;
8339                 elem->tgt_cnt = tgt_cnt;
8340                 elem->next = pptr->port_offline_tgts;
8341                 pptr->port_offline_tgts = elem;
8342         } else {
8343                 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8344         }
8345 
8346         return (1);
8347 }
8348 
8349 
8350 static void
8351 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8352     int link_cnt, int tgt_cnt, int flags)
8353 {
8354         ASSERT(mutex_owned(&pptr->port_mutex));
8355         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8356 
8357         fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8358         ptgt->tgt_state = FCP_TGT_OFFLINE;
8359         ptgt->tgt_pd_handle = NULL;
8360         fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8361 }
8362 
8363 
8364 static void
8365 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8366     int flags)
8367 {
8368         struct  fcp_lun *plun;
8369 
8370         ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8371         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8372 
8373         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8374                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8375                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8376                 }
8377         }
8378 }
8379 
8380 
8381 /*
8382  * take a LUN offline
8383  *
8384  * enters and leaves with the target mutex held, releasing it in the process
8385  *
8386  * allocates memory in non-sleep mode
8387  */
8388 static void
8389 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8390     int nowait, int flags)
8391 {
8392         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
8393         struct fcp_lun_elem     *elem;
8394 
8395         ASSERT(plun != NULL);
8396         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8397 
8398         if (nowait) {
8399                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8400                 return;
8401         }
8402 
8403         if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8404                 elem->flags = flags;
8405                 elem->time = fcp_watchdog_time;
8406                 if (nowait == 0) {
8407                         elem->time += fcp_offline_delay;
8408                 }
8409                 elem->plun = plun;
8410                 elem->link_cnt = link_cnt;
8411                 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8412                 elem->next = pptr->port_offline_luns;
8413                 pptr->port_offline_luns = elem;
8414         } else {
8415                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8416         }
8417 }
8418 
8419 
8420 static void
8421 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8422 {
8423         struct fcp_pkt  *head = NULL;
8424 
8425         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8426 
8427         mutex_exit(&LUN_TGT->tgt_mutex);
8428 
8429         head = fcp_scan_commands(plun);
8430         if (head != NULL) {
8431                 fcp_abort_commands(head, LUN_PORT);
8432         }
8433 
8434         mutex_enter(&LUN_TGT->tgt_mutex);
8435 
8436         if (plun->lun_cip && plun->lun_mpxio) {
8437                 /*
8438                  * Intimate MPxIO lun busy is cleared
8439                  */
8440                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8441                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8442                     0, 0)) {
8443                         fcp_log(CE_NOTE, LUN_PORT->port_dip,
8444                             "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8445                             LUN_TGT->tgt_d_id, plun->lun_num);
8446                 }
8447                 /*
8448                  * Intimate MPxIO that the lun is now marked for offline
8449                  */
8450                 mutex_exit(&LUN_TGT->tgt_mutex);
8451                 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8452                 mutex_enter(&LUN_TGT->tgt_mutex);
8453         }
8454 }
8455 
8456 static void
8457 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8458     int flags)
8459 {
8460         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8461 
8462         mutex_exit(&LUN_TGT->tgt_mutex);
8463         fcp_update_offline_flags(plun);
8464         mutex_enter(&LUN_TGT->tgt_mutex);
8465 
8466         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8467 
8468         FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8469             fcp_trace, FCP_BUF_LEVEL_4, 0,
8470             "offline_lun: passing OFFLINE elem to HP thread");
8471 
8472         if (plun->lun_cip) {
8473                 fcp_log(CE_NOTE, LUN_PORT->port_dip,
8474                     "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8475                     plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8476                     LUN_TGT->tgt_trace);
8477 
8478                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8479                     link_cnt, tgt_cnt, flags, 0)) {
8480                         fcp_log(CE_CONT, LUN_PORT->port_dip,
8481                             "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8482                             LUN_TGT->tgt_d_id, plun->lun_num);
8483                 }
8484         }
8485 }
8486 
8487 static void
8488 fcp_scan_offline_luns(struct fcp_port *pptr)
8489 {
8490         struct fcp_lun_elem     *elem;
8491         struct fcp_lun_elem     *prev;
8492         struct fcp_lun_elem     *next;
8493 
8494         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8495 
8496         prev = NULL;
8497         elem = pptr->port_offline_luns;
8498         while (elem) {
8499                 next = elem->next;
8500                 if (elem->time <= fcp_watchdog_time) {
8501                         int                     changed = 1;
8502                         struct fcp_tgt  *ptgt = elem->plun->lun_tgt;
8503 
8504                         mutex_enter(&ptgt->tgt_mutex);
8505                         if (pptr->port_link_cnt == elem->link_cnt &&
8506                             ptgt->tgt_change_cnt == elem->tgt_cnt) {
8507                                 changed = 0;
8508                         }
8509 
8510                         if (!changed &&
8511                             !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8512                                 fcp_offline_lun_now(elem->plun,
8513                                     elem->link_cnt, elem->tgt_cnt, elem->flags);
8514                         }
8515                         mutex_exit(&ptgt->tgt_mutex);
8516 
8517                         kmem_free(elem, sizeof (*elem));
8518 
8519                         if (prev) {
8520                                 prev->next = next;
8521                         } else {
8522                                 pptr->port_offline_luns = next;
8523                         }
8524                 } else {
8525                         prev = elem;
8526                 }
8527                 elem = next;
8528         }
8529 }
8530 
8531 
8532 static void
8533 fcp_scan_offline_tgts(struct fcp_port *pptr)
8534 {
8535         struct fcp_tgt_elem     *elem;
8536         struct fcp_tgt_elem     *prev;
8537         struct fcp_tgt_elem     *next;
8538 
8539         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8540 
8541         prev = NULL;
8542         elem = pptr->port_offline_tgts;
8543         while (elem) {
8544                 next = elem->next;
8545                 if (elem->time <= fcp_watchdog_time) {
8546                         int             outdated = 1;
8547                         struct fcp_tgt  *ptgt = elem->ptgt;
8548 
8549                         mutex_enter(&ptgt->tgt_mutex);
8550 
8551                         if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8552                                 /* No change on tgt since elem was created. */
8553                                 outdated = 0;
8554                         } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8555                             pptr->port_link_cnt == elem->link_cnt + 1 &&
8556                             ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8557                                 /*
8558                                  * Exactly one thing happened to the target
8559                                  * inbetween: the local port went offline.
8560                                  * For fp the remote port is already gone so
8561                                  * it will not tell us again to offline the
8562                                  * target. We must offline it now.
8563                                  */
8564                                 outdated = 0;
8565                         }
8566 
8567                         if (!outdated && !(ptgt->tgt_state &
8568                             FCP_TGT_OFFLINE)) {
8569                                 fcp_offline_target_now(pptr,
8570                                     ptgt, elem->link_cnt, elem->tgt_cnt,
8571                                     elem->flags);
8572                         }
8573 
8574                         mutex_exit(&ptgt->tgt_mutex);
8575 
8576                         kmem_free(elem, sizeof (*elem));
8577 
8578                         if (prev) {
8579                                 prev->next = next;
8580                         } else {
8581                                 pptr->port_offline_tgts = next;
8582                         }
8583                 } else {
8584                         prev = elem;
8585                 }
8586                 elem = next;
8587         }
8588 }
8589 
8590 
8591 static void
8592 fcp_update_offline_flags(struct fcp_lun *plun)
8593 {
8594         struct fcp_port *pptr = LUN_PORT;
8595         ASSERT(plun != NULL);
8596 
8597         mutex_enter(&LUN_TGT->tgt_mutex);
8598         plun->lun_state |= FCP_LUN_OFFLINE;
8599         plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8600 
8601         mutex_enter(&plun->lun_mutex);
8602         if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8603                 dev_info_t *cdip = NULL;
8604 
8605                 mutex_exit(&LUN_TGT->tgt_mutex);
8606 
8607                 if (plun->lun_mpxio == 0) {
8608                         cdip = DIP(plun->lun_cip);
8609                 } else if (plun->lun_cip) {
8610                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8611                 }
8612 
8613                 mutex_exit(&plun->lun_mutex);
8614                 if (cdip) {
8615                         (void) ndi_event_retrieve_cookie(
8616                             pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8617                             &fcp_remove_eid, NDI_EVENT_NOPASS);
8618                         (void) ndi_event_run_callbacks(
8619                             pptr->port_ndi_event_hdl, cdip,
8620                             fcp_remove_eid, NULL);
8621                 }
8622         } else {
8623                 mutex_exit(&plun->lun_mutex);
8624                 mutex_exit(&LUN_TGT->tgt_mutex);
8625         }
8626 }
8627 
8628 
8629 /*
8630  * Scan all of the command pkts for this port, moving pkts that
8631  * match our LUN onto our own list (headed by "head")
8632  */
8633 static struct fcp_pkt *
8634 fcp_scan_commands(struct fcp_lun *plun)
8635 {
8636         struct fcp_port *pptr = LUN_PORT;
8637 
8638         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8639         struct fcp_pkt  *ncmd = NULL;   /* next pkt ptr */
8640         struct fcp_pkt  *pcmd = NULL;   /* the previous command */
8641 
8642         struct fcp_pkt  *head = NULL;   /* head of our list */
8643         struct fcp_pkt  *tail = NULL;   /* tail of our list */
8644 
8645         int                     cmds_found = 0;
8646 
8647         mutex_enter(&pptr->port_pkt_mutex);
8648         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8649                 struct fcp_lun *tlun =
8650                     ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8651 
8652                 ncmd = cmd->cmd_next;        /* set next command */
8653 
8654                 /*
8655                  * if this pkt is for a different LUN  or the
8656                  * command is sent down, skip it.
8657                  */
8658                 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8659                     (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8660                         pcmd = cmd;
8661                         continue;
8662                 }
8663                 cmds_found++;
8664                 if (pcmd != NULL) {
8665                         ASSERT(pptr->port_pkt_head != cmd);
8666                         pcmd->cmd_next = cmd->cmd_next;
8667                 } else {
8668                         ASSERT(cmd == pptr->port_pkt_head);
8669                         pptr->port_pkt_head = cmd->cmd_next;
8670                 }
8671 
8672                 if (cmd == pptr->port_pkt_tail) {
8673                         pptr->port_pkt_tail = pcmd;
8674                         if (pcmd) {
8675                                 pcmd->cmd_next = NULL;
8676                         }
8677                 }
8678 
8679                 if (head == NULL) {
8680                         head = tail = cmd;
8681                 } else {
8682                         ASSERT(tail != NULL);
8683 
8684                         tail->cmd_next = cmd;
8685                         tail = cmd;
8686                 }
8687                 cmd->cmd_next = NULL;
8688         }
8689         mutex_exit(&pptr->port_pkt_mutex);
8690 
8691         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8692             fcp_trace, FCP_BUF_LEVEL_8, 0,
8693             "scan commands: %d cmd(s) found", cmds_found);
8694 
8695         return (head);
8696 }
8697 
8698 
8699 /*
8700  * Abort all the commands in the command queue
8701  */
8702 static void
8703 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8704 {
8705         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8706         struct  fcp_pkt *ncmd = NULL;   /* next pkt ptr */
8707 
8708         ASSERT(mutex_owned(&pptr->port_mutex));
8709 
8710         /* scan through the pkts and invalid them */
8711         for (cmd = head; cmd != NULL; cmd = ncmd) {
8712                 struct scsi_pkt *pkt = cmd->cmd_pkt;
8713 
8714                 ncmd = cmd->cmd_next;
8715                 ASSERT(pkt != NULL);
8716 
8717                 /*
8718                  * The lun is going to be marked offline. Indicate
8719                  * the target driver not to requeue or retry this command
8720                  * as the device is going to be offlined pretty soon.
8721                  */
8722                 pkt->pkt_reason = CMD_DEV_GONE;
8723                 pkt->pkt_statistics = 0;
8724                 pkt->pkt_state = 0;
8725 
8726                 /* reset cmd flags/state */
8727                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8728                 cmd->cmd_state = FCP_PKT_IDLE;
8729 
8730                 /*
8731                  * ensure we have a packet completion routine,
8732                  * then call it.
8733                  */
8734                 ASSERT(pkt->pkt_comp != NULL);
8735 
8736                 mutex_exit(&pptr->port_mutex);
8737                 fcp_post_callback(cmd);
8738                 mutex_enter(&pptr->port_mutex);
8739         }
8740 }
8741 
8742 
8743 /*
8744  * the pkt_comp callback for command packets
8745  */
8746 static void
8747 fcp_cmd_callback(fc_packet_t *fpkt)
8748 {
8749         struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8750         struct scsi_pkt *pkt = cmd->cmd_pkt;
8751         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8752 
8753         ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8754 
8755         if (cmd->cmd_state == FCP_PKT_IDLE) {
8756                 cmn_err(CE_PANIC, "Packet already completed %p",
8757                     (void *)cmd);
8758         }
8759 
8760         /*
8761          * Watch thread should be freeing the packet, ignore the pkt.
8762          */
8763         if (cmd->cmd_state == FCP_PKT_ABORTING) {
8764                 fcp_log(CE_CONT, pptr->port_dip,
8765                     "!FCP: Pkt completed while aborting\n");
8766                 return;
8767         }
8768         cmd->cmd_state = FCP_PKT_IDLE;
8769 
8770         fcp_complete_pkt(fpkt);
8771 
8772 #ifdef  DEBUG
8773         mutex_enter(&pptr->port_pkt_mutex);
8774         pptr->port_npkts--;
8775         mutex_exit(&pptr->port_pkt_mutex);
8776 #endif /* DEBUG */
8777 
8778         fcp_post_callback(cmd);
8779 }
8780 
8781 
8782 static void
8783 fcp_complete_pkt(fc_packet_t *fpkt)
8784 {
8785         int                     error = 0;
8786         struct fcp_pkt  *cmd = (struct fcp_pkt *)
8787             fpkt->pkt_ulp_private;
8788         struct scsi_pkt         *pkt = cmd->cmd_pkt;
8789         struct fcp_port         *pptr = ADDR2FCP(&pkt->pkt_address);
8790         struct fcp_lun  *plun;
8791         struct fcp_tgt  *ptgt;
8792         struct fcp_rsp          *rsp;
8793         struct scsi_address     save;
8794 
8795 #ifdef  DEBUG
8796         save = pkt->pkt_address;
8797 #endif /* DEBUG */
8798 
8799         rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8800 
8801         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8802                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8803                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8804                             sizeof (struct fcp_rsp));
8805                 }
8806 
8807                 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8808                     STATE_SENT_CMD | STATE_GOT_STATUS;
8809 
8810                 pkt->pkt_resid = 0;
8811 
8812                 if (fpkt->pkt_datalen) {
8813                         pkt->pkt_state |= STATE_XFERRED_DATA;
8814                         if (fpkt->pkt_data_resid) {
8815                                 error++;
8816                         }
8817                 }
8818 
8819                 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8820                     rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8821                         /*
8822                          * The next two checks make sure that if there
8823                          * is no sense data or a valid response and
8824                          * the command came back with check condition,
8825                          * the command should be retried.
8826                          */
8827                         if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8828                             !rsp->fcp_u.fcp_status.sense_len_set) {
8829                                 pkt->pkt_state &= ~STATE_XFERRED_DATA;
8830                                 pkt->pkt_resid = cmd->cmd_dmacount;
8831                         }
8832                 }
8833 
8834                 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8835                         return;
8836                 }
8837 
8838                 plun = ADDR2LUN(&pkt->pkt_address);
8839                 ptgt = plun->lun_tgt;
8840                 ASSERT(ptgt != NULL);
8841 
8842                 /*
8843                  * Update the transfer resid, if appropriate
8844                  */
8845                 if (rsp->fcp_u.fcp_status.resid_over ||
8846                     rsp->fcp_u.fcp_status.resid_under) {
8847                         pkt->pkt_resid = rsp->fcp_resid;
8848                 }
8849 
8850                 /*
8851                  * First see if we got a FCP protocol error.
8852                  */
8853                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
8854                         struct fcp_rsp_info     *bep;
8855                         bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8856                             sizeof (struct fcp_rsp));
8857 
8858                         if (fcp_validate_fcp_response(rsp, pptr) !=
8859                             FC_SUCCESS) {
8860                                 pkt->pkt_reason = CMD_CMPLT;
8861                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8862 
8863                                 fcp_log(CE_WARN, pptr->port_dip,
8864                                     "!SCSI command to d_id=0x%x lun=0x%x"
8865                                     " failed, Bad FCP response values:"
8866                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8867                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8868                                     ptgt->tgt_d_id, plun->lun_num,
8869                                     rsp->reserved_0, rsp->reserved_1,
8870                                     rsp->fcp_u.fcp_status.reserved_0,
8871                                     rsp->fcp_u.fcp_status.reserved_1,
8872                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8873 
8874                                 return;
8875                         }
8876 
8877                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8878                                 FCP_CP_IN(fpkt->pkt_resp +
8879                                     sizeof (struct fcp_rsp), bep,
8880                                     fpkt->pkt_resp_acc,
8881                                     sizeof (struct fcp_rsp_info));
8882                         }
8883 
8884                         if (bep->rsp_code != FCP_NO_FAILURE) {
8885                                 child_info_t    *cip;
8886 
8887                                 pkt->pkt_reason = CMD_TRAN_ERR;
8888 
8889                                 mutex_enter(&plun->lun_mutex);
8890                                 cip = plun->lun_cip;
8891                                 mutex_exit(&plun->lun_mutex);
8892 
8893                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8894                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
8895                                     "FCP response error on cmd=%p"
8896                                     " target=0x%x, cip=%p", cmd,
8897                                     ptgt->tgt_d_id, cip);
8898                         }
8899                 }
8900 
8901                 /*
8902                  * See if we got a SCSI error with sense data
8903                  */
8904                 if (rsp->fcp_u.fcp_status.sense_len_set) {
8905                         uchar_t                         rqlen;
8906                         caddr_t                         sense_from;
8907                         child_info_t                    *cip;
8908                         timeout_id_t                    tid;
8909                         struct scsi_arq_status          *arq;
8910                         struct scsi_extended_sense      *sense_to;
8911 
8912                         arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8913                         sense_to = &arq->sts_sensedata;
8914 
8915                         rqlen = (uchar_t)min(rsp->fcp_sense_len,
8916                             sizeof (struct scsi_extended_sense));
8917 
8918                         sense_from = (caddr_t)fpkt->pkt_resp +
8919                             sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8920 
8921                         if (fcp_validate_fcp_response(rsp, pptr) !=
8922                             FC_SUCCESS) {
8923                                 pkt->pkt_reason = CMD_CMPLT;
8924                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8925 
8926                                 fcp_log(CE_WARN, pptr->port_dip,
8927                                     "!SCSI command to d_id=0x%x lun=0x%x"
8928                                     " failed, Bad FCP response values:"
8929                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8930                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8931                                     ptgt->tgt_d_id, plun->lun_num,
8932                                     rsp->reserved_0, rsp->reserved_1,
8933                                     rsp->fcp_u.fcp_status.reserved_0,
8934                                     rsp->fcp_u.fcp_status.reserved_1,
8935                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8936 
8937                                 return;
8938                         }
8939 
8940                         /*
8941                          * copy in sense information
8942                          */
8943                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8944                                 FCP_CP_IN(sense_from, sense_to,
8945                                     fpkt->pkt_resp_acc, rqlen);
8946                         } else {
8947                                 bcopy(sense_from, sense_to, rqlen);
8948                         }
8949 
8950                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8951                             (FCP_SENSE_NO_LUN(sense_to))) {
8952                                 mutex_enter(&ptgt->tgt_mutex);
8953                                 if (ptgt->tgt_tid == NULL) {
8954                                         /*
8955                                          * Kick off rediscovery
8956                                          */
8957                                         tid = timeout(fcp_reconfigure_luns,
8958                                             (caddr_t)ptgt, drv_usectohz(1));
8959 
8960                                         ptgt->tgt_tid = tid;
8961                                         ptgt->tgt_state |= FCP_TGT_BUSY;
8962                                 }
8963                                 mutex_exit(&ptgt->tgt_mutex);
8964                                 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8965                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8966                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8967                                             "!FCP: Report Lun Has Changed"
8968                                             " target=%x", ptgt->tgt_d_id);
8969                                 } else if (FCP_SENSE_NO_LUN(sense_to)) {
8970                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8971                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8972                                             "!FCP: LU Not Supported"
8973                                             " target=%x", ptgt->tgt_d_id);
8974                                 }
8975                         }
8976                         ASSERT(pkt->pkt_scbp != NULL);
8977 
8978                         pkt->pkt_state |= STATE_ARQ_DONE;
8979 
8980                         arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8981 
8982                         *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8983                         arq->sts_rqpkt_reason = 0;
8984                         arq->sts_rqpkt_statistics = 0;
8985 
8986                         arq->sts_rqpkt_state = STATE_GOT_BUS |
8987                             STATE_GOT_TARGET | STATE_SENT_CMD |
8988                             STATE_GOT_STATUS | STATE_ARQ_DONE |
8989                             STATE_XFERRED_DATA;
8990 
8991                         mutex_enter(&plun->lun_mutex);
8992                         cip = plun->lun_cip;
8993                         mutex_exit(&plun->lun_mutex);
8994 
8995                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8996                             fcp_trace, FCP_BUF_LEVEL_8, 0,
8997                             "SCSI Check condition on cmd=%p target=0x%x"
8998                             " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
8999                             " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9000                             cmd->cmd_fcp_cmd.fcp_cdb[0],
9001                             rsp->fcp_u.fcp_status.scsi_status,
9002                             sense_to->es_key, sense_to->es_add_code,
9003                             sense_to->es_qual_code);
9004                 }
9005         } else {
9006                 plun = ADDR2LUN(&pkt->pkt_address);
9007                 ptgt = plun->lun_tgt;
9008                 ASSERT(ptgt != NULL);
9009 
9010                 /*
9011                  * Work harder to translate errors into target driver
9012                  * understandable ones. Note with despair that the target
9013                  * drivers don't decode pkt_state and pkt_reason exhaustively
9014                  * They resort to using the big hammer most often, which
9015                  * may not get fixed in the life time of this driver.
9016                  */
9017                 pkt->pkt_state = 0;
9018                 pkt->pkt_statistics = 0;
9019 
9020                 switch (fpkt->pkt_state) {
9021                 case FC_PKT_TRAN_ERROR:
9022                         switch (fpkt->pkt_reason) {
9023                         case FC_REASON_OVERRUN:
9024                                 pkt->pkt_reason = CMD_CMD_OVR;
9025                                 pkt->pkt_statistics |= STAT_ABORTED;
9026                                 break;
9027 
9028                         case FC_REASON_XCHG_BSY: {
9029                                 caddr_t ptr;
9030 
9031                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9032 
9033                                 ptr = (caddr_t)pkt->pkt_scbp;
9034                                 if (ptr) {
9035                                         *ptr = STATUS_BUSY;
9036                                 }
9037                                 break;
9038                         }
9039 
9040                         case FC_REASON_ABORTED:
9041                                 pkt->pkt_reason = CMD_TRAN_ERR;
9042                                 pkt->pkt_statistics |= STAT_ABORTED;
9043                                 break;
9044 
9045                         case FC_REASON_ABORT_FAILED:
9046                                 pkt->pkt_reason = CMD_ABORT_FAIL;
9047                                 break;
9048 
9049                         case FC_REASON_NO_SEQ_INIT:
9050                         case FC_REASON_CRC_ERROR:
9051                                 pkt->pkt_reason = CMD_TRAN_ERR;
9052                                 pkt->pkt_statistics |= STAT_ABORTED;
9053                                 break;
9054                         default:
9055                                 pkt->pkt_reason = CMD_TRAN_ERR;
9056                                 break;
9057                         }
9058                         break;
9059 
9060                 case FC_PKT_PORT_OFFLINE: {
9061                         dev_info_t      *cdip = NULL;
9062                         caddr_t         ptr;
9063 
9064                         if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9065                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9066                                     fcp_trace, FCP_BUF_LEVEL_8, 0,
9067                                     "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9068                                     ptgt->tgt_d_id);
9069                         }
9070 
9071                         mutex_enter(&plun->lun_mutex);
9072                         if (plun->lun_mpxio == 0) {
9073                                 cdip = DIP(plun->lun_cip);
9074                         } else if (plun->lun_cip) {
9075                                 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9076                         }
9077 
9078                         mutex_exit(&plun->lun_mutex);
9079 
9080                         if (cdip) {
9081                                 (void) ndi_event_retrieve_cookie(
9082                                     pptr->port_ndi_event_hdl, cdip,
9083                                     FCAL_REMOVE_EVENT, &fcp_remove_eid,
9084                                     NDI_EVENT_NOPASS);
9085                                 (void) ndi_event_run_callbacks(
9086                                     pptr->port_ndi_event_hdl, cdip,
9087                                     fcp_remove_eid, NULL);
9088                         }
9089 
9090                         /*
9091                          * If the link goes off-line for a lip,
9092                          * this will cause a error to the ST SG
9093                          * SGEN drivers. By setting BUSY we will
9094                          * give the drivers the chance to retry
9095                          * before it blows of the job. ST will
9096                          * remember how many times it has retried.
9097                          */
9098 
9099                         if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9100                             (plun->lun_type == DTYPE_CHANGER)) {
9101                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9102                                 ptr = (caddr_t)pkt->pkt_scbp;
9103                                 if (ptr) {
9104                                         *ptr = STATUS_BUSY;
9105                                 }
9106                         } else {
9107                                 pkt->pkt_reason = CMD_TRAN_ERR;
9108                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9109                         }
9110                         break;
9111                 }
9112 
9113                 case FC_PKT_TRAN_BSY:
9114                         /*
9115                          * Use the ssd Qfull handling here.
9116                          */
9117                         *pkt->pkt_scbp = STATUS_INTERMEDIATE;
9118                         pkt->pkt_state = STATE_GOT_BUS;
9119                         break;
9120 
9121                 case FC_PKT_TIMEOUT:
9122                         pkt->pkt_reason = CMD_TIMEOUT;
9123                         if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9124                                 pkt->pkt_statistics |= STAT_TIMEOUT;
9125                         } else {
9126                                 pkt->pkt_statistics |= STAT_ABORTED;
9127                         }
9128                         break;
9129 
9130                 case FC_PKT_LOCAL_RJT:
9131                         switch (fpkt->pkt_reason) {
9132                         case FC_REASON_OFFLINE: {
9133                                 dev_info_t      *cdip = NULL;
9134 
9135                                 mutex_enter(&plun->lun_mutex);
9136                                 if (plun->lun_mpxio == 0) {
9137                                         cdip = DIP(plun->lun_cip);
9138                                 } else if (plun->lun_cip) {
9139                                         cdip = mdi_pi_get_client(
9140                                             PIP(plun->lun_cip));
9141                                 }
9142                                 mutex_exit(&plun->lun_mutex);
9143 
9144                                 if (cdip) {
9145                                         (void) ndi_event_retrieve_cookie(
9146                                             pptr->port_ndi_event_hdl, cdip,
9147                                             FCAL_REMOVE_EVENT,
9148                                             &fcp_remove_eid,
9149                                             NDI_EVENT_NOPASS);
9150                                         (void) ndi_event_run_callbacks(
9151                                             pptr->port_ndi_event_hdl,
9152                                             cdip, fcp_remove_eid, NULL);
9153                                 }
9154 
9155                                 pkt->pkt_reason = CMD_TRAN_ERR;
9156                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9157 
9158                                 break;
9159                         }
9160 
9161                         case FC_REASON_NOMEM:
9162                         case FC_REASON_QFULL: {
9163                                 caddr_t ptr;
9164 
9165                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9166                                 ptr = (caddr_t)pkt->pkt_scbp;
9167                                 if (ptr) {
9168                                         *ptr = STATUS_BUSY;
9169                                 }
9170                                 break;
9171                         }
9172 
9173                         case FC_REASON_DMA_ERROR:
9174                                 pkt->pkt_reason = CMD_DMA_DERR;
9175                                 pkt->pkt_statistics |= STAT_ABORTED;
9176                                 break;
9177 
9178                         case FC_REASON_CRC_ERROR:
9179                         case FC_REASON_UNDERRUN: {
9180                                 uchar_t         status;
9181                                 /*
9182                                  * Work around for Bugid: 4240945.
9183                                  * IB on A5k doesn't set the Underrun bit
9184                                  * in the fcp status, when it is transferring
9185                                  * less than requested amount of data. Work
9186                                  * around the ses problem to keep luxadm
9187                                  * happy till ibfirmware is fixed.
9188                                  */
9189                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9190                                         FCP_CP_IN(fpkt->pkt_resp, rsp,
9191                                             fpkt->pkt_resp_acc,
9192                                             sizeof (struct fcp_rsp));
9193                                 }
9194                                 status = rsp->fcp_u.fcp_status.scsi_status;
9195                                 if (((plun->lun_type & DTYPE_MASK) ==
9196                                     DTYPE_ESI) && (status == STATUS_GOOD)) {
9197                                         pkt->pkt_reason = CMD_CMPLT;
9198                                         *pkt->pkt_scbp = status;
9199                                         pkt->pkt_resid = 0;
9200                                 } else {
9201                                         pkt->pkt_reason = CMD_TRAN_ERR;
9202                                         pkt->pkt_statistics |= STAT_ABORTED;
9203                                 }
9204                                 break;
9205                         }
9206 
9207                         case FC_REASON_NO_CONNECTION:
9208                         case FC_REASON_UNSUPPORTED:
9209                         case FC_REASON_ILLEGAL_REQ:
9210                         case FC_REASON_BAD_SID:
9211                         case FC_REASON_DIAG_BUSY:
9212                         case FC_REASON_FCAL_OPN_FAIL:
9213                         case FC_REASON_BAD_XID:
9214                         default:
9215                                 pkt->pkt_reason = CMD_TRAN_ERR;
9216                                 pkt->pkt_statistics |= STAT_ABORTED;
9217                                 break;
9218 
9219                         }
9220                         break;
9221 
9222                 case FC_PKT_NPORT_RJT:
9223                 case FC_PKT_FABRIC_RJT:
9224                 case FC_PKT_NPORT_BSY:
9225                 case FC_PKT_FABRIC_BSY:
9226                 default:
9227                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9228                             fcp_trace, FCP_BUF_LEVEL_8, 0,
9229                             "FC Status 0x%x, reason 0x%x",
9230                             fpkt->pkt_state, fpkt->pkt_reason);
9231                         pkt->pkt_reason = CMD_TRAN_ERR;
9232                         pkt->pkt_statistics |= STAT_ABORTED;
9233                         break;
9234                 }
9235 
9236                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9237                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9238                     "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9239                     " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9240                     fpkt->pkt_reason);
9241         }
9242 
9243         ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9244 }
9245 
9246 
9247 static int
9248 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9249 {
9250         if (rsp->reserved_0 || rsp->reserved_1 ||
9251             rsp->fcp_u.fcp_status.reserved_0 ||
9252             rsp->fcp_u.fcp_status.reserved_1) {
9253                 /*
9254                  * These reserved fields should ideally be zero. FCP-2 does say
9255                  * that the recipient need not check for reserved fields to be
9256                  * zero. If they are not zero, we will not make a fuss about it
9257                  * - just log it (in debug to both trace buffer and messages
9258                  * file and to trace buffer only in non-debug) and move on.
9259                  *
9260                  * Non-zero reserved fields were seen with minnows.
9261                  *
9262                  * qlc takes care of some of this but we cannot assume that all
9263                  * FCAs will do so.
9264                  */
9265                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9266                     FCP_BUF_LEVEL_5, 0,
9267                     "Got fcp response packet with non-zero reserved fields "
9268                     "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9269                     "status.reserved_0:0x%x, status.reserved_1:0x%x",
9270                     rsp->reserved_0, rsp->reserved_1,
9271                     rsp->fcp_u.fcp_status.reserved_0,
9272                     rsp->fcp_u.fcp_status.reserved_1);
9273         }
9274 
9275         if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9276             (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9277                 return (FC_FAILURE);
9278         }
9279 
9280         if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9281             (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9282             sizeof (struct fcp_rsp))) {
9283                 return (FC_FAILURE);
9284         }
9285 
9286         return (FC_SUCCESS);
9287 }
9288 
9289 
9290 /*
9291  * This is called when there is a change the in device state. The case we're
9292  * handling here is, if the d_id s does not match, offline this tgt and online
9293  * a new tgt with the new d_id.  called from fcp_handle_devices with
9294  * port_mutex held.
9295  */
9296 static int
9297 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9298     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9299 {
9300         ASSERT(mutex_owned(&pptr->port_mutex));
9301 
9302         FCP_TRACE(fcp_logq, pptr->port_instbuf,
9303             fcp_trace, FCP_BUF_LEVEL_3, 0,
9304             "Starting fcp_device_changed...");
9305 
9306         /*
9307          * The two cases where the port_device_changed is called is
9308          * either it changes it's d_id or it's hard address.
9309          */
9310         if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9311             (FC_TOP_EXTERNAL(pptr->port_topology) &&
9312             (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9313 
9314                 /* offline this target */
9315                 mutex_enter(&ptgt->tgt_mutex);
9316                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9317                         (void) fcp_offline_target(pptr, ptgt, link_cnt,
9318                             0, 1, NDI_DEVI_REMOVE);
9319                 }
9320                 mutex_exit(&ptgt->tgt_mutex);
9321 
9322                 fcp_log(CE_NOTE, pptr->port_dip,
9323                     "Change in target properties: Old D_ID=%x New D_ID=%x"
9324                     " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9325                     map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9326                     map_entry->map_hard_addr.hard_addr);
9327         }
9328 
9329         return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9330             link_cnt, tgt_cnt, cause));
9331 }
9332 
9333 /*
9334  *     Function: fcp_alloc_lun
9335  *
9336  *  Description: Creates a new lun structure and adds it to the list
9337  *               of luns of the target.
9338  *
9339  *     Argument: ptgt           Target the lun will belong to.
9340  *
9341  * Return Value: NULL           Failed
9342  *               Not NULL       Succeeded
9343  *
9344  *      Context: Kernel context
9345  */
9346 static struct fcp_lun *
9347 fcp_alloc_lun(struct fcp_tgt *ptgt)
9348 {
9349         struct fcp_lun *plun;
9350 
9351         plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9352         if (plun != NULL) {
9353                 /*
9354                  * Initialize the mutex before putting in the target list
9355                  * especially before releasing the target mutex.
9356                  */
9357                 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9358                 plun->lun_tgt = ptgt;
9359 
9360                 mutex_enter(&ptgt->tgt_mutex);
9361                 plun->lun_next = ptgt->tgt_lun;
9362                 ptgt->tgt_lun = plun;
9363                 plun->lun_old_guid = NULL;
9364                 plun->lun_old_guid_size = 0;
9365                 mutex_exit(&ptgt->tgt_mutex);
9366         }
9367 
9368         return (plun);
9369 }
9370 
9371 /*
9372  *     Function: fcp_dealloc_lun
9373  *
9374  *  Description: Frees the LUN structure passed by the caller.
9375  *
9376  *     Argument: plun           LUN structure to free.
9377  *
9378  * Return Value: None
9379  *
9380  *      Context: Kernel context.
9381  */
9382 static void
9383 fcp_dealloc_lun(struct fcp_lun *plun)
9384 {
9385         mutex_enter(&plun->lun_mutex);
9386         if (plun->lun_cip) {
9387                 fcp_remove_child(plun);
9388         }
9389         mutex_exit(&plun->lun_mutex);
9390 
9391         mutex_destroy(&plun->lun_mutex);
9392         if (plun->lun_guid) {
9393                 kmem_free(plun->lun_guid, plun->lun_guid_size);
9394         }
9395         if (plun->lun_old_guid) {
9396                 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9397         }
9398         kmem_free(plun, sizeof (*plun));
9399 }
9400 
9401 /*
9402  *     Function: fcp_alloc_tgt
9403  *
9404  *  Description: Creates a new target structure and adds it to the port
9405  *               hash list.
9406  *
9407  *     Argument: pptr           fcp port structure
9408  *               *map_entry     entry describing the target to create
9409  *               link_cnt       Link state change counter
9410  *
9411  * Return Value: NULL           Failed
9412  *               Not NULL       Succeeded
9413  *
9414  *      Context: Kernel context.
9415  */
9416 static struct fcp_tgt *
9417 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9418 {
9419         int                     hash;
9420         uchar_t                 *wwn;
9421         struct fcp_tgt  *ptgt;
9422 
9423         ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9424         if (ptgt != NULL) {
9425                 mutex_enter(&pptr->port_mutex);
9426                 if (link_cnt != pptr->port_link_cnt) {
9427                         /*
9428                          * oh oh -- another link reset
9429                          * in progress -- give up
9430                          */
9431                         mutex_exit(&pptr->port_mutex);
9432                         kmem_free(ptgt, sizeof (*ptgt));
9433                         ptgt = NULL;
9434                 } else {
9435                         /*
9436                          * initialize the mutex before putting in the port
9437                          * wwn list, especially before releasing the port
9438                          * mutex.
9439                          */
9440                         mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9441 
9442                         /* add new target entry to the port's hash list */
9443                         wwn = (uchar_t *)&map_entry->map_pwwn;
9444                         hash = FCP_HASH(wwn);
9445 
9446                         ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9447                         pptr->port_tgt_hash_table[hash] = ptgt;
9448 
9449                         /* save cross-ptr */
9450                         ptgt->tgt_port = pptr;
9451 
9452                         ptgt->tgt_change_cnt = 1;
9453 
9454                         /* initialize the target manual_config_only flag */
9455                         if (fcp_enable_auto_configuration) {
9456                                 ptgt->tgt_manual_config_only = 0;
9457                         } else {
9458                                 ptgt->tgt_manual_config_only = 1;
9459                         }
9460 
9461                         mutex_exit(&pptr->port_mutex);
9462                 }
9463         }
9464 
9465         return (ptgt);
9466 }
9467 
9468 /*
9469  *     Function: fcp_dealloc_tgt
9470  *
9471  *  Description: Frees the target structure passed by the caller.
9472  *
9473  *     Argument: ptgt           Target structure to free.
9474  *
9475  * Return Value: None
9476  *
9477  *      Context: Kernel context.
9478  */
9479 static void
9480 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9481 {
9482         mutex_destroy(&ptgt->tgt_mutex);
9483         kmem_free(ptgt, sizeof (*ptgt));
9484 }
9485 
9486 
9487 /*
9488  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9489  *
9490  *      Device discovery commands will not be retried for-ever as
9491  *      this will have repercussions on other devices that need to
9492  *      be submitted to the hotplug thread. After a quick glance
9493  *      at the SCSI-3 spec, it was found that the spec doesn't
9494  *      mandate a forever retry, rather recommends a delayed retry.
9495  *
9496  *      Since Photon IB is single threaded, STATUS_BUSY is common
9497  *      in a 4+initiator environment. Make sure the total time
9498  *      spent on retries (including command timeout) does not
9499  *      60 seconds
9500  */
9501 static void
9502 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9503 {
9504         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9505         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9506 
9507         mutex_enter(&pptr->port_mutex);
9508         mutex_enter(&ptgt->tgt_mutex);
9509         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9510                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
9511                     fcp_trace, FCP_BUF_LEVEL_2, 0,
9512                     "fcp_queue_ipkt,1:state change occured"
9513                     " for D_ID=0x%x", ptgt->tgt_d_id);
9514                 mutex_exit(&ptgt->tgt_mutex);
9515                 mutex_exit(&pptr->port_mutex);
9516                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9517                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
9518                 fcp_icmd_free(pptr, icmd);
9519                 return;
9520         }
9521         mutex_exit(&ptgt->tgt_mutex);
9522 
9523         icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9524 
9525         if (pptr->port_ipkt_list != NULL) {
9526                 /* add pkt to front of doubly-linked list */
9527                 pptr->port_ipkt_list->ipkt_prev = icmd;
9528                 icmd->ipkt_next = pptr->port_ipkt_list;
9529                 pptr->port_ipkt_list = icmd;
9530                 icmd->ipkt_prev = NULL;
9531         } else {
9532                 /* this is the first/only pkt on the list */
9533                 pptr->port_ipkt_list = icmd;
9534                 icmd->ipkt_next = NULL;
9535                 icmd->ipkt_prev = NULL;
9536         }
9537         mutex_exit(&pptr->port_mutex);
9538 }
9539 
9540 /*
9541  *     Function: fcp_transport
9542  *
9543  *  Description: This function submits the Fibre Channel packet to the transort
9544  *               layer by calling fc_ulp_transport().  If fc_ulp_transport()
9545  *               fails the submission, the treatment depends on the value of
9546  *               the variable internal.
9547  *
9548  *     Argument: port_handle    fp/fctl port handle.
9549  *               *fpkt          Packet to submit to the transport layer.
9550  *               internal       Not zero when it's an internal packet.
9551  *
9552  * Return Value: FC_TRAN_BUSY
9553  *               FC_STATEC_BUSY
9554  *               FC_OFFLINE
9555  *               FC_LOGINREQ
9556  *               FC_DEVICE_BUSY
9557  *               FC_SUCCESS
9558  */
9559 static int
9560 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9561 {
9562         int     rval;
9563 
9564         rval = fc_ulp_transport(port_handle, fpkt);
9565         if (rval == FC_SUCCESS) {
9566                 return (rval);
9567         }
9568 
9569         /*
9570          * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9571          * a command, if the underlying modules see that there is a state
9572          * change, or if a port is OFFLINE, that means, that state change
9573          * hasn't reached FCP yet, so re-queue the command for deferred
9574          * submission.
9575          */
9576         if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9577             (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9578             (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9579                 /*
9580                  * Defer packet re-submission. Life hang is possible on
9581                  * internal commands if the port driver sends FC_STATEC_BUSY
9582                  * for ever, but that shouldn't happen in a good environment.
9583                  * Limiting re-transport for internal commands is probably a
9584                  * good idea..
9585                  * A race condition can happen when a port sees barrage of
9586                  * link transitions offline to online. If the FCTL has
9587                  * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9588                  * internal commands should be queued to do the discovery.
9589                  * The race condition is when an online comes and FCP starts
9590                  * its internal discovery and the link goes offline. It is
9591                  * possible that the statec_callback has not reached FCP
9592                  * and FCP is carrying on with its internal discovery.
9593                  * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9594                  * that the link has gone offline. At this point FCP should
9595                  * drop all the internal commands and wait for the
9596                  * statec_callback. It will be facilitated by incrementing
9597                  * port_link_cnt.
9598                  *
9599                  * For external commands, the (FC)pkt_timeout is decremented
9600                  * by the QUEUE Delay added by our driver, Care is taken to
9601                  * ensure that it doesn't become zero (zero means no timeout)
9602                  * If the time expires right inside driver queue itself,
9603                  * the watch thread will return it to the original caller
9604                  * indicating that the command has timed-out.
9605                  */
9606                 if (internal) {
9607                         char                    *op;
9608                         struct fcp_ipkt *icmd;
9609 
9610                         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9611                         switch (icmd->ipkt_opcode) {
9612                         case SCMD_REPORT_LUN:
9613                                 op = "REPORT LUN";
9614                                 break;
9615 
9616                         case SCMD_INQUIRY:
9617                                 op = "INQUIRY";
9618                                 break;
9619 
9620                         case SCMD_INQUIRY_PAGE83:
9621                                 op = "INQUIRY-83";
9622                                 break;
9623 
9624                         default:
9625                                 op = "Internal SCSI COMMAND";
9626                                 break;
9627                         }
9628 
9629                         if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9630                             icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9631                                 rval = FC_SUCCESS;
9632                         }
9633                 } else {
9634                         struct fcp_pkt *cmd;
9635                         struct fcp_port *pptr;
9636 
9637                         cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9638                         cmd->cmd_state = FCP_PKT_IDLE;
9639                         pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9640 
9641                         if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9642                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9643                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9644                                     "fcp_transport: xport busy for pkt %p",
9645                                     cmd->cmd_pkt);
9646                                 rval = FC_TRAN_BUSY;
9647                         } else {
9648                                 fcp_queue_pkt(pptr, cmd);
9649                                 rval = FC_SUCCESS;
9650                         }
9651                 }
9652         }
9653 
9654         return (rval);
9655 }
9656 
9657 /*VARARGS3*/
9658 static void
9659 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9660 {
9661         char            buf[256];
9662         va_list         ap;
9663 
9664         if (dip == NULL) {
9665                 dip = fcp_global_dip;
9666         }
9667 
9668         va_start(ap, fmt);
9669         (void) vsprintf(buf, fmt, ap);
9670         va_end(ap);
9671 
9672         scsi_log(dip, "fcp", level, buf);
9673 }
9674 
9675 /*
9676  * This function retries NS registry of FC4 type.
9677  * It assumes that fcp_mutex is held.
9678  * The function does nothing if topology is not fabric
9679  * So, the topology has to be set before this function can be called
9680  */
9681 static void
9682 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9683 {
9684         int     rval;
9685 
9686         ASSERT(MUTEX_HELD(&pptr->port_mutex));
9687 
9688         if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9689             ((pptr->port_topology != FC_TOP_FABRIC) &&
9690             (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9691                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9692                         pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9693                 }
9694                 return;
9695         }
9696         mutex_exit(&pptr->port_mutex);
9697         rval = fcp_do_ns_registry(pptr, s_id);
9698         mutex_enter(&pptr->port_mutex);
9699 
9700         if (rval == 0) {
9701                 /* Registry successful. Reset flag */
9702                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9703         }
9704 }
9705 
9706 /*
9707  * This function registers the ULP with the switch by calling transport i/f
9708  */
9709 static int
9710 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9711 {
9712         fc_ns_cmd_t             ns_cmd;
9713         ns_rfc_type_t           rfc;
9714         uint32_t                types[8];
9715 
9716         /*
9717          * Prepare the Name server structure to
9718          * register with the transport in case of
9719          * Fabric configuration.
9720          */
9721         bzero(&rfc, sizeof (rfc));
9722         bzero(types, sizeof (types));
9723 
9724         types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9725             (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9726 
9727         rfc.rfc_port_id.port_id = s_id;
9728         bcopy(types, rfc.rfc_types, sizeof (types));
9729 
9730         ns_cmd.ns_flags = 0;
9731         ns_cmd.ns_cmd = NS_RFT_ID;
9732         ns_cmd.ns_req_len = sizeof (rfc);
9733         ns_cmd.ns_req_payload = (caddr_t)&rfc;
9734         ns_cmd.ns_resp_len = 0;
9735         ns_cmd.ns_resp_payload = NULL;
9736 
9737         /*
9738          * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9739          */
9740         if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9741                 fcp_log(CE_WARN, pptr->port_dip,
9742                     "!ns_registry: failed name server registration");
9743                 return (1);
9744         }
9745 
9746         return (0);
9747 }
9748 
9749 /*
9750  *     Function: fcp_handle_port_attach
9751  *
9752  *  Description: This function is called from fcp_port_attach() to attach a
9753  *               new port. This routine does the following:
9754  *
9755  *              1) Allocates an fcp_port structure and initializes it.
9756  *              2) Tries to register the new FC-4 (FCP) capablity with the name
9757  *                 server.
9758  *              3) Kicks off the enumeration of the targets/luns visible
9759  *                 through this new port.  That is done by calling
9760  *                 fcp_statec_callback() if the port is online.
9761  *
9762  *     Argument: ulph           fp/fctl port handle.
9763  *               *pinfo         Port information.
9764  *               s_id           Port ID.
9765  *               instance       Device instance number for the local port
9766  *                              (returned by ddi_get_instance()).
9767  *
9768  * Return Value: DDI_SUCCESS
9769  *               DDI_FAILURE
9770  *
9771  *      Context: User and Kernel context.
9772  */
9773 /*ARGSUSED*/
9774 int
9775 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9776     uint32_t s_id, int instance)
9777 {
9778         int                     res = DDI_FAILURE;
9779         scsi_hba_tran_t         *tran;
9780         int                     mutex_initted = FALSE;
9781         int                     hba_attached = FALSE;
9782         int                     soft_state_linked = FALSE;
9783         int                     event_bind = FALSE;
9784         struct fcp_port         *pptr;
9785         fc_portmap_t            *tmp_list = NULL;
9786         uint32_t                max_cnt, alloc_cnt;
9787         uchar_t                 *boot_wwn = NULL;
9788         uint_t                  nbytes;
9789         int                     manual_cfg;
9790 
9791         /*
9792          * this port instance attaching for the first time (or after
9793          * being detached before)
9794          */
9795         FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9796             FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9797 
9798         if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9799                 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9800                     "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9801                     instance);
9802                 return (res);
9803         }
9804 
9805         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9806                 /* this shouldn't happen */
9807                 ddi_soft_state_free(fcp_softstate, instance);
9808                 cmn_err(CE_WARN, "fcp: bad soft state");
9809                 return (res);
9810         }
9811 
9812         (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9813 
9814         /*
9815          * Make a copy of ulp_port_info as fctl allocates
9816          * a temp struct.
9817          */
9818         (void) fcp_cp_pinfo(pptr, pinfo);
9819 
9820         /*
9821          * Check for manual_configuration_only property.
9822          * Enable manual configurtion if the property is
9823          * set to 1, otherwise disable manual configuration.
9824          */
9825         if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9826             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9827             MANUAL_CFG_ONLY,
9828             -1)) != -1) {
9829                 if (manual_cfg == 1) {
9830                         char    *pathname;
9831                         pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9832                         (void) ddi_pathname(pptr->port_dip, pathname);
9833                         cmn_err(CE_NOTE,
9834                             "%s (%s%d) %s is enabled via %s.conf.",
9835                             pathname,
9836                             ddi_driver_name(pptr->port_dip),
9837                             ddi_get_instance(pptr->port_dip),
9838                             MANUAL_CFG_ONLY,
9839                             ddi_driver_name(pptr->port_dip));
9840                         fcp_enable_auto_configuration = 0;
9841                         kmem_free(pathname, MAXPATHLEN);
9842                 }
9843         }
9844         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9845         pptr->port_link_cnt = 1;
9846         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9847         pptr->port_id = s_id;
9848         pptr->port_instance = instance;
9849         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9850         pptr->port_state = FCP_STATE_INIT;
9851         if (pinfo->port_acc_attr == NULL) {
9852                 /*
9853                  * The corresponding FCA doesn't support DMA at all
9854                  */
9855                 pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9856         }
9857 
9858         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9859 
9860         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9861                 /*
9862                  * If FCA supports DMA in SCSI data phase, we need preallocate
9863                  * dma cookie, so stash the cookie size
9864                  */
9865                 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9866                     pptr->port_data_dma_attr.dma_attr_sgllen;
9867         }
9868 
9869         /*
9870          * The two mutexes of fcp_port are initialized.  The variable
9871          * mutex_initted is incremented to remember that fact.  That variable
9872          * is checked when the routine fails and the mutexes have to be
9873          * destroyed.
9874          */
9875         mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9876         mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9877         mutex_initted++;
9878 
9879         /*
9880          * The SCSI tran structure is allocate and initialized now.
9881          */
9882         if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9883                 fcp_log(CE_WARN, pptr->port_dip,
9884                     "!fcp%d: scsi_hba_tran_alloc failed", instance);
9885                 goto fail;
9886         }
9887 
9888         /* link in the transport structure then fill it in */
9889         pptr->port_tran = tran;
9890         tran->tran_hba_private               = pptr;
9891         tran->tran_tgt_init          = fcp_scsi_tgt_init;
9892         tran->tran_tgt_probe         = NULL;
9893         tran->tran_tgt_free          = fcp_scsi_tgt_free;
9894         tran->tran_start             = fcp_scsi_start;
9895         tran->tran_reset             = fcp_scsi_reset;
9896         tran->tran_abort             = fcp_scsi_abort;
9897         tran->tran_getcap            = fcp_scsi_getcap;
9898         tran->tran_setcap            = fcp_scsi_setcap;
9899         tran->tran_init_pkt          = NULL;
9900         tran->tran_destroy_pkt               = NULL;
9901         tran->tran_dmafree           = NULL;
9902         tran->tran_sync_pkt          = NULL;
9903         tran->tran_reset_notify              = fcp_scsi_reset_notify;
9904         tran->tran_get_bus_addr              = fcp_scsi_get_bus_addr;
9905         tran->tran_get_name          = fcp_scsi_get_name;
9906         tran->tran_clear_aca         = NULL;
9907         tran->tran_clear_task_set    = NULL;
9908         tran->tran_terminate_task    = NULL;
9909         tran->tran_get_eventcookie   = fcp_scsi_bus_get_eventcookie;
9910         tran->tran_add_eventcall     = fcp_scsi_bus_add_eventcall;
9911         tran->tran_remove_eventcall  = fcp_scsi_bus_remove_eventcall;
9912         tran->tran_post_event                = fcp_scsi_bus_post_event;
9913         tran->tran_quiesce           = NULL;
9914         tran->tran_unquiesce         = NULL;
9915         tran->tran_bus_reset         = NULL;
9916         tran->tran_bus_config                = fcp_scsi_bus_config;
9917         tran->tran_bus_unconfig              = fcp_scsi_bus_unconfig;
9918         tran->tran_bus_power         = NULL;
9919         tran->tran_interconnect_type = INTERCONNECT_FABRIC;
9920 
9921         tran->tran_pkt_constructor   = fcp_kmem_cache_constructor;
9922         tran->tran_pkt_destructor    = fcp_kmem_cache_destructor;
9923         tran->tran_setup_pkt         = fcp_pkt_setup;
9924         tran->tran_teardown_pkt              = fcp_pkt_teardown;
9925         tran->tran_hba_len           = pptr->port_priv_pkt_len +
9926             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9927         if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9928                 /*
9929                  * If FCA don't support DMA, then we use different vectors to
9930                  * minimize the effects on DMA code flow path
9931                  */
9932                 tran->tran_start        = fcp_pseudo_start;
9933                 tran->tran_init_pkt     = fcp_pseudo_init_pkt;
9934                 tran->tran_destroy_pkt          = fcp_pseudo_destroy_pkt;
9935                 tran->tran_sync_pkt     = fcp_pseudo_sync_pkt;
9936                 tran->tran_dmafree      = fcp_pseudo_dmafree;
9937                 tran->tran_setup_pkt    = NULL;
9938                 tran->tran_teardown_pkt         = NULL;
9939                 tran->tran_pkt_constructor = NULL;
9940                 tran->tran_pkt_destructor  = NULL;
9941                 pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9942         }
9943 
9944         /*
9945          * Allocate an ndi event handle
9946          */
9947         pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9948             kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9949 
9950         bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9951             sizeof (fcp_ndi_event_defs));
9952 
9953         (void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9954             &pptr->port_ndi_event_hdl, NDI_SLEEP);
9955 
9956         pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9957         pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9958         pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9959 
9960         if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9961             (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9962             &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9963                 goto fail;
9964         }
9965         event_bind++;   /* Checked in fail case */
9966 
9967         if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9968             tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9969             != DDI_SUCCESS) {
9970                 fcp_log(CE_WARN, pptr->port_dip,
9971                     "!fcp%d: scsi_hba_attach_setup failed", instance);
9972                 goto fail;
9973         }
9974         hba_attached++; /* Checked in fail case */
9975 
9976         pptr->port_mpxio = 0;
9977         if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9978             MDI_SUCCESS) {
9979                 pptr->port_mpxio++;
9980         }
9981 
9982         /*
9983          * The following code is putting the new port structure in the global
9984          * list of ports and, if it is the first port to attach, it start the
9985          * fcp_watchdog_tick.
9986          *
9987          * Why put this new port in the global before we are done attaching it?
9988          * We are actually making the structure globally known before we are
9989          * done attaching it.  The reason for that is: because of the code that
9990          * follows.  At this point the resources to handle the port are
9991          * allocated.  This function is now going to do the following:
9992          *
9993          *   1) It is going to try to register with the name server advertizing
9994          *      the new FCP capability of the port.
9995          *   2) It is going to play the role of the fp/fctl layer by building
9996          *      a list of worlwide names reachable through this port and call
9997          *      itself on fcp_statec_callback().  That requires the port to
9998          *      be part of the global list.
9999          */
10000         mutex_enter(&fcp_global_mutex);
10001         if (fcp_port_head == NULL) {
10002                 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10003         }
10004         pptr->port_next = fcp_port_head;
10005         fcp_port_head = pptr;
10006         soft_state_linked++;
10007 
10008         if (fcp_watchdog_init++ == 0) {
10009                 fcp_watchdog_tick = fcp_watchdog_timeout *
10010                     drv_usectohz(1000000);
10011                 fcp_watchdog_id = timeout(fcp_watch, NULL,
10012                     fcp_watchdog_tick);
10013         }
10014         mutex_exit(&fcp_global_mutex);
10015 
10016         /*
10017          * Here an attempt is made to register with the name server, the new
10018          * FCP capability.  That is done using an RTF_ID to the name server.
10019          * It is done synchronously.  The function fcp_do_ns_registry()
10020          * doesn't return till the name server responded.
10021          * On failures, just ignore it for now and it will get retried during
10022          * state change callbacks. We'll set a flag to show this failure
10023          */
10024         if (fcp_do_ns_registry(pptr, s_id)) {
10025                 mutex_enter(&pptr->port_mutex);
10026                 pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10027                 mutex_exit(&pptr->port_mutex);
10028         } else {
10029                 mutex_enter(&pptr->port_mutex);
10030                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10031                 mutex_exit(&pptr->port_mutex);
10032         }
10033 
10034         /*
10035          * Lookup for boot WWN property
10036          */
10037         if (modrootloaded != 1) {
10038                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10039                     ddi_get_parent(pinfo->port_dip),
10040                     DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10041                     &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10042                     (nbytes == FC_WWN_SIZE)) {
10043                         bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10044                 }
10045                 if (boot_wwn) {
10046                         ddi_prop_free(boot_wwn);
10047                 }
10048         }
10049 
10050         /*
10051          * Handle various topologies and link states.
10052          */
10053         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10054         case FC_STATE_OFFLINE:
10055 
10056                 /*
10057                  * we're attaching a port where the link is offline
10058                  *
10059                  * Wait for ONLINE, at which time a state
10060                  * change will cause a statec_callback
10061                  *
10062                  * in the mean time, do not do anything
10063                  */
10064                 res = DDI_SUCCESS;
10065                 pptr->port_state |= FCP_STATE_OFFLINE;
10066                 break;
10067 
10068         case FC_STATE_ONLINE: {
10069                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
10070                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10071                         res = DDI_SUCCESS;
10072                         break;
10073                 }
10074                 /*
10075                  * discover devices and create nodes (a private
10076                  * loop or point-to-point)
10077                  */
10078                 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10079 
10080                 /*
10081                  * At this point we are going to build a list of all the ports
10082                  * that can be reached through this local port.  It looks like
10083                  * we cannot handle more than FCP_MAX_DEVICES per local port
10084                  * (128).
10085                  */
10086                 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10087                     sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10088                     KM_NOSLEEP)) == NULL) {
10089                         fcp_log(CE_WARN, pptr->port_dip,
10090                             "!fcp%d: failed to allocate portmap",
10091                             instance);
10092                         goto fail;
10093                 }
10094 
10095                 /*
10096                  * fc_ulp_getportmap() is going to provide us with the list of
10097                  * remote ports in the buffer we just allocated.  The way the
10098                  * list is going to be retrieved depends on the topology.
10099                  * However, if we are connected to a Fabric, a name server
10100                  * request may be sent to get the list of FCP capable ports.
10101                  * It should be noted that is the case the request is
10102                  * synchronous.  This means we are stuck here till the name
10103                  * server replies.  A lot of things can change during that time
10104                  * and including, may be, being called on
10105                  * fcp_statec_callback() for different reasons. I'm not sure
10106                  * the code can handle that.
10107                  */
10108                 max_cnt = FCP_MAX_DEVICES;
10109                 alloc_cnt = FCP_MAX_DEVICES;
10110                 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10111                     &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10112                     FC_SUCCESS) {
10113                         caddr_t msg;
10114 
10115                         (void) fc_ulp_error(res, &msg);
10116 
10117                         /*
10118                          * this  just means the transport is
10119                          * busy perhaps building a portmap so,
10120                          * for now, succeed this port attach
10121                          * when the transport has a new map,
10122                          * it'll send us a state change then
10123                          */
10124                         fcp_log(CE_WARN, pptr->port_dip,
10125                             "!failed to get port map : %s", msg);
10126 
10127                         res = DDI_SUCCESS;
10128                         break;  /* go return result */
10129                 }
10130                 if (max_cnt > alloc_cnt) {
10131                         alloc_cnt = max_cnt;
10132                 }
10133 
10134                 /*
10135                  * We are now going to call fcp_statec_callback() ourselves.
10136                  * By issuing this call we are trying to kick off the enumera-
10137                  * tion process.
10138                  */
10139                 /*
10140                  * let the state change callback do the SCSI device
10141                  * discovery and create the devinfos
10142                  */
10143                 fcp_statec_callback(ulph, pptr->port_fp_handle,
10144                     pptr->port_phys_state, pptr->port_topology, tmp_list,
10145                     max_cnt, pptr->port_id);
10146 
10147                 res = DDI_SUCCESS;
10148                 break;
10149         }
10150 
10151         default:
10152                 /* unknown port state */
10153                 fcp_log(CE_WARN, pptr->port_dip,
10154                     "!fcp%d: invalid port state at attach=0x%x",
10155                     instance, pptr->port_phys_state);
10156 
10157                 mutex_enter(&pptr->port_mutex);
10158                 pptr->port_phys_state = FCP_STATE_OFFLINE;
10159                 mutex_exit(&pptr->port_mutex);
10160 
10161                 res = DDI_SUCCESS;
10162                 break;
10163         }
10164 
10165         /* free temp list if used */
10166         if (tmp_list != NULL) {
10167                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10168         }
10169 
10170         /* note the attach time */
10171         pptr->port_attach_time = ddi_get_lbolt64();
10172 
10173         /* all done */
10174         return (res);
10175 
10176         /* a failure we have to clean up after */
10177 fail:
10178         fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10179 
10180         if (soft_state_linked) {
10181                 /* remove this fcp_port from the linked list */
10182                 (void) fcp_soft_state_unlink(pptr);
10183         }
10184 
10185         /* unbind and free event set */
10186         if (pptr->port_ndi_event_hdl) {
10187                 if (event_bind) {
10188                         (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10189                             &pptr->port_ndi_events, NDI_SLEEP);
10190                 }
10191                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10192         }
10193 
10194         if (pptr->port_ndi_event_defs) {
10195                 (void) kmem_free(pptr->port_ndi_event_defs,
10196                     sizeof (fcp_ndi_event_defs));
10197         }
10198 
10199         /*
10200          * Clean up mpxio stuff
10201          */
10202         if (pptr->port_mpxio) {
10203                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10204                 pptr->port_mpxio--;
10205         }
10206 
10207         /* undo SCSI HBA setup */
10208         if (hba_attached) {
10209                 (void) scsi_hba_detach(pptr->port_dip);
10210         }
10211         if (pptr->port_tran != NULL) {
10212                 scsi_hba_tran_free(pptr->port_tran);
10213         }
10214 
10215         mutex_enter(&fcp_global_mutex);
10216 
10217         /*
10218          * We check soft_state_linked, because it is incremented right before
10219          * we call increment fcp_watchdog_init.  Therefore, we know if
10220          * soft_state_linked is still FALSE, we do not want to decrement
10221          * fcp_watchdog_init or possibly call untimeout.
10222          */
10223 
10224         if (soft_state_linked) {
10225                 if (--fcp_watchdog_init == 0) {
10226                         timeout_id_t    tid = fcp_watchdog_id;
10227 
10228                         mutex_exit(&fcp_global_mutex);
10229                         (void) untimeout(tid);
10230                 } else {
10231                         mutex_exit(&fcp_global_mutex);
10232                 }
10233         } else {
10234                 mutex_exit(&fcp_global_mutex);
10235         }
10236 
10237         if (mutex_initted) {
10238                 mutex_destroy(&pptr->port_mutex);
10239                 mutex_destroy(&pptr->port_pkt_mutex);
10240         }
10241 
10242         if (tmp_list != NULL) {
10243                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10244         }
10245 
10246         /* this makes pptr invalid */
10247         ddi_soft_state_free(fcp_softstate, instance);
10248 
10249         return (DDI_FAILURE);
10250 }
10251 
10252 
10253 static int
10254 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10255 {
10256         int count = 0;
10257 
10258         mutex_enter(&pptr->port_mutex);
10259 
10260         /*
10261          * if the port is powered down or suspended, nothing else
10262          * to do; just return.
10263          */
10264         if (flag != FCP_STATE_DETACHING) {
10265                 if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10266                     FCP_STATE_SUSPENDED)) {
10267                         pptr->port_state |= flag;
10268                         mutex_exit(&pptr->port_mutex);
10269                         return (FC_SUCCESS);
10270                 }
10271         }
10272 
10273         if (pptr->port_state & FCP_STATE_IN_MDI) {
10274                 mutex_exit(&pptr->port_mutex);
10275                 return (FC_FAILURE);
10276         }
10277 
10278         FCP_TRACE(fcp_logq, pptr->port_instbuf,
10279             fcp_trace, FCP_BUF_LEVEL_2, 0,
10280             "fcp_handle_port_detach: port is detaching");
10281 
10282         pptr->port_state |= flag;
10283 
10284         /*
10285          * Wait for any ongoing reconfig/ipkt to complete, that
10286          * ensures the freeing to targets/luns is safe.
10287          * No more ref to this port should happen from statec/ioctl
10288          * after that as it was removed from the global port list.
10289          */
10290         while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10291             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10292                 /*
10293                  * Let's give sufficient time for reconfig/ipkt
10294                  * to complete.
10295                  */
10296                 if (count++ >= FCP_ICMD_DEADLINE) {
10297                         break;
10298                 }
10299                 mutex_exit(&pptr->port_mutex);
10300                 delay(drv_usectohz(1000000));
10301                 mutex_enter(&pptr->port_mutex);
10302         }
10303 
10304         /*
10305          * if the driver is still busy then fail to
10306          * suspend/power down.
10307          */
10308         if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10309             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10310                 pptr->port_state &= ~flag;
10311                 mutex_exit(&pptr->port_mutex);
10312                 return (FC_FAILURE);
10313         }
10314 
10315         if (flag == FCP_STATE_DETACHING) {
10316                 pptr = fcp_soft_state_unlink(pptr);
10317                 ASSERT(pptr != NULL);
10318         }
10319 
10320         pptr->port_link_cnt++;
10321         pptr->port_state |= FCP_STATE_OFFLINE;
10322         pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10323 
10324         fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10325             FCP_CAUSE_LINK_DOWN);
10326         mutex_exit(&pptr->port_mutex);
10327 
10328         /* kill watch dog timer if we're the last */
10329         mutex_enter(&fcp_global_mutex);
10330         if (--fcp_watchdog_init == 0) {
10331                 timeout_id_t    tid = fcp_watchdog_id;
10332                 mutex_exit(&fcp_global_mutex);
10333                 (void) untimeout(tid);
10334         } else {
10335                 mutex_exit(&fcp_global_mutex);
10336         }
10337 
10338         /* clean up the port structures */
10339         if (flag == FCP_STATE_DETACHING) {
10340                 fcp_cleanup_port(pptr, instance);
10341         }
10342 
10343         return (FC_SUCCESS);
10344 }
10345 
10346 
10347 static void
10348 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10349 {
10350         ASSERT(pptr != NULL);
10351 
10352         /* unbind and free event set */
10353         if (pptr->port_ndi_event_hdl) {
10354                 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10355                     &pptr->port_ndi_events, NDI_SLEEP);
10356                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10357         }
10358 
10359         if (pptr->port_ndi_event_defs) {
10360                 (void) kmem_free(pptr->port_ndi_event_defs,
10361                     sizeof (fcp_ndi_event_defs));
10362         }
10363 
10364         /* free the lun/target structures and devinfos */
10365         fcp_free_targets(pptr);
10366 
10367         /*
10368          * Clean up mpxio stuff
10369          */
10370         if (pptr->port_mpxio) {
10371                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10372                 pptr->port_mpxio--;
10373         }
10374 
10375         /* clean up SCSA stuff */
10376         (void) scsi_hba_detach(pptr->port_dip);
10377         if (pptr->port_tran != NULL) {
10378                 scsi_hba_tran_free(pptr->port_tran);
10379         }
10380 
10381 #ifdef  KSTATS_CODE
10382         /* clean up kstats */
10383         if (pptr->fcp_ksp != NULL) {
10384                 kstat_delete(pptr->fcp_ksp);
10385         }
10386 #endif
10387 
10388         /* clean up soft state mutexes/condition variables */
10389         mutex_destroy(&pptr->port_mutex);
10390         mutex_destroy(&pptr->port_pkt_mutex);
10391 
10392         /* all done with soft state */
10393         ddi_soft_state_free(fcp_softstate, instance);
10394 }
10395 
10396 /*
10397  *     Function: fcp_kmem_cache_constructor
10398  *
10399  *  Description: This function allocates and initializes the resources required
10400  *               to build a scsi_pkt structure the target driver.  The result
10401  *               of the allocation and initialization will be cached in the
10402  *               memory cache.  As DMA resources may be allocated here, that
10403  *               means DMA resources will be tied up in the cache manager.
10404  *               This is a tradeoff that has been made for performance reasons.
10405  *
10406  *     Argument: *buf           Memory to preinitialize.
10407  *               *arg           FCP port structure (fcp_port).
10408  *               kmflags        Value passed to kmem_cache_alloc() and
10409  *                              propagated to the constructor.
10410  *
10411  * Return Value: 0      Allocation/Initialization was successful.
10412  *               -1     Allocation or Initialization failed.
10413  *
10414  *
10415  * If the returned value is 0, the buffer is initialized like this:
10416  *
10417  *                  +================================+
10418  *           +----> |              struct scsi_pkt        |
10419  *           |      |                                |
10420  *           | +--- | pkt_ha_private                 |
10421  *           | |    |                                |
10422  *           | |    +================================+
10423  *           | |
10424  *           | |    +================================+
10425  *           | +--> |            struct fcp_pkt           | <---------+
10426  *           |      |                                |           |
10427  *           +----- | cmd_pkt                        |           |
10428  *                  |                     cmd_fp_pkt | ---+      |
10429  *        +-------->| cmd_fcp_rsp[]               |    |      |
10430  *        |    +--->| cmd_fcp_cmd[]               |    |      |
10431  *        |    |    |--------------------------------|    |      |
10432  *        |    |    |         struct fc_packet       | <--+   |
10433  *        |    |    |                                |           |
10434  *        |    |    |                pkt_ulp_private | ----------+
10435  *        |    |    |                pkt_fca_private | -----+
10436  *        |    |    |                pkt_data_cookie | ---+ |
10437  *        |    |    | pkt_cmdlen                     |    | |
10438  *        |    |(a) | pkt_rsplen                     |    | |
10439  *        |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10440  *        |     (b) |                 pkt_cmd_cookie | ---|-|----------+    |
10441  *        +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10442  *                  |                pkt_resp_cookie | ---|-|--+   |   |    |
10443  *                  | pkt_cmd_dma                    |    | |  |   |   |    |
10444  *                  | pkt_cmd_acc                    |    | |  |   |   |    |
10445  *                  +================================+    | |  |   |   |    |
10446  *                  |         dma_cookies            | <--+ |  |   |   |    |
10447  *                  |                                |      |  |   |   |    |
10448  *                  +================================+      |  |   |   |    |
10449  *                  |         fca_private            | <----+  |   |   |    |
10450  *                  |                                |         |   |   |    |
10451  *                  +================================+         |   |   |    |
10452  *                                                             |   |   |    |
10453  *                                                             |   |   |    |
10454  *                  +================================+   (d)   |   |   |    |
10455  *                  |        fcp_resp cookies        | <-------+   |   |    |
10456  *                  |                                |             |   |    |
10457  *                  +================================+             |   |    |
10458  *                                                                 |   |    |
10459  *                  +================================+   (d)       |   |    |
10460  *                  |           fcp_resp             | <-----------+   |    |
10461  *                  |   (DMA resources associated)   |                 |    |
10462  *                  +================================+                 |    |
10463  *                                                                     |    |
10464  *                                                                     |    |
10465  *                                                                     |    |
10466  *                  +================================+   (c)           |    |
10467  *                  |        fcp_cmd cookies         | <---------------+    |
10468  *                  |                                |                      |
10469  *                  +================================+                      |
10470  *                                                                          |
10471  *                  +================================+   (c)                |
10472  *                  |            fcp_cmd             | <--------------------+
10473  *                  |   (DMA resources associated)   |
10474  *                  +================================+
10475  *
10476  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10477  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10478  * (c) Only if DMA is used for the FCP_CMD buffer.
10479  * (d) Only if DMA is used for the FCP_RESP buffer
10480  */
10481 static int
10482 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10483     int kmflags)
10484 {
10485         struct fcp_pkt  *cmd;
10486         struct fcp_port *pptr;
10487         fc_packet_t     *fpkt;
10488 
10489         pptr = (struct fcp_port *)tran->tran_hba_private;
10490         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10491         bzero(cmd, tran->tran_hba_len);
10492 
10493         cmd->cmd_pkt = pkt;
10494         pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10495         fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10496         cmd->cmd_fp_pkt = fpkt;
10497 
10498         cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10499         cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10500         cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10501             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10502 
10503         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10504             sizeof (struct fcp_pkt));
10505 
10506         fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10507         fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10508 
10509         if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10510                 /*
10511                  * The underlying HBA doesn't want to DMA the fcp_cmd or
10512                  * fcp_resp.  The transfer of information will be done by
10513                  * bcopy.
10514                  * The naming of the flags (that is actually a value) is
10515                  * unfortunate.  FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10516                  * DMA" but instead "NO DMA".
10517                  */
10518                 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10519                 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10520                 fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10521         } else {
10522                 /*
10523                  * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10524                  * buffer.  A buffer is allocated for each one the ddi_dma_*
10525                  * interfaces.
10526                  */
10527                 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10528                         return (-1);
10529                 }
10530         }
10531 
10532         return (0);
10533 }
10534 
10535 /*
10536  *     Function: fcp_kmem_cache_destructor
10537  *
10538  *  Description: Called by the destructor of the cache managed by SCSA.
10539  *               All the resources pre-allocated in fcp_pkt_constructor
10540  *               and the data also pre-initialized in fcp_pkt_constructor
10541  *               are freed and uninitialized here.
10542  *
10543  *     Argument: *buf           Memory to uninitialize.
10544  *               *arg           FCP port structure (fcp_port).
10545  *
10546  * Return Value: None
10547  *
10548  *      Context: kernel
10549  */
10550 static void
10551 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10552 {
10553         struct fcp_pkt  *cmd;
10554         struct fcp_port *pptr;
10555 
10556         pptr = (struct fcp_port *)(tran->tran_hba_private);
10557         cmd = pkt->pkt_ha_private;
10558 
10559         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10560                 /*
10561                  * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10562                  * buffer and DMA resources allocated to do so are released.
10563                  */
10564                 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10565         }
10566 }
10567 
10568 /*
10569  *     Function: fcp_alloc_cmd_resp
10570  *
10571  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10572  *               will be DMAed by the HBA.  The buffer is allocated applying
10573  *               the DMA requirements for the HBA.  The buffers allocated will
10574  *               also be bound.  DMA resources are allocated in the process.
10575  *               They will be released by fcp_free_cmd_resp().
10576  *
10577  *     Argument: *pptr  FCP port.
10578  *               *fpkt  fc packet for which the cmd and resp packet should be
10579  *                      allocated.
10580  *               flags  Allocation flags.
10581  *
10582  * Return Value: FC_FAILURE
10583  *               FC_SUCCESS
10584  *
10585  *      Context: User or Kernel context only if flags == KM_SLEEP.
10586  *               Interrupt context if the KM_SLEEP is not specified.
10587  */
10588 static int
10589 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10590 {
10591         int                     rval;
10592         int                     cmd_len;
10593         int                     resp_len;
10594         ulong_t                 real_len;
10595         int                     (*cb) (caddr_t);
10596         ddi_dma_cookie_t        pkt_cookie;
10597         ddi_dma_cookie_t        *cp;
10598         uint32_t                cnt;
10599 
10600         cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10601 
10602         cmd_len = fpkt->pkt_cmdlen;
10603         resp_len = fpkt->pkt_rsplen;
10604 
10605         ASSERT(fpkt->pkt_cmd_dma == NULL);
10606 
10607         /* Allocation of a DMA handle used in subsequent calls. */
10608         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10609             cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10610                 return (FC_FAILURE);
10611         }
10612 
10613         /* A buffer is allocated that satisfies the DMA requirements. */
10614         rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10615             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10616             (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10617 
10618         if (rval != DDI_SUCCESS) {
10619                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10620                 return (FC_FAILURE);
10621         }
10622 
10623         if (real_len < cmd_len) {
10624                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10625                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10626                 return (FC_FAILURE);
10627         }
10628 
10629         /* The buffer allocated is DMA bound. */
10630         rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10631             fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10632             cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10633 
10634         if (rval != DDI_DMA_MAPPED) {
10635                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10636                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10637                 return (FC_FAILURE);
10638         }
10639 
10640         if (fpkt->pkt_cmd_cookie_cnt >
10641             pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10642                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10643                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10644                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10645                 return (FC_FAILURE);
10646         }
10647 
10648         ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10649 
10650         /*
10651          * The buffer where the scatter/gather list is going to be built is
10652          * allocated.
10653          */
10654         cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10655             fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10656             KM_NOSLEEP);
10657 
10658         if (cp == NULL) {
10659                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10660                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10661                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10662                 return (FC_FAILURE);
10663         }
10664 
10665         /*
10666          * The scatter/gather list for the buffer we just allocated is built
10667          * here.
10668          */
10669         *cp = pkt_cookie;
10670         cp++;
10671 
10672         for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10673                 ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10674                     &pkt_cookie);
10675                 *cp = pkt_cookie;
10676         }
10677 
10678         ASSERT(fpkt->pkt_resp_dma == NULL);
10679         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10680             cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10681                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10682                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10683                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10684                 return (FC_FAILURE);
10685         }
10686 
10687         rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10688             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10689             (caddr_t *)&fpkt->pkt_resp, &real_len,
10690             &fpkt->pkt_resp_acc);
10691 
10692         if (rval != DDI_SUCCESS) {
10693                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10694                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10695                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10696                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10697                 kmem_free(fpkt->pkt_cmd_cookie,
10698                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10699                 return (FC_FAILURE);
10700         }
10701 
10702         if (real_len < resp_len) {
10703                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10704                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10705                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10706                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10707                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10708                 kmem_free(fpkt->pkt_cmd_cookie,
10709                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10710                 return (FC_FAILURE);
10711         }
10712 
10713         rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10714             fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10715             cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10716 
10717         if (rval != DDI_DMA_MAPPED) {
10718                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10719                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10720                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10721                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10722                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10723                 kmem_free(fpkt->pkt_cmd_cookie,
10724                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10725                 return (FC_FAILURE);
10726         }
10727 
10728         if (fpkt->pkt_resp_cookie_cnt >
10729             pptr->port_resp_dma_attr.dma_attr_sgllen) {
10730                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10731                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10732                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10733                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10734                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10735                 kmem_free(fpkt->pkt_cmd_cookie,
10736                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10737                 return (FC_FAILURE);
10738         }
10739 
10740         ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10741 
10742         cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10743             fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10744             KM_NOSLEEP);
10745 
10746         if (cp == NULL) {
10747                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10748                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10749                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10750                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10751                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10752                 kmem_free(fpkt->pkt_cmd_cookie,
10753                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10754                 return (FC_FAILURE);
10755         }
10756 
10757         *cp = pkt_cookie;
10758         cp++;
10759 
10760         for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10761                 ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10762                     &pkt_cookie);
10763                 *cp = pkt_cookie;
10764         }
10765 
10766         return (FC_SUCCESS);
10767 }
10768 
10769 /*
10770  *     Function: fcp_free_cmd_resp
10771  *
10772  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10773  *               allocated by fcp_alloc_cmd_resp() and all the resources
10774  *               associated with them.  That includes the DMA resources and the
10775  *               buffer allocated for the cookies of each one of them.
10776  *
10777  *     Argument: *pptr          FCP port context.
10778  *               *fpkt          fc packet containing the cmd and resp packet
10779  *                              to be released.
10780  *
10781  * Return Value: None
10782  *
10783  *      Context: Interrupt, User and Kernel context.
10784  */
10785 /* ARGSUSED */
10786 static void
10787 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10788 {
10789         ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10790 
10791         if (fpkt->pkt_resp_dma) {
10792                 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10793                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10794                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10795         }
10796 
10797         if (fpkt->pkt_resp_cookie) {
10798                 kmem_free(fpkt->pkt_resp_cookie,
10799                     fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10800                 fpkt->pkt_resp_cookie = NULL;
10801         }
10802 
10803         if (fpkt->pkt_cmd_dma) {
10804                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10805                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10806                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10807         }
10808 
10809         if (fpkt->pkt_cmd_cookie) {
10810                 kmem_free(fpkt->pkt_cmd_cookie,
10811                     fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10812                 fpkt->pkt_cmd_cookie = NULL;
10813         }
10814 }
10815 
10816 
10817 /*
10818  * called by the transport to do our own target initialization
10819  *
10820  * can acquire and release the global mutex
10821  */
10822 /* ARGSUSED */
10823 static int
10824 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10825     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10826 {
10827         uchar_t                 *bytes;
10828         uint_t                  nbytes;
10829         uint16_t                lun_num;
10830         struct fcp_tgt  *ptgt;
10831         struct fcp_lun  *plun;
10832         struct fcp_port *pptr = (struct fcp_port *)
10833             hba_tran->tran_hba_private;
10834 
10835         ASSERT(pptr != NULL);
10836 
10837         FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10838             FCP_BUF_LEVEL_8, 0,
10839             "fcp_phys_tgt_init: called for %s (instance %d)",
10840             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10841 
10842         /* get our port WWN property */
10843         bytes = NULL;
10844         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10845             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10846             (nbytes != FC_WWN_SIZE)) {
10847                 /* no port WWN property */
10848                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10849                     FCP_BUF_LEVEL_8, 0,
10850                     "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10851                     " for %s (instance %d): bytes=%p nbytes=%x",
10852                     ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10853                     nbytes);
10854 
10855                 if (bytes != NULL) {
10856                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10857                 }
10858 
10859                 return (DDI_NOT_WELL_FORMED);
10860         }
10861         ASSERT(bytes != NULL);
10862 
10863         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10864             LUN_PROP, 0xFFFF);
10865         if (lun_num == 0xFFFF) {
10866                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10867                     FCP_BUF_LEVEL_8, 0,
10868                     "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10869                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10870                     ddi_get_instance(tgt_dip));
10871 
10872                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10873                 return (DDI_NOT_WELL_FORMED);
10874         }
10875 
10876         mutex_enter(&pptr->port_mutex);
10877         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10878                 mutex_exit(&pptr->port_mutex);
10879                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10880                     FCP_BUF_LEVEL_8, 0,
10881                     "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10882                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10883                     ddi_get_instance(tgt_dip));
10884 
10885                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10886                 return (DDI_FAILURE);
10887         }
10888 
10889         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10890             FC_WWN_SIZE) == 0);
10891         ASSERT(plun->lun_num == lun_num);
10892 
10893         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10894 
10895         ptgt = plun->lun_tgt;
10896 
10897         mutex_enter(&ptgt->tgt_mutex);
10898         plun->lun_tgt_count++;
10899         scsi_device_hba_private_set(sd, plun);
10900         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10901         plun->lun_sd = sd;
10902         mutex_exit(&ptgt->tgt_mutex);
10903         mutex_exit(&pptr->port_mutex);
10904 
10905         return (DDI_SUCCESS);
10906 }
10907 
10908 /*ARGSUSED*/
10909 static int
10910 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10911     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10912 {
10913         uchar_t                 *bytes;
10914         uint_t                  nbytes;
10915         uint16_t                lun_num;
10916         struct fcp_tgt  *ptgt;
10917         struct fcp_lun  *plun;
10918         struct fcp_port *pptr = (struct fcp_port *)
10919             hba_tran->tran_hba_private;
10920         child_info_t            *cip;
10921 
10922         ASSERT(pptr != NULL);
10923 
10924         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10925             fcp_trace, FCP_BUF_LEVEL_8, 0,
10926             "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10927             " (tgt_dip %p)", ddi_get_name(tgt_dip),
10928             ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10929 
10930         cip = (child_info_t *)sd->sd_pathinfo;
10931         if (cip == NULL) {
10932                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10933                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10934                     "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10935                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10936                     ddi_get_instance(tgt_dip));
10937 
10938                 return (DDI_NOT_WELL_FORMED);
10939         }
10940 
10941         /* get our port WWN property */
10942         bytes = NULL;
10943         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10944             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10945             (nbytes != FC_WWN_SIZE)) {
10946                 if (bytes) {
10947                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10948                 }
10949                 return (DDI_NOT_WELL_FORMED);
10950         }
10951 
10952         ASSERT(bytes != NULL);
10953 
10954         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10955             LUN_PROP, 0xFFFF);
10956         if (lun_num == 0xFFFF) {
10957                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10958                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10959                     "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10960                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10961                     ddi_get_instance(tgt_dip));
10962 
10963                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10964                 return (DDI_NOT_WELL_FORMED);
10965         }
10966 
10967         mutex_enter(&pptr->port_mutex);
10968         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10969                 mutex_exit(&pptr->port_mutex);
10970                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10971                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10972                     "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10973                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10974                     ddi_get_instance(tgt_dip));
10975 
10976                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10977                 return (DDI_FAILURE);
10978         }
10979 
10980         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10981             FC_WWN_SIZE) == 0);
10982         ASSERT(plun->lun_num == lun_num);
10983 
10984         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10985 
10986         ptgt = plun->lun_tgt;
10987 
10988         mutex_enter(&ptgt->tgt_mutex);
10989         plun->lun_tgt_count++;
10990         scsi_device_hba_private_set(sd, plun);
10991         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10992         plun->lun_sd = sd;
10993         mutex_exit(&ptgt->tgt_mutex);
10994         mutex_exit(&pptr->port_mutex);
10995 
10996         return (DDI_SUCCESS);
10997 }
10998 
10999 
11000 /*
11001  * called by the transport to do our own target initialization
11002  *
11003  * can acquire and release the global mutex
11004  */
11005 /* ARGSUSED */
11006 static int
11007 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11008     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11009 {
11010         struct fcp_port *pptr = (struct fcp_port *)
11011             hba_tran->tran_hba_private;
11012         int                     rval;
11013 
11014         ASSERT(pptr != NULL);
11015 
11016         /*
11017          * Child node is getting initialized.  Look at the mpxio component
11018          * type on the child device to see if this device is mpxio managed
11019          * or not.
11020          */
11021         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11022                 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11023         } else {
11024                 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11025         }
11026 
11027         return (rval);
11028 }
11029 
11030 
11031 /* ARGSUSED */
11032 static void
11033 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11034     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11035 {
11036         struct fcp_lun  *plun = scsi_device_hba_private_get(sd);
11037         struct fcp_tgt  *ptgt;
11038 
11039         FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11040             fcp_trace, FCP_BUF_LEVEL_8, 0,
11041             "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11042             ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11043             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11044 
11045         if (plun == NULL) {
11046                 return;
11047         }
11048         ptgt = plun->lun_tgt;
11049 
11050         ASSERT(ptgt != NULL);
11051 
11052         mutex_enter(&ptgt->tgt_mutex);
11053         ASSERT(plun->lun_tgt_count > 0);
11054 
11055         if (--plun->lun_tgt_count == 0) {
11056                 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11057         }
11058         plun->lun_sd = NULL;
11059         mutex_exit(&ptgt->tgt_mutex);
11060 }
11061 
11062 /*
11063  *     Function: fcp_scsi_start
11064  *
11065  *  Description: This function is called by the target driver to request a
11066  *               command to be sent.
11067  *
11068  *     Argument: *ap            SCSI address of the device.
11069  *               *pkt           SCSI packet containing the cmd to send.
11070  *
11071  * Return Value: TRAN_ACCEPT
11072  *               TRAN_BUSY
11073  *               TRAN_BADPKT
11074  *               TRAN_FATAL_ERROR
11075  */
11076 static int
11077 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11078 {
11079         struct fcp_port *pptr = ADDR2FCP(ap);
11080         struct fcp_lun  *plun = ADDR2LUN(ap);
11081         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11082         struct fcp_tgt  *ptgt = plun->lun_tgt;
11083         int                     rval;
11084 
11085         /* ensure command isn't already issued */
11086         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11087 
11088         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11089             fcp_trace, FCP_BUF_LEVEL_9, 0,
11090             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11091 
11092         /*
11093          * It is strange that we enter the fcp_port mutex and the target
11094          * mutex to check the lun state (which has a mutex of its own).
11095          */
11096         mutex_enter(&pptr->port_mutex);
11097         mutex_enter(&ptgt->tgt_mutex);
11098 
11099         /*
11100          * If the device is offline and is not in the process of coming
11101          * online, fail the request.
11102          */
11103 
11104         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11105             !(plun->lun_state & FCP_LUN_ONLINING)) {
11106                 mutex_exit(&ptgt->tgt_mutex);
11107                 mutex_exit(&pptr->port_mutex);
11108 
11109                 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11110                         pkt->pkt_reason = CMD_DEV_GONE;
11111                 }
11112 
11113                 return (TRAN_FATAL_ERROR);
11114         }
11115         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11116 
11117         /*
11118          * If we are suspended, kernel is trying to dump, so don't
11119          * block, fail or defer requests - send them down right away.
11120          * NOTE: If we are in panic (i.e. trying to dump), we can't
11121          * assume we have been suspended.  There is hardware such as
11122          * the v880 that doesn't do PM.  Thus, the check for
11123          * ddi_in_panic.
11124          *
11125          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11126          * of changing.  So, if we can queue the packet, do it.  Eventually,
11127          * either the device will have gone away or changed and we can fail
11128          * the request, or we can proceed if the device didn't change.
11129          *
11130          * If the pd in the target or the packet is NULL it's probably
11131          * because the device has gone away, we allow the request to be
11132          * put on the internal queue here in case the device comes back within
11133          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11134          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11135          * could be NULL because the device was disappearing during or since
11136          * packet initialization.
11137          */
11138 
11139         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11140             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11141             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11142             (ptgt->tgt_pd_handle == NULL) ||
11143             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11144                 /*
11145                  * If ((LUN is busy AND
11146                  *      LUN not suspended AND
11147                  *      The system is not in panic state) OR
11148                  *      (The port is coming up))
11149                  *
11150                  * We check to see if the any of the flags FLAG_NOINTR or
11151                  * FLAG_NOQUEUE is set.  If one of them is set the value
11152                  * returned will be TRAN_BUSY.  If not, the request is queued.
11153                  */
11154                 mutex_exit(&ptgt->tgt_mutex);
11155                 mutex_exit(&pptr->port_mutex);
11156 
11157                 /* see if using interrupts is allowed (so queueing'll work) */
11158                 if (pkt->pkt_flags & FLAG_NOINTR) {
11159                         pkt->pkt_resid = 0;
11160                         return (TRAN_BUSY);
11161                 }
11162                 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11163                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11164                             fcp_trace, FCP_BUF_LEVEL_9, 0,
11165                             "fcp_scsi_start: lun busy for pkt %p", pkt);
11166                         return (TRAN_BUSY);
11167                 }
11168 #ifdef  DEBUG
11169                 mutex_enter(&pptr->port_pkt_mutex);
11170                 pptr->port_npkts++;
11171                 mutex_exit(&pptr->port_pkt_mutex);
11172 #endif /* DEBUG */
11173 
11174                 /* got queue up the pkt for later */
11175                 fcp_queue_pkt(pptr, cmd);
11176                 return (TRAN_ACCEPT);
11177         }
11178         cmd->cmd_state = FCP_PKT_ISSUED;
11179 
11180         mutex_exit(&ptgt->tgt_mutex);
11181         mutex_exit(&pptr->port_mutex);
11182 
11183         /*
11184          * Now that we released the mutexes, what was protected by them can
11185          * change.
11186          */
11187 
11188         /*
11189          * If there is a reconfiguration in progress, wait for it to complete.
11190          */
11191         fcp_reconfig_wait(pptr);
11192 
11193         cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11194             pkt->pkt_time : 0;
11195 
11196         /* prepare the packet */
11197 
11198         fcp_prepare_pkt(pptr, cmd, plun);
11199 
11200         if (cmd->cmd_pkt->pkt_time) {
11201                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11202         } else {
11203                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11204         }
11205 
11206         /*
11207          * if interrupts aren't allowed (e.g. at dump time) then we'll
11208          * have to do polled I/O
11209          */
11210         if (pkt->pkt_flags & FLAG_NOINTR) {
11211                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
11212                 return (fcp_dopoll(pptr, cmd));
11213         }
11214 
11215 #ifdef  DEBUG
11216         mutex_enter(&pptr->port_pkt_mutex);
11217         pptr->port_npkts++;
11218         mutex_exit(&pptr->port_pkt_mutex);
11219 #endif /* DEBUG */
11220 
11221         rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11222         if (rval == FC_SUCCESS) {
11223                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11224                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11225                     "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11226                 return (TRAN_ACCEPT);
11227         }
11228 
11229         cmd->cmd_state = FCP_PKT_IDLE;
11230 
11231 #ifdef  DEBUG
11232         mutex_enter(&pptr->port_pkt_mutex);
11233         pptr->port_npkts--;
11234         mutex_exit(&pptr->port_pkt_mutex);
11235 #endif /* DEBUG */
11236 
11237         /*
11238          * For lack of clearer definitions, choose
11239          * between TRAN_BUSY and TRAN_FATAL_ERROR.
11240          */
11241 
11242         if (rval == FC_TRAN_BUSY) {
11243                 pkt->pkt_resid = 0;
11244                 rval = TRAN_BUSY;
11245         } else {
11246                 mutex_enter(&ptgt->tgt_mutex);
11247                 if (plun->lun_state & FCP_LUN_OFFLINE) {
11248                         child_info_t    *cip;
11249 
11250                         mutex_enter(&plun->lun_mutex);
11251                         cip = plun->lun_cip;
11252                         mutex_exit(&plun->lun_mutex);
11253 
11254                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11255                             fcp_trace, FCP_BUF_LEVEL_6, 0,
11256                             "fcp_transport failed 2 for %x: %x; dip=%p",
11257                             plun->lun_tgt->tgt_d_id, rval, cip);
11258 
11259                         rval = TRAN_FATAL_ERROR;
11260                 } else {
11261                         if (pkt->pkt_flags & FLAG_NOQUEUE) {
11262                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11263                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11264                                     "fcp_scsi_start: FC_BUSY for pkt %p",
11265                                     pkt);
11266                                 rval = TRAN_BUSY;
11267                         } else {
11268                                 rval = TRAN_ACCEPT;
11269                                 fcp_queue_pkt(pptr, cmd);
11270                         }
11271                 }
11272                 mutex_exit(&ptgt->tgt_mutex);
11273         }
11274 
11275         return (rval);
11276 }
11277 
11278 /*
11279  * called by the transport to abort a packet
11280  */
11281 /*ARGSUSED*/
11282 static int
11283 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11284 {
11285         int tgt_cnt;
11286         struct fcp_port         *pptr = ADDR2FCP(ap);
11287         struct fcp_lun  *plun = ADDR2LUN(ap);
11288         struct fcp_tgt  *ptgt = plun->lun_tgt;
11289 
11290         if (pkt == NULL) {
11291                 if (ptgt) {
11292                         mutex_enter(&ptgt->tgt_mutex);
11293                         tgt_cnt = ptgt->tgt_change_cnt;
11294                         mutex_exit(&ptgt->tgt_mutex);
11295                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11296                         return (TRUE);
11297                 }
11298         }
11299         return (FALSE);
11300 }
11301 
11302 
11303 /*
11304  * Perform reset
11305  */
11306 int
11307 fcp_scsi_reset(struct scsi_address *ap, int level)
11308 {
11309         int                     rval = 0;
11310         struct fcp_port         *pptr = ADDR2FCP(ap);
11311         struct fcp_lun  *plun = ADDR2LUN(ap);
11312         struct fcp_tgt  *ptgt = plun->lun_tgt;
11313 
11314         if (level == RESET_ALL) {
11315                 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11316                         rval = 1;
11317                 }
11318         } else if (level == RESET_TARGET || level == RESET_LUN) {
11319                 /*
11320                  * If we are in the middle of discovery, return
11321                  * SUCCESS as this target will be rediscovered
11322                  * anyway
11323                  */
11324                 mutex_enter(&ptgt->tgt_mutex);
11325                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11326                         mutex_exit(&ptgt->tgt_mutex);
11327                         return (1);
11328                 }
11329                 mutex_exit(&ptgt->tgt_mutex);
11330 
11331                 if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11332                         rval = 1;
11333                 }
11334         }
11335         return (rval);
11336 }
11337 
11338 
11339 /*
11340  * called by the framework to get a SCSI capability
11341  */
11342 static int
11343 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11344 {
11345         return (fcp_commoncap(ap, cap, 0, whom, 0));
11346 }
11347 
11348 
11349 /*
11350  * called by the framework to set a SCSI capability
11351  */
11352 static int
11353 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11354 {
11355         return (fcp_commoncap(ap, cap, value, whom, 1));
11356 }
11357 
11358 /*
11359  *     Function: fcp_pkt_setup
11360  *
11361  *  Description: This function sets up the scsi_pkt structure passed by the
11362  *               caller. This function assumes fcp_pkt_constructor has been
11363  *               called previously for the packet passed by the caller.  If
11364  *               successful this call will have the following results:
11365  *
11366  *                 - The resources needed that will be constant through out
11367  *                   the whole transaction are allocated.
11368  *                 - The fields that will be constant through out the whole
11369  *                   transaction are initialized.
11370  *                 - The scsi packet will be linked to the LUN structure
11371  *                   addressed by the transaction.
11372  *
11373  *     Argument:
11374  *               *pkt           Pointer to a scsi_pkt structure.
11375  *               callback
11376  *               arg
11377  *
11378  * Return Value: 0      Success
11379  *               !0     Failure
11380  *
11381  *      Context: Kernel context or interrupt context
11382  */
11383 /* ARGSUSED */
11384 static int
11385 fcp_pkt_setup(struct scsi_pkt *pkt,
11386     int (*callback)(caddr_t arg),
11387     caddr_t arg)
11388 {
11389         struct fcp_pkt  *cmd;
11390         struct fcp_port *pptr;
11391         struct fcp_lun  *plun;
11392         struct fcp_tgt  *ptgt;
11393         int             kf;
11394         fc_packet_t     *fpkt;
11395         fc_frame_hdr_t  *hp;
11396 
11397         pptr = ADDR2FCP(&pkt->pkt_address);
11398         plun = ADDR2LUN(&pkt->pkt_address);
11399         ptgt = plun->lun_tgt;
11400 
11401         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11402         fpkt = cmd->cmd_fp_pkt;
11403 
11404         /*
11405          * this request is for dma allocation only
11406          */
11407         /*
11408          * First step of fcp_scsi_init_pkt: pkt allocation
11409          * We determine if the caller is willing to wait for the
11410          * resources.
11411          */
11412         kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11413 
11414         /*
11415          * Selective zeroing of the pkt.
11416          */
11417         cmd->cmd_back = NULL;
11418         cmd->cmd_next = NULL;
11419 
11420         /*
11421          * Zero out fcp command
11422          */
11423         bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11424 
11425         cmd->cmd_state = FCP_PKT_IDLE;
11426 
11427         fpkt = cmd->cmd_fp_pkt;
11428         fpkt->pkt_data_acc = NULL;
11429 
11430         /*
11431          * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11432          * could be destroyed.  We need fail pkt_setup.
11433          */
11434         if (pptr->port_state & FCP_STATE_OFFLINE) {
11435                 return (-1);
11436         }
11437 
11438         mutex_enter(&ptgt->tgt_mutex);
11439         fpkt->pkt_pd = ptgt->tgt_pd_handle;
11440 
11441         if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11442             != FC_SUCCESS) {
11443                 mutex_exit(&ptgt->tgt_mutex);
11444                 return (-1);
11445         }
11446 
11447         mutex_exit(&ptgt->tgt_mutex);
11448 
11449         /* Fill in the Fabric Channel Header */
11450         hp = &fpkt->pkt_cmd_fhdr;
11451         hp->r_ctl = R_CTL_COMMAND;
11452         hp->rsvd = 0;
11453         hp->type = FC_TYPE_SCSI_FCP;
11454         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11455         hp->seq_id = 0;
11456         hp->df_ctl  = 0;
11457         hp->seq_cnt = 0;
11458         hp->ox_id = 0xffff;
11459         hp->rx_id = 0xffff;
11460         hp->ro = 0;
11461 
11462         /*
11463          * A doubly linked list (cmd_forw, cmd_back) is built
11464          * out of every allocated packet on a per-lun basis
11465          *
11466          * The packets are maintained in the list so as to satisfy
11467          * scsi_abort() requests. At present (which is unlikely to
11468          * change in the future) nobody performs a real scsi_abort
11469          * in the SCSI target drivers (as they don't keep the packets
11470          * after doing scsi_transport - so they don't know how to
11471          * abort a packet other than sending a NULL to abort all
11472          * outstanding packets)
11473          */
11474         mutex_enter(&plun->lun_mutex);
11475         if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11476                 plun->lun_pkt_head->cmd_back = cmd;
11477         } else {
11478                 plun->lun_pkt_tail = cmd;
11479         }
11480         plun->lun_pkt_head = cmd;
11481         mutex_exit(&plun->lun_mutex);
11482         return (0);
11483 }
11484 
11485 /*
11486  *     Function: fcp_pkt_teardown
11487  *
11488  *  Description: This function releases a scsi_pkt structure and all the
11489  *               resources attached to it.
11490  *
11491  *     Argument: *pkt           Pointer to a scsi_pkt structure.
11492  *
11493  * Return Value: None
11494  *
11495  *      Context: User, Kernel or Interrupt context.
11496  */
11497 static void
11498 fcp_pkt_teardown(struct scsi_pkt *pkt)
11499 {
11500         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
11501         struct fcp_lun  *plun = ADDR2LUN(&pkt->pkt_address);
11502         struct fcp_pkt  *cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11503 
11504         /*
11505          * Remove the packet from the per-lun list
11506          */
11507         mutex_enter(&plun->lun_mutex);
11508         if (cmd->cmd_back) {
11509                 ASSERT(cmd != plun->lun_pkt_head);
11510                 cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11511         } else {
11512                 ASSERT(cmd == plun->lun_pkt_head);
11513                 plun->lun_pkt_head = cmd->cmd_forw;
11514         }
11515 
11516         if (cmd->cmd_forw) {
11517                 cmd->cmd_forw->cmd_back = cmd->cmd_back;
11518         } else {
11519                 ASSERT(cmd == plun->lun_pkt_tail);
11520                 plun->lun_pkt_tail = cmd->cmd_back;
11521         }
11522 
11523         mutex_exit(&plun->lun_mutex);
11524 
11525         (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11526 }
11527 
11528 /*
11529  * Routine for reset notification setup, to register or cancel.
11530  * This function is called by SCSA
11531  */
11532 /*ARGSUSED*/
11533 static int
11534 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11535     void (*callback)(caddr_t), caddr_t arg)
11536 {
11537         struct fcp_port *pptr = ADDR2FCP(ap);
11538 
11539         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11540             &pptr->port_mutex, &pptr->port_reset_notify_listf));
11541 }
11542 
11543 
11544 static int
11545 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11546     ddi_eventcookie_t *event_cookiep)
11547 {
11548         struct fcp_port *pptr = fcp_dip2port(dip);
11549 
11550         if (pptr == NULL) {
11551                 return (DDI_FAILURE);
11552         }
11553 
11554         return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11555             event_cookiep, NDI_EVENT_NOPASS));
11556 }
11557 
11558 
11559 static int
11560 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11561     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11562     ddi_callback_id_t *cb_id)
11563 {
11564         struct fcp_port *pptr = fcp_dip2port(dip);
11565 
11566         if (pptr == NULL) {
11567                 return (DDI_FAILURE);
11568         }
11569 
11570         return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11571             eventid, callback, arg, NDI_SLEEP, cb_id));
11572 }
11573 
11574 
11575 static int
11576 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11577 {
11578 
11579         struct fcp_port *pptr = fcp_dip2port(dip);
11580 
11581         if (pptr == NULL) {
11582                 return (DDI_FAILURE);
11583         }
11584         return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11585 }
11586 
11587 
11588 /*
11589  * called by the transport to post an event
11590  */
11591 static int
11592 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11593     ddi_eventcookie_t eventid, void *impldata)
11594 {
11595         struct fcp_port *pptr = fcp_dip2port(dip);
11596 
11597         if (pptr == NULL) {
11598                 return (DDI_FAILURE);
11599         }
11600 
11601         return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11602             eventid, impldata));
11603 }
11604 
11605 
11606 /*
11607  * A target in in many cases in Fibre Channel has a one to one relation
11608  * with a port identifier (which is also known as D_ID and also as AL_PA
11609  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11610  * will most likely result in resetting all LUNs (which means a reset will
11611  * occur on all the SCSI devices connected at the other end of the bridge)
11612  * That is the latest favorite topic for discussion, for, one can debate as
11613  * hot as one likes and come up with arguably a best solution to one's
11614  * satisfaction
11615  *
11616  * To stay on track and not digress much, here are the problems stated
11617  * briefly:
11618  *
11619  *      SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11620  *      target drivers use RESET_TARGET even if their instance is on a
11621  *      LUN. Doesn't that sound a bit broken ?
11622  *
11623  *      FCP SCSI (the current spec) only defines RESET TARGET in the
11624  *      control fields of an FCP_CMND structure. It should have been
11625  *      fixed right there, giving flexibility to the initiators to
11626  *      minimize havoc that could be caused by resetting a target.
11627  */
11628 static int
11629 fcp_reset_target(struct scsi_address *ap, int level)
11630 {
11631         int                     rval = FC_FAILURE;
11632         char                    lun_id[25];
11633         struct fcp_port         *pptr = ADDR2FCP(ap);
11634         struct fcp_lun  *plun = ADDR2LUN(ap);
11635         struct fcp_tgt  *ptgt = plun->lun_tgt;
11636         struct scsi_pkt         *pkt;
11637         struct fcp_pkt  *cmd;
11638         struct fcp_rsp          *rsp;
11639         uint32_t                tgt_cnt;
11640         struct fcp_rsp_info     *rsp_info;
11641         struct fcp_reset_elem   *p;
11642         int                     bval;
11643 
11644         if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11645             KM_NOSLEEP)) == NULL) {
11646                 return (rval);
11647         }
11648 
11649         mutex_enter(&ptgt->tgt_mutex);
11650         if (level == RESET_TARGET) {
11651                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11652                         mutex_exit(&ptgt->tgt_mutex);
11653                         kmem_free(p, sizeof (struct fcp_reset_elem));
11654                         return (rval);
11655                 }
11656                 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11657                 (void) strcpy(lun_id, " ");
11658         } else {
11659                 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11660                         mutex_exit(&ptgt->tgt_mutex);
11661                         kmem_free(p, sizeof (struct fcp_reset_elem));
11662                         return (rval);
11663                 }
11664                 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11665 
11666                 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11667         }
11668         tgt_cnt = ptgt->tgt_change_cnt;
11669 
11670         mutex_exit(&ptgt->tgt_mutex);
11671 
11672         if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11673             0, 0, NULL, 0)) == NULL) {
11674                 kmem_free(p, sizeof (struct fcp_reset_elem));
11675                 mutex_enter(&ptgt->tgt_mutex);
11676                 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11677                 mutex_exit(&ptgt->tgt_mutex);
11678                 return (rval);
11679         }
11680         pkt->pkt_time = FCP_POLL_TIMEOUT;
11681 
11682         /* fill in cmd part of packet */
11683         cmd = PKT2CMD(pkt);
11684         if (level == RESET_TARGET) {
11685                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11686         } else {
11687                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11688         }
11689         cmd->cmd_fp_pkt->pkt_comp = NULL;
11690         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11691 
11692         /* prepare a packet for transport */
11693         fcp_prepare_pkt(pptr, cmd, plun);
11694 
11695         if (cmd->cmd_pkt->pkt_time) {
11696                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11697         } else {
11698                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11699         }
11700 
11701         (void) fc_ulp_busy_port(pptr->port_fp_handle);
11702         bval = fcp_dopoll(pptr, cmd);
11703         fc_ulp_idle_port(pptr->port_fp_handle);
11704 
11705         /* submit the packet */
11706         if (bval == TRAN_ACCEPT) {
11707                 int error = 3;
11708 
11709                 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11710                 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11711                     sizeof (struct fcp_rsp));
11712 
11713                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
11714                         if (fcp_validate_fcp_response(rsp, pptr) ==
11715                             FC_SUCCESS) {
11716                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11717                                         FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11718                                             sizeof (struct fcp_rsp), rsp_info,
11719                                             cmd->cmd_fp_pkt->pkt_resp_acc,
11720                                             sizeof (struct fcp_rsp_info));
11721                                 }
11722                                 if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11723                                         rval = FC_SUCCESS;
11724                                         error = 0;
11725                                 } else {
11726                                         error = 1;
11727                                 }
11728                         } else {
11729                                 error = 2;
11730                         }
11731                 }
11732 
11733                 switch (error) {
11734                 case 0:
11735                         fcp_log(CE_WARN, pptr->port_dip,
11736                             "!FCP: WWN 0x%08x%08x %s reset successfully",
11737                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11738                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11739                         break;
11740 
11741                 case 1:
11742                         fcp_log(CE_WARN, pptr->port_dip,
11743                             "!FCP: Reset to WWN  0x%08x%08x %s failed,"
11744                             " response code=%x",
11745                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11746                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11747                             rsp_info->rsp_code);
11748                         break;
11749 
11750                 case 2:
11751                         fcp_log(CE_WARN, pptr->port_dip,
11752                             "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11753                             " Bad FCP response values: rsvd1=%x,"
11754                             " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11755                             " rsplen=%x, senselen=%x",
11756                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11757                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11758                             rsp->reserved_0, rsp->reserved_1,
11759                             rsp->fcp_u.fcp_status.reserved_0,
11760                             rsp->fcp_u.fcp_status.reserved_1,
11761                             rsp->fcp_response_len, rsp->fcp_sense_len);
11762                         break;
11763 
11764                 default:
11765                         fcp_log(CE_WARN, pptr->port_dip,
11766                             "!FCP: Reset to WWN  0x%08x%08x %s failed",
11767                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11768                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11769                         break;
11770                 }
11771         }
11772         scsi_destroy_pkt(pkt);
11773 
11774         if (rval == FC_FAILURE) {
11775                 mutex_enter(&ptgt->tgt_mutex);
11776                 if (level == RESET_TARGET) {
11777                         fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11778                 } else {
11779                         fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11780                 }
11781                 mutex_exit(&ptgt->tgt_mutex);
11782                 kmem_free(p, sizeof (struct fcp_reset_elem));
11783                 return (rval);
11784         }
11785 
11786         mutex_enter(&pptr->port_mutex);
11787         if (level == RESET_TARGET) {
11788                 p->tgt = ptgt;
11789                 p->lun = NULL;
11790         } else {
11791                 p->tgt = NULL;
11792                 p->lun = plun;
11793         }
11794         p->tgt = ptgt;
11795         p->tgt_cnt = tgt_cnt;
11796         p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11797         p->next = pptr->port_reset_list;
11798         pptr->port_reset_list = p;
11799 
11800         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11801             fcp_trace, FCP_BUF_LEVEL_3, 0,
11802             "Notify ssd of the reset to reinstate the reservations");
11803 
11804         scsi_hba_reset_notify_callback(&pptr->port_mutex,
11805             &pptr->port_reset_notify_listf);
11806 
11807         mutex_exit(&pptr->port_mutex);
11808 
11809         return (rval);
11810 }
11811 
11812 
11813 /*
11814  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11815  * SCSI capabilities
11816  */
11817 /* ARGSUSED */
11818 static int
11819 fcp_commoncap(struct scsi_address *ap, char *cap,
11820     int val, int tgtonly, int doset)
11821 {
11822         struct fcp_port         *pptr = ADDR2FCP(ap);
11823         struct fcp_lun  *plun = ADDR2LUN(ap);
11824         struct fcp_tgt  *ptgt = plun->lun_tgt;
11825         int                     cidx;
11826         int                     rval = FALSE;
11827 
11828         if (cap == (char *)0) {
11829                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11830                     fcp_trace, FCP_BUF_LEVEL_3, 0,
11831                     "fcp_commoncap: invalid arg");
11832                 return (rval);
11833         }
11834 
11835         if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11836                 return (UNDEFINED);
11837         }
11838 
11839         /*
11840          * Process setcap request.
11841          */
11842         if (doset) {
11843                 /*
11844                  * At present, we can only set binary (0/1) values
11845                  */
11846                 switch (cidx) {
11847                 case SCSI_CAP_ARQ:
11848                         if (val == 0) {
11849                                 rval = FALSE;
11850                         } else {
11851                                 rval = TRUE;
11852                         }
11853                         break;
11854 
11855                 case SCSI_CAP_LUN_RESET:
11856                         if (val) {
11857                                 plun->lun_cap |= FCP_LUN_CAP_RESET;
11858                         } else {
11859                                 plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11860                         }
11861                         rval = TRUE;
11862                         break;
11863 
11864                 case SCSI_CAP_SECTOR_SIZE:
11865                         rval = TRUE;
11866                         break;
11867                 default:
11868                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11869                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11870                             "fcp_setcap: unsupported %d", cidx);
11871                         rval = UNDEFINED;
11872                         break;
11873                 }
11874 
11875                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11876                     fcp_trace, FCP_BUF_LEVEL_5, 0,
11877                     "set cap: cap=%s, val/tgtonly/doset/rval = "
11878                     "0x%x/0x%x/0x%x/%d",
11879                     cap, val, tgtonly, doset, rval);
11880 
11881         } else {
11882                 /*
11883                  * Process getcap request.
11884                  */
11885                 switch (cidx) {
11886                 case SCSI_CAP_DMA_MAX:
11887                         rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11888 
11889                         /*
11890                          * Need to make an adjustment qlc is uint_t 64
11891                          * st is int, so we will make the adjustment here
11892                          * being as nobody wants to touch this.
11893                          * It still leaves the max single block length
11894                          * of 2 gig. This should last .
11895                          */
11896 
11897                         if (rval == -1) {
11898                                 rval = MAX_INT_DMA;
11899                         }
11900 
11901                         break;
11902 
11903                 case SCSI_CAP_INITIATOR_ID:
11904                         rval = pptr->port_id;
11905                         break;
11906 
11907                 case SCSI_CAP_ARQ:
11908                 case SCSI_CAP_RESET_NOTIFICATION:
11909                 case SCSI_CAP_TAGGED_QING:
11910                         rval = TRUE;
11911                         break;
11912 
11913                 case SCSI_CAP_SCSI_VERSION:
11914                         rval = 3;
11915                         break;
11916 
11917                 case SCSI_CAP_INTERCONNECT_TYPE:
11918                         if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11919                             (ptgt->tgt_hard_addr == 0)) {
11920                                 rval = INTERCONNECT_FABRIC;
11921                         } else {
11922                                 rval = INTERCONNECT_FIBRE;
11923                         }
11924                         break;
11925 
11926                 case SCSI_CAP_LUN_RESET:
11927                         rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11928                             TRUE : FALSE;
11929                         break;
11930 
11931                 default:
11932                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11933                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11934                             "fcp_getcap: unsupported %d", cidx);
11935                         rval = UNDEFINED;
11936                         break;
11937                 }
11938 
11939                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11940                     fcp_trace, FCP_BUF_LEVEL_8, 0,
11941                     "get cap: cap=%s, val/tgtonly/doset/rval = "
11942                     "0x%x/0x%x/0x%x/%d",
11943                     cap, val, tgtonly, doset, rval);
11944         }
11945 
11946         return (rval);
11947 }
11948 
11949 /*
11950  * called by the transport to get the port-wwn and lun
11951  * properties of this device, and to create a "name" based on them
11952  *
11953  * these properties don't exist on sun4m
11954  *
11955  * return 1 for success else return 0
11956  */
11957 /* ARGSUSED */
11958 static int
11959 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11960 {
11961         int                     i;
11962         int                     *lun;
11963         int                     numChars;
11964         uint_t                  nlun;
11965         uint_t                  count;
11966         uint_t                  nbytes;
11967         uchar_t                 *bytes;
11968         uint16_t                lun_num;
11969         uint32_t                tgt_id;
11970         char                    **conf_wwn;
11971         char                    tbuf[(FC_WWN_SIZE << 1) + 1];
11972         uchar_t                 barray[FC_WWN_SIZE];
11973         dev_info_t              *tgt_dip;
11974         struct fcp_tgt  *ptgt;
11975         struct fcp_port *pptr;
11976         struct fcp_lun  *plun;
11977 
11978         ASSERT(sd != NULL);
11979         ASSERT(name != NULL);
11980 
11981         tgt_dip = sd->sd_dev;
11982         pptr = ddi_get_soft_state(fcp_softstate,
11983             ddi_get_instance(ddi_get_parent(tgt_dip)));
11984         if (pptr == NULL) {
11985                 return (0);
11986         }
11987 
11988         ASSERT(tgt_dip != NULL);
11989 
11990         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11991             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11992             LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11993                 name[0] = '\0';
11994                 return (0);
11995         }
11996 
11997         if (nlun == 0) {
11998                 ddi_prop_free(lun);
11999                 return (0);
12000         }
12001 
12002         lun_num = lun[0];
12003         ddi_prop_free(lun);
12004 
12005         /*
12006          * Lookup for .conf WWN property
12007          */
12008         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12009             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12010             &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12011                 ASSERT(count >= 1);
12012 
12013                 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12014                 ddi_prop_free(conf_wwn);
12015                 mutex_enter(&pptr->port_mutex);
12016                 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12017                         mutex_exit(&pptr->port_mutex);
12018                         return (0);
12019                 }
12020                 ptgt = plun->lun_tgt;
12021                 mutex_exit(&pptr->port_mutex);
12022 
12023                 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12024                     tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12025 
12026                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12027                     ptgt->tgt_hard_addr != 0) {
12028                         tgt_id = (uint32_t)fcp_alpa_to_switch[
12029                             ptgt->tgt_hard_addr];
12030                 } else {
12031                         tgt_id = ptgt->tgt_d_id;
12032                 }
12033 
12034                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12035                     TARGET_PROP, tgt_id);
12036         }
12037 
12038         /* get the our port-wwn property */
12039         bytes = NULL;
12040         if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12041             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12042             &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12043                 if (bytes != NULL) {
12044                         ddi_prop_free(bytes);
12045                 }
12046                 return (0);
12047         }
12048 
12049         for (i = 0; i < FC_WWN_SIZE; i++) {
12050                 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12051         }
12052 
12053         /* Stick in the address of the form "wWWN,LUN" */
12054         numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12055 
12056         ASSERT(numChars < len);
12057         if (numChars >= len) {
12058                 fcp_log(CE_WARN, pptr->port_dip,
12059                     "!fcp_scsi_get_name: "
12060                     "name parameter length too small, it needs to be %d",
12061                     numChars+1);
12062         }
12063 
12064         ddi_prop_free(bytes);
12065 
12066         return (1);
12067 }
12068 
12069 
12070 /*
12071  * called by the transport to get the SCSI target id value, returning
12072  * it in "name"
12073  *
12074  * this isn't needed/used on sun4m
12075  *
12076  * return 1 for success else return 0
12077  */
12078 /* ARGSUSED */
12079 static int
12080 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12081 {
12082         struct fcp_lun  *plun = ADDR2LUN(&sd->sd_address);
12083         struct fcp_tgt  *ptgt;
12084         int    numChars;
12085 
12086         if (plun == NULL) {
12087                 return (0);
12088         }
12089 
12090         if ((ptgt = plun->lun_tgt) == NULL) {
12091                 return (0);
12092         }
12093 
12094         numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12095 
12096         ASSERT(numChars < len);
12097         if (numChars >= len) {
12098                 fcp_log(CE_WARN, NULL,
12099                     "!fcp_scsi_get_bus_addr: "
12100                     "name parameter length too small, it needs to be %d",
12101                     numChars+1);
12102         }
12103 
12104         return (1);
12105 }
12106 
12107 
12108 /*
12109  * called internally to reset the link where the specified port lives
12110  */
12111 static int
12112 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12113 {
12114         la_wwn_t                wwn;
12115         struct fcp_lun  *plun;
12116         struct fcp_tgt  *ptgt;
12117 
12118         /* disable restart of lip if we're suspended */
12119         mutex_enter(&pptr->port_mutex);
12120 
12121         if (pptr->port_state & (FCP_STATE_SUSPENDED |
12122             FCP_STATE_POWER_DOWN)) {
12123                 mutex_exit(&pptr->port_mutex);
12124                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12125                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12126                     "fcp_linkreset, fcp%d: link reset "
12127                     "disabled due to DDI_SUSPEND",
12128                     ddi_get_instance(pptr->port_dip));
12129                 return (FC_FAILURE);
12130         }
12131 
12132         if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12133                 mutex_exit(&pptr->port_mutex);
12134                 return (FC_SUCCESS);
12135         }
12136 
12137         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12138             fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12139 
12140         /*
12141          * If ap == NULL assume local link reset.
12142          */
12143         if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12144                 plun = ADDR2LUN(ap);
12145                 ptgt = plun->lun_tgt;
12146                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12147         } else {
12148                 bzero((caddr_t)&wwn, sizeof (wwn));
12149         }
12150         mutex_exit(&pptr->port_mutex);
12151 
12152         return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12153 }
12154 
12155 
12156 /*
12157  * called from fcp_port_attach() to resume a port
12158  * return DDI_* success/failure status
12159  * acquires and releases the global mutex
12160  * acquires and releases the port mutex
12161  */
12162 /*ARGSUSED*/
12163 
12164 static int
12165 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12166     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12167 {
12168         int                     res = DDI_FAILURE; /* default result */
12169         struct fcp_port *pptr;          /* port state ptr */
12170         uint32_t                alloc_cnt;
12171         uint32_t                max_cnt;
12172         fc_portmap_t            *tmp_list = NULL;
12173 
12174         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12175             FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12176             instance);
12177 
12178         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12179                 cmn_err(CE_WARN, "fcp: bad soft state");
12180                 return (res);
12181         }
12182 
12183         mutex_enter(&pptr->port_mutex);
12184         switch (cmd) {
12185         case FC_CMD_RESUME:
12186                 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12187                 pptr->port_state &= ~FCP_STATE_SUSPENDED;
12188                 break;
12189 
12190         case FC_CMD_POWER_UP:
12191                 /*
12192                  * If the port is DDI_SUSPENded, defer rediscovery
12193                  * until DDI_RESUME occurs
12194                  */
12195                 if (pptr->port_state & FCP_STATE_SUSPENDED) {
12196                         pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12197                         mutex_exit(&pptr->port_mutex);
12198                         return (DDI_SUCCESS);
12199                 }
12200                 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12201         }
12202         pptr->port_id = s_id;
12203         pptr->port_state = FCP_STATE_INIT;
12204         mutex_exit(&pptr->port_mutex);
12205 
12206         /*
12207          * Make a copy of ulp_port_info as fctl allocates
12208          * a temp struct.
12209          */
12210         (void) fcp_cp_pinfo(pptr, pinfo);
12211 
12212         mutex_enter(&fcp_global_mutex);
12213         if (fcp_watchdog_init++ == 0) {
12214                 fcp_watchdog_tick = fcp_watchdog_timeout *
12215                     drv_usectohz(1000000);
12216                 fcp_watchdog_id = timeout(fcp_watch,
12217                     NULL, fcp_watchdog_tick);
12218         }
12219         mutex_exit(&fcp_global_mutex);
12220 
12221         /*
12222          * Handle various topologies and link states.
12223          */
12224         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12225         case FC_STATE_OFFLINE:
12226                 /*
12227                  * Wait for ONLINE, at which time a state
12228                  * change will cause a statec_callback
12229                  */
12230                 res = DDI_SUCCESS;
12231                 break;
12232 
12233         case FC_STATE_ONLINE:
12234 
12235                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
12236                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12237                         res = DDI_SUCCESS;
12238                         break;
12239                 }
12240 
12241                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12242                     !fcp_enable_auto_configuration) {
12243                         tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12244                         if (tmp_list == NULL) {
12245                                 if (!alloc_cnt) {
12246                                         res = DDI_SUCCESS;
12247                                 }
12248                                 break;
12249                         }
12250                         max_cnt = alloc_cnt;
12251                 } else {
12252                         ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12253 
12254                         alloc_cnt = FCP_MAX_DEVICES;
12255 
12256                         if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12257                             (sizeof (fc_portmap_t)) * alloc_cnt,
12258                             KM_NOSLEEP)) == NULL) {
12259                                 fcp_log(CE_WARN, pptr->port_dip,
12260                                     "!fcp%d: failed to allocate portmap",
12261                                     instance);
12262                                 break;
12263                         }
12264 
12265                         max_cnt = alloc_cnt;
12266                         if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12267                             &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12268                             FC_SUCCESS) {
12269                                 caddr_t msg;
12270 
12271                                 (void) fc_ulp_error(res, &msg);
12272 
12273                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12274                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12275                                     "resume failed getportmap: reason=0x%x",
12276                                     res);
12277 
12278                                 fcp_log(CE_WARN, pptr->port_dip,
12279                                     "!failed to get port map : %s", msg);
12280                                 break;
12281                         }
12282                         if (max_cnt > alloc_cnt) {
12283                                 alloc_cnt = max_cnt;
12284                         }
12285                 }
12286 
12287                 /*
12288                  * do the SCSI device discovery and create
12289                  * the devinfos
12290                  */
12291                 fcp_statec_callback(ulph, pptr->port_fp_handle,
12292                     pptr->port_phys_state, pptr->port_topology, tmp_list,
12293                     max_cnt, pptr->port_id);
12294 
12295                 res = DDI_SUCCESS;
12296                 break;
12297 
12298         default:
12299                 fcp_log(CE_WARN, pptr->port_dip,
12300                     "!fcp%d: invalid port state at attach=0x%x",
12301                     instance, pptr->port_phys_state);
12302 
12303                 mutex_enter(&pptr->port_mutex);
12304                 pptr->port_phys_state = FCP_STATE_OFFLINE;
12305                 mutex_exit(&pptr->port_mutex);
12306                 res = DDI_SUCCESS;
12307 
12308                 break;
12309         }
12310 
12311         if (tmp_list != NULL) {
12312                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12313         }
12314 
12315         return (res);
12316 }
12317 
12318 
12319 static void
12320 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12321 {
12322         pptr->port_fp_modlinkage = *pinfo->port_linkage;
12323         pptr->port_dip = pinfo->port_dip;
12324         pptr->port_fp_handle = pinfo->port_handle;
12325         if (pinfo->port_acc_attr != NULL) {
12326                 /*
12327                  * FCA supports DMA
12328                  */
12329                 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12330                 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12331                 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12332                 pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12333         }
12334         pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12335         pptr->port_max_exch = pinfo->port_fca_max_exch;
12336         pptr->port_phys_state = pinfo->port_state;
12337         pptr->port_topology = pinfo->port_flags;
12338         pptr->port_reset_action = pinfo->port_reset_action;
12339         pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12340         pptr->port_fcp_dma = pinfo->port_fcp_dma;
12341         bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12342         bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12343 
12344         /* Clear FMA caps to avoid fm-capability ereport */
12345         if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12346                 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12347         if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12348                 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12349         if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12350                 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12351 }
12352 
12353 /*
12354  * If the elements wait field is set to 1 then
12355  * another thread is waiting for the operation to complete. Once
12356  * it is complete, the waiting thread is signaled and the element is
12357  * freed by the waiting thread. If the elements wait field is set to 0
12358  * the element is freed.
12359  */
12360 static void
12361 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12362 {
12363         ASSERT(elem != NULL);
12364         mutex_enter(&elem->mutex);
12365         elem->result = result;
12366         if (elem->wait) {
12367                 elem->wait = 0;
12368                 cv_signal(&elem->cv);
12369                 mutex_exit(&elem->mutex);
12370         } else {
12371                 mutex_exit(&elem->mutex);
12372                 cv_destroy(&elem->cv);
12373                 mutex_destroy(&elem->mutex);
12374                 kmem_free(elem, sizeof (struct fcp_hp_elem));
12375         }
12376 }
12377 
12378 /*
12379  * This function is invoked from the taskq thread to allocate
12380  * devinfo nodes and to online/offline them.
12381  */
12382 static void
12383 fcp_hp_task(void *arg)
12384 {
12385         struct fcp_hp_elem      *elem = (struct fcp_hp_elem *)arg;
12386         struct fcp_lun  *plun = elem->lun;
12387         struct fcp_port         *pptr = elem->port;
12388         int                     result;
12389 
12390         ASSERT(elem->what == FCP_ONLINE ||
12391             elem->what == FCP_OFFLINE ||
12392             elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12393             elem->what == FCP_MPXIO_PATH_SET_BUSY);
12394 
12395         mutex_enter(&pptr->port_mutex);
12396         mutex_enter(&plun->lun_mutex);
12397         if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12398             plun->lun_event_count != elem->event_cnt) ||
12399             pptr->port_state & (FCP_STATE_SUSPENDED |
12400             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12401                 mutex_exit(&plun->lun_mutex);
12402                 mutex_exit(&pptr->port_mutex);
12403                 fcp_process_elem(elem, NDI_FAILURE);
12404                 return;
12405         }
12406         mutex_exit(&plun->lun_mutex);
12407         mutex_exit(&pptr->port_mutex);
12408 
12409         result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12410             elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12411         fcp_process_elem(elem, result);
12412 }
12413 
12414 
12415 static child_info_t *
12416 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12417     int tcount)
12418 {
12419         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12420 
12421         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12422                 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12423 
12424                 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12425                 /*
12426                  * Child has not been created yet. Create the child device
12427                  * based on the per-Lun flags.
12428                  */
12429                 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12430                         plun->lun_cip =
12431                             CIP(fcp_create_dip(plun, lcount, tcount));
12432                         plun->lun_mpxio = 0;
12433                 } else {
12434                         plun->lun_cip =
12435                             CIP(fcp_create_pip(plun, lcount, tcount));
12436                         plun->lun_mpxio = 1;
12437                 }
12438         } else {
12439                 plun->lun_cip = cip;
12440         }
12441 
12442         return (plun->lun_cip);
12443 }
12444 
12445 
12446 static int
12447 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12448 {
12449         int             rval = FC_FAILURE;
12450         dev_info_t      *pdip;
12451         struct dev_info *dip;
12452         int             circular;
12453 
12454         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12455 
12456         pdip = plun->lun_tgt->tgt_port->port_dip;
12457 
12458         if (plun->lun_cip == NULL) {
12459                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12460                     fcp_trace, FCP_BUF_LEVEL_3, 0,
12461                     "fcp_is_dip_present: plun->lun_cip is NULL: "
12462                     "plun: %p lun state: %x num: %d target state: %x",
12463                     plun, plun->lun_state, plun->lun_num,
12464                     plun->lun_tgt->tgt_port->port_state);
12465                 return (rval);
12466         }
12467         ndi_devi_enter(pdip, &circular);
12468         dip = DEVI(pdip)->devi_child;
12469         while (dip) {
12470                 if (dip == DEVI(cdip)) {
12471                         rval = FC_SUCCESS;
12472                         break;
12473                 }
12474                 dip = dip->devi_sibling;
12475         }
12476         ndi_devi_exit(pdip, circular);
12477         return (rval);
12478 }
12479 
12480 static int
12481 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12482 {
12483         int             rval = FC_FAILURE;
12484 
12485         ASSERT(plun != NULL);
12486         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12487 
12488         if (plun->lun_mpxio == 0) {
12489                 rval = fcp_is_dip_present(plun, DIP(cip));
12490         } else {
12491                 rval = fcp_is_pip_present(plun, PIP(cip));
12492         }
12493 
12494         return (rval);
12495 }
12496 
12497 /*
12498  *     Function: fcp_create_dip
12499  *
12500  *  Description: Creates a dev_info_t structure for the LUN specified by the
12501  *               caller.
12502  *
12503  *     Argument: plun           Lun structure
12504  *               link_cnt       Link state count.
12505  *               tgt_cnt        Target state change count.
12506  *
12507  * Return Value: NULL if it failed
12508  *               dev_info_t structure address if it succeeded
12509  *
12510  *      Context: Kernel context
12511  */
12512 static dev_info_t *
12513 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12514 {
12515         int                     failure = 0;
12516         uint32_t                tgt_id;
12517         uint64_t                sam_lun;
12518         struct fcp_tgt  *ptgt = plun->lun_tgt;
12519         struct fcp_port *pptr = ptgt->tgt_port;
12520         dev_info_t              *pdip = pptr->port_dip;
12521         dev_info_t              *cdip = NULL;
12522         dev_info_t              *old_dip = DIP(plun->lun_cip);
12523         char                    *nname = NULL;
12524         char                    **compatible = NULL;
12525         int                     ncompatible;
12526         char                    *scsi_binding_set;
12527         char                    t_pwwn[17];
12528 
12529         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12530         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12531 
12532         /* get the 'scsi-binding-set' property */
12533         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12534             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12535             &scsi_binding_set) != DDI_PROP_SUCCESS) {
12536                 scsi_binding_set = NULL;
12537         }
12538 
12539         /* determine the node name and compatible */
12540         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12541             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12542         if (scsi_binding_set) {
12543                 ddi_prop_free(scsi_binding_set);
12544         }
12545 
12546         if (nname == NULL) {
12547 #ifdef  DEBUG
12548                 cmn_err(CE_WARN, "%s%d: no driver for "
12549                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12550                     "    compatible: %s",
12551                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12552                     ptgt->tgt_port_wwn.raw_wwn[0],
12553                     ptgt->tgt_port_wwn.raw_wwn[1],
12554                     ptgt->tgt_port_wwn.raw_wwn[2],
12555                     ptgt->tgt_port_wwn.raw_wwn[3],
12556                     ptgt->tgt_port_wwn.raw_wwn[4],
12557                     ptgt->tgt_port_wwn.raw_wwn[5],
12558                     ptgt->tgt_port_wwn.raw_wwn[6],
12559                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12560                     *compatible);
12561 #endif  /* DEBUG */
12562                 failure++;
12563                 goto end_of_fcp_create_dip;
12564         }
12565 
12566         cdip = fcp_find_existing_dip(plun, pdip, nname);
12567 
12568         /*
12569          * if the old_dip does not match the cdip, that means there is
12570          * some property change. since we'll be using the cdip, we need
12571          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12572          * then the dtype for the device has been updated. Offline the
12573          * the old device and create a new device with the new device type
12574          * Refer to bug: 4764752
12575          */
12576         if (old_dip && (cdip != old_dip ||
12577             plun->lun_state & FCP_LUN_CHANGED)) {
12578                 plun->lun_state &= ~(FCP_LUN_INIT);
12579                 mutex_exit(&plun->lun_mutex);
12580                 mutex_exit(&pptr->port_mutex);
12581 
12582                 mutex_enter(&ptgt->tgt_mutex);
12583                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12584                     link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12585                 mutex_exit(&ptgt->tgt_mutex);
12586 
12587 #ifdef DEBUG
12588                 if (cdip != NULL) {
12589                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12590                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12591                             "Old dip=%p; New dip=%p don't match", old_dip,
12592                             cdip);
12593                 } else {
12594                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12595                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12596                             "Old dip=%p; New dip=NULL don't match", old_dip);
12597                 }
12598 #endif
12599 
12600                 mutex_enter(&pptr->port_mutex);
12601                 mutex_enter(&plun->lun_mutex);
12602         }
12603 
12604         if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12605                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12606                 if (ndi_devi_alloc(pptr->port_dip, nname,
12607                     DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12608                         failure++;
12609                         goto end_of_fcp_create_dip;
12610                 }
12611         }
12612 
12613         /*
12614          * Previously all the properties for the devinfo were destroyed here
12615          * with a call to ndi_prop_remove_all(). Since this may cause loss of
12616          * the devid property (and other properties established by the target
12617          * driver or framework) which the code does not always recreate, this
12618          * call was removed.
12619          * This opens a theoretical possibility that we may return with a
12620          * stale devid on the node if the scsi entity behind the fibre channel
12621          * lun has changed.
12622          */
12623 
12624         /* decorate the node with compatible */
12625         if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12626             "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12627                 failure++;
12628                 goto end_of_fcp_create_dip;
12629         }
12630 
12631         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12632             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12633                 failure++;
12634                 goto end_of_fcp_create_dip;
12635         }
12636 
12637         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12638             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12639                 failure++;
12640                 goto end_of_fcp_create_dip;
12641         }
12642 
12643         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12644         t_pwwn[16] = '\0';
12645         if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12646             != DDI_PROP_SUCCESS) {
12647                 failure++;
12648                 goto end_of_fcp_create_dip;
12649         }
12650 
12651         /*
12652          * If there is no hard address - We might have to deal with
12653          * that by using WWN - Having said that it is important to
12654          * recognize this problem early so ssd can be informed of
12655          * the right interconnect type.
12656          */
12657         if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12658                 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12659         } else {
12660                 tgt_id = ptgt->tgt_d_id;
12661         }
12662 
12663         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12664             tgt_id) != DDI_PROP_SUCCESS) {
12665                 failure++;
12666                 goto end_of_fcp_create_dip;
12667         }
12668 
12669         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12670             (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12671                 failure++;
12672                 goto end_of_fcp_create_dip;
12673         }
12674         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12675         if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12676             sam_lun) != DDI_PROP_SUCCESS) {
12677                 failure++;
12678                 goto end_of_fcp_create_dip;
12679         }
12680 
12681 end_of_fcp_create_dip:
12682         scsi_hba_nodename_compatible_free(nname, compatible);
12683 
12684         if (cdip != NULL && failure) {
12685                 (void) ndi_prop_remove_all(cdip);
12686                 (void) ndi_devi_free(cdip);
12687                 cdip = NULL;
12688         }
12689 
12690         return (cdip);
12691 }
12692 
12693 /*
12694  *     Function: fcp_create_pip
12695  *
12696  *  Description: Creates a Path Id for the LUN specified by the caller.
12697  *
12698  *     Argument: plun           Lun structure
12699  *               link_cnt       Link state count.
12700  *               tgt_cnt        Target state count.
12701  *
12702  * Return Value: NULL if it failed
12703  *               mdi_pathinfo_t structure address if it succeeded
12704  *
12705  *      Context: Kernel context
12706  */
12707 static mdi_pathinfo_t *
12708 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12709 {
12710         int                     i;
12711         char                    buf[MAXNAMELEN];
12712         char                    uaddr[MAXNAMELEN];
12713         int                     failure = 0;
12714         uint32_t                tgt_id;
12715         uint64_t                sam_lun;
12716         struct fcp_tgt  *ptgt = plun->lun_tgt;
12717         struct fcp_port *pptr = ptgt->tgt_port;
12718         dev_info_t              *pdip = pptr->port_dip;
12719         mdi_pathinfo_t          *pip = NULL;
12720         mdi_pathinfo_t          *old_pip = PIP(plun->lun_cip);
12721         char                    *nname = NULL;
12722         char                    **compatible = NULL;
12723         int                     ncompatible;
12724         char                    *scsi_binding_set;
12725         char                    t_pwwn[17];
12726 
12727         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12728         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12729 
12730         scsi_binding_set = "vhci";
12731 
12732         /* determine the node name and compatible */
12733         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12734             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12735 
12736         if (nname == NULL) {
12737 #ifdef  DEBUG
12738                 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12739                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12740                     "    compatible: %s",
12741                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12742                     ptgt->tgt_port_wwn.raw_wwn[0],
12743                     ptgt->tgt_port_wwn.raw_wwn[1],
12744                     ptgt->tgt_port_wwn.raw_wwn[2],
12745                     ptgt->tgt_port_wwn.raw_wwn[3],
12746                     ptgt->tgt_port_wwn.raw_wwn[4],
12747                     ptgt->tgt_port_wwn.raw_wwn[5],
12748                     ptgt->tgt_port_wwn.raw_wwn[6],
12749                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12750                     *compatible);
12751 #endif  /* DEBUG */
12752                 failure++;
12753                 goto end_of_fcp_create_pip;
12754         }
12755 
12756         pip = fcp_find_existing_pip(plun, pdip);
12757 
12758         /*
12759          * if the old_dip does not match the cdip, that means there is
12760          * some property change. since we'll be using the cdip, we need
12761          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12762          * then the dtype for the device has been updated. Offline the
12763          * the old device and create a new device with the new device type
12764          * Refer to bug: 4764752
12765          */
12766         if (old_pip && (pip != old_pip ||
12767             plun->lun_state & FCP_LUN_CHANGED)) {
12768                 plun->lun_state &= ~(FCP_LUN_INIT);
12769                 mutex_exit(&plun->lun_mutex);
12770                 mutex_exit(&pptr->port_mutex);
12771 
12772                 mutex_enter(&ptgt->tgt_mutex);
12773                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12774                     FCP_OFFLINE, lcount, tcount,
12775                     NDI_DEVI_REMOVE, 0);
12776                 mutex_exit(&ptgt->tgt_mutex);
12777 
12778                 if (pip != NULL) {
12779                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12780                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12781                             "Old pip=%p; New pip=%p don't match",
12782                             old_pip, pip);
12783                 } else {
12784                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12785                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12786                             "Old pip=%p; New pip=NULL don't match",
12787                             old_pip);
12788                 }
12789 
12790                 mutex_enter(&pptr->port_mutex);
12791                 mutex_enter(&plun->lun_mutex);
12792         }
12793 
12794         /*
12795          * Since FC_WWN_SIZE is 8 bytes and its not like the
12796          * lun_guid_size which is dependent on the target, I don't
12797          * believe the same trancation happens here UNLESS the standards
12798          * change the FC_WWN_SIZE value to something larger than
12799          * MAXNAMELEN(currently 255 bytes).
12800          */
12801 
12802         for (i = 0; i < FC_WWN_SIZE; i++) {
12803                 (void) sprintf(&buf[i << 1], "%02x",
12804                     ptgt->tgt_port_wwn.raw_wwn[i]);
12805         }
12806 
12807         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12808             buf, plun->lun_num);
12809 
12810         if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12811                 /*
12812                  * Release the locks before calling into
12813                  * mdi_pi_alloc_compatible() since this can result in a
12814                  * callback into fcp which can result in a deadlock
12815                  * (see bug # 4870272).
12816                  *
12817                  * Basically, what we are trying to avoid is the scenario where
12818                  * one thread does ndi_devi_enter() and tries to grab
12819                  * fcp_mutex and another does it the other way round.
12820                  *
12821                  * But before we do that, make sure that nobody releases the
12822                  * port in the meantime. We can do this by setting a flag.
12823                  */
12824                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12825                 pptr->port_state |= FCP_STATE_IN_MDI;
12826                 mutex_exit(&plun->lun_mutex);
12827                 mutex_exit(&pptr->port_mutex);
12828                 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12829                     uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12830                         fcp_log(CE_WARN, pptr->port_dip,
12831                             "!path alloc failed:0x%x", plun);
12832                         mutex_enter(&pptr->port_mutex);
12833                         mutex_enter(&plun->lun_mutex);
12834                         pptr->port_state &= ~FCP_STATE_IN_MDI;
12835                         failure++;
12836                         goto end_of_fcp_create_pip;
12837                 }
12838                 mutex_enter(&pptr->port_mutex);
12839                 mutex_enter(&plun->lun_mutex);
12840                 pptr->port_state &= ~FCP_STATE_IN_MDI;
12841         } else {
12842                 (void) mdi_prop_remove(pip, NULL);
12843         }
12844 
12845         mdi_pi_set_phci_private(pip, (caddr_t)plun);
12846 
12847         if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12848             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12849             != DDI_PROP_SUCCESS) {
12850                 failure++;
12851                 goto end_of_fcp_create_pip;
12852         }
12853 
12854         if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12855             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12856             != DDI_PROP_SUCCESS) {
12857                 failure++;
12858                 goto end_of_fcp_create_pip;
12859         }
12860 
12861         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12862         t_pwwn[16] = '\0';
12863         if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12864             != DDI_PROP_SUCCESS) {
12865                 failure++;
12866                 goto end_of_fcp_create_pip;
12867         }
12868 
12869         /*
12870          * If there is no hard address - We might have to deal with
12871          * that by using WWN - Having said that it is important to
12872          * recognize this problem early so ssd can be informed of
12873          * the right interconnect type.
12874          */
12875         if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12876             ptgt->tgt_hard_addr != 0) {
12877                 tgt_id = (uint32_t)
12878                     fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12879         } else {
12880                 tgt_id = ptgt->tgt_d_id;
12881         }
12882 
12883         if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12884             != DDI_PROP_SUCCESS) {
12885                 failure++;
12886                 goto end_of_fcp_create_pip;
12887         }
12888 
12889         if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12890             != DDI_PROP_SUCCESS) {
12891                 failure++;
12892                 goto end_of_fcp_create_pip;
12893         }
12894         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12895         if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12896             != DDI_PROP_SUCCESS) {
12897                 failure++;
12898                 goto end_of_fcp_create_pip;
12899         }
12900 
12901 end_of_fcp_create_pip:
12902         scsi_hba_nodename_compatible_free(nname, compatible);
12903 
12904         if (pip != NULL && failure) {
12905                 (void) mdi_prop_remove(pip, NULL);
12906                 mutex_exit(&plun->lun_mutex);
12907                 mutex_exit(&pptr->port_mutex);
12908                 (void) mdi_pi_free(pip, 0);
12909                 mutex_enter(&pptr->port_mutex);
12910                 mutex_enter(&plun->lun_mutex);
12911                 pip = NULL;
12912         }
12913 
12914         return (pip);
12915 }
12916 
12917 static dev_info_t *
12918 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12919 {
12920         uint_t                  nbytes;
12921         uchar_t                 *bytes;
12922         uint_t                  nwords;
12923         uint32_t                tgt_id;
12924         int                     *words;
12925         dev_info_t              *cdip;
12926         dev_info_t              *ndip;
12927         struct fcp_tgt  *ptgt = plun->lun_tgt;
12928         struct fcp_port *pptr = ptgt->tgt_port;
12929         int                     circular;
12930 
12931         ndi_devi_enter(pdip, &circular);
12932 
12933         ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12934         while ((cdip = ndip) != NULL) {
12935                 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12936 
12937                 if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12938                         continue;
12939                 }
12940 
12941                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12942                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12943                     &nbytes) != DDI_PROP_SUCCESS) {
12944                         continue;
12945                 }
12946 
12947                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12948                         if (bytes != NULL) {
12949                                 ddi_prop_free(bytes);
12950                         }
12951                         continue;
12952                 }
12953                 ASSERT(bytes != NULL);
12954 
12955                 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12956                         ddi_prop_free(bytes);
12957                         continue;
12958                 }
12959 
12960                 ddi_prop_free(bytes);
12961 
12962                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12963                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12964                     &nbytes) != DDI_PROP_SUCCESS) {
12965                         continue;
12966                 }
12967 
12968                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12969                         if (bytes != NULL) {
12970                                 ddi_prop_free(bytes);
12971                         }
12972                         continue;
12973                 }
12974                 ASSERT(bytes != NULL);
12975 
12976                 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12977                         ddi_prop_free(bytes);
12978                         continue;
12979                 }
12980 
12981                 ddi_prop_free(bytes);
12982 
12983                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12984                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12985                     &nwords) != DDI_PROP_SUCCESS) {
12986                         continue;
12987                 }
12988 
12989                 if (nwords != 1 || words == NULL) {
12990                         if (words != NULL) {
12991                                 ddi_prop_free(words);
12992                         }
12993                         continue;
12994                 }
12995                 ASSERT(words != NULL);
12996 
12997                 /*
12998                  * If there is no hard address - We might have to deal with
12999                  * that by using WWN - Having said that it is important to
13000                  * recognize this problem early so ssd can be informed of
13001                  * the right interconnect type.
13002                  */
13003                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13004                     ptgt->tgt_hard_addr != 0) {
13005                         tgt_id =
13006                             (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13007                 } else {
13008                         tgt_id = ptgt->tgt_d_id;
13009                 }
13010 
13011                 if (tgt_id != (uint32_t)*words) {
13012                         ddi_prop_free(words);
13013                         continue;
13014                 }
13015                 ddi_prop_free(words);
13016 
13017                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13018                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13019                     &nwords) != DDI_PROP_SUCCESS) {
13020                         continue;
13021                 }
13022 
13023                 if (nwords != 1 || words == NULL) {
13024                         if (words != NULL) {
13025                                 ddi_prop_free(words);
13026                         }
13027                         continue;
13028                 }
13029                 ASSERT(words != NULL);
13030 
13031                 if (plun->lun_num == (uint16_t)*words) {
13032                         ddi_prop_free(words);
13033                         break;
13034                 }
13035                 ddi_prop_free(words);
13036         }
13037         ndi_devi_exit(pdip, circular);
13038 
13039         return (cdip);
13040 }
13041 
13042 
13043 static int
13044 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13045 {
13046         dev_info_t      *pdip;
13047         char            buf[MAXNAMELEN];
13048         char            uaddr[MAXNAMELEN];
13049         int             rval = FC_FAILURE;
13050 
13051         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13052 
13053         pdip = plun->lun_tgt->tgt_port->port_dip;
13054 
13055         /*
13056          * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13057          * non-NULL even when the LUN is not there as in the case when a LUN is
13058          * configured and then deleted on the device end (for T3/T4 case). In
13059          * such cases, pip will be NULL.
13060          *
13061          * If the device generates an RSCN, it will end up getting offlined when
13062          * it disappeared and a new LUN will get created when it is rediscovered
13063          * on the device. If we check for lun_cip here, the LUN will not end
13064          * up getting onlined since this function will end up returning a
13065          * FC_SUCCESS.
13066          *
13067          * The behavior is different on other devices. For instance, on a HDS,
13068          * there was no RSCN generated by the device but the next I/O generated
13069          * a check condition and rediscovery got triggered that way. So, in
13070          * such cases, this path will not be exercised
13071          */
13072         if (pip == NULL) {
13073                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13074                     fcp_trace, FCP_BUF_LEVEL_4, 0,
13075                     "fcp_is_pip_present: plun->lun_cip is NULL: "
13076                     "plun: %p lun state: %x num: %d target state: %x",
13077                     plun, plun->lun_state, plun->lun_num,
13078                     plun->lun_tgt->tgt_port->port_state);
13079                 return (rval);
13080         }
13081 
13082         fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13083 
13084         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13085 
13086         if (plun->lun_old_guid) {
13087                 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13088                         rval = FC_SUCCESS;
13089                 }
13090         } else {
13091                 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13092                         rval = FC_SUCCESS;
13093                 }
13094         }
13095         return (rval);
13096 }
13097 
13098 static mdi_pathinfo_t *
13099 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13100 {
13101         char                    buf[MAXNAMELEN];
13102         char                    uaddr[MAXNAMELEN];
13103         mdi_pathinfo_t          *pip;
13104         struct fcp_tgt  *ptgt = plun->lun_tgt;
13105         struct fcp_port *pptr = ptgt->tgt_port;
13106 
13107         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13108 
13109         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13110         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13111 
13112         pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13113 
13114         return (pip);
13115 }
13116 
13117 
13118 static int
13119 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13120     int tcount, int flags, int *circ)
13121 {
13122         int                     rval;
13123         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
13124         struct fcp_tgt  *ptgt = plun->lun_tgt;
13125         dev_info_t              *cdip = NULL;
13126 
13127         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13128         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13129 
13130         if (plun->lun_cip == NULL) {
13131                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13132                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13133                     "fcp_online_child: plun->lun_cip is NULL: "
13134                     "plun: %p state: %x num: %d target state: %x",
13135                     plun, plun->lun_state, plun->lun_num,
13136                     plun->lun_tgt->tgt_port->port_state);
13137                 return (NDI_FAILURE);
13138         }
13139 again:
13140         if (plun->lun_mpxio == 0) {
13141                 cdip = DIP(cip);
13142                 mutex_exit(&plun->lun_mutex);
13143                 mutex_exit(&pptr->port_mutex);
13144 
13145                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13146                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13147                     "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13148                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13149 
13150                 /*
13151                  * We could check for FCP_LUN_INIT here but chances
13152                  * of getting here when it's already in FCP_LUN_INIT
13153                  * is rare and a duplicate ndi_devi_online wouldn't
13154                  * hurt either (as the node would already have been
13155                  * in CF2)
13156                  */
13157                 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13158                         rval = ndi_devi_bind_driver(cdip, flags);
13159                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13160                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13161                             "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13162                 } else {
13163                         rval = ndi_devi_online(cdip, flags);
13164                 }
13165 
13166                 /*
13167                  * We log the message into trace buffer if the device
13168                  * is "ses" and into syslog for any other device
13169                  * type. This is to prevent the ndi_devi_online failure
13170                  * message that appears for V880/A5K ses devices.
13171                  */
13172                 if (rval == NDI_SUCCESS) {
13173                         mutex_enter(&ptgt->tgt_mutex);
13174                         plun->lun_state |= FCP_LUN_INIT;
13175                         mutex_exit(&ptgt->tgt_mutex);
13176                 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13177                         fcp_log(CE_NOTE, pptr->port_dip,
13178                             "!ndi_devi_online:"
13179                             " failed for %s: target=%x lun=%x %x",
13180                             ddi_get_name(cdip), ptgt->tgt_d_id,
13181                             plun->lun_num, rval);
13182                 } else {
13183                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13184                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13185                             " !ndi_devi_online:"
13186                             " failed for %s: target=%x lun=%x %x",
13187                             ddi_get_name(cdip), ptgt->tgt_d_id,
13188                             plun->lun_num, rval);
13189                 }
13190         } else {
13191                 cdip = mdi_pi_get_client(PIP(cip));
13192                 mutex_exit(&plun->lun_mutex);
13193                 mutex_exit(&pptr->port_mutex);
13194 
13195                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13196                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13197                     "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13198                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13199 
13200                 /*
13201                  * Hold path and exit phci to avoid deadlock with power
13202                  * management code during mdi_pi_online.
13203                  */
13204                 mdi_hold_path(PIP(cip));
13205                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13206 
13207                 rval = mdi_pi_online(PIP(cip), flags);
13208 
13209                 mdi_devi_enter_phci(pptr->port_dip, circ);
13210                 mdi_rele_path(PIP(cip));
13211 
13212                 if (rval == MDI_SUCCESS) {
13213                         mutex_enter(&ptgt->tgt_mutex);
13214                         plun->lun_state |= FCP_LUN_INIT;
13215                         mutex_exit(&ptgt->tgt_mutex);
13216 
13217                         /*
13218                          * Clear MPxIO path permanent disable in case
13219                          * fcp hotplug dropped the offline event.
13220                          */
13221                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13222 
13223                 } else if (rval == MDI_NOT_SUPPORTED) {
13224                         child_info_t    *old_cip = cip;
13225 
13226                         /*
13227                          * MPxIO does not support this device yet.
13228                          * Enumerate in legacy mode.
13229                          */
13230                         mutex_enter(&pptr->port_mutex);
13231                         mutex_enter(&plun->lun_mutex);
13232                         plun->lun_mpxio = 0;
13233                         plun->lun_cip = NULL;
13234                         cdip = fcp_create_dip(plun, lcount, tcount);
13235                         plun->lun_cip = cip = CIP(cdip);
13236                         if (cip == NULL) {
13237                                 fcp_log(CE_WARN, pptr->port_dip,
13238                                     "!fcp_online_child: "
13239                                     "Create devinfo failed for LU=%p", plun);
13240                                 mutex_exit(&plun->lun_mutex);
13241 
13242                                 mutex_enter(&ptgt->tgt_mutex);
13243                                 plun->lun_state |= FCP_LUN_OFFLINE;
13244                                 mutex_exit(&ptgt->tgt_mutex);
13245 
13246                                 mutex_exit(&pptr->port_mutex);
13247 
13248                                 /*
13249                                  * free the mdi_pathinfo node
13250                                  */
13251                                 (void) mdi_pi_free(PIP(old_cip), 0);
13252                         } else {
13253                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13254                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13255                                     "fcp_online_child: creating devinfo "
13256                                     "node 0x%p for plun 0x%p",
13257                                     cip, plun);
13258                                 mutex_exit(&plun->lun_mutex);
13259                                 mutex_exit(&pptr->port_mutex);
13260                                 /*
13261                                  * free the mdi_pathinfo node
13262                                  */
13263                                 (void) mdi_pi_free(PIP(old_cip), 0);
13264                                 mutex_enter(&pptr->port_mutex);
13265                                 mutex_enter(&plun->lun_mutex);
13266                                 goto again;
13267                         }
13268                 } else {
13269                         if (cdip) {
13270                                 fcp_log(CE_NOTE, pptr->port_dip,
13271                                     "!fcp_online_child: mdi_pi_online:"
13272                                     " failed for %s: target=%x lun=%x %x",
13273                                     ddi_get_name(cdip), ptgt->tgt_d_id,
13274                                     plun->lun_num, rval);
13275                         }
13276                 }
13277                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13278         }
13279 
13280         if (rval == NDI_SUCCESS) {
13281                 if (cdip) {
13282                         (void) ndi_event_retrieve_cookie(
13283                             pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13284                             &fcp_insert_eid, NDI_EVENT_NOPASS);
13285                         (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13286                             cdip, fcp_insert_eid, NULL);
13287                 }
13288         }
13289         mutex_enter(&pptr->port_mutex);
13290         mutex_enter(&plun->lun_mutex);
13291         return (rval);
13292 }
13293 
13294 /* ARGSUSED */
13295 static int
13296 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13297     int tcount, int flags, int *circ)
13298 {
13299         int             rval;
13300         int             lun_mpxio;
13301         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13302         struct fcp_tgt  *ptgt = plun->lun_tgt;
13303         dev_info_t      *cdip;
13304 
13305         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13306         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13307 
13308         if (plun->lun_cip == NULL) {
13309                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13310                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13311                     "fcp_offline_child: plun->lun_cip is NULL: "
13312                     "plun: %p lun state: %x num: %d target state: %x",
13313                     plun, plun->lun_state, plun->lun_num,
13314                     plun->lun_tgt->tgt_port->port_state);
13315                 return (NDI_FAILURE);
13316         }
13317 
13318         /*
13319          * We will use this value twice. Make a copy to be sure we use
13320          * the same value in both places.
13321          */
13322         lun_mpxio = plun->lun_mpxio;
13323 
13324         if (lun_mpxio == 0) {
13325                 cdip = DIP(cip);
13326                 mutex_exit(&plun->lun_mutex);
13327                 mutex_exit(&pptr->port_mutex);
13328                 rval = ndi_devi_offline(DIP(cip), flags);
13329                 if (rval != NDI_SUCCESS) {
13330                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13331                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13332                             "fcp_offline_child: ndi_devi_offline failed "
13333                             "rval=%x cip=%p", rval, cip);
13334                 }
13335         } else {
13336                 cdip = mdi_pi_get_client(PIP(cip));
13337                 mutex_exit(&plun->lun_mutex);
13338                 mutex_exit(&pptr->port_mutex);
13339 
13340                 /*
13341                  * Exit phci to avoid deadlock with power management code
13342                  * during mdi_pi_offline
13343                  */
13344                 mdi_hold_path(PIP(cip));
13345                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13346 
13347                 rval = mdi_pi_offline(PIP(cip), flags);
13348 
13349                 mdi_devi_enter_phci(pptr->port_dip, circ);
13350                 mdi_rele_path(PIP(cip));
13351 
13352                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13353         }
13354 
13355         mutex_enter(&ptgt->tgt_mutex);
13356         plun->lun_state &= ~FCP_LUN_INIT;
13357         mutex_exit(&ptgt->tgt_mutex);
13358 
13359         if (rval == NDI_SUCCESS) {
13360                 cdip = NULL;
13361                 if (flags & NDI_DEVI_REMOVE) {
13362                         mutex_enter(&plun->lun_mutex);
13363                         /*
13364                          * If the guid of the LUN changes, lun_cip will not
13365                          * equal to cip, and after offlining the LUN with the
13366                          * old guid, we should keep lun_cip since it's the cip
13367                          * of the LUN with the new guid.
13368                          * Otherwise remove our reference to child node.
13369                          *
13370                          * This must be done before the child node is freed,
13371                          * otherwise other threads could see a stale lun_cip
13372                          * pointer.
13373                          */
13374                         if (plun->lun_cip == cip) {
13375                                 plun->lun_cip = NULL;
13376                         }
13377                         if (plun->lun_old_guid) {
13378                                 kmem_free(plun->lun_old_guid,
13379                                     plun->lun_old_guid_size);
13380                                 plun->lun_old_guid = NULL;
13381                                 plun->lun_old_guid_size = 0;
13382                         }
13383                         mutex_exit(&plun->lun_mutex);
13384                 }
13385         }
13386 
13387         if (lun_mpxio != 0) {
13388                 if (rval == NDI_SUCCESS) {
13389                         /*
13390                          * Clear MPxIO path permanent disable as the path is
13391                          * already offlined.
13392                          */
13393                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13394 
13395                         if (flags & NDI_DEVI_REMOVE) {
13396                                 (void) mdi_pi_free(PIP(cip), 0);
13397                         }
13398                 } else {
13399                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13400                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13401                             "fcp_offline_child: mdi_pi_offline failed "
13402                             "rval=%x cip=%p", rval, cip);
13403                 }
13404         }
13405 
13406         mutex_enter(&pptr->port_mutex);
13407         mutex_enter(&plun->lun_mutex);
13408 
13409         if (cdip) {
13410                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13411                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13412                     " target=%x lun=%x", "ndi_offline",
13413                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13414         }
13415 
13416         return (rval);
13417 }
13418 
13419 static void
13420 fcp_remove_child(struct fcp_lun *plun)
13421 {
13422         child_info_t *cip;
13423         int circ;
13424 
13425         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13426 
13427         if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13428                 if (plun->lun_mpxio == 0) {
13429                         (void) ndi_prop_remove_all(DIP(plun->lun_cip));
13430                         (void) ndi_devi_free(DIP(plun->lun_cip));
13431                         plun->lun_cip = NULL;
13432                 } else {
13433                         /*
13434                          * Clear reference to the child node in the lun.
13435                          * This must be done before freeing it with mdi_pi_free
13436                          * and with lun_mutex held so that other threads always
13437                          * see either valid lun_cip or NULL when holding
13438                          * lun_mutex. We keep a copy in cip.
13439                          */
13440                         cip = plun->lun_cip;
13441                         plun->lun_cip = NULL;
13442 
13443                         mutex_exit(&plun->lun_mutex);
13444                         mutex_exit(&plun->lun_tgt->tgt_mutex);
13445                         mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13446 
13447                         mdi_devi_enter(
13448                             plun->lun_tgt->tgt_port->port_dip, &circ);
13449 
13450                         /*
13451                          * Exit phci to avoid deadlock with power management
13452                          * code during mdi_pi_offline
13453                          */
13454                         mdi_hold_path(PIP(cip));
13455                         mdi_devi_exit_phci(
13456                             plun->lun_tgt->tgt_port->port_dip, circ);
13457                         (void) mdi_pi_offline(PIP(cip),
13458                             NDI_DEVI_REMOVE);
13459                         mdi_devi_enter_phci(
13460                             plun->lun_tgt->tgt_port->port_dip, &circ);
13461                         mdi_rele_path(PIP(cip));
13462 
13463                         mdi_devi_exit(
13464                             plun->lun_tgt->tgt_port->port_dip, circ);
13465 
13466                         FCP_TRACE(fcp_logq,
13467                             plun->lun_tgt->tgt_port->port_instbuf,
13468                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13469                             "lun=%p pip freed %p", plun, cip);
13470 
13471                         (void) mdi_prop_remove(PIP(cip), NULL);
13472                         (void) mdi_pi_free(PIP(cip), 0);
13473 
13474                         mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13475                         mutex_enter(&plun->lun_tgt->tgt_mutex);
13476                         mutex_enter(&plun->lun_mutex);
13477                 }
13478         } else {
13479                 plun->lun_cip = NULL;
13480         }
13481 }
13482 
13483 /*
13484  * called when a timeout occurs
13485  *
13486  * can be scheduled during an attach or resume (if not already running)
13487  *
13488  * one timeout is set up for all ports
13489  *
13490  * acquires and releases the global mutex
13491  */
13492 /*ARGSUSED*/
13493 static void
13494 fcp_watch(void *arg)
13495 {
13496         struct fcp_port *pptr;
13497         struct fcp_ipkt *icmd;
13498         struct fcp_ipkt *nicmd;
13499         struct fcp_pkt  *cmd;
13500         struct fcp_pkt  *ncmd;
13501         struct fcp_pkt  *tail;
13502         struct fcp_pkt  *pcmd;
13503         struct fcp_pkt  *save_head;
13504         struct fcp_port *save_port;
13505 
13506         /* increment global watchdog time */
13507         fcp_watchdog_time += fcp_watchdog_timeout;
13508 
13509         mutex_enter(&fcp_global_mutex);
13510 
13511         /* scan each port in our list */
13512         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13513                 save_port = fcp_port_head;
13514                 pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13515                 mutex_exit(&fcp_global_mutex);
13516 
13517                 mutex_enter(&pptr->port_mutex);
13518                 if (pptr->port_ipkt_list == NULL &&
13519                     (pptr->port_state & (FCP_STATE_SUSPENDED |
13520                     FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13521                         pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13522                         mutex_exit(&pptr->port_mutex);
13523                         mutex_enter(&fcp_global_mutex);
13524                         goto end_of_watchdog;
13525                 }
13526 
13527                 /*
13528                  * We check if a list of targets need to be offlined.
13529                  */
13530                 if (pptr->port_offline_tgts) {
13531                         fcp_scan_offline_tgts(pptr);
13532                 }
13533 
13534                 /*
13535                  * We check if a list of luns need to be offlined.
13536                  */
13537                 if (pptr->port_offline_luns) {
13538                         fcp_scan_offline_luns(pptr);
13539                 }
13540 
13541                 /*
13542                  * We check if a list of targets or luns need to be reset.
13543                  */
13544                 if (pptr->port_reset_list) {
13545                         fcp_check_reset_delay(pptr);
13546                 }
13547 
13548                 mutex_exit(&pptr->port_mutex);
13549 
13550                 /*
13551                  * This is where the pending commands (pkt) are checked for
13552                  * timeout.
13553                  */
13554                 mutex_enter(&pptr->port_pkt_mutex);
13555                 tail = pptr->port_pkt_tail;
13556 
13557                 for (pcmd = NULL, cmd = pptr->port_pkt_head;
13558                     cmd != NULL; cmd = ncmd) {
13559                         ncmd = cmd->cmd_next;
13560                         /*
13561                          * If a command is in this queue the bit CFLAG_IN_QUEUE
13562                          * must be set.
13563                          */
13564                         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13565                         /*
13566                          * FCP_INVALID_TIMEOUT will be set for those
13567                          * command that need to be failed. Mostly those
13568                          * cmds that could not be queued down for the
13569                          * "timeout" value. cmd->cmd_timeout is used
13570                          * to try and requeue the command regularly.
13571                          */
13572                         if (cmd->cmd_timeout >= fcp_watchdog_time) {
13573                                 /*
13574                                  * This command hasn't timed out yet.  Let's
13575                                  * go to the next one.
13576                                  */
13577                                 pcmd = cmd;
13578                                 goto end_of_loop;
13579                         }
13580 
13581                         if (cmd == pptr->port_pkt_head) {
13582                                 ASSERT(pcmd == NULL);
13583                                 pptr->port_pkt_head = cmd->cmd_next;
13584                         } else {
13585                                 ASSERT(pcmd != NULL);
13586                                 pcmd->cmd_next = cmd->cmd_next;
13587                         }
13588 
13589                         if (cmd == pptr->port_pkt_tail) {
13590                                 ASSERT(cmd->cmd_next == NULL);
13591                                 pptr->port_pkt_tail = pcmd;
13592                                 if (pcmd) {
13593                                         pcmd->cmd_next = NULL;
13594                                 }
13595                         }
13596                         cmd->cmd_next = NULL;
13597 
13598                         /*
13599                          * save the current head before dropping the
13600                          * mutex - If the head doesn't remain the
13601                          * same after re acquiring the mutex, just
13602                          * bail out and revisit on next tick.
13603                          *
13604                          * PS: The tail pointer can change as the commands
13605                          * get requeued after failure to retransport
13606                          */
13607                         save_head = pptr->port_pkt_head;
13608                         mutex_exit(&pptr->port_pkt_mutex);
13609 
13610                         if (cmd->cmd_fp_pkt->pkt_timeout ==
13611                             FCP_INVALID_TIMEOUT) {
13612                                 struct scsi_pkt         *pkt = cmd->cmd_pkt;
13613                                 struct fcp_lun  *plun;
13614                                 struct fcp_tgt  *ptgt;
13615 
13616                                 plun = ADDR2LUN(&pkt->pkt_address);
13617                                 ptgt = plun->lun_tgt;
13618 
13619                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13620                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13621                                     "SCSI cmd 0x%x to D_ID=%x timed out",
13622                                     pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13623 
13624                                 cmd->cmd_state == FCP_PKT_ABORTING ?
13625                                     fcp_fail_cmd(cmd, CMD_RESET,
13626                                     STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13627                                     CMD_TIMEOUT, STAT_ABORTED);
13628                         } else {
13629                                 fcp_retransport_cmd(pptr, cmd);
13630                         }
13631                         mutex_enter(&pptr->port_pkt_mutex);
13632                         if (save_head && save_head != pptr->port_pkt_head) {
13633                                 /*
13634                                  * Looks like linked list got changed (mostly
13635                                  * happens when an an OFFLINE LUN code starts
13636                                  * returning overflow queue commands in
13637                                  * parallel. So bail out and revisit during
13638                                  * next tick
13639                                  */
13640                                 break;
13641                         }
13642                 end_of_loop:
13643                         /*
13644                          * Scan only upto the previously known tail pointer
13645                          * to avoid excessive processing - lots of new packets
13646                          * could have been added to the tail or the old ones
13647                          * re-queued.
13648                          */
13649                         if (cmd == tail) {
13650                                 break;
13651                         }
13652                 }
13653                 mutex_exit(&pptr->port_pkt_mutex);
13654 
13655                 mutex_enter(&pptr->port_mutex);
13656                 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13657                         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13658 
13659                         nicmd = icmd->ipkt_next;
13660                         if ((icmd->ipkt_restart != 0) &&
13661                             (icmd->ipkt_restart >= fcp_watchdog_time)) {
13662                                 /* packet has not timed out */
13663                                 continue;
13664                         }
13665 
13666                         /* time for packet re-transport */
13667                         if (icmd == pptr->port_ipkt_list) {
13668                                 pptr->port_ipkt_list = icmd->ipkt_next;
13669                                 if (pptr->port_ipkt_list) {
13670                                         pptr->port_ipkt_list->ipkt_prev =
13671                                             NULL;
13672                                 }
13673                         } else {
13674                                 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13675                                 if (icmd->ipkt_next) {
13676                                         icmd->ipkt_next->ipkt_prev =
13677                                             icmd->ipkt_prev;
13678                                 }
13679                         }
13680                         icmd->ipkt_next = NULL;
13681                         icmd->ipkt_prev = NULL;
13682                         mutex_exit(&pptr->port_mutex);
13683 
13684                         if (fcp_is_retryable(icmd)) {
13685                                 fc_ulp_rscn_info_t *rscnp =
13686                                     (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13687                                     pkt_ulp_rscn_infop;
13688 
13689                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13690                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13691                                     "%x to D_ID=%x Retrying..",
13692                                     icmd->ipkt_opcode,
13693                                     icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13694 
13695                                 /*
13696                                  * Update the RSCN count in the packet
13697                                  * before resending.
13698                                  */
13699 
13700                                 if (rscnp != NULL) {
13701                                         rscnp->ulp_rscn_count =
13702                                             fc_ulp_get_rscn_count(pptr->
13703                                             port_fp_handle);
13704                                 }
13705 
13706                                 mutex_enter(&pptr->port_mutex);
13707                                 mutex_enter(&ptgt->tgt_mutex);
13708                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13709                                         mutex_exit(&ptgt->tgt_mutex);
13710                                         mutex_exit(&pptr->port_mutex);
13711                                         switch (icmd->ipkt_opcode) {
13712                                                 int rval;
13713                                         case LA_ELS_PLOGI:
13714                                                 if ((rval = fc_ulp_login(
13715                                                     pptr->port_fp_handle,
13716                                                     &icmd->ipkt_fpkt, 1)) ==
13717                                                     FC_SUCCESS) {
13718                                                         mutex_enter(
13719                                                             &pptr->port_mutex);
13720                                                         continue;
13721                                                 }
13722                                                 if (fcp_handle_ipkt_errors(
13723                                                     pptr, ptgt, icmd, rval,
13724                                                     "PLOGI") == DDI_SUCCESS) {
13725                                                         mutex_enter(
13726                                                             &pptr->port_mutex);
13727                                                         continue;
13728                                                 }
13729                                                 break;
13730 
13731                                         case LA_ELS_PRLI:
13732                                                 if ((rval = fc_ulp_issue_els(
13733                                                     pptr->port_fp_handle,
13734                                                     icmd->ipkt_fpkt)) ==
13735                                                     FC_SUCCESS) {
13736                                                         mutex_enter(
13737                                                             &pptr->port_mutex);
13738                                                         continue;
13739                                                 }
13740                                                 if (fcp_handle_ipkt_errors(
13741                                                     pptr, ptgt, icmd, rval,
13742                                                     "PRLI") == DDI_SUCCESS) {
13743                                                         mutex_enter(
13744                                                             &pptr->port_mutex);
13745                                                         continue;
13746                                                 }
13747                                                 break;
13748 
13749                                         default:
13750                                                 if ((rval = fcp_transport(
13751                                                     pptr->port_fp_handle,
13752                                                     icmd->ipkt_fpkt, 1)) ==
13753                                                     FC_SUCCESS) {
13754                                                         mutex_enter(
13755                                                             &pptr->port_mutex);
13756                                                         continue;
13757                                                 }
13758                                                 if (fcp_handle_ipkt_errors(
13759                                                     pptr, ptgt, icmd, rval,
13760                                                     "PRLI") == DDI_SUCCESS) {
13761                                                         mutex_enter(
13762                                                             &pptr->port_mutex);
13763                                                         continue;
13764                                                 }
13765                                                 break;
13766                                         }
13767                                 } else {
13768                                         mutex_exit(&ptgt->tgt_mutex);
13769                                         mutex_exit(&pptr->port_mutex);
13770                                 }
13771                         } else {
13772                                 fcp_print_error(icmd->ipkt_fpkt);
13773                         }
13774 
13775                         (void) fcp_call_finish_init(pptr, ptgt,
13776                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13777                             icmd->ipkt_cause);
13778                         fcp_icmd_free(pptr, icmd);
13779                         mutex_enter(&pptr->port_mutex);
13780                 }
13781 
13782                 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13783                 mutex_exit(&pptr->port_mutex);
13784                 mutex_enter(&fcp_global_mutex);
13785 
13786         end_of_watchdog:
13787                 /*
13788                  * Bail out early before getting into trouble
13789                  */
13790                 if (save_port != fcp_port_head) {
13791                         break;
13792                 }
13793         }
13794 
13795         if (fcp_watchdog_init > 0) {
13796                 /* reschedule timeout to go again */
13797                 fcp_watchdog_id =
13798                     timeout(fcp_watch, NULL, fcp_watchdog_tick);
13799         }
13800         mutex_exit(&fcp_global_mutex);
13801 }
13802 
13803 
13804 static void
13805 fcp_check_reset_delay(struct fcp_port *pptr)
13806 {
13807         uint32_t                tgt_cnt;
13808         int                     level;
13809         struct fcp_tgt  *ptgt;
13810         struct fcp_lun  *plun;
13811         struct fcp_reset_elem *cur = NULL;
13812         struct fcp_reset_elem *next = NULL;
13813         struct fcp_reset_elem *prev = NULL;
13814 
13815         ASSERT(mutex_owned(&pptr->port_mutex));
13816 
13817         next = pptr->port_reset_list;
13818         while ((cur = next) != NULL) {
13819                 next = cur->next;
13820 
13821                 if (cur->timeout < fcp_watchdog_time) {
13822                         prev = cur;
13823                         continue;
13824                 }
13825 
13826                 ptgt = cur->tgt;
13827                 plun = cur->lun;
13828                 tgt_cnt = cur->tgt_cnt;
13829 
13830                 if (ptgt) {
13831                         level = RESET_TARGET;
13832                 } else {
13833                         ASSERT(plun != NULL);
13834                         level = RESET_LUN;
13835                         ptgt = plun->lun_tgt;
13836                 }
13837                 if (prev) {
13838                         prev->next = next;
13839                 } else {
13840                         /*
13841                          * Because we drop port mutex while doing aborts for
13842                          * packets, we can't rely on reset_list pointing to
13843                          * our head
13844                          */
13845                         if (cur == pptr->port_reset_list) {
13846                                 pptr->port_reset_list = next;
13847                         } else {
13848                                 struct fcp_reset_elem *which;
13849 
13850                                 which = pptr->port_reset_list;
13851                                 while (which && which->next != cur) {
13852                                         which = which->next;
13853                                 }
13854                                 ASSERT(which != NULL);
13855 
13856                                 which->next = next;
13857                                 prev = which;
13858                         }
13859                 }
13860 
13861                 kmem_free(cur, sizeof (*cur));
13862 
13863                 if (tgt_cnt == ptgt->tgt_change_cnt) {
13864                         mutex_enter(&ptgt->tgt_mutex);
13865                         if (level == RESET_TARGET) {
13866                                 fcp_update_tgt_state(ptgt,
13867                                     FCP_RESET, FCP_LUN_BUSY);
13868                         } else {
13869                                 fcp_update_lun_state(plun,
13870                                     FCP_RESET, FCP_LUN_BUSY);
13871                         }
13872                         mutex_exit(&ptgt->tgt_mutex);
13873 
13874                         mutex_exit(&pptr->port_mutex);
13875                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13876                         mutex_enter(&pptr->port_mutex);
13877                 }
13878         }
13879 }
13880 
13881 
13882 static void
13883 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13884     struct fcp_lun *rlun, int tgt_cnt)
13885 {
13886         int                     rval;
13887         struct fcp_lun  *tlun, *nlun;
13888         struct fcp_pkt  *pcmd = NULL, *ncmd = NULL,
13889             *cmd = NULL, *head = NULL,
13890             *tail = NULL;
13891 
13892         mutex_enter(&pptr->port_pkt_mutex);
13893         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13894                 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13895                 struct fcp_tgt *ptgt = plun->lun_tgt;
13896 
13897                 ncmd = cmd->cmd_next;
13898 
13899                 if (ptgt != ttgt && plun != rlun) {
13900                         pcmd = cmd;
13901                         continue;
13902                 }
13903 
13904                 if (pcmd != NULL) {
13905                         ASSERT(pptr->port_pkt_head != cmd);
13906                         pcmd->cmd_next = ncmd;
13907                 } else {
13908                         ASSERT(cmd == pptr->port_pkt_head);
13909                         pptr->port_pkt_head = ncmd;
13910                 }
13911                 if (pptr->port_pkt_tail == cmd) {
13912                         ASSERT(cmd->cmd_next == NULL);
13913                         pptr->port_pkt_tail = pcmd;
13914                         if (pcmd != NULL) {
13915                                 pcmd->cmd_next = NULL;
13916                         }
13917                 }
13918 
13919                 if (head == NULL) {
13920                         head = tail = cmd;
13921                 } else {
13922                         ASSERT(tail != NULL);
13923                         tail->cmd_next = cmd;
13924                         tail = cmd;
13925                 }
13926                 cmd->cmd_next = NULL;
13927         }
13928         mutex_exit(&pptr->port_pkt_mutex);
13929 
13930         for (cmd = head; cmd != NULL; cmd = ncmd) {
13931                 struct scsi_pkt *pkt = cmd->cmd_pkt;
13932 
13933                 ncmd = cmd->cmd_next;
13934                 ASSERT(pkt != NULL);
13935 
13936                 mutex_enter(&pptr->port_mutex);
13937                 if (ttgt->tgt_change_cnt == tgt_cnt) {
13938                         mutex_exit(&pptr->port_mutex);
13939                         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13940                         pkt->pkt_reason = CMD_RESET;
13941                         pkt->pkt_statistics |= STAT_DEV_RESET;
13942                         cmd->cmd_state = FCP_PKT_IDLE;
13943                         fcp_post_callback(cmd);
13944                 } else {
13945                         mutex_exit(&pptr->port_mutex);
13946                 }
13947         }
13948 
13949         /*
13950          * If the FCA will return all the commands in its queue then our
13951          * work is easy, just return.
13952          */
13953 
13954         if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13955                 return;
13956         }
13957 
13958         /*
13959          * For RESET_LUN get hold of target pointer
13960          */
13961         if (ttgt == NULL) {
13962                 ASSERT(rlun != NULL);
13963 
13964                 ttgt = rlun->lun_tgt;
13965 
13966                 ASSERT(ttgt != NULL);
13967         }
13968 
13969         /*
13970          * There are some severe race conditions here.
13971          * While we are trying to abort the pkt, it might be completing
13972          * so mark it aborted and if the abort does not succeed then
13973          * handle it in the watch thread.
13974          */
13975         mutex_enter(&ttgt->tgt_mutex);
13976         nlun = ttgt->tgt_lun;
13977         mutex_exit(&ttgt->tgt_mutex);
13978         while ((tlun = nlun) != NULL) {
13979                 int restart = 0;
13980                 if (rlun && rlun != tlun) {
13981                         mutex_enter(&ttgt->tgt_mutex);
13982                         nlun = tlun->lun_next;
13983                         mutex_exit(&ttgt->tgt_mutex);
13984                         continue;
13985                 }
13986                 mutex_enter(&tlun->lun_mutex);
13987                 cmd = tlun->lun_pkt_head;
13988                 while (cmd != NULL) {
13989                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
13990                                 struct scsi_pkt *pkt;
13991 
13992                                 restart = 1;
13993                                 cmd->cmd_state = FCP_PKT_ABORTING;
13994                                 mutex_exit(&tlun->lun_mutex);
13995                                 rval = fc_ulp_abort(pptr->port_fp_handle,
13996                                     cmd->cmd_fp_pkt, KM_SLEEP);
13997                                 if (rval == FC_SUCCESS) {
13998                                         pkt = cmd->cmd_pkt;
13999                                         pkt->pkt_reason = CMD_RESET;
14000                                         pkt->pkt_statistics |= STAT_DEV_RESET;
14001                                         cmd->cmd_state = FCP_PKT_IDLE;
14002                                         fcp_post_callback(cmd);
14003                                 } else {
14004                                         caddr_t msg;
14005 
14006                                         (void) fc_ulp_error(rval, &msg);
14007 
14008                                         /*
14009                                          * This part is tricky. The abort
14010                                          * failed and now the command could
14011                                          * be completing.  The cmd_state ==
14012                                          * FCP_PKT_ABORTING should save
14013                                          * us in fcp_cmd_callback. If we
14014                                          * are already aborting ignore the
14015                                          * command in fcp_cmd_callback.
14016                                          * Here we leave this packet for 20
14017                                          * sec to be aborted in the
14018                                          * fcp_watch thread.
14019                                          */
14020                                         fcp_log(CE_WARN, pptr->port_dip,
14021                                             "!Abort failed after reset %s",
14022                                             msg);
14023 
14024                                         cmd->cmd_timeout =
14025                                             fcp_watchdog_time +
14026                                             cmd->cmd_pkt->pkt_time +
14027                                             FCP_FAILED_DELAY;
14028 
14029                                         cmd->cmd_fp_pkt->pkt_timeout =
14030                                             FCP_INVALID_TIMEOUT;
14031                                         /*
14032                                          * This is a hack, cmd is put in the
14033                                          * overflow queue so that it can be
14034                                          * timed out finally
14035                                          */
14036                                         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14037 
14038                                         mutex_enter(&pptr->port_pkt_mutex);
14039                                         if (pptr->port_pkt_head) {
14040                                                 ASSERT(pptr->port_pkt_tail
14041                                                     != NULL);
14042                                                 pptr->port_pkt_tail->cmd_next
14043                                                     = cmd;
14044                                                 pptr->port_pkt_tail = cmd;
14045                                         } else {
14046                                                 ASSERT(pptr->port_pkt_tail
14047                                                     == NULL);
14048                                                 pptr->port_pkt_head =
14049                                                     pptr->port_pkt_tail
14050                                                     = cmd;
14051                                         }
14052                                         cmd->cmd_next = NULL;
14053                                         mutex_exit(&pptr->port_pkt_mutex);
14054                                 }
14055                                 mutex_enter(&tlun->lun_mutex);
14056                                 cmd = tlun->lun_pkt_head;
14057                         } else {
14058                                 cmd = cmd->cmd_forw;
14059                         }
14060                 }
14061                 mutex_exit(&tlun->lun_mutex);
14062 
14063                 mutex_enter(&ttgt->tgt_mutex);
14064                 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14065                 mutex_exit(&ttgt->tgt_mutex);
14066 
14067                 mutex_enter(&pptr->port_mutex);
14068                 if (tgt_cnt != ttgt->tgt_change_cnt) {
14069                         mutex_exit(&pptr->port_mutex);
14070                         return;
14071                 } else {
14072                         mutex_exit(&pptr->port_mutex);
14073                 }
14074         }
14075 }
14076 
14077 
14078 /*
14079  * unlink the soft state, returning the soft state found (if any)
14080  *
14081  * acquires and releases the global mutex
14082  */
14083 struct fcp_port *
14084 fcp_soft_state_unlink(struct fcp_port *pptr)
14085 {
14086         struct fcp_port *hptr;          /* ptr index */
14087         struct fcp_port *tptr;          /* prev hptr */
14088 
14089         mutex_enter(&fcp_global_mutex);
14090         for (hptr = fcp_port_head, tptr = NULL;
14091             hptr != NULL;
14092             tptr = hptr, hptr = hptr->port_next) {
14093                 if (hptr == pptr) {
14094                         /* we found a match -- remove this item */
14095                         if (tptr == NULL) {
14096                                 /* we're at the head of the list */
14097                                 fcp_port_head = hptr->port_next;
14098                         } else {
14099                                 tptr->port_next = hptr->port_next;
14100                         }
14101                         break;                  /* success */
14102                 }
14103         }
14104         if (fcp_port_head == NULL) {
14105                 fcp_cleanup_blacklist(&fcp_lun_blacklist);
14106         }
14107         mutex_exit(&fcp_global_mutex);
14108         return (hptr);
14109 }
14110 
14111 
14112 /*
14113  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14114  * WWN and a LUN number
14115  */
14116 /* ARGSUSED */
14117 static struct fcp_lun *
14118 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14119 {
14120         int hash;
14121         struct fcp_tgt *ptgt;
14122         struct fcp_lun *plun;
14123 
14124         ASSERT(mutex_owned(&pptr->port_mutex));
14125 
14126         hash = FCP_HASH(wwn);
14127         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14128             ptgt = ptgt->tgt_next) {
14129                 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14130                     sizeof (ptgt->tgt_port_wwn)) == 0) {
14131                         mutex_enter(&ptgt->tgt_mutex);
14132                         for (plun = ptgt->tgt_lun;
14133                             plun != NULL;
14134                             plun = plun->lun_next) {
14135                                 if (plun->lun_num == lun) {
14136                                         mutex_exit(&ptgt->tgt_mutex);
14137                                         return (plun);
14138                                 }
14139                         }
14140                         mutex_exit(&ptgt->tgt_mutex);
14141                         return (NULL);
14142                 }
14143         }
14144         return (NULL);
14145 }
14146 
14147 /*
14148  *     Function: fcp_prepare_pkt
14149  *
14150  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14151  *               for fcp_start(). It binds the data or partially maps it.
14152  *               Builds the FCP header and starts the initialization of the
14153  *               Fibre Channel header.
14154  *
14155  *     Argument: *pptr          FCP port.
14156  *               *cmd           FCP packet.
14157  *               *plun          LUN the command will be sent to.
14158  *
14159  *      Context: User, Kernel and Interrupt context.
14160  */
14161 static void
14162 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14163     struct fcp_lun *plun)
14164 {
14165         fc_packet_t             *fpkt = cmd->cmd_fp_pkt;
14166         struct fcp_tgt          *ptgt = plun->lun_tgt;
14167         struct fcp_cmd          *fcmd = &cmd->cmd_fcp_cmd;
14168 
14169         ASSERT(cmd->cmd_pkt->pkt_comp ||
14170             (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14171 
14172         if (cmd->cmd_pkt->pkt_numcookies) {
14173                 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14174                         fcmd->fcp_cntl.cntl_read_data = 1;
14175                         fcmd->fcp_cntl.cntl_write_data = 0;
14176                         fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14177                 } else {
14178                         fcmd->fcp_cntl.cntl_read_data = 0;
14179                         fcmd->fcp_cntl.cntl_write_data = 1;
14180                         fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14181                 }
14182 
14183                 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14184 
14185                 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14186                 ASSERT(fpkt->pkt_data_cookie_cnt <=
14187                     pptr->port_data_dma_attr.dma_attr_sgllen);
14188 
14189                 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14190 
14191                 /* FCA needs pkt_datalen to be set */
14192                 fpkt->pkt_datalen = cmd->cmd_dmacount;
14193                 fcmd->fcp_data_len = cmd->cmd_dmacount;
14194         } else {
14195                 fcmd->fcp_cntl.cntl_read_data = 0;
14196                 fcmd->fcp_cntl.cntl_write_data = 0;
14197                 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14198                 fpkt->pkt_datalen = 0;
14199                 fcmd->fcp_data_len = 0;
14200         }
14201 
14202         /* set up the Tagged Queuing type */
14203         if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14204                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14205         } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14206                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14207         } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14208                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14209         } else {
14210                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14211         }
14212 
14213         fcmd->fcp_ent_addr = plun->lun_addr;
14214 
14215         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14216                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14217                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14218         } else {
14219                 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14220         }
14221 
14222         cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14223         cmd->cmd_pkt->pkt_state = 0;
14224         cmd->cmd_pkt->pkt_statistics = 0;
14225         cmd->cmd_pkt->pkt_resid = 0;
14226 
14227         cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14228 
14229         if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14230                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14231                 fpkt->pkt_comp = NULL;
14232         } else {
14233                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14234                 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14235                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14236                 }
14237                 fpkt->pkt_comp = fcp_cmd_callback;
14238         }
14239 
14240         mutex_enter(&pptr->port_mutex);
14241         if (pptr->port_state & FCP_STATE_SUSPENDED) {
14242                 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14243         }
14244         mutex_exit(&pptr->port_mutex);
14245 
14246         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14247         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14248 
14249         /*
14250          * Save a few kernel cycles here
14251          */
14252 #ifndef __lock_lint
14253         fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14254 #endif /* __lock_lint */
14255 }
14256 
14257 static void
14258 fcp_post_callback(struct fcp_pkt *cmd)
14259 {
14260         scsi_hba_pkt_comp(cmd->cmd_pkt);
14261 }
14262 
14263 
14264 /*
14265  * called to do polled I/O by fcp_start()
14266  *
14267  * return a transport status value, i.e. TRAN_ACCECPT for success
14268  */
14269 static int
14270 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14271 {
14272         int     rval;
14273 
14274 #ifdef  DEBUG
14275         mutex_enter(&pptr->port_pkt_mutex);
14276         pptr->port_npkts++;
14277         mutex_exit(&pptr->port_pkt_mutex);
14278 #endif /* DEBUG */
14279 
14280         if (cmd->cmd_fp_pkt->pkt_timeout) {
14281                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14282         } else {
14283                 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14284         }
14285 
14286         ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14287 
14288         cmd->cmd_state = FCP_PKT_ISSUED;
14289 
14290         rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14291 
14292 #ifdef  DEBUG
14293         mutex_enter(&pptr->port_pkt_mutex);
14294         pptr->port_npkts--;
14295         mutex_exit(&pptr->port_pkt_mutex);
14296 #endif /* DEBUG */
14297 
14298         cmd->cmd_state = FCP_PKT_IDLE;
14299 
14300         switch (rval) {
14301         case FC_SUCCESS:
14302                 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14303                         fcp_complete_pkt(cmd->cmd_fp_pkt);
14304                         rval = TRAN_ACCEPT;
14305                 } else {
14306                         rval = TRAN_FATAL_ERROR;
14307                 }
14308                 break;
14309 
14310         case FC_TRAN_BUSY:
14311                 rval = TRAN_BUSY;
14312                 cmd->cmd_pkt->pkt_resid = 0;
14313                 break;
14314 
14315         case FC_BADPACKET:
14316                 rval = TRAN_BADPKT;
14317                 break;
14318 
14319         default:
14320                 rval = TRAN_FATAL_ERROR;
14321                 break;
14322         }
14323 
14324         return (rval);
14325 }
14326 
14327 
14328 /*
14329  * called by some of the following transport-called routines to convert
14330  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14331  */
14332 static struct fcp_port *
14333 fcp_dip2port(dev_info_t *dip)
14334 {
14335         int     instance;
14336 
14337         instance = ddi_get_instance(dip);
14338         return (ddi_get_soft_state(fcp_softstate, instance));
14339 }
14340 
14341 
14342 /*
14343  * called internally to return a LUN given a dip
14344  */
14345 struct fcp_lun *
14346 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14347 {
14348         struct fcp_tgt *ptgt;
14349         struct fcp_lun *plun;
14350         int i;
14351 
14352 
14353         ASSERT(mutex_owned(&pptr->port_mutex));
14354 
14355         for (i = 0; i < FCP_NUM_HASH; i++) {
14356                 for (ptgt = pptr->port_tgt_hash_table[i];
14357                     ptgt != NULL;
14358                     ptgt = ptgt->tgt_next) {
14359                         mutex_enter(&ptgt->tgt_mutex);
14360                         for (plun = ptgt->tgt_lun; plun != NULL;
14361                             plun = plun->lun_next) {
14362                                 mutex_enter(&plun->lun_mutex);
14363                                 if (plun->lun_cip == cip) {
14364                                         mutex_exit(&plun->lun_mutex);
14365                                         mutex_exit(&ptgt->tgt_mutex);
14366                                         return (plun); /* match found */
14367                                 }
14368                                 mutex_exit(&plun->lun_mutex);
14369                         }
14370                         mutex_exit(&ptgt->tgt_mutex);
14371                 }
14372         }
14373         return (NULL);                          /* no LUN found */
14374 }
14375 
14376 /*
14377  * pass an element to the hotplug list, kick the hotplug thread
14378  * and wait for the element to get processed by the hotplug thread.
14379  * on return the element is freed.
14380  *
14381  * return zero success and non-zero on failure
14382  *
14383  * acquires/releases the target mutex
14384  *
14385  */
14386 static int
14387 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14388     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14389 {
14390         struct fcp_hp_elem      *elem;
14391         int                     rval;
14392 
14393         mutex_enter(&plun->lun_tgt->tgt_mutex);
14394         if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14395             what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14396                 mutex_exit(&plun->lun_tgt->tgt_mutex);
14397                 fcp_log(CE_CONT, pptr->port_dip,
14398                     "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14399                     what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14400                 return (NDI_FAILURE);
14401         }
14402         mutex_exit(&plun->lun_tgt->tgt_mutex);
14403         mutex_enter(&elem->mutex);
14404         if (elem->wait) {
14405                 while (elem->wait) {
14406                         cv_wait(&elem->cv, &elem->mutex);
14407                 }
14408         }
14409         rval = (elem->result);
14410         mutex_exit(&elem->mutex);
14411         mutex_destroy(&elem->mutex);
14412         cv_destroy(&elem->cv);
14413         kmem_free(elem, sizeof (struct fcp_hp_elem));
14414         return (rval);
14415 }
14416 
14417 /*
14418  * pass an element to the hotplug list, and then
14419  * kick the hotplug thread
14420  *
14421  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14422  *
14423  * acquires/releases the hotplug mutex
14424  *
14425  * called with the target mutex owned
14426  *
14427  * memory acquired in NOSLEEP mode
14428  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14429  *       for the hp daemon to process the request and is responsible for
14430  *       freeing the element
14431  */
14432 static struct fcp_hp_elem *
14433 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14434     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14435 {
14436         struct fcp_hp_elem      *elem;
14437         dev_info_t *pdip;
14438 
14439         ASSERT(pptr != NULL);
14440         ASSERT(plun != NULL);
14441         ASSERT(plun->lun_tgt != NULL);
14442         ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14443 
14444         /* create space for a hotplug element */
14445         if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14446             == NULL) {
14447                 fcp_log(CE_WARN, NULL,
14448                     "!can't allocate memory for hotplug element");
14449                 return (NULL);
14450         }
14451 
14452         /* fill in hotplug element */
14453         elem->port = pptr;
14454         elem->lun = plun;
14455         elem->cip = cip;
14456         elem->old_lun_mpxio = plun->lun_mpxio;
14457         elem->what = what;
14458         elem->flags = flags;
14459         elem->link_cnt = link_cnt;
14460         elem->tgt_cnt = tgt_cnt;
14461         elem->wait = wait;
14462         mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14463         cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14464 
14465         /* schedule the hotplug task */
14466         pdip = pptr->port_dip;
14467         mutex_enter(&plun->lun_mutex);
14468         if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14469                 plun->lun_event_count++;
14470                 elem->event_cnt = plun->lun_event_count;
14471         }
14472         mutex_exit(&plun->lun_mutex);
14473         if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14474             (void *)elem, KM_NOSLEEP) == NULL) {
14475                 mutex_enter(&plun->lun_mutex);
14476                 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14477                         plun->lun_event_count--;
14478                 }
14479                 mutex_exit(&plun->lun_mutex);
14480                 kmem_free(elem, sizeof (*elem));
14481                 return (0);
14482         }
14483 
14484         return (elem);
14485 }
14486 
14487 
14488 static void
14489 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14490 {
14491         int                     rval;
14492         struct scsi_address     *ap;
14493         struct fcp_lun  *plun;
14494         struct fcp_tgt  *ptgt;
14495         fc_packet_t     *fpkt;
14496 
14497         ap = &cmd->cmd_pkt->pkt_address;
14498         plun = ADDR2LUN(ap);
14499         ptgt = plun->lun_tgt;
14500 
14501         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14502 
14503         cmd->cmd_state = FCP_PKT_IDLE;
14504 
14505         mutex_enter(&pptr->port_mutex);
14506         mutex_enter(&ptgt->tgt_mutex);
14507         if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14508             (!(pptr->port_state & FCP_STATE_ONLINING))) {
14509                 fc_ulp_rscn_info_t *rscnp;
14510 
14511                 cmd->cmd_state = FCP_PKT_ISSUED;
14512 
14513                 /*
14514                  * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14515                  * originally NULL, hence we try to set it to the pd pointed
14516                  * to by the SCSI device we're trying to get to.
14517                  */
14518 
14519                 fpkt = cmd->cmd_fp_pkt;
14520                 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14521                         fpkt->pkt_pd = ptgt->tgt_pd_handle;
14522                         /*
14523                          * We need to notify the transport that we now have a
14524                          * reference to the remote port handle.
14525                          */
14526                         fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14527                 }
14528 
14529                 mutex_exit(&ptgt->tgt_mutex);
14530                 mutex_exit(&pptr->port_mutex);
14531 
14532                 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14533 
14534                 /* prepare the packet */
14535 
14536                 fcp_prepare_pkt(pptr, cmd, plun);
14537 
14538                 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14539                     pkt_ulp_rscn_infop;
14540 
14541                 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14542                     fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14543 
14544                 if (rscnp != NULL) {
14545                         rscnp->ulp_rscn_count =
14546                             fc_ulp_get_rscn_count(pptr->
14547                             port_fp_handle);
14548                 }
14549 
14550                 rval = fcp_transport(pptr->port_fp_handle,
14551                     cmd->cmd_fp_pkt, 0);
14552 
14553                 if (rval == FC_SUCCESS) {
14554                         return;
14555                 }
14556                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
14557         } else {
14558                 mutex_exit(&ptgt->tgt_mutex);
14559                 mutex_exit(&pptr->port_mutex);
14560         }
14561 
14562         fcp_queue_pkt(pptr, cmd);
14563 }
14564 
14565 
14566 static void
14567 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14568 {
14569         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14570 
14571         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14572         cmd->cmd_state = FCP_PKT_IDLE;
14573 
14574         cmd->cmd_pkt->pkt_reason = reason;
14575         cmd->cmd_pkt->pkt_state = 0;
14576         cmd->cmd_pkt->pkt_statistics = statistics;
14577 
14578         fcp_post_callback(cmd);
14579 }
14580 
14581 /*
14582  *     Function: fcp_queue_pkt
14583  *
14584  *  Description: This function queues the packet passed by the caller into
14585  *               the list of packets of the FCP port.
14586  *
14587  *     Argument: *pptr          FCP port.
14588  *               *cmd           FCP packet to queue.
14589  *
14590  * Return Value: None
14591  *
14592  *      Context: User, Kernel and Interrupt context.
14593  */
14594 static void
14595 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14596 {
14597         ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14598 
14599         mutex_enter(&pptr->port_pkt_mutex);
14600         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14601         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14602         cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14603 
14604         /*
14605          * zero pkt_time means hang around for ever
14606          */
14607         if (cmd->cmd_pkt->pkt_time) {
14608                 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14609                         cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14610                 } else {
14611                         /*
14612                          * Indicate the watch thread to fail the
14613                          * command by setting it to highest value
14614                          */
14615                         cmd->cmd_timeout = fcp_watchdog_time;
14616                         cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14617                 }
14618         }
14619 
14620         if (pptr->port_pkt_head) {
14621                 ASSERT(pptr->port_pkt_tail != NULL);
14622 
14623                 pptr->port_pkt_tail->cmd_next = cmd;
14624                 pptr->port_pkt_tail = cmd;
14625         } else {
14626                 ASSERT(pptr->port_pkt_tail == NULL);
14627 
14628                 pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14629         }
14630         cmd->cmd_next = NULL;
14631         mutex_exit(&pptr->port_pkt_mutex);
14632 }
14633 
14634 /*
14635  *     Function: fcp_update_targets
14636  *
14637  *  Description: This function applies the specified change of state to all
14638  *               the targets listed.  The operation applied is 'set'.
14639  *
14640  *     Argument: *pptr          FCP port.
14641  *               *dev_list      Array of fc_portmap_t structures.
14642  *               count          Length of dev_list.
14643  *               state          State bits to update.
14644  *               cause          Reason for the update.
14645  *
14646  * Return Value: None
14647  *
14648  *      Context: User, Kernel and Interrupt context.
14649  *               The mutex pptr->port_mutex must be held.
14650  */
14651 static void
14652 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14653     uint32_t count, uint32_t state, int cause)
14654 {
14655         fc_portmap_t            *map_entry;
14656         struct fcp_tgt  *ptgt;
14657 
14658         ASSERT(MUTEX_HELD(&pptr->port_mutex));
14659 
14660         while (count--) {
14661                 map_entry = &(dev_list[count]);
14662                 ptgt = fcp_lookup_target(pptr,
14663                     (uchar_t *)&(map_entry->map_pwwn));
14664                 if (ptgt == NULL) {
14665                         continue;
14666                 }
14667 
14668                 mutex_enter(&ptgt->tgt_mutex);
14669                 ptgt->tgt_trace = 0;
14670                 ptgt->tgt_change_cnt++;
14671                 ptgt->tgt_statec_cause = cause;
14672                 ptgt->tgt_tmp_cnt = 1;
14673                 fcp_update_tgt_state(ptgt, FCP_SET, state);
14674                 mutex_exit(&ptgt->tgt_mutex);
14675         }
14676 }
14677 
14678 static int
14679 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14680     int lcount, int tcount, int cause)
14681 {
14682         int rval;
14683 
14684         mutex_enter(&pptr->port_mutex);
14685         rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14686         mutex_exit(&pptr->port_mutex);
14687 
14688         return (rval);
14689 }
14690 
14691 
14692 static int
14693 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14694     int lcount, int tcount, int cause)
14695 {
14696         int     finish_init = 0;
14697         int     finish_tgt = 0;
14698         int     do_finish_init = 0;
14699         int     rval = FCP_NO_CHANGE;
14700 
14701         if (cause == FCP_CAUSE_LINK_CHANGE ||
14702             cause == FCP_CAUSE_LINK_DOWN) {
14703                 do_finish_init = 1;
14704         }
14705 
14706         if (ptgt != NULL) {
14707                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14708                     FCP_BUF_LEVEL_2, 0,
14709                     "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14710                     " cause = %d, d_id = 0x%x, tgt_done = %d",
14711                     pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14712                     pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14713                     ptgt->tgt_d_id, ptgt->tgt_done);
14714 
14715                 mutex_enter(&ptgt->tgt_mutex);
14716 
14717                 if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14718                         rval = FCP_DEV_CHANGE;
14719                         if (do_finish_init && ptgt->tgt_done == 0) {
14720                                 ptgt->tgt_done++;
14721                                 finish_init = 1;
14722                         }
14723                 } else {
14724                         if (--ptgt->tgt_tmp_cnt <= 0) {
14725                                 ptgt->tgt_tmp_cnt = 0;
14726                                 finish_tgt = 1;
14727 
14728                                 if (do_finish_init) {
14729                                         finish_init = 1;
14730                                 }
14731                         }
14732                 }
14733                 mutex_exit(&ptgt->tgt_mutex);
14734         } else {
14735                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14736                     FCP_BUF_LEVEL_2, 0,
14737                     "Call Finish Init for NO target");
14738 
14739                 if (do_finish_init) {
14740                         finish_init = 1;
14741                 }
14742         }
14743 
14744         if (finish_tgt) {
14745                 ASSERT(ptgt != NULL);
14746 
14747                 mutex_enter(&ptgt->tgt_mutex);
14748 #ifdef  DEBUG
14749                 bzero(ptgt->tgt_tmp_cnt_stack,
14750                     sizeof (ptgt->tgt_tmp_cnt_stack));
14751 
14752                 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14753                     FCP_STACK_DEPTH);
14754 #endif /* DEBUG */
14755                 mutex_exit(&ptgt->tgt_mutex);
14756 
14757                 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14758         }
14759 
14760         if (finish_init && lcount == pptr->port_link_cnt) {
14761                 ASSERT(pptr->port_tmp_cnt > 0);
14762                 if (--pptr->port_tmp_cnt == 0) {
14763                         fcp_finish_init(pptr);
14764                 }
14765         } else if (lcount != pptr->port_link_cnt) {
14766                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
14767                     fcp_trace, FCP_BUF_LEVEL_2, 0,
14768                     "fcp_call_finish_init_held,1: state change occured"
14769                     " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14770         }
14771 
14772         return (rval);
14773 }
14774 
14775 static void
14776 fcp_reconfigure_luns(void * tgt_handle)
14777 {
14778         uint32_t                dev_cnt;
14779         fc_portmap_t            *devlist;
14780         struct fcp_tgt  *ptgt = (struct fcp_tgt *)tgt_handle;
14781         struct fcp_port         *pptr = ptgt->tgt_port;
14782 
14783         /*
14784          * If the timer that fires this off got canceled too late, the
14785          * target could have been destroyed.
14786          */
14787 
14788         if (ptgt->tgt_tid == NULL) {
14789                 return;
14790         }
14791 
14792         devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14793         if (devlist == NULL) {
14794                 fcp_log(CE_WARN, pptr->port_dip,
14795                     "!fcp%d: failed to allocate for portmap",
14796                     pptr->port_instance);
14797                 return;
14798         }
14799 
14800         dev_cnt = 1;
14801         devlist->map_pd = ptgt->tgt_pd_handle;
14802         devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14803         devlist->map_did.port_id = ptgt->tgt_d_id;
14804 
14805         bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14806         bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14807 
14808         devlist->map_state = PORT_DEVICE_LOGGED_IN;
14809         devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14810         devlist->map_flags = 0;
14811 
14812         fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14813             pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14814 
14815         /*
14816          * Clear the tgt_tid after no more references to
14817          * the fcp_tgt
14818          */
14819         mutex_enter(&ptgt->tgt_mutex);
14820         ptgt->tgt_tid = NULL;
14821         mutex_exit(&ptgt->tgt_mutex);
14822 
14823         kmem_free(devlist, sizeof (*devlist));
14824 }
14825 
14826 
14827 static void
14828 fcp_free_targets(struct fcp_port *pptr)
14829 {
14830         int                     i;
14831         struct fcp_tgt  *ptgt;
14832 
14833         mutex_enter(&pptr->port_mutex);
14834         for (i = 0; i < FCP_NUM_HASH; i++) {
14835                 ptgt = pptr->port_tgt_hash_table[i];
14836                 while (ptgt != NULL) {
14837                         struct fcp_tgt *next_tgt = ptgt->tgt_next;
14838 
14839                         fcp_free_target(ptgt);
14840                         ptgt = next_tgt;
14841                 }
14842         }
14843         mutex_exit(&pptr->port_mutex);
14844 }
14845 
14846 
14847 static void
14848 fcp_free_target(struct fcp_tgt *ptgt)
14849 {
14850         struct fcp_lun  *plun;
14851         timeout_id_t            tid;
14852 
14853         mutex_enter(&ptgt->tgt_mutex);
14854         tid = ptgt->tgt_tid;
14855 
14856         /*
14857          * Cancel any pending timeouts for this target.
14858          */
14859 
14860         if (tid != NULL) {
14861                 /*
14862                  * Set tgt_tid to NULL first to avoid a race in the callback.
14863                  * If tgt_tid is NULL, the callback will simply return.
14864                  */
14865                 ptgt->tgt_tid = NULL;
14866                 mutex_exit(&ptgt->tgt_mutex);
14867                 (void) untimeout(tid);
14868                 mutex_enter(&ptgt->tgt_mutex);
14869         }
14870 
14871         plun = ptgt->tgt_lun;
14872         while (plun != NULL) {
14873                 struct fcp_lun *next_lun = plun->lun_next;
14874 
14875                 fcp_dealloc_lun(plun);
14876                 plun = next_lun;
14877         }
14878 
14879         mutex_exit(&ptgt->tgt_mutex);
14880         fcp_dealloc_tgt(ptgt);
14881 }
14882 
14883 /*
14884  *     Function: fcp_is_retryable
14885  *
14886  *  Description: Indicates if the internal packet is retryable.
14887  *
14888  *     Argument: *icmd          FCP internal packet.
14889  *
14890  * Return Value: 0      Not retryable
14891  *               1      Retryable
14892  *
14893  *      Context: User, Kernel and Interrupt context
14894  */
14895 static int
14896 fcp_is_retryable(struct fcp_ipkt *icmd)
14897 {
14898         if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14899             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14900                 return (0);
14901         }
14902 
14903         return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14904             icmd->ipkt_port->port_deadline) ? 1 : 0);
14905 }
14906 
14907 /*
14908  *     Function: fcp_create_on_demand
14909  *
14910  *     Argument: *pptr          FCP port.
14911  *               *pwwn          Port WWN.
14912  *
14913  * Return Value: 0      Success
14914  *               EIO
14915  *               ENOMEM
14916  *               EBUSY
14917  *               EINVAL
14918  *
14919  *      Context: User and Kernel context
14920  */
14921 static int
14922 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14923 {
14924         int                     wait_ms;
14925         int                     tcount;
14926         int                     lcount;
14927         int                     ret;
14928         int                     error;
14929         int                     rval = EIO;
14930         int                     ntries;
14931         fc_portmap_t            *devlist;
14932         opaque_t                pd;
14933         struct fcp_lun          *plun;
14934         struct fcp_tgt          *ptgt;
14935         int                     old_manual = 0;
14936 
14937         /* Allocates the fc_portmap_t structure. */
14938         devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14939 
14940         /*
14941          * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14942          * in the commented statement below:
14943          *
14944          * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14945          *
14946          * Below, the deadline for the discovery process is set.
14947          */
14948         mutex_enter(&pptr->port_mutex);
14949         pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14950         mutex_exit(&pptr->port_mutex);
14951 
14952         /*
14953          * We try to find the remote port based on the WWN provided by the
14954          * caller.  We actually ask fp/fctl if it has it.
14955          */
14956         pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14957             (la_wwn_t *)pwwn, &error, 1);
14958 
14959         if (pd == NULL) {
14960                 kmem_free(devlist, sizeof (*devlist));
14961                 return (rval);
14962         }
14963 
14964         /*
14965          * The remote port was found.  We ask fp/fctl to update our
14966          * fc_portmap_t structure.
14967          */
14968         ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14969             (la_wwn_t *)pwwn, devlist);
14970         if (ret != FC_SUCCESS) {
14971                 kmem_free(devlist, sizeof (*devlist));
14972                 return (rval);
14973         }
14974 
14975         /*
14976          * The map flag field is set to indicates that the creation is being
14977          * done at the user request (Ioclt probably luxadm or cfgadm).
14978          */
14979         devlist->map_type = PORT_DEVICE_USER_CREATE;
14980 
14981         mutex_enter(&pptr->port_mutex);
14982 
14983         /*
14984          * We check to see if fcp already has a target that describes the
14985          * device being created.  If not it is created.
14986          */
14987         ptgt = fcp_lookup_target(pptr, pwwn);
14988         if (ptgt == NULL) {
14989                 lcount = pptr->port_link_cnt;
14990                 mutex_exit(&pptr->port_mutex);
14991 
14992                 ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14993                 if (ptgt == NULL) {
14994                         fcp_log(CE_WARN, pptr->port_dip,
14995                             "!FC target allocation failed");
14996                         return (ENOMEM);
14997                 }
14998 
14999                 mutex_enter(&pptr->port_mutex);
15000         }
15001 
15002         mutex_enter(&ptgt->tgt_mutex);
15003         ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15004         ptgt->tgt_tmp_cnt = 1;
15005         ptgt->tgt_device_created = 0;
15006         /*
15007          * If fabric and auto config is set but the target was
15008          * manually unconfigured then reset to the manual_config_only to
15009          * 0 so the device will get configured.
15010          */
15011         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15012             fcp_enable_auto_configuration &&
15013             ptgt->tgt_manual_config_only == 1) {
15014                 old_manual = 1;
15015                 ptgt->tgt_manual_config_only = 0;
15016         }
15017         mutex_exit(&ptgt->tgt_mutex);
15018 
15019         fcp_update_targets(pptr, devlist, 1,
15020             FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15021 
15022         lcount = pptr->port_link_cnt;
15023         tcount = ptgt->tgt_change_cnt;
15024 
15025         if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15026             tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15027                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15028                     fcp_enable_auto_configuration && old_manual) {
15029                         mutex_enter(&ptgt->tgt_mutex);
15030                         ptgt->tgt_manual_config_only = 1;
15031                         mutex_exit(&ptgt->tgt_mutex);
15032                 }
15033 
15034                 if (pptr->port_link_cnt != lcount ||
15035                     ptgt->tgt_change_cnt != tcount) {
15036                         rval = EBUSY;
15037                 }
15038                 mutex_exit(&pptr->port_mutex);
15039 
15040                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15041                     FCP_BUF_LEVEL_3, 0,
15042                     "fcp_create_on_demand: mapflags ptgt=%x, "
15043                     "lcount=%x::port_link_cnt=%x, "
15044                     "tcount=%x: tgt_change_cnt=%x, rval=%x",
15045                     ptgt, lcount, pptr->port_link_cnt,
15046                     tcount, ptgt->tgt_change_cnt, rval);
15047                 return (rval);
15048         }
15049 
15050         /*
15051          * Due to lack of synchronization mechanisms, we perform
15052          * periodic monitoring of our request; Because requests
15053          * get dropped when another one supercedes (either because
15054          * of a link change or a target change), it is difficult to
15055          * provide a clean synchronization mechanism (such as a
15056          * semaphore or a conditional variable) without exhaustively
15057          * rewriting the mainline discovery code of this driver.
15058          */
15059         wait_ms = 500;
15060 
15061         ntries = fcp_max_target_retries;
15062 
15063         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15064             FCP_BUF_LEVEL_3, 0,
15065             "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15066             "lcount=%x::port_link_cnt=%x, "
15067             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15068             "tgt_tmp_cnt =%x",
15069             ntries, ptgt, lcount, pptr->port_link_cnt,
15070             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15071             ptgt->tgt_tmp_cnt);
15072 
15073         mutex_enter(&ptgt->tgt_mutex);
15074         while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15075             ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15076                 mutex_exit(&ptgt->tgt_mutex);
15077                 mutex_exit(&pptr->port_mutex);
15078 
15079                 delay(drv_usectohz(wait_ms * 1000));
15080 
15081                 mutex_enter(&pptr->port_mutex);
15082                 mutex_enter(&ptgt->tgt_mutex);
15083         }
15084 
15085 
15086         if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15087                 rval = EBUSY;
15088         } else {
15089                 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15090                     FCP_TGT_NODE_PRESENT) {
15091                         rval = 0;
15092                 }
15093         }
15094 
15095         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15096             FCP_BUF_LEVEL_3, 0,
15097             "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15098             "lcount=%x::port_link_cnt=%x, "
15099             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15100             "tgt_tmp_cnt =%x",
15101             ntries, ptgt, lcount, pptr->port_link_cnt,
15102             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15103             ptgt->tgt_tmp_cnt);
15104 
15105         if (rval) {
15106                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15107                     fcp_enable_auto_configuration && old_manual) {
15108                         ptgt->tgt_manual_config_only = 1;
15109                 }
15110                 mutex_exit(&ptgt->tgt_mutex);
15111                 mutex_exit(&pptr->port_mutex);
15112                 kmem_free(devlist, sizeof (*devlist));
15113 
15114                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15115                     FCP_BUF_LEVEL_3, 0,
15116                     "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15117                     "lcount=%x::port_link_cnt=%x, "
15118                     "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15119                     "tgt_device_created=%x, tgt D_ID=%x",
15120                     ntries, ptgt, lcount, pptr->port_link_cnt,
15121                     tcount, ptgt->tgt_change_cnt, rval,
15122                     ptgt->tgt_device_created, ptgt->tgt_d_id);
15123                 return (rval);
15124         }
15125 
15126         if ((plun = ptgt->tgt_lun) != NULL) {
15127                 tcount = plun->lun_tgt->tgt_change_cnt;
15128         } else {
15129                 rval = EINVAL;
15130         }
15131         lcount = pptr->port_link_cnt;
15132 
15133         /*
15134          * Configuring the target with no LUNs will fail. We
15135          * should reset the node state so that it is not
15136          * automatically configured when the LUNs are added
15137          * to this target.
15138          */
15139         if (ptgt->tgt_lun_cnt == 0) {
15140                 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15141         }
15142         mutex_exit(&ptgt->tgt_mutex);
15143         mutex_exit(&pptr->port_mutex);
15144 
15145         while (plun) {
15146                 child_info_t    *cip;
15147 
15148                 mutex_enter(&plun->lun_mutex);
15149                 cip = plun->lun_cip;
15150                 mutex_exit(&plun->lun_mutex);
15151 
15152                 mutex_enter(&ptgt->tgt_mutex);
15153                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15154                         mutex_exit(&ptgt->tgt_mutex);
15155 
15156                         rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15157                             FCP_ONLINE, lcount, tcount,
15158                             NDI_ONLINE_ATTACH);
15159                         if (rval != NDI_SUCCESS) {
15160                                 FCP_TRACE(fcp_logq,
15161                                     pptr->port_instbuf, fcp_trace,
15162                                     FCP_BUF_LEVEL_3, 0,
15163                                     "fcp_create_on_demand: "
15164                                     "pass_to_hp_and_wait failed "
15165                                     "rval=%x", rval);
15166                                 rval = EIO;
15167                         } else {
15168                                 mutex_enter(&LUN_TGT->tgt_mutex);
15169                                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
15170                                     FCP_LUN_BUSY);
15171                                 mutex_exit(&LUN_TGT->tgt_mutex);
15172                         }
15173                         mutex_enter(&ptgt->tgt_mutex);
15174                 }
15175 
15176                 plun = plun->lun_next;
15177                 mutex_exit(&ptgt->tgt_mutex);
15178         }
15179 
15180         kmem_free(devlist, sizeof (*devlist));
15181 
15182         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15183             fcp_enable_auto_configuration && old_manual) {
15184                 mutex_enter(&ptgt->tgt_mutex);
15185                 /* if successful then set manual to 0 */
15186                 if (rval == 0) {
15187                         ptgt->tgt_manual_config_only = 0;
15188                 } else {
15189                         /* reset to 1 so the user has to do the config */
15190                         ptgt->tgt_manual_config_only = 1;
15191                 }
15192                 mutex_exit(&ptgt->tgt_mutex);
15193         }
15194 
15195         return (rval);
15196 }
15197 
15198 
15199 static void
15200 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15201 {
15202         int             count;
15203         uchar_t         byte;
15204 
15205         count = 0;
15206         while (*string) {
15207                 byte = FCP_ATOB(*string); string++;
15208                 byte = byte << 4 | FCP_ATOB(*string); string++;
15209                 bytes[count++] = byte;
15210 
15211                 if (count >= byte_len) {
15212                         break;
15213                 }
15214         }
15215 }
15216 
15217 static void
15218 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15219 {
15220         int             i;
15221 
15222         for (i = 0; i < FC_WWN_SIZE; i++) {
15223                 (void) sprintf(string + (i * 2),
15224                     "%02x", wwn[i]);
15225         }
15226 
15227 }
15228 
15229 static void
15230 fcp_print_error(fc_packet_t *fpkt)
15231 {
15232         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
15233             fpkt->pkt_ulp_private;
15234         struct fcp_port *pptr;
15235         struct fcp_tgt  *ptgt;
15236         struct fcp_lun  *plun;
15237         caddr_t                 buf;
15238         int                     scsi_cmd = 0;
15239 
15240         ptgt = icmd->ipkt_tgt;
15241         plun = icmd->ipkt_lun;
15242         pptr = ptgt->tgt_port;
15243 
15244         buf = kmem_zalloc(256, KM_NOSLEEP);
15245         if (buf == NULL) {
15246                 return;
15247         }
15248 
15249         switch (icmd->ipkt_opcode) {
15250         case SCMD_REPORT_LUN:
15251                 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15252                     " lun=0x%%x failed");
15253                 scsi_cmd++;
15254                 break;
15255 
15256         case SCMD_INQUIRY_PAGE83:
15257                 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15258                     " lun=0x%%x failed");
15259                 scsi_cmd++;
15260                 break;
15261 
15262         case SCMD_INQUIRY:
15263                 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15264                     " lun=0x%%x failed");
15265                 scsi_cmd++;
15266                 break;
15267 
15268         case LA_ELS_PLOGI:
15269                 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15270                 break;
15271 
15272         case LA_ELS_PRLI:
15273                 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15274                 break;
15275         }
15276 
15277         if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15278                 struct fcp_rsp          response, *rsp;
15279                 uchar_t                 asc, ascq;
15280                 caddr_t                 sense_key = NULL;
15281                 struct fcp_rsp_info     fcp_rsp_err, *bep;
15282 
15283                 if (icmd->ipkt_nodma) {
15284                         rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15285                         bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15286                             sizeof (struct fcp_rsp));
15287                 } else {
15288                         rsp = &response;
15289                         bep = &fcp_rsp_err;
15290 
15291                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15292                             sizeof (struct fcp_rsp));
15293 
15294                         FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15295                             bep, fpkt->pkt_resp_acc,
15296                             sizeof (struct fcp_rsp_info));
15297                 }
15298 
15299 
15300                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15301                         (void) sprintf(buf + strlen(buf),
15302                             " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15303                             " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15304                             " senselen=%%x. Giving up");
15305 
15306                         fcp_log(CE_WARN, pptr->port_dip, buf,
15307                             ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15308                             rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15309                             rsp->fcp_u.fcp_status.reserved_1,
15310                             rsp->fcp_response_len, rsp->fcp_sense_len);
15311 
15312                         kmem_free(buf, 256);
15313                         return;
15314                 }
15315 
15316                 if (rsp->fcp_u.fcp_status.rsp_len_set &&
15317                     bep->rsp_code != FCP_NO_FAILURE) {
15318                         (void) sprintf(buf + strlen(buf),
15319                             " FCP Response code = 0x%x", bep->rsp_code);
15320                 }
15321 
15322                 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15323                         struct scsi_extended_sense sense_info, *sense_ptr;
15324 
15325                         if (icmd->ipkt_nodma) {
15326                                 sense_ptr = (struct scsi_extended_sense *)
15327                                     ((caddr_t)fpkt->pkt_resp +
15328                                     sizeof (struct fcp_rsp) +
15329                                     rsp->fcp_response_len);
15330                         } else {
15331                                 sense_ptr = &sense_info;
15332 
15333                                 FCP_CP_IN(fpkt->pkt_resp +
15334                                     sizeof (struct fcp_rsp) +
15335                                     rsp->fcp_response_len, &sense_info,
15336                                     fpkt->pkt_resp_acc,
15337                                     sizeof (struct scsi_extended_sense));
15338                         }
15339 
15340                         if (sense_ptr->es_key < NUM_SENSE_KEYS +
15341                             NUM_IMPL_SENSE_KEYS) {
15342                                 sense_key = sense_keys[sense_ptr->es_key];
15343                         } else {
15344                                 sense_key = "Undefined";
15345                         }
15346 
15347                         asc = sense_ptr->es_add_code;
15348                         ascq = sense_ptr->es_qual_code;
15349 
15350                         (void) sprintf(buf + strlen(buf),
15351                             ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15352                             " Giving up");
15353 
15354                         fcp_log(CE_WARN, pptr->port_dip, buf,
15355                             ptgt->tgt_d_id, plun->lun_num, sense_key,
15356                             asc, ascq);
15357                 } else {
15358                         (void) sprintf(buf + strlen(buf),
15359                             " : SCSI status=%%x. Giving up");
15360 
15361                         fcp_log(CE_WARN, pptr->port_dip, buf,
15362                             ptgt->tgt_d_id, plun->lun_num,
15363                             rsp->fcp_u.fcp_status.scsi_status);
15364                 }
15365         } else {
15366                 caddr_t state, reason, action, expln;
15367 
15368                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
15369                     &action, &expln);
15370 
15371                 (void) sprintf(buf + strlen(buf), ": State:%%s,"
15372                     " Reason:%%s. Giving up");
15373 
15374                 if (scsi_cmd) {
15375                         fcp_log(CE_WARN, pptr->port_dip, buf,
15376                             ptgt->tgt_d_id, plun->lun_num, state, reason);
15377                 } else {
15378                         fcp_log(CE_WARN, pptr->port_dip, buf,
15379                             ptgt->tgt_d_id, state, reason);
15380                 }
15381         }
15382 
15383         kmem_free(buf, 256);
15384 }
15385 
15386 
15387 static int
15388 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15389     struct fcp_ipkt *icmd, int rval, caddr_t op)
15390 {
15391         int     ret = DDI_FAILURE;
15392         char    *error;
15393 
15394         switch (rval) {
15395         case FC_DEVICE_BUSY_NEW_RSCN:
15396                 /*
15397                  * This means that there was a new RSCN that the transport
15398                  * knows about (which the ULP *may* know about too) but the
15399                  * pkt that was sent down was related to an older RSCN. So, we
15400                  * are just going to reset the retry count and deadline and
15401                  * continue to retry. The idea is that transport is currently
15402                  * working on the new RSCN and will soon let the ULPs know
15403                  * about it and when it does the existing logic will kick in
15404                  * where it will change the tcount to indicate that something
15405                  * changed on the target. So, rediscovery will start and there
15406                  * will not be an infinite retry.
15407                  *
15408                  * For a full flow of how the RSCN info is transferred back and
15409                  * forth, see fp.c
15410                  */
15411                 icmd->ipkt_retries = 0;
15412                 icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15413                     FCP_ICMD_DEADLINE;
15414 
15415                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15416                     FCP_BUF_LEVEL_3, 0,
15417                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15418                     rval, ptgt->tgt_d_id);
15419                 /* FALLTHROUGH */
15420 
15421         case FC_STATEC_BUSY:
15422         case FC_DEVICE_BUSY:
15423         case FC_PBUSY:
15424         case FC_FBUSY:
15425         case FC_TRAN_BUSY:
15426         case FC_OFFLINE:
15427                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15428                     FCP_BUF_LEVEL_3, 0,
15429                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15430                     rval, ptgt->tgt_d_id);
15431                 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15432                     fcp_is_retryable(icmd)) {
15433                         fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15434                         ret = DDI_SUCCESS;
15435                 }
15436                 break;
15437 
15438         case FC_LOGINREQ:
15439                 /*
15440                  * FC_LOGINREQ used to be handled just like all the cases
15441                  * above. It has been changed to handled a PRLI that fails
15442                  * with FC_LOGINREQ different than other ipkts that fail
15443                  * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15444                  * a simple matter to turn it into a PLOGI instead, so that's
15445                  * exactly what we do here.
15446                  */
15447                 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15448                         ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15449                             icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15450                             icmd->ipkt_change_cnt, icmd->ipkt_cause);
15451                 } else {
15452                         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15453                             FCP_BUF_LEVEL_3, 0,
15454                             "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15455                             rval, ptgt->tgt_d_id);
15456                         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15457                             fcp_is_retryable(icmd)) {
15458                                 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15459                                 ret = DDI_SUCCESS;
15460                         }
15461                 }
15462                 break;
15463 
15464         default:
15465                 mutex_enter(&pptr->port_mutex);
15466                 mutex_enter(&ptgt->tgt_mutex);
15467                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15468                         mutex_exit(&ptgt->tgt_mutex);
15469                         mutex_exit(&pptr->port_mutex);
15470 
15471                         (void) fc_ulp_error(rval, &error);
15472                         fcp_log(CE_WARN, pptr->port_dip,
15473                             "!Failed to send %s to D_ID=%x error=%s",
15474                             op, ptgt->tgt_d_id, error);
15475                 } else {
15476                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
15477                             fcp_trace, FCP_BUF_LEVEL_2, 0,
15478                             "fcp_handle_ipkt_errors,1: state change occured"
15479                             " for D_ID=0x%x", ptgt->tgt_d_id);
15480                         mutex_exit(&ptgt->tgt_mutex);
15481                         mutex_exit(&pptr->port_mutex);
15482                 }
15483                 break;
15484         }
15485 
15486         return (ret);
15487 }
15488 
15489 
15490 /*
15491  * Check of outstanding commands on any LUN for this target
15492  */
15493 static int
15494 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15495 {
15496         struct  fcp_lun *plun;
15497         struct  fcp_pkt *cmd;
15498 
15499         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15500                 mutex_enter(&plun->lun_mutex);
15501                 for (cmd = plun->lun_pkt_head; cmd != NULL;
15502                     cmd = cmd->cmd_forw) {
15503                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
15504                                 mutex_exit(&plun->lun_mutex);
15505                                 return (FC_SUCCESS);
15506                         }
15507                 }
15508                 mutex_exit(&plun->lun_mutex);
15509         }
15510 
15511         return (FC_FAILURE);
15512 }
15513 
15514 static fc_portmap_t *
15515 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15516 {
15517         int                     i;
15518         fc_portmap_t            *devlist;
15519         fc_portmap_t            *devptr = NULL;
15520         struct fcp_tgt  *ptgt;
15521 
15522         mutex_enter(&pptr->port_mutex);
15523         for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15524                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15525                     ptgt = ptgt->tgt_next) {
15526                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15527                                 ++*dev_cnt;
15528                         }
15529                 }
15530         }
15531 
15532         devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15533             KM_NOSLEEP);
15534         if (devlist == NULL) {
15535                 mutex_exit(&pptr->port_mutex);
15536                 fcp_log(CE_WARN, pptr->port_dip,
15537                     "!fcp%d: failed to allocate for portmap for construct map",
15538                     pptr->port_instance);
15539                 return (devptr);
15540         }
15541 
15542         for (i = 0; i < FCP_NUM_HASH; i++) {
15543                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15544                     ptgt = ptgt->tgt_next) {
15545                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15546                                 int ret;
15547 
15548                                 ret = fc_ulp_pwwn_to_portmap(
15549                                     pptr->port_fp_handle,
15550                                     (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15551                                     devlist);
15552 
15553                                 if (ret == FC_SUCCESS) {
15554                                         devlist++;
15555                                         continue;
15556                                 }
15557 
15558                                 devlist->map_pd = NULL;
15559                                 devlist->map_did.port_id = ptgt->tgt_d_id;
15560                                 devlist->map_hard_addr.hard_addr =
15561                                     ptgt->tgt_hard_addr;
15562 
15563                                 devlist->map_state = PORT_DEVICE_INVALID;
15564                                 devlist->map_type = PORT_DEVICE_OLD;
15565 
15566                                 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15567                                     &devlist->map_nwwn, FC_WWN_SIZE);
15568 
15569                                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15570                                     &devlist->map_pwwn, FC_WWN_SIZE);
15571 
15572                                 devlist++;
15573                         }
15574                 }
15575         }
15576 
15577         mutex_exit(&pptr->port_mutex);
15578 
15579         return (devptr);
15580 }
15581 /*
15582  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15583  */
15584 static void
15585 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15586 {
15587         int i;
15588         struct fcp_tgt  *ptgt;
15589         struct fcp_lun  *plun;
15590 
15591         for (i = 0; i < FCP_NUM_HASH; i++) {
15592                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15593                     ptgt = ptgt->tgt_next) {
15594                         mutex_enter(&ptgt->tgt_mutex);
15595                         for (plun = ptgt->tgt_lun; plun != NULL;
15596                             plun = plun->lun_next) {
15597                                 if (plun->lun_mpxio &&
15598                                     plun->lun_state & FCP_LUN_BUSY) {
15599                                         if (!fcp_pass_to_hp(pptr, plun,
15600                                             plun->lun_cip,
15601                                             FCP_MPXIO_PATH_SET_BUSY,
15602                                             pptr->port_link_cnt,
15603                                             ptgt->tgt_change_cnt, 0, 0)) {
15604                                                 FCP_TRACE(fcp_logq,
15605                                                     pptr->port_instbuf,
15606                                                     fcp_trace,
15607                                                     FCP_BUF_LEVEL_2, 0,
15608                                                     "path_verifybusy: "
15609                                                     "disable lun %p failed!",
15610                                                     plun);
15611                                         }
15612                                 }
15613                         }
15614                         mutex_exit(&ptgt->tgt_mutex);
15615                 }
15616         }
15617 }
15618 
15619 static int
15620 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15621 {
15622         dev_info_t              *cdip = NULL;
15623         dev_info_t              *pdip = NULL;
15624 
15625         ASSERT(plun);
15626 
15627         mutex_enter(&plun->lun_mutex);
15628         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15629                 mutex_exit(&plun->lun_mutex);
15630                 return (NDI_FAILURE);
15631         }
15632         mutex_exit(&plun->lun_mutex);
15633         cdip = mdi_pi_get_client(PIP(cip));
15634         pdip = mdi_pi_get_phci(PIP(cip));
15635 
15636         ASSERT(cdip != NULL);
15637         ASSERT(pdip != NULL);
15638 
15639         if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15640                 /* LUN ready for IO */
15641                 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15642         } else {
15643                 /* LUN busy to accept IO */
15644                 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15645         }
15646         return (NDI_SUCCESS);
15647 }
15648 
15649 /*
15650  * Caller must free the returned string of MAXPATHLEN len
15651  * If the device is offline (-1 instance number) NULL
15652  * will be returned.
15653  */
15654 static char *
15655 fcp_get_lun_path(struct fcp_lun *plun) {
15656         dev_info_t      *dip = NULL;
15657         char            *path = NULL;
15658         mdi_pathinfo_t  *pip = NULL;
15659 
15660         if (plun == NULL) {
15661                 return (NULL);
15662         }
15663 
15664         mutex_enter(&plun->lun_mutex);
15665         if (plun->lun_mpxio == 0) {
15666                 dip = DIP(plun->lun_cip);
15667                 mutex_exit(&plun->lun_mutex);
15668         } else {
15669                 /*
15670                  * lun_cip must be accessed with lun_mutex held. Here
15671                  * plun->lun_cip either points to a valid node or it is NULL.
15672                  * Make a copy so that we can release lun_mutex.
15673                  */
15674                 pip = PIP(plun->lun_cip);
15675 
15676                 /*
15677                  * Increase ref count on the path so that we can release
15678                  * lun_mutex and still be sure that the pathinfo node (and thus
15679                  * also the client) is not deallocated. If pip is NULL, this
15680                  * has no effect.
15681                  */
15682                 mdi_hold_path(pip);
15683 
15684                 mutex_exit(&plun->lun_mutex);
15685 
15686                 /* Get the client. If pip is NULL, we get NULL. */
15687                 dip = mdi_pi_get_client(pip);
15688         }
15689 
15690         if (dip == NULL)
15691                 goto out;
15692         if (ddi_get_instance(dip) < 0)
15693                 goto out;
15694 
15695         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15696         if (path == NULL)
15697                 goto out;
15698 
15699         (void) ddi_pathname(dip, path);
15700 
15701         /* Clean up. */
15702 out:
15703         if (pip != NULL)
15704                 mdi_rele_path(pip);
15705 
15706         /*
15707          * In reality, the user wants a fully valid path (one they can open)
15708          * but this string is lacking the mount point, and the minor node.
15709          * It would be nice if we could "figure these out" somehow
15710          * and fill them in.  Otherwise, the userland code has to understand
15711          * driver specific details of which minor node is the "best" or
15712          * "right" one to expose.  (Ex: which slice is the whole disk, or
15713          * which tape doesn't rewind)
15714          */
15715         return (path);
15716 }
15717 
15718 static int
15719 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15720     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15721 {
15722         int64_t reset_delay;
15723         int rval, retry = 0;
15724         struct fcp_port *pptr = fcp_dip2port(parent);
15725 
15726         reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15727             (ddi_get_lbolt64() - pptr->port_attach_time);
15728         if (reset_delay < 0) {
15729                 reset_delay = 0;
15730         }
15731 
15732         if (fcp_bus_config_debug) {
15733                 flag |= NDI_DEVI_DEBUG;
15734         }
15735 
15736         switch (op) {
15737         case BUS_CONFIG_ONE:
15738                 /*
15739                  * Retry the command since we need to ensure
15740                  * the fabric devices are available for root
15741                  */
15742                 while (retry++ < fcp_max_bus_config_retries) {
15743                         rval =  (ndi_busop_bus_config(parent,
15744                             flag | NDI_MDI_FALLBACK, op,
15745                             arg, childp, (clock_t)reset_delay));
15746                         if (rval == 0) {
15747                                 return (rval);
15748                         }
15749                 }
15750 
15751                 /*
15752                  * drain taskq to make sure nodes are created and then
15753                  * try again.
15754                  */
15755                 taskq_wait(DEVI(parent)->devi_taskq);
15756                 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15757                     op, arg, childp, 0));
15758 
15759         case BUS_CONFIG_DRIVER:
15760         case BUS_CONFIG_ALL: {
15761                 /*
15762                  * delay till all devices report in (port_tmp_cnt == 0)
15763                  * or FCP_INIT_WAIT_TIMEOUT
15764                  */
15765                 mutex_enter(&pptr->port_mutex);
15766                 while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15767                         (void) cv_timedwait(&pptr->port_config_cv,
15768                             &pptr->port_mutex,
15769                             ddi_get_lbolt() + (clock_t)reset_delay);
15770                         reset_delay =
15771                             (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15772                             (ddi_get_lbolt64() - pptr->port_attach_time);
15773                 }
15774                 mutex_exit(&pptr->port_mutex);
15775                 /* drain taskq to make sure nodes are created */
15776                 taskq_wait(DEVI(parent)->devi_taskq);
15777                 return (ndi_busop_bus_config(parent, flag, op,
15778                     arg, childp, 0));
15779         }
15780 
15781         default:
15782                 return (NDI_FAILURE);
15783         }
15784         /*NOTREACHED*/
15785 }
15786 
15787 static int
15788 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15789     ddi_bus_config_op_t op, void *arg)
15790 {
15791         if (fcp_bus_config_debug) {
15792                 flag |= NDI_DEVI_DEBUG;
15793         }
15794 
15795         return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15796 }
15797 
15798 
15799 /*
15800  * Routine to copy GUID into the lun structure.
15801  * returns 0 if copy was successful and 1 if encountered a
15802  * failure and did not copy the guid.
15803  */
15804 static int
15805 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15806 {
15807 
15808         int retval = 0;
15809 
15810         /* add one for the null terminator */
15811         const unsigned int len = strlen(guidp) + 1;
15812 
15813         if ((guidp == NULL) || (plun == NULL)) {
15814                 return (1);
15815         }
15816 
15817         /*
15818          * if the plun->lun_guid already has been allocated,
15819          * then check the size. if the size is exact, reuse
15820          * it....if not free it an allocate the required size.
15821          * The reallocation should NOT typically happen
15822          * unless the GUIDs reported changes between passes.
15823          * We free up and alloc again even if the
15824          * size was more than required. This is due to the
15825          * fact that the field lun_guid_size - serves
15826          * dual role of indicating the size of the wwn
15827          * size and ALSO the allocation size.
15828          */
15829         if (plun->lun_guid) {
15830                 if (plun->lun_guid_size != len) {
15831                         /*
15832                          * free the allocated memory and
15833                          * initialize the field
15834                          * lun_guid_size to 0.
15835                          */
15836                         kmem_free(plun->lun_guid, plun->lun_guid_size);
15837                         plun->lun_guid = NULL;
15838                         plun->lun_guid_size = 0;
15839                 }
15840         }
15841         /*
15842          * alloc only if not already done.
15843          */
15844         if (plun->lun_guid == NULL) {
15845                 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15846                 if (plun->lun_guid == NULL) {
15847                         cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15848                             "Unable to allocate"
15849                             "Memory for GUID!!! size %d", len);
15850                         retval = 1;
15851                 } else {
15852                         plun->lun_guid_size = len;
15853                 }
15854         }
15855         if (plun->lun_guid) {
15856                 /*
15857                  * now copy the GUID
15858                  */
15859                 bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15860         }
15861         return (retval);
15862 }
15863 
15864 /*
15865  * fcp_reconfig_wait
15866  *
15867  * Wait for a rediscovery/reconfiguration to complete before continuing.
15868  */
15869 
15870 static void
15871 fcp_reconfig_wait(struct fcp_port *pptr)
15872 {
15873         clock_t         reconfig_start, wait_timeout;
15874 
15875         /*
15876          * Quick check.  If pptr->port_tmp_cnt is 0, there is no
15877          * reconfiguration in progress.
15878          */
15879 
15880         mutex_enter(&pptr->port_mutex);
15881         if (pptr->port_tmp_cnt == 0) {
15882                 mutex_exit(&pptr->port_mutex);
15883                 return;
15884         }
15885         mutex_exit(&pptr->port_mutex);
15886 
15887         /*
15888          * If we cause a reconfig by raising power, delay until all devices
15889          * report in (port_tmp_cnt returns to 0)
15890          */
15891 
15892         reconfig_start = ddi_get_lbolt();
15893         wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15894 
15895         mutex_enter(&pptr->port_mutex);
15896 
15897         while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15898             pptr->port_tmp_cnt) {
15899 
15900                 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15901                     reconfig_start + wait_timeout);
15902         }
15903 
15904         mutex_exit(&pptr->port_mutex);
15905 
15906         /*
15907          * Even if fcp_tmp_count isn't 0, continue without error.  The port
15908          * we want may still be ok.  If not, it will error out later
15909          */
15910 }
15911 
15912 /*
15913  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15914  * We rely on the fcp_global_mutex to provide protection against changes to
15915  * the fcp_lun_blacklist.
15916  *
15917  * You can describe a list of target port WWNs and LUN numbers which will
15918  * not be configured. LUN numbers will be interpreted as decimal. White
15919  * spaces and ',' can be used in the list of LUN numbers.
15920  *
15921  * To prevent LUNs 1 and 2 from being configured for target
15922  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15923  *
15924  * pwwn-lun-blacklist=
15925  * "510000f010fd92a1,1,2",
15926  * "510000e012079df1,1,2";
15927  */
15928 static void
15929 fcp_read_blacklist(dev_info_t *dip,
15930     struct fcp_black_list_entry **pplun_blacklist) {
15931         char **prop_array       = NULL;
15932         char *curr_pwwn         = NULL;
15933         char *curr_lun          = NULL;
15934         uint32_t prop_item      = 0;
15935         int idx                 = 0;
15936         int len                 = 0;
15937 
15938         ASSERT(mutex_owned(&fcp_global_mutex));
15939         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15940             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15941             LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15942                 return;
15943         }
15944 
15945         for (idx = 0; idx < prop_item; idx++) {
15946 
15947                 curr_pwwn = prop_array[idx];
15948                 while (*curr_pwwn == ' ') {
15949                         curr_pwwn++;
15950                 }
15951                 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15952                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15953                             ", please check.", curr_pwwn);
15954                         continue;
15955                 }
15956                 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15957                     (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15958                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15959                             ", please check.", curr_pwwn);
15960                         continue;
15961                 }
15962                 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15963                         if (isxdigit(curr_pwwn[len]) != TRUE) {
15964                                 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15965                                     "blacklist, please check.", curr_pwwn);
15966                                 break;
15967                         }
15968                 }
15969                 if (len != sizeof (la_wwn_t) * 2) {
15970                         continue;
15971                 }
15972 
15973                 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15974                 *(curr_lun - 1) = '\0';
15975                 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15976         }
15977 
15978         ddi_prop_free(prop_array);
15979 }
15980 
15981 /*
15982  * Get the masking info about one remote target port designated by wwn.
15983  * Lun ids could be separated by ',' or white spaces.
15984  */
15985 static void
15986 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15987     struct fcp_black_list_entry **pplun_blacklist) {
15988         int             idx                     = 0;
15989         uint32_t        offset                  = 0;
15990         unsigned long   lun_id                  = 0;
15991         char            lunid_buf[16];
15992         char            *pend                   = NULL;
15993         int             illegal_digit           = 0;
15994 
15995         while (offset < strlen(curr_lun)) {
15996                 while ((curr_lun[offset + idx] != ',') &&
15997                     (curr_lun[offset + idx] != '\0') &&
15998                     (curr_lun[offset + idx] != ' ')) {
15999                         if (isdigit(curr_lun[offset + idx]) == 0) {
16000                                 illegal_digit++;
16001                         }
16002                         idx++;
16003                 }
16004                 if (illegal_digit > 0) {
16005                         offset += (idx+1);      /* To the start of next lun */
16006                         idx = 0;
16007                         illegal_digit = 0;
16008                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16009                             "the blacklist, please check digits.",
16010                             curr_lun, curr_pwwn);
16011                         continue;
16012                 }
16013                 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16014                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16015                             "the blacklist, please check the length of LUN#.",
16016                             curr_lun, curr_pwwn);
16017                         break;
16018                 }
16019                 if (idx == 0) { /* ignore ' ' or ',' or '\0' */
16020                     offset++;
16021                     continue;
16022                 }
16023 
16024                 bcopy(curr_lun + offset, lunid_buf, idx);
16025                 lunid_buf[idx] = '\0';
16026                 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16027                         fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16028                 } else {
16029                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16030                             "the blacklist, please check %s.",
16031                             curr_lun, curr_pwwn, lunid_buf);
16032                 }
16033                 offset += (idx+1);      /* To the start of next lun */
16034                 idx = 0;
16035         }
16036 }
16037 
16038 /*
16039  * Add one masking record
16040  */
16041 static void
16042 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16043     struct fcp_black_list_entry **pplun_blacklist) {
16044         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16045         struct fcp_black_list_entry     *new_entry      = NULL;
16046         la_wwn_t                        wwn;
16047 
16048         fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16049         while (tmp_entry) {
16050                 if ((bcmp(&tmp_entry->wwn, &wwn,
16051                     sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16052                         return;
16053                 }
16054 
16055                 tmp_entry = tmp_entry->next;
16056         }
16057 
16058         /* add to black list */
16059         new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16060             (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16061         bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16062         new_entry->lun = lun_id;
16063         new_entry->masked = 0;
16064         new_entry->next = *pplun_blacklist;
16065         *pplun_blacklist = new_entry;
16066 }
16067 
16068 /*
16069  * Check if we should mask the specified lun of this fcp_tgt
16070  */
16071 static int
16072 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16073         struct fcp_black_list_entry *remote_port;
16074 
16075         remote_port = fcp_lun_blacklist;
16076         while (remote_port != NULL) {
16077                 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16078                         if (remote_port->lun == lun_id) {
16079                                 remote_port->masked++;
16080                                 if (remote_port->masked == 1) {
16081                                         fcp_log(CE_NOTE, NULL, "LUN %d of port "
16082                                             "%02x%02x%02x%02x%02x%02x%02x%02x "
16083                                             "is masked due to black listing.\n",
16084                                             lun_id, wwn->raw_wwn[0],
16085                                             wwn->raw_wwn[1], wwn->raw_wwn[2],
16086                                             wwn->raw_wwn[3], wwn->raw_wwn[4],
16087                                             wwn->raw_wwn[5], wwn->raw_wwn[6],
16088                                             wwn->raw_wwn[7]);
16089                                 }
16090                                 return (TRUE);
16091                         }
16092                 }
16093                 remote_port = remote_port->next;
16094         }
16095         return (FALSE);
16096 }
16097 
16098 /*
16099  * Release all allocated resources
16100  */
16101 static void
16102 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16103         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16104         struct fcp_black_list_entry     *current_entry  = NULL;
16105 
16106         ASSERT(mutex_owned(&fcp_global_mutex));
16107         /*
16108          * Traverse all luns
16109          */
16110         while (tmp_entry) {
16111                 current_entry = tmp_entry;
16112                 tmp_entry = tmp_entry->next;
16113                 kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16114         }
16115         *pplun_blacklist = NULL;
16116 }
16117 
16118 /*
16119  * In fcp module,
16120  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16121  */
16122 static struct scsi_pkt *
16123 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16124     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16125     int flags, int (*callback)(), caddr_t arg)
16126 {
16127         fcp_port_t      *pptr = ADDR2FCP(ap);
16128         fcp_pkt_t       *cmd  = NULL;
16129         fc_frame_hdr_t  *hp;
16130 
16131         /*
16132          * First step: get the packet
16133          */
16134         if (pkt == NULL) {
16135                 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16136                     tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16137                     callback, arg);
16138                 if (pkt == NULL) {
16139                         return (NULL);
16140                 }
16141 
16142                 /*
16143                  * All fields in scsi_pkt will be initialized properly or
16144                  * set to zero. We need do nothing for scsi_pkt.
16145                  */
16146                 /*
16147                  * But it's our responsibility to link other related data
16148                  * structures. Their initialization will be done, just
16149                  * before the scsi_pkt will be sent to FCA.
16150                  */
16151                 cmd             = PKT2CMD(pkt);
16152                 cmd->cmd_pkt = pkt;
16153                 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16154                 /*
16155                  * fc_packet_t
16156                  */
16157                 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16158                 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16159                     sizeof (struct fcp_pkt));
16160                 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16161                 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16162                 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16163                 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16164                 /*
16165                  * Fill in the Fabric Channel Header
16166                  */
16167                 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16168                 hp->r_ctl = R_CTL_COMMAND;
16169                 hp->rsvd = 0;
16170                 hp->type = FC_TYPE_SCSI_FCP;
16171                 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16172                 hp->seq_id = 0;
16173                 hp->df_ctl  = 0;
16174                 hp->seq_cnt = 0;
16175                 hp->ox_id = 0xffff;
16176                 hp->rx_id = 0xffff;
16177                 hp->ro = 0;
16178         } else {
16179                 /*
16180                  * We need think if we should reset any elements in
16181                  * related data structures.
16182                  */
16183                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
16184                     fcp_trace, FCP_BUF_LEVEL_6, 0,
16185                     "reusing pkt, flags %d", flags);
16186                 cmd = PKT2CMD(pkt);
16187                 if (cmd->cmd_fp_pkt->pkt_pd) {
16188                         cmd->cmd_fp_pkt->pkt_pd = NULL;
16189                 }
16190         }
16191 
16192         /*
16193          * Second step:  dma allocation/move
16194          */
16195         if (bp && bp->b_bcount != 0) {
16196                 /*
16197                  * Mark if it's read or write
16198                  */
16199                 if (bp->b_flags & B_READ) {
16200                         cmd->cmd_flags |= CFLAG_IS_READ;
16201                 } else {
16202                         cmd->cmd_flags &= ~CFLAG_IS_READ;
16203                 }
16204 
16205                 bp_mapin(bp);
16206                 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16207                 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16208                 cmd->cmd_fp_pkt->pkt_data_resid = 0;
16209         } else {
16210                 /*
16211                  * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16212                  * to send zero-length read/write.
16213                  */
16214                 cmd->cmd_fp_pkt->pkt_data = NULL;
16215                 cmd->cmd_fp_pkt->pkt_datalen = 0;
16216         }
16217 
16218         return (pkt);
16219 }
16220 
16221 static void
16222 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16223 {
16224         fcp_port_t      *pptr = ADDR2FCP(ap);
16225 
16226         /*
16227          * First we let FCA to uninitilize private part.
16228          */
16229         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16230             PKT2CMD(pkt)->cmd_fp_pkt);
16231 
16232         /*
16233          * Then we uninitialize fc_packet.
16234          */
16235 
16236         /*
16237          * Thirdly, we uninitializae fcp_pkt.
16238          */
16239 
16240         /*
16241          * In the end, we free scsi_pkt.
16242          */
16243         scsi_hba_pkt_free(ap, pkt);
16244 }
16245 
16246 static int
16247 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16248 {
16249         fcp_port_t      *pptr = ADDR2FCP(ap);
16250         fcp_lun_t       *plun = ADDR2LUN(ap);
16251         fcp_tgt_t       *ptgt = plun->lun_tgt;
16252         fcp_pkt_t       *cmd  = PKT2CMD(pkt);
16253         fcp_cmd_t       *fcmd = &cmd->cmd_fcp_cmd;
16254         fc_packet_t     *fpkt = cmd->cmd_fp_pkt;
16255         int              rval;
16256 
16257         fpkt->pkt_pd = ptgt->tgt_pd_handle;
16258         (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16259 
16260         /*
16261          * Firstly, we need initialize fcp_pkt_t
16262          * Secondly, we need initialize fcp_cmd_t.
16263          */
16264         bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16265         fcmd->fcp_data_len = fpkt->pkt_datalen;
16266         fcmd->fcp_ent_addr = plun->lun_addr;
16267         if (pkt->pkt_flags & FLAG_HTAG) {
16268                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16269         } else if (pkt->pkt_flags & FLAG_OTAG) {
16270                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16271         } else if (pkt->pkt_flags & FLAG_STAG) {
16272                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16273         } else {
16274                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16275         }
16276 
16277         if (cmd->cmd_flags & CFLAG_IS_READ) {
16278                 fcmd->fcp_cntl.cntl_read_data = 1;
16279                 fcmd->fcp_cntl.cntl_write_data = 0;
16280         } else {
16281                 fcmd->fcp_cntl.cntl_read_data = 0;
16282                 fcmd->fcp_cntl.cntl_write_data = 1;
16283         }
16284 
16285         /*
16286          * Then we need initialize fc_packet_t too.
16287          */
16288         fpkt->pkt_timeout = pkt->pkt_time + 2;
16289         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16290         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16291         if (cmd->cmd_flags & CFLAG_IS_READ) {
16292                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16293         } else {
16294                 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16295         }
16296 
16297         if (pkt->pkt_flags & FLAG_NOINTR) {
16298                 fpkt->pkt_comp = NULL;
16299                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16300         } else {
16301                 fpkt->pkt_comp = fcp_cmd_callback;
16302                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16303                 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16304                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16305                 }
16306         }
16307 
16308         /*
16309          * Lastly, we need initialize scsi_pkt
16310          */
16311         pkt->pkt_reason = CMD_CMPLT;
16312         pkt->pkt_state = 0;
16313         pkt->pkt_statistics = 0;
16314         pkt->pkt_resid = 0;
16315 
16316         /*
16317          * if interrupts aren't allowed (e.g. at dump time) then we'll
16318          * have to do polled I/O
16319          */
16320         if (pkt->pkt_flags & FLAG_NOINTR) {
16321                 return (fcp_dopoll(pptr, cmd));
16322         }
16323 
16324         cmd->cmd_state = FCP_PKT_ISSUED;
16325         rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16326         if (rval == FC_SUCCESS) {
16327                 return (TRAN_ACCEPT);
16328         }
16329 
16330         /*
16331          * Need more consideration
16332          *
16333          * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16334          */
16335         cmd->cmd_state = FCP_PKT_IDLE;
16336         if (rval == FC_TRAN_BUSY) {
16337                 return (TRAN_BUSY);
16338         } else {
16339                 return (TRAN_FATAL_ERROR);
16340         }
16341 }
16342 
16343 /*
16344  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16345  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16346  */
16347 static void
16348 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16349 {
16350         FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16351             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16352 }
16353 
16354 /*
16355  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16356  */
16357 static void
16358 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16359 {
16360         FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16361             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16362 }