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,
 861         NULL
 862 };
 863 
 864 
 865 static fc_ulp_modinfo_t fcp_modinfo = {
 866         &fcp_modinfo,                       /* ulp_handle */
 867         FCTL_ULP_MODREV_4,              /* ulp_rev */
 868         FC4_SCSI_FCP,                   /* ulp_type */
 869         "fcp",                          /* ulp_name */
 870         FCP_STATEC_MASK,                /* ulp_statec_mask */
 871         fcp_port_attach,                /* ulp_port_attach */
 872         fcp_port_detach,                /* ulp_port_detach */
 873         fcp_port_ioctl,                 /* ulp_port_ioctl */
 874         fcp_els_callback,               /* ulp_els_callback */
 875         fcp_data_callback,              /* ulp_data_callback */
 876         fcp_statec_callback             /* ulp_statec_callback */
 877 };
 878 
 879 #ifdef  DEBUG
 880 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 881                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 882                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 883                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 884 #else
 885 #define FCP_TRACE_DEFAULT       (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |      \
 886                                 FCP_LEVEL_2 | FCP_LEVEL_3 |             \
 887                                 FCP_LEVEL_4 | FCP_LEVEL_5 |             \
 888                                 FCP_LEVEL_6 | FCP_LEVEL_7)
 889 #endif
 890 
 891 /* FCP global variables */
 892 int                     fcp_bus_config_debug = 0;
 893 static int              fcp_log_size = FCP_LOG_SIZE;
 894 static int              fcp_trace = FCP_TRACE_DEFAULT;
 895 static fc_trace_logq_t  *fcp_logq = NULL;
 896 static struct fcp_black_list_entry      *fcp_lun_blacklist = NULL;
 897 /*
 898  * The auto-configuration is set by default.  The only way of disabling it is
 899  * through the property MANUAL_CFG_ONLY in the fcp.conf file.
 900  */
 901 static int              fcp_enable_auto_configuration = 1;
 902 static int              fcp_max_bus_config_retries      = 4;
 903 static int              fcp_lun_ready_retry = 300;
 904 /*
 905  * The value assigned to the following variable has changed several times due
 906  * to a problem with the data underruns reporting of some firmware(s).  The
 907  * current value of 50 gives a timeout value of 25 seconds for a max number
 908  * of 256 LUNs.
 909  */
 910 static int              fcp_max_target_retries = 50;
 911 /*
 912  * Watchdog variables
 913  * ------------------
 914  *
 915  * fcp_watchdog_init
 916  *
 917  *      Indicates if the watchdog timer is running or not.  This is actually
 918  *      a counter of the number of Fibre Channel ports that attached.  When
 919  *      the first port attaches the watchdog is started.  When the last port
 920  *      detaches the watchdog timer is stopped.
 921  *
 922  * fcp_watchdog_time
 923  *
 924  *      This is the watchdog clock counter.  It is incremented by
 925  *      fcp_watchdog_time each time the watchdog timer expires.
 926  *
 927  * fcp_watchdog_timeout
 928  *
 929  *      Increment value of the variable fcp_watchdog_time as well as the
 930  *      the timeout value of the watchdog timer.  The unit is 1 second.  It
 931  *      is strange that this is not a #define   but a variable since the code
 932  *      never changes this value.  The reason why it can be said that the
 933  *      unit is 1 second is because the number of ticks for the watchdog
 934  *      timer is determined like this:
 935  *
 936  *          fcp_watchdog_tick = fcp_watchdog_timeout *
 937  *                                drv_usectohz(1000000);
 938  *
 939  *      The value 1000000 is hard coded in the code.
 940  *
 941  * fcp_watchdog_tick
 942  *
 943  *      Watchdog timer value in ticks.
 944  */
 945 static int              fcp_watchdog_init = 0;
 946 static int              fcp_watchdog_time = 0;
 947 static int              fcp_watchdog_timeout = 1;
 948 static int              fcp_watchdog_tick;
 949 
 950 /*
 951  * fcp_offline_delay is a global variable to enable customisation of
 952  * the timeout on link offlines or RSCNs. The default value is set
 953  * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as
 954  * specified in FCP4 Chapter 11 (see www.t10.org).
 955  *
 956  * The variable fcp_offline_delay is specified in SECONDS.
 957  *
 958  * If we made this a static var then the user would not be able to
 959  * change it. This variable is set in fcp_attach().
 960  */
 961 unsigned int            fcp_offline_delay = FCP_OFFLINE_DELAY;
 962 
 963 static void             *fcp_softstate = NULL; /* for soft state */
 964 static uchar_t          fcp_oflag = FCP_IDLE; /* open flag */
 965 static kmutex_t         fcp_global_mutex;
 966 static kmutex_t         fcp_ioctl_mutex;
 967 static dev_info_t       *fcp_global_dip = NULL;
 968 static timeout_id_t     fcp_watchdog_id;
 969 const char              *fcp_lun_prop = "lun";
 970 const char              *fcp_sam_lun_prop = "sam-lun";
 971 const char              *fcp_target_prop = "target";
 972 /*
 973  * NOTE: consumers of "node-wwn" property include stmsboot in ON
 974  * consolidation.
 975  */
 976 const char              *fcp_node_wwn_prop = "node-wwn";
 977 const char              *fcp_port_wwn_prop = "port-wwn";
 978 const char              *fcp_conf_wwn_prop = "fc-port-wwn";
 979 const char              *fcp_obp_boot_wwn = "fc-boot-dev-portwwn";
 980 const char              *fcp_manual_config_only = "manual_configuration_only";
 981 const char              *fcp_init_port_prop = "initiator-port";
 982 const char              *fcp_tgt_port_prop = "target-port";
 983 const char              *fcp_lun_blacklist_prop = "pwwn-lun-blacklist";
 984 
 985 static struct fcp_port  *fcp_port_head = NULL;
 986 static ddi_eventcookie_t        fcp_insert_eid;
 987 static ddi_eventcookie_t        fcp_remove_eid;
 988 
 989 static ndi_event_definition_t   fcp_ndi_event_defs[] = {
 990         { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL },
 991         { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT }
 992 };
 993 
 994 /*
 995  * List of valid commands for the scsi_ioctl call
 996  */
 997 static uint8_t scsi_ioctl_list[] = {
 998         SCMD_INQUIRY,
 999         SCMD_REPORT_LUN,
1000         SCMD_READ_CAPACITY
1001 };
1002 
1003 /*
1004  * this is used to dummy up a report lun response for cases
1005  * where the target doesn't support it
1006  */
1007 static uchar_t fcp_dummy_lun[] = {
1008         0x00,           /* MSB length (length = no of luns * 8) */
1009         0x00,
1010         0x00,
1011         0x08,           /* LSB length */
1012         0x00,           /* MSB reserved */
1013         0x00,
1014         0x00,
1015         0x00,           /* LSB reserved */
1016         FCP_PD_ADDRESSING,
1017         0x00,           /* LUN is ZERO at the first level */
1018         0x00,
1019         0x00,           /* second level is zero */
1020         0x00,
1021         0x00,           /* third level is zero */
1022         0x00,
1023         0x00            /* fourth level is zero */
1024 };
1025 
1026 static uchar_t fcp_alpa_to_switch[] = {
1027         0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00,
1028         0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00,
1029         0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74,
1030         0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e,
1031         0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67,
1032         0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00,
1033         0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d,
1034         0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00,
1035         0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e,
1036         0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b,
1037         0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43,
1038         0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00,
1039         0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37,
1040         0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
1041         0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
1042         0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c,
1043         0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27,
1044         0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f,
1045         0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00,
1046         0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15,
1047         0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e,
1048         0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00,
1049         0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00,
1050         0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1051 };
1052 
1053 static caddr_t pid = "SESS01          ";
1054 
1055 #if     !defined(lint)
1056 
1057 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex,
1058     fcp_port::fcp_next fcp_watchdog_id))
1059 
1060 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time))
1061 
1062 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1063     fcp_insert_eid
1064     fcp_remove_eid
1065     fcp_watchdog_time))
1066 
1067 _NOTE(SCHEME_PROTECTS_DATA("Unshared",
1068     fcp_cb_ops
1069     fcp_ops
1070     callb_cpr))
1071 
1072 #endif /* lint */
1073 
1074 /*
1075  * This table is used to determine whether or not it's safe to copy in
1076  * the target node name for a lun.  Since all luns behind the same target
1077  * have the same wwnn, only tagets that do not support multiple luns are
1078  * eligible to be enumerated under mpxio if they aren't page83 compliant.
1079  */
1080 
1081 char *fcp_symmetric_disk_table[] = {
1082         "SEAGATE ST",
1083         "IBM     DDYFT",
1084         "SUNW    SUNWGS",       /* Daktari enclosure */
1085         "SUN     SENA",         /* SES device */
1086         "SUN     SESS01"        /* VICOM SVE box */
1087 };
1088 
1089 int fcp_symmetric_disk_table_size =
1090         sizeof (fcp_symmetric_disk_table)/sizeof (char *);
1091 
1092 /*
1093  * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel
1094  * will panic if you don't pass this in to the routine, this information.
1095  * Need to determine what the actual impact to the system is by providing
1096  * this information if any. Since dma allocation is done in pkt_init it may
1097  * not have any impact. These values are straight from the Writing Device
1098  * Driver manual.
1099  */
1100 static ddi_dma_attr_t pseudo_fca_dma_attr = {
1101         DMA_ATTR_V0,    /* ddi_dma_attr version */
1102         0,              /* low address */
1103         0xffffffff,     /* high address */
1104         0x00ffffff,     /* counter upper bound */
1105         1,              /* alignment requirements */
1106         0x3f,           /* burst sizes */
1107         1,              /* minimum DMA access */
1108         0xffffffff,     /* maximum DMA access */
1109         (1 << 24) - 1,    /* segment boundary restrictions */
1110         1,              /* scater/gather list length */
1111         512,            /* device granularity */
1112         0               /* DMA flags */
1113 };
1114 
1115 /*
1116  * The _init(9e) return value should be that of mod_install(9f). Under
1117  * some circumstances, a failure may not be related mod_install(9f) and
1118  * one would then require a return value to indicate the failure. Looking
1119  * at mod_install(9f), it is expected to return 0 for success and non-zero
1120  * for failure. mod_install(9f) for device drivers, further goes down the
1121  * calling chain and ends up in ddi_installdrv(), whose return values are
1122  * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the
1123  * calling chain of mod_install(9f) which return values like EINVAL and
1124  * in some even return -1.
1125  *
1126  * To work around the vagaries of the mod_install() calling chain, return
1127  * either 0 or ENODEV depending on the success or failure of mod_install()
1128  */
1129 int
1130 _init(void)
1131 {
1132         int rval;
1133 
1134         /*
1135          * Allocate soft state and prepare to do ddi_soft_state_zalloc()
1136          * before registering with the transport first.
1137          */
1138         if (ddi_soft_state_init(&fcp_softstate,
1139             sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) {
1140                 return (EINVAL);
1141         }
1142 
1143         mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL);
1144         mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL);
1145 
1146         if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) {
1147                 cmn_err(CE_WARN, "fcp: fc_ulp_add failed");
1148                 mutex_destroy(&fcp_global_mutex);
1149                 mutex_destroy(&fcp_ioctl_mutex);
1150                 ddi_soft_state_fini(&fcp_softstate);
1151                 return (ENODEV);
1152         }
1153 
1154         fcp_logq = fc_trace_alloc_logq(fcp_log_size);
1155 
1156         if ((rval = mod_install(&modlinkage)) != 0) {
1157                 fc_trace_free_logq(fcp_logq);
1158                 (void) fc_ulp_remove(&fcp_modinfo);
1159                 mutex_destroy(&fcp_global_mutex);
1160                 mutex_destroy(&fcp_ioctl_mutex);
1161                 ddi_soft_state_fini(&fcp_softstate);
1162                 rval = ENODEV;
1163         }
1164 
1165         return (rval);
1166 }
1167 
1168 
1169 /*
1170  * the system is done with us as a driver, so clean up
1171  */
1172 int
1173 _fini(void)
1174 {
1175         int rval;
1176 
1177         /*
1178          * don't start cleaning up until we know that the module remove
1179          * has worked  -- if this works, then we know that each instance
1180          * has successfully been DDI_DETACHed
1181          */
1182         if ((rval = mod_remove(&modlinkage)) != 0) {
1183                 return (rval);
1184         }
1185 
1186         (void) fc_ulp_remove(&fcp_modinfo);
1187 
1188         ddi_soft_state_fini(&fcp_softstate);
1189         mutex_destroy(&fcp_global_mutex);
1190         mutex_destroy(&fcp_ioctl_mutex);
1191         fc_trace_free_logq(fcp_logq);
1192 
1193         return (rval);
1194 }
1195 
1196 
1197 int
1198 _info(struct modinfo *modinfop)
1199 {
1200         return (mod_info(&modlinkage, modinfop));
1201 }
1202 
1203 
1204 /*
1205  * attach the module
1206  */
1207 static int
1208 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
1209 {
1210         int rval = DDI_SUCCESS;
1211 
1212         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1213             FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd);
1214 
1215         if (cmd == DDI_ATTACH) {
1216                 /* The FCP pseudo device is created here. */
1217                 mutex_enter(&fcp_global_mutex);
1218                 fcp_global_dip = devi;
1219                 mutex_exit(&fcp_global_mutex);
1220 
1221                 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR,
1222                     0, DDI_PSEUDO, 0) == DDI_SUCCESS) {
1223                         ddi_report_dev(fcp_global_dip);
1224                 } else {
1225                         cmn_err(CE_WARN, "FCP: Cannot create minor node");
1226                         mutex_enter(&fcp_global_mutex);
1227                         fcp_global_dip = NULL;
1228                         mutex_exit(&fcp_global_mutex);
1229 
1230                         rval = DDI_FAILURE;
1231                 }
1232                 /*
1233                  * We check the fcp_offline_delay property at this
1234                  * point. This variable is global for the driver,
1235                  * not specific to an instance.
1236                  *
1237                  * We do not recommend setting the value to less
1238                  * than 10 seconds (RA_TOV_els), or greater than
1239                  * 60 seconds.
1240                  */
1241                 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY,
1242                     devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
1243                     "fcp_offline_delay", FCP_OFFLINE_DELAY);
1244                 if ((fcp_offline_delay < 10) ||
1245                     (fcp_offline_delay > 60)) {
1246                         cmn_err(CE_WARN, "Setting fcp_offline_delay "
1247                             "to %d second(s). This is outside the "
1248                             "recommended range of 10..60 seconds.",
1249                             fcp_offline_delay);
1250                 }
1251         }
1252 
1253         return (rval);
1254 }
1255 
1256 
1257 /*ARGSUSED*/
1258 static int
1259 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
1260 {
1261         int     res = DDI_SUCCESS;
1262 
1263         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1264             FCP_BUF_LEVEL_8, 0,  "module detach: cmd=0x%x", cmd);
1265 
1266         if (cmd == DDI_DETACH) {
1267                 /*
1268                  * Check if there are active ports/threads. If there
1269                  * are any, we will fail, else we will succeed (there
1270                  * should not be much to clean up)
1271                  */
1272                 mutex_enter(&fcp_global_mutex);
1273                 FCP_DTRACE(fcp_logq, "fcp",
1274                     fcp_trace, FCP_BUF_LEVEL_8, 0,  "port_head=%p",
1275                     (void *) fcp_port_head);
1276 
1277                 if (fcp_port_head == NULL) {
1278                         ddi_remove_minor_node(fcp_global_dip, NULL);
1279                         fcp_global_dip = NULL;
1280                         mutex_exit(&fcp_global_mutex);
1281                 } else {
1282                         mutex_exit(&fcp_global_mutex);
1283                         res = DDI_FAILURE;
1284                 }
1285         }
1286         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
1287             FCP_BUF_LEVEL_8, 0,  "module detach returning %d", res);
1288 
1289         return (res);
1290 }
1291 
1292 
1293 /* ARGSUSED */
1294 static int
1295 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp)
1296 {
1297         if (otype != OTYP_CHR) {
1298                 return (EINVAL);
1299         }
1300 
1301         /*
1302          * Allow only root to talk;
1303          */
1304         if (drv_priv(credp)) {
1305                 return (EPERM);
1306         }
1307 
1308         mutex_enter(&fcp_global_mutex);
1309         if (fcp_oflag & FCP_EXCL) {
1310                 mutex_exit(&fcp_global_mutex);
1311                 return (EBUSY);
1312         }
1313 
1314         if (flag & FEXCL) {
1315                 if (fcp_oflag & FCP_OPEN) {
1316                         mutex_exit(&fcp_global_mutex);
1317                         return (EBUSY);
1318                 }
1319                 fcp_oflag |= FCP_EXCL;
1320         }
1321         fcp_oflag |= FCP_OPEN;
1322         mutex_exit(&fcp_global_mutex);
1323 
1324         return (0);
1325 }
1326 
1327 
1328 /* ARGSUSED */
1329 static int
1330 fcp_close(dev_t dev, int flag, int otype, cred_t *credp)
1331 {
1332         if (otype != OTYP_CHR) {
1333                 return (EINVAL);
1334         }
1335 
1336         mutex_enter(&fcp_global_mutex);
1337         if (!(fcp_oflag & FCP_OPEN)) {
1338                 mutex_exit(&fcp_global_mutex);
1339                 return (ENODEV);
1340         }
1341         fcp_oflag = FCP_IDLE;
1342         mutex_exit(&fcp_global_mutex);
1343 
1344         return (0);
1345 }
1346 
1347 
1348 /*
1349  * fcp_ioctl
1350  *      Entry point for the FCP ioctls
1351  *
1352  * Input:
1353  *      See ioctl(9E)
1354  *
1355  * Output:
1356  *      See ioctl(9E)
1357  *
1358  * Returns:
1359  *      See ioctl(9E)
1360  *
1361  * Context:
1362  *      Kernel context.
1363  */
1364 /* ARGSUSED */
1365 static int
1366 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp,
1367     int *rval)
1368 {
1369         int                     ret = 0;
1370 
1371         mutex_enter(&fcp_global_mutex);
1372         if (!(fcp_oflag & FCP_OPEN)) {
1373                 mutex_exit(&fcp_global_mutex);
1374                 return (ENXIO);
1375         }
1376         mutex_exit(&fcp_global_mutex);
1377 
1378         switch (cmd) {
1379         case FCP_TGT_INQUIRY:
1380         case FCP_TGT_CREATE:
1381         case FCP_TGT_DELETE:
1382                 ret = fcp_setup_device_data_ioctl(cmd,
1383                     (struct fcp_ioctl *)data, mode, rval);
1384                 break;
1385 
1386         case FCP_TGT_SEND_SCSI:
1387                 mutex_enter(&fcp_ioctl_mutex);
1388                 ret = fcp_setup_scsi_ioctl(
1389                     (struct fcp_scsi_cmd *)data, mode, rval);
1390                 mutex_exit(&fcp_ioctl_mutex);
1391                 break;
1392 
1393         case FCP_STATE_COUNT:
1394                 ret = fcp_get_statec_count((struct fcp_ioctl *)data,
1395                     mode, rval);
1396                 break;
1397         case FCP_GET_TARGET_MAPPINGS:
1398                 ret = fcp_get_target_mappings((struct fcp_ioctl *)data,
1399                     mode, rval);
1400                 break;
1401         default:
1402                 fcp_log(CE_WARN, NULL,
1403                     "!Invalid ioctl opcode = 0x%x", cmd);
1404                 ret     = EINVAL;
1405         }
1406 
1407         return (ret);
1408 }
1409 
1410 
1411 /*
1412  * fcp_setup_device_data_ioctl
1413  *      Setup handler for the "device data" style of
1414  *      ioctl for FCP.  See "fcp_util.h" for data structure
1415  *      definition.
1416  *
1417  * Input:
1418  *      cmd     = FCP ioctl command
1419  *      data    = ioctl data
1420  *      mode    = See ioctl(9E)
1421  *
1422  * Output:
1423  *      data    = ioctl data
1424  *      rval    = return value - see ioctl(9E)
1425  *
1426  * Returns:
1427  *      See ioctl(9E)
1428  *
1429  * Context:
1430  *      Kernel context.
1431  */
1432 /* ARGSUSED */
1433 static int
1434 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode,
1435     int *rval)
1436 {
1437         struct fcp_port *pptr;
1438         struct  device_data     *dev_data;
1439         uint32_t                link_cnt;
1440         la_wwn_t                *wwn_ptr = NULL;
1441         struct fcp_tgt          *ptgt = NULL;
1442         struct fcp_lun          *plun = NULL;
1443         int                     i, error;
1444         struct fcp_ioctl        fioctl;
1445 
1446 #ifdef  _MULTI_DATAMODEL
1447         switch (ddi_model_convert_from(mode & FMODELS)) {
1448         case DDI_MODEL_ILP32: {
1449                 struct fcp32_ioctl f32_ioctl;
1450 
1451                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1452                     sizeof (struct fcp32_ioctl), mode)) {
1453                         return (EFAULT);
1454                 }
1455                 fioctl.fp_minor = f32_ioctl.fp_minor;
1456                 fioctl.listlen = f32_ioctl.listlen;
1457                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1458                 break;
1459         }
1460         case DDI_MODEL_NONE:
1461                 if (ddi_copyin((void *)data, (void *)&fioctl,
1462                     sizeof (struct fcp_ioctl), mode)) {
1463                         return (EFAULT);
1464                 }
1465                 break;
1466         }
1467 
1468 #else   /* _MULTI_DATAMODEL */
1469         if (ddi_copyin((void *)data, (void *)&fioctl,
1470             sizeof (struct fcp_ioctl), mode)) {
1471                 return (EFAULT);
1472         }
1473 #endif  /* _MULTI_DATAMODEL */
1474 
1475         /*
1476          * Right now we can assume that the minor number matches with
1477          * this instance of fp. If this changes we will need to
1478          * revisit this logic.
1479          */
1480         mutex_enter(&fcp_global_mutex);
1481         pptr = fcp_port_head;
1482         while (pptr) {
1483                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1484                         break;
1485                 } else {
1486                         pptr = pptr->port_next;
1487                 }
1488         }
1489         mutex_exit(&fcp_global_mutex);
1490         if (pptr == NULL) {
1491                 return (ENXIO);
1492         }
1493         mutex_enter(&pptr->port_mutex);
1494 
1495 
1496         if ((dev_data = kmem_zalloc((sizeof (struct device_data)) *
1497             fioctl.listlen, KM_NOSLEEP)) == NULL) {
1498                 mutex_exit(&pptr->port_mutex);
1499                 return (ENOMEM);
1500         }
1501 
1502         if (ddi_copyin(fioctl.list, dev_data,
1503             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1504                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1505                 mutex_exit(&pptr->port_mutex);
1506                 return (EFAULT);
1507         }
1508         link_cnt = pptr->port_link_cnt;
1509 
1510         if (cmd == FCP_TGT_INQUIRY) {
1511                 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn);
1512                 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn,
1513                     sizeof (wwn_ptr->raw_wwn)) == 0) {
1514                         /* This ioctl is requesting INQ info of local HBA */
1515                         mutex_exit(&pptr->port_mutex);
1516                         dev_data[0].dev0_type = DTYPE_UNKNOWN;
1517                         dev_data[0].dev_status = 0;
1518                         if (ddi_copyout(dev_data, fioctl.list,
1519                             (sizeof (struct device_data)) * fioctl.listlen,
1520                             mode)) {
1521                                 kmem_free(dev_data,
1522                                     sizeof (*dev_data) * fioctl.listlen);
1523                                 return (EFAULT);
1524                         }
1525                         kmem_free(dev_data,
1526                             sizeof (*dev_data) * fioctl.listlen);
1527 #ifdef  _MULTI_DATAMODEL
1528                         switch (ddi_model_convert_from(mode & FMODELS)) {
1529                         case DDI_MODEL_ILP32: {
1530                                 struct fcp32_ioctl f32_ioctl;
1531                                 f32_ioctl.fp_minor = fioctl.fp_minor;
1532                                 f32_ioctl.listlen = fioctl.listlen;
1533                                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1534                                 if (ddi_copyout((void *)&f32_ioctl,
1535                                     (void *)data,
1536                                     sizeof (struct fcp32_ioctl), mode)) {
1537                                         return (EFAULT);
1538                                 }
1539                                 break;
1540                         }
1541                         case DDI_MODEL_NONE:
1542                                 if (ddi_copyout((void *)&fioctl, (void *)data,
1543                                     sizeof (struct fcp_ioctl), mode)) {
1544                                         return (EFAULT);
1545                                 }
1546                                 break;
1547                         }
1548 #else   /* _MULTI_DATAMODEL */
1549                         if (ddi_copyout((void *)&fioctl, (void *)data,
1550                             sizeof (struct fcp_ioctl), mode)) {
1551                                 return (EFAULT);
1552                         }
1553 #endif  /* _MULTI_DATAMODEL */
1554                         return (0);
1555                 }
1556         }
1557 
1558         if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) {
1559                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1560                 mutex_exit(&pptr->port_mutex);
1561                 return (ENXIO);
1562         }
1563 
1564         for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt);
1565             i++) {
1566                 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn);
1567 
1568                 dev_data[i].dev0_type = DTYPE_UNKNOWN;
1569 
1570 
1571                 dev_data[i].dev_status = ENXIO;
1572 
1573                 if ((ptgt = fcp_lookup_target(pptr,
1574                     (uchar_t *)wwn_ptr)) == NULL) {
1575                         mutex_exit(&pptr->port_mutex);
1576                         if (fc_ulp_get_remote_port(pptr->port_fp_handle,
1577                             wwn_ptr, &error, 0) == NULL) {
1578                                 dev_data[i].dev_status = ENODEV;
1579                                 mutex_enter(&pptr->port_mutex);
1580                                 continue;
1581                         } else {
1582 
1583                                 dev_data[i].dev_status = EAGAIN;
1584 
1585                                 mutex_enter(&pptr->port_mutex);
1586                                 continue;
1587                         }
1588                 } else {
1589                         mutex_enter(&ptgt->tgt_mutex);
1590                         if (ptgt->tgt_state & (FCP_TGT_MARK |
1591                             FCP_TGT_BUSY)) {
1592                                 dev_data[i].dev_status = EAGAIN;
1593                                 mutex_exit(&ptgt->tgt_mutex);
1594                                 continue;
1595                         }
1596 
1597                         if (ptgt->tgt_state & FCP_TGT_OFFLINE) {
1598                                 if (ptgt->tgt_icap && !ptgt->tgt_tcap) {
1599                                         dev_data[i].dev_status = ENOTSUP;
1600                                 } else {
1601                                         dev_data[i].dev_status = ENXIO;
1602                                 }
1603                                 mutex_exit(&ptgt->tgt_mutex);
1604                                 continue;
1605                         }
1606 
1607                         switch (cmd) {
1608                         case FCP_TGT_INQUIRY:
1609                                 /*
1610                                  * The reason we give device type of
1611                                  * lun 0 only even though in some
1612                                  * cases(like maxstrat) lun 0 device
1613                                  * type may be 0x3f(invalid) is that
1614                                  * for bridge boxes target will appear
1615                                  * as luns and the first lun could be
1616                                  * a device that utility may not care
1617                                  * about (like a tape device).
1618                                  */
1619                                 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt;
1620                                 dev_data[i].dev_status = 0;
1621                                 mutex_exit(&ptgt->tgt_mutex);
1622 
1623                                 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
1624                                         dev_data[i].dev0_type = DTYPE_UNKNOWN;
1625                                 } else {
1626                                         dev_data[i].dev0_type = plun->lun_type;
1627                                 }
1628                                 mutex_enter(&ptgt->tgt_mutex);
1629                                 break;
1630 
1631                         case FCP_TGT_CREATE:
1632                                 mutex_exit(&ptgt->tgt_mutex);
1633                                 mutex_exit(&pptr->port_mutex);
1634 
1635                                 /*
1636                                  * serialize state change call backs.
1637                                  * only one call back will be handled
1638                                  * at a time.
1639                                  */
1640                                 mutex_enter(&fcp_global_mutex);
1641                                 if (fcp_oflag & FCP_BUSY) {
1642                                         mutex_exit(&fcp_global_mutex);
1643                                         if (dev_data) {
1644                                                 kmem_free(dev_data,
1645                                                     sizeof (*dev_data) *
1646                                                     fioctl.listlen);
1647                                         }
1648                                         return (EBUSY);
1649                                 }
1650                                 fcp_oflag |= FCP_BUSY;
1651                                 mutex_exit(&fcp_global_mutex);
1652 
1653                                 dev_data[i].dev_status =
1654                                     fcp_create_on_demand(pptr,
1655                                     wwn_ptr->raw_wwn);
1656 
1657                                 if (dev_data[i].dev_status != 0) {
1658                                         char    buf[25];
1659 
1660                                         for (i = 0; i < FC_WWN_SIZE; i++) {
1661                                                 (void) sprintf(&buf[i << 1],
1662                                                     "%02x",
1663                                                     wwn_ptr->raw_wwn[i]);
1664                                         }
1665 
1666                                         fcp_log(CE_WARN, pptr->port_dip,
1667                                             "!Failed to create nodes for"
1668                                             " pwwn=%s; error=%x", buf,
1669                                             dev_data[i].dev_status);
1670                                 }
1671 
1672                                 /* allow state change call backs again */
1673                                 mutex_enter(&fcp_global_mutex);
1674                                 fcp_oflag &= ~FCP_BUSY;
1675                                 mutex_exit(&fcp_global_mutex);
1676 
1677                                 mutex_enter(&pptr->port_mutex);
1678                                 mutex_enter(&ptgt->tgt_mutex);
1679 
1680                                 break;
1681 
1682                         case FCP_TGT_DELETE:
1683                                 break;
1684 
1685                         default:
1686                                 fcp_log(CE_WARN, pptr->port_dip,
1687                                     "!Invalid device data ioctl "
1688                                     "opcode = 0x%x", cmd);
1689                         }
1690                         mutex_exit(&ptgt->tgt_mutex);
1691                 }
1692         }
1693         mutex_exit(&pptr->port_mutex);
1694 
1695         if (ddi_copyout(dev_data, fioctl.list,
1696             (sizeof (struct device_data)) * fioctl.listlen, mode)) {
1697                 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1698                 return (EFAULT);
1699         }
1700         kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen);
1701 
1702 #ifdef  _MULTI_DATAMODEL
1703         switch (ddi_model_convert_from(mode & FMODELS)) {
1704         case DDI_MODEL_ILP32: {
1705                 struct fcp32_ioctl f32_ioctl;
1706 
1707                 f32_ioctl.fp_minor = fioctl.fp_minor;
1708                 f32_ioctl.listlen = fioctl.listlen;
1709                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1710                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1711                     sizeof (struct fcp32_ioctl), mode)) {
1712                         return (EFAULT);
1713                 }
1714                 break;
1715         }
1716         case DDI_MODEL_NONE:
1717                 if (ddi_copyout((void *)&fioctl, (void *)data,
1718                     sizeof (struct fcp_ioctl), mode)) {
1719                         return (EFAULT);
1720                 }
1721                 break;
1722         }
1723 #else   /* _MULTI_DATAMODEL */
1724 
1725         if (ddi_copyout((void *)&fioctl, (void *)data,
1726             sizeof (struct fcp_ioctl), mode)) {
1727                 return (EFAULT);
1728         }
1729 #endif  /* _MULTI_DATAMODEL */
1730 
1731         return (0);
1732 }
1733 
1734 /*
1735  * Fetch the target mappings (path, etc.) for all LUNs
1736  * on this port.
1737  */
1738 /* ARGSUSED */
1739 static int
1740 fcp_get_target_mappings(struct fcp_ioctl *data,
1741     int mode, int *rval)
1742 {
1743         struct fcp_port     *pptr;
1744         fc_hba_target_mappings_t    *mappings;
1745         fc_hba_mapping_entry_t      *map;
1746         struct fcp_tgt      *ptgt = NULL;
1747         struct fcp_lun      *plun = NULL;
1748         int                         i, mapIndex, mappingSize;
1749         int                         listlen;
1750         struct fcp_ioctl            fioctl;
1751         char                        *path;
1752         fcp_ent_addr_t              sam_lun_addr;
1753 
1754 #ifdef  _MULTI_DATAMODEL
1755         switch (ddi_model_convert_from(mode & FMODELS)) {
1756         case DDI_MODEL_ILP32: {
1757                 struct fcp32_ioctl f32_ioctl;
1758 
1759                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
1760                     sizeof (struct fcp32_ioctl), mode)) {
1761                         return (EFAULT);
1762                 }
1763                 fioctl.fp_minor = f32_ioctl.fp_minor;
1764                 fioctl.listlen = f32_ioctl.listlen;
1765                 fioctl.list = (caddr_t)(long)f32_ioctl.list;
1766                 break;
1767         }
1768         case DDI_MODEL_NONE:
1769                 if (ddi_copyin((void *)data, (void *)&fioctl,
1770                     sizeof (struct fcp_ioctl), mode)) {
1771                         return (EFAULT);
1772                 }
1773                 break;
1774         }
1775 
1776 #else   /* _MULTI_DATAMODEL */
1777         if (ddi_copyin((void *)data, (void *)&fioctl,
1778             sizeof (struct fcp_ioctl), mode)) {
1779                 return (EFAULT);
1780         }
1781 #endif  /* _MULTI_DATAMODEL */
1782 
1783         /*
1784          * Right now we can assume that the minor number matches with
1785          * this instance of fp. If this changes we will need to
1786          * revisit this logic.
1787          */
1788         mutex_enter(&fcp_global_mutex);
1789         pptr = fcp_port_head;
1790         while (pptr) {
1791                 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) {
1792                         break;
1793                 } else {
1794                         pptr = pptr->port_next;
1795                 }
1796         }
1797         mutex_exit(&fcp_global_mutex);
1798         if (pptr == NULL) {
1799                 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d",
1800                     fioctl.fp_minor);
1801                 return (ENXIO);
1802         }
1803 
1804 
1805         /* We use listlen to show the total buffer size */
1806         mappingSize = fioctl.listlen;
1807 
1808         /* Now calculate how many mapping entries will fit */
1809         listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t)
1810             - sizeof (fc_hba_target_mappings_t);
1811         if (listlen <= 0) {
1812                 cmn_err(CE_NOTE, "target mappings: Insufficient buffer");
1813                 return (ENXIO);
1814         }
1815         listlen = listlen / sizeof (fc_hba_mapping_entry_t);
1816 
1817         if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) {
1818                 return (ENOMEM);
1819         }
1820         mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION;
1821 
1822         /* Now get to work */
1823         mapIndex = 0;
1824 
1825         mutex_enter(&pptr->port_mutex);
1826         /* Loop through all targets on this port */
1827         for (i = 0; i < FCP_NUM_HASH; i++) {
1828                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
1829                     ptgt = ptgt->tgt_next) {
1830 
1831                         mutex_enter(&ptgt->tgt_mutex);
1832 
1833                         /* Loop through all LUNs on this target */
1834                         for (plun = ptgt->tgt_lun; plun != NULL;
1835                             plun = plun->lun_next) {
1836                                 if (plun->lun_state & FCP_LUN_OFFLINE) {
1837                                         continue;
1838                                 }
1839 
1840                                 path = fcp_get_lun_path(plun);
1841                                 if (path == NULL) {
1842                                         continue;
1843                                 }
1844 
1845                                 if (mapIndex >= listlen) {
1846                                         mapIndex ++;
1847                                         kmem_free(path, MAXPATHLEN);
1848                                         continue;
1849                                 }
1850                                 map = &mappings->entries[mapIndex++];
1851                                 bcopy(path, map->targetDriver,
1852                                     sizeof (map->targetDriver));
1853                                 map->d_id = ptgt->tgt_d_id;
1854                                 map->busNumber = 0;
1855                                 map->targetNumber = ptgt->tgt_d_id;
1856                                 map->osLUN = plun->lun_num;
1857 
1858                                 /*
1859                                  * We had swapped lun when we stored it in
1860                                  * lun_addr. We need to swap it back before
1861                                  * returning it to user land
1862                                  */
1863 
1864                                 sam_lun_addr.ent_addr_0 =
1865                                     BE_16(plun->lun_addr.ent_addr_0);
1866                                 sam_lun_addr.ent_addr_1 =
1867                                     BE_16(plun->lun_addr.ent_addr_1);
1868                                 sam_lun_addr.ent_addr_2 =
1869                                     BE_16(plun->lun_addr.ent_addr_2);
1870                                 sam_lun_addr.ent_addr_3 =
1871                                     BE_16(plun->lun_addr.ent_addr_3);
1872 
1873                                 bcopy(&sam_lun_addr, &map->samLUN,
1874                                     FCP_LUN_SIZE);
1875                                 bcopy(ptgt->tgt_node_wwn.raw_wwn,
1876                                     map->NodeWWN.raw_wwn, sizeof (la_wwn_t));
1877                                 bcopy(ptgt->tgt_port_wwn.raw_wwn,
1878                                     map->PortWWN.raw_wwn, sizeof (la_wwn_t));
1879 
1880                                 if (plun->lun_guid) {
1881 
1882                                         /* convert ascii wwn to bytes */
1883                                         fcp_ascii_to_wwn(plun->lun_guid,
1884                                             map->guid, sizeof (map->guid));
1885 
1886                                         if ((sizeof (map->guid)) <
1887                                             plun->lun_guid_size / 2) {
1888                                                 cmn_err(CE_WARN,
1889                                                     "fcp_get_target_mappings:"
1890                                                     "guid copy space "
1891                                                     "insufficient."
1892                                                     "Copy Truncation - "
1893                                                     "available %d; need %d",
1894                                                     (int)sizeof (map->guid),
1895                                                     (int)
1896                                                     plun->lun_guid_size / 2);
1897                                         }
1898                                 }
1899                                 kmem_free(path, MAXPATHLEN);
1900                         }
1901                         mutex_exit(&ptgt->tgt_mutex);
1902                 }
1903         }
1904         mutex_exit(&pptr->port_mutex);
1905         mappings->numLuns = mapIndex;
1906 
1907         if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) {
1908                 kmem_free(mappings, mappingSize);
1909                 return (EFAULT);
1910         }
1911         kmem_free(mappings, mappingSize);
1912 
1913 #ifdef  _MULTI_DATAMODEL
1914         switch (ddi_model_convert_from(mode & FMODELS)) {
1915         case DDI_MODEL_ILP32: {
1916                 struct fcp32_ioctl f32_ioctl;
1917 
1918                 f32_ioctl.fp_minor = fioctl.fp_minor;
1919                 f32_ioctl.listlen = fioctl.listlen;
1920                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
1921                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
1922                     sizeof (struct fcp32_ioctl), mode)) {
1923                         return (EFAULT);
1924                 }
1925                 break;
1926         }
1927         case DDI_MODEL_NONE:
1928                 if (ddi_copyout((void *)&fioctl, (void *)data,
1929                     sizeof (struct fcp_ioctl), mode)) {
1930                         return (EFAULT);
1931                 }
1932                 break;
1933         }
1934 #else   /* _MULTI_DATAMODEL */
1935 
1936         if (ddi_copyout((void *)&fioctl, (void *)data,
1937             sizeof (struct fcp_ioctl), mode)) {
1938                 return (EFAULT);
1939         }
1940 #endif  /* _MULTI_DATAMODEL */
1941 
1942         return (0);
1943 }
1944 
1945 /*
1946  * fcp_setup_scsi_ioctl
1947  *      Setup handler for the "scsi passthru" style of
1948  *      ioctl for FCP.  See "fcp_util.h" for data structure
1949  *      definition.
1950  *
1951  * Input:
1952  *      u_fscsi = ioctl data (user address space)
1953  *      mode    = See ioctl(9E)
1954  *
1955  * Output:
1956  *      u_fscsi = ioctl data (user address space)
1957  *      rval    = return value - see ioctl(9E)
1958  *
1959  * Returns:
1960  *      0       = OK
1961  *      EAGAIN  = See errno.h
1962  *      EBUSY   = See errno.h
1963  *      EFAULT  = See errno.h
1964  *      EINTR   = See errno.h
1965  *      EINVAL  = See errno.h
1966  *      EIO     = See errno.h
1967  *      ENOMEM  = See errno.h
1968  *      ENXIO   = See errno.h
1969  *
1970  * Context:
1971  *      Kernel context.
1972  */
1973 /* ARGSUSED */
1974 static int
1975 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi,
1976     int mode, int *rval)
1977 {
1978         int                     ret             = 0;
1979         int                     temp_ret;
1980         caddr_t                 k_cdbbufaddr    = NULL;
1981         caddr_t                 k_bufaddr       = NULL;
1982         caddr_t                 k_rqbufaddr     = NULL;
1983         caddr_t                 u_cdbbufaddr;
1984         caddr_t                 u_bufaddr;
1985         caddr_t                 u_rqbufaddr;
1986         struct fcp_scsi_cmd     k_fscsi;
1987 
1988         /*
1989          * Get fcp_scsi_cmd array element from user address space
1990          */
1991         if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode))
1992             != 0) {
1993                 return (ret);
1994         }
1995 
1996 
1997         /*
1998          * Even though kmem_alloc() checks the validity of the
1999          * buffer length, this check is needed when the
2000          * kmem_flags set and the zero buffer length is passed.
2001          */
2002         if ((k_fscsi.scsi_cdblen <= 0) ||
2003             (k_fscsi.scsi_buflen <= 0) ||
2004             (k_fscsi.scsi_rqlen <= 0)) {
2005                 return (EINVAL);
2006         }
2007 
2008         /*
2009          * Allocate data for fcp_scsi_cmd pointer fields
2010          */
2011         if (ret == 0) {
2012                 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP);
2013                 k_bufaddr    = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP);
2014                 k_rqbufaddr  = kmem_alloc(k_fscsi.scsi_rqlen,  KM_NOSLEEP);
2015 
2016                 if (k_cdbbufaddr == NULL ||
2017                     k_bufaddr    == NULL ||
2018                     k_rqbufaddr  == NULL) {
2019                         ret = ENOMEM;
2020                 }
2021         }
2022 
2023         /*
2024          * Get fcp_scsi_cmd pointer fields from user
2025          * address space
2026          */
2027         if (ret == 0) {
2028                 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr;
2029                 u_bufaddr    = k_fscsi.scsi_bufaddr;
2030                 u_rqbufaddr  = k_fscsi.scsi_rqbufaddr;
2031 
2032                 if (ddi_copyin(u_cdbbufaddr,
2033                     k_cdbbufaddr,
2034                     k_fscsi.scsi_cdblen,
2035                     mode)) {
2036                         ret = EFAULT;
2037                 } else if (ddi_copyin(u_bufaddr,
2038                     k_bufaddr,
2039                     k_fscsi.scsi_buflen,
2040                     mode)) {
2041                         ret = EFAULT;
2042                 } else if (ddi_copyin(u_rqbufaddr,
2043                     k_rqbufaddr,
2044                     k_fscsi.scsi_rqlen,
2045                     mode)) {
2046                         ret = EFAULT;
2047                 }
2048         }
2049 
2050         /*
2051          * Send scsi command (blocking)
2052          */
2053         if (ret == 0) {
2054                 /*
2055                  * Prior to sending the scsi command, the
2056                  * fcp_scsi_cmd data structure must contain kernel,
2057                  * not user, addresses.
2058                  */
2059                 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr;
2060                 k_fscsi.scsi_bufaddr    = k_bufaddr;
2061                 k_fscsi.scsi_rqbufaddr  = k_rqbufaddr;
2062 
2063                 ret = fcp_send_scsi_ioctl(&k_fscsi);
2064 
2065                 /*
2066                  * After sending the scsi command, the
2067                  * fcp_scsi_cmd data structure must contain user,
2068                  * not kernel, addresses.
2069                  */
2070                 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr;
2071                 k_fscsi.scsi_bufaddr    = u_bufaddr;
2072                 k_fscsi.scsi_rqbufaddr  = u_rqbufaddr;
2073         }
2074 
2075         /*
2076          * Put fcp_scsi_cmd pointer fields to user address space
2077          */
2078         if (ret == 0) {
2079                 if (ddi_copyout(k_cdbbufaddr,
2080                     u_cdbbufaddr,
2081                     k_fscsi.scsi_cdblen,
2082                     mode)) {
2083                         ret = EFAULT;
2084                 } else if (ddi_copyout(k_bufaddr,
2085                     u_bufaddr,
2086                     k_fscsi.scsi_buflen,
2087                     mode)) {
2088                         ret = EFAULT;
2089                 } else if (ddi_copyout(k_rqbufaddr,
2090                     u_rqbufaddr,
2091                     k_fscsi.scsi_rqlen,
2092                     mode)) {
2093                         ret = EFAULT;
2094                 }
2095         }
2096 
2097         /*
2098          * Free data for fcp_scsi_cmd pointer fields
2099          */
2100         if (k_cdbbufaddr != NULL) {
2101                 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen);
2102         }
2103         if (k_bufaddr != NULL) {
2104                 kmem_free(k_bufaddr, k_fscsi.scsi_buflen);
2105         }
2106         if (k_rqbufaddr != NULL) {
2107                 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen);
2108         }
2109 
2110         /*
2111          * Put fcp_scsi_cmd array element to user address space
2112          */
2113         temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode);
2114         if (temp_ret != 0) {
2115                 ret = temp_ret;
2116         }
2117 
2118         /*
2119          * Return status
2120          */
2121         return (ret);
2122 }
2123 
2124 
2125 /*
2126  * fcp_copyin_scsi_cmd
2127  *      Copy in fcp_scsi_cmd data structure from user address space.
2128  *      The data may be in 32 bit or 64 bit modes.
2129  *
2130  * Input:
2131  *      base_addr       = from address (user address space)
2132  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2133  *
2134  * Output:
2135  *      fscsi           = to address (kernel address space)
2136  *
2137  * Returns:
2138  *      0       = OK
2139  *      EFAULT  = Error
2140  *
2141  * Context:
2142  *      Kernel context.
2143  */
2144 static int
2145 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode)
2146 {
2147 #ifdef  _MULTI_DATAMODEL
2148         struct fcp32_scsi_cmd   f32scsi;
2149 
2150         switch (ddi_model_convert_from(mode & FMODELS)) {
2151         case DDI_MODEL_ILP32:
2152                 /*
2153                  * Copy data from user address space
2154                  */
2155                 if (ddi_copyin((void *)base_addr,
2156                     &f32scsi,
2157                     sizeof (struct fcp32_scsi_cmd),
2158                     mode)) {
2159                         return (EFAULT);
2160                 }
2161                 /*
2162                  * Convert from 32 bit to 64 bit
2163                  */
2164                 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi);
2165                 break;
2166         case DDI_MODEL_NONE:
2167                 /*
2168                  * Copy data from user address space
2169                  */
2170                 if (ddi_copyin((void *)base_addr,
2171                     fscsi,
2172                     sizeof (struct fcp_scsi_cmd),
2173                     mode)) {
2174                         return (EFAULT);
2175                 }
2176                 break;
2177         }
2178 #else   /* _MULTI_DATAMODEL */
2179         /*
2180          * Copy data from user address space
2181          */
2182         if (ddi_copyin((void *)base_addr,
2183             fscsi,
2184             sizeof (struct fcp_scsi_cmd),
2185             mode)) {
2186                 return (EFAULT);
2187         }
2188 #endif  /* _MULTI_DATAMODEL */
2189 
2190         return (0);
2191 }
2192 
2193 
2194 /*
2195  * fcp_copyout_scsi_cmd
2196  *      Copy out fcp_scsi_cmd data structure to user address space.
2197  *      The data may be in 32 bit or 64 bit modes.
2198  *
2199  * Input:
2200  *      fscsi           = to address (kernel address space)
2201  *      mode            = See ioctl(9E) and ddi_copyin(9F)
2202  *
2203  * Output:
2204  *      base_addr       = from address (user address space)
2205  *
2206  * Returns:
2207  *      0       = OK
2208  *      EFAULT  = Error
2209  *
2210  * Context:
2211  *      Kernel context.
2212  */
2213 static int
2214 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode)
2215 {
2216 #ifdef  _MULTI_DATAMODEL
2217         struct fcp32_scsi_cmd   f32scsi;
2218 
2219         switch (ddi_model_convert_from(mode & FMODELS)) {
2220         case DDI_MODEL_ILP32:
2221                 /*
2222                  * Convert from 64 bit to 32 bit
2223                  */
2224                 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi);
2225                 /*
2226                  * Copy data to user address space
2227                  */
2228                 if (ddi_copyout(&f32scsi,
2229                     (void *)base_addr,
2230                     sizeof (struct fcp32_scsi_cmd),
2231                     mode)) {
2232                         return (EFAULT);
2233                 }
2234                 break;
2235         case DDI_MODEL_NONE:
2236                 /*
2237                  * Copy data to user address space
2238                  */
2239                 if (ddi_copyout(fscsi,
2240                     (void *)base_addr,
2241                     sizeof (struct fcp_scsi_cmd),
2242                     mode)) {
2243                         return (EFAULT);
2244                 }
2245                 break;
2246         }
2247 #else   /* _MULTI_DATAMODEL */
2248         /*
2249          * Copy data to user address space
2250          */
2251         if (ddi_copyout(fscsi,
2252             (void *)base_addr,
2253             sizeof (struct fcp_scsi_cmd),
2254             mode)) {
2255                 return (EFAULT);
2256         }
2257 #endif  /* _MULTI_DATAMODEL */
2258 
2259         return (0);
2260 }
2261 
2262 
2263 /*
2264  * fcp_send_scsi_ioctl
2265  *      Sends the SCSI command in blocking mode.
2266  *
2267  * Input:
2268  *      fscsi           = SCSI command data structure
2269  *
2270  * Output:
2271  *      fscsi           = SCSI command data structure
2272  *
2273  * Returns:
2274  *      0       = OK
2275  *      EAGAIN  = See errno.h
2276  *      EBUSY   = See errno.h
2277  *      EINTR   = See errno.h
2278  *      EINVAL  = See errno.h
2279  *      EIO     = See errno.h
2280  *      ENOMEM  = See errno.h
2281  *      ENXIO   = See errno.h
2282  *
2283  * Context:
2284  *      Kernel context.
2285  */
2286 static int
2287 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi)
2288 {
2289         struct fcp_lun  *plun           = NULL;
2290         struct fcp_port *pptr           = NULL;
2291         struct fcp_tgt  *ptgt           = NULL;
2292         fc_packet_t             *fpkt           = NULL;
2293         struct fcp_ipkt *icmd           = NULL;
2294         int                     target_created  = FALSE;
2295         fc_frame_hdr_t          *hp;
2296         struct fcp_cmd          fcp_cmd;
2297         struct fcp_cmd          *fcmd;
2298         union scsi_cdb          *scsi_cdb;
2299         la_wwn_t                *wwn_ptr;
2300         int                     nodma;
2301         struct fcp_rsp          *rsp;
2302         struct fcp_rsp_info     *rsp_info;
2303         caddr_t                 rsp_sense;
2304         int                     buf_len;
2305         int                     info_len;
2306         int                     sense_len;
2307         struct scsi_extended_sense      *sense_to = NULL;
2308         timeout_id_t            tid;
2309         uint8_t                 reconfig_lun = FALSE;
2310         uint8_t                 reconfig_pending = FALSE;
2311         uint8_t                 scsi_cmd;
2312         int                     rsp_len;
2313         int                     cmd_index;
2314         int                     fc_status;
2315         int                     pkt_state;
2316         int                     pkt_action;
2317         int                     pkt_reason;
2318         int                     ret, xport_retval = ~FC_SUCCESS;
2319         int                     lcount;
2320         int                     tcount;
2321         int                     reconfig_status;
2322         int                     port_busy = FALSE;
2323         uchar_t                 *lun_string;
2324 
2325         /*
2326          * Check valid SCSI command
2327          */
2328         scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0];
2329         ret = EINVAL;
2330         for (cmd_index = 0;
2331             cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) &&
2332             ret != 0;
2333             cmd_index++) {
2334                 /*
2335                  * First byte of CDB is the SCSI command
2336                  */
2337                 if (scsi_ioctl_list[cmd_index] == scsi_cmd) {
2338                         ret = 0;
2339                 }
2340         }
2341 
2342         /*
2343          * Check inputs
2344          */
2345         if (fscsi->scsi_flags != FCP_SCSI_READ) {
2346                 ret = EINVAL;
2347         } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) {
2348                 /* no larger than */
2349                 ret = EINVAL;
2350         }
2351 
2352 
2353         /*
2354          * Find FC port
2355          */
2356         if (ret == 0) {
2357                 /*
2358                  * Acquire global mutex
2359                  */
2360                 mutex_enter(&fcp_global_mutex);
2361 
2362                 pptr = fcp_port_head;
2363                 while (pptr) {
2364                         if (pptr->port_instance ==
2365                             (uint32_t)fscsi->scsi_fc_port_num) {
2366                                 break;
2367                         } else {
2368                                 pptr = pptr->port_next;
2369                         }
2370                 }
2371 
2372                 if (pptr == NULL) {
2373                         ret = ENXIO;
2374                 } else {
2375                         /*
2376                          * fc_ulp_busy_port can raise power
2377                          *  so, we must not hold any mutexes involved in PM
2378                          */
2379                         mutex_exit(&fcp_global_mutex);
2380                         ret = fc_ulp_busy_port(pptr->port_fp_handle);
2381                 }
2382 
2383                 if (ret == 0) {
2384 
2385                         /* remember port is busy, so we will release later */
2386                         port_busy = TRUE;
2387 
2388                         /*
2389                          * If there is a reconfiguration in progress, wait
2390                          * for it to complete.
2391                          */
2392 
2393                         fcp_reconfig_wait(pptr);
2394 
2395                         /* reacquire mutexes in order */
2396                         mutex_enter(&fcp_global_mutex);
2397                         mutex_enter(&pptr->port_mutex);
2398 
2399                         /*
2400                          * Will port accept DMA?
2401                          */
2402                         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE)
2403                             ? 1 : 0;
2404 
2405                         /*
2406                          * If init or offline, device not known
2407                          *
2408                          * If we are discovering (onlining), we can
2409                          * NOT obviously provide reliable data about
2410                          * devices until it is complete
2411                          */
2412                         if (pptr->port_state &     (FCP_STATE_INIT |
2413                             FCP_STATE_OFFLINE)) {
2414                                 ret = ENXIO;
2415                         } else if (pptr->port_state & FCP_STATE_ONLINING) {
2416                                 ret = EBUSY;
2417                         } else {
2418                                 /*
2419                                  * Find target from pwwn
2420                                  *
2421                                  * The wwn must be put into a local
2422                                  * variable to ensure alignment.
2423                                  */
2424                                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2425                                 ptgt = fcp_lookup_target(pptr,
2426                                     (uchar_t *)wwn_ptr);
2427 
2428                                 /*
2429                                  * If target not found,
2430                                  */
2431                                 if (ptgt == NULL) {
2432                                         /*
2433                                          * Note: Still have global &
2434                                          * port mutexes
2435                                          */
2436                                         mutex_exit(&pptr->port_mutex);
2437                                         ptgt = fcp_port_create_tgt(pptr,
2438                                             wwn_ptr, &ret, &fc_status,
2439                                             &pkt_state, &pkt_action,
2440                                             &pkt_reason);
2441                                         mutex_enter(&pptr->port_mutex);
2442 
2443                                         fscsi->scsi_fc_status  = fc_status;
2444                                         fscsi->scsi_pkt_state  =
2445                                             (uchar_t)pkt_state;
2446                                         fscsi->scsi_pkt_reason = pkt_reason;
2447                                         fscsi->scsi_pkt_action =
2448                                             (uchar_t)pkt_action;
2449 
2450                                         if (ptgt != NULL) {
2451                                                 target_created = TRUE;
2452                                         } else if (ret == 0) {
2453                                                 ret = ENOMEM;
2454                                         }
2455                                 }
2456 
2457                                 if (ret == 0) {
2458                                         /*
2459                                          * Acquire target
2460                                          */
2461                                         mutex_enter(&ptgt->tgt_mutex);
2462 
2463                                         /*
2464                                          * If target is mark or busy,
2465                                          * then target can not be used
2466                                          */
2467                                         if (ptgt->tgt_state &
2468                                             (FCP_TGT_MARK |
2469                                             FCP_TGT_BUSY)) {
2470                                                 ret = EBUSY;
2471                                         } else {
2472                                                 /*
2473                                                  * Mark target as busy
2474                                                  */
2475                                                 ptgt->tgt_state |=
2476                                                     FCP_TGT_BUSY;
2477                                         }
2478 
2479                                         /*
2480                                          * Release target
2481                                          */
2482                                         lcount = pptr->port_link_cnt;
2483                                         tcount = ptgt->tgt_change_cnt;
2484                                         mutex_exit(&ptgt->tgt_mutex);
2485                                 }
2486                         }
2487 
2488                         /*
2489                          * Release port
2490                          */
2491                         mutex_exit(&pptr->port_mutex);
2492                 }
2493 
2494                 /*
2495                  * Release global mutex
2496                  */
2497                 mutex_exit(&fcp_global_mutex);
2498         }
2499 
2500         if (ret == 0) {
2501                 uint64_t belun = BE_64(fscsi->scsi_lun);
2502 
2503                 /*
2504                  * If it's a target device, find lun from pwwn
2505                  * The wwn must be put into a local
2506                  * variable to ensure alignment.
2507                  */
2508                 mutex_enter(&pptr->port_mutex);
2509                 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn);
2510                 if (!ptgt->tgt_tcap && ptgt->tgt_icap) {
2511                         /* this is not a target */
2512                         fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT;
2513                         ret = ENXIO;
2514                 } else if ((belun << 16) != 0) {
2515                         /*
2516                          * Since fcp only support PD and LU addressing method
2517                          * so far, the last 6 bytes of a valid LUN are expected
2518                          * to be filled with 00h.
2519                          */
2520                         fscsi->scsi_fc_status = FC_INVALID_LUN;
2521                         cmn_err(CE_WARN, "fcp: Unsupported LUN addressing"
2522                             " method 0x%02x with LUN number 0x%016" PRIx64,
2523                             (uint8_t)(belun >> 62), belun);
2524                         ret = ENXIO;
2525                 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr,
2526                     (uint16_t)((belun >> 48) & 0x3fff))) == NULL) {
2527                         /*
2528                          * This is a SCSI target, but no LUN at this
2529                          * address.
2530                          *
2531                          * In the future, we may want to send this to
2532                          * the target, and let it respond
2533                          * appropriately
2534                          */
2535                         ret = ENXIO;
2536                 }
2537                 mutex_exit(&pptr->port_mutex);
2538         }
2539 
2540         /*
2541          * Finished grabbing external resources
2542          * Allocate internal packet (icmd)
2543          */
2544         if (ret == 0) {
2545                 /*
2546                  * Calc rsp len assuming rsp info included
2547                  */
2548                 rsp_len = sizeof (struct fcp_rsp) +
2549                     sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen;
2550 
2551                 icmd = fcp_icmd_alloc(pptr, ptgt,
2552                     sizeof (struct fcp_cmd),
2553                     rsp_len,
2554                     fscsi->scsi_buflen,
2555                     nodma,
2556                     lcount,                     /* ipkt_link_cnt */
2557                     tcount,                     /* ipkt_change_cnt */
2558                     0,                          /* cause */
2559                     FC_INVALID_RSCN_COUNT);     /* invalidate the count */
2560 
2561                 if (icmd == NULL) {
2562                         ret = ENOMEM;
2563                 } else {
2564                         /*
2565                          * Setup internal packet as sema sync
2566                          */
2567                         fcp_ipkt_sema_init(icmd);
2568                 }
2569         }
2570 
2571         if (ret == 0) {
2572                 /*
2573                  * Init fpkt pointer for use.
2574                  */
2575 
2576                 fpkt = icmd->ipkt_fpkt;
2577 
2578                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
2579                 fpkt->pkt_tran_type  = FC_PKT_FCP_READ; /* only rd for now */
2580                 fpkt->pkt_timeout    = fscsi->scsi_timeout;
2581 
2582                 /*
2583                  * Init fcmd pointer for use by SCSI command
2584                  */
2585 
2586                 if (nodma) {
2587                         fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
2588                 } else {
2589                         fcmd = &fcp_cmd;
2590                 }
2591                 bzero(fcmd, sizeof (struct fcp_cmd));
2592                 ptgt = plun->lun_tgt;
2593 
2594                 lun_string = (uchar_t *)&fscsi->scsi_lun;
2595 
2596                 fcmd->fcp_ent_addr.ent_addr_0 =
2597                     BE_16(*(uint16_t *)&(lun_string[0]));
2598                 fcmd->fcp_ent_addr.ent_addr_1 =
2599                     BE_16(*(uint16_t *)&(lun_string[2]));
2600                 fcmd->fcp_ent_addr.ent_addr_2 =
2601                     BE_16(*(uint16_t *)&(lun_string[4]));
2602                 fcmd->fcp_ent_addr.ent_addr_3 =
2603                     BE_16(*(uint16_t *)&(lun_string[6]));
2604 
2605                 /*
2606                  * Setup internal packet(icmd)
2607                  */
2608                 icmd->ipkt_lun               = plun;
2609                 icmd->ipkt_restart   = 0;
2610                 icmd->ipkt_retries   = 0;
2611                 icmd->ipkt_opcode    = 0;
2612 
2613                 /*
2614                  * Init the frame HEADER Pointer for use
2615                  */
2616                 hp = &fpkt->pkt_cmd_fhdr;
2617 
2618                 hp->s_id     = pptr->port_id;
2619                 hp->d_id     = ptgt->tgt_d_id;
2620                 hp->r_ctl    = R_CTL_COMMAND;
2621                 hp->type     = FC_TYPE_SCSI_FCP;
2622                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
2623                 hp->rsvd     = 0;
2624                 hp->seq_id   = 0;
2625                 hp->seq_cnt  = 0;
2626                 hp->ox_id    = 0xffff;
2627                 hp->rx_id    = 0xffff;
2628                 hp->ro               = 0;
2629 
2630                 fcmd->fcp_cntl.cntl_qtype    = FCP_QTYPE_SIMPLE;
2631                 fcmd->fcp_cntl.cntl_read_data        = 1;    /* only rd for now */
2632                 fcmd->fcp_cntl.cntl_write_data       = 0;
2633                 fcmd->fcp_data_len   = fscsi->scsi_buflen;
2634 
2635                 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
2636                 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb,
2637                     fscsi->scsi_cdblen);
2638 
2639                 if (!nodma) {
2640                         FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
2641                             fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
2642                 }
2643 
2644                 /*
2645                  * Send SCSI command to FC transport
2646                  */
2647 
2648                 if (ret == 0) {
2649                         mutex_enter(&ptgt->tgt_mutex);
2650 
2651                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
2652                                 mutex_exit(&ptgt->tgt_mutex);
2653                                 fscsi->scsi_fc_status = xport_retval =
2654                                     fc_ulp_transport(pptr->port_fp_handle,
2655                                     fpkt);
2656                                 if (fscsi->scsi_fc_status != FC_SUCCESS) {
2657                                         ret = EIO;
2658                                 }
2659                         } else {
2660                                 mutex_exit(&ptgt->tgt_mutex);
2661                                 ret = EBUSY;
2662                         }
2663                 }
2664         }
2665 
2666         /*
2667          * Wait for completion only if fc_ulp_transport was called and it
2668          * returned a success. This is the only time callback will happen.
2669          * Otherwise, there is no point in waiting
2670          */
2671         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2672                 ret = fcp_ipkt_sema_wait(icmd);
2673         }
2674 
2675         /*
2676          * Copy data to IOCTL data structures
2677          */
2678         rsp = NULL;
2679         if ((ret == 0) && (xport_retval == FC_SUCCESS)) {
2680                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
2681 
2682                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
2683                         fcp_log(CE_WARN, pptr->port_dip,
2684                             "!SCSI command to d_id=0x%x lun=0x%x"
2685                             " failed, Bad FCP response values:"
2686                             " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
2687                             " sts-rsvd2=%x, rsplen=%x, senselen=%x",
2688                             ptgt->tgt_d_id, plun->lun_num,
2689                             rsp->reserved_0, rsp->reserved_1,
2690                             rsp->fcp_u.fcp_status.reserved_0,
2691                             rsp->fcp_u.fcp_status.reserved_1,
2692                             rsp->fcp_response_len, rsp->fcp_sense_len);
2693 
2694                         ret = EIO;
2695                 }
2696         }
2697 
2698         if ((ret == 0) && (rsp != NULL)) {
2699                 /*
2700                  * Calc response lengths
2701                  */
2702                 sense_len = 0;
2703                 info_len = 0;
2704 
2705                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
2706                         info_len = rsp->fcp_response_len;
2707                 }
2708 
2709                 rsp_info   = (struct fcp_rsp_info *)
2710                     ((uint8_t *)rsp + sizeof (struct fcp_rsp));
2711 
2712                 /*
2713                  * Get SCSI status
2714                  */
2715                 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status;
2716                 /*
2717                  * If a lun was just added or removed and the next command
2718                  * comes through this interface, we need to capture the check
2719                  * condition so we can discover the new topology.
2720                  */
2721                 if (fscsi->scsi_bufstatus != STATUS_GOOD &&
2722                     rsp->fcp_u.fcp_status.sense_len_set) {
2723                         sense_len = rsp->fcp_sense_len;
2724                         rsp_sense  = (caddr_t)((uint8_t *)rsp_info + info_len);
2725                         sense_to = (struct scsi_extended_sense *)rsp_sense;
2726                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
2727                             (FCP_SENSE_NO_LUN(sense_to))) {
2728                                 reconfig_lun = TRUE;
2729                         }
2730                 }
2731 
2732                 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) &&
2733                     (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) {
2734                         if (reconfig_lun == FALSE) {
2735                                 reconfig_status =
2736                                     fcp_is_reconfig_needed(ptgt, fpkt);
2737                         }
2738 
2739                         if ((reconfig_lun == TRUE) ||
2740                             (reconfig_status == TRUE)) {
2741                                 mutex_enter(&ptgt->tgt_mutex);
2742                                 if (ptgt->tgt_tid == NULL) {
2743                                         /*
2744                                          * Either we've been notified the
2745                                          * REPORT_LUN data has changed, or
2746                                          * we've determined on our own that
2747                                          * we're out of date.  Kick off
2748                                          * rediscovery.
2749                                          */
2750                                         tid = timeout(fcp_reconfigure_luns,
2751                                             (caddr_t)ptgt, drv_usectohz(1));
2752 
2753                                         ptgt->tgt_tid = tid;
2754                                         ptgt->tgt_state |= FCP_TGT_BUSY;
2755                                         ret = EBUSY;
2756                                         reconfig_pending = TRUE;
2757                                 }
2758                                 mutex_exit(&ptgt->tgt_mutex);
2759                         }
2760                 }
2761 
2762                 /*
2763                  * Calc residuals and buffer lengths
2764                  */
2765 
2766                 if (ret == 0) {
2767                         buf_len = fscsi->scsi_buflen;
2768                         fscsi->scsi_bufresid = 0;
2769                         if (rsp->fcp_u.fcp_status.resid_under) {
2770                                 if (rsp->fcp_resid <= fscsi->scsi_buflen) {
2771                                         fscsi->scsi_bufresid = rsp->fcp_resid;
2772                                 } else {
2773                                         cmn_err(CE_WARN, "fcp: bad residue %x "
2774                                             "for txfer len %x", rsp->fcp_resid,
2775                                             fscsi->scsi_buflen);
2776                                         fscsi->scsi_bufresid =
2777                                             fscsi->scsi_buflen;
2778                                 }
2779                                 buf_len -= fscsi->scsi_bufresid;
2780                         }
2781                         if (rsp->fcp_u.fcp_status.resid_over) {
2782                                 fscsi->scsi_bufresid = -rsp->fcp_resid;
2783                         }
2784 
2785                         fscsi->scsi_rqresid  = fscsi->scsi_rqlen - sense_len;
2786                         if (fscsi->scsi_rqlen < sense_len) {
2787                                 sense_len = fscsi->scsi_rqlen;
2788                         }
2789 
2790                         fscsi->scsi_fc_rspcode       = 0;
2791                         if (rsp->fcp_u.fcp_status.rsp_len_set) {
2792                                 fscsi->scsi_fc_rspcode       = rsp_info->rsp_code;
2793                         }
2794                         fscsi->scsi_pkt_state        = fpkt->pkt_state;
2795                         fscsi->scsi_pkt_action       = fpkt->pkt_action;
2796                         fscsi->scsi_pkt_reason       = fpkt->pkt_reason;
2797 
2798                         /*
2799                          * Copy data and request sense
2800                          *
2801                          * Data must be copied by using the FCP_CP_IN macro.
2802                          * This will ensure the proper byte order since the data
2803                          * is being copied directly from the memory mapped
2804                          * device register.
2805                          *
2806                          * The response (and request sense) will be in the
2807                          * correct byte order.  No special copy is necessary.
2808                          */
2809 
2810                         if (buf_len) {
2811                                 FCP_CP_IN(fpkt->pkt_data,
2812                                     fscsi->scsi_bufaddr,
2813                                     fpkt->pkt_data_acc,
2814                                     buf_len);
2815                         }
2816                         bcopy((void *)rsp_sense,
2817                             (void *)fscsi->scsi_rqbufaddr,
2818                             sense_len);
2819                 }
2820         }
2821 
2822         /*
2823          * Cleanup transport data structures if icmd was alloc-ed
2824          * So, cleanup happens in the same thread that icmd was alloc-ed
2825          */
2826         if (icmd != NULL) {
2827                 fcp_ipkt_sema_cleanup(icmd);
2828         }
2829 
2830         /* restore pm busy/idle status */
2831         if (port_busy) {
2832                 fc_ulp_idle_port(pptr->port_fp_handle);
2833         }
2834 
2835         /*
2836          * Cleanup target.  if a reconfig is pending, don't clear the BUSY
2837          * flag, it'll be cleared when the reconfig is complete.
2838          */
2839         if ((ptgt != NULL) && !reconfig_pending) {
2840                 /*
2841                  * If target was created,
2842                  */
2843                 if (target_created) {
2844                         mutex_enter(&ptgt->tgt_mutex);
2845                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2846                         mutex_exit(&ptgt->tgt_mutex);
2847                 } else {
2848                         /*
2849                          * De-mark target as busy
2850                          */
2851                         mutex_enter(&ptgt->tgt_mutex);
2852                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
2853                         mutex_exit(&ptgt->tgt_mutex);
2854                 }
2855         }
2856         return (ret);
2857 }
2858 
2859 
2860 static int
2861 fcp_is_reconfig_needed(struct fcp_tgt *ptgt,
2862     fc_packet_t *fpkt)
2863 {
2864         uchar_t                 *lun_string;
2865         uint16_t                lun_num, i;
2866         int                     num_luns;
2867         int                     actual_luns;
2868         int                     num_masked_luns;
2869         int                     lun_buflen;
2870         struct fcp_lun  *plun   = NULL;
2871         struct fcp_reportlun_resp       *report_lun;
2872         uint8_t                 reconfig_needed = FALSE;
2873         uint8_t                 lun_exists = FALSE;
2874         fcp_port_t                      *pptr            = ptgt->tgt_port;
2875 
2876         report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP);
2877 
2878         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
2879             fpkt->pkt_datalen);
2880 
2881         /* get number of luns (which is supplied as LUNS * 8) */
2882         num_luns = BE_32(report_lun->num_lun) >> 3;
2883 
2884         /*
2885          * Figure out exactly how many lun strings our response buffer
2886          * can hold.
2887          */
2888         lun_buflen = (fpkt->pkt_datalen -
2889             2 * sizeof (uint32_t)) / sizeof (longlong_t);
2890 
2891         /*
2892          * Is our response buffer full or not? We don't want to
2893          * potentially walk beyond the number of luns we have.
2894          */
2895         if (num_luns <= lun_buflen) {
2896                 actual_luns = num_luns;
2897         } else {
2898                 actual_luns = lun_buflen;
2899         }
2900 
2901         mutex_enter(&ptgt->tgt_mutex);
2902 
2903         /* Scan each lun to see if we have masked it. */
2904         num_masked_luns = 0;
2905         if (fcp_lun_blacklist != NULL) {
2906                 for (i = 0; i < actual_luns; i++) {
2907                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2908                         switch (lun_string[0] & 0xC0) {
2909                         case FCP_LUN_ADDRESSING:
2910                         case FCP_PD_ADDRESSING:
2911                         case FCP_VOLUME_ADDRESSING:
2912                                 lun_num = ((lun_string[0] & 0x3F) << 8)
2913                                     | lun_string[1];
2914                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
2915                                     lun_num) == TRUE) {
2916                                         num_masked_luns++;
2917                                 }
2918                                 break;
2919                         default:
2920                                 break;
2921                         }
2922                 }
2923         }
2924 
2925         /*
2926          * The quick and easy check.  If the number of LUNs reported
2927          * doesn't match the number we currently know about, we need
2928          * to reconfigure.
2929          */
2930         if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) {
2931                 mutex_exit(&ptgt->tgt_mutex);
2932                 kmem_free(report_lun, fpkt->pkt_datalen);
2933                 return (TRUE);
2934         }
2935 
2936         /*
2937          * If the quick and easy check doesn't turn up anything, we walk
2938          * the list of luns from the REPORT_LUN response and look for
2939          * any luns we don't know about.  If we find one, we know we need
2940          * to reconfigure. We will skip LUNs that are masked because of the
2941          * blacklist.
2942          */
2943         for (i = 0; i < actual_luns; i++) {
2944                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
2945                 lun_exists = FALSE;
2946                 switch (lun_string[0] & 0xC0) {
2947                 case FCP_LUN_ADDRESSING:
2948                 case FCP_PD_ADDRESSING:
2949                 case FCP_VOLUME_ADDRESSING:
2950                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
2951 
2952                         if ((fcp_lun_blacklist != NULL) && (fcp_should_mask(
2953                             &ptgt->tgt_port_wwn, lun_num) == TRUE)) {
2954                                 lun_exists = TRUE;
2955                                 break;
2956                         }
2957 
2958                         for (plun = ptgt->tgt_lun; plun;
2959                             plun = plun->lun_next) {
2960                                 if (plun->lun_num == lun_num) {
2961                                         lun_exists = TRUE;
2962                                         break;
2963                                 }
2964                         }
2965                         break;
2966                 default:
2967                         break;
2968                 }
2969 
2970                 if (lun_exists == FALSE) {
2971                         reconfig_needed = TRUE;
2972                         break;
2973                 }
2974         }
2975 
2976         mutex_exit(&ptgt->tgt_mutex);
2977         kmem_free(report_lun, fpkt->pkt_datalen);
2978 
2979         return (reconfig_needed);
2980 }
2981 
2982 /*
2983  * This function is called by fcp_handle_page83 and uses inquiry response data
2984  * stored in plun->lun_inq to determine whether or not a device is a member of
2985  * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table,
2986  * otherwise 1.
2987  */
2988 static int
2989 fcp_symmetric_device_probe(struct fcp_lun *plun)
2990 {
2991         struct scsi_inquiry     *stdinq = &plun->lun_inq;
2992         char                    *devidptr;
2993         int                     i, len;
2994 
2995         for (i = 0; i < fcp_symmetric_disk_table_size; i++) {
2996                 devidptr = fcp_symmetric_disk_table[i];
2997                 len = (int)strlen(devidptr);
2998 
2999                 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) {
3000                         return (0);
3001                 }
3002         }
3003         return (1);
3004 }
3005 
3006 
3007 /*
3008  * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl
3009  * It basically returns the current count of # of state change callbacks
3010  * i.e the value of tgt_change_cnt.
3011  *
3012  * INPUT:
3013  *   fcp_ioctl.fp_minor -> The minor # of the fp port
3014  *   fcp_ioctl.listlen  -> 1
3015  *   fcp_ioctl.list     -> Pointer to a 32 bit integer
3016  */
3017 /*ARGSUSED2*/
3018 static int
3019 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval)
3020 {
3021         int                     ret;
3022         uint32_t                link_cnt;
3023         struct fcp_ioctl        fioctl;
3024         struct fcp_port *pptr = NULL;
3025 
3026         if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl,
3027             &pptr)) != 0) {
3028                 return (ret);
3029         }
3030 
3031         ASSERT(pptr != NULL);
3032 
3033         if (fioctl.listlen != 1) {
3034                 return (EINVAL);
3035         }
3036 
3037         mutex_enter(&pptr->port_mutex);
3038         if (pptr->port_state & FCP_STATE_OFFLINE) {
3039                 mutex_exit(&pptr->port_mutex);
3040                 return (ENXIO);
3041         }
3042 
3043         /*
3044          * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded):
3045          * When the fcp initially attaches to the port and there are nothing
3046          * hanging out of the port or if there was a repeat offline state change
3047          * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case).
3048          * In the latter case, port_tmp_cnt will be non-zero and that is how we
3049          * will differentiate the 2 cases.
3050          */
3051         if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) {
3052                 mutex_exit(&pptr->port_mutex);
3053                 return (ENXIO);
3054         }
3055 
3056         link_cnt = pptr->port_link_cnt;
3057         mutex_exit(&pptr->port_mutex);
3058 
3059         if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) {
3060                 return (EFAULT);
3061         }
3062 
3063 #ifdef  _MULTI_DATAMODEL
3064         switch (ddi_model_convert_from(mode & FMODELS)) {
3065         case DDI_MODEL_ILP32: {
3066                 struct fcp32_ioctl f32_ioctl;
3067 
3068                 f32_ioctl.fp_minor = fioctl.fp_minor;
3069                 f32_ioctl.listlen = fioctl.listlen;
3070                 f32_ioctl.list = (caddr32_t)(long)fioctl.list;
3071                 if (ddi_copyout((void *)&f32_ioctl, (void *)data,
3072                     sizeof (struct fcp32_ioctl), mode)) {
3073                         return (EFAULT);
3074                 }
3075                 break;
3076         }
3077         case DDI_MODEL_NONE:
3078                 if (ddi_copyout((void *)&fioctl, (void *)data,
3079                     sizeof (struct fcp_ioctl), mode)) {
3080                         return (EFAULT);
3081                 }
3082                 break;
3083         }
3084 #else   /* _MULTI_DATAMODEL */
3085 
3086         if (ddi_copyout((void *)&fioctl, (void *)data,
3087             sizeof (struct fcp_ioctl), mode)) {
3088                 return (EFAULT);
3089         }
3090 #endif  /* _MULTI_DATAMODEL */
3091 
3092         return (0);
3093 }
3094 
3095 /*
3096  * This function copies the fcp_ioctl structure passed in from user land
3097  * into kernel land. Handles 32 bit applications.
3098  */
3099 /*ARGSUSED*/
3100 static int
3101 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval,
3102     struct fcp_ioctl *fioctl, struct fcp_port **pptr)
3103 {
3104         struct fcp_port *t_pptr;
3105 
3106 #ifdef  _MULTI_DATAMODEL
3107         switch (ddi_model_convert_from(mode & FMODELS)) {
3108         case DDI_MODEL_ILP32: {
3109                 struct fcp32_ioctl f32_ioctl;
3110 
3111                 if (ddi_copyin((void *)data, (void *)&f32_ioctl,
3112                     sizeof (struct fcp32_ioctl), mode)) {
3113                         return (EFAULT);
3114                 }
3115                 fioctl->fp_minor = f32_ioctl.fp_minor;
3116                 fioctl->listlen = f32_ioctl.listlen;
3117                 fioctl->list = (caddr_t)(long)f32_ioctl.list;
3118                 break;
3119         }
3120         case DDI_MODEL_NONE:
3121                 if (ddi_copyin((void *)data, (void *)fioctl,
3122                     sizeof (struct fcp_ioctl), mode)) {
3123                         return (EFAULT);
3124                 }
3125                 break;
3126         }
3127 
3128 #else   /* _MULTI_DATAMODEL */
3129         if (ddi_copyin((void *)data, (void *)fioctl,
3130             sizeof (struct fcp_ioctl), mode)) {
3131                 return (EFAULT);
3132         }
3133 #endif  /* _MULTI_DATAMODEL */
3134 
3135         /*
3136          * Right now we can assume that the minor number matches with
3137          * this instance of fp. If this changes we will need to
3138          * revisit this logic.
3139          */
3140         mutex_enter(&fcp_global_mutex);
3141         t_pptr = fcp_port_head;
3142         while (t_pptr) {
3143                 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) {
3144                         break;
3145                 } else {
3146                         t_pptr = t_pptr->port_next;
3147                 }
3148         }
3149         *pptr = t_pptr;
3150         mutex_exit(&fcp_global_mutex);
3151         if (t_pptr == NULL) {
3152                 return (ENXIO);
3153         }
3154 
3155         return (0);
3156 }
3157 
3158 /*
3159  *     Function: fcp_port_create_tgt
3160  *
3161  *  Description: As the name suggest this function creates the target context
3162  *               specified by the the WWN provided by the caller.  If the
3163  *               creation goes well and the target is known by fp/fctl a PLOGI
3164  *               followed by a PRLI are issued.
3165  *
3166  *     Argument: pptr           fcp port structure
3167  *               pwwn           WWN of the target
3168  *               ret_val        Address of the return code.  It could be:
3169  *                              EIO, ENOMEM or 0.
3170  *               fc_status      PLOGI or PRLI status completion
3171  *               fc_pkt_state   PLOGI or PRLI state completion
3172  *               fc_pkt_reason  PLOGI or PRLI reason completion
3173  *               fc_pkt_action  PLOGI or PRLI action completion
3174  *
3175  * Return Value: NULL if it failed
3176  *               Target structure address if it succeeds
3177  */
3178 static struct fcp_tgt *
3179 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val,
3180     int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action)
3181 {
3182         struct fcp_tgt  *ptgt = NULL;
3183         fc_portmap_t            devlist;
3184         int                     lcount;
3185         int                     error;
3186 
3187         *ret_val = 0;
3188 
3189         /*
3190          * Check FC port device & get port map
3191          */
3192         if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn,
3193             &error, 1) == NULL) {
3194                 *ret_val = EIO;
3195         } else {
3196                 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn,
3197                     &devlist) != FC_SUCCESS) {
3198                         *ret_val = EIO;
3199                 }
3200         }
3201 
3202         /* Set port map flags */
3203         devlist.map_type = PORT_DEVICE_USER_CREATE;
3204 
3205         /* Allocate target */
3206         if (*ret_val == 0) {
3207                 lcount = pptr->port_link_cnt;
3208                 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount);
3209                 if (ptgt == NULL) {
3210                         fcp_log(CE_WARN, pptr->port_dip,
3211                             "!FC target allocation failed");
3212                         *ret_val = ENOMEM;
3213                 } else {
3214                         /* Setup target */
3215                         mutex_enter(&ptgt->tgt_mutex);
3216 
3217                         ptgt->tgt_statec_cause       = FCP_CAUSE_TGT_CHANGE;
3218                         ptgt->tgt_tmp_cnt    = 1;
3219                         ptgt->tgt_d_id               = devlist.map_did.port_id;
3220                         ptgt->tgt_hard_addr  =
3221                             devlist.map_hard_addr.hard_addr;
3222                         ptgt->tgt_pd_handle  = devlist.map_pd;
3223                         ptgt->tgt_fca_dev    = NULL;
3224 
3225                         bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
3226                             FC_WWN_SIZE);
3227                         bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
3228                             FC_WWN_SIZE);
3229 
3230                         mutex_exit(&ptgt->tgt_mutex);
3231                 }
3232         }
3233 
3234         /* Release global mutex for PLOGI and PRLI */
3235         mutex_exit(&fcp_global_mutex);
3236 
3237         /* Send PLOGI (If necessary) */
3238         if (*ret_val == 0) {
3239                 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status,
3240                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3241         }
3242 
3243         /* Send PRLI (If necessary) */
3244         if (*ret_val == 0) {
3245                 *ret_val = fcp_tgt_send_prli(ptgt, fc_status,
3246                     fc_pkt_state, fc_pkt_reason, fc_pkt_action);
3247         }
3248 
3249         mutex_enter(&fcp_global_mutex);
3250 
3251         return (ptgt);
3252 }
3253 
3254 /*
3255  *     Function: fcp_tgt_send_plogi
3256  *
3257  *  Description: This function sends a PLOGI to the target specified by the
3258  *               caller and waits till it completes.
3259  *
3260  *     Argument: ptgt           Target to send the plogi to.
3261  *               fc_status      Status returned by fp/fctl in the PLOGI request.
3262  *               fc_pkt_state   State returned by fp/fctl in the PLOGI request.
3263  *               fc_pkt_reason  Reason returned by fp/fctl in the PLOGI request.
3264  *               fc_pkt_action  Action returned by fp/fctl in the PLOGI request.
3265  *
3266  * Return Value: 0
3267  *               ENOMEM
3268  *               EIO
3269  *
3270  *      Context: User context.
3271  */
3272 static int
3273 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3274     int *fc_pkt_reason, int *fc_pkt_action)
3275 {
3276         struct fcp_port *pptr;
3277         struct fcp_ipkt *icmd;
3278         struct fc_packet        *fpkt;
3279         fc_frame_hdr_t          *hp;
3280         struct la_els_logi      logi;
3281         int                     tcount;
3282         int                     lcount;
3283         int                     ret, login_retval = ~FC_SUCCESS;
3284 
3285         ret = 0;
3286 
3287         pptr = ptgt->tgt_port;
3288 
3289         lcount = pptr->port_link_cnt;
3290         tcount = ptgt->tgt_change_cnt;
3291 
3292         /* Alloc internal packet */
3293         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t),
3294             sizeof (la_els_logi_t), 0,
3295             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
3296             lcount, tcount, 0, FC_INVALID_RSCN_COUNT);
3297 
3298         if (icmd == NULL) {
3299                 ret = ENOMEM;
3300         } else {
3301                 /*
3302                  * Setup internal packet as sema sync
3303                  */
3304                 fcp_ipkt_sema_init(icmd);
3305 
3306                 /*
3307                  * Setup internal packet (icmd)
3308                  */
3309                 icmd->ipkt_lun               = NULL;
3310                 icmd->ipkt_restart   = 0;
3311                 icmd->ipkt_retries   = 0;
3312                 icmd->ipkt_opcode    = LA_ELS_PLOGI;
3313 
3314                 /*
3315                  * Setup fc_packet
3316                  */
3317                 fpkt = icmd->ipkt_fpkt;
3318 
3319                 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
3320                 fpkt->pkt_tran_type  = FC_PKT_EXCHANGE;
3321                 fpkt->pkt_timeout    = FCP_ELS_TIMEOUT;
3322 
3323                 /*
3324                  * Setup FC frame header
3325                  */
3326                 hp = &fpkt->pkt_cmd_fhdr;
3327 
3328                 hp->s_id     = pptr->port_id;     /* source ID */
3329                 hp->d_id     = ptgt->tgt_d_id;    /* dest ID */
3330                 hp->r_ctl    = R_CTL_ELS_REQ;
3331                 hp->type     = FC_TYPE_EXTENDED_LS;
3332                 hp->f_ctl    = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
3333                 hp->seq_id   = 0;
3334                 hp->rsvd     = 0;
3335                 hp->df_ctl   = 0;
3336                 hp->seq_cnt  = 0;
3337                 hp->ox_id    = 0xffff;               /* i.e. none */
3338                 hp->rx_id    = 0xffff;               /* i.e. none */
3339                 hp->ro               = 0;
3340 
3341                 /*
3342                  * Setup PLOGI
3343                  */
3344                 bzero(&logi, sizeof (struct la_els_logi));
3345                 logi.ls_code.ls_code = LA_ELS_PLOGI;
3346 
3347                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
3348                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
3349 
3350                 /*
3351                  * Send PLOGI
3352                  */
3353                 *fc_status = login_retval =
3354                     fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
3355                 if (*fc_status != FC_SUCCESS) {
3356                         ret = EIO;
3357                 }
3358         }
3359 
3360         /*
3361          * Wait for completion
3362          */
3363         if ((ret == 0) && (login_retval == FC_SUCCESS)) {
3364                 ret = fcp_ipkt_sema_wait(icmd);
3365 
3366                 *fc_pkt_state   = fpkt->pkt_state;
3367                 *fc_pkt_reason  = fpkt->pkt_reason;
3368                 *fc_pkt_action  = fpkt->pkt_action;
3369         }
3370 
3371         /*
3372          * Cleanup transport data structures if icmd was alloc-ed AND if there
3373          * is going to be no callback (i.e if fc_ulp_login() failed).
3374          * Otherwise, cleanup happens in callback routine.
3375          */
3376         if (icmd != NULL) {
3377                 fcp_ipkt_sema_cleanup(icmd);
3378         }
3379 
3380         return (ret);
3381 }
3382 
3383 /*
3384  *     Function: fcp_tgt_send_prli
3385  *
3386  *  Description: Does nothing as of today.
3387  *
3388  *     Argument: ptgt           Target to send the prli to.
3389  *               fc_status      Status returned by fp/fctl in the PRLI request.
3390  *               fc_pkt_state   State returned by fp/fctl in the PRLI request.
3391  *               fc_pkt_reason  Reason returned by fp/fctl in the PRLI request.
3392  *               fc_pkt_action  Action returned by fp/fctl in the PRLI request.
3393  *
3394  * Return Value: 0
3395  */
3396 /*ARGSUSED*/
3397 static int
3398 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state,
3399     int *fc_pkt_reason, int *fc_pkt_action)
3400 {
3401         return (0);
3402 }
3403 
3404 /*
3405  *     Function: fcp_ipkt_sema_init
3406  *
3407  *  Description: Initializes the semaphore contained in the internal packet.
3408  *
3409  *     Argument: icmd   Internal packet the semaphore of which must be
3410  *                      initialized.
3411  *
3412  * Return Value: None
3413  *
3414  *      Context: User context only.
3415  */
3416 static void
3417 fcp_ipkt_sema_init(struct fcp_ipkt *icmd)
3418 {
3419         struct fc_packet        *fpkt;
3420 
3421         fpkt = icmd->ipkt_fpkt;
3422 
3423         /* Create semaphore for sync */
3424         sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL);
3425 
3426         /* Setup the completion callback */
3427         fpkt->pkt_comp = fcp_ipkt_sema_callback;
3428 }
3429 
3430 /*
3431  *     Function: fcp_ipkt_sema_wait
3432  *
3433  *  Description: Wait on the semaphore embedded in the internal packet.  The
3434  *               semaphore is released in the callback.
3435  *
3436  *     Argument: icmd   Internal packet to wait on for completion.
3437  *
3438  * Return Value: 0
3439  *               EIO
3440  *               EBUSY
3441  *               EAGAIN
3442  *
3443  *      Context: User context only.
3444  *
3445  * This function does a conversion between the field pkt_state of the fc_packet
3446  * embedded in the internal packet (icmd) and the code it returns.
3447  */
3448 static int
3449 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd)
3450 {
3451         struct fc_packet        *fpkt;
3452         int     ret;
3453 
3454         ret = EIO;
3455         fpkt = icmd->ipkt_fpkt;
3456 
3457         /*
3458          * Wait on semaphore
3459          */
3460         sema_p(&(icmd->ipkt_sema));
3461 
3462         /*
3463          * Check the status of the FC packet
3464          */
3465         switch (fpkt->pkt_state) {
3466         case FC_PKT_SUCCESS:
3467                 ret = 0;
3468                 break;
3469         case FC_PKT_LOCAL_RJT:
3470                 switch (fpkt->pkt_reason) {
3471                 case FC_REASON_SEQ_TIMEOUT:
3472                 case FC_REASON_RX_BUF_TIMEOUT:
3473                         ret = EAGAIN;
3474                         break;
3475                 case FC_REASON_PKT_BUSY:
3476                         ret = EBUSY;
3477                         break;
3478                 }
3479                 break;
3480         case FC_PKT_TIMEOUT:
3481                 ret = EAGAIN;
3482                 break;
3483         case FC_PKT_LOCAL_BSY:
3484         case FC_PKT_TRAN_BSY:
3485         case FC_PKT_NPORT_BSY:
3486         case FC_PKT_FABRIC_BSY:
3487                 ret = EBUSY;
3488                 break;
3489         case FC_PKT_LS_RJT:
3490         case FC_PKT_BA_RJT:
3491                 switch (fpkt->pkt_reason) {
3492                 case FC_REASON_LOGICAL_BSY:
3493                         ret = EBUSY;
3494                         break;
3495                 }
3496                 break;
3497         case FC_PKT_FS_RJT:
3498                 switch (fpkt->pkt_reason) {
3499                 case FC_REASON_FS_LOGICAL_BUSY:
3500                         ret = EBUSY;
3501                         break;
3502                 }
3503                 break;
3504         }
3505 
3506         return (ret);
3507 }
3508 
3509 /*
3510  *     Function: fcp_ipkt_sema_callback
3511  *
3512  *  Description: Registered as the completion callback function for the FC
3513  *               transport when the ipkt semaphore is used for sync. This will
3514  *               cleanup the used data structures, if necessary and wake up
3515  *               the user thread to complete the transaction.
3516  *
3517  *     Argument: fpkt   FC packet (points to the icmd)
3518  *
3519  * Return Value: None
3520  *
3521  *      Context: User context only
3522  */
3523 static void
3524 fcp_ipkt_sema_callback(struct fc_packet *fpkt)
3525 {
3526         struct fcp_ipkt *icmd;
3527 
3528         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
3529 
3530         /*
3531          * Wake up user thread
3532          */
3533         sema_v(&(icmd->ipkt_sema));
3534 }
3535 
3536 /*
3537  *     Function: fcp_ipkt_sema_cleanup
3538  *
3539  *  Description: Called to cleanup (if necessary) the data structures used
3540  *               when ipkt sema is used for sync.  This function will detect
3541  *               whether the caller is the last thread (via counter) and
3542  *               cleanup only if necessary.
3543  *
3544  *     Argument: icmd   Internal command packet
3545  *
3546  * Return Value: None
3547  *
3548  *      Context: User context only
3549  */
3550 static void
3551 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd)
3552 {
3553         struct fcp_tgt  *ptgt;
3554         struct fcp_port *pptr;
3555 
3556         ptgt = icmd->ipkt_tgt;
3557         pptr = icmd->ipkt_port;
3558 
3559         /*
3560          * Acquire data structure
3561          */
3562         mutex_enter(&ptgt->tgt_mutex);
3563 
3564         /*
3565          * Destroy semaphore
3566          */
3567         sema_destroy(&(icmd->ipkt_sema));
3568 
3569         /*
3570          * Cleanup internal packet
3571          */
3572         mutex_exit(&ptgt->tgt_mutex);
3573         fcp_icmd_free(pptr, icmd);
3574 }
3575 
3576 /*
3577  *     Function: fcp_port_attach
3578  *
3579  *  Description: Called by the transport framework to resume, suspend or
3580  *               attach a new port.
3581  *
3582  *     Argument: ulph           Port handle
3583  *               *pinfo         Port information
3584  *               cmd            Command
3585  *               s_id           Port ID
3586  *
3587  * Return Value: FC_FAILURE or FC_SUCCESS
3588  */
3589 /*ARGSUSED*/
3590 static int
3591 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
3592     fc_attach_cmd_t cmd, uint32_t s_id)
3593 {
3594         int     instance;
3595         int     res = FC_FAILURE; /* default result */
3596 
3597         ASSERT(pinfo != NULL);
3598 
3599         instance = ddi_get_instance(pinfo->port_dip);
3600 
3601         switch (cmd) {
3602         case FC_CMD_ATTACH:
3603                 /*
3604                  * this port instance attaching for the first time (or after
3605                  * being detached before)
3606                  */
3607                 if (fcp_handle_port_attach(ulph, pinfo, s_id,
3608                     instance) == DDI_SUCCESS) {
3609                         res = FC_SUCCESS;
3610                 } else {
3611                         ASSERT(ddi_get_soft_state(fcp_softstate,
3612                             instance) == NULL);
3613                 }
3614                 break;
3615 
3616         case FC_CMD_RESUME:
3617         case FC_CMD_POWER_UP:
3618                 /*
3619                  * this port instance was attached and the suspended and
3620                  * will now be resumed
3621                  */
3622                 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd,
3623                     instance) == DDI_SUCCESS) {
3624                         res = FC_SUCCESS;
3625                 }
3626                 break;
3627 
3628         default:
3629                 /* shouldn't happen */
3630                 FCP_TRACE(fcp_logq, "fcp",
3631                     fcp_trace, FCP_BUF_LEVEL_2, 0,
3632                     "port_attach: unknown cmdcommand: %d", cmd);
3633                 break;
3634         }
3635 
3636         /* return result */
3637         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3638             FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res);
3639 
3640         return (res);
3641 }
3642 
3643 
3644 /*
3645  * detach or suspend this port instance
3646  *
3647  * acquires and releases the global mutex
3648  *
3649  * acquires and releases the mutex for this port
3650  *
3651  * acquires and releases the hotplug mutex for this port
3652  */
3653 /*ARGSUSED*/
3654 static int
3655 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info,
3656     fc_detach_cmd_t cmd)
3657 {
3658         int                     flag;
3659         int                     instance;
3660         struct fcp_port         *pptr;
3661 
3662         instance = ddi_get_instance(info->port_dip);
3663         pptr = ddi_get_soft_state(fcp_softstate, instance);
3664 
3665         switch (cmd) {
3666         case FC_CMD_SUSPEND:
3667                 FCP_DTRACE(fcp_logq, "fcp",
3668                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3669                     "port suspend called for port %d", instance);
3670                 flag = FCP_STATE_SUSPENDED;
3671                 break;
3672 
3673         case FC_CMD_POWER_DOWN:
3674                 FCP_DTRACE(fcp_logq, "fcp",
3675                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3676                     "port power down called for port %d", instance);
3677                 flag = FCP_STATE_POWER_DOWN;
3678                 break;
3679 
3680         case FC_CMD_DETACH:
3681                 FCP_DTRACE(fcp_logq, "fcp",
3682                     fcp_trace, FCP_BUF_LEVEL_8, 0,
3683                     "port detach called for port %d", instance);
3684                 flag = FCP_STATE_DETACHING;
3685                 break;
3686 
3687         default:
3688                 /* shouldn't happen */
3689                 return (FC_FAILURE);
3690         }
3691         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
3692             FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning");
3693 
3694         return (fcp_handle_port_detach(pptr, flag, instance));
3695 }
3696 
3697 
3698 /*
3699  * called for ioctls on the transport's devctl interface, and the transport
3700  * has passed it to us
3701  *
3702  * this will only be called for device control ioctls (i.e. hotplugging stuff)
3703  *
3704  * return FC_SUCCESS if we decide to claim the ioctl,
3705  * else return FC_UNCLAIMED
3706  *
3707  * *rval is set iff we decide to claim the ioctl
3708  */
3709 /*ARGSUSED*/
3710 static int
3711 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd,
3712     intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed)
3713 {
3714         int                     retval = FC_UNCLAIMED;  /* return value */
3715         struct fcp_port         *pptr = NULL;           /* our soft state */
3716         struct devctl_iocdata   *dcp = NULL;            /* for devctl */
3717         dev_info_t              *cdip;
3718         mdi_pathinfo_t          *pip = NULL;
3719         char                    *ndi_nm;                /* NDI name */
3720         char                    *ndi_addr;              /* NDI addr */
3721         int                     is_mpxio, circ;
3722         int                     devi_entered = 0;
3723         clock_t                 end_time;
3724 
3725         ASSERT(rval != NULL);
3726 
3727         FCP_DTRACE(fcp_logq, "fcp",
3728             fcp_trace, FCP_BUF_LEVEL_8, 0,
3729             "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed);
3730 
3731         /* if already claimed then forget it */
3732         if (claimed) {
3733                 /*
3734                  * for now, if this ioctl has already been claimed, then
3735                  * we just ignore it
3736                  */
3737                 return (retval);
3738         }
3739 
3740         /* get our port info */
3741         if ((pptr = fcp_get_port(port_handle)) == NULL) {
3742                 fcp_log(CE_WARN, NULL,
3743                     "!fcp:Invalid port handle handle in ioctl");
3744                 *rval = ENXIO;
3745                 return (retval);
3746         }
3747         is_mpxio = pptr->port_mpxio;
3748 
3749         switch (cmd) {
3750         case DEVCTL_BUS_GETSTATE:
3751         case DEVCTL_BUS_QUIESCE:
3752         case DEVCTL_BUS_UNQUIESCE:
3753         case DEVCTL_BUS_RESET:
3754         case DEVCTL_BUS_RESETALL:
3755 
3756         case DEVCTL_BUS_DEV_CREATE:
3757                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3758                         return (retval);
3759                 }
3760                 break;
3761 
3762         case DEVCTL_DEVICE_GETSTATE:
3763         case DEVCTL_DEVICE_OFFLINE:
3764         case DEVCTL_DEVICE_ONLINE:
3765         case DEVCTL_DEVICE_REMOVE:
3766         case DEVCTL_DEVICE_RESET:
3767                 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) {
3768                         return (retval);
3769                 }
3770 
3771                 ASSERT(dcp != NULL);
3772 
3773                 /* ensure we have a name and address */
3774                 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) ||
3775                     ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) {
3776                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
3777                             fcp_trace, FCP_BUF_LEVEL_2, 0,
3778                             "ioctl: can't get name (%s) or addr (%s)",
3779                             ndi_nm ? ndi_nm : "<null ptr>",
3780                             ndi_addr ? ndi_addr : "<null ptr>");
3781                         ndi_dc_freehdl(dcp);
3782                         return (retval);
3783                 }
3784 
3785 
3786                 /* get our child's DIP */
3787                 ASSERT(pptr != NULL);
3788                 if (is_mpxio) {
3789                         mdi_devi_enter(pptr->port_dip, &circ);
3790                 } else {
3791                         ndi_devi_enter(pptr->port_dip, &circ);
3792                 }
3793                 devi_entered = 1;
3794 
3795                 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm,
3796                     ndi_addr)) == NULL) {
3797                         /* Look for virtually enumerated devices. */
3798                         pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr);
3799                         if (pip == NULL ||
3800                             ((cdip = mdi_pi_get_client(pip)) == NULL)) {
3801                                 *rval = ENXIO;
3802                                 goto out;
3803                         }
3804                 }
3805                 break;
3806 
3807         default:
3808                 *rval = ENOTTY;
3809                 return (retval);
3810         }
3811 
3812         /* this ioctl is ours -- process it */
3813 
3814         retval = FC_SUCCESS;            /* just means we claim the ioctl */
3815 
3816         /* we assume it will be a success; else we'll set error value */
3817         *rval = 0;
3818 
3819 
3820         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
3821             fcp_trace, FCP_BUF_LEVEL_8, 0,
3822             "ioctl: claiming this one");
3823 
3824         /* handle ioctls now */
3825         switch (cmd) {
3826         case DEVCTL_DEVICE_GETSTATE:
3827                 ASSERT(cdip != NULL);
3828                 ASSERT(dcp != NULL);
3829                 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) {
3830                         *rval = EFAULT;
3831                 }
3832                 break;
3833 
3834         case DEVCTL_DEVICE_REMOVE:
3835         case DEVCTL_DEVICE_OFFLINE: {
3836                 int                     flag = 0;
3837                 int                     lcount;
3838                 int                     tcount;
3839                 struct fcp_pkt  *head = NULL;
3840                 struct fcp_lun  *plun;
3841                 child_info_t            *cip = CIP(cdip);
3842                 int                     all = 1;
3843                 struct fcp_lun  *tplun;
3844                 struct fcp_tgt  *ptgt;
3845 
3846                 ASSERT(pptr != NULL);
3847                 ASSERT(cdip != NULL);
3848 
3849                 mutex_enter(&pptr->port_mutex);
3850                 if (pip != NULL) {
3851                         cip = CIP(pip);
3852                 }
3853                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3854                         mutex_exit(&pptr->port_mutex);
3855                         *rval = ENXIO;
3856                         break;
3857                 }
3858 
3859                 head = fcp_scan_commands(plun);
3860                 if (head != NULL) {
3861                         fcp_abort_commands(head, LUN_PORT);
3862                 }
3863                 lcount = pptr->port_link_cnt;
3864                 tcount = plun->lun_tgt->tgt_change_cnt;
3865                 mutex_exit(&pptr->port_mutex);
3866 
3867                 if (cmd == DEVCTL_DEVICE_REMOVE) {
3868                         flag = NDI_DEVI_REMOVE;
3869                 }
3870 
3871                 if (is_mpxio) {
3872                         mdi_devi_exit(pptr->port_dip, circ);
3873                 } else {
3874                         ndi_devi_exit(pptr->port_dip, circ);
3875                 }
3876                 devi_entered = 0;
3877 
3878                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3879                     FCP_OFFLINE, lcount, tcount, flag);
3880 
3881                 if (*rval != NDI_SUCCESS) {
3882                         *rval = (*rval == NDI_BUSY) ? EBUSY : EIO;
3883                         break;
3884                 }
3885 
3886                 fcp_update_offline_flags(plun);
3887 
3888                 ptgt = plun->lun_tgt;
3889                 mutex_enter(&ptgt->tgt_mutex);
3890                 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun =
3891                     tplun->lun_next) {
3892                         mutex_enter(&tplun->lun_mutex);
3893                         if (!(tplun->lun_state & FCP_LUN_OFFLINE)) {
3894                                 all = 0;
3895                         }
3896                         mutex_exit(&tplun->lun_mutex);
3897                 }
3898 
3899                 if (all) {
3900                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
3901                         /*
3902                          * The user is unconfiguring/offlining the device.
3903                          * If fabric and the auto configuration is set
3904                          * then make sure the user is the only one who
3905                          * can reconfigure the device.
3906                          */
3907                         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
3908                             fcp_enable_auto_configuration) {
3909                                 ptgt->tgt_manual_config_only = 1;
3910                         }
3911                 }
3912                 mutex_exit(&ptgt->tgt_mutex);
3913                 break;
3914         }
3915 
3916         case DEVCTL_DEVICE_ONLINE: {
3917                 int                     lcount;
3918                 int                     tcount;
3919                 struct fcp_lun  *plun;
3920                 child_info_t            *cip = CIP(cdip);
3921 
3922                 ASSERT(cdip != NULL);
3923                 ASSERT(pptr != NULL);
3924 
3925                 mutex_enter(&pptr->port_mutex);
3926                 if (pip != NULL) {
3927                         cip = CIP(pip);
3928                 }
3929                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
3930                         mutex_exit(&pptr->port_mutex);
3931                         *rval = ENXIO;
3932                         break;
3933                 }
3934                 lcount = pptr->port_link_cnt;
3935                 tcount = plun->lun_tgt->tgt_change_cnt;
3936                 mutex_exit(&pptr->port_mutex);
3937 
3938                 /*
3939                  * The FCP_LUN_ONLINING flag is used in fcp_scsi_start()
3940                  * to allow the device attach to occur when the device is
3941                  * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command
3942                  * from the scsi_probe()).
3943                  */
3944                 mutex_enter(&LUN_TGT->tgt_mutex);
3945                 plun->lun_state |= FCP_LUN_ONLINING;
3946                 mutex_exit(&LUN_TGT->tgt_mutex);
3947 
3948                 if (is_mpxio) {
3949                         mdi_devi_exit(pptr->port_dip, circ);
3950                 } else {
3951                         ndi_devi_exit(pptr->port_dip, circ);
3952                 }
3953                 devi_entered = 0;
3954 
3955                 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
3956                     FCP_ONLINE, lcount, tcount, 0);
3957 
3958                 if (*rval != NDI_SUCCESS) {
3959                         /* Reset the FCP_LUN_ONLINING bit */
3960                         mutex_enter(&LUN_TGT->tgt_mutex);
3961                         plun->lun_state &= ~FCP_LUN_ONLINING;
3962                         mutex_exit(&LUN_TGT->tgt_mutex);
3963                         *rval = EIO;
3964                         break;
3965                 }
3966                 mutex_enter(&LUN_TGT->tgt_mutex);
3967                 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY |
3968                     FCP_LUN_ONLINING);
3969                 mutex_exit(&LUN_TGT->tgt_mutex);
3970                 break;
3971         }
3972 
3973         case DEVCTL_BUS_DEV_CREATE: {
3974                 uchar_t                 *bytes = NULL;
3975                 uint_t                  nbytes;
3976                 struct fcp_tgt          *ptgt = NULL;
3977                 struct fcp_lun          *plun = NULL;
3978                 dev_info_t              *useless_dip = NULL;
3979 
3980                 *rval = ndi_dc_devi_create(dcp, pptr->port_dip,
3981                     DEVCTL_CONSTRUCT, &useless_dip);
3982                 if (*rval != 0 || useless_dip == NULL) {
3983                         break;
3984                 }
3985 
3986                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip,
3987                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
3988                     &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
3989                         *rval = EINVAL;
3990                         (void) ndi_devi_free(useless_dip);
3991                         if (bytes != NULL) {
3992                                 ddi_prop_free(bytes);
3993                         }
3994                         break;
3995                 }
3996 
3997                 *rval = fcp_create_on_demand(pptr, bytes);
3998                 if (*rval == 0) {
3999                         mutex_enter(&pptr->port_mutex);
4000                         ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes);
4001                         if (ptgt) {
4002                                 /*
4003                                  * We now have a pointer to the target that
4004                                  * was created. Lets point to the first LUN on
4005                                  * this new target.
4006                                  */
4007                                 mutex_enter(&ptgt->tgt_mutex);
4008 
4009                                 plun = ptgt->tgt_lun;
4010                                 /*
4011                                  * There may be stale/offline LUN entries on
4012                                  * this list (this is by design) and so we have
4013                                  * to make sure we point to the first online
4014                                  * LUN
4015                                  */
4016                                 while (plun &&
4017                                     plun->lun_state & FCP_LUN_OFFLINE) {
4018                                         plun = plun->lun_next;
4019                                 }
4020 
4021                                 mutex_exit(&ptgt->tgt_mutex);
4022                         }
4023                         mutex_exit(&pptr->port_mutex);
4024                 }
4025 
4026                 if (*rval == 0 && ptgt && plun) {
4027                         mutex_enter(&plun->lun_mutex);
4028                         /*
4029                          * Allow up to fcp_lun_ready_retry seconds to
4030                          * configure all the luns behind the target.
4031                          *
4032                          * The intent here is to allow targets with long
4033                          * reboot/reset-recovery times to become available
4034                          * while limiting the maximum wait time for an
4035                          * unresponsive target.
4036                          */
4037                         end_time = ddi_get_lbolt() +
4038                             SEC_TO_TICK(fcp_lun_ready_retry);
4039 
4040                         while (ddi_get_lbolt() < end_time) {
4041                                 retval = FC_SUCCESS;
4042 
4043                                 /*
4044                                  * The new ndi interfaces for on-demand creation
4045                                  * are inflexible, Do some more work to pass on
4046                                  * a path name of some LUN (design is broken !)
4047                                  */
4048                                 if (plun->lun_cip) {
4049                                         if (plun->lun_mpxio == 0) {
4050                                                 cdip = DIP(plun->lun_cip);
4051                                         } else {
4052                                                 cdip = mdi_pi_get_client(
4053                                                     PIP(plun->lun_cip));
4054                                         }
4055                                         if (cdip == NULL) {
4056                                                 *rval = ENXIO;
4057                                                 break;
4058                                         }
4059 
4060                                         if (!i_ddi_devi_attached(cdip)) {
4061                                                 mutex_exit(&plun->lun_mutex);
4062                                                 delay(drv_usectohz(1000000));
4063                                                 mutex_enter(&plun->lun_mutex);
4064                                         } else {
4065                                                 /*
4066                                                  * This Lun is ready, lets
4067                                                  * check the next one.
4068                                                  */
4069                                                 mutex_exit(&plun->lun_mutex);
4070                                                 plun = plun->lun_next;
4071                                                 while (plun && (plun->lun_state
4072                                                     & FCP_LUN_OFFLINE)) {
4073                                                         plun = plun->lun_next;
4074                                                 }
4075                                                 if (!plun) {
4076                                                         break;
4077                                                 }
4078                                                 mutex_enter(&plun->lun_mutex);
4079                                         }
4080                                 } else {
4081                                         /*
4082                                          * lun_cip field for a valid lun
4083                                          * should never be NULL. Fail the
4084                                          * command.
4085                                          */
4086                                         *rval = ENXIO;
4087                                         break;
4088                                 }
4089                         }
4090                         if (plun) {
4091                                 mutex_exit(&plun->lun_mutex);
4092                         } else {
4093                                 char devnm[MAXNAMELEN];
4094                                 int nmlen;
4095 
4096                                 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s",
4097                                     ddi_node_name(cdip),
4098                                     ddi_get_name_addr(cdip));
4099 
4100                                 if (copyout(&devnm, dcp->cpyout_buf, nmlen) !=
4101                                     0) {
4102                                         *rval = EFAULT;
4103                                 }
4104                         }
4105                 } else {
4106                         int     i;
4107                         char    buf[25];
4108 
4109                         for (i = 0; i < FC_WWN_SIZE; i++) {
4110                                 (void) sprintf(&buf[i << 1], "%02x", bytes[i]);
4111                         }
4112 
4113                         fcp_log(CE_WARN, pptr->port_dip,
4114                             "!Failed to create nodes for pwwn=%s; error=%x",
4115                             buf, *rval);
4116                 }
4117 
4118                 (void) ndi_devi_free(useless_dip);
4119                 ddi_prop_free(bytes);
4120                 break;
4121         }
4122 
4123         case DEVCTL_DEVICE_RESET: {
4124                 struct fcp_lun          *plun;
4125                 child_info_t            *cip = CIP(cdip);
4126 
4127                 ASSERT(cdip != NULL);
4128                 ASSERT(pptr != NULL);
4129                 mutex_enter(&pptr->port_mutex);
4130                 if (pip != NULL) {
4131                         cip = CIP(pip);
4132                 }
4133                 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) {
4134                         mutex_exit(&pptr->port_mutex);
4135                         *rval = ENXIO;
4136                         break;
4137                 }
4138                 mutex_exit(&pptr->port_mutex);
4139 
4140                 mutex_enter(&plun->lun_tgt->tgt_mutex);
4141                 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) {
4142                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4143 
4144                         *rval = ENXIO;
4145                         break;
4146                 }
4147 
4148                 if (plun->lun_sd == NULL) {
4149                         mutex_exit(&plun->lun_tgt->tgt_mutex);
4150 
4151                         *rval = ENXIO;
4152                         break;
4153                 }
4154                 mutex_exit(&plun->lun_tgt->tgt_mutex);
4155 
4156                 /*
4157                  * set up ap so that fcp_reset can figure out
4158                  * which target to reset
4159                  */
4160                 if (fcp_scsi_reset(&plun->lun_sd->sd_address,
4161                     RESET_TARGET) == FALSE) {
4162                         *rval = EIO;
4163                 }
4164                 break;
4165         }
4166 
4167         case DEVCTL_BUS_GETSTATE:
4168                 ASSERT(dcp != NULL);
4169                 ASSERT(pptr != NULL);
4170                 ASSERT(pptr->port_dip != NULL);
4171                 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) !=
4172                     NDI_SUCCESS) {
4173                         *rval = EFAULT;
4174                 }
4175                 break;
4176 
4177         case DEVCTL_BUS_QUIESCE:
4178         case DEVCTL_BUS_UNQUIESCE:
4179                 *rval = ENOTSUP;
4180                 break;
4181 
4182         case DEVCTL_BUS_RESET:
4183         case DEVCTL_BUS_RESETALL:
4184                 ASSERT(pptr != NULL);
4185                 (void) fcp_linkreset(pptr, NULL,  KM_SLEEP);
4186                 break;
4187 
4188         default:
4189                 ASSERT(dcp != NULL);
4190                 *rval = ENOTTY;
4191                 break;
4192         }
4193 
4194         /* all done -- clean up and return */
4195 out:    if (devi_entered) {
4196                 if (is_mpxio) {
4197                         mdi_devi_exit(pptr->port_dip, circ);
4198                 } else {
4199                         ndi_devi_exit(pptr->port_dip, circ);
4200                 }
4201         }
4202 
4203         if (dcp != NULL) {
4204                 ndi_dc_freehdl(dcp);
4205         }
4206 
4207         return (retval);
4208 }
4209 
4210 
4211 /*ARGSUSED*/
4212 static int
4213 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4214     uint32_t claimed)
4215 {
4216         uchar_t                 r_ctl;
4217         uchar_t                 ls_code;
4218         struct fcp_port *pptr;
4219 
4220         if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) {
4221                 return (FC_UNCLAIMED);
4222         }
4223 
4224         mutex_enter(&pptr->port_mutex);
4225         if (pptr->port_state & (FCP_STATE_DETACHING |
4226             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4227                 mutex_exit(&pptr->port_mutex);
4228                 return (FC_UNCLAIMED);
4229         }
4230         mutex_exit(&pptr->port_mutex);
4231 
4232         r_ctl = buf->ub_frame.r_ctl;
4233 
4234         switch (r_ctl & R_CTL_ROUTING) {
4235         case R_CTL_EXTENDED_SVC:
4236                 if (r_ctl == R_CTL_ELS_REQ) {
4237                         ls_code = buf->ub_buffer[0];
4238 
4239                         switch (ls_code) {
4240                         case LA_ELS_PRLI:
4241                                 /*
4242                                  * We really don't care if something fails.
4243                                  * If the PRLI was not sent out, then the
4244                                  * other end will time it out.
4245                                  */
4246                                 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) {
4247                                         return (FC_SUCCESS);
4248                                 }
4249                                 return (FC_UNCLAIMED);
4250                                 /* NOTREACHED */
4251 
4252                         default:
4253                                 break;
4254                         }
4255                 }
4256                 /* FALLTHROUGH */
4257 
4258         default:
4259                 return (FC_UNCLAIMED);
4260         }
4261 }
4262 
4263 
4264 /*ARGSUSED*/
4265 static int
4266 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf,
4267     uint32_t claimed)
4268 {
4269         return (FC_UNCLAIMED);
4270 }
4271 
4272 /*
4273  *     Function: fcp_statec_callback
4274  *
4275  *  Description: The purpose of this function is to handle a port state change.
4276  *               It is called from fp/fctl and, in a few instances, internally.
4277  *
4278  *     Argument: ulph           fp/fctl port handle
4279  *               port_handle    fcp_port structure
4280  *               port_state     Physical state of the port
4281  *               port_top       Topology
4282  *               *devlist       Pointer to the first entry of a table
4283  *                              containing the remote ports that can be
4284  *                              reached.
4285  *               dev_cnt        Number of entries pointed by devlist.
4286  *               port_sid       Port ID of the local port.
4287  *
4288  * Return Value: None
4289  */
4290 /*ARGSUSED*/
4291 static void
4292 fcp_statec_callback(opaque_t ulph, opaque_t port_handle,
4293     uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist,
4294     uint32_t dev_cnt, uint32_t port_sid)
4295 {
4296         uint32_t                link_count;
4297         int                     map_len = 0;
4298         struct fcp_port *pptr;
4299         fcp_map_tag_t           *map_tag = NULL;
4300 
4301         if ((pptr = fcp_get_port(port_handle)) == NULL) {
4302                 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback");
4303                 return;                 /* nothing to work with! */
4304         }
4305 
4306         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4307             fcp_trace, FCP_BUF_LEVEL_2, 0,
4308             "fcp_statec_callback: port state/dev_cnt/top ="
4309             "%d/%d/%d", FC_PORT_STATE_MASK(port_state),
4310             dev_cnt, port_top);
4311 
4312         mutex_enter(&pptr->port_mutex);
4313 
4314         /*
4315          * If a thread is in detach, don't do anything.
4316          */
4317         if (pptr->port_state & (FCP_STATE_DETACHING |
4318             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
4319                 mutex_exit(&pptr->port_mutex);
4320                 return;
4321         }
4322 
4323         /*
4324          * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if
4325          * init_pkt is called, it knows whether or not the target's status
4326          * (or pd) might be changing.
4327          */
4328 
4329         if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) {
4330                 pptr->port_state |= FCP_STATE_IN_CB_DEVC;
4331         }
4332 
4333         /*
4334          * the transport doesn't allocate or probe unless being
4335          * asked to by either the applications or ULPs
4336          *
4337          * in cases where the port is OFFLINE at the time of port
4338          * attach callback and the link comes ONLINE later, for
4339          * easier automatic node creation (i.e. without you having to
4340          * go out and run the utility to perform LOGINs) the
4341          * following conditional is helpful
4342          */
4343         pptr->port_phys_state = port_state;
4344 
4345         if (dev_cnt) {
4346                 mutex_exit(&pptr->port_mutex);
4347 
4348                 map_len = sizeof (*map_tag) * dev_cnt;
4349                 map_tag = kmem_alloc(map_len, KM_NOSLEEP);
4350                 if (map_tag == NULL) {
4351                         fcp_log(CE_WARN, pptr->port_dip,
4352                             "!fcp%d: failed to allocate for map tags; "
4353                             " state change will not be processed",
4354                             pptr->port_instance);
4355 
4356                         mutex_enter(&pptr->port_mutex);
4357                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4358                         mutex_exit(&pptr->port_mutex);
4359 
4360                         return;
4361                 }
4362 
4363                 mutex_enter(&pptr->port_mutex);
4364         }
4365 
4366         if (pptr->port_id != port_sid) {
4367                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4368                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4369                     "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id,
4370                     port_sid);
4371                 /*
4372                  * The local port changed ID. It is the first time a port ID
4373                  * is assigned or something drastic happened.  We might have
4374                  * been unplugged and replugged on another loop or fabric port
4375                  * or somebody grabbed the AL_PA we had or somebody rezoned
4376                  * the fabric we were plugged into.
4377                  */
4378                 pptr->port_id = port_sid;
4379         }
4380 
4381         switch (FC_PORT_STATE_MASK(port_state)) {
4382         case FC_STATE_OFFLINE:
4383         case FC_STATE_RESET_REQUESTED:
4384                 /*
4385                  * link has gone from online to offline -- just update the
4386                  * state of this port to BUSY and MARKed to go offline
4387                  */
4388                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4389                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4390                     "link went offline");
4391                 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) {
4392                         /*
4393                          * We were offline a while ago and this one
4394                          * seems to indicate that the loop has gone
4395                          * dead forever.
4396                          */
4397                         pptr->port_tmp_cnt += dev_cnt;
4398                         pptr->port_state &= ~FCP_STATE_OFFLINE;
4399                         pptr->port_state |= FCP_STATE_INIT;
4400                         link_count = pptr->port_link_cnt;
4401                         fcp_handle_devices(pptr, devlist, dev_cnt,
4402                             link_count, map_tag, FCP_CAUSE_LINK_DOWN);
4403                 } else {
4404                         pptr->port_link_cnt++;
4405                         ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED));
4406                         fcp_update_state(pptr, (FCP_LUN_BUSY |
4407                             FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN);
4408                         if (pptr->port_mpxio) {
4409                                 fcp_update_mpxio_path_verifybusy(pptr);
4410                         }
4411                         pptr->port_state |= FCP_STATE_OFFLINE;
4412                         pptr->port_state &=
4413                             ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
4414                         pptr->port_tmp_cnt = 0;
4415                 }
4416                 mutex_exit(&pptr->port_mutex);
4417                 break;
4418 
4419         case FC_STATE_ONLINE:
4420         case FC_STATE_LIP:
4421         case FC_STATE_LIP_LBIT_SET:
4422                 /*
4423                  * link has gone from offline to online
4424                  */
4425                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4426                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4427                     "link went online");
4428 
4429                 pptr->port_link_cnt++;
4430 
4431                 while (pptr->port_ipkt_cnt) {
4432                         mutex_exit(&pptr->port_mutex);
4433                         delay(drv_usectohz(1000000));
4434                         mutex_enter(&pptr->port_mutex);
4435                 }
4436 
4437                 pptr->port_topology = port_top;
4438 
4439                 /*
4440                  * The state of the targets and luns accessible through this
4441                  * port is updated.
4442                  */
4443                 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK,
4444                     FCP_CAUSE_LINK_CHANGE);
4445 
4446                 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE);
4447                 pptr->port_state |= FCP_STATE_ONLINING;
4448                 pptr->port_tmp_cnt = dev_cnt;
4449                 link_count = pptr->port_link_cnt;
4450 
4451                 pptr->port_deadline = fcp_watchdog_time +
4452                     FCP_ICMD_DEADLINE;
4453 
4454                 if (!dev_cnt) {
4455                         /*
4456                          * We go directly to the online state if no remote
4457                          * ports were discovered.
4458                          */
4459                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4460                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4461                             "No remote ports discovered");
4462 
4463                         pptr->port_state &= ~FCP_STATE_ONLINING;
4464                         pptr->port_state |= FCP_STATE_ONLINE;
4465                 }
4466 
4467                 switch (port_top) {
4468                 case FC_TOP_FABRIC:
4469                 case FC_TOP_PUBLIC_LOOP:
4470                 case FC_TOP_PRIVATE_LOOP:
4471                 case FC_TOP_PT_PT:
4472 
4473                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4474                                 fcp_retry_ns_registry(pptr, port_sid);
4475                         }
4476 
4477                         fcp_handle_devices(pptr, devlist, dev_cnt, link_count,
4478                             map_tag, FCP_CAUSE_LINK_CHANGE);
4479                         break;
4480 
4481                 default:
4482                         /*
4483                          * We got here because we were provided with an unknown
4484                          * topology.
4485                          */
4486                         if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4487                                 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
4488                         }
4489 
4490                         pptr->port_tmp_cnt -= dev_cnt;
4491                         fcp_log(CE_WARN, pptr->port_dip,
4492                             "!unknown/unsupported topology (0x%x)", port_top);
4493                         break;
4494                 }
4495                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4496                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4497                     "Notify ssd of the reset to reinstate the reservations");
4498 
4499                 scsi_hba_reset_notify_callback(&pptr->port_mutex,
4500                     &pptr->port_reset_notify_listf);
4501 
4502                 mutex_exit(&pptr->port_mutex);
4503 
4504                 break;
4505 
4506         case FC_STATE_RESET:
4507                 ASSERT(pptr->port_state & FCP_STATE_OFFLINE);
4508                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4509                     fcp_trace, FCP_BUF_LEVEL_3, 0,
4510                     "RESET state, waiting for Offline/Online state_cb");
4511                 mutex_exit(&pptr->port_mutex);
4512                 break;
4513 
4514         case FC_STATE_DEVICE_CHANGE:
4515                 /*
4516                  * We come here when an application has requested
4517                  * Dynamic node creation/deletion in Fabric connectivity.
4518                  */
4519                 if (pptr->port_state & (FCP_STATE_OFFLINE |
4520                     FCP_STATE_INIT)) {
4521                         /*
4522                          * This case can happen when the FCTL is in the
4523                          * process of giving us on online and the host on
4524                          * the other side issues a PLOGI/PLOGO. Ideally
4525                          * the state changes should be serialized unless
4526                          * they are opposite (online-offline).
4527                          * The transport will give us a final state change
4528                          * so we can ignore this for the time being.
4529                          */
4530                         pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4531                         mutex_exit(&pptr->port_mutex);
4532                         break;
4533                 }
4534 
4535                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4536                         fcp_retry_ns_registry(pptr, port_sid);
4537                 }
4538 
4539                 /*
4540                  * Extend the deadline under steady state conditions
4541                  * to provide more time for the device-change-commands
4542                  */
4543                 if (!pptr->port_ipkt_cnt) {
4544                         pptr->port_deadline = fcp_watchdog_time +
4545                             FCP_ICMD_DEADLINE;
4546                 }
4547 
4548                 /*
4549                  * There is another race condition here, where if we were
4550                  * in ONLINEING state and a devices in the map logs out,
4551                  * fp will give another state change as DEVICE_CHANGE
4552                  * and OLD. This will result in that target being offlined.
4553                  * The pd_handle is freed. If from the first statec callback
4554                  * we were going to fire a PLOGI/PRLI, the system will
4555                  * panic in fc_ulp_transport with invalid pd_handle.
4556                  * The fix is to check for the link_cnt before issuing
4557                  * any command down.
4558                  */
4559                 fcp_update_targets(pptr, devlist, dev_cnt,
4560                     FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE);
4561 
4562                 link_count = pptr->port_link_cnt;
4563 
4564                 fcp_handle_devices(pptr, devlist, dev_cnt,
4565                     link_count, map_tag, FCP_CAUSE_TGT_CHANGE);
4566 
4567                 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC;
4568 
4569                 mutex_exit(&pptr->port_mutex);
4570                 break;
4571 
4572         case FC_STATE_TARGET_PORT_RESET:
4573                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
4574                         fcp_retry_ns_registry(pptr, port_sid);
4575                 }
4576 
4577                 /* Do nothing else */
4578                 mutex_exit(&pptr->port_mutex);
4579                 break;
4580 
4581         default:
4582                 fcp_log(CE_WARN, pptr->port_dip,
4583                     "!Invalid state change=0x%x", port_state);
4584                 mutex_exit(&pptr->port_mutex);
4585                 break;
4586         }
4587 
4588         if (map_tag) {
4589                 kmem_free(map_tag, map_len);
4590         }
4591 }
4592 
4593 /*
4594  *     Function: fcp_handle_devices
4595  *
4596  *  Description: This function updates the devices currently known by
4597  *               walking the list provided by the caller.  The list passed
4598  *               by the caller is supposed to be the list of reachable
4599  *               devices.
4600  *
4601  *     Argument: *pptr          Fcp port structure.
4602  *               *devlist       Pointer to the first entry of a table
4603  *                              containing the remote ports that can be
4604  *                              reached.
4605  *               dev_cnt        Number of entries pointed by devlist.
4606  *               link_cnt       Link state count.
4607  *               *map_tag       Array of fcp_map_tag_t structures.
4608  *               cause          What caused this function to be called.
4609  *
4610  * Return Value: None
4611  *
4612  *        Notes: The pptr->port_mutex must be held.
4613  */
4614 static void
4615 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[],
4616     uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause)
4617 {
4618         int                     i;
4619         int                     check_finish_init = 0;
4620         fc_portmap_t            *map_entry;
4621         struct fcp_tgt  *ptgt = NULL;
4622 
4623         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4624             fcp_trace, FCP_BUF_LEVEL_3, 0,
4625             "fcp_handle_devices: called for %d dev(s)", dev_cnt);
4626 
4627         if (dev_cnt) {
4628                 ASSERT(map_tag != NULL);
4629         }
4630 
4631         /*
4632          * The following code goes through the list of remote ports that are
4633          * accessible through this (pptr) local port (The list walked is the
4634          * one provided by the caller which is the list of the remote ports
4635          * currently reachable).  It checks if any of them was already
4636          * known by looking for the corresponding target structure based on
4637          * the world wide name.  If a target is part of the list it is tagged
4638          * (ptgt->tgt_aux_state = FCP_TGT_TAGGED).
4639          *
4640          * Old comment
4641          * -----------
4642          * Before we drop port mutex; we MUST get the tags updated; This
4643          * two step process is somewhat slow, but more reliable.
4644          */
4645         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4646                 map_entry = &(devlist[i]);
4647 
4648                 /*
4649                  * get ptr to this map entry in our port's
4650                  * list (if any)
4651                  */
4652                 ptgt = fcp_lookup_target(pptr,
4653                     (uchar_t *)&(map_entry->map_pwwn));
4654 
4655                 if (ptgt) {
4656                         map_tag[i] = ptgt->tgt_change_cnt;
4657                         if (cause == FCP_CAUSE_LINK_CHANGE) {
4658                                 ptgt->tgt_aux_state = FCP_TGT_TAGGED;
4659                         }
4660                 }
4661         }
4662 
4663         /*
4664          * At this point we know which devices of the new list were already
4665          * known (The field tgt_aux_state of the target structure has been
4666          * set to FCP_TGT_TAGGED).
4667          *
4668          * The following code goes through the list of targets currently known
4669          * by the local port (the list is actually a hashing table).  If a
4670          * target is found and is not tagged, it means the target cannot
4671          * be reached anymore through the local port (pptr).  It is offlined.
4672          * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE.
4673          */
4674         for (i = 0; i < FCP_NUM_HASH; i++) {
4675                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
4676                     ptgt = ptgt->tgt_next) {
4677                         mutex_enter(&ptgt->tgt_mutex);
4678                         if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) &&
4679                             (cause == FCP_CAUSE_LINK_CHANGE) &&
4680                             !(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4681                                 fcp_offline_target_now(pptr, ptgt,
4682                                     link_cnt, ptgt->tgt_change_cnt, 0);
4683                         }
4684                         mutex_exit(&ptgt->tgt_mutex);
4685                 }
4686         }
4687 
4688         /*
4689          * At this point, the devices that were known but cannot be reached
4690          * anymore, have most likely been offlined.
4691          *
4692          * The following section of code seems to go through the list of
4693          * remote ports that can now be reached.  For every single one it
4694          * checks if it is already known or if it is a new port.
4695          */
4696         for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) {
4697 
4698                 if (check_finish_init) {
4699                         ASSERT(i > 0);
4700                         (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4701                             map_tag[i - 1], cause);
4702                         check_finish_init = 0;
4703                 }
4704 
4705                 /* get a pointer to this map entry */
4706                 map_entry = &(devlist[i]);
4707 
4708                 /*
4709                  * Check for the duplicate map entry flag. If we have marked
4710                  * this entry as a duplicate we skip it since the correct
4711                  * (perhaps even same) state change will be encountered
4712                  * later in the list.
4713                  */
4714                 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) {
4715                         continue;
4716                 }
4717 
4718                 /* get ptr to this map entry in our port's list (if any) */
4719                 ptgt = fcp_lookup_target(pptr,
4720                     (uchar_t *)&(map_entry->map_pwwn));
4721 
4722                 if (ptgt) {
4723                         /*
4724                          * This device was already known.  The field
4725                          * tgt_aux_state is reset (was probably set to
4726                          * FCP_TGT_TAGGED previously in this routine).
4727                          */
4728                         ptgt->tgt_aux_state = 0;
4729                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4730                             fcp_trace, FCP_BUF_LEVEL_3, 0,
4731                             "handle_devices: map did/state/type/flags = "
4732                             "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, "
4733                             "tgt_state=%d",
4734                             map_entry->map_did.port_id, map_entry->map_state,
4735                             map_entry->map_type, map_entry->map_flags,
4736                             ptgt->tgt_d_id, ptgt->tgt_state);
4737                 }
4738 
4739                 if (map_entry->map_type == PORT_DEVICE_OLD ||
4740                     map_entry->map_type == PORT_DEVICE_NEW ||
4741                     map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED ||
4742                     map_entry->map_type == PORT_DEVICE_CHANGED) {
4743                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
4744                             fcp_trace, FCP_BUF_LEVEL_2, 0,
4745                             "map_type=%x, did = %x",
4746                             map_entry->map_type,
4747                             map_entry->map_did.port_id);
4748                 }
4749 
4750                 switch (map_entry->map_type) {
4751                 case PORT_DEVICE_NOCHANGE:
4752                 case PORT_DEVICE_USER_CREATE:
4753                 case PORT_DEVICE_USER_LOGIN:
4754                 case PORT_DEVICE_NEW:
4755                 case PORT_DEVICE_REPORTLUN_CHANGED:
4756                         FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1);
4757 
4758                         if (fcp_handle_mapflags(pptr, ptgt, map_entry,
4759                             link_cnt, (ptgt) ? map_tag[i] : 0,
4760                             cause) == TRUE) {
4761 
4762                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4763                                     FCP_TGT_TRACE_2);
4764                                 check_finish_init++;
4765                         }
4766                         break;
4767 
4768                 case PORT_DEVICE_OLD:
4769                         if (ptgt != NULL) {
4770                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4771                                     FCP_TGT_TRACE_3);
4772 
4773                                 mutex_enter(&ptgt->tgt_mutex);
4774                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4775                                         /*
4776                                          * Must do an in-line wait for I/Os
4777                                          * to get drained
4778                                          */
4779                                         mutex_exit(&ptgt->tgt_mutex);
4780                                         mutex_exit(&pptr->port_mutex);
4781 
4782                                         mutex_enter(&ptgt->tgt_mutex);
4783                                         while (ptgt->tgt_ipkt_cnt ||
4784                                             fcp_outstanding_lun_cmds(ptgt)
4785                                             == FC_SUCCESS) {
4786                                                 mutex_exit(&ptgt->tgt_mutex);
4787                                                 delay(drv_usectohz(1000000));
4788                                                 mutex_enter(&ptgt->tgt_mutex);
4789                                         }
4790                                         mutex_exit(&ptgt->tgt_mutex);
4791 
4792                                         mutex_enter(&pptr->port_mutex);
4793                                         mutex_enter(&ptgt->tgt_mutex);
4794 
4795                                         (void) fcp_offline_target(pptr, ptgt,
4796                                             link_cnt, map_tag[i], 0, 0);
4797                                 }
4798                                 mutex_exit(&ptgt->tgt_mutex);
4799                         }
4800                         check_finish_init++;
4801                         break;
4802 
4803                 case PORT_DEVICE_USER_DELETE:
4804                 case PORT_DEVICE_USER_LOGOUT:
4805                         if (ptgt != NULL) {
4806                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4807                                     FCP_TGT_TRACE_4);
4808 
4809                                 mutex_enter(&ptgt->tgt_mutex);
4810                                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
4811                                         (void) fcp_offline_target(pptr, ptgt,
4812                                             link_cnt, map_tag[i], 1, 0);
4813                                 }
4814                                 mutex_exit(&ptgt->tgt_mutex);
4815                         }
4816                         check_finish_init++;
4817                         break;
4818 
4819                 case PORT_DEVICE_CHANGED:
4820                         if (ptgt != NULL) {
4821                                 FCP_TGT_TRACE(ptgt, map_tag[i],
4822                                     FCP_TGT_TRACE_5);
4823 
4824                                 if (fcp_device_changed(pptr, ptgt,
4825                                     map_entry, link_cnt, map_tag[i],
4826                                     cause) == TRUE) {
4827                                         check_finish_init++;
4828                                 }
4829                         } else {
4830                                 if (fcp_handle_mapflags(pptr, ptgt,
4831                                     map_entry, link_cnt, 0, cause) == TRUE) {
4832                                         check_finish_init++;
4833                                 }
4834                         }
4835                         break;
4836 
4837                 default:
4838                         fcp_log(CE_WARN, pptr->port_dip,
4839                             "!Invalid map_type=0x%x", map_entry->map_type);
4840                         check_finish_init++;
4841                         break;
4842                 }
4843         }
4844 
4845         if (check_finish_init && pptr->port_link_cnt == link_cnt) {
4846                 ASSERT(i > 0);
4847                 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt,
4848                     map_tag[i-1], cause);
4849         } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) {
4850                 fcp_offline_all(pptr, link_cnt, cause);
4851         }
4852 }
4853 
4854 static int
4855 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause)
4856 {
4857         struct fcp_lun  *plun;
4858         struct fcp_port *pptr;
4859         int              rscn_count;
4860         int              lun0_newalloc;
4861         int              ret  = TRUE;
4862 
4863         ASSERT(ptgt);
4864         pptr = ptgt->tgt_port;
4865         lun0_newalloc = 0;
4866         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
4867                 /*
4868                  * no LUN struct for LUN 0 yet exists,
4869                  * so create one
4870                  */
4871                 plun = fcp_alloc_lun(ptgt);
4872                 if (plun == NULL) {
4873                         fcp_log(CE_WARN, pptr->port_dip,
4874                             "!Failed to allocate lun 0 for"
4875                             " D_ID=%x", ptgt->tgt_d_id);
4876                         return (ret);
4877                 }
4878                 lun0_newalloc = 1;
4879         }
4880 
4881         mutex_enter(&ptgt->tgt_mutex);
4882         /*
4883          * consider lun 0 as device not connected if it is
4884          * offlined or newly allocated
4885          */
4886         if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) {
4887                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
4888         }
4889         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
4890         plun->lun_state &= ~FCP_LUN_OFFLINE;
4891         ptgt->tgt_lun_cnt = 1;
4892         ptgt->tgt_report_lun_cnt = 0;
4893         mutex_exit(&ptgt->tgt_mutex);
4894 
4895         rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle);
4896         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
4897             sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt,
4898             ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) {
4899                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
4900                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN "
4901                     "to D_ID=%x", ptgt->tgt_d_id);
4902         } else {
4903                 ret = FALSE;
4904         }
4905 
4906         return (ret);
4907 }
4908 
4909 /*
4910  *     Function: fcp_handle_mapflags
4911  *
4912  *  Description: This function creates a target structure if the ptgt passed
4913  *               is NULL.  It also kicks off the PLOGI if we are not logged
4914  *               into the target yet or the PRLI if we are logged into the
4915  *               target already.  The rest of the treatment is done in the
4916  *               callbacks of the PLOGI or PRLI.
4917  *
4918  *     Argument: *pptr          FCP Port structure.
4919  *               *ptgt          Target structure.
4920  *               *map_entry     Array of fc_portmap_t structures.
4921  *               link_cnt       Link state count.
4922  *               tgt_cnt        Target state count.
4923  *               cause          What caused this function to be called.
4924  *
4925  * Return Value: TRUE   Failed
4926  *               FALSE  Succeeded
4927  *
4928  *        Notes: pptr->port_mutex must be owned.
4929  */
4930 static int
4931 fcp_handle_mapflags(struct fcp_port     *pptr, struct fcp_tgt   *ptgt,
4932     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
4933 {
4934         int                     lcount;
4935         int                     tcount;
4936         int                     ret = TRUE;
4937         int                     alloc;
4938         struct fcp_ipkt *icmd;
4939         struct fcp_lun  *pseq_lun = NULL;
4940         uchar_t                 opcode;
4941         int                     valid_ptgt_was_passed = FALSE;
4942 
4943         ASSERT(mutex_owned(&pptr->port_mutex));
4944 
4945         /*
4946          * This case is possible where the FCTL has come up and done discovery
4947          * before FCP was loaded and attached. FCTL would have discovered the
4948          * devices and later the ULP came online. In this case ULP's would get
4949          * PORT_DEVICE_NOCHANGE but target would be NULL.
4950          */
4951         if (ptgt == NULL) {
4952                 /* don't already have a target */
4953                 mutex_exit(&pptr->port_mutex);
4954                 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt);
4955                 mutex_enter(&pptr->port_mutex);
4956 
4957                 if (ptgt == NULL) {
4958                         fcp_log(CE_WARN, pptr->port_dip,
4959                             "!FC target allocation failed");
4960                         return (ret);
4961                 }
4962                 mutex_enter(&ptgt->tgt_mutex);
4963                 ptgt->tgt_statec_cause = cause;
4964                 ptgt->tgt_tmp_cnt = 1;
4965                 mutex_exit(&ptgt->tgt_mutex);
4966         } else {
4967                 valid_ptgt_was_passed = TRUE;
4968         }
4969 
4970         /*
4971          * Copy in the target parameters
4972          */
4973         mutex_enter(&ptgt->tgt_mutex);
4974         ptgt->tgt_d_id = map_entry->map_did.port_id;
4975         ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr;
4976         ptgt->tgt_pd_handle = map_entry->map_pd;
4977         ptgt->tgt_fca_dev = NULL;
4978 
4979         /* Copy port and node WWNs */
4980         bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0],
4981             FC_WWN_SIZE);
4982         bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0],
4983             FC_WWN_SIZE);
4984 
4985         if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) &&
4986             (map_entry->map_type == PORT_DEVICE_NOCHANGE) &&
4987             (map_entry->map_state == PORT_DEVICE_LOGGED_IN) &&
4988             valid_ptgt_was_passed) {
4989                 /*
4990                  * determine if there are any tape LUNs on this target
4991                  */
4992                 for (pseq_lun = ptgt->tgt_lun;
4993                     pseq_lun != NULL;
4994                     pseq_lun = pseq_lun->lun_next) {
4995                         if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) &&
4996                             !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) {
4997                                 fcp_update_tgt_state(ptgt, FCP_RESET,
4998                                     FCP_LUN_MARK);
4999                                 mutex_exit(&ptgt->tgt_mutex);
5000                                 return (ret);
5001                         }
5002                 }
5003         }
5004 
5005         /*
5006          * if UA'REPORT_LUN_CHANGED received,
5007          * send out REPORT LUN promptly, skip PLOGI/PRLI process
5008          */
5009         if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) {
5010                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK);
5011                 mutex_exit(&ptgt->tgt_mutex);
5012                 mutex_exit(&pptr->port_mutex);
5013 
5014                 ret = fcp_handle_reportlun_changed(ptgt, cause);
5015 
5016                 mutex_enter(&pptr->port_mutex);
5017                 return (ret);
5018         }
5019 
5020         /*
5021          * If ptgt was NULL when this function was entered, then tgt_node_state
5022          * was never specifically initialized but zeroed out which means
5023          * FCP_TGT_NODE_NONE.
5024          */
5025         switch (ptgt->tgt_node_state) {
5026         case FCP_TGT_NODE_NONE:
5027         case FCP_TGT_NODE_ON_DEMAND:
5028                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5029                     !fcp_enable_auto_configuration &&
5030                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5031                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5032                 } else if (FC_TOP_EXTERNAL(pptr->port_topology) &&
5033                     fcp_enable_auto_configuration &&
5034                     (ptgt->tgt_manual_config_only == 1) &&
5035                     map_entry->map_type != PORT_DEVICE_USER_CREATE) {
5036                         /*
5037                          * If auto configuration is set and
5038                          * the tgt_manual_config_only flag is set then
5039                          * we only want the user to be able to change
5040                          * the state through create_on_demand.
5041                          */
5042                         ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND;
5043                 } else {
5044                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5045                 }
5046                 break;
5047 
5048         case FCP_TGT_NODE_PRESENT:
5049                 break;
5050         }
5051         /*
5052          * If we are booting from a fabric device, make sure we
5053          * mark the node state appropriately for this target to be
5054          * enumerated
5055          */
5056         if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) {
5057                 if (bcmp((caddr_t)pptr->port_boot_wwn,
5058                     (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
5059                     sizeof (ptgt->tgt_port_wwn)) == 0) {
5060                         ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
5061                 }
5062         }
5063         mutex_exit(&ptgt->tgt_mutex);
5064 
5065         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5066             fcp_trace, FCP_BUF_LEVEL_3, 0,
5067             "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x",
5068             map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id,
5069             map_entry->map_rscn_info.ulp_rscn_count);
5070 
5071         mutex_enter(&ptgt->tgt_mutex);
5072 
5073         /*
5074          * Reset target OFFLINE state and mark the target BUSY
5075          */
5076         ptgt->tgt_state &= ~FCP_TGT_OFFLINE;
5077         ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK);
5078 
5079         tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
5080         lcount = link_cnt;
5081 
5082         mutex_exit(&ptgt->tgt_mutex);
5083         mutex_exit(&pptr->port_mutex);
5084 
5085         /*
5086          * if we are already logged in, then we do a PRLI, else
5087          * we do a PLOGI first (to get logged in)
5088          *
5089          * We will not check if we are the PLOGI initiator
5090          */
5091         opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN &&
5092             map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI;
5093 
5094         alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t));
5095 
5096         icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5097             pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount,
5098             cause, map_entry->map_rscn_info.ulp_rscn_count);
5099 
5100         if (icmd == NULL) {
5101                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29);
5102                 /*
5103                  * We've exited port_mutex before calling fcp_icmd_alloc,
5104                  * we need to make sure we reacquire it before returning.
5105                  */
5106                 mutex_enter(&pptr->port_mutex);
5107                 return (FALSE);
5108         }
5109 
5110         /* TRUE is only returned while target is intended skipped */
5111         ret = FALSE;
5112         /* discover info about this target */
5113         if ((fcp_send_els(pptr, ptgt, icmd, opcode,
5114             lcount, tcount, cause)) == DDI_SUCCESS) {
5115                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9);
5116         } else {
5117                 fcp_icmd_free(pptr, icmd);
5118                 ret = TRUE;
5119         }
5120         mutex_enter(&pptr->port_mutex);
5121 
5122         return (ret);
5123 }
5124 
5125 /*
5126  *     Function: fcp_send_els
5127  *
5128  *  Description: Sends an ELS to the target specified by the caller.  Supports
5129  *               PLOGI and PRLI.
5130  *
5131  *     Argument: *pptr          Fcp port.
5132  *               *ptgt          Target to send the ELS to.
5133  *               *icmd          Internal packet
5134  *               opcode         ELS opcode
5135  *               lcount         Link state change counter
5136  *               tcount         Target state change counter
5137  *               cause          What caused the call
5138  *
5139  * Return Value: DDI_SUCCESS
5140  *               Others
5141  */
5142 static int
5143 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt,
5144     struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause)
5145 {
5146         fc_packet_t             *fpkt;
5147         fc_frame_hdr_t          *hp;
5148         int                     internal = 0;
5149         int                     alloc;
5150         int                     cmd_len;
5151         int                     resp_len;
5152         int                     res = DDI_FAILURE; /* default result */
5153         int                     rval = DDI_FAILURE;
5154 
5155         ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI);
5156         ASSERT(ptgt->tgt_port == pptr);
5157 
5158         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5159             fcp_trace, FCP_BUF_LEVEL_5, 0,
5160             "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode,
5161             (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI");
5162 
5163         if (opcode == LA_ELS_PLOGI) {
5164                 cmd_len = sizeof (la_els_logi_t);
5165                 resp_len = sizeof (la_els_logi_t);
5166         } else {
5167                 ASSERT(opcode == LA_ELS_PRLI);
5168                 cmd_len = sizeof (la_els_prli_t);
5169                 resp_len = sizeof (la_els_prli_t);
5170         }
5171 
5172         if (icmd == NULL) {
5173                 alloc = FCP_MAX(sizeof (la_els_logi_t),
5174                     sizeof (la_els_prli_t));
5175                 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0,
5176                     pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5177                     lcount, tcount, cause, FC_INVALID_RSCN_COUNT);
5178                 if (icmd == NULL) {
5179                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10);
5180                         return (res);
5181                 }
5182                 internal++;
5183         }
5184         fpkt = icmd->ipkt_fpkt;
5185 
5186         fpkt->pkt_cmdlen = cmd_len;
5187         fpkt->pkt_rsplen = resp_len;
5188         fpkt->pkt_datalen = 0;
5189         icmd->ipkt_retries = 0;
5190 
5191         /* fill in fpkt info */
5192         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5193         fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
5194         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5195 
5196         /* get ptr to frame hdr in fpkt */
5197         hp = &fpkt->pkt_cmd_fhdr;
5198 
5199         /*
5200          * fill in frame hdr
5201          */
5202         hp->r_ctl = R_CTL_ELS_REQ;
5203         hp->s_id = pptr->port_id; /* source ID */
5204         hp->d_id = ptgt->tgt_d_id;        /* dest ID */
5205         hp->type = FC_TYPE_EXTENDED_LS;
5206         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
5207         hp->seq_id = 0;
5208         hp->rsvd = 0;
5209         hp->df_ctl  = 0;
5210         hp->seq_cnt = 0;
5211         hp->ox_id = 0xffff;          /* i.e. none */
5212         hp->rx_id = 0xffff;          /* i.e. none */
5213         hp->ro = 0;
5214 
5215         /*
5216          * at this point we have a filled in cmd pkt
5217          *
5218          * fill in the respective info, then use the transport to send
5219          * the packet
5220          *
5221          * for a PLOGI call fc_ulp_login(), and
5222          * for a PRLI call fc_ulp_issue_els()
5223          */
5224         switch (opcode) {
5225         case LA_ELS_PLOGI: {
5226                 struct la_els_logi logi;
5227 
5228                 bzero(&logi, sizeof (struct la_els_logi));
5229 
5230                 hp = &fpkt->pkt_cmd_fhdr;
5231                 hp->r_ctl = R_CTL_ELS_REQ;
5232                 logi.ls_code.ls_code = LA_ELS_PLOGI;
5233                 logi.ls_code.mbz = 0;
5234 
5235                 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd,
5236                     fpkt->pkt_cmd_acc, sizeof (struct la_els_logi));
5237 
5238                 icmd->ipkt_opcode = LA_ELS_PLOGI;
5239 
5240                 mutex_enter(&pptr->port_mutex);
5241                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5242 
5243                         mutex_exit(&pptr->port_mutex);
5244 
5245                         rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1);
5246                         if (rval == FC_SUCCESS) {
5247                                 res = DDI_SUCCESS;
5248                                 break;
5249                         }
5250 
5251                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11);
5252 
5253                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5254                             rval, "PLOGI");
5255                 } else {
5256                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5257                             fcp_trace, FCP_BUF_LEVEL_5, 0,
5258                             "fcp_send_els1: state change occured"
5259                             " for D_ID=0x%x", ptgt->tgt_d_id);
5260                         mutex_exit(&pptr->port_mutex);
5261                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12);
5262                 }
5263                 break;
5264         }
5265 
5266         case LA_ELS_PRLI: {
5267                 struct la_els_prli      prli;
5268                 struct fcp_prli         *fprli;
5269 
5270                 bzero(&prli, sizeof (struct la_els_prli));
5271 
5272                 hp = &fpkt->pkt_cmd_fhdr;
5273                 hp->r_ctl = R_CTL_ELS_REQ;
5274 
5275                 /* fill in PRLI cmd ELS fields */
5276                 prli.ls_code = LA_ELS_PRLI;
5277                 prli.page_length = 0x10;        /* huh? */
5278                 prli.payload_length = sizeof (struct la_els_prli);
5279 
5280                 icmd->ipkt_opcode = LA_ELS_PRLI;
5281 
5282                 /* get ptr to PRLI service params */
5283                 fprli = (struct fcp_prli *)prli.service_params;
5284 
5285                 /* fill in service params */
5286                 fprli->type = 0x08;
5287                 fprli->resvd1 = 0;
5288                 fprli->orig_process_assoc_valid = 0;
5289                 fprli->resp_process_assoc_valid = 0;
5290                 fprli->establish_image_pair = 1;
5291                 fprli->resvd2 = 0;
5292                 fprli->resvd3 = 0;
5293                 fprli->obsolete_1 = 0;
5294                 fprli->obsolete_2 = 0;
5295                 fprli->data_overlay_allowed = 0;
5296                 fprli->initiator_fn = 1;
5297                 fprli->confirmed_compl_allowed = 1;
5298 
5299                 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5300                         fprli->target_fn = 1;
5301                 } else {
5302                         fprli->target_fn = 0;
5303                 }
5304 
5305                 fprli->retry = 1;
5306                 fprli->read_xfer_rdy_disabled = 1;
5307                 fprli->write_xfer_rdy_disabled = 0;
5308 
5309                 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5310                     fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5311 
5312                 /* issue the PRLI request */
5313 
5314                 mutex_enter(&pptr->port_mutex);
5315                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
5316 
5317                         mutex_exit(&pptr->port_mutex);
5318 
5319                         rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt);
5320                         if (rval == FC_SUCCESS) {
5321                                 res = DDI_SUCCESS;
5322                                 break;
5323                         }
5324 
5325                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13);
5326 
5327                         res = fcp_handle_ipkt_errors(pptr, ptgt, icmd,
5328                             rval, "PRLI");
5329                 } else {
5330                         mutex_exit(&pptr->port_mutex);
5331                         FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14);
5332                 }
5333                 break;
5334         }
5335 
5336         default:
5337                 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode);
5338                 break;
5339         }
5340 
5341         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5342             fcp_trace, FCP_BUF_LEVEL_5, 0,
5343             "fcp_send_els: returning %d", res);
5344 
5345         if (res != DDI_SUCCESS) {
5346                 if (internal) {
5347                         fcp_icmd_free(pptr, icmd);
5348                 }
5349         }
5350 
5351         return (res);
5352 }
5353 
5354 
5355 /*
5356  * called internally update the state of all of the tgts and each LUN
5357  * for this port (i.e. each target  known to be attached to this port)
5358  * if they are not already offline
5359  *
5360  * must be called with the port mutex owned
5361  *
5362  * acquires and releases the target mutexes for each target attached
5363  * to this port
5364  */
5365 void
5366 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause)
5367 {
5368         int i;
5369         struct fcp_tgt *ptgt;
5370 
5371         ASSERT(mutex_owned(&pptr->port_mutex));
5372 
5373         for (i = 0; i < FCP_NUM_HASH; i++) {
5374                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5375                     ptgt = ptgt->tgt_next) {
5376                         mutex_enter(&ptgt->tgt_mutex);
5377                         fcp_update_tgt_state(ptgt, FCP_SET, state);
5378                         ptgt->tgt_change_cnt++;
5379                         ptgt->tgt_statec_cause = cause;
5380                         ptgt->tgt_tmp_cnt = 1;
5381                         ptgt->tgt_done = 0;
5382                         mutex_exit(&ptgt->tgt_mutex);
5383                 }
5384         }
5385 }
5386 
5387 
5388 static void
5389 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause)
5390 {
5391         int i;
5392         int ndevs;
5393         struct fcp_tgt *ptgt;
5394 
5395         ASSERT(mutex_owned(&pptr->port_mutex));
5396 
5397         for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) {
5398                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5399                     ptgt = ptgt->tgt_next) {
5400                         ndevs++;
5401                 }
5402         }
5403 
5404         if (ndevs == 0) {
5405                 return;
5406         }
5407         pptr->port_tmp_cnt = ndevs;
5408 
5409         for (i = 0; i < FCP_NUM_HASH; i++) {
5410                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
5411                     ptgt = ptgt->tgt_next) {
5412                         (void) fcp_call_finish_init_held(pptr, ptgt,
5413                             lcount, ptgt->tgt_change_cnt, cause);
5414                 }
5415         }
5416 }
5417 
5418 /*
5419  *     Function: fcp_update_tgt_state
5420  *
5421  *  Description: This function updates the field tgt_state of a target.  That
5422  *               field is a bitmap and which bit can be set or reset
5423  *               individually.  The action applied to the target state is also
5424  *               applied to all the LUNs belonging to the target (provided the
5425  *               LUN is not offline).  A side effect of applying the state
5426  *               modification to the target and the LUNs is the field tgt_trace
5427  *               of the target and lun_trace of the LUNs is set to zero.
5428  *
5429  *
5430  *     Argument: *ptgt  Target structure.
5431  *               flag   Flag indication what action to apply (set/reset).
5432  *               state  State bits to update.
5433  *
5434  * Return Value: None
5435  *
5436  *      Context: Interrupt, Kernel or User context.
5437  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5438  *               calling this function.
5439  */
5440 void
5441 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state)
5442 {
5443         struct fcp_lun *plun;
5444 
5445         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5446 
5447         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
5448                 /* The target is not offline. */
5449                 if (flag == FCP_SET) {
5450                         ptgt->tgt_state |= state;
5451                         ptgt->tgt_trace = 0;
5452                 } else {
5453                         ptgt->tgt_state &= ~state;
5454                 }
5455 
5456                 for (plun = ptgt->tgt_lun; plun != NULL;
5457                     plun = plun->lun_next) {
5458                         if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
5459                                 /* The LUN is not offline. */
5460                                 if (flag == FCP_SET) {
5461                                         plun->lun_state |= state;
5462                                         plun->lun_trace = 0;
5463                                 } else {
5464                                         plun->lun_state &= ~state;
5465                                 }
5466                         }
5467                 }
5468         }
5469 }
5470 
5471 /*
5472  *     Function: fcp_update_tgt_state
5473  *
5474  *  Description: This function updates the field lun_state of a LUN.  That
5475  *               field is a bitmap and which bit can be set or reset
5476  *               individually.
5477  *
5478  *     Argument: *plun  LUN structure.
5479  *               flag   Flag indication what action to apply (set/reset).
5480  *               state  State bits to update.
5481  *
5482  * Return Value: None
5483  *
5484  *      Context: Interrupt, Kernel or User context.
5485  *               The mutex of the target (ptgt->tgt_mutex) must be owned when
5486  *               calling this function.
5487  */
5488 void
5489 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state)
5490 {
5491         struct fcp_tgt  *ptgt = plun->lun_tgt;
5492 
5493         ASSERT(mutex_owned(&ptgt->tgt_mutex));
5494 
5495         if (!(plun->lun_state & FCP_TGT_OFFLINE)) {
5496                 if (flag == FCP_SET) {
5497                         plun->lun_state |= state;
5498                 } else {
5499                         plun->lun_state &= ~state;
5500                 }
5501         }
5502 }
5503 
5504 /*
5505  *     Function: fcp_get_port
5506  *
5507  *  Description: This function returns the fcp_port structure from the opaque
5508  *               handle passed by the caller.  That opaque handle is the handle
5509  *               used by fp/fctl to identify a particular local port.  That
5510  *               handle has been stored in the corresponding fcp_port
5511  *               structure.  This function is going to walk the global list of
5512  *               fcp_port structures till one has a port_fp_handle that matches
5513  *               the handle passed by the caller.  This function enters the
5514  *               mutex fcp_global_mutex while walking the global list and then
5515  *               releases it.
5516  *
5517  *     Argument: port_handle    Opaque handle that fp/fctl uses to identify a
5518  *                              particular port.
5519  *
5520  * Return Value: NULL           Not found.
5521  *               Not NULL       Pointer to the fcp_port structure.
5522  *
5523  *      Context: Interrupt, Kernel or User context.
5524  */
5525 static struct fcp_port *
5526 fcp_get_port(opaque_t port_handle)
5527 {
5528         struct fcp_port *pptr;
5529 
5530         ASSERT(port_handle != NULL);
5531 
5532         mutex_enter(&fcp_global_mutex);
5533         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
5534                 if (pptr->port_fp_handle == port_handle) {
5535                         break;
5536                 }
5537         }
5538         mutex_exit(&fcp_global_mutex);
5539 
5540         return (pptr);
5541 }
5542 
5543 
5544 static void
5545 fcp_unsol_callback(fc_packet_t *fpkt)
5546 {
5547         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
5548         struct fcp_port *pptr = icmd->ipkt_port;
5549 
5550         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
5551                 caddr_t state, reason, action, expln;
5552 
5553                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
5554                     &action, &expln);
5555 
5556                 fcp_log(CE_WARN, pptr->port_dip,
5557                     "!couldn't post response to unsolicited request: "
5558                     " state=%s reason=%s rx_id=%x ox_id=%x",
5559                     state, reason, fpkt->pkt_cmd_fhdr.ox_id,
5560                     fpkt->pkt_cmd_fhdr.rx_id);
5561         }
5562         fcp_icmd_free(pptr, icmd);
5563 }
5564 
5565 
5566 /*
5567  * Perform general purpose preparation of a response to an unsolicited request
5568  */
5569 static void
5570 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf,
5571     uchar_t r_ctl, uchar_t type)
5572 {
5573         pkt->pkt_cmd_fhdr.r_ctl = r_ctl;
5574         pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id;
5575         pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id;
5576         pkt->pkt_cmd_fhdr.type = type;
5577         pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT;
5578         pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id;
5579         pkt->pkt_cmd_fhdr.df_ctl  = buf->ub_frame.df_ctl;
5580         pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt;
5581         pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id;
5582         pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id;
5583         pkt->pkt_cmd_fhdr.ro = 0;
5584         pkt->pkt_cmd_fhdr.rsvd = 0;
5585         pkt->pkt_comp = fcp_unsol_callback;
5586         pkt->pkt_pd = NULL;
5587         pkt->pkt_ub_resp_token = (opaque_t)buf;
5588 }
5589 
5590 
5591 /*ARGSUSED*/
5592 static int
5593 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf)
5594 {
5595         fc_packet_t             *fpkt;
5596         struct la_els_prli      prli;
5597         struct fcp_prli         *fprli;
5598         struct fcp_ipkt *icmd;
5599         struct la_els_prli      *from;
5600         struct fcp_prli         *orig;
5601         struct fcp_tgt  *ptgt;
5602         int                     tcount = 0;
5603         int                     lcount;
5604 
5605         from = (struct la_els_prli *)buf->ub_buffer;
5606         orig = (struct fcp_prli *)from->service_params;
5607         if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) !=
5608             NULL) {
5609                 mutex_enter(&ptgt->tgt_mutex);
5610                 tcount = ptgt->tgt_change_cnt;
5611                 mutex_exit(&ptgt->tgt_mutex);
5612         }
5613 
5614         mutex_enter(&pptr->port_mutex);
5615         lcount = pptr->port_link_cnt;
5616         mutex_exit(&pptr->port_mutex);
5617 
5618         if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t),
5619             sizeof (la_els_prli_t), 0,
5620             pptr->port_state & FCP_STATE_FCA_IS_NODMA,
5621             lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) {
5622                 return (FC_FAILURE);
5623         }
5624 
5625         fpkt = icmd->ipkt_fpkt;
5626         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
5627         fpkt->pkt_tran_type = FC_PKT_OUTBOUND;
5628         fpkt->pkt_timeout = FCP_ELS_TIMEOUT;
5629         fpkt->pkt_cmdlen = sizeof (la_els_prli_t);
5630         fpkt->pkt_rsplen = 0;
5631         fpkt->pkt_datalen = 0;
5632 
5633         icmd->ipkt_opcode = LA_ELS_PRLI;
5634 
5635         bzero(&prli, sizeof (struct la_els_prli));
5636         fprli = (struct fcp_prli *)prli.service_params;
5637         prli.ls_code = LA_ELS_ACC;
5638         prli.page_length = 0x10;
5639         prli.payload_length = sizeof (struct la_els_prli);
5640 
5641         /* fill in service params */
5642         fprli->type = 0x08;
5643         fprli->resvd1 = 0;
5644         fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid;
5645         fprli->orig_process_associator = orig->orig_process_associator;
5646         fprli->resp_process_assoc_valid = 0;
5647         fprli->establish_image_pair = 1;
5648         fprli->resvd2 = 0;
5649         fprli->resvd3 = 0;
5650         fprli->obsolete_1 = 0;
5651         fprli->obsolete_2 = 0;
5652         fprli->data_overlay_allowed = 0;
5653         fprli->initiator_fn = 1;
5654         fprli->confirmed_compl_allowed = 1;
5655 
5656         if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) {
5657                 fprli->target_fn = 1;
5658         } else {
5659                 fprli->target_fn = 0;
5660         }
5661 
5662         fprli->retry = 1;
5663         fprli->read_xfer_rdy_disabled = 1;
5664         fprli->write_xfer_rdy_disabled = 0;
5665 
5666         /* save the unsol prli payload first */
5667         FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp,
5668             fpkt->pkt_resp_acc, sizeof (struct la_els_prli));
5669 
5670         FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd,
5671             fpkt->pkt_cmd_acc, sizeof (struct la_els_prli));
5672 
5673         fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS);
5674 
5675         mutex_enter(&pptr->port_mutex);
5676         if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) {
5677                 int rval;
5678                 mutex_exit(&pptr->port_mutex);
5679 
5680                 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) !=
5681                     FC_SUCCESS) {
5682                         if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) &&
5683                             ptgt != NULL) {
5684                                 fcp_queue_ipkt(pptr, fpkt);
5685                                 return (FC_SUCCESS);
5686                         }
5687                         /* Let it timeout */
5688                         fcp_icmd_free(pptr, icmd);
5689                         return (FC_FAILURE);
5690                 }
5691         } else {
5692                 mutex_exit(&pptr->port_mutex);
5693                 fcp_icmd_free(pptr, icmd);
5694                 return (FC_FAILURE);
5695         }
5696 
5697         (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token);
5698 
5699         return (FC_SUCCESS);
5700 }
5701 
5702 /*
5703  *     Function: fcp_icmd_alloc
5704  *
5705  *  Description: This function allocated a fcp_ipkt structure.  The pkt_comp
5706  *               field is initialized to fcp_icmd_callback.  Sometimes it is
5707  *               modified by the caller (such as fcp_send_scsi).  The
5708  *               structure is also tied to the state of the line and of the
5709  *               target at a particular time.  That link is established by
5710  *               setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount
5711  *               and tcount which came respectively from pptr->link_cnt and
5712  *               ptgt->tgt_change_cnt.
5713  *
5714  *     Argument: *pptr          Fcp port.
5715  *               *ptgt          Target (destination of the command).
5716  *               cmd_len        Length of the command.
5717  *               resp_len       Length of the expected response.
5718  *               data_len       Length of the data.
5719  *               nodma          Indicates weither the command and response.
5720  *                              will be transfer through DMA or not.
5721  *               lcount         Link state change counter.
5722  *               tcount         Target state change counter.
5723  *               cause          Reason that lead to this call.
5724  *
5725  * Return Value: NULL           Failed.
5726  *               Not NULL       Internal packet address.
5727  */
5728 static struct fcp_ipkt *
5729 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len,
5730     int resp_len, int data_len, int nodma, int lcount, int tcount, int cause,
5731     uint32_t rscn_count)
5732 {
5733         int                     dma_setup = 0;
5734         fc_packet_t             *fpkt;
5735         struct fcp_ipkt *icmd = NULL;
5736 
5737         icmd = kmem_zalloc(sizeof (struct fcp_ipkt) +
5738             pptr->port_dmacookie_sz + pptr->port_priv_pkt_len,
5739             KM_NOSLEEP);
5740         if (icmd == NULL) {
5741                 fcp_log(CE_WARN, pptr->port_dip,
5742                     "!internal packet allocation failed");
5743                 return (NULL);
5744         }
5745 
5746         /*
5747          * initialize the allocated packet
5748          */
5749         icmd->ipkt_nodma = nodma;
5750         icmd->ipkt_next = icmd->ipkt_prev = NULL;
5751         icmd->ipkt_lun = NULL;
5752 
5753         icmd->ipkt_link_cnt = lcount;
5754         icmd->ipkt_change_cnt = tcount;
5755         icmd->ipkt_cause = cause;
5756 
5757         mutex_enter(&pptr->port_mutex);
5758         icmd->ipkt_port = pptr;
5759         mutex_exit(&pptr->port_mutex);
5760 
5761         /* keep track of amt of data to be sent in pkt */
5762         icmd->ipkt_cmdlen = cmd_len;
5763         icmd->ipkt_resplen = resp_len;
5764         icmd->ipkt_datalen = data_len;
5765 
5766         /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */
5767         icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet);
5768 
5769         /* set pkt's private ptr to point to cmd pkt */
5770         icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd;
5771 
5772         /* set FCA private ptr to memory just beyond */
5773         icmd->ipkt_fpkt->pkt_fca_private = (opaque_t)
5774             ((char *)icmd + sizeof (struct fcp_ipkt) +
5775             pptr->port_dmacookie_sz);
5776 
5777         /* get ptr to fpkt substruct and fill it in */
5778         fpkt = icmd->ipkt_fpkt;
5779         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd +
5780             sizeof (struct fcp_ipkt));
5781 
5782         if (ptgt != NULL) {
5783                 icmd->ipkt_tgt = ptgt;
5784                 fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
5785         }
5786 
5787         fpkt->pkt_comp = fcp_icmd_callback;
5788         fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
5789         fpkt->pkt_cmdlen = cmd_len;
5790         fpkt->pkt_rsplen = resp_len;
5791         fpkt->pkt_datalen = data_len;
5792 
5793         /*
5794          * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the
5795          * rscn_count as fcp knows down to the transport. If a valid count was
5796          * passed into this function, we allocate memory to actually pass down
5797          * this info.
5798          *
5799          * BTW, if the kmem_zalloc fails, we won't try too hard. This will
5800          * basically mean that fcp will not be able to help transport
5801          * distinguish if a new RSCN has come after fcp was last informed about
5802          * it. In such cases, it might lead to the problem mentioned in CR/bug #
5803          * 5068068 where the device might end up going offline in case of RSCN
5804          * storms.
5805          */
5806         fpkt->pkt_ulp_rscn_infop = NULL;
5807         if (rscn_count != FC_INVALID_RSCN_COUNT) {
5808                 fpkt->pkt_ulp_rscn_infop = kmem_zalloc(
5809                     sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP);
5810                 if (fpkt->pkt_ulp_rscn_infop == NULL) {
5811                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5812                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5813                             "Failed to alloc memory to pass rscn info");
5814                 }
5815         }
5816 
5817         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5818                 fc_ulp_rscn_info_t      *rscnp;
5819 
5820                 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop;
5821                 rscnp->ulp_rscn_count = rscn_count;
5822         }
5823 
5824         if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) {
5825                 goto fail;
5826         }
5827         dma_setup++;
5828 
5829         /*
5830          * Must hold target mutex across setting of pkt_pd and call to
5831          * fc_ulp_init_packet to ensure the handle to the target doesn't go
5832          * away while we're not looking.
5833          */
5834         if (ptgt != NULL) {
5835                 mutex_enter(&ptgt->tgt_mutex);
5836                 fpkt->pkt_pd = ptgt->tgt_pd_handle;
5837 
5838                 /* ask transport to do its initialization on this pkt */
5839                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5840                     != FC_SUCCESS) {
5841                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5842                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5843                             "fc_ulp_init_packet failed");
5844                         mutex_exit(&ptgt->tgt_mutex);
5845                         goto fail;
5846                 }
5847                 mutex_exit(&ptgt->tgt_mutex);
5848         } else {
5849                 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP)
5850                     != FC_SUCCESS) {
5851                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
5852                             fcp_trace, FCP_BUF_LEVEL_6, 0,
5853                             "fc_ulp_init_packet failed");
5854                         goto fail;
5855                 }
5856         }
5857 
5858         mutex_enter(&pptr->port_mutex);
5859         if (pptr->port_state & (FCP_STATE_DETACHING |
5860             FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) {
5861                 int rval;
5862 
5863                 mutex_exit(&pptr->port_mutex);
5864 
5865                 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt);
5866                 ASSERT(rval == FC_SUCCESS);
5867 
5868                 goto fail;
5869         }
5870 
5871         if (ptgt != NULL) {
5872                 mutex_enter(&ptgt->tgt_mutex);
5873                 ptgt->tgt_ipkt_cnt++;
5874                 mutex_exit(&ptgt->tgt_mutex);
5875         }
5876 
5877         pptr->port_ipkt_cnt++;
5878 
5879         mutex_exit(&pptr->port_mutex);
5880 
5881         return (icmd);
5882 
5883 fail:
5884         if (fpkt->pkt_ulp_rscn_infop != NULL) {
5885                 kmem_free(fpkt->pkt_ulp_rscn_infop,
5886                     sizeof (fc_ulp_rscn_info_t));
5887                 fpkt->pkt_ulp_rscn_infop = NULL;
5888         }
5889 
5890         if (dma_setup) {
5891                 fcp_free_dma(pptr, icmd);
5892         }
5893         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5894             (size_t)pptr->port_dmacookie_sz);
5895 
5896         return (NULL);
5897 }
5898 
5899 /*
5900  *     Function: fcp_icmd_free
5901  *
5902  *  Description: Frees the internal command passed by the caller.
5903  *
5904  *     Argument: *pptr          Fcp port.
5905  *               *icmd          Internal packet to free.
5906  *
5907  * Return Value: None
5908  */
5909 static void
5910 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd)
5911 {
5912         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
5913 
5914         /* Let the underlying layers do their cleanup. */
5915         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
5916             icmd->ipkt_fpkt);
5917 
5918         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) {
5919                 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop,
5920                     sizeof (fc_ulp_rscn_info_t));
5921         }
5922 
5923         fcp_free_dma(pptr, icmd);
5924 
5925         kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len +
5926             (size_t)pptr->port_dmacookie_sz);
5927 
5928         mutex_enter(&pptr->port_mutex);
5929 
5930         if (ptgt) {
5931                 mutex_enter(&ptgt->tgt_mutex);
5932                 ptgt->tgt_ipkt_cnt--;
5933                 mutex_exit(&ptgt->tgt_mutex);
5934         }
5935 
5936         pptr->port_ipkt_cnt--;
5937         mutex_exit(&pptr->port_mutex);
5938 }
5939 
5940 /*
5941  *     Function: fcp_alloc_dma
5942  *
5943  *  Description: Allocated the DMA resources required for the internal
5944  *               packet.
5945  *
5946  *     Argument: *pptr  FCP port.
5947  *               *icmd  Internal FCP packet.
5948  *               nodma  Indicates if the Cmd and Resp will be DMAed.
5949  *               flags  Allocation flags (Sleep or NoSleep).
5950  *
5951  * Return Value: FC_SUCCESS
5952  *               FC_NOMEM
5953  */
5954 static int
5955 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd,
5956     int nodma, int flags)
5957 {
5958         int             rval;
5959         size_t          real_size;
5960         uint_t          ccount;
5961         int             bound = 0;
5962         int             cmd_resp = 0;
5963         fc_packet_t     *fpkt;
5964         ddi_dma_cookie_t        pkt_data_cookie;
5965         ddi_dma_cookie_t        *cp;
5966         uint32_t                cnt;
5967 
5968         fpkt = &icmd->ipkt_fc_packet;
5969 
5970         ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL &&
5971             fpkt->pkt_resp_dma == NULL);
5972 
5973         icmd->ipkt_nodma = nodma;
5974 
5975         if (nodma) {
5976                 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags);
5977                 if (fpkt->pkt_cmd == NULL) {
5978                         goto fail;
5979                 }
5980 
5981                 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags);
5982                 if (fpkt->pkt_resp == NULL) {
5983                         goto fail;
5984                 }
5985         } else {
5986                 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen);
5987 
5988                 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags);
5989                 if (rval == FC_FAILURE) {
5990                         ASSERT(fpkt->pkt_cmd_dma == NULL &&
5991                             fpkt->pkt_resp_dma == NULL);
5992                         goto fail;
5993                 }
5994                 cmd_resp++;
5995         }
5996 
5997         if ((fpkt->pkt_datalen != 0) &&
5998             !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
5999                 /*
6000                  * set up DMA handle and memory for the data in this packet
6001                  */
6002                 if (ddi_dma_alloc_handle(pptr->port_dip,
6003                     &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT,
6004                     NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) {
6005                         goto fail;
6006                 }
6007 
6008                 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen,
6009                     &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT,
6010                     DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data,
6011                     &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) {
6012                         goto fail;
6013                 }
6014 
6015                 /* was DMA mem size gotten < size asked for/needed ?? */
6016                 if (real_size < fpkt->pkt_datalen) {
6017                         goto fail;
6018                 }
6019 
6020                 /* bind DMA address and handle together */
6021                 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma,
6022                     NULL, fpkt->pkt_data, real_size, DDI_DMA_READ |
6023                     DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
6024                     &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) {
6025                         goto fail;
6026                 }
6027                 bound++;
6028 
6029                 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) {
6030                         goto fail;
6031                 }
6032 
6033                 fpkt->pkt_data_cookie_cnt = ccount;
6034 
6035                 cp = fpkt->pkt_data_cookie;
6036                 *cp = pkt_data_cookie;
6037                 cp++;
6038 
6039                 for (cnt = 1; cnt < ccount; cnt++, cp++) {
6040                         ddi_dma_nextcookie(fpkt->pkt_data_dma,
6041                             &pkt_data_cookie);
6042                         *cp = pkt_data_cookie;
6043                 }
6044 
6045         } else if (fpkt->pkt_datalen != 0) {
6046                 /*
6047                  * If it's a pseudo FCA, then it can't support DMA even in
6048                  * SCSI data phase.
6049                  */
6050                 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags);
6051                 if (fpkt->pkt_data == NULL) {
6052                         goto fail;
6053                 }
6054 
6055         }
6056 
6057         return (FC_SUCCESS);
6058 
6059 fail:
6060         if (bound) {
6061                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6062         }
6063 
6064         if (fpkt->pkt_data_dma) {
6065                 if (fpkt->pkt_data) {
6066                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6067                 }
6068                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6069         } else {
6070                 if (fpkt->pkt_data) {
6071                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6072                 }
6073         }
6074 
6075         if (nodma) {
6076                 if (fpkt->pkt_cmd) {
6077                         kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen);
6078                 }
6079                 if (fpkt->pkt_resp) {
6080                         kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen);
6081                 }
6082         } else {
6083                 if (cmd_resp) {
6084                         fcp_free_cmd_resp(pptr, fpkt);
6085                 }
6086         }
6087 
6088         return (FC_NOMEM);
6089 }
6090 
6091 
6092 static void
6093 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd)
6094 {
6095         fc_packet_t *fpkt = icmd->ipkt_fpkt;
6096 
6097         if (fpkt->pkt_data_dma) {
6098                 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma);
6099                 if (fpkt->pkt_data) {
6100                         ddi_dma_mem_free(&fpkt->pkt_data_acc);
6101                 }
6102                 ddi_dma_free_handle(&fpkt->pkt_data_dma);
6103         } else {
6104                 if (fpkt->pkt_data) {
6105                         kmem_free(fpkt->pkt_data, fpkt->pkt_datalen);
6106                 }
6107                 /*
6108                  * Need we reset pkt_* to zero???
6109                  */
6110         }
6111 
6112         if (icmd->ipkt_nodma) {
6113                 if (fpkt->pkt_cmd) {
6114                         kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen);
6115                 }
6116                 if (fpkt->pkt_resp) {
6117                         kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen);
6118                 }
6119         } else {
6120                 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
6121 
6122                 fcp_free_cmd_resp(pptr, fpkt);
6123         }
6124 }
6125 
6126 /*
6127  *     Function: fcp_lookup_target
6128  *
6129  *  Description: Finds a target given a WWN.
6130  *
6131  *     Argument: *pptr  FCP port.
6132  *               *wwn   World Wide Name of the device to look for.
6133  *
6134  * Return Value: NULL           No target found
6135  *               Not NULL       Target structure
6136  *
6137  *      Context: Interrupt context.
6138  *               The mutex pptr->port_mutex must be owned.
6139  */
6140 /* ARGSUSED */
6141 static struct fcp_tgt *
6142 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn)
6143 {
6144         int                     hash;
6145         struct fcp_tgt  *ptgt;
6146 
6147         ASSERT(mutex_owned(&pptr->port_mutex));
6148 
6149         hash = FCP_HASH(wwn);
6150 
6151         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
6152             ptgt = ptgt->tgt_next) {
6153                 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) &&
6154                     bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
6155                     sizeof (ptgt->tgt_port_wwn)) == 0) {
6156                         break;
6157                 }
6158         }
6159 
6160         return (ptgt);
6161 }
6162 
6163 
6164 /*
6165  * Find target structure given a port identifier
6166  */
6167 static struct fcp_tgt *
6168 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id)
6169 {
6170         fc_portid_t             port_id;
6171         la_wwn_t                pwwn;
6172         struct fcp_tgt  *ptgt = NULL;
6173 
6174         port_id.priv_lilp_posit = 0;
6175         port_id.port_id = d_id;
6176         if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id,
6177             &pwwn) == FC_SUCCESS) {
6178                 mutex_enter(&pptr->port_mutex);
6179                 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn);
6180                 mutex_exit(&pptr->port_mutex);
6181         }
6182 
6183         return (ptgt);
6184 }
6185 
6186 
6187 /*
6188  * the packet completion callback routine for info cmd pkts
6189  *
6190  * this means fpkt pts to a response to either a PLOGI or a PRLI
6191  *
6192  * if there is an error an attempt is made to call a routine to resend
6193  * the command that failed
6194  */
6195 static void
6196 fcp_icmd_callback(fc_packet_t *fpkt)
6197 {
6198         struct fcp_ipkt *icmd;
6199         struct fcp_port *pptr;
6200         struct fcp_tgt  *ptgt;
6201         struct la_els_prli      *prli;
6202         struct la_els_prli      prli_s;
6203         struct fcp_prli         *fprli;
6204         struct fcp_lun  *plun;
6205         int             free_pkt = 1;
6206         int             rval;
6207         ls_code_t       resp;
6208         uchar_t         prli_acc = 0;
6209         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
6210         int             lun0_newalloc;
6211 
6212         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
6213 
6214         /* get ptrs to the port and target structs for the cmd */
6215         pptr = icmd->ipkt_port;
6216         ptgt = icmd->ipkt_tgt;
6217 
6218         FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp));
6219 
6220         if (icmd->ipkt_opcode == LA_ELS_PRLI) {
6221                 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc,
6222                     sizeof (prli_s));
6223                 prli_acc = (prli_s.ls_code == LA_ELS_ACC);
6224         }
6225 
6226         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6227             fcp_trace, FCP_BUF_LEVEL_2, 0,
6228             "ELS (%x) callback state=0x%x reason=0x%x for %x",
6229             icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason,
6230             ptgt->tgt_d_id);
6231 
6232         if ((fpkt->pkt_state == FC_PKT_SUCCESS) &&
6233             ((resp.ls_code == LA_ELS_ACC) || prli_acc)) {
6234 
6235                 mutex_enter(&ptgt->tgt_mutex);
6236                 if (ptgt->tgt_pd_handle == NULL) {
6237                         /*
6238                          * in a fabric environment the port device handles
6239                          * get created only after successful LOGIN into the
6240                          * transport, so the transport makes this port
6241                          * device (pd) handle available in this packet, so
6242                          * save it now
6243                          */
6244                         ASSERT(fpkt->pkt_pd != NULL);
6245                         ptgt->tgt_pd_handle = fpkt->pkt_pd;
6246                 }
6247                 mutex_exit(&ptgt->tgt_mutex);
6248 
6249                 /* which ELS cmd is this response for ?? */
6250                 switch (icmd->ipkt_opcode) {
6251                 case LA_ELS_PLOGI:
6252                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6253                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6254                             "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x",
6255                             ptgt->tgt_d_id,
6256                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
6257                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]));
6258 
6259                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6260                             FCP_TGT_TRACE_15);
6261 
6262                         /* Note that we are not allocating a new icmd */
6263                         if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI,
6264                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6265                             icmd->ipkt_cause) != DDI_SUCCESS) {
6266                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6267                                     FCP_TGT_TRACE_16);
6268                                 goto fail;
6269                         }
6270                         break;
6271 
6272                 case LA_ELS_PRLI:
6273                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6274                             fcp_trace, FCP_BUF_LEVEL_5, 0,
6275                             "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id);
6276 
6277                         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6278                             FCP_TGT_TRACE_17);
6279 
6280                         prli = &prli_s;
6281 
6282                         FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc,
6283                             sizeof (prli_s));
6284 
6285                         fprli = (struct fcp_prli *)prli->service_params;
6286 
6287                         mutex_enter(&ptgt->tgt_mutex);
6288                         ptgt->tgt_icap = fprli->initiator_fn;
6289                         ptgt->tgt_tcap = fprli->target_fn;
6290                         mutex_exit(&ptgt->tgt_mutex);
6291 
6292                         if ((fprli->type != 0x08) || (fprli->target_fn != 1)) {
6293                                 /*
6294                                  * this FCP device does not support target mode
6295                                  */
6296                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6297                                     FCP_TGT_TRACE_18);
6298                                 goto fail;
6299                         }
6300                         if (fprli->retry == 1) {
6301                                 fc_ulp_disable_relogin(pptr->port_fp_handle,
6302                                     &ptgt->tgt_port_wwn);
6303                         }
6304 
6305                         /* target is no longer offline */
6306                         mutex_enter(&pptr->port_mutex);
6307                         mutex_enter(&ptgt->tgt_mutex);
6308                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6309                                 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE |
6310                                     FCP_TGT_MARK);
6311                         } else {
6312                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6313                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6314                                     "fcp_icmd_callback,1: state change "
6315                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6316                                 mutex_exit(&ptgt->tgt_mutex);
6317                                 mutex_exit(&pptr->port_mutex);
6318                                 goto fail;
6319                         }
6320                         mutex_exit(&ptgt->tgt_mutex);
6321                         mutex_exit(&pptr->port_mutex);
6322 
6323                         /*
6324                          * lun 0 should always respond to inquiry, so
6325                          * get the LUN struct for LUN 0
6326                          *
6327                          * Currently we deal with first level of addressing.
6328                          * If / when we start supporting 0x device types
6329                          * (DTYPE_ARRAY_CTRL, i.e. array controllers)
6330                          * this logic will need revisiting.
6331                          */
6332                         lun0_newalloc = 0;
6333                         if ((plun = fcp_get_lun(ptgt, 0)) == NULL) {
6334                                 /*
6335                                  * no LUN struct for LUN 0 yet exists,
6336                                  * so create one
6337                                  */
6338                                 plun = fcp_alloc_lun(ptgt);
6339                                 if (plun == NULL) {
6340                                         fcp_log(CE_WARN, pptr->port_dip,
6341                                             "!Failed to allocate lun 0 for"
6342                                             " D_ID=%x", ptgt->tgt_d_id);
6343                                         goto fail;
6344                                 }
6345                                 lun0_newalloc = 1;
6346                         }
6347 
6348                         /* fill in LUN info */
6349                         mutex_enter(&ptgt->tgt_mutex);
6350                         /*
6351                          * consider lun 0 as device not connected if it is
6352                          * offlined or newly allocated
6353                          */
6354                         if ((plun->lun_state & FCP_LUN_OFFLINE) ||
6355                             lun0_newalloc) {
6356                                 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED;
6357                         }
6358                         plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK);
6359                         plun->lun_state &= ~FCP_LUN_OFFLINE;
6360                         ptgt->tgt_lun_cnt = 1;
6361                         ptgt->tgt_report_lun_cnt = 0;
6362                         mutex_exit(&ptgt->tgt_mutex);
6363 
6364                         /* Retrieve the rscn count (if a valid one exists) */
6365                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
6366                                 rscn_count = ((fc_ulp_rscn_info_t *)
6367                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))
6368                                     ->ulp_rscn_count;
6369                         } else {
6370                                 rscn_count = FC_INVALID_RSCN_COUNT;
6371                         }
6372 
6373                         /* send Report Lun request to target */
6374                         if (fcp_send_scsi(plun, SCMD_REPORT_LUN,
6375                             sizeof (struct fcp_reportlun_resp),
6376                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
6377                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
6378                                 mutex_enter(&pptr->port_mutex);
6379                                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6380                                         fcp_log(CE_WARN, pptr->port_dip,
6381                                             "!Failed to send REPORT LUN to"
6382                                             "  D_ID=%x", ptgt->tgt_d_id);
6383                                 } else {
6384                                         FCP_TRACE(fcp_logq,
6385                                             pptr->port_instbuf, fcp_trace,
6386                                             FCP_BUF_LEVEL_5, 0,
6387                                             "fcp_icmd_callback,2:state change"
6388                                             " occured for D_ID=0x%x",
6389                                             ptgt->tgt_d_id);
6390                                 }
6391                                 mutex_exit(&pptr->port_mutex);
6392 
6393                                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6394                                     FCP_TGT_TRACE_19);
6395 
6396                                 goto fail;
6397                         } else {
6398                                 free_pkt = 0;
6399                                 fcp_icmd_free(pptr, icmd);
6400                         }
6401                         break;
6402 
6403                 default:
6404                         fcp_log(CE_WARN, pptr->port_dip,
6405                             "!fcp_icmd_callback Invalid opcode");
6406                         goto fail;
6407                 }
6408 
6409                 return;
6410         }
6411 
6412 
6413         /*
6414          * Other PLOGI failures are not retried as the
6415          * transport does it already
6416          */
6417         if (icmd->ipkt_opcode != LA_ELS_PLOGI) {
6418                 if (fcp_is_retryable(icmd) &&
6419                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6420 
6421                         if (FCP_MUST_RETRY(fpkt)) {
6422                                 fcp_queue_ipkt(pptr, fpkt);
6423                                 return;
6424                         }
6425 
6426                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6427                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6428                             "ELS PRLI is retried for d_id=0x%x, state=%x,"
6429                             " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state,
6430                             fpkt->pkt_reason);
6431 
6432                         /*
6433                          * Retry by recalling the routine that
6434                          * originally queued this packet
6435                          */
6436                         mutex_enter(&pptr->port_mutex);
6437                         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6438                                 caddr_t msg;
6439 
6440                                 mutex_exit(&pptr->port_mutex);
6441 
6442                                 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI);
6443 
6444                                 if (fpkt->pkt_state == FC_PKT_TIMEOUT) {
6445                                         fpkt->pkt_timeout +=
6446                                             FCP_TIMEOUT_DELTA;
6447                                 }
6448 
6449                                 rval = fc_ulp_issue_els(pptr->port_fp_handle,
6450                                     fpkt);
6451                                 if (rval == FC_SUCCESS) {
6452                                         return;
6453                                 }
6454 
6455                                 if (rval == FC_STATEC_BUSY ||
6456                                     rval == FC_OFFLINE) {
6457                                         fcp_queue_ipkt(pptr, fpkt);
6458                                         return;
6459                                 }
6460                                 (void) fc_ulp_error(rval, &msg);
6461 
6462                                 fcp_log(CE_NOTE, pptr->port_dip,
6463                                     "!ELS 0x%x failed to d_id=0x%x;"
6464                                     " %s", icmd->ipkt_opcode,
6465                                     ptgt->tgt_d_id, msg);
6466                         } else {
6467                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6468                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6469                                     "fcp_icmd_callback,3: state change "
6470                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
6471                                 mutex_exit(&pptr->port_mutex);
6472                         }
6473                 }
6474         } else {
6475                 if (fcp_is_retryable(icmd) &&
6476                     icmd->ipkt_retries++ < FCP_MAX_RETRIES) {
6477                         if (FCP_MUST_RETRY(fpkt)) {
6478                                 fcp_queue_ipkt(pptr, fpkt);
6479                                 return;
6480                         }
6481                 }
6482                 mutex_enter(&pptr->port_mutex);
6483                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) &&
6484                     fpkt->pkt_state != FC_PKT_PORT_OFFLINE) {
6485                         mutex_exit(&pptr->port_mutex);
6486                         fcp_print_error(fpkt);
6487                 } else {
6488                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6489                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6490                             "fcp_icmd_callback,4: state change occured"
6491                             " for D_ID=0x%x", ptgt->tgt_d_id);
6492                         mutex_exit(&pptr->port_mutex);
6493                 }
6494         }
6495 
6496 fail:
6497         if (free_pkt) {
6498                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6499                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
6500                 fcp_icmd_free(pptr, icmd);
6501         }
6502 }
6503 
6504 
6505 /*
6506  * called internally to send an info cmd using the transport
6507  *
6508  * sends either an INQ or a REPORT_LUN
6509  *
6510  * when the packet is completed fcp_scsi_callback is called
6511  */
6512 static int
6513 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len,
6514     int lcount, int tcount, int cause, uint32_t rscn_count)
6515 {
6516         int                     nodma;
6517         struct fcp_ipkt         *icmd;
6518         struct fcp_tgt          *ptgt;
6519         struct fcp_port         *pptr;
6520         fc_frame_hdr_t          *hp;
6521         fc_packet_t             *fpkt;
6522         struct fcp_cmd          fcp_cmd;
6523         struct fcp_cmd          *fcmd;
6524         union scsi_cdb          *scsi_cdb;
6525 
6526         ASSERT(plun != NULL);
6527 
6528         ptgt = plun->lun_tgt;
6529         ASSERT(ptgt != NULL);
6530 
6531         pptr = ptgt->tgt_port;
6532         ASSERT(pptr != NULL);
6533 
6534         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6535             fcp_trace, FCP_BUF_LEVEL_5, 0,
6536             "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode);
6537 
6538         nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0;
6539         icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd),
6540             FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause,
6541             rscn_count);
6542 
6543         if (icmd == NULL) {
6544                 return (DDI_FAILURE);
6545         }
6546 
6547         fpkt = icmd->ipkt_fpkt;
6548         fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR;
6549         icmd->ipkt_retries = 0;
6550         icmd->ipkt_opcode = opcode;
6551         icmd->ipkt_lun = plun;
6552 
6553         if (nodma) {
6554                 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd;
6555         } else {
6556                 fcmd = &fcp_cmd;
6557         }
6558         bzero(fcmd, sizeof (struct fcp_cmd));
6559 
6560         fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT;
6561 
6562         hp = &fpkt->pkt_cmd_fhdr;
6563 
6564         hp->s_id = pptr->port_id;
6565         hp->d_id = ptgt->tgt_d_id;
6566         hp->r_ctl = R_CTL_COMMAND;
6567         hp->type = FC_TYPE_SCSI_FCP;
6568         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
6569         hp->rsvd = 0;
6570         hp->seq_id = 0;
6571         hp->seq_cnt = 0;
6572         hp->ox_id = 0xffff;
6573         hp->rx_id = 0xffff;
6574         hp->ro = 0;
6575 
6576         bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE);
6577 
6578         /*
6579          * Request SCSI target for expedited processing
6580          */
6581 
6582         /*
6583          * Set up for untagged queuing because we do not
6584          * know if the fibre device supports queuing.
6585          */
6586         fcmd->fcp_cntl.cntl_reserved_0 = 0;
6587         fcmd->fcp_cntl.cntl_reserved_1 = 0;
6588         fcmd->fcp_cntl.cntl_reserved_2 = 0;
6589         fcmd->fcp_cntl.cntl_reserved_3 = 0;
6590         fcmd->fcp_cntl.cntl_reserved_4 = 0;
6591         fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
6592         scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb;
6593 
6594         switch (opcode) {
6595         case SCMD_INQUIRY_PAGE83:
6596                 /*
6597                  * Prepare to get the Inquiry VPD page 83 information
6598                  */
6599                 fcmd->fcp_cntl.cntl_read_data = 1;
6600                 fcmd->fcp_cntl.cntl_write_data = 0;
6601                 fcmd->fcp_data_len = alloc_len;
6602 
6603                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6604                 fpkt->pkt_comp = fcp_scsi_callback;
6605 
6606                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6607                 scsi_cdb->g0_addr2 = 0x01;
6608                 scsi_cdb->g0_addr1 = 0x83;
6609                 scsi_cdb->g0_count0 = (uchar_t)alloc_len;
6610                 break;
6611 
6612         case SCMD_INQUIRY:
6613                 fcmd->fcp_cntl.cntl_read_data = 1;
6614                 fcmd->fcp_cntl.cntl_write_data = 0;
6615                 fcmd->fcp_data_len = alloc_len;
6616 
6617                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6618                 fpkt->pkt_comp = fcp_scsi_callback;
6619 
6620                 scsi_cdb->scc_cmd = SCMD_INQUIRY;
6621                 scsi_cdb->g0_count0 = SUN_INQSIZE;
6622                 break;
6623 
6624         case SCMD_REPORT_LUN: {
6625                 fc_portid_t     d_id;
6626                 opaque_t        fca_dev;
6627 
6628                 ASSERT(alloc_len >= 16);
6629 
6630                 d_id.priv_lilp_posit = 0;
6631                 d_id.port_id = ptgt->tgt_d_id;
6632 
6633                 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id);
6634 
6635                 mutex_enter(&ptgt->tgt_mutex);
6636                 ptgt->tgt_fca_dev = fca_dev;
6637                 mutex_exit(&ptgt->tgt_mutex);
6638 
6639                 fcmd->fcp_cntl.cntl_read_data = 1;
6640                 fcmd->fcp_cntl.cntl_write_data = 0;
6641                 fcmd->fcp_data_len = alloc_len;
6642 
6643                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
6644                 fpkt->pkt_comp = fcp_scsi_callback;
6645 
6646                 scsi_cdb->scc_cmd = SCMD_REPORT_LUN;
6647                 scsi_cdb->scc5_count0 = alloc_len & 0xff;
6648                 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff;
6649                 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff;
6650                 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff;
6651                 break;
6652         }
6653 
6654         default:
6655                 fcp_log(CE_WARN, pptr->port_dip,
6656                     "!fcp_send_scsi Invalid opcode");
6657                 break;
6658         }
6659 
6660         if (!nodma) {
6661                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
6662                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
6663         }
6664 
6665         mutex_enter(&pptr->port_mutex);
6666         if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
6667 
6668                 mutex_exit(&pptr->port_mutex);
6669                 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) !=
6670                     FC_SUCCESS) {
6671                         fcp_icmd_free(pptr, icmd);
6672                         return (DDI_FAILURE);
6673                 }
6674                 return (DDI_SUCCESS);
6675         } else {
6676                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6677                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6678                     "fcp_send_scsi,1: state change occured"
6679                     " for D_ID=0x%x", ptgt->tgt_d_id);
6680                 mutex_exit(&pptr->port_mutex);
6681                 fcp_icmd_free(pptr, icmd);
6682                 return (DDI_FAILURE);
6683         }
6684 }
6685 
6686 
6687 /*
6688  * called by fcp_scsi_callback to check to handle the case where
6689  * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION
6690  */
6691 static int
6692 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt)
6693 {
6694         uchar_t                         rqlen;
6695         int                             rval = DDI_FAILURE;
6696         struct scsi_extended_sense      sense_info, *sense;
6697         struct fcp_ipkt         *icmd = (struct fcp_ipkt *)
6698             fpkt->pkt_ulp_private;
6699         struct fcp_tgt          *ptgt = icmd->ipkt_tgt;
6700         struct fcp_port         *pptr = ptgt->tgt_port;
6701 
6702         ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN);
6703 
6704         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) {
6705                 /*
6706                  * SCSI-II Reserve Release support. Some older FC drives return
6707                  * Reservation conflict for Report Luns command.
6708                  */
6709                 if (icmd->ipkt_nodma) {
6710                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6711                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6712                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6713                 } else {
6714                         fcp_rsp_t       new_resp;
6715 
6716                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6717                             fpkt->pkt_resp_acc, sizeof (new_resp));
6718 
6719                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6720                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6721                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6722 
6723                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6724                             fpkt->pkt_resp_acc, sizeof (new_resp));
6725                 }
6726 
6727                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6728                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6729 
6730                 return (DDI_SUCCESS);
6731         }
6732 
6733         sense = &sense_info;
6734         if (!rsp->fcp_u.fcp_status.sense_len_set) {
6735                 /* no need to continue if sense length is not set */
6736                 return (rval);
6737         }
6738 
6739         /* casting 64-bit integer to 8-bit */
6740         rqlen = (uchar_t)min(rsp->fcp_sense_len,
6741             sizeof (struct scsi_extended_sense));
6742 
6743         if (rqlen < 14) {
6744                 /* no need to continue if request length isn't long enough */
6745                 return (rval);
6746         }
6747 
6748         if (icmd->ipkt_nodma) {
6749                 /*
6750                  * We can safely use fcp_response_len here since the
6751                  * only path that calls fcp_check_reportlun,
6752                  * fcp_scsi_callback, has already called
6753                  * fcp_validate_fcp_response.
6754                  */
6755                 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp +
6756                     sizeof (struct fcp_rsp) + rsp->fcp_response_len);
6757         } else {
6758                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) +
6759                     rsp->fcp_response_len, sense, fpkt->pkt_resp_acc,
6760                     sizeof (struct scsi_extended_sense));
6761         }
6762 
6763         if (!FCP_SENSE_NO_LUN(sense)) {
6764                 mutex_enter(&ptgt->tgt_mutex);
6765                 /* clear the flag if any */
6766                 ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6767                 mutex_exit(&ptgt->tgt_mutex);
6768         }
6769 
6770         if ((sense->es_key == KEY_ILLEGAL_REQUEST) &&
6771             (sense->es_add_code == 0x20)) {
6772                 if (icmd->ipkt_nodma) {
6773                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6774                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6775                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6776                 } else {
6777                         fcp_rsp_t       new_resp;
6778 
6779                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6780                             fpkt->pkt_resp_acc, sizeof (new_resp));
6781 
6782                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6783                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6784                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6785 
6786                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6787                             fpkt->pkt_resp_acc, sizeof (new_resp));
6788                 }
6789 
6790                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6791                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6792 
6793                 return (DDI_SUCCESS);
6794         }
6795 
6796         /*
6797          * This is for the STK library which returns a check condition,
6798          * to indicate device is not ready, manual assistance needed.
6799          * This is to a report lun command when the door is open.
6800          */
6801         if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) {
6802                 if (icmd->ipkt_nodma) {
6803                         rsp->fcp_u.fcp_status.rsp_len_set = 0;
6804                         rsp->fcp_u.fcp_status.sense_len_set = 0;
6805                         rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6806                 } else {
6807                         fcp_rsp_t       new_resp;
6808 
6809                         FCP_CP_IN(fpkt->pkt_resp, &new_resp,
6810                             fpkt->pkt_resp_acc, sizeof (new_resp));
6811 
6812                         new_resp.fcp_u.fcp_status.rsp_len_set = 0;
6813                         new_resp.fcp_u.fcp_status.sense_len_set = 0;
6814                         new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD;
6815 
6816                         FCP_CP_OUT(&new_resp, fpkt->pkt_resp,
6817                             fpkt->pkt_resp_acc, sizeof (new_resp));
6818                 }
6819 
6820                 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data,
6821                     fpkt->pkt_data_acc, sizeof (fcp_dummy_lun));
6822 
6823                 return (DDI_SUCCESS);
6824         }
6825 
6826         if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) ||
6827             (FCP_SENSE_NO_LUN(sense))) {
6828                 mutex_enter(&ptgt->tgt_mutex);
6829                 if ((FCP_SENSE_NO_LUN(sense)) &&
6830                     (ptgt->tgt_state & FCP_TGT_ILLREQ)) {
6831                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
6832                         mutex_exit(&ptgt->tgt_mutex);
6833                         /*
6834                          * reconfig was triggred by ILLEGAL REQUEST but
6835                          * got ILLEGAL REQUEST again
6836                          */
6837                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6838                             fcp_trace, FCP_BUF_LEVEL_3, 0,
6839                             "!FCP: Unable to obtain Report Lun data"
6840                             " target=%x", ptgt->tgt_d_id);
6841                 } else {
6842                         if (ptgt->tgt_tid == NULL) {
6843                                 timeout_id_t    tid;
6844                                 /*
6845                                  * REPORT LUN data has changed.  Kick off
6846                                  * rediscovery
6847                                  */
6848                                 tid = timeout(fcp_reconfigure_luns,
6849                                     (caddr_t)ptgt, (clock_t)drv_usectohz(1));
6850 
6851                                 ptgt->tgt_tid = tid;
6852                                 ptgt->tgt_state |= FCP_TGT_BUSY;
6853                         }
6854                         if (FCP_SENSE_NO_LUN(sense)) {
6855                                 ptgt->tgt_state |= FCP_TGT_ILLREQ;
6856                         }
6857                         mutex_exit(&ptgt->tgt_mutex);
6858                         if (FCP_SENSE_REPORTLUN_CHANGED(sense)) {
6859                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6860                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6861                                     "!FCP:Report Lun Has Changed"
6862                                     " target=%x", ptgt->tgt_d_id);
6863                         } else if (FCP_SENSE_NO_LUN(sense)) {
6864                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6865                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
6866                                     "!FCP:LU Not Supported"
6867                                     " target=%x", ptgt->tgt_d_id);
6868                         }
6869                 }
6870                 rval = DDI_SUCCESS;
6871         }
6872 
6873         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6874             fcp_trace, FCP_BUF_LEVEL_5, 0,
6875             "D_ID=%x, sense=%x, status=%x",
6876             fpkt->pkt_cmd_fhdr.d_id, sense->es_key,
6877             rsp->fcp_u.fcp_status.scsi_status);
6878 
6879         return (rval);
6880 }
6881 
6882 /*
6883  *     Function: fcp_scsi_callback
6884  *
6885  *  Description: This is the callback routine set by fcp_send_scsi() after
6886  *               it calls fcp_icmd_alloc().  The SCSI command completed here
6887  *               and autogenerated by FCP are:  REPORT_LUN, INQUIRY and
6888  *               INQUIRY_PAGE83.
6889  *
6890  *     Argument: *fpkt   FC packet used to convey the command
6891  *
6892  * Return Value: None
6893  */
6894 static void
6895 fcp_scsi_callback(fc_packet_t *fpkt)
6896 {
6897         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
6898             fpkt->pkt_ulp_private;
6899         struct fcp_rsp_info     fcp_rsp_err, *bep;
6900         struct fcp_port *pptr;
6901         struct fcp_tgt  *ptgt;
6902         struct fcp_lun  *plun;
6903         struct fcp_rsp          response, *rsp;
6904 
6905         ptgt = icmd->ipkt_tgt;
6906         pptr = ptgt->tgt_port;
6907         plun = icmd->ipkt_lun;
6908 
6909         if (icmd->ipkt_nodma) {
6910                 rsp = (struct fcp_rsp *)fpkt->pkt_resp;
6911         } else {
6912                 rsp = &response;
6913                 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
6914                     sizeof (struct fcp_rsp));
6915         }
6916 
6917         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6918             fcp_trace, FCP_BUF_LEVEL_2, 0,
6919             "SCSI callback state=0x%x for %x, op_code=0x%x, "
6920             "status=%x, lun num=%x",
6921             fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode,
6922             rsp->fcp_u.fcp_status.scsi_status, plun->lun_num);
6923 
6924         /*
6925          * Pre-init LUN GUID with NWWN if it is not a device that
6926          * supports multiple luns and we know it's not page83
6927          * compliant.  Although using a NWWN is not lun unique,
6928          * we will be fine since there is only one lun behind the taget
6929          * in this case.
6930          */
6931         if ((plun->lun_guid_size == 0) &&
6932             (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
6933             (fcp_symmetric_device_probe(plun) == 0)) {
6934 
6935                 char ascii_wwn[FC_WWN_SIZE*2+1];
6936                 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn);
6937                 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn);
6938         }
6939 
6940         /*
6941          * Some old FC tapes and FC <-> SCSI bridge devices return overrun
6942          * when thay have more data than what is asked in CDB. An overrun
6943          * is really when FCP_DL is smaller than the data length in CDB.
6944          * In the case here we know that REPORT LUN command we formed within
6945          * this binary has correct FCP_DL. So this OVERRUN is due to bad device
6946          * behavior. In reality this is FC_SUCCESS.
6947          */
6948         if ((fpkt->pkt_state != FC_PKT_SUCCESS) &&
6949             (fpkt->pkt_reason == FC_REASON_OVERRUN) &&
6950             (icmd->ipkt_opcode == SCMD_REPORT_LUN)) {
6951                 fpkt->pkt_state = FC_PKT_SUCCESS;
6952         }
6953 
6954         if (fpkt->pkt_state != FC_PKT_SUCCESS) {
6955                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
6956                     fcp_trace, FCP_BUF_LEVEL_2, 0,
6957                     "icmd failed with state=0x%x for %x", fpkt->pkt_state,
6958                     ptgt->tgt_d_id);
6959 
6960                 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) {
6961                         /*
6962                          * Inquiry VPD page command on A5K SES devices would
6963                          * result in data CRC errors.
6964                          */
6965                         if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) {
6966                                 (void) fcp_handle_page83(fpkt, icmd, 1);
6967                                 return;
6968                         }
6969                 }
6970                 if (fpkt->pkt_state == FC_PKT_TIMEOUT ||
6971                     FCP_MUST_RETRY(fpkt)) {
6972                         fpkt->pkt_timeout += FCP_TIMEOUT_DELTA;
6973                         fcp_retry_scsi_cmd(fpkt);
6974                         return;
6975                 }
6976 
6977                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
6978                     FCP_TGT_TRACE_20);
6979 
6980                 mutex_enter(&pptr->port_mutex);
6981                 mutex_enter(&ptgt->tgt_mutex);
6982                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
6983                         mutex_exit(&ptgt->tgt_mutex);
6984                         mutex_exit(&pptr->port_mutex);
6985                         fcp_print_error(fpkt);
6986                 } else {
6987                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
6988                             fcp_trace, FCP_BUF_LEVEL_2, 0,
6989                             "fcp_scsi_callback,1: state change occured"
6990                             " for D_ID=0x%x", ptgt->tgt_d_id);
6991                         mutex_exit(&ptgt->tgt_mutex);
6992                         mutex_exit(&pptr->port_mutex);
6993                 }
6994                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
6995                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
6996                 fcp_icmd_free(pptr, icmd);
6997                 return;
6998         }
6999 
7000         FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21);
7001 
7002         mutex_enter(&pptr->port_mutex);
7003         mutex_enter(&ptgt->tgt_mutex);
7004         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7005                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7006                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7007                     "fcp_scsi_callback,2: state change occured"
7008                     " for D_ID=0x%x", ptgt->tgt_d_id);
7009                 mutex_exit(&ptgt->tgt_mutex);
7010                 mutex_exit(&pptr->port_mutex);
7011                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7012                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7013                 fcp_icmd_free(pptr, icmd);
7014                 return;
7015         }
7016         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7017 
7018         mutex_exit(&ptgt->tgt_mutex);
7019         mutex_exit(&pptr->port_mutex);
7020 
7021         if (icmd->ipkt_nodma) {
7022                 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp +
7023                     sizeof (struct fcp_rsp));
7024         } else {
7025                 bep = &fcp_rsp_err;
7026                 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep,
7027                     fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info));
7028         }
7029 
7030         if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
7031                 fcp_retry_scsi_cmd(fpkt);
7032                 return;
7033         }
7034 
7035         if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code !=
7036             FCP_NO_FAILURE) {
7037                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7038                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7039                     "rsp_code=0x%x, rsp_len_set=0x%x",
7040                     bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set);
7041                 fcp_retry_scsi_cmd(fpkt);
7042                 return;
7043         }
7044 
7045         if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL ||
7046             rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) {
7047                 fcp_queue_ipkt(pptr, fpkt);
7048                 return;
7049         }
7050 
7051         /*
7052          * Devices that do not support INQUIRY_PAGE83, return check condition
7053          * with illegal request as per SCSI spec.
7054          * Crossbridge is one such device and Daktari's SES node is another.
7055          * We want to ideally enumerate these devices as a non-mpxio devices.
7056          * SES nodes (Daktari only currently) are an exception to this.
7057          */
7058         if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) &&
7059             (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) {
7060 
7061                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7062                     fcp_trace, FCP_BUF_LEVEL_3, 0,
7063                     "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with "
7064                     "check condition. May enumerate as non-mpxio device",
7065                     ptgt->tgt_d_id, plun->lun_type);
7066 
7067                 /*
7068                  * If we let Daktari's SES be enumerated as a non-mpxio
7069                  * device, there will be a discrepency in that the other
7070                  * internal FC disks will get enumerated as mpxio devices.
7071                  * Applications like luxadm expect this to be consistent.
7072                  *
7073                  * So, we put in a hack here to check if this is an SES device
7074                  * and handle it here.
7075                  */
7076                 if (plun->lun_type == DTYPE_ESI) {
7077                         /*
7078                          * Since, pkt_state is actually FC_PKT_SUCCESS
7079                          * at this stage, we fake a failure here so that
7080                          * fcp_handle_page83 will create a device path using
7081                          * the WWN instead of the GUID which is not there anyway
7082                          */
7083                         fpkt->pkt_state = FC_PKT_LOCAL_RJT;
7084                         (void) fcp_handle_page83(fpkt, icmd, 1);
7085                         return;
7086                 }
7087 
7088                 mutex_enter(&ptgt->tgt_mutex);
7089                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
7090                     FCP_LUN_MARK | FCP_LUN_BUSY);
7091                 mutex_exit(&ptgt->tgt_mutex);
7092 
7093                 (void) fcp_call_finish_init(pptr, ptgt,
7094                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7095                     icmd->ipkt_cause);
7096                 fcp_icmd_free(pptr, icmd);
7097                 return;
7098         }
7099 
7100         if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7101                 int rval = DDI_FAILURE;
7102 
7103                 /*
7104                  * handle cases where report lun isn't supported
7105                  * by faking up our own REPORT_LUN response or
7106                  * UNIT ATTENTION
7107                  */
7108                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7109                         rval = fcp_check_reportlun(rsp, fpkt);
7110 
7111                         /*
7112                          * fcp_check_reportlun might have modified the
7113                          * FCP response. Copy it in again to get an updated
7114                          * FCP response
7115                          */
7116                         if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) {
7117                                 rsp = &response;
7118 
7119                                 FCP_CP_IN(fpkt->pkt_resp, rsp,
7120                                     fpkt->pkt_resp_acc,
7121                                     sizeof (struct fcp_rsp));
7122                         }
7123                 }
7124 
7125                 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) {
7126                         if (rval == DDI_SUCCESS) {
7127                                 (void) fcp_call_finish_init(pptr, ptgt,
7128                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7129                                     icmd->ipkt_cause);
7130                                 fcp_icmd_free(pptr, icmd);
7131                         } else {
7132                                 fcp_retry_scsi_cmd(fpkt);
7133                         }
7134 
7135                         return;
7136                 }
7137         } else {
7138                 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) {
7139                         mutex_enter(&ptgt->tgt_mutex);
7140                         ptgt->tgt_state &= ~FCP_TGT_ILLREQ;
7141                         mutex_exit(&ptgt->tgt_mutex);
7142                 }
7143         }
7144 
7145         ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD);
7146         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
7147                 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0,
7148                     DDI_DMA_SYNC_FORCPU);
7149         }
7150 
7151         switch (icmd->ipkt_opcode) {
7152         case SCMD_INQUIRY:
7153                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1);
7154                 fcp_handle_inquiry(fpkt, icmd);
7155                 break;
7156 
7157         case SCMD_REPORT_LUN:
7158                 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt,
7159                     FCP_TGT_TRACE_22);
7160                 fcp_handle_reportlun(fpkt, icmd);
7161                 break;
7162 
7163         case SCMD_INQUIRY_PAGE83:
7164                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2);
7165                 (void) fcp_handle_page83(fpkt, icmd, 0);
7166                 break;
7167 
7168         default:
7169                 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode");
7170                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7171                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7172                 fcp_icmd_free(pptr, icmd);
7173                 break;
7174         }
7175 }
7176 
7177 
7178 static void
7179 fcp_retry_scsi_cmd(fc_packet_t *fpkt)
7180 {
7181         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
7182             fpkt->pkt_ulp_private;
7183         struct fcp_tgt  *ptgt = icmd->ipkt_tgt;
7184         struct fcp_port *pptr = ptgt->tgt_port;
7185 
7186         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
7187             fcp_is_retryable(icmd)) {
7188                 mutex_enter(&pptr->port_mutex);
7189                 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7190                         mutex_exit(&pptr->port_mutex);
7191                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7192                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7193                             "Retrying %s to %x; state=%x, reason=%x",
7194                             (icmd->ipkt_opcode == SCMD_REPORT_LUN) ?
7195                             "Report LUN" : "INQUIRY", ptgt->tgt_d_id,
7196                             fpkt->pkt_state, fpkt->pkt_reason);
7197 
7198                         fcp_queue_ipkt(pptr, fpkt);
7199                 } else {
7200                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7201                             fcp_trace, FCP_BUF_LEVEL_3, 0,
7202                             "fcp_retry_scsi_cmd,1: state change occured"
7203                             " for D_ID=0x%x", ptgt->tgt_d_id);
7204                         mutex_exit(&pptr->port_mutex);
7205                         (void) fcp_call_finish_init(pptr, ptgt,
7206                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7207                             icmd->ipkt_cause);
7208                         fcp_icmd_free(pptr, icmd);
7209                 }
7210         } else {
7211                 fcp_print_error(fpkt);
7212                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7213                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7214                 fcp_icmd_free(pptr, icmd);
7215         }
7216 }
7217 
7218 /*
7219  *     Function: fcp_handle_page83
7220  *
7221  *  Description: Treats the response to INQUIRY_PAGE83.
7222  *
7223  *     Argument: *fpkt  FC packet used to convey the command.
7224  *               *icmd  Original fcp_ipkt structure.
7225  *               ignore_page83_data
7226  *                      if it's 1, that means it's a special devices's
7227  *                      page83 response, it should be enumerated under mpxio
7228  *
7229  * Return Value: None
7230  */
7231 static void
7232 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd,
7233     int ignore_page83_data)
7234 {
7235         struct fcp_port *pptr;
7236         struct fcp_lun  *plun;
7237         struct fcp_tgt  *ptgt;
7238         uchar_t                 dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE];
7239         int                     fail = 0;
7240         ddi_devid_t             devid;
7241         char                    *guid = NULL;
7242         int                     ret;
7243 
7244         ASSERT(icmd != NULL && fpkt != NULL);
7245 
7246         pptr = icmd->ipkt_port;
7247         ptgt = icmd->ipkt_tgt;
7248         plun = icmd->ipkt_lun;
7249 
7250         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
7251                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7);
7252 
7253                 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc,
7254                     SCMD_MAX_INQUIRY_PAGE83_SIZE);
7255 
7256                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7257                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7258                     "fcp_handle_page83: port=%d, tgt D_ID=0x%x, "
7259                     "dtype=0x%x, lun num=%x",
7260                     pptr->port_instance, ptgt->tgt_d_id,
7261                     dev_id_page[0], plun->lun_num);
7262 
7263                 ret = ddi_devid_scsi_encode(
7264                     DEVID_SCSI_ENCODE_VERSION_LATEST,
7265                     NULL,               /* driver name */
7266                     (unsigned char *) &plun->lun_inq, /* standard inquiry */
7267                     sizeof (plun->lun_inq), /* size of standard inquiry */
7268                     NULL,               /* page 80 data */
7269                     0,          /* page 80 len */
7270                     dev_id_page,        /* page 83 data */
7271                     SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */
7272                     &devid);
7273 
7274                 if (ret == DDI_SUCCESS) {
7275 
7276                         guid = ddi_devid_to_guid(devid);
7277 
7278                         if (guid) {
7279                                 /*
7280                                  * Check our current guid.  If it's non null
7281                                  * and it has changed, we need to copy it into
7282                                  * lun_old_guid since we might still need it.
7283                                  */
7284                                 if (plun->lun_guid &&
7285                                     strcmp(guid, plun->lun_guid)) {
7286                                         unsigned int len;
7287 
7288                                         /*
7289                                          * If the guid of the LUN changes,
7290                                          * reconfiguration should be triggered
7291                                          * to reflect the changes.
7292                                          * i.e. we should offline the LUN with
7293                                          * the old guid, and online the LUN with
7294                                          * the new guid.
7295                                          */
7296                                         plun->lun_state |= FCP_LUN_CHANGED;
7297 
7298                                         if (plun->lun_old_guid) {
7299                                                 kmem_free(plun->lun_old_guid,
7300                                                     plun->lun_old_guid_size);
7301                                         }
7302 
7303                                         len = plun->lun_guid_size;
7304                                         plun->lun_old_guid_size = len;
7305 
7306                                         plun->lun_old_guid = kmem_zalloc(len,
7307                                             KM_NOSLEEP);
7308 
7309                                         if (plun->lun_old_guid) {
7310                                                 /*
7311                                                  * The alloc was successful then
7312                                                  * let's do the copy.
7313                                                  */
7314                                                 bcopy(plun->lun_guid,
7315                                                     plun->lun_old_guid, len);
7316                                         } else {
7317                                                 fail = 1;
7318                                                 plun->lun_old_guid_size = 0;
7319                                         }
7320                                 }
7321                                 if (!fail) {
7322                                         if (fcp_copy_guid_2_lun_block(
7323                                             plun, guid)) {
7324                                                 fail = 1;
7325                                         }
7326                                 }
7327                                 ddi_devid_free_guid(guid);
7328 
7329                         } else {
7330                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7331                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7332                                     "fcp_handle_page83: unable to create "
7333                                     "GUID");
7334 
7335                                 /* couldn't create good guid from devid */
7336                                 fail = 1;
7337                         }
7338                         ddi_devid_free(devid);
7339 
7340                 } else if (ret == DDI_NOT_WELL_FORMED) {
7341                         /* NULL filled data for page 83 */
7342                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7343                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7344                             "fcp_handle_page83: retry GUID");
7345 
7346                         icmd->ipkt_retries = 0;
7347                         fcp_retry_scsi_cmd(fpkt);
7348                         return;
7349                 } else {
7350                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7351                             fcp_trace, FCP_BUF_LEVEL_2, 0,
7352                             "fcp_handle_page83: bad ddi_devid_scsi_encode %x",
7353                             ret);
7354                         /*
7355                          * Since the page83 validation
7356                          * introduced late, we are being
7357                          * tolerant to the existing devices
7358                          * that already found to be working
7359                          * under mpxio, like A5200's SES device,
7360                          * its page83 response will not be standard-compliant,
7361                          * but we still want it to be enumerated under mpxio.
7362                          */
7363                         if (fcp_symmetric_device_probe(plun) != 0) {
7364                                 fail = 1;
7365                         }
7366                 }
7367 
7368         } else {
7369                 /* bad packet state */
7370                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8);
7371 
7372                 /*
7373                  * For some special devices (A5K SES and Daktari's SES devices),
7374                  * they should be enumerated under mpxio
7375                  * or "luxadm dis" will fail
7376                  */
7377                 if (ignore_page83_data) {
7378                         fail = 0;
7379                 } else {
7380                         fail = 1;
7381                 }
7382                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7383                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7384                     "!Devid page cmd failed. "
7385                     "fpkt_state: %x fpkt_reason: %x",
7386                     "ignore_page83: %d",
7387                     fpkt->pkt_state, fpkt->pkt_reason,
7388                     ignore_page83_data);
7389         }
7390 
7391         mutex_enter(&pptr->port_mutex);
7392         mutex_enter(&plun->lun_mutex);
7393         /*
7394          * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid
7395          * mismatch between lun_cip and lun_mpxio.
7396          */
7397         if (plun->lun_cip == NULL) {
7398                 /*
7399                  * If we don't have a guid for this lun it's because we were
7400                  * unable to glean one from the page 83 response.  Set the
7401                  * control flag to 0 here to make sure that we don't attempt to
7402                  * enumerate it under mpxio.
7403                  */
7404                 if (fail || pptr->port_mpxio == 0) {
7405                         plun->lun_mpxio = 0;
7406                 } else {
7407                         plun->lun_mpxio = 1;
7408                 }
7409         }
7410         mutex_exit(&plun->lun_mutex);
7411         mutex_exit(&pptr->port_mutex);
7412 
7413         mutex_enter(&ptgt->tgt_mutex);
7414         plun->lun_state &=
7415             ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY);
7416         mutex_exit(&ptgt->tgt_mutex);
7417 
7418         (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7419             icmd->ipkt_change_cnt, icmd->ipkt_cause);
7420 
7421         fcp_icmd_free(pptr, icmd);
7422 }
7423 
7424 /*
7425  *     Function: fcp_handle_inquiry
7426  *
7427  *  Description: Called by fcp_scsi_callback to handle the response to an
7428  *               INQUIRY request.
7429  *
7430  *     Argument: *fpkt  FC packet used to convey the command.
7431  *               *icmd  Original fcp_ipkt structure.
7432  *
7433  * Return Value: None
7434  */
7435 static void
7436 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7437 {
7438         struct fcp_port *pptr;
7439         struct fcp_lun  *plun;
7440         struct fcp_tgt  *ptgt;
7441         uchar_t         dtype;
7442         uchar_t         pqual;
7443         uint32_t        rscn_count = FC_INVALID_RSCN_COUNT;
7444 
7445         ASSERT(icmd != NULL && fpkt != NULL);
7446 
7447         pptr = icmd->ipkt_port;
7448         ptgt = icmd->ipkt_tgt;
7449         plun = icmd->ipkt_lun;
7450 
7451         FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc,
7452             sizeof (struct scsi_inquiry));
7453 
7454         dtype = plun->lun_inq.inq_dtype & DTYPE_MASK;
7455         pqual = plun->lun_inq.inq_dtype >> 5;
7456 
7457         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7458             fcp_trace, FCP_BUF_LEVEL_5, 0,
7459             "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, "
7460             "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id,
7461             plun->lun_num, dtype, pqual);
7462 
7463         if (pqual != 0) {
7464                 /*
7465                  * Non-zero peripheral qualifier
7466                  */
7467                 fcp_log(CE_CONT, pptr->port_dip,
7468                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7469                     "Device type=0x%x Peripheral qual=0x%x\n",
7470                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7471 
7472                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7473                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7474                     "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: "
7475                     "Device type=0x%x Peripheral qual=0x%x\n",
7476                     ptgt->tgt_d_id, plun->lun_num, dtype, pqual);
7477 
7478                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3);
7479 
7480                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7481                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7482                 fcp_icmd_free(pptr, icmd);
7483                 return;
7484         }
7485 
7486         /*
7487          * If the device is already initialized, check the dtype
7488          * for a change. If it has changed then update the flags
7489          * so the create_luns will offline the old device and
7490          * create the new device. Refer to bug: 4764752
7491          */
7492         if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) {
7493                 plun->lun_state |= FCP_LUN_CHANGED;
7494         }
7495         plun->lun_type = plun->lun_inq.inq_dtype;
7496 
7497         /*
7498          * This code is setting/initializing the throttling in the FCA
7499          * driver.
7500          */
7501         mutex_enter(&pptr->port_mutex);
7502         if (!pptr->port_notify) {
7503                 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) {
7504                         uint32_t cmd = 0;
7505                         cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) |
7506                             ((cmd & 0xFFFFFF00 >> 8) |
7507                             FCP_SVE_THROTTLE << 8));
7508                         pptr->port_notify = 1;
7509                         mutex_exit(&pptr->port_mutex);
7510                         (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd);
7511                         mutex_enter(&pptr->port_mutex);
7512                 }
7513         }
7514 
7515         if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) {
7516                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7517                     fcp_trace, FCP_BUF_LEVEL_2, 0,
7518                     "fcp_handle_inquiry,1:state change occured"
7519                     " for D_ID=0x%x", ptgt->tgt_d_id);
7520                 mutex_exit(&pptr->port_mutex);
7521 
7522                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5);
7523                 (void) fcp_call_finish_init(pptr, ptgt,
7524                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7525                     icmd->ipkt_cause);
7526                 fcp_icmd_free(pptr, icmd);
7527                 return;
7528         }
7529         ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0);
7530         mutex_exit(&pptr->port_mutex);
7531 
7532         /* Retrieve the rscn count (if a valid one exists) */
7533         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7534                 rscn_count = ((fc_ulp_rscn_info_t *)
7535                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count;
7536         } else {
7537                 rscn_count = FC_INVALID_RSCN_COUNT;
7538         }
7539 
7540         if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83,
7541             SCMD_MAX_INQUIRY_PAGE83_SIZE,
7542             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7543             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7544                 fcp_log(CE_WARN, NULL, "!failed to send page 83");
7545                 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6);
7546                 (void) fcp_call_finish_init(pptr, ptgt,
7547                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7548                     icmd->ipkt_cause);
7549         }
7550 
7551         /*
7552          * Read Inquiry VPD Page 0x83 to uniquely
7553          * identify this logical unit.
7554          */
7555         fcp_icmd_free(pptr, icmd);
7556 }
7557 
7558 /*
7559  *     Function: fcp_handle_reportlun
7560  *
7561  *  Description: Called by fcp_scsi_callback to handle the response to a
7562  *               REPORT_LUN request.
7563  *
7564  *     Argument: *fpkt  FC packet used to convey the command.
7565  *               *icmd  Original fcp_ipkt structure.
7566  *
7567  * Return Value: None
7568  */
7569 static void
7570 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd)
7571 {
7572         int                             i;
7573         int                             nluns_claimed;
7574         int                             nluns_bufmax;
7575         int                             len;
7576         uint16_t                        lun_num;
7577         uint32_t                        rscn_count = FC_INVALID_RSCN_COUNT;
7578         struct fcp_port                 *pptr;
7579         struct fcp_tgt                  *ptgt;
7580         struct fcp_lun                  *plun;
7581         struct fcp_reportlun_resp       *report_lun;
7582 
7583         pptr = icmd->ipkt_port;
7584         ptgt = icmd->ipkt_tgt;
7585         len = fpkt->pkt_datalen;
7586 
7587         if ((len < FCP_LUN_HEADER) ||
7588             ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) {
7589                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7590                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7591                 fcp_icmd_free(pptr, icmd);
7592                 return;
7593         }
7594 
7595         FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc,
7596             fpkt->pkt_datalen);
7597 
7598         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7599             fcp_trace, FCP_BUF_LEVEL_5, 0,
7600             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x",
7601             pptr->port_instance, ptgt->tgt_d_id);
7602 
7603         /*
7604          * Get the number of luns (which is supplied as LUNS * 8) the
7605          * device claims it has.
7606          */
7607         nluns_claimed = BE_32(report_lun->num_lun) >> 3;
7608 
7609         /*
7610          * Get the maximum number of luns the buffer submitted can hold.
7611          */
7612         nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE;
7613 
7614         /*
7615          * Due to limitations of certain hardware, we support only 16 bit LUNs
7616          */
7617         if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) {
7618                 kmem_free(report_lun, len);
7619 
7620                 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support"
7621                     " 0x%x number of LUNs for target=%x", nluns_claimed,
7622                     ptgt->tgt_d_id);
7623 
7624                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7625                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7626                 fcp_icmd_free(pptr, icmd);
7627                 return;
7628         }
7629 
7630         /*
7631          * If there are more LUNs than we have allocated memory for,
7632          * allocate more space and send down yet another report lun if
7633          * the maximum number of attempts hasn't been reached.
7634          */
7635         mutex_enter(&ptgt->tgt_mutex);
7636 
7637         if ((nluns_claimed > nluns_bufmax) &&
7638             (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) {
7639 
7640                 struct fcp_lun *plun;
7641 
7642                 ptgt->tgt_report_lun_cnt++;
7643                 plun = ptgt->tgt_lun;
7644                 ASSERT(plun != NULL);
7645                 mutex_exit(&ptgt->tgt_mutex);
7646 
7647                 kmem_free(report_lun, len);
7648 
7649                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7650                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7651                     "!Dynamically discovered %d LUNs for D_ID=%x",
7652                     nluns_claimed, ptgt->tgt_d_id);
7653 
7654                 /* Retrieve the rscn count (if a valid one exists) */
7655                 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7656                         rscn_count = ((fc_ulp_rscn_info_t *)
7657                             (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7658                             ulp_rscn_count;
7659                 } else {
7660                         rscn_count = FC_INVALID_RSCN_COUNT;
7661                 }
7662 
7663                 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN,
7664                     FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE),
7665                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7666                     icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7667                         (void) fcp_call_finish_init(pptr, ptgt,
7668                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7669                             icmd->ipkt_cause);
7670                 }
7671 
7672                 fcp_icmd_free(pptr, icmd);
7673                 return;
7674         }
7675 
7676         if (nluns_claimed > nluns_bufmax) {
7677                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7678                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7679                     "Target=%x:%x:%x:%x:%x:%x:%x:%x"
7680                     "    Number of LUNs lost=%x",
7681                     ptgt->tgt_port_wwn.raw_wwn[0],
7682                     ptgt->tgt_port_wwn.raw_wwn[1],
7683                     ptgt->tgt_port_wwn.raw_wwn[2],
7684                     ptgt->tgt_port_wwn.raw_wwn[3],
7685                     ptgt->tgt_port_wwn.raw_wwn[4],
7686                     ptgt->tgt_port_wwn.raw_wwn[5],
7687                     ptgt->tgt_port_wwn.raw_wwn[6],
7688                     ptgt->tgt_port_wwn.raw_wwn[7],
7689                     nluns_claimed - nluns_bufmax);
7690 
7691                 nluns_claimed = nluns_bufmax;
7692         }
7693         ptgt->tgt_lun_cnt = nluns_claimed;
7694 
7695         /*
7696          * Identify missing LUNs and print warning messages
7697          */
7698         for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) {
7699                 int offline;
7700                 int exists = 0;
7701 
7702                 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0;
7703 
7704                 for (i = 0; i < nluns_claimed && exists == 0; i++) {
7705                         uchar_t         *lun_string;
7706 
7707                         lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7708 
7709                         switch (lun_string[0] & 0xC0) {
7710                         case FCP_LUN_ADDRESSING:
7711                         case FCP_PD_ADDRESSING:
7712                         case FCP_VOLUME_ADDRESSING:
7713                                 lun_num = ((lun_string[0] & 0x3F) << 8) |
7714                                     lun_string[1];
7715                                 if (plun->lun_num == lun_num) {
7716                                         exists++;
7717                                         break;
7718                                 }
7719                                 break;
7720 
7721                         default:
7722                                 break;
7723                         }
7724                 }
7725 
7726                 if (!exists && !offline) {
7727                         mutex_exit(&ptgt->tgt_mutex);
7728 
7729                         mutex_enter(&pptr->port_mutex);
7730                         mutex_enter(&ptgt->tgt_mutex);
7731                         if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7732                                 /*
7733                                  * set disappear flag when device was connected
7734                                  */
7735                                 if (!(plun->lun_state &
7736                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7737                                         plun->lun_state |= FCP_LUN_DISAPPEARED;
7738                                 }
7739                                 mutex_exit(&ptgt->tgt_mutex);
7740                                 mutex_exit(&pptr->port_mutex);
7741                                 if (!(plun->lun_state &
7742                                     FCP_LUN_DEVICE_NOT_CONNECTED)) {
7743                                         fcp_log(CE_NOTE, pptr->port_dip,
7744                                             "!Lun=%x for target=%x disappeared",
7745                                             plun->lun_num, ptgt->tgt_d_id);
7746                                 }
7747                                 mutex_enter(&ptgt->tgt_mutex);
7748                         } else {
7749                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7750                                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7751                                     "fcp_handle_reportlun,1: state change"
7752                                     " occured for D_ID=0x%x", ptgt->tgt_d_id);
7753                                 mutex_exit(&ptgt->tgt_mutex);
7754                                 mutex_exit(&pptr->port_mutex);
7755                                 kmem_free(report_lun, len);
7756                                 (void) fcp_call_finish_init(pptr, ptgt,
7757                                     icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7758                                     icmd->ipkt_cause);
7759                                 fcp_icmd_free(pptr, icmd);
7760                                 return;
7761                         }
7762                 } else if (exists) {
7763                         /*
7764                          * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0
7765                          * actually exists in REPORT_LUN response
7766                          */
7767                         if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) {
7768                                 plun->lun_state &=
7769                                     ~FCP_LUN_DEVICE_NOT_CONNECTED;
7770                         }
7771                         if (offline || plun->lun_num == 0) {
7772                                 if (plun->lun_state & FCP_LUN_DISAPPEARED)  {
7773                                         plun->lun_state &= ~FCP_LUN_DISAPPEARED;
7774                                         mutex_exit(&ptgt->tgt_mutex);
7775                                         fcp_log(CE_NOTE, pptr->port_dip,
7776                                             "!Lun=%x for target=%x reappeared",
7777                                             plun->lun_num, ptgt->tgt_d_id);
7778                                         mutex_enter(&ptgt->tgt_mutex);
7779                                 }
7780                         }
7781                 }
7782         }
7783 
7784         ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1;
7785         mutex_exit(&ptgt->tgt_mutex);
7786 
7787         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7788             fcp_trace, FCP_BUF_LEVEL_5, 0,
7789             "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)",
7790             pptr->port_instance, ptgt->tgt_d_id, nluns_claimed);
7791 
7792         /* scan each lun */
7793         for (i = 0; i < nluns_claimed; i++) {
7794                 uchar_t *lun_string;
7795 
7796                 lun_string = (uchar_t *)&(report_lun->lun_string[i]);
7797 
7798                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
7799                     fcp_trace, FCP_BUF_LEVEL_5, 0,
7800                     "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d,"
7801                     " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1],
7802                     lun_string[0]);
7803 
7804                 switch (lun_string[0] & 0xC0) {
7805                 case FCP_LUN_ADDRESSING:
7806                 case FCP_PD_ADDRESSING:
7807                 case FCP_VOLUME_ADDRESSING:
7808                         lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1];
7809 
7810                         /* We will skip masked LUNs because of the blacklist. */
7811                         if (fcp_lun_blacklist != NULL) {
7812                                 mutex_enter(&ptgt->tgt_mutex);
7813                                 if (fcp_should_mask(&ptgt->tgt_port_wwn,
7814                                     lun_num) == TRUE) {
7815                                         ptgt->tgt_lun_cnt--;
7816                                         mutex_exit(&ptgt->tgt_mutex);
7817                                         break;
7818                                 }
7819                                 mutex_exit(&ptgt->tgt_mutex);
7820                         }
7821 
7822                         /* see if this LUN is already allocated */
7823                         if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) {
7824                                 plun = fcp_alloc_lun(ptgt);
7825                                 if (plun == NULL) {
7826                                         fcp_log(CE_NOTE, pptr->port_dip,
7827                                             "!Lun allocation failed"
7828                                             " target=%x lun=%x",
7829                                             ptgt->tgt_d_id, lun_num);
7830                                         break;
7831                                 }
7832                         }
7833 
7834                         mutex_enter(&plun->lun_tgt->tgt_mutex);
7835                         /* convert to LUN */
7836                         plun->lun_addr.ent_addr_0 =
7837                             BE_16(*(uint16_t *)&(lun_string[0]));
7838                         plun->lun_addr.ent_addr_1 =
7839                             BE_16(*(uint16_t *)&(lun_string[2]));
7840                         plun->lun_addr.ent_addr_2 =
7841                             BE_16(*(uint16_t *)&(lun_string[4]));
7842                         plun->lun_addr.ent_addr_3 =
7843                             BE_16(*(uint16_t *)&(lun_string[6]));
7844 
7845                         plun->lun_num = lun_num;
7846                         plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK;
7847                         plun->lun_state &= ~FCP_LUN_OFFLINE;
7848                         mutex_exit(&plun->lun_tgt->tgt_mutex);
7849 
7850                         /* Retrieve the rscn count (if a valid one exists) */
7851                         if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) {
7852                                 rscn_count = ((fc_ulp_rscn_info_t *)
7853                                     (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->
7854                                     ulp_rscn_count;
7855                         } else {
7856                                 rscn_count = FC_INVALID_RSCN_COUNT;
7857                         }
7858 
7859                         if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE,
7860                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
7861                             icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) {
7862                                 mutex_enter(&pptr->port_mutex);
7863                                 mutex_enter(&plun->lun_tgt->tgt_mutex);
7864                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
7865                                         fcp_log(CE_NOTE, pptr->port_dip,
7866                                             "!failed to send INQUIRY"
7867                                             " target=%x lun=%x",
7868                                             ptgt->tgt_d_id, plun->lun_num);
7869                                 } else {
7870                                         FCP_TRACE(fcp_logq,
7871                                             pptr->port_instbuf, fcp_trace,
7872                                             FCP_BUF_LEVEL_5, 0,
7873                                             "fcp_handle_reportlun,2: state"
7874                                             " change occured for D_ID=0x%x",
7875                                             ptgt->tgt_d_id);
7876                                 }
7877                                 mutex_exit(&plun->lun_tgt->tgt_mutex);
7878                                 mutex_exit(&pptr->port_mutex);
7879                         } else {
7880                                 continue;
7881                         }
7882                         break;
7883 
7884                 default:
7885                         fcp_log(CE_WARN, NULL,
7886                             "!Unsupported LUN Addressing method %x "
7887                             "in response to REPORT_LUN", lun_string[0]);
7888                         break;
7889                 }
7890 
7891                 /*
7892                  * each time through this loop we should decrement
7893                  * the tmp_cnt by one -- since we go through this loop
7894                  * one time for each LUN, the tmp_cnt should never be <=0
7895                  */
7896                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7897                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7898         }
7899 
7900         if (i == 0) {
7901                 fcp_log(CE_WARN, pptr->port_dip,
7902                     "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id);
7903                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
7904                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
7905         }
7906 
7907         kmem_free(report_lun, len);
7908         fcp_icmd_free(pptr, icmd);
7909 }
7910 
7911 
7912 /*
7913  * called internally to return a LUN given a target and a LUN number
7914  */
7915 static struct fcp_lun *
7916 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num)
7917 {
7918         struct fcp_lun  *plun;
7919 
7920         mutex_enter(&ptgt->tgt_mutex);
7921         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
7922                 if (plun->lun_num == lun_num) {
7923                         mutex_exit(&ptgt->tgt_mutex);
7924                         return (plun);
7925                 }
7926         }
7927         mutex_exit(&ptgt->tgt_mutex);
7928 
7929         return (NULL);
7930 }
7931 
7932 
7933 /*
7934  * handle finishing one target for fcp_finish_init
7935  *
7936  * return true (non-zero) if we want finish_init to continue with the
7937  * next target
7938  *
7939  * called with the port mutex held
7940  */
7941 /*ARGSUSED*/
7942 static int
7943 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt,
7944     int link_cnt, int tgt_cnt, int cause)
7945 {
7946         int     rval = 1;
7947         ASSERT(pptr != NULL);
7948         ASSERT(ptgt != NULL);
7949 
7950         FCP_TRACE(fcp_logq, pptr->port_instbuf,
7951             fcp_trace, FCP_BUF_LEVEL_5, 0,
7952             "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id,
7953             ptgt->tgt_state);
7954 
7955         ASSERT(mutex_owned(&pptr->port_mutex));
7956 
7957         if ((pptr->port_link_cnt != link_cnt) ||
7958             (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) {
7959                 /*
7960                  * oh oh -- another link reset or target change
7961                  * must have occurred while we are in here
7962                  */
7963                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23);
7964 
7965                 return (0);
7966         } else {
7967                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24);
7968         }
7969 
7970         mutex_enter(&ptgt->tgt_mutex);
7971 
7972         if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
7973                 /*
7974                  * tgt is not offline -- is it marked (i.e. needs
7975                  * to be offlined) ??
7976                  */
7977                 if (ptgt->tgt_state & FCP_TGT_MARK) {
7978                         /*
7979                          * this target not offline *and*
7980                          * marked
7981                          */
7982                         ptgt->tgt_state &= ~FCP_TGT_MARK;
7983                         rval = fcp_offline_target(pptr, ptgt, link_cnt,
7984                             tgt_cnt, 0, 0);
7985                 } else {
7986                         ptgt->tgt_state &= ~FCP_TGT_BUSY;
7987 
7988                         /* create the LUNs */
7989                         if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) {
7990                                 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT;
7991                                 fcp_create_luns(ptgt, link_cnt, tgt_cnt,
7992                                     cause);
7993                                 ptgt->tgt_device_created = 1;
7994                         } else {
7995                                 fcp_update_tgt_state(ptgt, FCP_RESET,
7996                                     FCP_LUN_BUSY);
7997                         }
7998                 }
7999         }
8000 
8001         mutex_exit(&ptgt->tgt_mutex);
8002 
8003         return (rval);
8004 }
8005 
8006 
8007 /*
8008  * this routine is called to finish port initialization
8009  *
8010  * Each port has a "temp" counter -- when a state change happens (e.g.
8011  * port online), the temp count is set to the number of devices in the map.
8012  * Then, as each device gets "discovered", the temp counter is decremented
8013  * by one.  When this count reaches zero we know that all of the devices
8014  * in the map have been discovered (or an error has occurred), so we can
8015  * then finish initialization -- which is done by this routine (well, this
8016  * and fcp-finish_tgt())
8017  *
8018  * acquires and releases the global mutex
8019  *
8020  * called with the port mutex owned
8021  */
8022 static void
8023 fcp_finish_init(struct fcp_port *pptr)
8024 {
8025 #ifdef  DEBUG
8026         bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack));
8027         pptr->port_finish_depth = getpcstack(pptr->port_finish_stack,
8028             FCP_STACK_DEPTH);
8029 #endif /* DEBUG */
8030 
8031         ASSERT(mutex_owned(&pptr->port_mutex));
8032 
8033         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8034             fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:"
8035             " entering; ipkt count=%d", pptr->port_ipkt_cnt);
8036 
8037         if ((pptr->port_state & FCP_STATE_ONLINING) &&
8038             !(pptr->port_state & (FCP_STATE_SUSPENDED |
8039             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
8040                 pptr->port_state &= ~FCP_STATE_ONLINING;
8041                 pptr->port_state |= FCP_STATE_ONLINE;
8042         }
8043 
8044         /* Wake up threads waiting on config done */
8045         cv_broadcast(&pptr->port_config_cv);
8046 }
8047 
8048 
8049 /*
8050  * called from fcp_finish_init to create the LUNs for a target
8051  *
8052  * called with the port mutex owned
8053  */
8054 static void
8055 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause)
8056 {
8057         struct fcp_lun  *plun;
8058         struct fcp_port *pptr;
8059         child_info_t            *cip = NULL;
8060 
8061         ASSERT(ptgt != NULL);
8062         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8063 
8064         pptr = ptgt->tgt_port;
8065 
8066         ASSERT(pptr != NULL);
8067 
8068         /* scan all LUNs for this target */
8069         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8070                 if (plun->lun_state & FCP_LUN_OFFLINE) {
8071                         continue;
8072                 }
8073 
8074                 if (plun->lun_state & FCP_LUN_MARK) {
8075                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8076                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8077                             "fcp_create_luns: offlining marked LUN!");
8078                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0);
8079                         continue;
8080                 }
8081 
8082                 plun->lun_state &= ~FCP_LUN_BUSY;
8083 
8084                 /*
8085                  * There are conditions in which FCP_LUN_INIT flag is cleared
8086                  * but we have a valid plun->lun_cip. To cover this case also
8087                  * CLEAR_BUSY whenever we have a valid lun_cip.
8088                  */
8089                 if (plun->lun_mpxio && plun->lun_cip &&
8090                     (!fcp_pass_to_hp(pptr, plun, plun->lun_cip,
8091                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8092                     0, 0))) {
8093                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8094                             fcp_trace, FCP_BUF_LEVEL_2, 0,
8095                             "fcp_create_luns: enable lun %p failed!",
8096                             plun);
8097                 }
8098 
8099                 if (plun->lun_state & FCP_LUN_INIT &&
8100                     !(plun->lun_state & FCP_LUN_CHANGED)) {
8101                         continue;
8102                 }
8103 
8104                 if (cause == FCP_CAUSE_USER_CREATE) {
8105                         continue;
8106                 }
8107 
8108                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8109                     fcp_trace, FCP_BUF_LEVEL_6, 0,
8110                     "create_luns: passing ONLINE elem to HP thread");
8111 
8112                 /*
8113                  * If lun has changed, prepare for offlining the old path.
8114                  * Do not offline the old path right now, since it may be
8115                  * still opened.
8116                  */
8117                 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) {
8118                         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8119                 }
8120 
8121                 /* pass an ONLINE element to the hotplug thread */
8122                 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8123                     link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) {
8124 
8125                         /*
8126                          * We can not synchronous attach (i.e pass
8127                          * NDI_ONLINE_ATTACH) here as we might be
8128                          * coming from an interrupt or callback
8129                          * thread.
8130                          */
8131                         if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE,
8132                             link_cnt, tgt_cnt, 0, 0)) {
8133                                 fcp_log(CE_CONT, pptr->port_dip,
8134                                     "Can not ONLINE LUN; D_ID=%x, LUN=%x\n",
8135                                     plun->lun_tgt->tgt_d_id, plun->lun_num);
8136                         }
8137                 }
8138         }
8139 }
8140 
8141 
8142 /*
8143  * function to online/offline devices
8144  */
8145 static int
8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio,
8147     int online, int lcount, int tcount, int flags)
8148 {
8149         int                     rval = NDI_FAILURE;
8150         int                     circ;
8151         child_info_t            *ccip;
8152         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
8153         int                     is_mpxio = pptr->port_mpxio;
8154         dev_info_t              *cdip, *pdip;
8155         char                    *devname;
8156 
8157         if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) {
8158                 /*
8159                  * When this event gets serviced, lun_cip and lun_mpxio
8160                  * has changed, so it should be invalidated now.
8161                  */
8162                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
8163                     FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: "
8164                     "plun: %p, cip: %p, what:%d", plun, cip, online);
8165                 return (rval);
8166         }
8167 
8168         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8169             fcp_trace, FCP_BUF_LEVEL_2, 0,
8170             "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x "
8171             "flags=%x mpxio=%x\n",
8172             plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags,
8173             plun->lun_mpxio);
8174 
8175         /*
8176          * lun_mpxio needs checking here because we can end up in a race
8177          * condition where this task has been dispatched while lun_mpxio is
8178          * set, but an earlier FCP_ONLINE task for the same LUN tried to
8179          * enable MPXIO for the LUN, but was unable to, and hence cleared
8180          * the flag. We rely on the serialization of the tasks here. We return
8181          * NDI_SUCCESS so any callers continue without reporting spurious
8182          * errors, and the still think we're an MPXIO LUN.
8183          */
8184 
8185         if (online == FCP_MPXIO_PATH_CLEAR_BUSY ||
8186             online == FCP_MPXIO_PATH_SET_BUSY) {
8187                 if (plun->lun_mpxio) {
8188                         rval = fcp_update_mpxio_path(plun, cip, online);
8189                 } else {
8190                         rval = NDI_SUCCESS;
8191                 }
8192                 return (rval);
8193         }
8194 
8195         /*
8196          * Explicit devfs_clean() due to ndi_devi_offline() not
8197          * executing devfs_clean() if parent lock is held.
8198          */
8199         ASSERT(!servicing_interrupt());
8200         if (online == FCP_OFFLINE) {
8201                 if (plun->lun_mpxio == 0) {
8202                         if (plun->lun_cip == cip) {
8203                                 cdip = DIP(plun->lun_cip);
8204                         } else {
8205                                 cdip = DIP(cip);
8206                         }
8207                 } else if ((plun->lun_cip == cip) && plun->lun_cip) {
8208                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8209                 } else if ((plun->lun_cip != cip) && cip) {
8210                         /*
8211                          * This means a DTYPE/GUID change, we shall get the
8212                          * dip of the old cip instead of the current lun_cip.
8213                          */
8214                         cdip = mdi_pi_get_client(PIP(cip));
8215                 }
8216                 if (cdip) {
8217                         if (i_ddi_devi_attached(cdip)) {
8218                                 pdip = ddi_get_parent(cdip);
8219                                 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
8220                                 ndi_devi_enter(pdip, &circ);
8221                                 (void) ddi_deviname(cdip, devname);
8222                                 ndi_devi_exit(pdip, circ);
8223                                 /*
8224                                  * Release parent lock before calling
8225                                  * devfs_clean().
8226                                  */
8227                                 rval = devfs_clean(pdip, devname + 1,
8228                                     DV_CLEAN_FORCE);
8229                                 kmem_free(devname, MAXNAMELEN + 1);
8230                                 /*
8231                                  * Return if devfs_clean() fails for
8232                                  * non-MPXIO case.
8233                                  * For MPXIO case, another path could be
8234                                  * offlined.
8235                                  */
8236                                 if (rval && plun->lun_mpxio == 0) {
8237                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8238                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8239                                             "fcp_trigger_lun: devfs_clean "
8240                                             "failed rval=%x  dip=%p",
8241                                             rval, pdip);
8242                                         return (NDI_FAILURE);
8243                                 }
8244                         }
8245                 }
8246         }
8247 
8248         if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) {
8249                 return (NDI_FAILURE);
8250         }
8251 
8252         if (is_mpxio) {
8253                 mdi_devi_enter(pptr->port_dip, &circ);
8254         } else {
8255                 ndi_devi_enter(pptr->port_dip, &circ);
8256         }
8257 
8258         mutex_enter(&pptr->port_mutex);
8259         mutex_enter(&plun->lun_mutex);
8260 
8261         if (online == FCP_ONLINE) {
8262                 ccip = fcp_get_cip(plun, cip, lcount, tcount);
8263                 if (ccip == NULL) {
8264                         goto fail;
8265                 }
8266         } else {
8267                 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) {
8268                         goto fail;
8269                 }
8270                 ccip = cip;
8271         }
8272 
8273         if (online == FCP_ONLINE) {
8274                 rval = fcp_online_child(plun, ccip, lcount, tcount, flags,
8275                     &circ);
8276                 fc_ulp_log_device_event(pptr->port_fp_handle,
8277                     FC_ULP_DEVICE_ONLINE);
8278         } else {
8279                 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags,
8280                     &circ);
8281                 fc_ulp_log_device_event(pptr->port_fp_handle,
8282                     FC_ULP_DEVICE_OFFLINE);
8283         }
8284 
8285 fail:   mutex_exit(&plun->lun_mutex);
8286         mutex_exit(&pptr->port_mutex);
8287 
8288         if (is_mpxio) {
8289                 mdi_devi_exit(pptr->port_dip, circ);
8290         } else {
8291                 ndi_devi_exit(pptr->port_dip, circ);
8292         }
8293 
8294         fc_ulp_idle_port(pptr->port_fp_handle);
8295 
8296         return (rval);
8297 }
8298 
8299 
8300 /*
8301  * take a target offline by taking all of its LUNs offline
8302  */
8303 /*ARGSUSED*/
8304 static int
8305 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8306     int link_cnt, int tgt_cnt, int nowait, int flags)
8307 {
8308         struct fcp_tgt_elem     *elem;
8309 
8310         ASSERT(mutex_owned(&pptr->port_mutex));
8311         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8312 
8313         ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE));
8314 
8315         if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt !=
8316             ptgt->tgt_change_cnt)) {
8317                 mutex_exit(&ptgt->tgt_mutex);
8318                 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25);
8319                 mutex_enter(&ptgt->tgt_mutex);
8320 
8321                 return (0);
8322         }
8323 
8324         ptgt->tgt_pd_handle = NULL;
8325         mutex_exit(&ptgt->tgt_mutex);
8326         FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26);
8327         mutex_enter(&ptgt->tgt_mutex);
8328 
8329         tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt;
8330 
8331         if (ptgt->tgt_tcap &&
8332             (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8333                 elem->flags = flags;
8334                 elem->time = fcp_watchdog_time;
8335                 if (nowait == 0) {
8336                         elem->time += fcp_offline_delay;
8337                 }
8338                 elem->ptgt = ptgt;
8339                 elem->link_cnt = link_cnt;
8340                 elem->tgt_cnt = tgt_cnt;
8341                 elem->next = pptr->port_offline_tgts;
8342                 pptr->port_offline_tgts = elem;
8343         } else {
8344                 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags);
8345         }
8346 
8347         return (1);
8348 }
8349 
8350 
8351 static void
8352 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt,
8353     int link_cnt, int tgt_cnt, int flags)
8354 {
8355         ASSERT(mutex_owned(&pptr->port_mutex));
8356         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8357 
8358         fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn);
8359         ptgt->tgt_state = FCP_TGT_OFFLINE;
8360         ptgt->tgt_pd_handle = NULL;
8361         fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags);
8362 }
8363 
8364 
8365 static void
8366 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt,
8367     int flags)
8368 {
8369         struct  fcp_lun *plun;
8370 
8371         ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex));
8372         ASSERT(mutex_owned(&ptgt->tgt_mutex));
8373 
8374         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
8375                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
8376                         fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags);
8377                 }
8378         }
8379 }
8380 
8381 
8382 /*
8383  * take a LUN offline
8384  *
8385  * enters and leaves with the target mutex held, releasing it in the process
8386  *
8387  * allocates memory in non-sleep mode
8388  */
8389 static void
8390 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8391     int nowait, int flags)
8392 {
8393         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
8394         struct fcp_lun_elem     *elem;
8395 
8396         ASSERT(plun != NULL);
8397         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8398 
8399         if (nowait) {
8400                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8401                 return;
8402         }
8403 
8404         if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) {
8405                 elem->flags = flags;
8406                 elem->time = fcp_watchdog_time;
8407                 if (nowait == 0) {
8408                         elem->time += fcp_offline_delay;
8409                 }
8410                 elem->plun = plun;
8411                 elem->link_cnt = link_cnt;
8412                 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt;
8413                 elem->next = pptr->port_offline_luns;
8414                 pptr->port_offline_luns = elem;
8415         } else {
8416                 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags);
8417         }
8418 }
8419 
8420 
8421 static void
8422 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
8423 {
8424         struct fcp_pkt  *head = NULL;
8425 
8426         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8427 
8428         mutex_exit(&LUN_TGT->tgt_mutex);
8429 
8430         head = fcp_scan_commands(plun);
8431         if (head != NULL) {
8432                 fcp_abort_commands(head, LUN_PORT);
8433         }
8434 
8435         mutex_enter(&LUN_TGT->tgt_mutex);
8436 
8437         if (plun->lun_cip && plun->lun_mpxio) {
8438                 /*
8439                  * Intimate MPxIO lun busy is cleared
8440                  */
8441                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip,
8442                     FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt,
8443                     0, 0)) {
8444                         fcp_log(CE_NOTE, LUN_PORT->port_dip,
8445                             "Can not ENABLE LUN; D_ID=%x, LUN=%x",
8446                             LUN_TGT->tgt_d_id, plun->lun_num);
8447                 }
8448                 /*
8449                  * Intimate MPxIO that the lun is now marked for offline
8450                  */
8451                 mutex_exit(&LUN_TGT->tgt_mutex);
8452                 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE);
8453                 mutex_enter(&LUN_TGT->tgt_mutex);
8454         }
8455 }
8456 
8457 static void
8458 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt,
8459     int flags)
8460 {
8461         ASSERT(mutex_owned(&LUN_TGT->tgt_mutex));
8462 
8463         mutex_exit(&LUN_TGT->tgt_mutex);
8464         fcp_update_offline_flags(plun);
8465         mutex_enter(&LUN_TGT->tgt_mutex);
8466 
8467         fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt);
8468 
8469         FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
8470             fcp_trace, FCP_BUF_LEVEL_4, 0,
8471             "offline_lun: passing OFFLINE elem to HP thread");
8472 
8473         if (plun->lun_cip) {
8474                 fcp_log(CE_NOTE, LUN_PORT->port_dip,
8475                     "!offlining lun=%x (trace=%x), target=%x (trace=%x)",
8476                     plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id,
8477                     LUN_TGT->tgt_trace);
8478 
8479                 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE,
8480                     link_cnt, tgt_cnt, flags, 0)) {
8481                         fcp_log(CE_CONT, LUN_PORT->port_dip,
8482                             "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n",
8483                             LUN_TGT->tgt_d_id, plun->lun_num);
8484                 }
8485         }
8486 }
8487 
8488 static void
8489 fcp_scan_offline_luns(struct fcp_port *pptr)
8490 {
8491         struct fcp_lun_elem     *elem;
8492         struct fcp_lun_elem     *prev;
8493         struct fcp_lun_elem     *next;
8494 
8495         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8496 
8497         prev = NULL;
8498         elem = pptr->port_offline_luns;
8499         while (elem) {
8500                 next = elem->next;
8501                 if (elem->time <= fcp_watchdog_time) {
8502                         int                     changed = 1;
8503                         struct fcp_tgt  *ptgt = elem->plun->lun_tgt;
8504 
8505                         mutex_enter(&ptgt->tgt_mutex);
8506                         if (pptr->port_link_cnt == elem->link_cnt &&
8507                             ptgt->tgt_change_cnt == elem->tgt_cnt) {
8508                                 changed = 0;
8509                         }
8510 
8511                         if (!changed &&
8512                             !(elem->plun->lun_state & FCP_TGT_OFFLINE)) {
8513                                 fcp_offline_lun_now(elem->plun,
8514                                     elem->link_cnt, elem->tgt_cnt, elem->flags);
8515                         }
8516                         mutex_exit(&ptgt->tgt_mutex);
8517 
8518                         kmem_free(elem, sizeof (*elem));
8519 
8520                         if (prev) {
8521                                 prev->next = next;
8522                         } else {
8523                                 pptr->port_offline_luns = next;
8524                         }
8525                 } else {
8526                         prev = elem;
8527                 }
8528                 elem = next;
8529         }
8530 }
8531 
8532 
8533 static void
8534 fcp_scan_offline_tgts(struct fcp_port *pptr)
8535 {
8536         struct fcp_tgt_elem     *elem;
8537         struct fcp_tgt_elem     *prev;
8538         struct fcp_tgt_elem     *next;
8539 
8540         ASSERT(MUTEX_HELD(&pptr->port_mutex));
8541 
8542         prev = NULL;
8543         elem = pptr->port_offline_tgts;
8544         while (elem) {
8545                 next = elem->next;
8546                 if (elem->time <= fcp_watchdog_time) {
8547                         int             outdated = 1;
8548                         struct fcp_tgt  *ptgt = elem->ptgt;
8549 
8550                         mutex_enter(&ptgt->tgt_mutex);
8551 
8552                         if (ptgt->tgt_change_cnt == elem->tgt_cnt) {
8553                                 /* No change on tgt since elem was created. */
8554                                 outdated = 0;
8555                         } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 &&
8556                             pptr->port_link_cnt == elem->link_cnt + 1 &&
8557                             ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) {
8558                                 /*
8559                                  * Exactly one thing happened to the target
8560                                  * inbetween: the local port went offline.
8561                                  * For fp the remote port is already gone so
8562                                  * it will not tell us again to offline the
8563                                  * target. We must offline it now.
8564                                  */
8565                                 outdated = 0;
8566                         }
8567 
8568                         if (!outdated && !(ptgt->tgt_state &
8569                             FCP_TGT_OFFLINE)) {
8570                                 fcp_offline_target_now(pptr,
8571                                     ptgt, elem->link_cnt, elem->tgt_cnt,
8572                                     elem->flags);
8573                         }
8574 
8575                         mutex_exit(&ptgt->tgt_mutex);
8576 
8577                         kmem_free(elem, sizeof (*elem));
8578 
8579                         if (prev) {
8580                                 prev->next = next;
8581                         } else {
8582                                 pptr->port_offline_tgts = next;
8583                         }
8584                 } else {
8585                         prev = elem;
8586                 }
8587                 elem = next;
8588         }
8589 }
8590 
8591 
8592 static void
8593 fcp_update_offline_flags(struct fcp_lun *plun)
8594 {
8595         struct fcp_port *pptr = LUN_PORT;
8596         ASSERT(plun != NULL);
8597 
8598         mutex_enter(&LUN_TGT->tgt_mutex);
8599         plun->lun_state |= FCP_LUN_OFFLINE;
8600         plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK);
8601 
8602         mutex_enter(&plun->lun_mutex);
8603         if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) {
8604                 dev_info_t *cdip = NULL;
8605 
8606                 mutex_exit(&LUN_TGT->tgt_mutex);
8607 
8608                 if (plun->lun_mpxio == 0) {
8609                         cdip = DIP(plun->lun_cip);
8610                 } else if (plun->lun_cip) {
8611                         cdip = mdi_pi_get_client(PIP(plun->lun_cip));
8612                 }
8613 
8614                 mutex_exit(&plun->lun_mutex);
8615                 if (cdip) {
8616                         (void) ndi_event_retrieve_cookie(
8617                             pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT,
8618                             &fcp_remove_eid, NDI_EVENT_NOPASS);
8619                         (void) ndi_event_run_callbacks(
8620                             pptr->port_ndi_event_hdl, cdip,
8621                             fcp_remove_eid, NULL);
8622                 }
8623         } else {
8624                 mutex_exit(&plun->lun_mutex);
8625                 mutex_exit(&LUN_TGT->tgt_mutex);
8626         }
8627 }
8628 
8629 
8630 /*
8631  * Scan all of the command pkts for this port, moving pkts that
8632  * match our LUN onto our own list (headed by "head")
8633  */
8634 static struct fcp_pkt *
8635 fcp_scan_commands(struct fcp_lun *plun)
8636 {
8637         struct fcp_port *pptr = LUN_PORT;
8638 
8639         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8640         struct fcp_pkt  *ncmd = NULL;   /* next pkt ptr */
8641         struct fcp_pkt  *pcmd = NULL;   /* the previous command */
8642 
8643         struct fcp_pkt  *head = NULL;   /* head of our list */
8644         struct fcp_pkt  *tail = NULL;   /* tail of our list */
8645 
8646         int                     cmds_found = 0;
8647 
8648         mutex_enter(&pptr->port_pkt_mutex);
8649         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
8650                 struct fcp_lun *tlun =
8651                     ADDR2LUN(&cmd->cmd_pkt->pkt_address);
8652 
8653                 ncmd = cmd->cmd_next;        /* set next command */
8654 
8655                 /*
8656                  * if this pkt is for a different LUN  or the
8657                  * command is sent down, skip it.
8658                  */
8659                 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED ||
8660                     (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) {
8661                         pcmd = cmd;
8662                         continue;
8663                 }
8664                 cmds_found++;
8665                 if (pcmd != NULL) {
8666                         ASSERT(pptr->port_pkt_head != cmd);
8667                         pcmd->cmd_next = cmd->cmd_next;
8668                 } else {
8669                         ASSERT(cmd == pptr->port_pkt_head);
8670                         pptr->port_pkt_head = cmd->cmd_next;
8671                 }
8672 
8673                 if (cmd == pptr->port_pkt_tail) {
8674                         pptr->port_pkt_tail = pcmd;
8675                         if (pcmd) {
8676                                 pcmd->cmd_next = NULL;
8677                         }
8678                 }
8679 
8680                 if (head == NULL) {
8681                         head = tail = cmd;
8682                 } else {
8683                         ASSERT(tail != NULL);
8684 
8685                         tail->cmd_next = cmd;
8686                         tail = cmd;
8687                 }
8688                 cmd->cmd_next = NULL;
8689         }
8690         mutex_exit(&pptr->port_pkt_mutex);
8691 
8692         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8693             fcp_trace, FCP_BUF_LEVEL_8, 0,
8694             "scan commands: %d cmd(s) found", cmds_found);
8695 
8696         return (head);
8697 }
8698 
8699 
8700 /*
8701  * Abort all the commands in the command queue
8702  */
8703 static void
8704 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr)
8705 {
8706         struct fcp_pkt  *cmd = NULL;    /* pkt cmd ptr */
8707         struct  fcp_pkt *ncmd = NULL;   /* next pkt ptr */
8708 
8709         ASSERT(mutex_owned(&pptr->port_mutex));
8710 
8711         /* scan through the pkts and invalid them */
8712         for (cmd = head; cmd != NULL; cmd = ncmd) {
8713                 struct scsi_pkt *pkt = cmd->cmd_pkt;
8714 
8715                 ncmd = cmd->cmd_next;
8716                 ASSERT(pkt != NULL);
8717 
8718                 /*
8719                  * The lun is going to be marked offline. Indicate
8720                  * the target driver not to requeue or retry this command
8721                  * as the device is going to be offlined pretty soon.
8722                  */
8723                 pkt->pkt_reason = CMD_DEV_GONE;
8724                 pkt->pkt_statistics = 0;
8725                 pkt->pkt_state = 0;
8726 
8727                 /* reset cmd flags/state */
8728                 cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
8729                 cmd->cmd_state = FCP_PKT_IDLE;
8730 
8731                 /*
8732                  * ensure we have a packet completion routine,
8733                  * then call it.
8734                  */
8735                 ASSERT(pkt->pkt_comp != NULL);
8736 
8737                 mutex_exit(&pptr->port_mutex);
8738                 fcp_post_callback(cmd);
8739                 mutex_enter(&pptr->port_mutex);
8740         }
8741 }
8742 
8743 
8744 /*
8745  * the pkt_comp callback for command packets
8746  */
8747 static void
8748 fcp_cmd_callback(fc_packet_t *fpkt)
8749 {
8750         struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
8751         struct scsi_pkt *pkt = cmd->cmd_pkt;
8752         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
8753 
8754         ASSERT(cmd->cmd_state != FCP_PKT_IDLE);
8755 
8756         if (cmd->cmd_state == FCP_PKT_IDLE) {
8757                 cmn_err(CE_PANIC, "Packet already completed %p",
8758                     (void *)cmd);
8759         }
8760 
8761         /*
8762          * Watch thread should be freeing the packet, ignore the pkt.
8763          */
8764         if (cmd->cmd_state == FCP_PKT_ABORTING) {
8765                 fcp_log(CE_CONT, pptr->port_dip,
8766                     "!FCP: Pkt completed while aborting\n");
8767                 return;
8768         }
8769         cmd->cmd_state = FCP_PKT_IDLE;
8770 
8771         fcp_complete_pkt(fpkt);
8772 
8773 #ifdef  DEBUG
8774         mutex_enter(&pptr->port_pkt_mutex);
8775         pptr->port_npkts--;
8776         mutex_exit(&pptr->port_pkt_mutex);
8777 #endif /* DEBUG */
8778 
8779         fcp_post_callback(cmd);
8780 }
8781 
8782 
8783 static void
8784 fcp_complete_pkt(fc_packet_t *fpkt)
8785 {
8786         int                     error = 0;
8787         struct fcp_pkt  *cmd = (struct fcp_pkt *)
8788             fpkt->pkt_ulp_private;
8789         struct scsi_pkt         *pkt = cmd->cmd_pkt;
8790         struct fcp_port         *pptr = ADDR2FCP(&pkt->pkt_address);
8791         struct fcp_lun  *plun;
8792         struct fcp_tgt  *ptgt;
8793         struct fcp_rsp          *rsp;
8794         struct scsi_address     save;
8795 
8796 #ifdef  DEBUG
8797         save = pkt->pkt_address;
8798 #endif /* DEBUG */
8799 
8800         rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
8801 
8802         if (fpkt->pkt_state == FC_PKT_SUCCESS) {
8803                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8804                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
8805                             sizeof (struct fcp_rsp));
8806                 }
8807 
8808                 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
8809                     STATE_SENT_CMD | STATE_GOT_STATUS;
8810 
8811                 pkt->pkt_resid = 0;
8812 
8813                 if (fpkt->pkt_datalen) {
8814                         pkt->pkt_state |= STATE_XFERRED_DATA;
8815                         if (fpkt->pkt_data_resid) {
8816                                 error++;
8817                         }
8818                 }
8819 
8820                 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) =
8821                     rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) {
8822                         /*
8823                          * The next two checks make sure that if there
8824                          * is no sense data or a valid response and
8825                          * the command came back with check condition,
8826                          * the command should be retried.
8827                          */
8828                         if (!rsp->fcp_u.fcp_status.rsp_len_set &&
8829                             !rsp->fcp_u.fcp_status.sense_len_set) {
8830                                 pkt->pkt_state &= ~STATE_XFERRED_DATA;
8831                                 pkt->pkt_resid = cmd->cmd_dmacount;
8832                         }
8833                 }
8834 
8835                 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) {
8836                         return;
8837                 }
8838 
8839                 plun = ADDR2LUN(&pkt->pkt_address);
8840                 ptgt = plun->lun_tgt;
8841                 ASSERT(ptgt != NULL);
8842 
8843                 /*
8844                  * Update the transfer resid, if appropriate
8845                  */
8846                 if (rsp->fcp_u.fcp_status.resid_over ||
8847                     rsp->fcp_u.fcp_status.resid_under) {
8848                         pkt->pkt_resid = rsp->fcp_resid;
8849                 }
8850 
8851                 /*
8852                  * First see if we got a FCP protocol error.
8853                  */
8854                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
8855                         struct fcp_rsp_info     *bep;
8856                         bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
8857                             sizeof (struct fcp_rsp));
8858 
8859                         if (fcp_validate_fcp_response(rsp, pptr) !=
8860                             FC_SUCCESS) {
8861                                 pkt->pkt_reason = CMD_CMPLT;
8862                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8863 
8864                                 fcp_log(CE_WARN, pptr->port_dip,
8865                                     "!SCSI command to d_id=0x%x lun=0x%x"
8866                                     " failed, Bad FCP response values:"
8867                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8868                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8869                                     ptgt->tgt_d_id, plun->lun_num,
8870                                     rsp->reserved_0, rsp->reserved_1,
8871                                     rsp->fcp_u.fcp_status.reserved_0,
8872                                     rsp->fcp_u.fcp_status.reserved_1,
8873                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8874 
8875                                 return;
8876                         }
8877 
8878                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8879                                 FCP_CP_IN(fpkt->pkt_resp +
8880                                     sizeof (struct fcp_rsp), bep,
8881                                     fpkt->pkt_resp_acc,
8882                                     sizeof (struct fcp_rsp_info));
8883                         }
8884 
8885                         if (bep->rsp_code != FCP_NO_FAILURE) {
8886                                 child_info_t    *cip;
8887 
8888                                 pkt->pkt_reason = CMD_TRAN_ERR;
8889 
8890                                 mutex_enter(&plun->lun_mutex);
8891                                 cip = plun->lun_cip;
8892                                 mutex_exit(&plun->lun_mutex);
8893 
8894                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
8895                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
8896                                     "FCP response error on cmd=%p"
8897                                     " target=0x%x, cip=%p", cmd,
8898                                     ptgt->tgt_d_id, cip);
8899                         }
8900                 }
8901 
8902                 /*
8903                  * See if we got a SCSI error with sense data
8904                  */
8905                 if (rsp->fcp_u.fcp_status.sense_len_set) {
8906                         uchar_t                         rqlen;
8907                         caddr_t                         sense_from;
8908                         child_info_t                    *cip;
8909                         timeout_id_t                    tid;
8910                         struct scsi_arq_status          *arq;
8911                         struct scsi_extended_sense      *sense_to;
8912 
8913                         arq = (struct scsi_arq_status *)pkt->pkt_scbp;
8914                         sense_to = &arq->sts_sensedata;
8915 
8916                         rqlen = (uchar_t)min(rsp->fcp_sense_len,
8917                             sizeof (struct scsi_extended_sense));
8918 
8919                         sense_from = (caddr_t)fpkt->pkt_resp +
8920                             sizeof (struct fcp_rsp) + rsp->fcp_response_len;
8921 
8922                         if (fcp_validate_fcp_response(rsp, pptr) !=
8923                             FC_SUCCESS) {
8924                                 pkt->pkt_reason = CMD_CMPLT;
8925                                 *(pkt->pkt_scbp) = STATUS_CHECK;
8926 
8927                                 fcp_log(CE_WARN, pptr->port_dip,
8928                                     "!SCSI command to d_id=0x%x lun=0x%x"
8929                                     " failed, Bad FCP response values:"
8930                                     " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x,"
8931                                     " sts-rsvd2=%x, rsplen=%x, senselen=%x",
8932                                     ptgt->tgt_d_id, plun->lun_num,
8933                                     rsp->reserved_0, rsp->reserved_1,
8934                                     rsp->fcp_u.fcp_status.reserved_0,
8935                                     rsp->fcp_u.fcp_status.reserved_1,
8936                                     rsp->fcp_response_len, rsp->fcp_sense_len);
8937 
8938                                 return;
8939                         }
8940 
8941                         /*
8942                          * copy in sense information
8943                          */
8944                         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
8945                                 FCP_CP_IN(sense_from, sense_to,
8946                                     fpkt->pkt_resp_acc, rqlen);
8947                         } else {
8948                                 bcopy(sense_from, sense_to, rqlen);
8949                         }
8950 
8951                         if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) ||
8952                             (FCP_SENSE_NO_LUN(sense_to))) {
8953                                 mutex_enter(&ptgt->tgt_mutex);
8954                                 if (ptgt->tgt_tid == NULL) {
8955                                         /*
8956                                          * Kick off rediscovery
8957                                          */
8958                                         tid = timeout(fcp_reconfigure_luns,
8959                                             (caddr_t)ptgt, drv_usectohz(1));
8960 
8961                                         ptgt->tgt_tid = tid;
8962                                         ptgt->tgt_state |= FCP_TGT_BUSY;
8963                                 }
8964                                 mutex_exit(&ptgt->tgt_mutex);
8965                                 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) {
8966                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8967                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8968                                             "!FCP: Report Lun Has Changed"
8969                                             " target=%x", ptgt->tgt_d_id);
8970                                 } else if (FCP_SENSE_NO_LUN(sense_to)) {
8971                                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
8972                                             fcp_trace, FCP_BUF_LEVEL_3, 0,
8973                                             "!FCP: LU Not Supported"
8974                                             " target=%x", ptgt->tgt_d_id);
8975                                 }
8976                         }
8977                         ASSERT(pkt->pkt_scbp != NULL);
8978 
8979                         pkt->pkt_state |= STATE_ARQ_DONE;
8980 
8981                         arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen;
8982 
8983                         *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD;
8984                         arq->sts_rqpkt_reason = 0;
8985                         arq->sts_rqpkt_statistics = 0;
8986 
8987                         arq->sts_rqpkt_state = STATE_GOT_BUS |
8988                             STATE_GOT_TARGET | STATE_SENT_CMD |
8989                             STATE_GOT_STATUS | STATE_ARQ_DONE |
8990                             STATE_XFERRED_DATA;
8991 
8992                         mutex_enter(&plun->lun_mutex);
8993                         cip = plun->lun_cip;
8994                         mutex_exit(&plun->lun_mutex);
8995 
8996                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
8997                             fcp_trace, FCP_BUF_LEVEL_8, 0,
8998                             "SCSI Check condition on cmd=%p target=0x%x"
8999                             " LUN=%p, cmd=%x SCSI status=%x, es key=%x"
9000                             " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip,
9001                             cmd->cmd_fcp_cmd.fcp_cdb[0],
9002                             rsp->fcp_u.fcp_status.scsi_status,
9003                             sense_to->es_key, sense_to->es_add_code,
9004                             sense_to->es_qual_code);
9005                 }
9006         } else {
9007                 plun = ADDR2LUN(&pkt->pkt_address);
9008                 ptgt = plun->lun_tgt;
9009                 ASSERT(ptgt != NULL);
9010 
9011                 /*
9012                  * Work harder to translate errors into target driver
9013                  * understandable ones. Note with despair that the target
9014                  * drivers don't decode pkt_state and pkt_reason exhaustively
9015                  * They resort to using the big hammer most often, which
9016                  * may not get fixed in the life time of this driver.
9017                  */
9018                 pkt->pkt_state = 0;
9019                 pkt->pkt_statistics = 0;
9020 
9021                 switch (fpkt->pkt_state) {
9022                 case FC_PKT_TRAN_ERROR:
9023                         switch (fpkt->pkt_reason) {
9024                         case FC_REASON_OVERRUN:
9025                                 pkt->pkt_reason = CMD_CMD_OVR;
9026                                 pkt->pkt_statistics |= STAT_ABORTED;
9027                                 break;
9028 
9029                         case FC_REASON_XCHG_BSY: {
9030                                 caddr_t ptr;
9031 
9032                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9033 
9034                                 ptr = (caddr_t)pkt->pkt_scbp;
9035                                 if (ptr) {
9036                                         *ptr = STATUS_BUSY;
9037                                 }
9038                                 break;
9039                         }
9040 
9041                         case FC_REASON_ABORTED:
9042                                 pkt->pkt_reason = CMD_TRAN_ERR;
9043                                 pkt->pkt_statistics |= STAT_ABORTED;
9044                                 break;
9045 
9046                         case FC_REASON_ABORT_FAILED:
9047                                 pkt->pkt_reason = CMD_ABORT_FAIL;
9048                                 break;
9049 
9050                         case FC_REASON_NO_SEQ_INIT:
9051                         case FC_REASON_CRC_ERROR:
9052                                 pkt->pkt_reason = CMD_TRAN_ERR;
9053                                 pkt->pkt_statistics |= STAT_ABORTED;
9054                                 break;
9055                         default:
9056                                 pkt->pkt_reason = CMD_TRAN_ERR;
9057                                 break;
9058                         }
9059                         break;
9060 
9061                 case FC_PKT_PORT_OFFLINE: {
9062                         dev_info_t      *cdip = NULL;
9063                         caddr_t         ptr;
9064 
9065                         if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) {
9066                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9067                                     fcp_trace, FCP_BUF_LEVEL_8, 0,
9068                                     "SCSI cmd; LOGIN REQUIRED from FCA for %x",
9069                                     ptgt->tgt_d_id);
9070                         }
9071 
9072                         mutex_enter(&plun->lun_mutex);
9073                         if (plun->lun_mpxio == 0) {
9074                                 cdip = DIP(plun->lun_cip);
9075                         } else if (plun->lun_cip) {
9076                                 cdip = mdi_pi_get_client(PIP(plun->lun_cip));
9077                         }
9078 
9079                         mutex_exit(&plun->lun_mutex);
9080 
9081                         if (cdip) {
9082                                 (void) ndi_event_retrieve_cookie(
9083                                     pptr->port_ndi_event_hdl, cdip,
9084                                     FCAL_REMOVE_EVENT, &fcp_remove_eid,
9085                                     NDI_EVENT_NOPASS);
9086                                 (void) ndi_event_run_callbacks(
9087                                     pptr->port_ndi_event_hdl, cdip,
9088                                     fcp_remove_eid, NULL);
9089                         }
9090 
9091                         /*
9092                          * If the link goes off-line for a lip,
9093                          * this will cause a error to the ST SG
9094                          * SGEN drivers. By setting BUSY we will
9095                          * give the drivers the chance to retry
9096                          * before it blows of the job. ST will
9097                          * remember how many times it has retried.
9098                          */
9099 
9100                         if ((plun->lun_type == DTYPE_SEQUENTIAL) ||
9101                             (plun->lun_type == DTYPE_CHANGER)) {
9102                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9103                                 ptr = (caddr_t)pkt->pkt_scbp;
9104                                 if (ptr) {
9105                                         *ptr = STATUS_BUSY;
9106                                 }
9107                         } else {
9108                                 pkt->pkt_reason = CMD_TRAN_ERR;
9109                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9110                         }
9111                         break;
9112                 }
9113 
9114                 case FC_PKT_TRAN_BSY:
9115                         /*
9116                          * Use the ssd Qfull handling here.
9117                          */
9118                         *pkt->pkt_scbp = STATUS_INTERMEDIATE;
9119                         pkt->pkt_state = STATE_GOT_BUS;
9120                         break;
9121 
9122                 case FC_PKT_TIMEOUT:
9123                         pkt->pkt_reason = CMD_TIMEOUT;
9124                         if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) {
9125                                 pkt->pkt_statistics |= STAT_TIMEOUT;
9126                         } else {
9127                                 pkt->pkt_statistics |= STAT_ABORTED;
9128                         }
9129                         break;
9130 
9131                 case FC_PKT_LOCAL_RJT:
9132                         switch (fpkt->pkt_reason) {
9133                         case FC_REASON_OFFLINE: {
9134                                 dev_info_t      *cdip = NULL;
9135 
9136                                 mutex_enter(&plun->lun_mutex);
9137                                 if (plun->lun_mpxio == 0) {
9138                                         cdip = DIP(plun->lun_cip);
9139                                 } else if (plun->lun_cip) {
9140                                         cdip = mdi_pi_get_client(
9141                                             PIP(plun->lun_cip));
9142                                 }
9143                                 mutex_exit(&plun->lun_mutex);
9144 
9145                                 if (cdip) {
9146                                         (void) ndi_event_retrieve_cookie(
9147                                             pptr->port_ndi_event_hdl, cdip,
9148                                             FCAL_REMOVE_EVENT,
9149                                             &fcp_remove_eid,
9150                                             NDI_EVENT_NOPASS);
9151                                         (void) ndi_event_run_callbacks(
9152                                             pptr->port_ndi_event_hdl,
9153                                             cdip, fcp_remove_eid, NULL);
9154                                 }
9155 
9156                                 pkt->pkt_reason = CMD_TRAN_ERR;
9157                                 pkt->pkt_statistics |= STAT_BUS_RESET;
9158 
9159                                 break;
9160                         }
9161 
9162                         case FC_REASON_NOMEM:
9163                         case FC_REASON_QFULL: {
9164                                 caddr_t ptr;
9165 
9166                                 pkt->pkt_reason = CMD_CMPLT; /* Lie */
9167                                 ptr = (caddr_t)pkt->pkt_scbp;
9168                                 if (ptr) {
9169                                         *ptr = STATUS_BUSY;
9170                                 }
9171                                 break;
9172                         }
9173 
9174                         case FC_REASON_DMA_ERROR:
9175                                 pkt->pkt_reason = CMD_DMA_DERR;
9176                                 pkt->pkt_statistics |= STAT_ABORTED;
9177                                 break;
9178 
9179                         case FC_REASON_CRC_ERROR:
9180                         case FC_REASON_UNDERRUN: {
9181                                 uchar_t         status;
9182                                 /*
9183                                  * Work around for Bugid: 4240945.
9184                                  * IB on A5k doesn't set the Underrun bit
9185                                  * in the fcp status, when it is transferring
9186                                  * less than requested amount of data. Work
9187                                  * around the ses problem to keep luxadm
9188                                  * happy till ibfirmware is fixed.
9189                                  */
9190                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
9191                                         FCP_CP_IN(fpkt->pkt_resp, rsp,
9192                                             fpkt->pkt_resp_acc,
9193                                             sizeof (struct fcp_rsp));
9194                                 }
9195                                 status = rsp->fcp_u.fcp_status.scsi_status;
9196                                 if (((plun->lun_type & DTYPE_MASK) ==
9197                                     DTYPE_ESI) && (status == STATUS_GOOD)) {
9198                                         pkt->pkt_reason = CMD_CMPLT;
9199                                         *pkt->pkt_scbp = status;
9200                                         pkt->pkt_resid = 0;
9201                                 } else {
9202                                         pkt->pkt_reason = CMD_TRAN_ERR;
9203                                         pkt->pkt_statistics |= STAT_ABORTED;
9204                                 }
9205                                 break;
9206                         }
9207 
9208                         case FC_REASON_NO_CONNECTION:
9209                         case FC_REASON_UNSUPPORTED:
9210                         case FC_REASON_ILLEGAL_REQ:
9211                         case FC_REASON_BAD_SID:
9212                         case FC_REASON_DIAG_BUSY:
9213                         case FC_REASON_FCAL_OPN_FAIL:
9214                         case FC_REASON_BAD_XID:
9215                         default:
9216                                 pkt->pkt_reason = CMD_TRAN_ERR;
9217                                 pkt->pkt_statistics |= STAT_ABORTED;
9218                                 break;
9219 
9220                         }
9221                         break;
9222 
9223                 case FC_PKT_NPORT_RJT:
9224                 case FC_PKT_FABRIC_RJT:
9225                 case FC_PKT_NPORT_BSY:
9226                 case FC_PKT_FABRIC_BSY:
9227                 default:
9228                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9229                             fcp_trace, FCP_BUF_LEVEL_8, 0,
9230                             "FC Status 0x%x, reason 0x%x",
9231                             fpkt->pkt_state, fpkt->pkt_reason);
9232                         pkt->pkt_reason = CMD_TRAN_ERR;
9233                         pkt->pkt_statistics |= STAT_ABORTED;
9234                         break;
9235                 }
9236 
9237                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9238                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9239                     "!FC error on cmd=%p target=0x%x: pkt state=0x%x "
9240                     " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state,
9241                     fpkt->pkt_reason);
9242         }
9243 
9244         ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran);
9245 }
9246 
9247 
9248 static int
9249 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr)
9250 {
9251         if (rsp->reserved_0 || rsp->reserved_1 ||
9252             rsp->fcp_u.fcp_status.reserved_0 ||
9253             rsp->fcp_u.fcp_status.reserved_1) {
9254                 /*
9255                  * These reserved fields should ideally be zero. FCP-2 does say
9256                  * that the recipient need not check for reserved fields to be
9257                  * zero. If they are not zero, we will not make a fuss about it
9258                  * - just log it (in debug to both trace buffer and messages
9259                  * file and to trace buffer only in non-debug) and move on.
9260                  *
9261                  * Non-zero reserved fields were seen with minnows.
9262                  *
9263                  * qlc takes care of some of this but we cannot assume that all
9264                  * FCAs will do so.
9265                  */
9266                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
9267                     FCP_BUF_LEVEL_5, 0,
9268                     "Got fcp response packet with non-zero reserved fields "
9269                     "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, "
9270                     "status.reserved_0:0x%x, status.reserved_1:0x%x",
9271                     rsp->reserved_0, rsp->reserved_1,
9272                     rsp->fcp_u.fcp_status.reserved_0,
9273                     rsp->fcp_u.fcp_status.reserved_1);
9274         }
9275 
9276         if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len >
9277             (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) {
9278                 return (FC_FAILURE);
9279         }
9280 
9281         if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len >
9282             (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len -
9283             sizeof (struct fcp_rsp))) {
9284                 return (FC_FAILURE);
9285         }
9286 
9287         return (FC_SUCCESS);
9288 }
9289 
9290 
9291 /*
9292  * This is called when there is a change the in device state. The case we're
9293  * handling here is, if the d_id s does not match, offline this tgt and online
9294  * a new tgt with the new d_id.  called from fcp_handle_devices with
9295  * port_mutex held.
9296  */
9297 static int
9298 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt,
9299     fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause)
9300 {
9301         ASSERT(mutex_owned(&pptr->port_mutex));
9302 
9303         FCP_TRACE(fcp_logq, pptr->port_instbuf,
9304             fcp_trace, FCP_BUF_LEVEL_3, 0,
9305             "Starting fcp_device_changed...");
9306 
9307         /*
9308          * The two cases where the port_device_changed is called is
9309          * either it changes it's d_id or it's hard address.
9310          */
9311         if ((ptgt->tgt_d_id != map_entry->map_did.port_id) ||
9312             (FC_TOP_EXTERNAL(pptr->port_topology) &&
9313             (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) {
9314 
9315                 /* offline this target */
9316                 mutex_enter(&ptgt->tgt_mutex);
9317                 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) {
9318                         (void) fcp_offline_target(pptr, ptgt, link_cnt,
9319                             0, 1, NDI_DEVI_REMOVE);
9320                 }
9321                 mutex_exit(&ptgt->tgt_mutex);
9322 
9323                 fcp_log(CE_NOTE, pptr->port_dip,
9324                     "Change in target properties: Old D_ID=%x New D_ID=%x"
9325                     " Old HA=%x New HA=%x", ptgt->tgt_d_id,
9326                     map_entry->map_did.port_id, ptgt->tgt_hard_addr,
9327                     map_entry->map_hard_addr.hard_addr);
9328         }
9329 
9330         return (fcp_handle_mapflags(pptr, ptgt, map_entry,
9331             link_cnt, tgt_cnt, cause));
9332 }
9333 
9334 /*
9335  *     Function: fcp_alloc_lun
9336  *
9337  *  Description: Creates a new lun structure and adds it to the list
9338  *               of luns of the target.
9339  *
9340  *     Argument: ptgt           Target the lun will belong to.
9341  *
9342  * Return Value: NULL           Failed
9343  *               Not NULL       Succeeded
9344  *
9345  *      Context: Kernel context
9346  */
9347 static struct fcp_lun *
9348 fcp_alloc_lun(struct fcp_tgt *ptgt)
9349 {
9350         struct fcp_lun *plun;
9351 
9352         plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP);
9353         if (plun != NULL) {
9354                 /*
9355                  * Initialize the mutex before putting in the target list
9356                  * especially before releasing the target mutex.
9357                  */
9358                 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL);
9359                 plun->lun_tgt = ptgt;
9360 
9361                 mutex_enter(&ptgt->tgt_mutex);
9362                 plun->lun_next = ptgt->tgt_lun;
9363                 ptgt->tgt_lun = plun;
9364                 plun->lun_old_guid = NULL;
9365                 plun->lun_old_guid_size = 0;
9366                 mutex_exit(&ptgt->tgt_mutex);
9367         }
9368 
9369         return (plun);
9370 }
9371 
9372 /*
9373  *     Function: fcp_dealloc_lun
9374  *
9375  *  Description: Frees the LUN structure passed by the caller.
9376  *
9377  *     Argument: plun           LUN structure to free.
9378  *
9379  * Return Value: None
9380  *
9381  *      Context: Kernel context.
9382  */
9383 static void
9384 fcp_dealloc_lun(struct fcp_lun *plun)
9385 {
9386         mutex_enter(&plun->lun_mutex);
9387         if (plun->lun_cip) {
9388                 fcp_remove_child(plun);
9389         }
9390         mutex_exit(&plun->lun_mutex);
9391 
9392         mutex_destroy(&plun->lun_mutex);
9393         if (plun->lun_guid) {
9394                 kmem_free(plun->lun_guid, plun->lun_guid_size);
9395         }
9396         if (plun->lun_old_guid) {
9397                 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size);
9398         }
9399         kmem_free(plun, sizeof (*plun));
9400 }
9401 
9402 /*
9403  *     Function: fcp_alloc_tgt
9404  *
9405  *  Description: Creates a new target structure and adds it to the port
9406  *               hash list.
9407  *
9408  *     Argument: pptr           fcp port structure
9409  *               *map_entry     entry describing the target to create
9410  *               link_cnt       Link state change counter
9411  *
9412  * Return Value: NULL           Failed
9413  *               Not NULL       Succeeded
9414  *
9415  *      Context: Kernel context.
9416  */
9417 static struct fcp_tgt *
9418 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt)
9419 {
9420         int                     hash;
9421         uchar_t                 *wwn;
9422         struct fcp_tgt  *ptgt;
9423 
9424         ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP);
9425         if (ptgt != NULL) {
9426                 mutex_enter(&pptr->port_mutex);
9427                 if (link_cnt != pptr->port_link_cnt) {
9428                         /*
9429                          * oh oh -- another link reset
9430                          * in progress -- give up
9431                          */
9432                         mutex_exit(&pptr->port_mutex);
9433                         kmem_free(ptgt, sizeof (*ptgt));
9434                         ptgt = NULL;
9435                 } else {
9436                         /*
9437                          * initialize the mutex before putting in the port
9438                          * wwn list, especially before releasing the port
9439                          * mutex.
9440                          */
9441                         mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL);
9442 
9443                         /* add new target entry to the port's hash list */
9444                         wwn = (uchar_t *)&map_entry->map_pwwn;
9445                         hash = FCP_HASH(wwn);
9446 
9447                         ptgt->tgt_next = pptr->port_tgt_hash_table[hash];
9448                         pptr->port_tgt_hash_table[hash] = ptgt;
9449 
9450                         /* save cross-ptr */
9451                         ptgt->tgt_port = pptr;
9452 
9453                         ptgt->tgt_change_cnt = 1;
9454 
9455                         /* initialize the target manual_config_only flag */
9456                         if (fcp_enable_auto_configuration) {
9457                                 ptgt->tgt_manual_config_only = 0;
9458                         } else {
9459                                 ptgt->tgt_manual_config_only = 1;
9460                         }
9461 
9462                         mutex_exit(&pptr->port_mutex);
9463                 }
9464         }
9465 
9466         return (ptgt);
9467 }
9468 
9469 /*
9470  *     Function: fcp_dealloc_tgt
9471  *
9472  *  Description: Frees the target structure passed by the caller.
9473  *
9474  *     Argument: ptgt           Target structure to free.
9475  *
9476  * Return Value: None
9477  *
9478  *      Context: Kernel context.
9479  */
9480 static void
9481 fcp_dealloc_tgt(struct fcp_tgt *ptgt)
9482 {
9483         mutex_destroy(&ptgt->tgt_mutex);
9484         kmem_free(ptgt, sizeof (*ptgt));
9485 }
9486 
9487 
9488 /*
9489  * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry
9490  *
9491  *      Device discovery commands will not be retried for-ever as
9492  *      this will have repercussions on other devices that need to
9493  *      be submitted to the hotplug thread. After a quick glance
9494  *      at the SCSI-3 spec, it was found that the spec doesn't
9495  *      mandate a forever retry, rather recommends a delayed retry.
9496  *
9497  *      Since Photon IB is single threaded, STATUS_BUSY is common
9498  *      in a 4+initiator environment. Make sure the total time
9499  *      spent on retries (including command timeout) does not
9500  *      60 seconds
9501  */
9502 static void
9503 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt)
9504 {
9505         struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9506         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
9507 
9508         mutex_enter(&pptr->port_mutex);
9509         mutex_enter(&ptgt->tgt_mutex);
9510         if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
9511                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
9512                     fcp_trace, FCP_BUF_LEVEL_2, 0,
9513                     "fcp_queue_ipkt,1:state change occured"
9514                     " for D_ID=0x%x", ptgt->tgt_d_id);
9515                 mutex_exit(&ptgt->tgt_mutex);
9516                 mutex_exit(&pptr->port_mutex);
9517                 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt,
9518                     icmd->ipkt_change_cnt, icmd->ipkt_cause);
9519                 fcp_icmd_free(pptr, icmd);
9520                 return;
9521         }
9522         mutex_exit(&ptgt->tgt_mutex);
9523 
9524         icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++;
9525 
9526         if (pptr->port_ipkt_list != NULL) {
9527                 /* add pkt to front of doubly-linked list */
9528                 pptr->port_ipkt_list->ipkt_prev = icmd;
9529                 icmd->ipkt_next = pptr->port_ipkt_list;
9530                 pptr->port_ipkt_list = icmd;
9531                 icmd->ipkt_prev = NULL;
9532         } else {
9533                 /* this is the first/only pkt on the list */
9534                 pptr->port_ipkt_list = icmd;
9535                 icmd->ipkt_next = NULL;
9536                 icmd->ipkt_prev = NULL;
9537         }
9538         mutex_exit(&pptr->port_mutex);
9539 }
9540 
9541 /*
9542  *     Function: fcp_transport
9543  *
9544  *  Description: This function submits the Fibre Channel packet to the transort
9545  *               layer by calling fc_ulp_transport().  If fc_ulp_transport()
9546  *               fails the submission, the treatment depends on the value of
9547  *               the variable internal.
9548  *
9549  *     Argument: port_handle    fp/fctl port handle.
9550  *               *fpkt          Packet to submit to the transport layer.
9551  *               internal       Not zero when it's an internal packet.
9552  *
9553  * Return Value: FC_TRAN_BUSY
9554  *               FC_STATEC_BUSY
9555  *               FC_OFFLINE
9556  *               FC_LOGINREQ
9557  *               FC_DEVICE_BUSY
9558  *               FC_SUCCESS
9559  */
9560 static int
9561 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal)
9562 {
9563         int     rval;
9564 
9565         rval = fc_ulp_transport(port_handle, fpkt);
9566         if (rval == FC_SUCCESS) {
9567                 return (rval);
9568         }
9569 
9570         /*
9571          * LUN isn't marked BUSY or OFFLINE, so we got here to transport
9572          * a command, if the underlying modules see that there is a state
9573          * change, or if a port is OFFLINE, that means, that state change
9574          * hasn't reached FCP yet, so re-queue the command for deferred
9575          * submission.
9576          */
9577         if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) ||
9578             (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) ||
9579             (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) {
9580                 /*
9581                  * Defer packet re-submission. Life hang is possible on
9582                  * internal commands if the port driver sends FC_STATEC_BUSY
9583                  * for ever, but that shouldn't happen in a good environment.
9584                  * Limiting re-transport for internal commands is probably a
9585                  * good idea..
9586                  * A race condition can happen when a port sees barrage of
9587                  * link transitions offline to online. If the FCTL has
9588                  * returned FC_STATEC_BUSY or FC_OFFLINE then none of the
9589                  * internal commands should be queued to do the discovery.
9590                  * The race condition is when an online comes and FCP starts
9591                  * its internal discovery and the link goes offline. It is
9592                  * possible that the statec_callback has not reached FCP
9593                  * and FCP is carrying on with its internal discovery.
9594                  * FC_STATEC_BUSY or FC_OFFLINE will be the first indication
9595                  * that the link has gone offline. At this point FCP should
9596                  * drop all the internal commands and wait for the
9597                  * statec_callback. It will be facilitated by incrementing
9598                  * port_link_cnt.
9599                  *
9600                  * For external commands, the (FC)pkt_timeout is decremented
9601                  * by the QUEUE Delay added by our driver, Care is taken to
9602                  * ensure that it doesn't become zero (zero means no timeout)
9603                  * If the time expires right inside driver queue itself,
9604                  * the watch thread will return it to the original caller
9605                  * indicating that the command has timed-out.
9606                  */
9607                 if (internal) {
9608                         char                    *op;
9609                         struct fcp_ipkt *icmd;
9610 
9611                         icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private;
9612                         switch (icmd->ipkt_opcode) {
9613                         case SCMD_REPORT_LUN:
9614                                 op = "REPORT LUN";
9615                                 break;
9616 
9617                         case SCMD_INQUIRY:
9618                                 op = "INQUIRY";
9619                                 break;
9620 
9621                         case SCMD_INQUIRY_PAGE83:
9622                                 op = "INQUIRY-83";
9623                                 break;
9624 
9625                         default:
9626                                 op = "Internal SCSI COMMAND";
9627                                 break;
9628                         }
9629 
9630                         if (fcp_handle_ipkt_errors(icmd->ipkt_port,
9631                             icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) {
9632                                 rval = FC_SUCCESS;
9633                         }
9634                 } else {
9635                         struct fcp_pkt *cmd;
9636                         struct fcp_port *pptr;
9637 
9638                         cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private;
9639                         cmd->cmd_state = FCP_PKT_IDLE;
9640                         pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address);
9641 
9642                         if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) {
9643                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
9644                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
9645                                     "fcp_transport: xport busy for pkt %p",
9646                                     cmd->cmd_pkt);
9647                                 rval = FC_TRAN_BUSY;
9648                         } else {
9649                                 fcp_queue_pkt(pptr, cmd);
9650                                 rval = FC_SUCCESS;
9651                         }
9652                 }
9653         }
9654 
9655         return (rval);
9656 }
9657 
9658 /*VARARGS3*/
9659 static void
9660 fcp_log(int level, dev_info_t *dip, const char *fmt, ...)
9661 {
9662         char            buf[256];
9663         va_list         ap;
9664 
9665         if (dip == NULL) {
9666                 dip = fcp_global_dip;
9667         }
9668 
9669         va_start(ap, fmt);
9670         (void) vsprintf(buf, fmt, ap);
9671         va_end(ap);
9672 
9673         scsi_log(dip, "fcp", level, buf);
9674 }
9675 
9676 /*
9677  * This function retries NS registry of FC4 type.
9678  * It assumes that fcp_mutex is held.
9679  * The function does nothing if topology is not fabric
9680  * So, the topology has to be set before this function can be called
9681  */
9682 static void
9683 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9684 {
9685         int     rval;
9686 
9687         ASSERT(MUTEX_HELD(&pptr->port_mutex));
9688 
9689         if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) ||
9690             ((pptr->port_topology != FC_TOP_FABRIC) &&
9691             (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) {
9692                 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) {
9693                         pptr->port_state &= ~FCP_STATE_NS_REG_FAILED;
9694                 }
9695                 return;
9696         }
9697         mutex_exit(&pptr->port_mutex);
9698         rval = fcp_do_ns_registry(pptr, s_id);
9699         mutex_enter(&pptr->port_mutex);
9700 
9701         if (rval == 0) {
9702                 /* Registry successful. Reset flag */
9703                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
9704         }
9705 }
9706 
9707 /*
9708  * This function registers the ULP with the switch by calling transport i/f
9709  */
9710 static int
9711 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id)
9712 {
9713         fc_ns_cmd_t             ns_cmd;
9714         ns_rfc_type_t           rfc;
9715         uint32_t                types[8];
9716 
9717         /*
9718          * Prepare the Name server structure to
9719          * register with the transport in case of
9720          * Fabric configuration.
9721          */
9722         bzero(&rfc, sizeof (rfc));
9723         bzero(types, sizeof (types));
9724 
9725         types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] =
9726             (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP));
9727 
9728         rfc.rfc_port_id.port_id = s_id;
9729         bcopy(types, rfc.rfc_types, sizeof (types));
9730 
9731         ns_cmd.ns_flags = 0;
9732         ns_cmd.ns_cmd = NS_RFT_ID;
9733         ns_cmd.ns_req_len = sizeof (rfc);
9734         ns_cmd.ns_req_payload = (caddr_t)&rfc;
9735         ns_cmd.ns_resp_len = 0;
9736         ns_cmd.ns_resp_payload = NULL;
9737 
9738         /*
9739          * Perform the Name Server Registration for SCSI_FCP FC4 Type.
9740          */
9741         if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) {
9742                 fcp_log(CE_WARN, pptr->port_dip,
9743                     "!ns_registry: failed name server registration");
9744                 return (1);
9745         }
9746 
9747         return (0);
9748 }
9749 
9750 /*
9751  *     Function: fcp_handle_port_attach
9752  *
9753  *  Description: This function is called from fcp_port_attach() to attach a
9754  *               new port. This routine does the following:
9755  *
9756  *              1) Allocates an fcp_port structure and initializes it.
9757  *              2) Tries to register the new FC-4 (FCP) capablity with the name
9758  *                 server.
9759  *              3) Kicks off the enumeration of the targets/luns visible
9760  *                 through this new port.  That is done by calling
9761  *                 fcp_statec_callback() if the port is online.
9762  *
9763  *     Argument: ulph           fp/fctl port handle.
9764  *               *pinfo         Port information.
9765  *               s_id           Port ID.
9766  *               instance       Device instance number for the local port
9767  *                              (returned by ddi_get_instance()).
9768  *
9769  * Return Value: DDI_SUCCESS
9770  *               DDI_FAILURE
9771  *
9772  *      Context: User and Kernel context.
9773  */
9774 /*ARGSUSED*/
9775 int
9776 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo,
9777     uint32_t s_id, int instance)
9778 {
9779         int                     res = DDI_FAILURE;
9780         scsi_hba_tran_t         *tran;
9781         int                     mutex_initted = FALSE;
9782         int                     hba_attached = FALSE;
9783         int                     soft_state_linked = FALSE;
9784         int                     event_bind = FALSE;
9785         struct fcp_port         *pptr;
9786         fc_portmap_t            *tmp_list = NULL;
9787         uint32_t                max_cnt, alloc_cnt;
9788         uchar_t                 *boot_wwn = NULL;
9789         uint_t                  nbytes;
9790         int                     manual_cfg;
9791 
9792         /*
9793          * this port instance attaching for the first time (or after
9794          * being detached before)
9795          */
9796         FCP_TRACE(fcp_logq, "fcp", fcp_trace,
9797             FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance);
9798 
9799         if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) {
9800                 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed"
9801                     "parent dip: %p; instance: %d", (void *)pinfo->port_dip,
9802                     instance);
9803                 return (res);
9804         }
9805 
9806         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
9807                 /* this shouldn't happen */
9808                 ddi_soft_state_free(fcp_softstate, instance);
9809                 cmn_err(CE_WARN, "fcp: bad soft state");
9810                 return (res);
9811         }
9812 
9813         (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance);
9814 
9815         /*
9816          * Make a copy of ulp_port_info as fctl allocates
9817          * a temp struct.
9818          */
9819         (void) fcp_cp_pinfo(pptr, pinfo);
9820 
9821         /*
9822          * Check for manual_configuration_only property.
9823          * Enable manual configurtion if the property is
9824          * set to 1, otherwise disable manual configuration.
9825          */
9826         if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip,
9827             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
9828             MANUAL_CFG_ONLY,
9829             -1)) != -1) {
9830                 if (manual_cfg == 1) {
9831                         char    *pathname;
9832                         pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
9833                         (void) ddi_pathname(pptr->port_dip, pathname);
9834                         cmn_err(CE_NOTE,
9835                             "%s (%s%d) %s is enabled via %s.conf.",
9836                             pathname,
9837                             ddi_driver_name(pptr->port_dip),
9838                             ddi_get_instance(pptr->port_dip),
9839                             MANUAL_CFG_ONLY,
9840                             ddi_driver_name(pptr->port_dip));
9841                         fcp_enable_auto_configuration = 0;
9842                         kmem_free(pathname, MAXPATHLEN);
9843                 }
9844         }
9845         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9846         pptr->port_link_cnt = 1;
9847         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt));
9848         pptr->port_id = s_id;
9849         pptr->port_instance = instance;
9850         _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state));
9851         pptr->port_state = FCP_STATE_INIT;
9852         if (pinfo->port_acc_attr == NULL) {
9853                 /*
9854                  * The corresponding FCA doesn't support DMA at all
9855                  */
9856                 pptr->port_state |= FCP_STATE_FCA_IS_NODMA;
9857         }
9858 
9859         _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state));
9860 
9861         if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) {
9862                 /*
9863                  * If FCA supports DMA in SCSI data phase, we need preallocate
9864                  * dma cookie, so stash the cookie size
9865                  */
9866                 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) *
9867                     pptr->port_data_dma_attr.dma_attr_sgllen;
9868         }
9869 
9870         /*
9871          * The two mutexes of fcp_port are initialized.  The variable
9872          * mutex_initted is incremented to remember that fact.  That variable
9873          * is checked when the routine fails and the mutexes have to be
9874          * destroyed.
9875          */
9876         mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL);
9877         mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL);
9878         mutex_initted++;
9879 
9880         /*
9881          * The SCSI tran structure is allocate and initialized now.
9882          */
9883         if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) {
9884                 fcp_log(CE_WARN, pptr->port_dip,
9885                     "!fcp%d: scsi_hba_tran_alloc failed", instance);
9886                 goto fail;
9887         }
9888 
9889         /* link in the transport structure then fill it in */
9890         pptr->port_tran = tran;
9891         tran->tran_hba_private               = pptr;
9892         tran->tran_tgt_init          = fcp_scsi_tgt_init;
9893         tran->tran_tgt_probe         = NULL;
9894         tran->tran_tgt_free          = fcp_scsi_tgt_free;
9895         tran->tran_start             = fcp_scsi_start;
9896         tran->tran_reset             = fcp_scsi_reset;
9897         tran->tran_abort             = fcp_scsi_abort;
9898         tran->tran_getcap            = fcp_scsi_getcap;
9899         tran->tran_setcap            = fcp_scsi_setcap;
9900         tran->tran_init_pkt          = NULL;
9901         tran->tran_destroy_pkt               = NULL;
9902         tran->tran_dmafree           = NULL;
9903         tran->tran_sync_pkt          = NULL;
9904         tran->tran_reset_notify              = fcp_scsi_reset_notify;
9905         tran->tran_get_bus_addr              = fcp_scsi_get_bus_addr;
9906         tran->tran_get_name          = fcp_scsi_get_name;
9907         tran->tran_clear_aca         = NULL;
9908         tran->tran_clear_task_set    = NULL;
9909         tran->tran_terminate_task    = NULL;
9910         tran->tran_get_eventcookie   = fcp_scsi_bus_get_eventcookie;
9911         tran->tran_add_eventcall     = fcp_scsi_bus_add_eventcall;
9912         tran->tran_remove_eventcall  = fcp_scsi_bus_remove_eventcall;
9913         tran->tran_post_event                = fcp_scsi_bus_post_event;
9914         tran->tran_quiesce           = NULL;
9915         tran->tran_unquiesce         = NULL;
9916         tran->tran_bus_reset         = NULL;
9917         tran->tran_bus_config                = fcp_scsi_bus_config;
9918         tran->tran_bus_unconfig              = fcp_scsi_bus_unconfig;
9919         tran->tran_bus_power         = NULL;
9920         tran->tran_interconnect_type = INTERCONNECT_FABRIC;
9921 
9922         tran->tran_pkt_constructor   = fcp_kmem_cache_constructor;
9923         tran->tran_pkt_destructor    = fcp_kmem_cache_destructor;
9924         tran->tran_setup_pkt         = fcp_pkt_setup;
9925         tran->tran_teardown_pkt              = fcp_pkt_teardown;
9926         tran->tran_hba_len           = pptr->port_priv_pkt_len +
9927             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz;
9928         if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) {
9929                 /*
9930                  * If FCA don't support DMA, then we use different vectors to
9931                  * minimize the effects on DMA code flow path
9932                  */
9933                 tran->tran_start        = fcp_pseudo_start;
9934                 tran->tran_init_pkt     = fcp_pseudo_init_pkt;
9935                 tran->tran_destroy_pkt          = fcp_pseudo_destroy_pkt;
9936                 tran->tran_sync_pkt     = fcp_pseudo_sync_pkt;
9937                 tran->tran_dmafree      = fcp_pseudo_dmafree;
9938                 tran->tran_setup_pkt    = NULL;
9939                 tran->tran_teardown_pkt         = NULL;
9940                 tran->tran_pkt_constructor = NULL;
9941                 tran->tran_pkt_destructor  = NULL;
9942                 pptr->port_data_dma_attr   = pseudo_fca_dma_attr;
9943         }
9944 
9945         /*
9946          * Allocate an ndi event handle
9947          */
9948         pptr->port_ndi_event_defs = (ndi_event_definition_t *)
9949             kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP);
9950 
9951         bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs,
9952             sizeof (fcp_ndi_event_defs));
9953 
9954         (void) ndi_event_alloc_hdl(pptr->port_dip, NULL,
9955             &pptr->port_ndi_event_hdl, NDI_SLEEP);
9956 
9957         pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1;
9958         pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS;
9959         pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs;
9960 
9961         if (DEVI_IS_ATTACHING(pptr->port_dip) &&
9962             (ndi_event_bind_set(pptr->port_ndi_event_hdl,
9963             &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) {
9964                 goto fail;
9965         }
9966         event_bind++;   /* Checked in fail case */
9967 
9968         if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr,
9969             tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB)
9970             != DDI_SUCCESS) {
9971                 fcp_log(CE_WARN, pptr->port_dip,
9972                     "!fcp%d: scsi_hba_attach_setup failed", instance);
9973                 goto fail;
9974         }
9975         hba_attached++; /* Checked in fail case */
9976 
9977         pptr->port_mpxio = 0;
9978         if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) ==
9979             MDI_SUCCESS) {
9980                 pptr->port_mpxio++;
9981         }
9982 
9983         /*
9984          * The following code is putting the new port structure in the global
9985          * list of ports and, if it is the first port to attach, it start the
9986          * fcp_watchdog_tick.
9987          *
9988          * Why put this new port in the global before we are done attaching it?
9989          * We are actually making the structure globally known before we are
9990          * done attaching it.  The reason for that is: because of the code that
9991          * follows.  At this point the resources to handle the port are
9992          * allocated.  This function is now going to do the following:
9993          *
9994          *   1) It is going to try to register with the name server advertizing
9995          *      the new FCP capability of the port.
9996          *   2) It is going to play the role of the fp/fctl layer by building
9997          *      a list of worlwide names reachable through this port and call
9998          *      itself on fcp_statec_callback().  That requires the port to
9999          *      be part of the global list.
10000          */
10001         mutex_enter(&fcp_global_mutex);
10002         if (fcp_port_head == NULL) {
10003                 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist);
10004         }
10005         pptr->port_next = fcp_port_head;
10006         fcp_port_head = pptr;
10007         soft_state_linked++;
10008 
10009         if (fcp_watchdog_init++ == 0) {
10010                 fcp_watchdog_tick = fcp_watchdog_timeout *
10011                     drv_usectohz(1000000);
10012                 fcp_watchdog_id = timeout(fcp_watch, NULL,
10013                     fcp_watchdog_tick);
10014         }
10015         mutex_exit(&fcp_global_mutex);
10016 
10017         /*
10018          * Here an attempt is made to register with the name server, the new
10019          * FCP capability.  That is done using an RTF_ID to the name server.
10020          * It is done synchronously.  The function fcp_do_ns_registry()
10021          * doesn't return till the name server responded.
10022          * On failures, just ignore it for now and it will get retried during
10023          * state change callbacks. We'll set a flag to show this failure
10024          */
10025         if (fcp_do_ns_registry(pptr, s_id)) {
10026                 mutex_enter(&pptr->port_mutex);
10027                 pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10028                 mutex_exit(&pptr->port_mutex);
10029         } else {
10030                 mutex_enter(&pptr->port_mutex);
10031                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10032                 mutex_exit(&pptr->port_mutex);
10033         }
10034 
10035         /*
10036          * Lookup for boot WWN property
10037          */
10038         if (modrootloaded != 1) {
10039                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10040                     ddi_get_parent(pinfo->port_dip),
10041                     DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10042                     &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10043                     (nbytes == FC_WWN_SIZE)) {
10044                         bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10045                 }
10046                 if (boot_wwn) {
10047                         ddi_prop_free(boot_wwn);
10048                 }
10049         }
10050 
10051         /*
10052          * Handle various topologies and link states.
10053          */
10054         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10055         case FC_STATE_OFFLINE:
10056 
10057                 /*
10058                  * we're attaching a port where the link is offline
10059                  *
10060                  * Wait for ONLINE, at which time a state
10061                  * change will cause a statec_callback
10062                  *
10063                  * in the mean time, do not do anything
10064                  */
10065                 res = DDI_SUCCESS;
10066                 pptr->port_state |= FCP_STATE_OFFLINE;
10067                 break;
10068 
10069         case FC_STATE_ONLINE: {
10070                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
10071                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10072                         res = DDI_SUCCESS;
10073                         break;
10074                 }
10075                 /*
10076                  * discover devices and create nodes (a private
10077                  * loop or point-to-point)
10078                  */
10079                 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10080 
10081                 /*
10082                  * At this point we are going to build a list of all the ports
10083                  * that can be reached through this local port.  It looks like
10084                  * we cannot handle more than FCP_MAX_DEVICES per local port
10085                  * (128).
10086                  */
10087                 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10088                     sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10089                     KM_NOSLEEP)) == NULL) {
10090                         fcp_log(CE_WARN, pptr->port_dip,
10091                             "!fcp%d: failed to allocate portmap",
10092                             instance);
10093                         goto fail;
10094                 }
10095 
10096                 /*
10097                  * fc_ulp_getportmap() is going to provide us with the list of
10098                  * remote ports in the buffer we just allocated.  The way the
10099                  * list is going to be retrieved depends on the topology.
10100                  * However, if we are connected to a Fabric, a name server
10101                  * request may be sent to get the list of FCP capable ports.
10102                  * It should be noted that is the case the request is
10103                  * synchronous.  This means we are stuck here till the name
10104                  * server replies.  A lot of things can change during that time
10105                  * and including, may be, being called on
10106                  * fcp_statec_callback() for different reasons. I'm not sure
10107                  * the code can handle that.
10108                  */
10109                 max_cnt = FCP_MAX_DEVICES;
10110                 alloc_cnt = FCP_MAX_DEVICES;
10111                 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10112                     &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10113                     FC_SUCCESS) {
10114                         caddr_t msg;
10115 
10116                         (void) fc_ulp_error(res, &msg);
10117 
10118                         /*
10119                          * this  just means the transport is
10120                          * busy perhaps building a portmap so,
10121                          * for now, succeed this port attach
10122                          * when the transport has a new map,
10123                          * it'll send us a state change then
10124                          */
10125                         fcp_log(CE_WARN, pptr->port_dip,
10126                             "!failed to get port map : %s", msg);
10127 
10128                         res = DDI_SUCCESS;
10129                         break;  /* go return result */
10130                 }
10131                 if (max_cnt > alloc_cnt) {
10132                         alloc_cnt = max_cnt;
10133                 }
10134 
10135                 /*
10136                  * We are now going to call fcp_statec_callback() ourselves.
10137                  * By issuing this call we are trying to kick off the enumera-
10138                  * tion process.
10139                  */
10140                 /*
10141                  * let the state change callback do the SCSI device
10142                  * discovery and create the devinfos
10143                  */
10144                 fcp_statec_callback(ulph, pptr->port_fp_handle,
10145                     pptr->port_phys_state, pptr->port_topology, tmp_list,
10146                     max_cnt, pptr->port_id);
10147 
10148                 res = DDI_SUCCESS;
10149                 break;
10150         }
10151 
10152         default:
10153                 /* unknown port state */
10154                 fcp_log(CE_WARN, pptr->port_dip,
10155                     "!fcp%d: invalid port state at attach=0x%x",
10156                     instance, pptr->port_phys_state);
10157 
10158                 mutex_enter(&pptr->port_mutex);
10159                 pptr->port_phys_state = FCP_STATE_OFFLINE;
10160                 mutex_exit(&pptr->port_mutex);
10161 
10162                 res = DDI_SUCCESS;
10163                 break;
10164         }
10165 
10166         /* free temp list if used */
10167         if (tmp_list != NULL) {
10168                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10169         }
10170 
10171         /* note the attach time */
10172         pptr->port_attach_time = ddi_get_lbolt64();
10173 
10174         /* all done */
10175         return (res);
10176 
10177         /* a failure we have to clean up after */
10178 fail:
10179         fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10180 
10181         if (soft_state_linked) {
10182                 /* remove this fcp_port from the linked list */
10183                 (void) fcp_soft_state_unlink(pptr);
10184         }
10185 
10186         /* unbind and free event set */
10187         if (pptr->port_ndi_event_hdl) {
10188                 if (event_bind) {
10189                         (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10190                             &pptr->port_ndi_events, NDI_SLEEP);
10191                 }
10192                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10193         }
10194 
10195         if (pptr->port_ndi_event_defs) {
10196                 (void) kmem_free(pptr->port_ndi_event_defs,
10197                     sizeof (fcp_ndi_event_defs));
10198         }
10199 
10200         /*
10201          * Clean up mpxio stuff
10202          */
10203         if (pptr->port_mpxio) {
10204                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10205                 pptr->port_mpxio--;
10206         }
10207 
10208         /* undo SCSI HBA setup */
10209         if (hba_attached) {
10210                 (void) scsi_hba_detach(pptr->port_dip);
10211         }
10212         if (pptr->port_tran != NULL) {
10213                 scsi_hba_tran_free(pptr->port_tran);
10214         }
10215 
10216         mutex_enter(&fcp_global_mutex);
10217 
10218         /*
10219          * We check soft_state_linked, because it is incremented right before
10220          * we call increment fcp_watchdog_init.  Therefore, we know if
10221          * soft_state_linked is still FALSE, we do not want to decrement
10222          * fcp_watchdog_init or possibly call untimeout.
10223          */
10224 
10225         if (soft_state_linked) {
10226                 if (--fcp_watchdog_init == 0) {
10227                         timeout_id_t    tid = fcp_watchdog_id;
10228 
10229                         mutex_exit(&fcp_global_mutex);
10230                         (void) untimeout(tid);
10231                 } else {
10232                         mutex_exit(&fcp_global_mutex);
10233                 }
10234         } else {
10235                 mutex_exit(&fcp_global_mutex);
10236         }
10237 
10238         if (mutex_initted) {
10239                 mutex_destroy(&pptr->port_mutex);
10240                 mutex_destroy(&pptr->port_pkt_mutex);
10241         }
10242 
10243         if (tmp_list != NULL) {
10244                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10245         }
10246 
10247         /* this makes pptr invalid */
10248         ddi_soft_state_free(fcp_softstate, instance);
10249 
10250         return (DDI_FAILURE);
10251 }
10252 
10253 
10254 static int
10255 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10256 {
10257         int count = 0;
10258 
10259         mutex_enter(&pptr->port_mutex);
10260 
10261         /*
10262          * if the port is powered down or suspended, nothing else
10263          * to do; just return.
10264          */
10265         if (flag != FCP_STATE_DETACHING) {
10266                 if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10267                     FCP_STATE_SUSPENDED)) {
10268                         pptr->port_state |= flag;
10269                         mutex_exit(&pptr->port_mutex);
10270                         return (FC_SUCCESS);
10271                 }
10272         }
10273 
10274         if (pptr->port_state & FCP_STATE_IN_MDI) {
10275                 mutex_exit(&pptr->port_mutex);
10276                 return (FC_FAILURE);
10277         }
10278 
10279         FCP_TRACE(fcp_logq, pptr->port_instbuf,
10280             fcp_trace, FCP_BUF_LEVEL_2, 0,
10281             "fcp_handle_port_detach: port is detaching");
10282 
10283         pptr->port_state |= flag;
10284 
10285         /*
10286          * Wait for any ongoing reconfig/ipkt to complete, that
10287          * ensures the freeing to targets/luns is safe.
10288          * No more ref to this port should happen from statec/ioctl
10289          * after that as it was removed from the global port list.
10290          */
10291         while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10292             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10293                 /*
10294                  * Let's give sufficient time for reconfig/ipkt
10295                  * to complete.
10296                  */
10297                 if (count++ >= FCP_ICMD_DEADLINE) {
10298                         break;
10299                 }
10300                 mutex_exit(&pptr->port_mutex);
10301                 delay(drv_usectohz(1000000));
10302                 mutex_enter(&pptr->port_mutex);
10303         }
10304 
10305         /*
10306          * if the driver is still busy then fail to
10307          * suspend/power down.
10308          */
10309         if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10310             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10311                 pptr->port_state &= ~flag;
10312                 mutex_exit(&pptr->port_mutex);
10313                 return (FC_FAILURE);
10314         }
10315 
10316         if (flag == FCP_STATE_DETACHING) {
10317                 pptr = fcp_soft_state_unlink(pptr);
10318                 ASSERT(pptr != NULL);
10319         }
10320 
10321         pptr->port_link_cnt++;
10322         pptr->port_state |= FCP_STATE_OFFLINE;
10323         pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10324 
10325         fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10326             FCP_CAUSE_LINK_DOWN);
10327         mutex_exit(&pptr->port_mutex);
10328 
10329         /* kill watch dog timer if we're the last */
10330         mutex_enter(&fcp_global_mutex);
10331         if (--fcp_watchdog_init == 0) {
10332                 timeout_id_t    tid = fcp_watchdog_id;
10333                 mutex_exit(&fcp_global_mutex);
10334                 (void) untimeout(tid);
10335         } else {
10336                 mutex_exit(&fcp_global_mutex);
10337         }
10338 
10339         /* clean up the port structures */
10340         if (flag == FCP_STATE_DETACHING) {
10341                 fcp_cleanup_port(pptr, instance);
10342         }
10343 
10344         return (FC_SUCCESS);
10345 }
10346 
10347 
10348 static void
10349 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10350 {
10351         ASSERT(pptr != NULL);
10352 
10353         /* unbind and free event set */
10354         if (pptr->port_ndi_event_hdl) {
10355                 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10356                     &pptr->port_ndi_events, NDI_SLEEP);
10357                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10358         }
10359 
10360         if (pptr->port_ndi_event_defs) {
10361                 (void) kmem_free(pptr->port_ndi_event_defs,
10362                     sizeof (fcp_ndi_event_defs));
10363         }
10364 
10365         /* free the lun/target structures and devinfos */
10366         fcp_free_targets(pptr);
10367 
10368         /*
10369          * Clean up mpxio stuff
10370          */
10371         if (pptr->port_mpxio) {
10372                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10373                 pptr->port_mpxio--;
10374         }
10375 
10376         /* clean up SCSA stuff */
10377         (void) scsi_hba_detach(pptr->port_dip);
10378         if (pptr->port_tran != NULL) {
10379                 scsi_hba_tran_free(pptr->port_tran);
10380         }
10381 
10382 #ifdef  KSTATS_CODE
10383         /* clean up kstats */
10384         if (pptr->fcp_ksp != NULL) {
10385                 kstat_delete(pptr->fcp_ksp);
10386         }
10387 #endif
10388 
10389         /* clean up soft state mutexes/condition variables */
10390         mutex_destroy(&pptr->port_mutex);
10391         mutex_destroy(&pptr->port_pkt_mutex);
10392 
10393         /* all done with soft state */
10394         ddi_soft_state_free(fcp_softstate, instance);
10395 }
10396 
10397 /*
10398  *     Function: fcp_kmem_cache_constructor
10399  *
10400  *  Description: This function allocates and initializes the resources required
10401  *               to build a scsi_pkt structure the target driver.  The result
10402  *               of the allocation and initialization will be cached in the
10403  *               memory cache.  As DMA resources may be allocated here, that
10404  *               means DMA resources will be tied up in the cache manager.
10405  *               This is a tradeoff that has been made for performance reasons.
10406  *
10407  *     Argument: *buf           Memory to preinitialize.
10408  *               *arg           FCP port structure (fcp_port).
10409  *               kmflags        Value passed to kmem_cache_alloc() and
10410  *                              propagated to the constructor.
10411  *
10412  * Return Value: 0      Allocation/Initialization was successful.
10413  *               -1     Allocation or Initialization failed.
10414  *
10415  *
10416  * If the returned value is 0, the buffer is initialized like this:
10417  *
10418  *                  +================================+
10419  *           +----> |              struct scsi_pkt        |
10420  *           |      |                                |
10421  *           | +--- | pkt_ha_private                 |
10422  *           | |    |                                |
10423  *           | |    +================================+
10424  *           | |
10425  *           | |    +================================+
10426  *           | +--> |            struct fcp_pkt           | <---------+
10427  *           |      |                                |           |
10428  *           +----- | cmd_pkt                        |           |
10429  *                  |                     cmd_fp_pkt | ---+      |
10430  *        +-------->| cmd_fcp_rsp[]               |    |      |
10431  *        |    +--->| cmd_fcp_cmd[]               |    |      |
10432  *        |    |    |--------------------------------|    |      |
10433  *        |    |    |         struct fc_packet       | <--+   |
10434  *        |    |    |                                |           |
10435  *        |    |    |                pkt_ulp_private | ----------+
10436  *        |    |    |                pkt_fca_private | -----+
10437  *        |    |    |                pkt_data_cookie | ---+ |
10438  *        |    |    | pkt_cmdlen                     |    | |
10439  *        |    |(a) | pkt_rsplen                     |    | |
10440  *        |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10441  *        |     (b) |                 pkt_cmd_cookie | ---|-|----------+    |
10442  *        +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10443  *                  |                pkt_resp_cookie | ---|-|--+   |   |    |
10444  *                  | pkt_cmd_dma                    |    | |  |   |   |    |
10445  *                  | pkt_cmd_acc                    |    | |  |   |   |    |
10446  *                  +================================+    | |  |   |   |    |
10447  *                  |         dma_cookies            | <--+ |  |   |   |    |
10448  *                  |                                |      |  |   |   |    |
10449  *                  +================================+      |  |   |   |    |
10450  *                  |         fca_private            | <----+  |   |   |    |
10451  *                  |                                |         |   |   |    |
10452  *                  +================================+         |   |   |    |
10453  *                                                             |   |   |    |
10454  *                                                             |   |   |    |
10455  *                  +================================+   (d)   |   |   |    |
10456  *                  |        fcp_resp cookies        | <-------+   |   |    |
10457  *                  |                                |             |   |    |
10458  *                  +================================+             |   |    |
10459  *                                                                 |   |    |
10460  *                  +================================+   (d)       |   |    |
10461  *                  |           fcp_resp             | <-----------+   |    |
10462  *                  |   (DMA resources associated)   |                 |    |
10463  *                  +================================+                 |    |
10464  *                                                                     |    |
10465  *                                                                     |    |
10466  *                                                                     |    |
10467  *                  +================================+   (c)           |    |
10468  *                  |        fcp_cmd cookies         | <---------------+    |
10469  *                  |                                |                      |
10470  *                  +================================+                      |
10471  *                                                                          |
10472  *                  +================================+   (c)                |
10473  *                  |            fcp_cmd             | <--------------------+
10474  *                  |   (DMA resources associated)   |
10475  *                  +================================+
10476  *
10477  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10478  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10479  * (c) Only if DMA is used for the FCP_CMD buffer.
10480  * (d) Only if DMA is used for the FCP_RESP buffer
10481  */
10482 static int
10483 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10484     int kmflags)
10485 {
10486         struct fcp_pkt  *cmd;
10487         struct fcp_port *pptr;
10488         fc_packet_t     *fpkt;
10489 
10490         pptr = (struct fcp_port *)tran->tran_hba_private;
10491         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10492         bzero(cmd, tran->tran_hba_len);
10493 
10494         cmd->cmd_pkt = pkt;
10495         pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10496         fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10497         cmd->cmd_fp_pkt = fpkt;
10498 
10499         cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10500         cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10501         cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10502             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10503 
10504         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10505             sizeof (struct fcp_pkt));
10506 
10507         fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10508         fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10509 
10510         if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10511                 /*
10512                  * The underlying HBA doesn't want to DMA the fcp_cmd or
10513                  * fcp_resp.  The transfer of information will be done by
10514                  * bcopy.
10515                  * The naming of the flags (that is actually a value) is
10516                  * unfortunate.  FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10517                  * DMA" but instead "NO DMA".
10518                  */
10519                 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10520                 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10521                 fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10522         } else {
10523                 /*
10524                  * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10525                  * buffer.  A buffer is allocated for each one the ddi_dma_*
10526                  * interfaces.
10527                  */
10528                 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10529                         return (-1);
10530                 }
10531         }
10532 
10533         return (0);
10534 }
10535 
10536 /*
10537  *     Function: fcp_kmem_cache_destructor
10538  *
10539  *  Description: Called by the destructor of the cache managed by SCSA.
10540  *               All the resources pre-allocated in fcp_pkt_constructor
10541  *               and the data also pre-initialized in fcp_pkt_constructor
10542  *               are freed and uninitialized here.
10543  *
10544  *     Argument: *buf           Memory to uninitialize.
10545  *               *arg           FCP port structure (fcp_port).
10546  *
10547  * Return Value: None
10548  *
10549  *      Context: kernel
10550  */
10551 static void
10552 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10553 {
10554         struct fcp_pkt  *cmd;
10555         struct fcp_port *pptr;
10556 
10557         pptr = (struct fcp_port *)(tran->tran_hba_private);
10558         cmd = pkt->pkt_ha_private;
10559 
10560         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10561                 /*
10562                  * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10563                  * buffer and DMA resources allocated to do so are released.
10564                  */
10565                 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10566         }
10567 }
10568 
10569 /*
10570  *     Function: fcp_alloc_cmd_resp
10571  *
10572  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10573  *               will be DMAed by the HBA.  The buffer is allocated applying
10574  *               the DMA requirements for the HBA.  The buffers allocated will
10575  *               also be bound.  DMA resources are allocated in the process.
10576  *               They will be released by fcp_free_cmd_resp().
10577  *
10578  *     Argument: *pptr  FCP port.
10579  *               *fpkt  fc packet for which the cmd and resp packet should be
10580  *                      allocated.
10581  *               flags  Allocation flags.
10582  *
10583  * Return Value: FC_FAILURE
10584  *               FC_SUCCESS
10585  *
10586  *      Context: User or Kernel context only if flags == KM_SLEEP.
10587  *               Interrupt context if the KM_SLEEP is not specified.
10588  */
10589 static int
10590 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10591 {
10592         int                     rval;
10593         int                     cmd_len;
10594         int                     resp_len;
10595         ulong_t                 real_len;
10596         int                     (*cb) (caddr_t);
10597         ddi_dma_cookie_t        pkt_cookie;
10598         ddi_dma_cookie_t        *cp;
10599         uint32_t                cnt;
10600 
10601         cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10602 
10603         cmd_len = fpkt->pkt_cmdlen;
10604         resp_len = fpkt->pkt_rsplen;
10605 
10606         ASSERT(fpkt->pkt_cmd_dma == NULL);
10607 
10608         /* Allocation of a DMA handle used in subsequent calls. */
10609         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10610             cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10611                 return (FC_FAILURE);
10612         }
10613 
10614         /* A buffer is allocated that satisfies the DMA requirements. */
10615         rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10616             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10617             (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10618 
10619         if (rval != DDI_SUCCESS) {
10620                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10621                 return (FC_FAILURE);
10622         }
10623 
10624         if (real_len < cmd_len) {
10625                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10626                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10627                 return (FC_FAILURE);
10628         }
10629 
10630         /* The buffer allocated is DMA bound. */
10631         rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10632             fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10633             cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10634 
10635         if (rval != DDI_DMA_MAPPED) {
10636                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10637                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10638                 return (FC_FAILURE);
10639         }
10640 
10641         if (fpkt->pkt_cmd_cookie_cnt >
10642             pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10643                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10644                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10645                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10646                 return (FC_FAILURE);
10647         }
10648 
10649         ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10650 
10651         /*
10652          * The buffer where the scatter/gather list is going to be built is
10653          * allocated.
10654          */
10655         cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10656             fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10657             KM_NOSLEEP);
10658 
10659         if (cp == NULL) {
10660                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10661                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10662                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10663                 return (FC_FAILURE);
10664         }
10665 
10666         /*
10667          * The scatter/gather list for the buffer we just allocated is built
10668          * here.
10669          */
10670         *cp = pkt_cookie;
10671         cp++;
10672 
10673         for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10674                 ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10675                     &pkt_cookie);
10676                 *cp = pkt_cookie;
10677         }
10678 
10679         ASSERT(fpkt->pkt_resp_dma == NULL);
10680         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10681             cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10682                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10683                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10684                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10685                 return (FC_FAILURE);
10686         }
10687 
10688         rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10689             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10690             (caddr_t *)&fpkt->pkt_resp, &real_len,
10691             &fpkt->pkt_resp_acc);
10692 
10693         if (rval != DDI_SUCCESS) {
10694                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10695                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10696                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10697                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10698                 kmem_free(fpkt->pkt_cmd_cookie,
10699                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10700                 return (FC_FAILURE);
10701         }
10702 
10703         if (real_len < resp_len) {
10704                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10705                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10706                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10707                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10708                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10709                 kmem_free(fpkt->pkt_cmd_cookie,
10710                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10711                 return (FC_FAILURE);
10712         }
10713 
10714         rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10715             fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10716             cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10717 
10718         if (rval != DDI_DMA_MAPPED) {
10719                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10720                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10721                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10722                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10723                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10724                 kmem_free(fpkt->pkt_cmd_cookie,
10725                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10726                 return (FC_FAILURE);
10727         }
10728 
10729         if (fpkt->pkt_resp_cookie_cnt >
10730             pptr->port_resp_dma_attr.dma_attr_sgllen) {
10731                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10732                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10733                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10734                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10735                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10736                 kmem_free(fpkt->pkt_cmd_cookie,
10737                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10738                 return (FC_FAILURE);
10739         }
10740 
10741         ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10742 
10743         cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10744             fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10745             KM_NOSLEEP);
10746 
10747         if (cp == NULL) {
10748                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10749                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10750                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10751                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10752                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10753                 kmem_free(fpkt->pkt_cmd_cookie,
10754                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10755                 return (FC_FAILURE);
10756         }
10757 
10758         *cp = pkt_cookie;
10759         cp++;
10760 
10761         for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10762                 ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10763                     &pkt_cookie);
10764                 *cp = pkt_cookie;
10765         }
10766 
10767         return (FC_SUCCESS);
10768 }
10769 
10770 /*
10771  *     Function: fcp_free_cmd_resp
10772  *
10773  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10774  *               allocated by fcp_alloc_cmd_resp() and all the resources
10775  *               associated with them.  That includes the DMA resources and the
10776  *               buffer allocated for the cookies of each one of them.
10777  *
10778  *     Argument: *pptr          FCP port context.
10779  *               *fpkt          fc packet containing the cmd and resp packet
10780  *                              to be released.
10781  *
10782  * Return Value: None
10783  *
10784  *      Context: Interrupt, User and Kernel context.
10785  */
10786 /* ARGSUSED */
10787 static void
10788 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10789 {
10790         ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10791 
10792         if (fpkt->pkt_resp_dma) {
10793                 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10794                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10795                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10796         }
10797 
10798         if (fpkt->pkt_resp_cookie) {
10799                 kmem_free(fpkt->pkt_resp_cookie,
10800                     fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10801                 fpkt->pkt_resp_cookie = NULL;
10802         }
10803 
10804         if (fpkt->pkt_cmd_dma) {
10805                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10806                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10807                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10808         }
10809 
10810         if (fpkt->pkt_cmd_cookie) {
10811                 kmem_free(fpkt->pkt_cmd_cookie,
10812                     fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10813                 fpkt->pkt_cmd_cookie = NULL;
10814         }
10815 }
10816 
10817 
10818 /*
10819  * called by the transport to do our own target initialization
10820  *
10821  * can acquire and release the global mutex
10822  */
10823 /* ARGSUSED */
10824 static int
10825 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10826     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10827 {
10828         uchar_t                 *bytes;
10829         uint_t                  nbytes;
10830         uint16_t                lun_num;
10831         struct fcp_tgt  *ptgt;
10832         struct fcp_lun  *plun;
10833         struct fcp_port *pptr = (struct fcp_port *)
10834             hba_tran->tran_hba_private;
10835 
10836         ASSERT(pptr != NULL);
10837 
10838         FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10839             FCP_BUF_LEVEL_8, 0,
10840             "fcp_phys_tgt_init: called for %s (instance %d)",
10841             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10842 
10843         /* get our port WWN property */
10844         bytes = NULL;
10845         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10846             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10847             (nbytes != FC_WWN_SIZE)) {
10848                 /* no port WWN property */
10849                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10850                     FCP_BUF_LEVEL_8, 0,
10851                     "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10852                     " for %s (instance %d): bytes=%p nbytes=%x",
10853                     ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10854                     nbytes);
10855 
10856                 if (bytes != NULL) {
10857                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10858                 }
10859 
10860                 return (DDI_NOT_WELL_FORMED);
10861         }
10862         ASSERT(bytes != NULL);
10863 
10864         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10865             LUN_PROP, 0xFFFF);
10866         if (lun_num == 0xFFFF) {
10867                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10868                     FCP_BUF_LEVEL_8, 0,
10869                     "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10870                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10871                     ddi_get_instance(tgt_dip));
10872 
10873                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10874                 return (DDI_NOT_WELL_FORMED);
10875         }
10876 
10877         mutex_enter(&pptr->port_mutex);
10878         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10879                 mutex_exit(&pptr->port_mutex);
10880                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10881                     FCP_BUF_LEVEL_8, 0,
10882                     "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10883                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10884                     ddi_get_instance(tgt_dip));
10885 
10886                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10887                 return (DDI_FAILURE);
10888         }
10889 
10890         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10891             FC_WWN_SIZE) == 0);
10892         ASSERT(plun->lun_num == lun_num);
10893 
10894         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10895 
10896         ptgt = plun->lun_tgt;
10897 
10898         mutex_enter(&ptgt->tgt_mutex);
10899         plun->lun_tgt_count++;
10900         scsi_device_hba_private_set(sd, plun);
10901         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10902         plun->lun_sd = sd;
10903         mutex_exit(&ptgt->tgt_mutex);
10904         mutex_exit(&pptr->port_mutex);
10905 
10906         return (DDI_SUCCESS);
10907 }
10908 
10909 /*ARGSUSED*/
10910 static int
10911 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10912     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10913 {
10914         uchar_t                 *bytes;
10915         uint_t                  nbytes;
10916         uint16_t                lun_num;
10917         struct fcp_tgt  *ptgt;
10918         struct fcp_lun  *plun;
10919         struct fcp_port *pptr = (struct fcp_port *)
10920             hba_tran->tran_hba_private;
10921         child_info_t            *cip;
10922 
10923         ASSERT(pptr != NULL);
10924 
10925         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10926             fcp_trace, FCP_BUF_LEVEL_8, 0,
10927             "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10928             " (tgt_dip %p)", ddi_get_name(tgt_dip),
10929             ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10930 
10931         cip = (child_info_t *)sd->sd_pathinfo;
10932         if (cip == NULL) {
10933                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10934                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10935                     "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10936                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10937                     ddi_get_instance(tgt_dip));
10938 
10939                 return (DDI_NOT_WELL_FORMED);
10940         }
10941 
10942         /* get our port WWN property */
10943         bytes = NULL;
10944         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10945             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10946             (nbytes != FC_WWN_SIZE)) {
10947                 if (bytes) {
10948                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10949                 }
10950                 return (DDI_NOT_WELL_FORMED);
10951         }
10952 
10953         ASSERT(bytes != NULL);
10954 
10955         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10956             LUN_PROP, 0xFFFF);
10957         if (lun_num == 0xFFFF) {
10958                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10959                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10960                     "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10961                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10962                     ddi_get_instance(tgt_dip));
10963 
10964                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10965                 return (DDI_NOT_WELL_FORMED);
10966         }
10967 
10968         mutex_enter(&pptr->port_mutex);
10969         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10970                 mutex_exit(&pptr->port_mutex);
10971                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10972                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10973                     "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10974                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10975                     ddi_get_instance(tgt_dip));
10976 
10977                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10978                 return (DDI_FAILURE);
10979         }
10980 
10981         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10982             FC_WWN_SIZE) == 0);
10983         ASSERT(plun->lun_num == lun_num);
10984 
10985         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10986 
10987         ptgt = plun->lun_tgt;
10988 
10989         mutex_enter(&ptgt->tgt_mutex);
10990         plun->lun_tgt_count++;
10991         scsi_device_hba_private_set(sd, plun);
10992         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10993         plun->lun_sd = sd;
10994         mutex_exit(&ptgt->tgt_mutex);
10995         mutex_exit(&pptr->port_mutex);
10996 
10997         return (DDI_SUCCESS);
10998 }
10999 
11000 
11001 /*
11002  * called by the transport to do our own target initialization
11003  *
11004  * can acquire and release the global mutex
11005  */
11006 /* ARGSUSED */
11007 static int
11008 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11009     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11010 {
11011         struct fcp_port *pptr = (struct fcp_port *)
11012             hba_tran->tran_hba_private;
11013         int                     rval;
11014 
11015         ASSERT(pptr != NULL);
11016 
11017         /*
11018          * Child node is getting initialized.  Look at the mpxio component
11019          * type on the child device to see if this device is mpxio managed
11020          * or not.
11021          */
11022         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11023                 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11024         } else {
11025                 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11026         }
11027 
11028         return (rval);
11029 }
11030 
11031 
11032 /* ARGSUSED */
11033 static void
11034 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11035     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11036 {
11037         struct fcp_lun  *plun = scsi_device_hba_private_get(sd);
11038         struct fcp_tgt  *ptgt;
11039 
11040         FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11041             fcp_trace, FCP_BUF_LEVEL_8, 0,
11042             "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11043             ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11044             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11045 
11046         if (plun == NULL) {
11047                 return;
11048         }
11049         ptgt = plun->lun_tgt;
11050 
11051         ASSERT(ptgt != NULL);
11052 
11053         mutex_enter(&ptgt->tgt_mutex);
11054         ASSERT(plun->lun_tgt_count > 0);
11055 
11056         if (--plun->lun_tgt_count == 0) {
11057                 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11058         }
11059         plun->lun_sd = NULL;
11060         mutex_exit(&ptgt->tgt_mutex);
11061 }
11062 
11063 /*
11064  *     Function: fcp_scsi_start
11065  *
11066  *  Description: This function is called by the target driver to request a
11067  *               command to be sent.
11068  *
11069  *     Argument: *ap            SCSI address of the device.
11070  *               *pkt           SCSI packet containing the cmd to send.
11071  *
11072  * Return Value: TRAN_ACCEPT
11073  *               TRAN_BUSY
11074  *               TRAN_BADPKT
11075  *               TRAN_FATAL_ERROR
11076  */
11077 static int
11078 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11079 {
11080         struct fcp_port *pptr = ADDR2FCP(ap);
11081         struct fcp_lun  *plun = ADDR2LUN(ap);
11082         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11083         struct fcp_tgt  *ptgt = plun->lun_tgt;
11084         int                     rval;
11085 
11086         /* ensure command isn't already issued */
11087         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11088 
11089         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11090             fcp_trace, FCP_BUF_LEVEL_9, 0,
11091             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11092 
11093         /*
11094          * It is strange that we enter the fcp_port mutex and the target
11095          * mutex to check the lun state (which has a mutex of its own).
11096          */
11097         mutex_enter(&pptr->port_mutex);
11098         mutex_enter(&ptgt->tgt_mutex);
11099 
11100         /*
11101          * If the device is offline and is not in the process of coming
11102          * online, fail the request.
11103          */
11104 
11105         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11106             !(plun->lun_state & FCP_LUN_ONLINING)) {
11107                 mutex_exit(&ptgt->tgt_mutex);
11108                 mutex_exit(&pptr->port_mutex);
11109 
11110                 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11111                         pkt->pkt_reason = CMD_DEV_GONE;
11112                 }
11113 
11114                 return (TRAN_FATAL_ERROR);
11115         }
11116         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11117 
11118         /*
11119          * If we are suspended, kernel is trying to dump, so don't
11120          * block, fail or defer requests - send them down right away.
11121          * NOTE: If we are in panic (i.e. trying to dump), we can't
11122          * assume we have been suspended.  There is hardware such as
11123          * the v880 that doesn't do PM.  Thus, the check for
11124          * ddi_in_panic.
11125          *
11126          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11127          * of changing.  So, if we can queue the packet, do it.  Eventually,
11128          * either the device will have gone away or changed and we can fail
11129          * the request, or we can proceed if the device didn't change.
11130          *
11131          * If the pd in the target or the packet is NULL it's probably
11132          * because the device has gone away, we allow the request to be
11133          * put on the internal queue here in case the device comes back within
11134          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11135          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11136          * could be NULL because the device was disappearing during or since
11137          * packet initialization.
11138          */
11139 
11140         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11141             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11142             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11143             (ptgt->tgt_pd_handle == NULL) ||
11144             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11145                 /*
11146                  * If ((LUN is busy AND
11147                  *      LUN not suspended AND
11148                  *      The system is not in panic state) OR
11149                  *      (The port is coming up))
11150                  *
11151                  * We check to see if the any of the flags FLAG_NOINTR or
11152                  * FLAG_NOQUEUE is set.  If one of them is set the value
11153                  * returned will be TRAN_BUSY.  If not, the request is queued.
11154                  */
11155                 mutex_exit(&ptgt->tgt_mutex);
11156                 mutex_exit(&pptr->port_mutex);
11157 
11158                 /* see if using interrupts is allowed (so queueing'll work) */
11159                 if (pkt->pkt_flags & FLAG_NOINTR) {
11160                         pkt->pkt_resid = 0;
11161                         return (TRAN_BUSY);
11162                 }
11163                 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11164                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11165                             fcp_trace, FCP_BUF_LEVEL_9, 0,
11166                             "fcp_scsi_start: lun busy for pkt %p", pkt);
11167                         return (TRAN_BUSY);
11168                 }
11169 #ifdef  DEBUG
11170                 mutex_enter(&pptr->port_pkt_mutex);
11171                 pptr->port_npkts++;
11172                 mutex_exit(&pptr->port_pkt_mutex);
11173 #endif /* DEBUG */
11174 
11175                 /* got queue up the pkt for later */
11176                 fcp_queue_pkt(pptr, cmd);
11177                 return (TRAN_ACCEPT);
11178         }
11179         cmd->cmd_state = FCP_PKT_ISSUED;
11180 
11181         mutex_exit(&ptgt->tgt_mutex);
11182         mutex_exit(&pptr->port_mutex);
11183 
11184         /*
11185          * Now that we released the mutexes, what was protected by them can
11186          * change.
11187          */
11188 
11189         /*
11190          * If there is a reconfiguration in progress, wait for it to complete.
11191          */
11192         fcp_reconfig_wait(pptr);
11193 
11194         cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11195             pkt->pkt_time : 0;
11196 
11197         /* prepare the packet */
11198 
11199         fcp_prepare_pkt(pptr, cmd, plun);
11200 
11201         if (cmd->cmd_pkt->pkt_time) {
11202                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11203         } else {
11204                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11205         }
11206 
11207         /*
11208          * if interrupts aren't allowed (e.g. at dump time) then we'll
11209          * have to do polled I/O
11210          */
11211         if (pkt->pkt_flags & FLAG_NOINTR) {
11212                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
11213                 return (fcp_dopoll(pptr, cmd));
11214         }
11215 
11216 #ifdef  DEBUG
11217         mutex_enter(&pptr->port_pkt_mutex);
11218         pptr->port_npkts++;
11219         mutex_exit(&pptr->port_pkt_mutex);
11220 #endif /* DEBUG */
11221 
11222         rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11223         if (rval == FC_SUCCESS) {
11224                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11225                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11226                     "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11227                 return (TRAN_ACCEPT);
11228         }
11229 
11230         cmd->cmd_state = FCP_PKT_IDLE;
11231 
11232 #ifdef  DEBUG
11233         mutex_enter(&pptr->port_pkt_mutex);
11234         pptr->port_npkts--;
11235         mutex_exit(&pptr->port_pkt_mutex);
11236 #endif /* DEBUG */
11237 
11238         /*
11239          * For lack of clearer definitions, choose
11240          * between TRAN_BUSY and TRAN_FATAL_ERROR.
11241          */
11242 
11243         if (rval == FC_TRAN_BUSY) {
11244                 pkt->pkt_resid = 0;
11245                 rval = TRAN_BUSY;
11246         } else {
11247                 mutex_enter(&ptgt->tgt_mutex);
11248                 if (plun->lun_state & FCP_LUN_OFFLINE) {
11249                         child_info_t    *cip;
11250 
11251                         mutex_enter(&plun->lun_mutex);
11252                         cip = plun->lun_cip;
11253                         mutex_exit(&plun->lun_mutex);
11254 
11255                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11256                             fcp_trace, FCP_BUF_LEVEL_6, 0,
11257                             "fcp_transport failed 2 for %x: %x; dip=%p",
11258                             plun->lun_tgt->tgt_d_id, rval, cip);
11259 
11260                         rval = TRAN_FATAL_ERROR;
11261                 } else {
11262                         if (pkt->pkt_flags & FLAG_NOQUEUE) {
11263                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11264                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11265                                     "fcp_scsi_start: FC_BUSY for pkt %p",
11266                                     pkt);
11267                                 rval = TRAN_BUSY;
11268                         } else {
11269                                 rval = TRAN_ACCEPT;
11270                                 fcp_queue_pkt(pptr, cmd);
11271                         }
11272                 }
11273                 mutex_exit(&ptgt->tgt_mutex);
11274         }
11275 
11276         return (rval);
11277 }
11278 
11279 /*
11280  * called by the transport to abort a packet
11281  */
11282 /*ARGSUSED*/
11283 static int
11284 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11285 {
11286         int tgt_cnt;
11287         struct fcp_port         *pptr = ADDR2FCP(ap);
11288         struct fcp_lun  *plun = ADDR2LUN(ap);
11289         struct fcp_tgt  *ptgt = plun->lun_tgt;
11290 
11291         if (pkt == NULL) {
11292                 if (ptgt) {
11293                         mutex_enter(&ptgt->tgt_mutex);
11294                         tgt_cnt = ptgt->tgt_change_cnt;
11295                         mutex_exit(&ptgt->tgt_mutex);
11296                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11297                         return (TRUE);
11298                 }
11299         }
11300         return (FALSE);
11301 }
11302 
11303 
11304 /*
11305  * Perform reset
11306  */
11307 int
11308 fcp_scsi_reset(struct scsi_address *ap, int level)
11309 {
11310         int                     rval = 0;
11311         struct fcp_port         *pptr = ADDR2FCP(ap);
11312         struct fcp_lun  *plun = ADDR2LUN(ap);
11313         struct fcp_tgt  *ptgt = plun->lun_tgt;
11314 
11315         if (level == RESET_ALL) {
11316                 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11317                         rval = 1;
11318                 }
11319         } else if (level == RESET_TARGET || level == RESET_LUN) {
11320                 /*
11321                  * If we are in the middle of discovery, return
11322                  * SUCCESS as this target will be rediscovered
11323                  * anyway
11324                  */
11325                 mutex_enter(&ptgt->tgt_mutex);
11326                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11327                         mutex_exit(&ptgt->tgt_mutex);
11328                         return (1);
11329                 }
11330                 mutex_exit(&ptgt->tgt_mutex);
11331 
11332                 if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11333                         rval = 1;
11334                 }
11335         }
11336         return (rval);
11337 }
11338 
11339 
11340 /*
11341  * called by the framework to get a SCSI capability
11342  */
11343 static int
11344 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11345 {
11346         return (fcp_commoncap(ap, cap, 0, whom, 0));
11347 }
11348 
11349 
11350 /*
11351  * called by the framework to set a SCSI capability
11352  */
11353 static int
11354 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11355 {
11356         return (fcp_commoncap(ap, cap, value, whom, 1));
11357 }
11358 
11359 /*
11360  *     Function: fcp_pkt_setup
11361  *
11362  *  Description: This function sets up the scsi_pkt structure passed by the
11363  *               caller. This function assumes fcp_pkt_constructor has been
11364  *               called previously for the packet passed by the caller.  If
11365  *               successful this call will have the following results:
11366  *
11367  *                 - The resources needed that will be constant through out
11368  *                   the whole transaction are allocated.
11369  *                 - The fields that will be constant through out the whole
11370  *                   transaction are initialized.
11371  *                 - The scsi packet will be linked to the LUN structure
11372  *                   addressed by the transaction.
11373  *
11374  *     Argument:
11375  *               *pkt           Pointer to a scsi_pkt structure.
11376  *               callback
11377  *               arg
11378  *
11379  * Return Value: 0      Success
11380  *               !0     Failure
11381  *
11382  *      Context: Kernel context or interrupt context
11383  */
11384 /* ARGSUSED */
11385 static int
11386 fcp_pkt_setup(struct scsi_pkt *pkt,
11387     int (*callback)(caddr_t arg),
11388     caddr_t arg)
11389 {
11390         struct fcp_pkt  *cmd;
11391         struct fcp_port *pptr;
11392         struct fcp_lun  *plun;
11393         struct fcp_tgt  *ptgt;
11394         int             kf;
11395         fc_packet_t     *fpkt;
11396         fc_frame_hdr_t  *hp;
11397 
11398         pptr = ADDR2FCP(&pkt->pkt_address);
11399         plun = ADDR2LUN(&pkt->pkt_address);
11400         ptgt = plun->lun_tgt;
11401 
11402         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11403         fpkt = cmd->cmd_fp_pkt;
11404 
11405         /*
11406          * this request is for dma allocation only
11407          */
11408         /*
11409          * First step of fcp_scsi_init_pkt: pkt allocation
11410          * We determine if the caller is willing to wait for the
11411          * resources.
11412          */
11413         kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11414 
11415         /*
11416          * Selective zeroing of the pkt.
11417          */
11418         cmd->cmd_back = NULL;
11419         cmd->cmd_next = NULL;
11420 
11421         /*
11422          * Zero out fcp command
11423          */
11424         bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11425 
11426         cmd->cmd_state = FCP_PKT_IDLE;
11427 
11428         fpkt = cmd->cmd_fp_pkt;
11429         fpkt->pkt_data_acc = NULL;
11430 
11431         /*
11432          * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11433          * could be destroyed.  We need fail pkt_setup.
11434          */
11435         if (pptr->port_state & FCP_STATE_OFFLINE) {
11436                 return (-1);
11437         }
11438 
11439         mutex_enter(&ptgt->tgt_mutex);
11440         fpkt->pkt_pd = ptgt->tgt_pd_handle;
11441 
11442         if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11443             != FC_SUCCESS) {
11444                 mutex_exit(&ptgt->tgt_mutex);
11445                 return (-1);
11446         }
11447 
11448         mutex_exit(&ptgt->tgt_mutex);
11449 
11450         /* Fill in the Fabric Channel Header */
11451         hp = &fpkt->pkt_cmd_fhdr;
11452         hp->r_ctl = R_CTL_COMMAND;
11453         hp->rsvd = 0;
11454         hp->type = FC_TYPE_SCSI_FCP;
11455         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11456         hp->seq_id = 0;
11457         hp->df_ctl  = 0;
11458         hp->seq_cnt = 0;
11459         hp->ox_id = 0xffff;
11460         hp->rx_id = 0xffff;
11461         hp->ro = 0;
11462 
11463         /*
11464          * A doubly linked list (cmd_forw, cmd_back) is built
11465          * out of every allocated packet on a per-lun basis
11466          *
11467          * The packets are maintained in the list so as to satisfy
11468          * scsi_abort() requests. At present (which is unlikely to
11469          * change in the future) nobody performs a real scsi_abort
11470          * in the SCSI target drivers (as they don't keep the packets
11471          * after doing scsi_transport - so they don't know how to
11472          * abort a packet other than sending a NULL to abort all
11473          * outstanding packets)
11474          */
11475         mutex_enter(&plun->lun_mutex);
11476         if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11477                 plun->lun_pkt_head->cmd_back = cmd;
11478         } else {
11479                 plun->lun_pkt_tail = cmd;
11480         }
11481         plun->lun_pkt_head = cmd;
11482         mutex_exit(&plun->lun_mutex);
11483         return (0);
11484 }
11485 
11486 /*
11487  *     Function: fcp_pkt_teardown
11488  *
11489  *  Description: This function releases a scsi_pkt structure and all the
11490  *               resources attached to it.
11491  *
11492  *     Argument: *pkt           Pointer to a scsi_pkt structure.
11493  *
11494  * Return Value: None
11495  *
11496  *      Context: User, Kernel or Interrupt context.
11497  */
11498 static void
11499 fcp_pkt_teardown(struct scsi_pkt *pkt)
11500 {
11501         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
11502         struct fcp_lun  *plun = ADDR2LUN(&pkt->pkt_address);
11503         struct fcp_pkt  *cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11504 
11505         /*
11506          * Remove the packet from the per-lun list
11507          */
11508         mutex_enter(&plun->lun_mutex);
11509         if (cmd->cmd_back) {
11510                 ASSERT(cmd != plun->lun_pkt_head);
11511                 cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11512         } else {
11513                 ASSERT(cmd == plun->lun_pkt_head);
11514                 plun->lun_pkt_head = cmd->cmd_forw;
11515         }
11516 
11517         if (cmd->cmd_forw) {
11518                 cmd->cmd_forw->cmd_back = cmd->cmd_back;
11519         } else {
11520                 ASSERT(cmd == plun->lun_pkt_tail);
11521                 plun->lun_pkt_tail = cmd->cmd_back;
11522         }
11523 
11524         mutex_exit(&plun->lun_mutex);
11525 
11526         (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11527 }
11528 
11529 /*
11530  * Routine for reset notification setup, to register or cancel.
11531  * This function is called by SCSA
11532  */
11533 /*ARGSUSED*/
11534 static int
11535 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11536     void (*callback)(caddr_t), caddr_t arg)
11537 {
11538         struct fcp_port *pptr = ADDR2FCP(ap);
11539 
11540         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11541             &pptr->port_mutex, &pptr->port_reset_notify_listf));
11542 }
11543 
11544 
11545 static int
11546 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11547     ddi_eventcookie_t *event_cookiep)
11548 {
11549         struct fcp_port *pptr = fcp_dip2port(dip);
11550 
11551         if (pptr == NULL) {
11552                 return (DDI_FAILURE);
11553         }
11554 
11555         return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11556             event_cookiep, NDI_EVENT_NOPASS));
11557 }
11558 
11559 
11560 static int
11561 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11562     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11563     ddi_callback_id_t *cb_id)
11564 {
11565         struct fcp_port *pptr = fcp_dip2port(dip);
11566 
11567         if (pptr == NULL) {
11568                 return (DDI_FAILURE);
11569         }
11570 
11571         return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11572             eventid, callback, arg, NDI_SLEEP, cb_id));
11573 }
11574 
11575 
11576 static int
11577 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11578 {
11579 
11580         struct fcp_port *pptr = fcp_dip2port(dip);
11581 
11582         if (pptr == NULL) {
11583                 return (DDI_FAILURE);
11584         }
11585         return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11586 }
11587 
11588 
11589 /*
11590  * called by the transport to post an event
11591  */
11592 static int
11593 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11594     ddi_eventcookie_t eventid, void *impldata)
11595 {
11596         struct fcp_port *pptr = fcp_dip2port(dip);
11597 
11598         if (pptr == NULL) {
11599                 return (DDI_FAILURE);
11600         }
11601 
11602         return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11603             eventid, impldata));
11604 }
11605 
11606 
11607 /*
11608  * A target in in many cases in Fibre Channel has a one to one relation
11609  * with a port identifier (which is also known as D_ID and also as AL_PA
11610  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11611  * will most likely result in resetting all LUNs (which means a reset will
11612  * occur on all the SCSI devices connected at the other end of the bridge)
11613  * That is the latest favorite topic for discussion, for, one can debate as
11614  * hot as one likes and come up with arguably a best solution to one's
11615  * satisfaction
11616  *
11617  * To stay on track and not digress much, here are the problems stated
11618  * briefly:
11619  *
11620  *      SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11621  *      target drivers use RESET_TARGET even if their instance is on a
11622  *      LUN. Doesn't that sound a bit broken ?
11623  *
11624  *      FCP SCSI (the current spec) only defines RESET TARGET in the
11625  *      control fields of an FCP_CMND structure. It should have been
11626  *      fixed right there, giving flexibility to the initiators to
11627  *      minimize havoc that could be caused by resetting a target.
11628  */
11629 static int
11630 fcp_reset_target(struct scsi_address *ap, int level)
11631 {
11632         int                     rval = FC_FAILURE;
11633         char                    lun_id[25];
11634         struct fcp_port         *pptr = ADDR2FCP(ap);
11635         struct fcp_lun  *plun = ADDR2LUN(ap);
11636         struct fcp_tgt  *ptgt = plun->lun_tgt;
11637         struct scsi_pkt         *pkt;
11638         struct fcp_pkt  *cmd;
11639         struct fcp_rsp          *rsp;
11640         uint32_t                tgt_cnt;
11641         struct fcp_rsp_info     *rsp_info;
11642         struct fcp_reset_elem   *p;
11643         int                     bval;
11644 
11645         if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11646             KM_NOSLEEP)) == NULL) {
11647                 return (rval);
11648         }
11649 
11650         mutex_enter(&ptgt->tgt_mutex);
11651         if (level == RESET_TARGET) {
11652                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11653                         mutex_exit(&ptgt->tgt_mutex);
11654                         kmem_free(p, sizeof (struct fcp_reset_elem));
11655                         return (rval);
11656                 }
11657                 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11658                 (void) strcpy(lun_id, " ");
11659         } else {
11660                 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11661                         mutex_exit(&ptgt->tgt_mutex);
11662                         kmem_free(p, sizeof (struct fcp_reset_elem));
11663                         return (rval);
11664                 }
11665                 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11666 
11667                 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11668         }
11669         tgt_cnt = ptgt->tgt_change_cnt;
11670 
11671         mutex_exit(&ptgt->tgt_mutex);
11672 
11673         if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11674             0, 0, NULL, 0)) == NULL) {
11675                 kmem_free(p, sizeof (struct fcp_reset_elem));
11676                 mutex_enter(&ptgt->tgt_mutex);
11677                 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11678                 mutex_exit(&ptgt->tgt_mutex);
11679                 return (rval);
11680         }
11681         pkt->pkt_time = FCP_POLL_TIMEOUT;
11682 
11683         /* fill in cmd part of packet */
11684         cmd = PKT2CMD(pkt);
11685         if (level == RESET_TARGET) {
11686                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11687         } else {
11688                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11689         }
11690         cmd->cmd_fp_pkt->pkt_comp = NULL;
11691         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11692 
11693         /* prepare a packet for transport */
11694         fcp_prepare_pkt(pptr, cmd, plun);
11695 
11696         if (cmd->cmd_pkt->pkt_time) {
11697                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11698         } else {
11699                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11700         }
11701 
11702         (void) fc_ulp_busy_port(pptr->port_fp_handle);
11703         bval = fcp_dopoll(pptr, cmd);
11704         fc_ulp_idle_port(pptr->port_fp_handle);
11705 
11706         /* submit the packet */
11707         if (bval == TRAN_ACCEPT) {
11708                 int error = 3;
11709 
11710                 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11711                 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11712                     sizeof (struct fcp_rsp));
11713 
11714                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
11715                         if (fcp_validate_fcp_response(rsp, pptr) ==
11716                             FC_SUCCESS) {
11717                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11718                                         FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11719                                             sizeof (struct fcp_rsp), rsp_info,
11720                                             cmd->cmd_fp_pkt->pkt_resp_acc,
11721                                             sizeof (struct fcp_rsp_info));
11722                                 }
11723                                 if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11724                                         rval = FC_SUCCESS;
11725                                         error = 0;
11726                                 } else {
11727                                         error = 1;
11728                                 }
11729                         } else {
11730                                 error = 2;
11731                         }
11732                 }
11733 
11734                 switch (error) {
11735                 case 0:
11736                         fcp_log(CE_WARN, pptr->port_dip,
11737                             "!FCP: WWN 0x%08x%08x %s reset successfully",
11738                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11739                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11740                         break;
11741 
11742                 case 1:
11743                         fcp_log(CE_WARN, pptr->port_dip,
11744                             "!FCP: Reset to WWN  0x%08x%08x %s failed,"
11745                             " response code=%x",
11746                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11747                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11748                             rsp_info->rsp_code);
11749                         break;
11750 
11751                 case 2:
11752                         fcp_log(CE_WARN, pptr->port_dip,
11753                             "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11754                             " Bad FCP response values: rsvd1=%x,"
11755                             " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11756                             " rsplen=%x, senselen=%x",
11757                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11758                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11759                             rsp->reserved_0, rsp->reserved_1,
11760                             rsp->fcp_u.fcp_status.reserved_0,
11761                             rsp->fcp_u.fcp_status.reserved_1,
11762                             rsp->fcp_response_len, rsp->fcp_sense_len);
11763                         break;
11764 
11765                 default:
11766                         fcp_log(CE_WARN, pptr->port_dip,
11767                             "!FCP: Reset to WWN  0x%08x%08x %s failed",
11768                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11769                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11770                         break;
11771                 }
11772         }
11773         scsi_destroy_pkt(pkt);
11774 
11775         if (rval == FC_FAILURE) {
11776                 mutex_enter(&ptgt->tgt_mutex);
11777                 if (level == RESET_TARGET) {
11778                         fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11779                 } else {
11780                         fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11781                 }
11782                 mutex_exit(&ptgt->tgt_mutex);
11783                 kmem_free(p, sizeof (struct fcp_reset_elem));
11784                 return (rval);
11785         }
11786 
11787         mutex_enter(&pptr->port_mutex);
11788         if (level == RESET_TARGET) {
11789                 p->tgt = ptgt;
11790                 p->lun = NULL;
11791         } else {
11792                 p->tgt = NULL;
11793                 p->lun = plun;
11794         }
11795         p->tgt = ptgt;
11796         p->tgt_cnt = tgt_cnt;
11797         p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11798         p->next = pptr->port_reset_list;
11799         pptr->port_reset_list = p;
11800 
11801         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11802             fcp_trace, FCP_BUF_LEVEL_3, 0,
11803             "Notify ssd of the reset to reinstate the reservations");
11804 
11805         scsi_hba_reset_notify_callback(&pptr->port_mutex,
11806             &pptr->port_reset_notify_listf);
11807 
11808         mutex_exit(&pptr->port_mutex);
11809 
11810         return (rval);
11811 }
11812 
11813 
11814 /*
11815  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11816  * SCSI capabilities
11817  */
11818 /* ARGSUSED */
11819 static int
11820 fcp_commoncap(struct scsi_address *ap, char *cap,
11821     int val, int tgtonly, int doset)
11822 {
11823         struct fcp_port         *pptr = ADDR2FCP(ap);
11824         struct fcp_lun  *plun = ADDR2LUN(ap);
11825         struct fcp_tgt  *ptgt = plun->lun_tgt;
11826         int                     cidx;
11827         int                     rval = FALSE;
11828 
11829         if (cap == (char *)0) {
11830                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11831                     fcp_trace, FCP_BUF_LEVEL_3, 0,
11832                     "fcp_commoncap: invalid arg");
11833                 return (rval);
11834         }
11835 
11836         if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11837                 return (UNDEFINED);
11838         }
11839 
11840         /*
11841          * Process setcap request.
11842          */
11843         if (doset) {
11844                 /*
11845                  * At present, we can only set binary (0/1) values
11846                  */
11847                 switch (cidx) {
11848                 case SCSI_CAP_ARQ:
11849                         if (val == 0) {
11850                                 rval = FALSE;
11851                         } else {
11852                                 rval = TRUE;
11853                         }
11854                         break;
11855 
11856                 case SCSI_CAP_LUN_RESET:
11857                         if (val) {
11858                                 plun->lun_cap |= FCP_LUN_CAP_RESET;
11859                         } else {
11860                                 plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11861                         }
11862                         rval = TRUE;
11863                         break;
11864 
11865                 case SCSI_CAP_SECTOR_SIZE:
11866                         rval = TRUE;
11867                         break;
11868                 default:
11869                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11870                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11871                             "fcp_setcap: unsupported %d", cidx);
11872                         rval = UNDEFINED;
11873                         break;
11874                 }
11875 
11876                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11877                     fcp_trace, FCP_BUF_LEVEL_5, 0,
11878                     "set cap: cap=%s, val/tgtonly/doset/rval = "
11879                     "0x%x/0x%x/0x%x/%d",
11880                     cap, val, tgtonly, doset, rval);
11881 
11882         } else {
11883                 /*
11884                  * Process getcap request.
11885                  */
11886                 switch (cidx) {
11887                 case SCSI_CAP_DMA_MAX:
11888                         rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11889 
11890                         /*
11891                          * Need to make an adjustment qlc is uint_t 64
11892                          * st is int, so we will make the adjustment here
11893                          * being as nobody wants to touch this.
11894                          * It still leaves the max single block length
11895                          * of 2 gig. This should last .
11896                          */
11897 
11898                         if (rval == -1) {
11899                                 rval = MAX_INT_DMA;
11900                         }
11901 
11902                         break;
11903 
11904                 case SCSI_CAP_INITIATOR_ID:
11905                         rval = pptr->port_id;
11906                         break;
11907 
11908                 case SCSI_CAP_ARQ:
11909                 case SCSI_CAP_RESET_NOTIFICATION:
11910                 case SCSI_CAP_TAGGED_QING:
11911                         rval = TRUE;
11912                         break;
11913 
11914                 case SCSI_CAP_SCSI_VERSION:
11915                         rval = 3;
11916                         break;
11917 
11918                 case SCSI_CAP_INTERCONNECT_TYPE:
11919                         if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11920                             (ptgt->tgt_hard_addr == 0)) {
11921                                 rval = INTERCONNECT_FABRIC;
11922                         } else {
11923                                 rval = INTERCONNECT_FIBRE;
11924                         }
11925                         break;
11926 
11927                 case SCSI_CAP_LUN_RESET:
11928                         rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11929                             TRUE : FALSE;
11930                         break;
11931 
11932                 default:
11933                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11934                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11935                             "fcp_getcap: unsupported %d", cidx);
11936                         rval = UNDEFINED;
11937                         break;
11938                 }
11939 
11940                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11941                     fcp_trace, FCP_BUF_LEVEL_8, 0,
11942                     "get cap: cap=%s, val/tgtonly/doset/rval = "
11943                     "0x%x/0x%x/0x%x/%d",
11944                     cap, val, tgtonly, doset, rval);
11945         }
11946 
11947         return (rval);
11948 }
11949 
11950 /*
11951  * called by the transport to get the port-wwn and lun
11952  * properties of this device, and to create a "name" based on them
11953  *
11954  * these properties don't exist on sun4m
11955  *
11956  * return 1 for success else return 0
11957  */
11958 /* ARGSUSED */
11959 static int
11960 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11961 {
11962         int                     i;
11963         int                     *lun;
11964         int                     numChars;
11965         uint_t                  nlun;
11966         uint_t                  count;
11967         uint_t                  nbytes;
11968         uchar_t                 *bytes;
11969         uint16_t                lun_num;
11970         uint32_t                tgt_id;
11971         char                    **conf_wwn;
11972         char                    tbuf[(FC_WWN_SIZE << 1) + 1];
11973         uchar_t                 barray[FC_WWN_SIZE];
11974         dev_info_t              *tgt_dip;
11975         struct fcp_tgt  *ptgt;
11976         struct fcp_port *pptr;
11977         struct fcp_lun  *plun;
11978 
11979         ASSERT(sd != NULL);
11980         ASSERT(name != NULL);
11981 
11982         tgt_dip = sd->sd_dev;
11983         pptr = ddi_get_soft_state(fcp_softstate,
11984             ddi_get_instance(ddi_get_parent(tgt_dip)));
11985         if (pptr == NULL) {
11986                 return (0);
11987         }
11988 
11989         ASSERT(tgt_dip != NULL);
11990 
11991         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11992             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11993             LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11994                 name[0] = '\0';
11995                 return (0);
11996         }
11997 
11998         if (nlun == 0) {
11999                 ddi_prop_free(lun);
12000                 return (0);
12001         }
12002 
12003         lun_num = lun[0];
12004         ddi_prop_free(lun);
12005 
12006         /*
12007          * Lookup for .conf WWN property
12008          */
12009         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12010             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12011             &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12012                 ASSERT(count >= 1);
12013 
12014                 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12015                 ddi_prop_free(conf_wwn);
12016                 mutex_enter(&pptr->port_mutex);
12017                 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12018                         mutex_exit(&pptr->port_mutex);
12019                         return (0);
12020                 }
12021                 ptgt = plun->lun_tgt;
12022                 mutex_exit(&pptr->port_mutex);
12023 
12024                 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12025                     tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12026 
12027                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12028                     ptgt->tgt_hard_addr != 0) {
12029                         tgt_id = (uint32_t)fcp_alpa_to_switch[
12030                             ptgt->tgt_hard_addr];
12031                 } else {
12032                         tgt_id = ptgt->tgt_d_id;
12033                 }
12034 
12035                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12036                     TARGET_PROP, tgt_id);
12037         }
12038 
12039         /* get the our port-wwn property */
12040         bytes = NULL;
12041         if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12042             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12043             &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12044                 if (bytes != NULL) {
12045                         ddi_prop_free(bytes);
12046                 }
12047                 return (0);
12048         }
12049 
12050         for (i = 0; i < FC_WWN_SIZE; i++) {
12051                 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12052         }
12053 
12054         /* Stick in the address of the form "wWWN,LUN" */
12055         numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12056 
12057         ASSERT(numChars < len);
12058         if (numChars >= len) {
12059                 fcp_log(CE_WARN, pptr->port_dip,
12060                     "!fcp_scsi_get_name: "
12061                     "name parameter length too small, it needs to be %d",
12062                     numChars+1);
12063         }
12064 
12065         ddi_prop_free(bytes);
12066 
12067         return (1);
12068 }
12069 
12070 
12071 /*
12072  * called by the transport to get the SCSI target id value, returning
12073  * it in "name"
12074  *
12075  * this isn't needed/used on sun4m
12076  *
12077  * return 1 for success else return 0
12078  */
12079 /* ARGSUSED */
12080 static int
12081 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12082 {
12083         struct fcp_lun  *plun = ADDR2LUN(&sd->sd_address);
12084         struct fcp_tgt  *ptgt;
12085         int    numChars;
12086 
12087         if (plun == NULL) {
12088                 return (0);
12089         }
12090 
12091         if ((ptgt = plun->lun_tgt) == NULL) {
12092                 return (0);
12093         }
12094 
12095         numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12096 
12097         ASSERT(numChars < len);
12098         if (numChars >= len) {
12099                 fcp_log(CE_WARN, NULL,
12100                     "!fcp_scsi_get_bus_addr: "
12101                     "name parameter length too small, it needs to be %d",
12102                     numChars+1);
12103         }
12104 
12105         return (1);
12106 }
12107 
12108 
12109 /*
12110  * called internally to reset the link where the specified port lives
12111  */
12112 static int
12113 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12114 {
12115         la_wwn_t                wwn;
12116         struct fcp_lun  *plun;
12117         struct fcp_tgt  *ptgt;
12118 
12119         /* disable restart of lip if we're suspended */
12120         mutex_enter(&pptr->port_mutex);
12121 
12122         if (pptr->port_state & (FCP_STATE_SUSPENDED |
12123             FCP_STATE_POWER_DOWN)) {
12124                 mutex_exit(&pptr->port_mutex);
12125                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12126                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12127                     "fcp_linkreset, fcp%d: link reset "
12128                     "disabled due to DDI_SUSPEND",
12129                     ddi_get_instance(pptr->port_dip));
12130                 return (FC_FAILURE);
12131         }
12132 
12133         if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12134                 mutex_exit(&pptr->port_mutex);
12135                 return (FC_SUCCESS);
12136         }
12137 
12138         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12139             fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12140 
12141         /*
12142          * If ap == NULL assume local link reset.
12143          */
12144         if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12145                 plun = ADDR2LUN(ap);
12146                 ptgt = plun->lun_tgt;
12147                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12148         } else {
12149                 bzero((caddr_t)&wwn, sizeof (wwn));
12150         }
12151         mutex_exit(&pptr->port_mutex);
12152 
12153         return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12154 }
12155 
12156 
12157 /*
12158  * called from fcp_port_attach() to resume a port
12159  * return DDI_* success/failure status
12160  * acquires and releases the global mutex
12161  * acquires and releases the port mutex
12162  */
12163 /*ARGSUSED*/
12164 
12165 static int
12166 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12167     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12168 {
12169         int                     res = DDI_FAILURE; /* default result */
12170         struct fcp_port *pptr;          /* port state ptr */
12171         uint32_t                alloc_cnt;
12172         uint32_t                max_cnt;
12173         fc_portmap_t            *tmp_list = NULL;
12174 
12175         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12176             FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12177             instance);
12178 
12179         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12180                 cmn_err(CE_WARN, "fcp: bad soft state");
12181                 return (res);
12182         }
12183 
12184         mutex_enter(&pptr->port_mutex);
12185         switch (cmd) {
12186         case FC_CMD_RESUME:
12187                 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12188                 pptr->port_state &= ~FCP_STATE_SUSPENDED;
12189                 break;
12190 
12191         case FC_CMD_POWER_UP:
12192                 /*
12193                  * If the port is DDI_SUSPENded, defer rediscovery
12194                  * until DDI_RESUME occurs
12195                  */
12196                 if (pptr->port_state & FCP_STATE_SUSPENDED) {
12197                         pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12198                         mutex_exit(&pptr->port_mutex);
12199                         return (DDI_SUCCESS);
12200                 }
12201                 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12202         }
12203         pptr->port_id = s_id;
12204         pptr->port_state = FCP_STATE_INIT;
12205         mutex_exit(&pptr->port_mutex);
12206 
12207         /*
12208          * Make a copy of ulp_port_info as fctl allocates
12209          * a temp struct.
12210          */
12211         (void) fcp_cp_pinfo(pptr, pinfo);
12212 
12213         mutex_enter(&fcp_global_mutex);
12214         if (fcp_watchdog_init++ == 0) {
12215                 fcp_watchdog_tick = fcp_watchdog_timeout *
12216                     drv_usectohz(1000000);
12217                 fcp_watchdog_id = timeout(fcp_watch,
12218                     NULL, fcp_watchdog_tick);
12219         }
12220         mutex_exit(&fcp_global_mutex);
12221 
12222         /*
12223          * Handle various topologies and link states.
12224          */
12225         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12226         case FC_STATE_OFFLINE:
12227                 /*
12228                  * Wait for ONLINE, at which time a state
12229                  * change will cause a statec_callback
12230                  */
12231                 res = DDI_SUCCESS;
12232                 break;
12233 
12234         case FC_STATE_ONLINE:
12235 
12236                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
12237                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12238                         res = DDI_SUCCESS;
12239                         break;
12240                 }
12241 
12242                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12243                     !fcp_enable_auto_configuration) {
12244                         tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12245                         if (tmp_list == NULL) {
12246                                 if (!alloc_cnt) {
12247                                         res = DDI_SUCCESS;
12248                                 }
12249                                 break;
12250                         }
12251                         max_cnt = alloc_cnt;
12252                 } else {
12253                         ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12254 
12255                         alloc_cnt = FCP_MAX_DEVICES;
12256 
12257                         if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12258                             (sizeof (fc_portmap_t)) * alloc_cnt,
12259                             KM_NOSLEEP)) == NULL) {
12260                                 fcp_log(CE_WARN, pptr->port_dip,
12261                                     "!fcp%d: failed to allocate portmap",
12262                                     instance);
12263                                 break;
12264                         }
12265 
12266                         max_cnt = alloc_cnt;
12267                         if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12268                             &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12269                             FC_SUCCESS) {
12270                                 caddr_t msg;
12271 
12272                                 (void) fc_ulp_error(res, &msg);
12273 
12274                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12275                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12276                                     "resume failed getportmap: reason=0x%x",
12277                                     res);
12278 
12279                                 fcp_log(CE_WARN, pptr->port_dip,
12280                                     "!failed to get port map : %s", msg);
12281                                 break;
12282                         }
12283                         if (max_cnt > alloc_cnt) {
12284                                 alloc_cnt = max_cnt;
12285                         }
12286                 }
12287 
12288                 /*
12289                  * do the SCSI device discovery and create
12290                  * the devinfos
12291                  */
12292                 fcp_statec_callback(ulph, pptr->port_fp_handle,
12293                     pptr->port_phys_state, pptr->port_topology, tmp_list,
12294                     max_cnt, pptr->port_id);
12295 
12296                 res = DDI_SUCCESS;
12297                 break;
12298 
12299         default:
12300                 fcp_log(CE_WARN, pptr->port_dip,
12301                     "!fcp%d: invalid port state at attach=0x%x",
12302                     instance, pptr->port_phys_state);
12303 
12304                 mutex_enter(&pptr->port_mutex);
12305                 pptr->port_phys_state = FCP_STATE_OFFLINE;
12306                 mutex_exit(&pptr->port_mutex);
12307                 res = DDI_SUCCESS;
12308 
12309                 break;
12310         }
12311 
12312         if (tmp_list != NULL) {
12313                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12314         }
12315 
12316         return (res);
12317 }
12318 
12319 
12320 static void
12321 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12322 {
12323         pptr->port_fp_modlinkage = *pinfo->port_linkage;
12324         pptr->port_dip = pinfo->port_dip;
12325         pptr->port_fp_handle = pinfo->port_handle;
12326         if (pinfo->port_acc_attr != NULL) {
12327                 /*
12328                  * FCA supports DMA
12329                  */
12330                 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12331                 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12332                 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12333                 pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12334         }
12335         pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12336         pptr->port_max_exch = pinfo->port_fca_max_exch;
12337         pptr->port_phys_state = pinfo->port_state;
12338         pptr->port_topology = pinfo->port_flags;
12339         pptr->port_reset_action = pinfo->port_reset_action;
12340         pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12341         pptr->port_fcp_dma = pinfo->port_fcp_dma;
12342         bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12343         bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12344 
12345         /* Clear FMA caps to avoid fm-capability ereport */
12346         if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12347                 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12348         if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12349                 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12350         if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12351                 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12352 }
12353 
12354 /*
12355  * If the elements wait field is set to 1 then
12356  * another thread is waiting for the operation to complete. Once
12357  * it is complete, the waiting thread is signaled and the element is
12358  * freed by the waiting thread. If the elements wait field is set to 0
12359  * the element is freed.
12360  */
12361 static void
12362 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12363 {
12364         ASSERT(elem != NULL);
12365         mutex_enter(&elem->mutex);
12366         elem->result = result;
12367         if (elem->wait) {
12368                 elem->wait = 0;
12369                 cv_signal(&elem->cv);
12370                 mutex_exit(&elem->mutex);
12371         } else {
12372                 mutex_exit(&elem->mutex);
12373                 cv_destroy(&elem->cv);
12374                 mutex_destroy(&elem->mutex);
12375                 kmem_free(elem, sizeof (struct fcp_hp_elem));
12376         }
12377 }
12378 
12379 /*
12380  * This function is invoked from the taskq thread to allocate
12381  * devinfo nodes and to online/offline them.
12382  */
12383 static void
12384 fcp_hp_task(void *arg)
12385 {
12386         struct fcp_hp_elem      *elem = (struct fcp_hp_elem *)arg;
12387         struct fcp_lun  *plun = elem->lun;
12388         struct fcp_port         *pptr = elem->port;
12389         int                     result;
12390 
12391         ASSERT(elem->what == FCP_ONLINE ||
12392             elem->what == FCP_OFFLINE ||
12393             elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12394             elem->what == FCP_MPXIO_PATH_SET_BUSY);
12395 
12396         mutex_enter(&pptr->port_mutex);
12397         mutex_enter(&plun->lun_mutex);
12398         if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12399             plun->lun_event_count != elem->event_cnt) ||
12400             pptr->port_state & (FCP_STATE_SUSPENDED |
12401             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12402                 mutex_exit(&plun->lun_mutex);
12403                 mutex_exit(&pptr->port_mutex);
12404                 fcp_process_elem(elem, NDI_FAILURE);
12405                 return;
12406         }
12407         mutex_exit(&plun->lun_mutex);
12408         mutex_exit(&pptr->port_mutex);
12409 
12410         result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12411             elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12412         fcp_process_elem(elem, result);
12413 }
12414 
12415 
12416 static child_info_t *
12417 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12418     int tcount)
12419 {
12420         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12421 
12422         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12423                 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12424 
12425                 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12426                 /*
12427                  * Child has not been created yet. Create the child device
12428                  * based on the per-Lun flags.
12429                  */
12430                 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12431                         plun->lun_cip =
12432                             CIP(fcp_create_dip(plun, lcount, tcount));
12433                         plun->lun_mpxio = 0;
12434                 } else {
12435                         plun->lun_cip =
12436                             CIP(fcp_create_pip(plun, lcount, tcount));
12437                         plun->lun_mpxio = 1;
12438                 }
12439         } else {
12440                 plun->lun_cip = cip;
12441         }
12442 
12443         return (plun->lun_cip);
12444 }
12445 
12446 
12447 static int
12448 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12449 {
12450         int             rval = FC_FAILURE;
12451         dev_info_t      *pdip;
12452         struct dev_info *dip;
12453         int             circular;
12454 
12455         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12456 
12457         pdip = plun->lun_tgt->tgt_port->port_dip;
12458 
12459         if (plun->lun_cip == NULL) {
12460                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12461                     fcp_trace, FCP_BUF_LEVEL_3, 0,
12462                     "fcp_is_dip_present: plun->lun_cip is NULL: "
12463                     "plun: %p lun state: %x num: %d target state: %x",
12464                     plun, plun->lun_state, plun->lun_num,
12465                     plun->lun_tgt->tgt_port->port_state);
12466                 return (rval);
12467         }
12468         ndi_devi_enter(pdip, &circular);
12469         dip = DEVI(pdip)->devi_child;
12470         while (dip) {
12471                 if (dip == DEVI(cdip)) {
12472                         rval = FC_SUCCESS;
12473                         break;
12474                 }
12475                 dip = dip->devi_sibling;
12476         }
12477         ndi_devi_exit(pdip, circular);
12478         return (rval);
12479 }
12480 
12481 static int
12482 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12483 {
12484         int             rval = FC_FAILURE;
12485 
12486         ASSERT(plun != NULL);
12487         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12488 
12489         if (plun->lun_mpxio == 0) {
12490                 rval = fcp_is_dip_present(plun, DIP(cip));
12491         } else {
12492                 rval = fcp_is_pip_present(plun, PIP(cip));
12493         }
12494 
12495         return (rval);
12496 }
12497 
12498 /*
12499  *     Function: fcp_create_dip
12500  *
12501  *  Description: Creates a dev_info_t structure for the LUN specified by the
12502  *               caller.
12503  *
12504  *     Argument: plun           Lun structure
12505  *               link_cnt       Link state count.
12506  *               tgt_cnt        Target state change count.
12507  *
12508  * Return Value: NULL if it failed
12509  *               dev_info_t structure address if it succeeded
12510  *
12511  *      Context: Kernel context
12512  */
12513 static dev_info_t *
12514 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12515 {
12516         int                     failure = 0;
12517         uint32_t                tgt_id;
12518         uint64_t                sam_lun;
12519         struct fcp_tgt  *ptgt = plun->lun_tgt;
12520         struct fcp_port *pptr = ptgt->tgt_port;
12521         dev_info_t              *pdip = pptr->port_dip;
12522         dev_info_t              *cdip = NULL;
12523         dev_info_t              *old_dip = DIP(plun->lun_cip);
12524         char                    *nname = NULL;
12525         char                    **compatible = NULL;
12526         int                     ncompatible;
12527         char                    *scsi_binding_set;
12528         char                    t_pwwn[17];
12529 
12530         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12531         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12532 
12533         /* get the 'scsi-binding-set' property */
12534         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12535             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12536             &scsi_binding_set) != DDI_PROP_SUCCESS) {
12537                 scsi_binding_set = NULL;
12538         }
12539 
12540         /* determine the node name and compatible */
12541         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12542             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12543         if (scsi_binding_set) {
12544                 ddi_prop_free(scsi_binding_set);
12545         }
12546 
12547         if (nname == NULL) {
12548 #ifdef  DEBUG
12549                 cmn_err(CE_WARN, "%s%d: no driver for "
12550                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12551                     "    compatible: %s",
12552                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12553                     ptgt->tgt_port_wwn.raw_wwn[0],
12554                     ptgt->tgt_port_wwn.raw_wwn[1],
12555                     ptgt->tgt_port_wwn.raw_wwn[2],
12556                     ptgt->tgt_port_wwn.raw_wwn[3],
12557                     ptgt->tgt_port_wwn.raw_wwn[4],
12558                     ptgt->tgt_port_wwn.raw_wwn[5],
12559                     ptgt->tgt_port_wwn.raw_wwn[6],
12560                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12561                     *compatible);
12562 #endif  /* DEBUG */
12563                 failure++;
12564                 goto end_of_fcp_create_dip;
12565         }
12566 
12567         cdip = fcp_find_existing_dip(plun, pdip, nname);
12568 
12569         /*
12570          * if the old_dip does not match the cdip, that means there is
12571          * some property change. since we'll be using the cdip, we need
12572          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12573          * then the dtype for the device has been updated. Offline the
12574          * the old device and create a new device with the new device type
12575          * Refer to bug: 4764752
12576          */
12577         if (old_dip && (cdip != old_dip ||
12578             plun->lun_state & FCP_LUN_CHANGED)) {
12579                 plun->lun_state &= ~(FCP_LUN_INIT);
12580                 mutex_exit(&plun->lun_mutex);
12581                 mutex_exit(&pptr->port_mutex);
12582 
12583                 mutex_enter(&ptgt->tgt_mutex);
12584                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12585                     link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12586                 mutex_exit(&ptgt->tgt_mutex);
12587 
12588 #ifdef DEBUG
12589                 if (cdip != NULL) {
12590                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12591                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12592                             "Old dip=%p; New dip=%p don't match", old_dip,
12593                             cdip);
12594                 } else {
12595                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12596                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12597                             "Old dip=%p; New dip=NULL don't match", old_dip);
12598                 }
12599 #endif
12600 
12601                 mutex_enter(&pptr->port_mutex);
12602                 mutex_enter(&plun->lun_mutex);
12603         }
12604 
12605         if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12606                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12607                 if (ndi_devi_alloc(pptr->port_dip, nname,
12608                     DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12609                         failure++;
12610                         goto end_of_fcp_create_dip;
12611                 }
12612         }
12613 
12614         /*
12615          * Previously all the properties for the devinfo were destroyed here
12616          * with a call to ndi_prop_remove_all(). Since this may cause loss of
12617          * the devid property (and other properties established by the target
12618          * driver or framework) which the code does not always recreate, this
12619          * call was removed.
12620          * This opens a theoretical possibility that we may return with a
12621          * stale devid on the node if the scsi entity behind the fibre channel
12622          * lun has changed.
12623          */
12624 
12625         /* decorate the node with compatible */
12626         if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12627             "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12628                 failure++;
12629                 goto end_of_fcp_create_dip;
12630         }
12631 
12632         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12633             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12634                 failure++;
12635                 goto end_of_fcp_create_dip;
12636         }
12637 
12638         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12639             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12640                 failure++;
12641                 goto end_of_fcp_create_dip;
12642         }
12643 
12644         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12645         t_pwwn[16] = '\0';
12646         if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12647             != DDI_PROP_SUCCESS) {
12648                 failure++;
12649                 goto end_of_fcp_create_dip;
12650         }
12651 
12652         /*
12653          * If there is no hard address - We might have to deal with
12654          * that by using WWN - Having said that it is important to
12655          * recognize this problem early so ssd can be informed of
12656          * the right interconnect type.
12657          */
12658         if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12659                 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12660         } else {
12661                 tgt_id = ptgt->tgt_d_id;
12662         }
12663 
12664         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12665             tgt_id) != DDI_PROP_SUCCESS) {
12666                 failure++;
12667                 goto end_of_fcp_create_dip;
12668         }
12669 
12670         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12671             (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12672                 failure++;
12673                 goto end_of_fcp_create_dip;
12674         }
12675         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12676         if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12677             sam_lun) != DDI_PROP_SUCCESS) {
12678                 failure++;
12679                 goto end_of_fcp_create_dip;
12680         }
12681 
12682 end_of_fcp_create_dip:
12683         scsi_hba_nodename_compatible_free(nname, compatible);
12684 
12685         if (cdip != NULL && failure) {
12686                 (void) ndi_prop_remove_all(cdip);
12687                 (void) ndi_devi_free(cdip);
12688                 cdip = NULL;
12689         }
12690 
12691         return (cdip);
12692 }
12693 
12694 /*
12695  *     Function: fcp_create_pip
12696  *
12697  *  Description: Creates a Path Id for the LUN specified by the caller.
12698  *
12699  *     Argument: plun           Lun structure
12700  *               link_cnt       Link state count.
12701  *               tgt_cnt        Target state count.
12702  *
12703  * Return Value: NULL if it failed
12704  *               mdi_pathinfo_t structure address if it succeeded
12705  *
12706  *      Context: Kernel context
12707  */
12708 static mdi_pathinfo_t *
12709 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12710 {
12711         int                     i;
12712         char                    buf[MAXNAMELEN];
12713         char                    uaddr[MAXNAMELEN];
12714         int                     failure = 0;
12715         uint32_t                tgt_id;
12716         uint64_t                sam_lun;
12717         struct fcp_tgt  *ptgt = plun->lun_tgt;
12718         struct fcp_port *pptr = ptgt->tgt_port;
12719         dev_info_t              *pdip = pptr->port_dip;
12720         mdi_pathinfo_t          *pip = NULL;
12721         mdi_pathinfo_t          *old_pip = PIP(plun->lun_cip);
12722         char                    *nname = NULL;
12723         char                    **compatible = NULL;
12724         int                     ncompatible;
12725         char                    *scsi_binding_set;
12726         char                    t_pwwn[17];
12727 
12728         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12729         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12730 
12731         scsi_binding_set = "vhci";
12732 
12733         /* determine the node name and compatible */
12734         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12735             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12736 
12737         if (nname == NULL) {
12738 #ifdef  DEBUG
12739                 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12740                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12741                     "    compatible: %s",
12742                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12743                     ptgt->tgt_port_wwn.raw_wwn[0],
12744                     ptgt->tgt_port_wwn.raw_wwn[1],
12745                     ptgt->tgt_port_wwn.raw_wwn[2],
12746                     ptgt->tgt_port_wwn.raw_wwn[3],
12747                     ptgt->tgt_port_wwn.raw_wwn[4],
12748                     ptgt->tgt_port_wwn.raw_wwn[5],
12749                     ptgt->tgt_port_wwn.raw_wwn[6],
12750                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12751                     *compatible);
12752 #endif  /* DEBUG */
12753                 failure++;
12754                 goto end_of_fcp_create_pip;
12755         }
12756 
12757         pip = fcp_find_existing_pip(plun, pdip);
12758 
12759         /*
12760          * if the old_dip does not match the cdip, that means there is
12761          * some property change. since we'll be using the cdip, we need
12762          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12763          * then the dtype for the device has been updated. Offline the
12764          * the old device and create a new device with the new device type
12765          * Refer to bug: 4764752
12766          */
12767         if (old_pip && (pip != old_pip ||
12768             plun->lun_state & FCP_LUN_CHANGED)) {
12769                 plun->lun_state &= ~(FCP_LUN_INIT);
12770                 mutex_exit(&plun->lun_mutex);
12771                 mutex_exit(&pptr->port_mutex);
12772 
12773                 mutex_enter(&ptgt->tgt_mutex);
12774                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12775                     FCP_OFFLINE, lcount, tcount,
12776                     NDI_DEVI_REMOVE, 0);
12777                 mutex_exit(&ptgt->tgt_mutex);
12778 
12779                 if (pip != NULL) {
12780                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12781                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12782                             "Old pip=%p; New pip=%p don't match",
12783                             old_pip, pip);
12784                 } else {
12785                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12786                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12787                             "Old pip=%p; New pip=NULL don't match",
12788                             old_pip);
12789                 }
12790 
12791                 mutex_enter(&pptr->port_mutex);
12792                 mutex_enter(&plun->lun_mutex);
12793         }
12794 
12795         /*
12796          * Since FC_WWN_SIZE is 8 bytes and its not like the
12797          * lun_guid_size which is dependent on the target, I don't
12798          * believe the same trancation happens here UNLESS the standards
12799          * change the FC_WWN_SIZE value to something larger than
12800          * MAXNAMELEN(currently 255 bytes).
12801          */
12802 
12803         for (i = 0; i < FC_WWN_SIZE; i++) {
12804                 (void) sprintf(&buf[i << 1], "%02x",
12805                     ptgt->tgt_port_wwn.raw_wwn[i]);
12806         }
12807 
12808         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12809             buf, plun->lun_num);
12810 
12811         if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12812                 /*
12813                  * Release the locks before calling into
12814                  * mdi_pi_alloc_compatible() since this can result in a
12815                  * callback into fcp which can result in a deadlock
12816                  * (see bug # 4870272).
12817                  *
12818                  * Basically, what we are trying to avoid is the scenario where
12819                  * one thread does ndi_devi_enter() and tries to grab
12820                  * fcp_mutex and another does it the other way round.
12821                  *
12822                  * But before we do that, make sure that nobody releases the
12823                  * port in the meantime. We can do this by setting a flag.
12824                  */
12825                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12826                 pptr->port_state |= FCP_STATE_IN_MDI;
12827                 mutex_exit(&plun->lun_mutex);
12828                 mutex_exit(&pptr->port_mutex);
12829                 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12830                     uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12831                         fcp_log(CE_WARN, pptr->port_dip,
12832                             "!path alloc failed:0x%x", plun);
12833                         mutex_enter(&pptr->port_mutex);
12834                         mutex_enter(&plun->lun_mutex);
12835                         pptr->port_state &= ~FCP_STATE_IN_MDI;
12836                         failure++;
12837                         goto end_of_fcp_create_pip;
12838                 }
12839                 mutex_enter(&pptr->port_mutex);
12840                 mutex_enter(&plun->lun_mutex);
12841                 pptr->port_state &= ~FCP_STATE_IN_MDI;
12842         } else {
12843                 (void) mdi_prop_remove(pip, NULL);
12844         }
12845 
12846         mdi_pi_set_phci_private(pip, (caddr_t)plun);
12847 
12848         if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12849             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12850             != DDI_PROP_SUCCESS) {
12851                 failure++;
12852                 goto end_of_fcp_create_pip;
12853         }
12854 
12855         if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12856             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12857             != DDI_PROP_SUCCESS) {
12858                 failure++;
12859                 goto end_of_fcp_create_pip;
12860         }
12861 
12862         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12863         t_pwwn[16] = '\0';
12864         if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12865             != DDI_PROP_SUCCESS) {
12866                 failure++;
12867                 goto end_of_fcp_create_pip;
12868         }
12869 
12870         /*
12871          * If there is no hard address - We might have to deal with
12872          * that by using WWN - Having said that it is important to
12873          * recognize this problem early so ssd can be informed of
12874          * the right interconnect type.
12875          */
12876         if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12877             ptgt->tgt_hard_addr != 0) {
12878                 tgt_id = (uint32_t)
12879                     fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12880         } else {
12881                 tgt_id = ptgt->tgt_d_id;
12882         }
12883 
12884         if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12885             != DDI_PROP_SUCCESS) {
12886                 failure++;
12887                 goto end_of_fcp_create_pip;
12888         }
12889 
12890         if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12891             != DDI_PROP_SUCCESS) {
12892                 failure++;
12893                 goto end_of_fcp_create_pip;
12894         }
12895         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12896         if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12897             != DDI_PROP_SUCCESS) {
12898                 failure++;
12899                 goto end_of_fcp_create_pip;
12900         }
12901 
12902 end_of_fcp_create_pip:
12903         scsi_hba_nodename_compatible_free(nname, compatible);
12904 
12905         if (pip != NULL && failure) {
12906                 (void) mdi_prop_remove(pip, NULL);
12907                 mutex_exit(&plun->lun_mutex);
12908                 mutex_exit(&pptr->port_mutex);
12909                 (void) mdi_pi_free(pip, 0);
12910                 mutex_enter(&pptr->port_mutex);
12911                 mutex_enter(&plun->lun_mutex);
12912                 pip = NULL;
12913         }
12914 
12915         return (pip);
12916 }
12917 
12918 static dev_info_t *
12919 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12920 {
12921         uint_t                  nbytes;
12922         uchar_t                 *bytes;
12923         uint_t                  nwords;
12924         uint32_t                tgt_id;
12925         int                     *words;
12926         dev_info_t              *cdip;
12927         dev_info_t              *ndip;
12928         struct fcp_tgt  *ptgt = plun->lun_tgt;
12929         struct fcp_port *pptr = ptgt->tgt_port;
12930         int                     circular;
12931 
12932         ndi_devi_enter(pdip, &circular);
12933 
12934         ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12935         while ((cdip = ndip) != NULL) {
12936                 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12937 
12938                 if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12939                         continue;
12940                 }
12941 
12942                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12943                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12944                     &nbytes) != DDI_PROP_SUCCESS) {
12945                         continue;
12946                 }
12947 
12948                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12949                         if (bytes != NULL) {
12950                                 ddi_prop_free(bytes);
12951                         }
12952                         continue;
12953                 }
12954                 ASSERT(bytes != NULL);
12955 
12956                 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12957                         ddi_prop_free(bytes);
12958                         continue;
12959                 }
12960 
12961                 ddi_prop_free(bytes);
12962 
12963                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12964                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12965                     &nbytes) != DDI_PROP_SUCCESS) {
12966                         continue;
12967                 }
12968 
12969                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12970                         if (bytes != NULL) {
12971                                 ddi_prop_free(bytes);
12972                         }
12973                         continue;
12974                 }
12975                 ASSERT(bytes != NULL);
12976 
12977                 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12978                         ddi_prop_free(bytes);
12979                         continue;
12980                 }
12981 
12982                 ddi_prop_free(bytes);
12983 
12984                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12985                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12986                     &nwords) != DDI_PROP_SUCCESS) {
12987                         continue;
12988                 }
12989 
12990                 if (nwords != 1 || words == NULL) {
12991                         if (words != NULL) {
12992                                 ddi_prop_free(words);
12993                         }
12994                         continue;
12995                 }
12996                 ASSERT(words != NULL);
12997 
12998                 /*
12999                  * If there is no hard address - We might have to deal with
13000                  * that by using WWN - Having said that it is important to
13001                  * recognize this problem early so ssd can be informed of
13002                  * the right interconnect type.
13003                  */
13004                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13005                     ptgt->tgt_hard_addr != 0) {
13006                         tgt_id =
13007                             (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13008                 } else {
13009                         tgt_id = ptgt->tgt_d_id;
13010                 }
13011 
13012                 if (tgt_id != (uint32_t)*words) {
13013                         ddi_prop_free(words);
13014                         continue;
13015                 }
13016                 ddi_prop_free(words);
13017 
13018                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13019                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13020                     &nwords) != DDI_PROP_SUCCESS) {
13021                         continue;
13022                 }
13023 
13024                 if (nwords != 1 || words == NULL) {
13025                         if (words != NULL) {
13026                                 ddi_prop_free(words);
13027                         }
13028                         continue;
13029                 }
13030                 ASSERT(words != NULL);
13031 
13032                 if (plun->lun_num == (uint16_t)*words) {
13033                         ddi_prop_free(words);
13034                         break;
13035                 }
13036                 ddi_prop_free(words);
13037         }
13038         ndi_devi_exit(pdip, circular);
13039 
13040         return (cdip);
13041 }
13042 
13043 
13044 static int
13045 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13046 {
13047         dev_info_t      *pdip;
13048         char            buf[MAXNAMELEN];
13049         char            uaddr[MAXNAMELEN];
13050         int             rval = FC_FAILURE;
13051 
13052         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13053 
13054         pdip = plun->lun_tgt->tgt_port->port_dip;
13055 
13056         /*
13057          * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13058          * non-NULL even when the LUN is not there as in the case when a LUN is
13059          * configured and then deleted on the device end (for T3/T4 case). In
13060          * such cases, pip will be NULL.
13061          *
13062          * If the device generates an RSCN, it will end up getting offlined when
13063          * it disappeared and a new LUN will get created when it is rediscovered
13064          * on the device. If we check for lun_cip here, the LUN will not end
13065          * up getting onlined since this function will end up returning a
13066          * FC_SUCCESS.
13067          *
13068          * The behavior is different on other devices. For instance, on a HDS,
13069          * there was no RSCN generated by the device but the next I/O generated
13070          * a check condition and rediscovery got triggered that way. So, in
13071          * such cases, this path will not be exercised
13072          */
13073         if (pip == NULL) {
13074                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13075                     fcp_trace, FCP_BUF_LEVEL_4, 0,
13076                     "fcp_is_pip_present: plun->lun_cip is NULL: "
13077                     "plun: %p lun state: %x num: %d target state: %x",
13078                     plun, plun->lun_state, plun->lun_num,
13079                     plun->lun_tgt->tgt_port->port_state);
13080                 return (rval);
13081         }
13082 
13083         fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13084 
13085         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13086 
13087         if (plun->lun_old_guid) {
13088                 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13089                         rval = FC_SUCCESS;
13090                 }
13091         } else {
13092                 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13093                         rval = FC_SUCCESS;
13094                 }
13095         }
13096         return (rval);
13097 }
13098 
13099 static mdi_pathinfo_t *
13100 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13101 {
13102         char                    buf[MAXNAMELEN];
13103         char                    uaddr[MAXNAMELEN];
13104         mdi_pathinfo_t          *pip;
13105         struct fcp_tgt  *ptgt = plun->lun_tgt;
13106         struct fcp_port *pptr = ptgt->tgt_port;
13107 
13108         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13109 
13110         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13111         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13112 
13113         pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13114 
13115         return (pip);
13116 }
13117 
13118 
13119 static int
13120 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13121     int tcount, int flags, int *circ)
13122 {
13123         int                     rval;
13124         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
13125         struct fcp_tgt  *ptgt = plun->lun_tgt;
13126         dev_info_t              *cdip = NULL;
13127 
13128         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13129         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13130 
13131         if (plun->lun_cip == NULL) {
13132                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13133                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13134                     "fcp_online_child: plun->lun_cip is NULL: "
13135                     "plun: %p state: %x num: %d target state: %x",
13136                     plun, plun->lun_state, plun->lun_num,
13137                     plun->lun_tgt->tgt_port->port_state);
13138                 return (NDI_FAILURE);
13139         }
13140 again:
13141         if (plun->lun_mpxio == 0) {
13142                 cdip = DIP(cip);
13143                 mutex_exit(&plun->lun_mutex);
13144                 mutex_exit(&pptr->port_mutex);
13145 
13146                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13147                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13148                     "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13149                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13150 
13151                 /*
13152                  * We could check for FCP_LUN_INIT here but chances
13153                  * of getting here when it's already in FCP_LUN_INIT
13154                  * is rare and a duplicate ndi_devi_online wouldn't
13155                  * hurt either (as the node would already have been
13156                  * in CF2)
13157                  */
13158                 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13159                         rval = ndi_devi_bind_driver(cdip, flags);
13160                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13161                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13162                             "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13163                 } else {
13164                         rval = ndi_devi_online(cdip, flags);
13165                 }
13166 
13167                 /*
13168                  * We log the message into trace buffer if the device
13169                  * is "ses" and into syslog for any other device
13170                  * type. This is to prevent the ndi_devi_online failure
13171                  * message that appears for V880/A5K ses devices.
13172                  */
13173                 if (rval == NDI_SUCCESS) {
13174                         mutex_enter(&ptgt->tgt_mutex);
13175                         plun->lun_state |= FCP_LUN_INIT;
13176                         mutex_exit(&ptgt->tgt_mutex);
13177                 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13178                         fcp_log(CE_NOTE, pptr->port_dip,
13179                             "!ndi_devi_online:"
13180                             " failed for %s: target=%x lun=%x %x",
13181                             ddi_get_name(cdip), ptgt->tgt_d_id,
13182                             plun->lun_num, rval);
13183                 } else {
13184                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13185                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13186                             " !ndi_devi_online:"
13187                             " failed for %s: target=%x lun=%x %x",
13188                             ddi_get_name(cdip), ptgt->tgt_d_id,
13189                             plun->lun_num, rval);
13190                 }
13191         } else {
13192                 cdip = mdi_pi_get_client(PIP(cip));
13193                 mutex_exit(&plun->lun_mutex);
13194                 mutex_exit(&pptr->port_mutex);
13195 
13196                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13197                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13198                     "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13199                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13200 
13201                 /*
13202                  * Hold path and exit phci to avoid deadlock with power
13203                  * management code during mdi_pi_online.
13204                  */
13205                 mdi_hold_path(PIP(cip));
13206                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13207 
13208                 rval = mdi_pi_online(PIP(cip), flags);
13209 
13210                 mdi_devi_enter_phci(pptr->port_dip, circ);
13211                 mdi_rele_path(PIP(cip));
13212 
13213                 if (rval == MDI_SUCCESS) {
13214                         mutex_enter(&ptgt->tgt_mutex);
13215                         plun->lun_state |= FCP_LUN_INIT;
13216                         mutex_exit(&ptgt->tgt_mutex);
13217 
13218                         /*
13219                          * Clear MPxIO path permanent disable in case
13220                          * fcp hotplug dropped the offline event.
13221                          */
13222                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13223 
13224                 } else if (rval == MDI_NOT_SUPPORTED) {
13225                         child_info_t    *old_cip = cip;
13226 
13227                         /*
13228                          * MPxIO does not support this device yet.
13229                          * Enumerate in legacy mode.
13230                          */
13231                         mutex_enter(&pptr->port_mutex);
13232                         mutex_enter(&plun->lun_mutex);
13233                         plun->lun_mpxio = 0;
13234                         plun->lun_cip = NULL;
13235                         cdip = fcp_create_dip(plun, lcount, tcount);
13236                         plun->lun_cip = cip = CIP(cdip);
13237                         if (cip == NULL) {
13238                                 fcp_log(CE_WARN, pptr->port_dip,
13239                                     "!fcp_online_child: "
13240                                     "Create devinfo failed for LU=%p", plun);
13241                                 mutex_exit(&plun->lun_mutex);
13242 
13243                                 mutex_enter(&ptgt->tgt_mutex);
13244                                 plun->lun_state |= FCP_LUN_OFFLINE;
13245                                 mutex_exit(&ptgt->tgt_mutex);
13246 
13247                                 mutex_exit(&pptr->port_mutex);
13248 
13249                                 /*
13250                                  * free the mdi_pathinfo node
13251                                  */
13252                                 (void) mdi_pi_free(PIP(old_cip), 0);
13253                         } else {
13254                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13255                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13256                                     "fcp_online_child: creating devinfo "
13257                                     "node 0x%p for plun 0x%p",
13258                                     cip, plun);
13259                                 mutex_exit(&plun->lun_mutex);
13260                                 mutex_exit(&pptr->port_mutex);
13261                                 /*
13262                                  * free the mdi_pathinfo node
13263                                  */
13264                                 (void) mdi_pi_free(PIP(old_cip), 0);
13265                                 mutex_enter(&pptr->port_mutex);
13266                                 mutex_enter(&plun->lun_mutex);
13267                                 goto again;
13268                         }
13269                 } else {
13270                         if (cdip) {
13271                                 fcp_log(CE_NOTE, pptr->port_dip,
13272                                     "!fcp_online_child: mdi_pi_online:"
13273                                     " failed for %s: target=%x lun=%x %x",
13274                                     ddi_get_name(cdip), ptgt->tgt_d_id,
13275                                     plun->lun_num, rval);
13276                         }
13277                 }
13278                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13279         }
13280 
13281         if (rval == NDI_SUCCESS) {
13282                 if (cdip) {
13283                         (void) ndi_event_retrieve_cookie(
13284                             pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13285                             &fcp_insert_eid, NDI_EVENT_NOPASS);
13286                         (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13287                             cdip, fcp_insert_eid, NULL);
13288                 }
13289         }
13290         mutex_enter(&pptr->port_mutex);
13291         mutex_enter(&plun->lun_mutex);
13292         return (rval);
13293 }
13294 
13295 /* ARGSUSED */
13296 static int
13297 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13298     int tcount, int flags, int *circ)
13299 {
13300         int             rval;
13301         int             lun_mpxio;
13302         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13303         struct fcp_tgt  *ptgt = plun->lun_tgt;
13304         dev_info_t      *cdip;
13305 
13306         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13307         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13308 
13309         if (plun->lun_cip == NULL) {
13310                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13311                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13312                     "fcp_offline_child: plun->lun_cip is NULL: "
13313                     "plun: %p lun state: %x num: %d target state: %x",
13314                     plun, plun->lun_state, plun->lun_num,
13315                     plun->lun_tgt->tgt_port->port_state);
13316                 return (NDI_FAILURE);
13317         }
13318 
13319         /*
13320          * We will use this value twice. Make a copy to be sure we use
13321          * the same value in both places.
13322          */
13323         lun_mpxio = plun->lun_mpxio;
13324 
13325         if (lun_mpxio == 0) {
13326                 cdip = DIP(cip);
13327                 mutex_exit(&plun->lun_mutex);
13328                 mutex_exit(&pptr->port_mutex);
13329                 rval = ndi_devi_offline(DIP(cip), flags);
13330                 if (rval != NDI_SUCCESS) {
13331                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13332                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13333                             "fcp_offline_child: ndi_devi_offline failed "
13334                             "rval=%x cip=%p", rval, cip);
13335                 }
13336         } else {
13337                 cdip = mdi_pi_get_client(PIP(cip));
13338                 mutex_exit(&plun->lun_mutex);
13339                 mutex_exit(&pptr->port_mutex);
13340 
13341                 /*
13342                  * Exit phci to avoid deadlock with power management code
13343                  * during mdi_pi_offline
13344                  */
13345                 mdi_hold_path(PIP(cip));
13346                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13347 
13348                 rval = mdi_pi_offline(PIP(cip), flags);
13349 
13350                 mdi_devi_enter_phci(pptr->port_dip, circ);
13351                 mdi_rele_path(PIP(cip));
13352 
13353                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13354         }
13355 
13356         mutex_enter(&ptgt->tgt_mutex);
13357         plun->lun_state &= ~FCP_LUN_INIT;
13358         mutex_exit(&ptgt->tgt_mutex);
13359 
13360         if (rval == NDI_SUCCESS) {
13361                 cdip = NULL;
13362                 if (flags & NDI_DEVI_REMOVE) {
13363                         mutex_enter(&plun->lun_mutex);
13364                         /*
13365                          * If the guid of the LUN changes, lun_cip will not
13366                          * equal to cip, and after offlining the LUN with the
13367                          * old guid, we should keep lun_cip since it's the cip
13368                          * of the LUN with the new guid.
13369                          * Otherwise remove our reference to child node.
13370                          *
13371                          * This must be done before the child node is freed,
13372                          * otherwise other threads could see a stale lun_cip
13373                          * pointer.
13374                          */
13375                         if (plun->lun_cip == cip) {
13376                                 plun->lun_cip = NULL;
13377                         }
13378                         if (plun->lun_old_guid) {
13379                                 kmem_free(plun->lun_old_guid,
13380                                     plun->lun_old_guid_size);
13381                                 plun->lun_old_guid = NULL;
13382                                 plun->lun_old_guid_size = 0;
13383                         }
13384                         mutex_exit(&plun->lun_mutex);
13385                 }
13386         }
13387 
13388         if (lun_mpxio != 0) {
13389                 if (rval == NDI_SUCCESS) {
13390                         /*
13391                          * Clear MPxIO path permanent disable as the path is
13392                          * already offlined.
13393                          */
13394                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13395 
13396                         if (flags & NDI_DEVI_REMOVE) {
13397                                 (void) mdi_pi_free(PIP(cip), 0);
13398                         }
13399                 } else {
13400                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13401                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13402                             "fcp_offline_child: mdi_pi_offline failed "
13403                             "rval=%x cip=%p", rval, cip);
13404                 }
13405         }
13406 
13407         mutex_enter(&pptr->port_mutex);
13408         mutex_enter(&plun->lun_mutex);
13409 
13410         if (cdip) {
13411                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13412                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13413                     " target=%x lun=%x", "ndi_offline",
13414                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13415         }
13416 
13417         return (rval);
13418 }
13419 
13420 static void
13421 fcp_remove_child(struct fcp_lun *plun)
13422 {
13423         child_info_t *cip;
13424         int circ;
13425 
13426         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13427 
13428         if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13429                 if (plun->lun_mpxio == 0) {
13430                         (void) ndi_prop_remove_all(DIP(plun->lun_cip));
13431                         (void) ndi_devi_free(DIP(plun->lun_cip));
13432                         plun->lun_cip = NULL;
13433                 } else {
13434                         /*
13435                          * Clear reference to the child node in the lun.
13436                          * This must be done before freeing it with mdi_pi_free
13437                          * and with lun_mutex held so that other threads always
13438                          * see either valid lun_cip or NULL when holding
13439                          * lun_mutex. We keep a copy in cip.
13440                          */
13441                         cip = plun->lun_cip;
13442                         plun->lun_cip = NULL;
13443 
13444                         mutex_exit(&plun->lun_mutex);
13445                         mutex_exit(&plun->lun_tgt->tgt_mutex);
13446                         mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13447 
13448                         mdi_devi_enter(
13449                             plun->lun_tgt->tgt_port->port_dip, &circ);
13450 
13451                         /*
13452                          * Exit phci to avoid deadlock with power management
13453                          * code during mdi_pi_offline
13454                          */
13455                         mdi_hold_path(PIP(cip));
13456                         mdi_devi_exit_phci(
13457                             plun->lun_tgt->tgt_port->port_dip, circ);
13458                         (void) mdi_pi_offline(PIP(cip),
13459                             NDI_DEVI_REMOVE);
13460                         mdi_devi_enter_phci(
13461                             plun->lun_tgt->tgt_port->port_dip, &circ);
13462                         mdi_rele_path(PIP(cip));
13463 
13464                         mdi_devi_exit(
13465                             plun->lun_tgt->tgt_port->port_dip, circ);
13466 
13467                         FCP_TRACE(fcp_logq,
13468                             plun->lun_tgt->tgt_port->port_instbuf,
13469                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13470                             "lun=%p pip freed %p", plun, cip);
13471 
13472                         (void) mdi_prop_remove(PIP(cip), NULL);
13473                         (void) mdi_pi_free(PIP(cip), 0);
13474 
13475                         mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13476                         mutex_enter(&plun->lun_tgt->tgt_mutex);
13477                         mutex_enter(&plun->lun_mutex);
13478                 }
13479         } else {
13480                 plun->lun_cip = NULL;
13481         }
13482 }
13483 
13484 /*
13485  * called when a timeout occurs
13486  *
13487  * can be scheduled during an attach or resume (if not already running)
13488  *
13489  * one timeout is set up for all ports
13490  *
13491  * acquires and releases the global mutex
13492  */
13493 /*ARGSUSED*/
13494 static void
13495 fcp_watch(void *arg)
13496 {
13497         struct fcp_port *pptr;
13498         struct fcp_ipkt *icmd;
13499         struct fcp_ipkt *nicmd;
13500         struct fcp_pkt  *cmd;
13501         struct fcp_pkt  *ncmd;
13502         struct fcp_pkt  *tail;
13503         struct fcp_pkt  *pcmd;
13504         struct fcp_pkt  *save_head;
13505         struct fcp_port *save_port;
13506 
13507         /* increment global watchdog time */
13508         fcp_watchdog_time += fcp_watchdog_timeout;
13509 
13510         mutex_enter(&fcp_global_mutex);
13511 
13512         /* scan each port in our list */
13513         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13514                 save_port = fcp_port_head;
13515                 pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13516                 mutex_exit(&fcp_global_mutex);
13517 
13518                 mutex_enter(&pptr->port_mutex);
13519                 if (pptr->port_ipkt_list == NULL &&
13520                     (pptr->port_state & (FCP_STATE_SUSPENDED |
13521                     FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13522                         pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13523                         mutex_exit(&pptr->port_mutex);
13524                         mutex_enter(&fcp_global_mutex);
13525                         goto end_of_watchdog;
13526                 }
13527 
13528                 /*
13529                  * We check if a list of targets need to be offlined.
13530                  */
13531                 if (pptr->port_offline_tgts) {
13532                         fcp_scan_offline_tgts(pptr);
13533                 }
13534 
13535                 /*
13536                  * We check if a list of luns need to be offlined.
13537                  */
13538                 if (pptr->port_offline_luns) {
13539                         fcp_scan_offline_luns(pptr);
13540                 }
13541 
13542                 /*
13543                  * We check if a list of targets or luns need to be reset.
13544                  */
13545                 if (pptr->port_reset_list) {
13546                         fcp_check_reset_delay(pptr);
13547                 }
13548 
13549                 mutex_exit(&pptr->port_mutex);
13550 
13551                 /*
13552                  * This is where the pending commands (pkt) are checked for
13553                  * timeout.
13554                  */
13555                 mutex_enter(&pptr->port_pkt_mutex);
13556                 tail = pptr->port_pkt_tail;
13557 
13558                 for (pcmd = NULL, cmd = pptr->port_pkt_head;
13559                     cmd != NULL; cmd = ncmd) {
13560                         ncmd = cmd->cmd_next;
13561                         /*
13562                          * If a command is in this queue the bit CFLAG_IN_QUEUE
13563                          * must be set.
13564                          */
13565                         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13566                         /*
13567                          * FCP_INVALID_TIMEOUT will be set for those
13568                          * command that need to be failed. Mostly those
13569                          * cmds that could not be queued down for the
13570                          * "timeout" value. cmd->cmd_timeout is used
13571                          * to try and requeue the command regularly.
13572                          */
13573                         if (cmd->cmd_timeout >= fcp_watchdog_time) {
13574                                 /*
13575                                  * This command hasn't timed out yet.  Let's
13576                                  * go to the next one.
13577                                  */
13578                                 pcmd = cmd;
13579                                 goto end_of_loop;
13580                         }
13581 
13582                         if (cmd == pptr->port_pkt_head) {
13583                                 ASSERT(pcmd == NULL);
13584                                 pptr->port_pkt_head = cmd->cmd_next;
13585                         } else {
13586                                 ASSERT(pcmd != NULL);
13587                                 pcmd->cmd_next = cmd->cmd_next;
13588                         }
13589 
13590                         if (cmd == pptr->port_pkt_tail) {
13591                                 ASSERT(cmd->cmd_next == NULL);
13592                                 pptr->port_pkt_tail = pcmd;
13593                                 if (pcmd) {
13594                                         pcmd->cmd_next = NULL;
13595                                 }
13596                         }
13597                         cmd->cmd_next = NULL;
13598 
13599                         /*
13600                          * save the current head before dropping the
13601                          * mutex - If the head doesn't remain the
13602                          * same after re acquiring the mutex, just
13603                          * bail out and revisit on next tick.
13604                          *
13605                          * PS: The tail pointer can change as the commands
13606                          * get requeued after failure to retransport
13607                          */
13608                         save_head = pptr->port_pkt_head;
13609                         mutex_exit(&pptr->port_pkt_mutex);
13610 
13611                         if (cmd->cmd_fp_pkt->pkt_timeout ==
13612                             FCP_INVALID_TIMEOUT) {
13613                                 struct scsi_pkt         *pkt = cmd->cmd_pkt;
13614                                 struct fcp_lun  *plun;
13615                                 struct fcp_tgt  *ptgt;
13616 
13617                                 plun = ADDR2LUN(&pkt->pkt_address);
13618                                 ptgt = plun->lun_tgt;
13619 
13620                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13621                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13622                                     "SCSI cmd 0x%x to D_ID=%x timed out",
13623                                     pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13624 
13625                                 cmd->cmd_state == FCP_PKT_ABORTING ?
13626                                     fcp_fail_cmd(cmd, CMD_RESET,
13627                                     STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13628                                     CMD_TIMEOUT, STAT_ABORTED);
13629                         } else {
13630                                 fcp_retransport_cmd(pptr, cmd);
13631                         }
13632                         mutex_enter(&pptr->port_pkt_mutex);
13633                         if (save_head && save_head != pptr->port_pkt_head) {
13634                                 /*
13635                                  * Looks like linked list got changed (mostly
13636                                  * happens when an an OFFLINE LUN code starts
13637                                  * returning overflow queue commands in
13638                                  * parallel. So bail out and revisit during
13639                                  * next tick
13640                                  */
13641                                 break;
13642                         }
13643                 end_of_loop:
13644                         /*
13645                          * Scan only upto the previously known tail pointer
13646                          * to avoid excessive processing - lots of new packets
13647                          * could have been added to the tail or the old ones
13648                          * re-queued.
13649                          */
13650                         if (cmd == tail) {
13651                                 break;
13652                         }
13653                 }
13654                 mutex_exit(&pptr->port_pkt_mutex);
13655 
13656                 mutex_enter(&pptr->port_mutex);
13657                 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13658                         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13659 
13660                         nicmd = icmd->ipkt_next;
13661                         if ((icmd->ipkt_restart != 0) &&
13662                             (icmd->ipkt_restart >= fcp_watchdog_time)) {
13663                                 /* packet has not timed out */
13664                                 continue;
13665                         }
13666 
13667                         /* time for packet re-transport */
13668                         if (icmd == pptr->port_ipkt_list) {
13669                                 pptr->port_ipkt_list = icmd->ipkt_next;
13670                                 if (pptr->port_ipkt_list) {
13671                                         pptr->port_ipkt_list->ipkt_prev =
13672                                             NULL;
13673                                 }
13674                         } else {
13675                                 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13676                                 if (icmd->ipkt_next) {
13677                                         icmd->ipkt_next->ipkt_prev =
13678                                             icmd->ipkt_prev;
13679                                 }
13680                         }
13681                         icmd->ipkt_next = NULL;
13682                         icmd->ipkt_prev = NULL;
13683                         mutex_exit(&pptr->port_mutex);
13684 
13685                         if (fcp_is_retryable(icmd)) {
13686                                 fc_ulp_rscn_info_t *rscnp =
13687                                     (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13688                                     pkt_ulp_rscn_infop;
13689 
13690                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13691                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13692                                     "%x to D_ID=%x Retrying..",
13693                                     icmd->ipkt_opcode,
13694                                     icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13695 
13696                                 /*
13697                                  * Update the RSCN count in the packet
13698                                  * before resending.
13699                                  */
13700 
13701                                 if (rscnp != NULL) {
13702                                         rscnp->ulp_rscn_count =
13703                                             fc_ulp_get_rscn_count(pptr->
13704                                             port_fp_handle);
13705                                 }
13706 
13707                                 mutex_enter(&pptr->port_mutex);
13708                                 mutex_enter(&ptgt->tgt_mutex);
13709                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13710                                         mutex_exit(&ptgt->tgt_mutex);
13711                                         mutex_exit(&pptr->port_mutex);
13712                                         switch (icmd->ipkt_opcode) {
13713                                                 int rval;
13714                                         case LA_ELS_PLOGI:
13715                                                 if ((rval = fc_ulp_login(
13716                                                     pptr->port_fp_handle,
13717                                                     &icmd->ipkt_fpkt, 1)) ==
13718                                                     FC_SUCCESS) {
13719                                                         mutex_enter(
13720                                                             &pptr->port_mutex);
13721                                                         continue;
13722                                                 }
13723                                                 if (fcp_handle_ipkt_errors(
13724                                                     pptr, ptgt, icmd, rval,
13725                                                     "PLOGI") == DDI_SUCCESS) {
13726                                                         mutex_enter(
13727                                                             &pptr->port_mutex);
13728                                                         continue;
13729                                                 }
13730                                                 break;
13731 
13732                                         case LA_ELS_PRLI:
13733                                                 if ((rval = fc_ulp_issue_els(
13734                                                     pptr->port_fp_handle,
13735                                                     icmd->ipkt_fpkt)) ==
13736                                                     FC_SUCCESS) {
13737                                                         mutex_enter(
13738                                                             &pptr->port_mutex);
13739                                                         continue;
13740                                                 }
13741                                                 if (fcp_handle_ipkt_errors(
13742                                                     pptr, ptgt, icmd, rval,
13743                                                     "PRLI") == DDI_SUCCESS) {
13744                                                         mutex_enter(
13745                                                             &pptr->port_mutex);
13746                                                         continue;
13747                                                 }
13748                                                 break;
13749 
13750                                         default:
13751                                                 if ((rval = fcp_transport(
13752                                                     pptr->port_fp_handle,
13753                                                     icmd->ipkt_fpkt, 1)) ==
13754                                                     FC_SUCCESS) {
13755                                                         mutex_enter(
13756                                                             &pptr->port_mutex);
13757                                                         continue;
13758                                                 }
13759                                                 if (fcp_handle_ipkt_errors(
13760                                                     pptr, ptgt, icmd, rval,
13761                                                     "PRLI") == DDI_SUCCESS) {
13762                                                         mutex_enter(
13763                                                             &pptr->port_mutex);
13764                                                         continue;
13765                                                 }
13766                                                 break;
13767                                         }
13768                                 } else {
13769                                         mutex_exit(&ptgt->tgt_mutex);
13770                                         mutex_exit(&pptr->port_mutex);
13771                                 }
13772                         } else {
13773                                 fcp_print_error(icmd->ipkt_fpkt);
13774                         }
13775 
13776                         (void) fcp_call_finish_init(pptr, ptgt,
13777                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13778                             icmd->ipkt_cause);
13779                         fcp_icmd_free(pptr, icmd);
13780                         mutex_enter(&pptr->port_mutex);
13781                 }
13782 
13783                 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13784                 mutex_exit(&pptr->port_mutex);
13785                 mutex_enter(&fcp_global_mutex);
13786 
13787         end_of_watchdog:
13788                 /*
13789                  * Bail out early before getting into trouble
13790                  */
13791                 if (save_port != fcp_port_head) {
13792                         break;
13793                 }
13794         }
13795 
13796         if (fcp_watchdog_init > 0) {
13797                 /* reschedule timeout to go again */
13798                 fcp_watchdog_id =
13799                     timeout(fcp_watch, NULL, fcp_watchdog_tick);
13800         }
13801         mutex_exit(&fcp_global_mutex);
13802 }
13803 
13804 
13805 static void
13806 fcp_check_reset_delay(struct fcp_port *pptr)
13807 {
13808         uint32_t                tgt_cnt;
13809         int                     level;
13810         struct fcp_tgt  *ptgt;
13811         struct fcp_lun  *plun;
13812         struct fcp_reset_elem *cur = NULL;
13813         struct fcp_reset_elem *next = NULL;
13814         struct fcp_reset_elem *prev = NULL;
13815 
13816         ASSERT(mutex_owned(&pptr->port_mutex));
13817 
13818         next = pptr->port_reset_list;
13819         while ((cur = next) != NULL) {
13820                 next = cur->next;
13821 
13822                 if (cur->timeout < fcp_watchdog_time) {
13823                         prev = cur;
13824                         continue;
13825                 }
13826 
13827                 ptgt = cur->tgt;
13828                 plun = cur->lun;
13829                 tgt_cnt = cur->tgt_cnt;
13830 
13831                 if (ptgt) {
13832                         level = RESET_TARGET;
13833                 } else {
13834                         ASSERT(plun != NULL);
13835                         level = RESET_LUN;
13836                         ptgt = plun->lun_tgt;
13837                 }
13838                 if (prev) {
13839                         prev->next = next;
13840                 } else {
13841                         /*
13842                          * Because we drop port mutex while doing aborts for
13843                          * packets, we can't rely on reset_list pointing to
13844                          * our head
13845                          */
13846                         if (cur == pptr->port_reset_list) {
13847                                 pptr->port_reset_list = next;
13848                         } else {
13849                                 struct fcp_reset_elem *which;
13850 
13851                                 which = pptr->port_reset_list;
13852                                 while (which && which->next != cur) {
13853                                         which = which->next;
13854                                 }
13855                                 ASSERT(which != NULL);
13856 
13857                                 which->next = next;
13858                                 prev = which;
13859                         }
13860                 }
13861 
13862                 kmem_free(cur, sizeof (*cur));
13863 
13864                 if (tgt_cnt == ptgt->tgt_change_cnt) {
13865                         mutex_enter(&ptgt->tgt_mutex);
13866                         if (level == RESET_TARGET) {
13867                                 fcp_update_tgt_state(ptgt,
13868                                     FCP_RESET, FCP_LUN_BUSY);
13869                         } else {
13870                                 fcp_update_lun_state(plun,
13871                                     FCP_RESET, FCP_LUN_BUSY);
13872                         }
13873                         mutex_exit(&ptgt->tgt_mutex);
13874 
13875                         mutex_exit(&pptr->port_mutex);
13876                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13877                         mutex_enter(&pptr->port_mutex);
13878                 }
13879         }
13880 }
13881 
13882 
13883 static void
13884 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13885     struct fcp_lun *rlun, int tgt_cnt)
13886 {
13887         int                     rval;
13888         struct fcp_lun  *tlun, *nlun;
13889         struct fcp_pkt  *pcmd = NULL, *ncmd = NULL,
13890             *cmd = NULL, *head = NULL,
13891             *tail = NULL;
13892 
13893         mutex_enter(&pptr->port_pkt_mutex);
13894         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13895                 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13896                 struct fcp_tgt *ptgt = plun->lun_tgt;
13897 
13898                 ncmd = cmd->cmd_next;
13899 
13900                 if (ptgt != ttgt && plun != rlun) {
13901                         pcmd = cmd;
13902                         continue;
13903                 }
13904 
13905                 if (pcmd != NULL) {
13906                         ASSERT(pptr->port_pkt_head != cmd);
13907                         pcmd->cmd_next = ncmd;
13908                 } else {
13909                         ASSERT(cmd == pptr->port_pkt_head);
13910                         pptr->port_pkt_head = ncmd;
13911                 }
13912                 if (pptr->port_pkt_tail == cmd) {
13913                         ASSERT(cmd->cmd_next == NULL);
13914                         pptr->port_pkt_tail = pcmd;
13915                         if (pcmd != NULL) {
13916                                 pcmd->cmd_next = NULL;
13917                         }
13918                 }
13919 
13920                 if (head == NULL) {
13921                         head = tail = cmd;
13922                 } else {
13923                         ASSERT(tail != NULL);
13924                         tail->cmd_next = cmd;
13925                         tail = cmd;
13926                 }
13927                 cmd->cmd_next = NULL;
13928         }
13929         mutex_exit(&pptr->port_pkt_mutex);
13930 
13931         for (cmd = head; cmd != NULL; cmd = ncmd) {
13932                 struct scsi_pkt *pkt = cmd->cmd_pkt;
13933 
13934                 ncmd = cmd->cmd_next;
13935                 ASSERT(pkt != NULL);
13936 
13937                 mutex_enter(&pptr->port_mutex);
13938                 if (ttgt->tgt_change_cnt == tgt_cnt) {
13939                         mutex_exit(&pptr->port_mutex);
13940                         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13941                         pkt->pkt_reason = CMD_RESET;
13942                         pkt->pkt_statistics |= STAT_DEV_RESET;
13943                         cmd->cmd_state = FCP_PKT_IDLE;
13944                         fcp_post_callback(cmd);
13945                 } else {
13946                         mutex_exit(&pptr->port_mutex);
13947                 }
13948         }
13949 
13950         /*
13951          * If the FCA will return all the commands in its queue then our
13952          * work is easy, just return.
13953          */
13954 
13955         if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13956                 return;
13957         }
13958 
13959         /*
13960          * For RESET_LUN get hold of target pointer
13961          */
13962         if (ttgt == NULL) {
13963                 ASSERT(rlun != NULL);
13964 
13965                 ttgt = rlun->lun_tgt;
13966 
13967                 ASSERT(ttgt != NULL);
13968         }
13969 
13970         /*
13971          * There are some severe race conditions here.
13972          * While we are trying to abort the pkt, it might be completing
13973          * so mark it aborted and if the abort does not succeed then
13974          * handle it in the watch thread.
13975          */
13976         mutex_enter(&ttgt->tgt_mutex);
13977         nlun = ttgt->tgt_lun;
13978         mutex_exit(&ttgt->tgt_mutex);
13979         while ((tlun = nlun) != NULL) {
13980                 int restart = 0;
13981                 if (rlun && rlun != tlun) {
13982                         mutex_enter(&ttgt->tgt_mutex);
13983                         nlun = tlun->lun_next;
13984                         mutex_exit(&ttgt->tgt_mutex);
13985                         continue;
13986                 }
13987                 mutex_enter(&tlun->lun_mutex);
13988                 cmd = tlun->lun_pkt_head;
13989                 while (cmd != NULL) {
13990                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
13991                                 struct scsi_pkt *pkt;
13992 
13993                                 restart = 1;
13994                                 cmd->cmd_state = FCP_PKT_ABORTING;
13995                                 mutex_exit(&tlun->lun_mutex);
13996                                 rval = fc_ulp_abort(pptr->port_fp_handle,
13997                                     cmd->cmd_fp_pkt, KM_SLEEP);
13998                                 if (rval == FC_SUCCESS) {
13999                                         pkt = cmd->cmd_pkt;
14000                                         pkt->pkt_reason = CMD_RESET;
14001                                         pkt->pkt_statistics |= STAT_DEV_RESET;
14002                                         cmd->cmd_state = FCP_PKT_IDLE;
14003                                         fcp_post_callback(cmd);
14004                                 } else {
14005                                         caddr_t msg;
14006 
14007                                         (void) fc_ulp_error(rval, &msg);
14008 
14009                                         /*
14010                                          * This part is tricky. The abort
14011                                          * failed and now the command could
14012                                          * be completing.  The cmd_state ==
14013                                          * FCP_PKT_ABORTING should save
14014                                          * us in fcp_cmd_callback. If we
14015                                          * are already aborting ignore the
14016                                          * command in fcp_cmd_callback.
14017                                          * Here we leave this packet for 20
14018                                          * sec to be aborted in the
14019                                          * fcp_watch thread.
14020                                          */
14021                                         fcp_log(CE_WARN, pptr->port_dip,
14022                                             "!Abort failed after reset %s",
14023                                             msg);
14024 
14025                                         cmd->cmd_timeout =
14026                                             fcp_watchdog_time +
14027                                             cmd->cmd_pkt->pkt_time +
14028                                             FCP_FAILED_DELAY;
14029 
14030                                         cmd->cmd_fp_pkt->pkt_timeout =
14031                                             FCP_INVALID_TIMEOUT;
14032                                         /*
14033                                          * This is a hack, cmd is put in the
14034                                          * overflow queue so that it can be
14035                                          * timed out finally
14036                                          */
14037                                         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14038 
14039                                         mutex_enter(&pptr->port_pkt_mutex);
14040                                         if (pptr->port_pkt_head) {
14041                                                 ASSERT(pptr->port_pkt_tail
14042                                                     != NULL);
14043                                                 pptr->port_pkt_tail->cmd_next
14044                                                     = cmd;
14045                                                 pptr->port_pkt_tail = cmd;
14046                                         } else {
14047                                                 ASSERT(pptr->port_pkt_tail
14048                                                     == NULL);
14049                                                 pptr->port_pkt_head =
14050                                                     pptr->port_pkt_tail
14051                                                     = cmd;
14052                                         }
14053                                         cmd->cmd_next = NULL;
14054                                         mutex_exit(&pptr->port_pkt_mutex);
14055                                 }
14056                                 mutex_enter(&tlun->lun_mutex);
14057                                 cmd = tlun->lun_pkt_head;
14058                         } else {
14059                                 cmd = cmd->cmd_forw;
14060                         }
14061                 }
14062                 mutex_exit(&tlun->lun_mutex);
14063 
14064                 mutex_enter(&ttgt->tgt_mutex);
14065                 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14066                 mutex_exit(&ttgt->tgt_mutex);
14067 
14068                 mutex_enter(&pptr->port_mutex);
14069                 if (tgt_cnt != ttgt->tgt_change_cnt) {
14070                         mutex_exit(&pptr->port_mutex);
14071                         return;
14072                 } else {
14073                         mutex_exit(&pptr->port_mutex);
14074                 }
14075         }
14076 }
14077 
14078 
14079 /*
14080  * unlink the soft state, returning the soft state found (if any)
14081  *
14082  * acquires and releases the global mutex
14083  */
14084 struct fcp_port *
14085 fcp_soft_state_unlink(struct fcp_port *pptr)
14086 {
14087         struct fcp_port *hptr;          /* ptr index */
14088         struct fcp_port *tptr;          /* prev hptr */
14089 
14090         mutex_enter(&fcp_global_mutex);
14091         for (hptr = fcp_port_head, tptr = NULL;
14092             hptr != NULL;
14093             tptr = hptr, hptr = hptr->port_next) {
14094                 if (hptr == pptr) {
14095                         /* we found a match -- remove this item */
14096                         if (tptr == NULL) {
14097                                 /* we're at the head of the list */
14098                                 fcp_port_head = hptr->port_next;
14099                         } else {
14100                                 tptr->port_next = hptr->port_next;
14101                         }
14102                         break;                  /* success */
14103                 }
14104         }
14105         if (fcp_port_head == NULL) {
14106                 fcp_cleanup_blacklist(&fcp_lun_blacklist);
14107         }
14108         mutex_exit(&fcp_global_mutex);
14109         return (hptr);
14110 }
14111 
14112 
14113 /*
14114  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14115  * WWN and a LUN number
14116  */
14117 /* ARGSUSED */
14118 static struct fcp_lun *
14119 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14120 {
14121         int hash;
14122         struct fcp_tgt *ptgt;
14123         struct fcp_lun *plun;
14124 
14125         ASSERT(mutex_owned(&pptr->port_mutex));
14126 
14127         hash = FCP_HASH(wwn);
14128         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14129             ptgt = ptgt->tgt_next) {
14130                 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14131                     sizeof (ptgt->tgt_port_wwn)) == 0) {
14132                         mutex_enter(&ptgt->tgt_mutex);
14133                         for (plun = ptgt->tgt_lun;
14134                             plun != NULL;
14135                             plun = plun->lun_next) {
14136                                 if (plun->lun_num == lun) {
14137                                         mutex_exit(&ptgt->tgt_mutex);
14138                                         return (plun);
14139                                 }
14140                         }
14141                         mutex_exit(&ptgt->tgt_mutex);
14142                         return (NULL);
14143                 }
14144         }
14145         return (NULL);
14146 }
14147 
14148 /*
14149  *     Function: fcp_prepare_pkt
14150  *
14151  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14152  *               for fcp_start(). It binds the data or partially maps it.
14153  *               Builds the FCP header and starts the initialization of the
14154  *               Fibre Channel header.
14155  *
14156  *     Argument: *pptr          FCP port.
14157  *               *cmd           FCP packet.
14158  *               *plun          LUN the command will be sent to.
14159  *
14160  *      Context: User, Kernel and Interrupt context.
14161  */
14162 static void
14163 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14164     struct fcp_lun *plun)
14165 {
14166         fc_packet_t             *fpkt = cmd->cmd_fp_pkt;
14167         struct fcp_tgt          *ptgt = plun->lun_tgt;
14168         struct fcp_cmd          *fcmd = &cmd->cmd_fcp_cmd;
14169 
14170         ASSERT(cmd->cmd_pkt->pkt_comp ||
14171             (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14172 
14173         if (cmd->cmd_pkt->pkt_numcookies) {
14174                 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14175                         fcmd->fcp_cntl.cntl_read_data = 1;
14176                         fcmd->fcp_cntl.cntl_write_data = 0;
14177                         fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14178                 } else {
14179                         fcmd->fcp_cntl.cntl_read_data = 0;
14180                         fcmd->fcp_cntl.cntl_write_data = 1;
14181                         fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14182                 }
14183 
14184                 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14185 
14186                 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14187                 ASSERT(fpkt->pkt_data_cookie_cnt <=
14188                     pptr->port_data_dma_attr.dma_attr_sgllen);
14189 
14190                 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14191 
14192                 /* FCA needs pkt_datalen to be set */
14193                 fpkt->pkt_datalen = cmd->cmd_dmacount;
14194                 fcmd->fcp_data_len = cmd->cmd_dmacount;
14195         } else {
14196                 fcmd->fcp_cntl.cntl_read_data = 0;
14197                 fcmd->fcp_cntl.cntl_write_data = 0;
14198                 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14199                 fpkt->pkt_datalen = 0;
14200                 fcmd->fcp_data_len = 0;
14201         }
14202 
14203         /* set up the Tagged Queuing type */
14204         if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14205                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14206         } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14207                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14208         } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14209                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14210         } else {
14211                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14212         }
14213 
14214         fcmd->fcp_ent_addr = plun->lun_addr;
14215 
14216         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14217                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14218                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14219         } else {
14220                 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14221         }
14222 
14223         cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14224         cmd->cmd_pkt->pkt_state = 0;
14225         cmd->cmd_pkt->pkt_statistics = 0;
14226         cmd->cmd_pkt->pkt_resid = 0;
14227 
14228         cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14229 
14230         if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14231                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14232                 fpkt->pkt_comp = NULL;
14233         } else {
14234                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14235                 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14236                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14237                 }
14238                 fpkt->pkt_comp = fcp_cmd_callback;
14239         }
14240 
14241         mutex_enter(&pptr->port_mutex);
14242         if (pptr->port_state & FCP_STATE_SUSPENDED) {
14243                 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14244         }
14245         mutex_exit(&pptr->port_mutex);
14246 
14247         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14248         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14249 
14250         /*
14251          * Save a few kernel cycles here
14252          */
14253 #ifndef __lock_lint
14254         fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14255 #endif /* __lock_lint */
14256 }
14257 
14258 static void
14259 fcp_post_callback(struct fcp_pkt *cmd)
14260 {
14261         scsi_hba_pkt_comp(cmd->cmd_pkt);
14262 }
14263 
14264 
14265 /*
14266  * called to do polled I/O by fcp_start()
14267  *
14268  * return a transport status value, i.e. TRAN_ACCECPT for success
14269  */
14270 static int
14271 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14272 {
14273         int     rval;
14274 
14275 #ifdef  DEBUG
14276         mutex_enter(&pptr->port_pkt_mutex);
14277         pptr->port_npkts++;
14278         mutex_exit(&pptr->port_pkt_mutex);
14279 #endif /* DEBUG */
14280 
14281         if (cmd->cmd_fp_pkt->pkt_timeout) {
14282                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14283         } else {
14284                 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14285         }
14286 
14287         ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14288 
14289         cmd->cmd_state = FCP_PKT_ISSUED;
14290 
14291         rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14292 
14293 #ifdef  DEBUG
14294         mutex_enter(&pptr->port_pkt_mutex);
14295         pptr->port_npkts--;
14296         mutex_exit(&pptr->port_pkt_mutex);
14297 #endif /* DEBUG */
14298 
14299         cmd->cmd_state = FCP_PKT_IDLE;
14300 
14301         switch (rval) {
14302         case FC_SUCCESS:
14303                 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14304                         fcp_complete_pkt(cmd->cmd_fp_pkt);
14305                         rval = TRAN_ACCEPT;
14306                 } else {
14307                         rval = TRAN_FATAL_ERROR;
14308                 }
14309                 break;
14310 
14311         case FC_TRAN_BUSY:
14312                 rval = TRAN_BUSY;
14313                 cmd->cmd_pkt->pkt_resid = 0;
14314                 break;
14315 
14316         case FC_BADPACKET:
14317                 rval = TRAN_BADPKT;
14318                 break;
14319 
14320         default:
14321                 rval = TRAN_FATAL_ERROR;
14322                 break;
14323         }
14324 
14325         return (rval);
14326 }
14327 
14328 
14329 /*
14330  * called by some of the following transport-called routines to convert
14331  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14332  */
14333 static struct fcp_port *
14334 fcp_dip2port(dev_info_t *dip)
14335 {
14336         int     instance;
14337 
14338         instance = ddi_get_instance(dip);
14339         return (ddi_get_soft_state(fcp_softstate, instance));
14340 }
14341 
14342 
14343 /*
14344  * called internally to return a LUN given a dip
14345  */
14346 struct fcp_lun *
14347 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14348 {
14349         struct fcp_tgt *ptgt;
14350         struct fcp_lun *plun;
14351         int i;
14352 
14353 
14354         ASSERT(mutex_owned(&pptr->port_mutex));
14355 
14356         for (i = 0; i < FCP_NUM_HASH; i++) {
14357                 for (ptgt = pptr->port_tgt_hash_table[i];
14358                     ptgt != NULL;
14359                     ptgt = ptgt->tgt_next) {
14360                         mutex_enter(&ptgt->tgt_mutex);
14361                         for (plun = ptgt->tgt_lun; plun != NULL;
14362                             plun = plun->lun_next) {
14363                                 mutex_enter(&plun->lun_mutex);
14364                                 if (plun->lun_cip == cip) {
14365                                         mutex_exit(&plun->lun_mutex);
14366                                         mutex_exit(&ptgt->tgt_mutex);
14367                                         return (plun); /* match found */
14368                                 }
14369                                 mutex_exit(&plun->lun_mutex);
14370                         }
14371                         mutex_exit(&ptgt->tgt_mutex);
14372                 }
14373         }
14374         return (NULL);                          /* no LUN found */
14375 }
14376 
14377 /*
14378  * pass an element to the hotplug list, kick the hotplug thread
14379  * and wait for the element to get processed by the hotplug thread.
14380  * on return the element is freed.
14381  *
14382  * return zero success and non-zero on failure
14383  *
14384  * acquires/releases the target mutex
14385  *
14386  */
14387 static int
14388 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14389     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14390 {
14391         struct fcp_hp_elem      *elem;
14392         int                     rval;
14393 
14394         mutex_enter(&plun->lun_tgt->tgt_mutex);
14395         if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14396             what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14397                 mutex_exit(&plun->lun_tgt->tgt_mutex);
14398                 fcp_log(CE_CONT, pptr->port_dip,
14399                     "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14400                     what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14401                 return (NDI_FAILURE);
14402         }
14403         mutex_exit(&plun->lun_tgt->tgt_mutex);
14404         mutex_enter(&elem->mutex);
14405         if (elem->wait) {
14406                 while (elem->wait) {
14407                         cv_wait(&elem->cv, &elem->mutex);
14408                 }
14409         }
14410         rval = (elem->result);
14411         mutex_exit(&elem->mutex);
14412         mutex_destroy(&elem->mutex);
14413         cv_destroy(&elem->cv);
14414         kmem_free(elem, sizeof (struct fcp_hp_elem));
14415         return (rval);
14416 }
14417 
14418 /*
14419  * pass an element to the hotplug list, and then
14420  * kick the hotplug thread
14421  *
14422  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14423  *
14424  * acquires/releases the hotplug mutex
14425  *
14426  * called with the target mutex owned
14427  *
14428  * memory acquired in NOSLEEP mode
14429  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14430  *       for the hp daemon to process the request and is responsible for
14431  *       freeing the element
14432  */
14433 static struct fcp_hp_elem *
14434 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14435     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14436 {
14437         struct fcp_hp_elem      *elem;
14438         dev_info_t *pdip;
14439 
14440         ASSERT(pptr != NULL);
14441         ASSERT(plun != NULL);
14442         ASSERT(plun->lun_tgt != NULL);
14443         ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14444 
14445         /* create space for a hotplug element */
14446         if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14447             == NULL) {
14448                 fcp_log(CE_WARN, NULL,
14449                     "!can't allocate memory for hotplug element");
14450                 return (NULL);
14451         }
14452 
14453         /* fill in hotplug element */
14454         elem->port = pptr;
14455         elem->lun = plun;
14456         elem->cip = cip;
14457         elem->old_lun_mpxio = plun->lun_mpxio;
14458         elem->what = what;
14459         elem->flags = flags;
14460         elem->link_cnt = link_cnt;
14461         elem->tgt_cnt = tgt_cnt;
14462         elem->wait = wait;
14463         mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14464         cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14465 
14466         /* schedule the hotplug task */
14467         pdip = pptr->port_dip;
14468         mutex_enter(&plun->lun_mutex);
14469         if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14470                 plun->lun_event_count++;
14471                 elem->event_cnt = plun->lun_event_count;
14472         }
14473         mutex_exit(&plun->lun_mutex);
14474         if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14475             (void *)elem, KM_NOSLEEP) == NULL) {
14476                 mutex_enter(&plun->lun_mutex);
14477                 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14478                         plun->lun_event_count--;
14479                 }
14480                 mutex_exit(&plun->lun_mutex);
14481                 kmem_free(elem, sizeof (*elem));
14482                 return (0);
14483         }
14484 
14485         return (elem);
14486 }
14487 
14488 
14489 static void
14490 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14491 {
14492         int                     rval;
14493         struct scsi_address     *ap;
14494         struct fcp_lun  *plun;
14495         struct fcp_tgt  *ptgt;
14496         fc_packet_t     *fpkt;
14497 
14498         ap = &cmd->cmd_pkt->pkt_address;
14499         plun = ADDR2LUN(ap);
14500         ptgt = plun->lun_tgt;
14501 
14502         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14503 
14504         cmd->cmd_state = FCP_PKT_IDLE;
14505 
14506         mutex_enter(&pptr->port_mutex);
14507         mutex_enter(&ptgt->tgt_mutex);
14508         if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14509             (!(pptr->port_state & FCP_STATE_ONLINING))) {
14510                 fc_ulp_rscn_info_t *rscnp;
14511 
14512                 cmd->cmd_state = FCP_PKT_ISSUED;
14513 
14514                 /*
14515                  * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14516                  * originally NULL, hence we try to set it to the pd pointed
14517                  * to by the SCSI device we're trying to get to.
14518                  */
14519 
14520                 fpkt = cmd->cmd_fp_pkt;
14521                 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14522                         fpkt->pkt_pd = ptgt->tgt_pd_handle;
14523                         /*
14524                          * We need to notify the transport that we now have a
14525                          * reference to the remote port handle.
14526                          */
14527                         fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14528                 }
14529 
14530                 mutex_exit(&ptgt->tgt_mutex);
14531                 mutex_exit(&pptr->port_mutex);
14532 
14533                 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14534 
14535                 /* prepare the packet */
14536 
14537                 fcp_prepare_pkt(pptr, cmd, plun);
14538 
14539                 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14540                     pkt_ulp_rscn_infop;
14541 
14542                 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14543                     fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14544 
14545                 if (rscnp != NULL) {
14546                         rscnp->ulp_rscn_count =
14547                             fc_ulp_get_rscn_count(pptr->
14548                             port_fp_handle);
14549                 }
14550 
14551                 rval = fcp_transport(pptr->port_fp_handle,
14552                     cmd->cmd_fp_pkt, 0);
14553 
14554                 if (rval == FC_SUCCESS) {
14555                         return;
14556                 }
14557                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
14558         } else {
14559                 mutex_exit(&ptgt->tgt_mutex);
14560                 mutex_exit(&pptr->port_mutex);
14561         }
14562 
14563         fcp_queue_pkt(pptr, cmd);
14564 }
14565 
14566 
14567 static void
14568 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14569 {
14570         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14571 
14572         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14573         cmd->cmd_state = FCP_PKT_IDLE;
14574 
14575         cmd->cmd_pkt->pkt_reason = reason;
14576         cmd->cmd_pkt->pkt_state = 0;
14577         cmd->cmd_pkt->pkt_statistics = statistics;
14578 
14579         fcp_post_callback(cmd);
14580 }
14581 
14582 /*
14583  *     Function: fcp_queue_pkt
14584  *
14585  *  Description: This function queues the packet passed by the caller into
14586  *               the list of packets of the FCP port.
14587  *
14588  *     Argument: *pptr          FCP port.
14589  *               *cmd           FCP packet to queue.
14590  *
14591  * Return Value: None
14592  *
14593  *      Context: User, Kernel and Interrupt context.
14594  */
14595 static void
14596 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14597 {
14598         ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14599 
14600         mutex_enter(&pptr->port_pkt_mutex);
14601         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14602         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14603         cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14604 
14605         /*
14606          * zero pkt_time means hang around for ever
14607          */
14608         if (cmd->cmd_pkt->pkt_time) {
14609                 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14610                         cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14611                 } else {
14612                         /*
14613                          * Indicate the watch thread to fail the
14614                          * command by setting it to highest value
14615                          */
14616                         cmd->cmd_timeout = fcp_watchdog_time;
14617                         cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14618                 }
14619         }
14620 
14621         if (pptr->port_pkt_head) {
14622                 ASSERT(pptr->port_pkt_tail != NULL);
14623 
14624                 pptr->port_pkt_tail->cmd_next = cmd;
14625                 pptr->port_pkt_tail = cmd;
14626         } else {
14627                 ASSERT(pptr->port_pkt_tail == NULL);
14628 
14629                 pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14630         }
14631         cmd->cmd_next = NULL;
14632         mutex_exit(&pptr->port_pkt_mutex);
14633 }
14634 
14635 /*
14636  *     Function: fcp_update_targets
14637  *
14638  *  Description: This function applies the specified change of state to all
14639  *               the targets listed.  The operation applied is 'set'.
14640  *
14641  *     Argument: *pptr          FCP port.
14642  *               *dev_list      Array of fc_portmap_t structures.
14643  *               count          Length of dev_list.
14644  *               state          State bits to update.
14645  *               cause          Reason for the update.
14646  *
14647  * Return Value: None
14648  *
14649  *      Context: User, Kernel and Interrupt context.
14650  *               The mutex pptr->port_mutex must be held.
14651  */
14652 static void
14653 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14654     uint32_t count, uint32_t state, int cause)
14655 {
14656         fc_portmap_t            *map_entry;
14657         struct fcp_tgt  *ptgt;
14658 
14659         ASSERT(MUTEX_HELD(&pptr->port_mutex));
14660 
14661         while (count--) {
14662                 map_entry = &(dev_list[count]);
14663                 ptgt = fcp_lookup_target(pptr,
14664                     (uchar_t *)&(map_entry->map_pwwn));
14665                 if (ptgt == NULL) {
14666                         continue;
14667                 }
14668 
14669                 mutex_enter(&ptgt->tgt_mutex);
14670                 ptgt->tgt_trace = 0;
14671                 ptgt->tgt_change_cnt++;
14672                 ptgt->tgt_statec_cause = cause;
14673                 ptgt->tgt_tmp_cnt = 1;
14674                 fcp_update_tgt_state(ptgt, FCP_SET, state);
14675                 mutex_exit(&ptgt->tgt_mutex);
14676         }
14677 }
14678 
14679 static int
14680 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14681     int lcount, int tcount, int cause)
14682 {
14683         int rval;
14684 
14685         mutex_enter(&pptr->port_mutex);
14686         rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14687         mutex_exit(&pptr->port_mutex);
14688 
14689         return (rval);
14690 }
14691 
14692 
14693 static int
14694 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14695     int lcount, int tcount, int cause)
14696 {
14697         int     finish_init = 0;
14698         int     finish_tgt = 0;
14699         int     do_finish_init = 0;
14700         int     rval = FCP_NO_CHANGE;
14701 
14702         if (cause == FCP_CAUSE_LINK_CHANGE ||
14703             cause == FCP_CAUSE_LINK_DOWN) {
14704                 do_finish_init = 1;
14705         }
14706 
14707         if (ptgt != NULL) {
14708                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14709                     FCP_BUF_LEVEL_2, 0,
14710                     "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14711                     " cause = %d, d_id = 0x%x, tgt_done = %d",
14712                     pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14713                     pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14714                     ptgt->tgt_d_id, ptgt->tgt_done);
14715 
14716                 mutex_enter(&ptgt->tgt_mutex);
14717 
14718                 if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14719                         rval = FCP_DEV_CHANGE;
14720                         if (do_finish_init && ptgt->tgt_done == 0) {
14721                                 ptgt->tgt_done++;
14722                                 finish_init = 1;
14723                         }
14724                 } else {
14725                         if (--ptgt->tgt_tmp_cnt <= 0) {
14726                                 ptgt->tgt_tmp_cnt = 0;
14727                                 finish_tgt = 1;
14728 
14729                                 if (do_finish_init) {
14730                                         finish_init = 1;
14731                                 }
14732                         }
14733                 }
14734                 mutex_exit(&ptgt->tgt_mutex);
14735         } else {
14736                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14737                     FCP_BUF_LEVEL_2, 0,
14738                     "Call Finish Init for NO target");
14739 
14740                 if (do_finish_init) {
14741                         finish_init = 1;
14742                 }
14743         }
14744 
14745         if (finish_tgt) {
14746                 ASSERT(ptgt != NULL);
14747 
14748                 mutex_enter(&ptgt->tgt_mutex);
14749 #ifdef  DEBUG
14750                 bzero(ptgt->tgt_tmp_cnt_stack,
14751                     sizeof (ptgt->tgt_tmp_cnt_stack));
14752 
14753                 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14754                     FCP_STACK_DEPTH);
14755 #endif /* DEBUG */
14756                 mutex_exit(&ptgt->tgt_mutex);
14757 
14758                 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14759         }
14760 
14761         if (finish_init && lcount == pptr->port_link_cnt) {
14762                 ASSERT(pptr->port_tmp_cnt > 0);
14763                 if (--pptr->port_tmp_cnt == 0) {
14764                         fcp_finish_init(pptr);
14765                 }
14766         } else if (lcount != pptr->port_link_cnt) {
14767                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
14768                     fcp_trace, FCP_BUF_LEVEL_2, 0,
14769                     "fcp_call_finish_init_held,1: state change occured"
14770                     " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14771         }
14772 
14773         return (rval);
14774 }
14775 
14776 static void
14777 fcp_reconfigure_luns(void * tgt_handle)
14778 {
14779         uint32_t                dev_cnt;
14780         fc_portmap_t            *devlist;
14781         struct fcp_tgt  *ptgt = (struct fcp_tgt *)tgt_handle;
14782         struct fcp_port         *pptr = ptgt->tgt_port;
14783 
14784         /*
14785          * If the timer that fires this off got canceled too late, the
14786          * target could have been destroyed.
14787          */
14788 
14789         if (ptgt->tgt_tid == NULL) {
14790                 return;
14791         }
14792 
14793         devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14794         if (devlist == NULL) {
14795                 fcp_log(CE_WARN, pptr->port_dip,
14796                     "!fcp%d: failed to allocate for portmap",
14797                     pptr->port_instance);
14798                 return;
14799         }
14800 
14801         dev_cnt = 1;
14802         devlist->map_pd = ptgt->tgt_pd_handle;
14803         devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14804         devlist->map_did.port_id = ptgt->tgt_d_id;
14805 
14806         bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14807         bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14808 
14809         devlist->map_state = PORT_DEVICE_LOGGED_IN;
14810         devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14811         devlist->map_flags = 0;
14812 
14813         fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14814             pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14815 
14816         /*
14817          * Clear the tgt_tid after no more references to
14818          * the fcp_tgt
14819          */
14820         mutex_enter(&ptgt->tgt_mutex);
14821         ptgt->tgt_tid = NULL;
14822         mutex_exit(&ptgt->tgt_mutex);
14823 
14824         kmem_free(devlist, sizeof (*devlist));
14825 }
14826 
14827 
14828 static void
14829 fcp_free_targets(struct fcp_port *pptr)
14830 {
14831         int                     i;
14832         struct fcp_tgt  *ptgt;
14833 
14834         mutex_enter(&pptr->port_mutex);
14835         for (i = 0; i < FCP_NUM_HASH; i++) {
14836                 ptgt = pptr->port_tgt_hash_table[i];
14837                 while (ptgt != NULL) {
14838                         struct fcp_tgt *next_tgt = ptgt->tgt_next;
14839 
14840                         fcp_free_target(ptgt);
14841                         ptgt = next_tgt;
14842                 }
14843         }
14844         mutex_exit(&pptr->port_mutex);
14845 }
14846 
14847 
14848 static void
14849 fcp_free_target(struct fcp_tgt *ptgt)
14850 {
14851         struct fcp_lun  *plun;
14852         timeout_id_t            tid;
14853 
14854         mutex_enter(&ptgt->tgt_mutex);
14855         tid = ptgt->tgt_tid;
14856 
14857         /*
14858          * Cancel any pending timeouts for this target.
14859          */
14860 
14861         if (tid != NULL) {
14862                 /*
14863                  * Set tgt_tid to NULL first to avoid a race in the callback.
14864                  * If tgt_tid is NULL, the callback will simply return.
14865                  */
14866                 ptgt->tgt_tid = NULL;
14867                 mutex_exit(&ptgt->tgt_mutex);
14868                 (void) untimeout(tid);
14869                 mutex_enter(&ptgt->tgt_mutex);
14870         }
14871 
14872         plun = ptgt->tgt_lun;
14873         while (plun != NULL) {
14874                 struct fcp_lun *next_lun = plun->lun_next;
14875 
14876                 fcp_dealloc_lun(plun);
14877                 plun = next_lun;
14878         }
14879 
14880         mutex_exit(&ptgt->tgt_mutex);
14881         fcp_dealloc_tgt(ptgt);
14882 }
14883 
14884 /*
14885  *     Function: fcp_is_retryable
14886  *
14887  *  Description: Indicates if the internal packet is retryable.
14888  *
14889  *     Argument: *icmd          FCP internal packet.
14890  *
14891  * Return Value: 0      Not retryable
14892  *               1      Retryable
14893  *
14894  *      Context: User, Kernel and Interrupt context
14895  */
14896 static int
14897 fcp_is_retryable(struct fcp_ipkt *icmd)
14898 {
14899         if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14900             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14901                 return (0);
14902         }
14903 
14904         return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14905             icmd->ipkt_port->port_deadline) ? 1 : 0);
14906 }
14907 
14908 /*
14909  *     Function: fcp_create_on_demand
14910  *
14911  *     Argument: *pptr          FCP port.
14912  *               *pwwn          Port WWN.
14913  *
14914  * Return Value: 0      Success
14915  *               EIO
14916  *               ENOMEM
14917  *               EBUSY
14918  *               EINVAL
14919  *
14920  *      Context: User and Kernel context
14921  */
14922 static int
14923 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14924 {
14925         int                     wait_ms;
14926         int                     tcount;
14927         int                     lcount;
14928         int                     ret;
14929         int                     error;
14930         int                     rval = EIO;
14931         int                     ntries;
14932         fc_portmap_t            *devlist;
14933         opaque_t                pd;
14934         struct fcp_lun          *plun;
14935         struct fcp_tgt          *ptgt;
14936         int                     old_manual = 0;
14937 
14938         /* Allocates the fc_portmap_t structure. */
14939         devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14940 
14941         /*
14942          * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14943          * in the commented statement below:
14944          *
14945          * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14946          *
14947          * Below, the deadline for the discovery process is set.
14948          */
14949         mutex_enter(&pptr->port_mutex);
14950         pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14951         mutex_exit(&pptr->port_mutex);
14952 
14953         /*
14954          * We try to find the remote port based on the WWN provided by the
14955          * caller.  We actually ask fp/fctl if it has it.
14956          */
14957         pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14958             (la_wwn_t *)pwwn, &error, 1);
14959 
14960         if (pd == NULL) {
14961                 kmem_free(devlist, sizeof (*devlist));
14962                 return (rval);
14963         }
14964 
14965         /*
14966          * The remote port was found.  We ask fp/fctl to update our
14967          * fc_portmap_t structure.
14968          */
14969         ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14970             (la_wwn_t *)pwwn, devlist);
14971         if (ret != FC_SUCCESS) {
14972                 kmem_free(devlist, sizeof (*devlist));
14973                 return (rval);
14974         }
14975 
14976         /*
14977          * The map flag field is set to indicates that the creation is being
14978          * done at the user request (Ioclt probably luxadm or cfgadm).
14979          */
14980         devlist->map_type = PORT_DEVICE_USER_CREATE;
14981 
14982         mutex_enter(&pptr->port_mutex);
14983 
14984         /*
14985          * We check to see if fcp already has a target that describes the
14986          * device being created.  If not it is created.
14987          */
14988         ptgt = fcp_lookup_target(pptr, pwwn);
14989         if (ptgt == NULL) {
14990                 lcount = pptr->port_link_cnt;
14991                 mutex_exit(&pptr->port_mutex);
14992 
14993                 ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14994                 if (ptgt == NULL) {
14995                         fcp_log(CE_WARN, pptr->port_dip,
14996                             "!FC target allocation failed");
14997                         return (ENOMEM);
14998                 }
14999 
15000                 mutex_enter(&pptr->port_mutex);
15001         }
15002 
15003         mutex_enter(&ptgt->tgt_mutex);
15004         ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15005         ptgt->tgt_tmp_cnt = 1;
15006         ptgt->tgt_device_created = 0;
15007         /*
15008          * If fabric and auto config is set but the target was
15009          * manually unconfigured then reset to the manual_config_only to
15010          * 0 so the device will get configured.
15011          */
15012         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15013             fcp_enable_auto_configuration &&
15014             ptgt->tgt_manual_config_only == 1) {
15015                 old_manual = 1;
15016                 ptgt->tgt_manual_config_only = 0;
15017         }
15018         mutex_exit(&ptgt->tgt_mutex);
15019 
15020         fcp_update_targets(pptr, devlist, 1,
15021             FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15022 
15023         lcount = pptr->port_link_cnt;
15024         tcount = ptgt->tgt_change_cnt;
15025 
15026         if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15027             tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15028                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15029                     fcp_enable_auto_configuration && old_manual) {
15030                         mutex_enter(&ptgt->tgt_mutex);
15031                         ptgt->tgt_manual_config_only = 1;
15032                         mutex_exit(&ptgt->tgt_mutex);
15033                 }
15034 
15035                 if (pptr->port_link_cnt != lcount ||
15036                     ptgt->tgt_change_cnt != tcount) {
15037                         rval = EBUSY;
15038                 }
15039                 mutex_exit(&pptr->port_mutex);
15040 
15041                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15042                     FCP_BUF_LEVEL_3, 0,
15043                     "fcp_create_on_demand: mapflags ptgt=%x, "
15044                     "lcount=%x::port_link_cnt=%x, "
15045                     "tcount=%x: tgt_change_cnt=%x, rval=%x",
15046                     ptgt, lcount, pptr->port_link_cnt,
15047                     tcount, ptgt->tgt_change_cnt, rval);
15048                 return (rval);
15049         }
15050 
15051         /*
15052          * Due to lack of synchronization mechanisms, we perform
15053          * periodic monitoring of our request; Because requests
15054          * get dropped when another one supercedes (either because
15055          * of a link change or a target change), it is difficult to
15056          * provide a clean synchronization mechanism (such as a
15057          * semaphore or a conditional variable) without exhaustively
15058          * rewriting the mainline discovery code of this driver.
15059          */
15060         wait_ms = 500;
15061 
15062         ntries = fcp_max_target_retries;
15063 
15064         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15065             FCP_BUF_LEVEL_3, 0,
15066             "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15067             "lcount=%x::port_link_cnt=%x, "
15068             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15069             "tgt_tmp_cnt =%x",
15070             ntries, ptgt, lcount, pptr->port_link_cnt,
15071             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15072             ptgt->tgt_tmp_cnt);
15073 
15074         mutex_enter(&ptgt->tgt_mutex);
15075         while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15076             ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15077                 mutex_exit(&ptgt->tgt_mutex);
15078                 mutex_exit(&pptr->port_mutex);
15079 
15080                 delay(drv_usectohz(wait_ms * 1000));
15081 
15082                 mutex_enter(&pptr->port_mutex);
15083                 mutex_enter(&ptgt->tgt_mutex);
15084         }
15085 
15086 
15087         if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15088                 rval = EBUSY;
15089         } else {
15090                 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15091                     FCP_TGT_NODE_PRESENT) {
15092                         rval = 0;
15093                 }
15094         }
15095 
15096         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15097             FCP_BUF_LEVEL_3, 0,
15098             "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15099             "lcount=%x::port_link_cnt=%x, "
15100             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15101             "tgt_tmp_cnt =%x",
15102             ntries, ptgt, lcount, pptr->port_link_cnt,
15103             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15104             ptgt->tgt_tmp_cnt);
15105 
15106         if (rval) {
15107                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15108                     fcp_enable_auto_configuration && old_manual) {
15109                         ptgt->tgt_manual_config_only = 1;
15110                 }
15111                 mutex_exit(&ptgt->tgt_mutex);
15112                 mutex_exit(&pptr->port_mutex);
15113                 kmem_free(devlist, sizeof (*devlist));
15114 
15115                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15116                     FCP_BUF_LEVEL_3, 0,
15117                     "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15118                     "lcount=%x::port_link_cnt=%x, "
15119                     "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15120                     "tgt_device_created=%x, tgt D_ID=%x",
15121                     ntries, ptgt, lcount, pptr->port_link_cnt,
15122                     tcount, ptgt->tgt_change_cnt, rval,
15123                     ptgt->tgt_device_created, ptgt->tgt_d_id);
15124                 return (rval);
15125         }
15126 
15127         if ((plun = ptgt->tgt_lun) != NULL) {
15128                 tcount = plun->lun_tgt->tgt_change_cnt;
15129         } else {
15130                 rval = EINVAL;
15131         }
15132         lcount = pptr->port_link_cnt;
15133 
15134         /*
15135          * Configuring the target with no LUNs will fail. We
15136          * should reset the node state so that it is not
15137          * automatically configured when the LUNs are added
15138          * to this target.
15139          */
15140         if (ptgt->tgt_lun_cnt == 0) {
15141                 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15142         }
15143         mutex_exit(&ptgt->tgt_mutex);
15144         mutex_exit(&pptr->port_mutex);
15145 
15146         while (plun) {
15147                 child_info_t    *cip;
15148 
15149                 mutex_enter(&plun->lun_mutex);
15150                 cip = plun->lun_cip;
15151                 mutex_exit(&plun->lun_mutex);
15152 
15153                 mutex_enter(&ptgt->tgt_mutex);
15154                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15155                         mutex_exit(&ptgt->tgt_mutex);
15156 
15157                         rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15158                             FCP_ONLINE, lcount, tcount,
15159                             NDI_ONLINE_ATTACH);
15160                         if (rval != NDI_SUCCESS) {
15161                                 FCP_TRACE(fcp_logq,
15162                                     pptr->port_instbuf, fcp_trace,
15163                                     FCP_BUF_LEVEL_3, 0,
15164                                     "fcp_create_on_demand: "
15165                                     "pass_to_hp_and_wait failed "
15166                                     "rval=%x", rval);
15167                                 rval = EIO;
15168                         } else {
15169                                 mutex_enter(&LUN_TGT->tgt_mutex);
15170                                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
15171                                     FCP_LUN_BUSY);
15172                                 mutex_exit(&LUN_TGT->tgt_mutex);
15173                         }
15174                         mutex_enter(&ptgt->tgt_mutex);
15175                 }
15176 
15177                 plun = plun->lun_next;
15178                 mutex_exit(&ptgt->tgt_mutex);
15179         }
15180 
15181         kmem_free(devlist, sizeof (*devlist));
15182 
15183         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15184             fcp_enable_auto_configuration && old_manual) {
15185                 mutex_enter(&ptgt->tgt_mutex);
15186                 /* if successful then set manual to 0 */
15187                 if (rval == 0) {
15188                         ptgt->tgt_manual_config_only = 0;
15189                 } else {
15190                         /* reset to 1 so the user has to do the config */
15191                         ptgt->tgt_manual_config_only = 1;
15192                 }
15193                 mutex_exit(&ptgt->tgt_mutex);
15194         }
15195 
15196         return (rval);
15197 }
15198 
15199 
15200 static void
15201 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15202 {
15203         int             count;
15204         uchar_t         byte;
15205 
15206         count = 0;
15207         while (*string) {
15208                 byte = FCP_ATOB(*string); string++;
15209                 byte = byte << 4 | FCP_ATOB(*string); string++;
15210                 bytes[count++] = byte;
15211 
15212                 if (count >= byte_len) {
15213                         break;
15214                 }
15215         }
15216 }
15217 
15218 static void
15219 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15220 {
15221         int             i;
15222 
15223         for (i = 0; i < FC_WWN_SIZE; i++) {
15224                 (void) sprintf(string + (i * 2),
15225                     "%02x", wwn[i]);
15226         }
15227 
15228 }
15229 
15230 static void
15231 fcp_print_error(fc_packet_t *fpkt)
15232 {
15233         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
15234             fpkt->pkt_ulp_private;
15235         struct fcp_port *pptr;
15236         struct fcp_tgt  *ptgt;
15237         struct fcp_lun  *plun;
15238         caddr_t                 buf;
15239         int                     scsi_cmd = 0;
15240 
15241         ptgt = icmd->ipkt_tgt;
15242         plun = icmd->ipkt_lun;
15243         pptr = ptgt->tgt_port;
15244 
15245         buf = kmem_zalloc(256, KM_NOSLEEP);
15246         if (buf == NULL) {
15247                 return;
15248         }
15249 
15250         switch (icmd->ipkt_opcode) {
15251         case SCMD_REPORT_LUN:
15252                 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15253                     " lun=0x%%x failed");
15254                 scsi_cmd++;
15255                 break;
15256 
15257         case SCMD_INQUIRY_PAGE83:
15258                 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15259                     " lun=0x%%x failed");
15260                 scsi_cmd++;
15261                 break;
15262 
15263         case SCMD_INQUIRY:
15264                 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15265                     " lun=0x%%x failed");
15266                 scsi_cmd++;
15267                 break;
15268 
15269         case LA_ELS_PLOGI:
15270                 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15271                 break;
15272 
15273         case LA_ELS_PRLI:
15274                 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15275                 break;
15276         }
15277 
15278         if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15279                 struct fcp_rsp          response, *rsp;
15280                 uchar_t                 asc, ascq;
15281                 caddr_t                 sense_key = NULL;
15282                 struct fcp_rsp_info     fcp_rsp_err, *bep;
15283 
15284                 if (icmd->ipkt_nodma) {
15285                         rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15286                         bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15287                             sizeof (struct fcp_rsp));
15288                 } else {
15289                         rsp = &response;
15290                         bep = &fcp_rsp_err;
15291 
15292                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15293                             sizeof (struct fcp_rsp));
15294 
15295                         FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15296                             bep, fpkt->pkt_resp_acc,
15297                             sizeof (struct fcp_rsp_info));
15298                 }
15299 
15300 
15301                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15302                         (void) sprintf(buf + strlen(buf),
15303                             " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15304                             " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15305                             " senselen=%%x. Giving up");
15306 
15307                         fcp_log(CE_WARN, pptr->port_dip, buf,
15308                             ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15309                             rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15310                             rsp->fcp_u.fcp_status.reserved_1,
15311                             rsp->fcp_response_len, rsp->fcp_sense_len);
15312 
15313                         kmem_free(buf, 256);
15314                         return;
15315                 }
15316 
15317                 if (rsp->fcp_u.fcp_status.rsp_len_set &&
15318                     bep->rsp_code != FCP_NO_FAILURE) {
15319                         (void) sprintf(buf + strlen(buf),
15320                             " FCP Response code = 0x%x", bep->rsp_code);
15321                 }
15322 
15323                 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15324                         struct scsi_extended_sense sense_info, *sense_ptr;
15325 
15326                         if (icmd->ipkt_nodma) {
15327                                 sense_ptr = (struct scsi_extended_sense *)
15328                                     ((caddr_t)fpkt->pkt_resp +
15329                                     sizeof (struct fcp_rsp) +
15330                                     rsp->fcp_response_len);
15331                         } else {
15332                                 sense_ptr = &sense_info;
15333 
15334                                 FCP_CP_IN(fpkt->pkt_resp +
15335                                     sizeof (struct fcp_rsp) +
15336                                     rsp->fcp_response_len, &sense_info,
15337                                     fpkt->pkt_resp_acc,
15338                                     sizeof (struct scsi_extended_sense));
15339                         }
15340 
15341                         if (sense_ptr->es_key < NUM_SENSE_KEYS +
15342                             NUM_IMPL_SENSE_KEYS) {
15343                                 sense_key = sense_keys[sense_ptr->es_key];
15344                         } else {
15345                                 sense_key = "Undefined";
15346                         }
15347 
15348                         asc = sense_ptr->es_add_code;
15349                         ascq = sense_ptr->es_qual_code;
15350 
15351                         (void) sprintf(buf + strlen(buf),
15352                             ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15353                             " Giving up");
15354 
15355                         fcp_log(CE_WARN, pptr->port_dip, buf,
15356                             ptgt->tgt_d_id, plun->lun_num, sense_key,
15357                             asc, ascq);
15358                 } else {
15359                         (void) sprintf(buf + strlen(buf),
15360                             " : SCSI status=%%x. Giving up");
15361 
15362                         fcp_log(CE_WARN, pptr->port_dip, buf,
15363                             ptgt->tgt_d_id, plun->lun_num,
15364                             rsp->fcp_u.fcp_status.scsi_status);
15365                 }
15366         } else {
15367                 caddr_t state, reason, action, expln;
15368 
15369                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
15370                     &action, &expln);
15371 
15372                 (void) sprintf(buf + strlen(buf), ": State:%%s,"
15373                     " Reason:%%s. Giving up");
15374 
15375                 if (scsi_cmd) {
15376                         fcp_log(CE_WARN, pptr->port_dip, buf,
15377                             ptgt->tgt_d_id, plun->lun_num, state, reason);
15378                 } else {
15379                         fcp_log(CE_WARN, pptr->port_dip, buf,
15380                             ptgt->tgt_d_id, state, reason);
15381                 }
15382         }
15383 
15384         kmem_free(buf, 256);
15385 }
15386 
15387 
15388 static int
15389 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15390     struct fcp_ipkt *icmd, int rval, caddr_t op)
15391 {
15392         int     ret = DDI_FAILURE;
15393         char    *error;
15394 
15395         switch (rval) {
15396         case FC_DEVICE_BUSY_NEW_RSCN:
15397                 /*
15398                  * This means that there was a new RSCN that the transport
15399                  * knows about (which the ULP *may* know about too) but the
15400                  * pkt that was sent down was related to an older RSCN. So, we
15401                  * are just going to reset the retry count and deadline and
15402                  * continue to retry. The idea is that transport is currently
15403                  * working on the new RSCN and will soon let the ULPs know
15404                  * about it and when it does the existing logic will kick in
15405                  * where it will change the tcount to indicate that something
15406                  * changed on the target. So, rediscovery will start and there
15407                  * will not be an infinite retry.
15408                  *
15409                  * For a full flow of how the RSCN info is transferred back and
15410                  * forth, see fp.c
15411                  */
15412                 icmd->ipkt_retries = 0;
15413                 icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15414                     FCP_ICMD_DEADLINE;
15415 
15416                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15417                     FCP_BUF_LEVEL_3, 0,
15418                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15419                     rval, ptgt->tgt_d_id);
15420                 /* FALLTHROUGH */
15421 
15422         case FC_STATEC_BUSY:
15423         case FC_DEVICE_BUSY:
15424         case FC_PBUSY:
15425         case FC_FBUSY:
15426         case FC_TRAN_BUSY:
15427         case FC_OFFLINE:
15428                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15429                     FCP_BUF_LEVEL_3, 0,
15430                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15431                     rval, ptgt->tgt_d_id);
15432                 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15433                     fcp_is_retryable(icmd)) {
15434                         fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15435                         ret = DDI_SUCCESS;
15436                 }
15437                 break;
15438 
15439         case FC_LOGINREQ:
15440                 /*
15441                  * FC_LOGINREQ used to be handled just like all the cases
15442                  * above. It has been changed to handled a PRLI that fails
15443                  * with FC_LOGINREQ different than other ipkts that fail
15444                  * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15445                  * a simple matter to turn it into a PLOGI instead, so that's
15446                  * exactly what we do here.
15447                  */
15448                 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15449                         ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15450                             icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15451                             icmd->ipkt_change_cnt, icmd->ipkt_cause);
15452                 } else {
15453                         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15454                             FCP_BUF_LEVEL_3, 0,
15455                             "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15456                             rval, ptgt->tgt_d_id);
15457                         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15458                             fcp_is_retryable(icmd)) {
15459                                 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15460                                 ret = DDI_SUCCESS;
15461                         }
15462                 }
15463                 break;
15464 
15465         default:
15466                 mutex_enter(&pptr->port_mutex);
15467                 mutex_enter(&ptgt->tgt_mutex);
15468                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15469                         mutex_exit(&ptgt->tgt_mutex);
15470                         mutex_exit(&pptr->port_mutex);
15471 
15472                         (void) fc_ulp_error(rval, &error);
15473                         fcp_log(CE_WARN, pptr->port_dip,
15474                             "!Failed to send %s to D_ID=%x error=%s",
15475                             op, ptgt->tgt_d_id, error);
15476                 } else {
15477                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
15478                             fcp_trace, FCP_BUF_LEVEL_2, 0,
15479                             "fcp_handle_ipkt_errors,1: state change occured"
15480                             " for D_ID=0x%x", ptgt->tgt_d_id);
15481                         mutex_exit(&ptgt->tgt_mutex);
15482                         mutex_exit(&pptr->port_mutex);
15483                 }
15484                 break;
15485         }
15486 
15487         return (ret);
15488 }
15489 
15490 
15491 /*
15492  * Check of outstanding commands on any LUN for this target
15493  */
15494 static int
15495 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15496 {
15497         struct  fcp_lun *plun;
15498         struct  fcp_pkt *cmd;
15499 
15500         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15501                 mutex_enter(&plun->lun_mutex);
15502                 for (cmd = plun->lun_pkt_head; cmd != NULL;
15503                     cmd = cmd->cmd_forw) {
15504                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
15505                                 mutex_exit(&plun->lun_mutex);
15506                                 return (FC_SUCCESS);
15507                         }
15508                 }
15509                 mutex_exit(&plun->lun_mutex);
15510         }
15511 
15512         return (FC_FAILURE);
15513 }
15514 
15515 static fc_portmap_t *
15516 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15517 {
15518         int                     i;
15519         fc_portmap_t            *devlist;
15520         fc_portmap_t            *devptr = NULL;
15521         struct fcp_tgt  *ptgt;
15522 
15523         mutex_enter(&pptr->port_mutex);
15524         for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15525                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15526                     ptgt = ptgt->tgt_next) {
15527                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15528                                 ++*dev_cnt;
15529                         }
15530                 }
15531         }
15532 
15533         devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15534             KM_NOSLEEP);
15535         if (devlist == NULL) {
15536                 mutex_exit(&pptr->port_mutex);
15537                 fcp_log(CE_WARN, pptr->port_dip,
15538                     "!fcp%d: failed to allocate for portmap for construct map",
15539                     pptr->port_instance);
15540                 return (devptr);
15541         }
15542 
15543         for (i = 0; i < FCP_NUM_HASH; i++) {
15544                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15545                     ptgt = ptgt->tgt_next) {
15546                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15547                                 int ret;
15548 
15549                                 ret = fc_ulp_pwwn_to_portmap(
15550                                     pptr->port_fp_handle,
15551                                     (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15552                                     devlist);
15553 
15554                                 if (ret == FC_SUCCESS) {
15555                                         devlist++;
15556                                         continue;
15557                                 }
15558 
15559                                 devlist->map_pd = NULL;
15560                                 devlist->map_did.port_id = ptgt->tgt_d_id;
15561                                 devlist->map_hard_addr.hard_addr =
15562                                     ptgt->tgt_hard_addr;
15563 
15564                                 devlist->map_state = PORT_DEVICE_INVALID;
15565                                 devlist->map_type = PORT_DEVICE_OLD;
15566 
15567                                 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15568                                     &devlist->map_nwwn, FC_WWN_SIZE);
15569 
15570                                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15571                                     &devlist->map_pwwn, FC_WWN_SIZE);
15572 
15573                                 devlist++;
15574                         }
15575                 }
15576         }
15577 
15578         mutex_exit(&pptr->port_mutex);
15579 
15580         return (devptr);
15581 }
15582 /*
15583  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15584  */
15585 static void
15586 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15587 {
15588         int i;
15589         struct fcp_tgt  *ptgt;
15590         struct fcp_lun  *plun;
15591 
15592         for (i = 0; i < FCP_NUM_HASH; i++) {
15593                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15594                     ptgt = ptgt->tgt_next) {
15595                         mutex_enter(&ptgt->tgt_mutex);
15596                         for (plun = ptgt->tgt_lun; plun != NULL;
15597                             plun = plun->lun_next) {
15598                                 if (plun->lun_mpxio &&
15599                                     plun->lun_state & FCP_LUN_BUSY) {
15600                                         if (!fcp_pass_to_hp(pptr, plun,
15601                                             plun->lun_cip,
15602                                             FCP_MPXIO_PATH_SET_BUSY,
15603                                             pptr->port_link_cnt,
15604                                             ptgt->tgt_change_cnt, 0, 0)) {
15605                                                 FCP_TRACE(fcp_logq,
15606                                                     pptr->port_instbuf,
15607                                                     fcp_trace,
15608                                                     FCP_BUF_LEVEL_2, 0,
15609                                                     "path_verifybusy: "
15610                                                     "disable lun %p failed!",
15611                                                     plun);
15612                                         }
15613                                 }
15614                         }
15615                         mutex_exit(&ptgt->tgt_mutex);
15616                 }
15617         }
15618 }
15619 
15620 static int
15621 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15622 {
15623         dev_info_t              *cdip = NULL;
15624         dev_info_t              *pdip = NULL;
15625 
15626         ASSERT(plun);
15627 
15628         mutex_enter(&plun->lun_mutex);
15629         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15630                 mutex_exit(&plun->lun_mutex);
15631                 return (NDI_FAILURE);
15632         }
15633         mutex_exit(&plun->lun_mutex);
15634         cdip = mdi_pi_get_client(PIP(cip));
15635         pdip = mdi_pi_get_phci(PIP(cip));
15636 
15637         ASSERT(cdip != NULL);
15638         ASSERT(pdip != NULL);
15639 
15640         if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15641                 /* LUN ready for IO */
15642                 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15643         } else {
15644                 /* LUN busy to accept IO */
15645                 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15646         }
15647         return (NDI_SUCCESS);
15648 }
15649 
15650 /*
15651  * Caller must free the returned string of MAXPATHLEN len
15652  * If the device is offline (-1 instance number) NULL
15653  * will be returned.
15654  */
15655 static char *
15656 fcp_get_lun_path(struct fcp_lun *plun) {
15657         dev_info_t      *dip = NULL;
15658         char            *path = NULL;
15659         mdi_pathinfo_t  *pip = NULL;
15660 
15661         if (plun == NULL) {
15662                 return (NULL);
15663         }
15664 
15665         mutex_enter(&plun->lun_mutex);
15666         if (plun->lun_mpxio == 0) {
15667                 dip = DIP(plun->lun_cip);
15668                 mutex_exit(&plun->lun_mutex);
15669         } else {
15670                 /*
15671                  * lun_cip must be accessed with lun_mutex held. Here
15672                  * plun->lun_cip either points to a valid node or it is NULL.
15673                  * Make a copy so that we can release lun_mutex.
15674                  */
15675                 pip = PIP(plun->lun_cip);
15676 
15677                 /*
15678                  * Increase ref count on the path so that we can release
15679                  * lun_mutex and still be sure that the pathinfo node (and thus
15680                  * also the client) is not deallocated. If pip is NULL, this
15681                  * has no effect.
15682                  */
15683                 mdi_hold_path(pip);
15684 
15685                 mutex_exit(&plun->lun_mutex);
15686 
15687                 /* Get the client. If pip is NULL, we get NULL. */
15688                 dip = mdi_pi_get_client(pip);
15689         }
15690 
15691         if (dip == NULL)
15692                 goto out;
15693         if (ddi_get_instance(dip) < 0)
15694                 goto out;
15695 
15696         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15697         if (path == NULL)
15698                 goto out;
15699 
15700         (void) ddi_pathname(dip, path);
15701 
15702         /* Clean up. */
15703 out:
15704         if (pip != NULL)
15705                 mdi_rele_path(pip);
15706 
15707         /*
15708          * In reality, the user wants a fully valid path (one they can open)
15709          * but this string is lacking the mount point, and the minor node.
15710          * It would be nice if we could "figure these out" somehow
15711          * and fill them in.  Otherwise, the userland code has to understand
15712          * driver specific details of which minor node is the "best" or
15713          * "right" one to expose.  (Ex: which slice is the whole disk, or
15714          * which tape doesn't rewind)
15715          */
15716         return (path);
15717 }
15718 
15719 static int
15720 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15721     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15722 {
15723         int64_t reset_delay;
15724         int rval, retry = 0;
15725         struct fcp_port *pptr = fcp_dip2port(parent);
15726 
15727         reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15728             (ddi_get_lbolt64() - pptr->port_attach_time);
15729         if (reset_delay < 0) {
15730                 reset_delay = 0;
15731         }
15732 
15733         if (fcp_bus_config_debug) {
15734                 flag |= NDI_DEVI_DEBUG;
15735         }
15736 
15737         switch (op) {
15738         case BUS_CONFIG_ONE:
15739                 /*
15740                  * Retry the command since we need to ensure
15741                  * the fabric devices are available for root
15742                  */
15743                 while (retry++ < fcp_max_bus_config_retries) {
15744                         rval =  (ndi_busop_bus_config(parent,
15745                             flag | NDI_MDI_FALLBACK, op,
15746                             arg, childp, (clock_t)reset_delay));
15747                         if (rval == 0) {
15748                                 return (rval);
15749                         }
15750                 }
15751 
15752                 /*
15753                  * drain taskq to make sure nodes are created and then
15754                  * try again.
15755                  */
15756                 taskq_wait(DEVI(parent)->devi_taskq);
15757                 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15758                     op, arg, childp, 0));
15759 
15760         case BUS_CONFIG_DRIVER:
15761         case BUS_CONFIG_ALL: {
15762                 /*
15763                  * delay till all devices report in (port_tmp_cnt == 0)
15764                  * or FCP_INIT_WAIT_TIMEOUT
15765                  */
15766                 mutex_enter(&pptr->port_mutex);
15767                 while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15768                         (void) cv_timedwait(&pptr->port_config_cv,
15769                             &pptr->port_mutex,
15770                             ddi_get_lbolt() + (clock_t)reset_delay);
15771                         reset_delay =
15772                             (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15773                             (ddi_get_lbolt64() - pptr->port_attach_time);
15774                 }
15775                 mutex_exit(&pptr->port_mutex);
15776                 /* drain taskq to make sure nodes are created */
15777                 taskq_wait(DEVI(parent)->devi_taskq);
15778                 return (ndi_busop_bus_config(parent, flag, op,
15779                     arg, childp, 0));
15780         }
15781 
15782         default:
15783                 return (NDI_FAILURE);
15784         }
15785         /*NOTREACHED*/
15786 }
15787 
15788 static int
15789 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15790     ddi_bus_config_op_t op, void *arg)
15791 {
15792         if (fcp_bus_config_debug) {
15793                 flag |= NDI_DEVI_DEBUG;
15794         }
15795 
15796         return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15797 }
15798 
15799 
15800 /*
15801  * Routine to copy GUID into the lun structure.
15802  * returns 0 if copy was successful and 1 if encountered a
15803  * failure and did not copy the guid.
15804  */
15805 static int
15806 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15807 {
15808 
15809         int retval = 0;
15810 
15811         /* add one for the null terminator */
15812         const unsigned int len = strlen(guidp) + 1;
15813 
15814         if ((guidp == NULL) || (plun == NULL)) {
15815                 return (1);
15816         }
15817 
15818         /*
15819          * if the plun->lun_guid already has been allocated,
15820          * then check the size. if the size is exact, reuse
15821          * it....if not free it an allocate the required size.
15822          * The reallocation should NOT typically happen
15823          * unless the GUIDs reported changes between passes.
15824          * We free up and alloc again even if the
15825          * size was more than required. This is due to the
15826          * fact that the field lun_guid_size - serves
15827          * dual role of indicating the size of the wwn
15828          * size and ALSO the allocation size.
15829          */
15830         if (plun->lun_guid) {
15831                 if (plun->lun_guid_size != len) {
15832                         /*
15833                          * free the allocated memory and
15834                          * initialize the field
15835                          * lun_guid_size to 0.
15836                          */
15837                         kmem_free(plun->lun_guid, plun->lun_guid_size);
15838                         plun->lun_guid = NULL;
15839                         plun->lun_guid_size = 0;
15840                 }
15841         }
15842         /*
15843          * alloc only if not already done.
15844          */
15845         if (plun->lun_guid == NULL) {
15846                 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15847                 if (plun->lun_guid == NULL) {
15848                         cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15849                             "Unable to allocate"
15850                             "Memory for GUID!!! size %d", len);
15851                         retval = 1;
15852                 } else {
15853                         plun->lun_guid_size = len;
15854                 }
15855         }
15856         if (plun->lun_guid) {
15857                 /*
15858                  * now copy the GUID
15859                  */
15860                 bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15861         }
15862         return (retval);
15863 }
15864 
15865 /*
15866  * fcp_reconfig_wait
15867  *
15868  * Wait for a rediscovery/reconfiguration to complete before continuing.
15869  */
15870 
15871 static void
15872 fcp_reconfig_wait(struct fcp_port *pptr)
15873 {
15874         clock_t         reconfig_start, wait_timeout;
15875 
15876         /*
15877          * Quick check.  If pptr->port_tmp_cnt is 0, there is no
15878          * reconfiguration in progress.
15879          */
15880 
15881         mutex_enter(&pptr->port_mutex);
15882         if (pptr->port_tmp_cnt == 0) {
15883                 mutex_exit(&pptr->port_mutex);
15884                 return;
15885         }
15886         mutex_exit(&pptr->port_mutex);
15887 
15888         /*
15889          * If we cause a reconfig by raising power, delay until all devices
15890          * report in (port_tmp_cnt returns to 0)
15891          */
15892 
15893         reconfig_start = ddi_get_lbolt();
15894         wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15895 
15896         mutex_enter(&pptr->port_mutex);
15897 
15898         while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15899             pptr->port_tmp_cnt) {
15900 
15901                 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15902                     reconfig_start + wait_timeout);
15903         }
15904 
15905         mutex_exit(&pptr->port_mutex);
15906 
15907         /*
15908          * Even if fcp_tmp_count isn't 0, continue without error.  The port
15909          * we want may still be ok.  If not, it will error out later
15910          */
15911 }
15912 
15913 /*
15914  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15915  * We rely on the fcp_global_mutex to provide protection against changes to
15916  * the fcp_lun_blacklist.
15917  *
15918  * You can describe a list of target port WWNs and LUN numbers which will
15919  * not be configured. LUN numbers will be interpreted as decimal. White
15920  * spaces and ',' can be used in the list of LUN numbers.
15921  *
15922  * To prevent LUNs 1 and 2 from being configured for target
15923  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15924  *
15925  * pwwn-lun-blacklist=
15926  * "510000f010fd92a1,1,2",
15927  * "510000e012079df1,1,2";
15928  */
15929 static void
15930 fcp_read_blacklist(dev_info_t *dip,
15931     struct fcp_black_list_entry **pplun_blacklist) {
15932         char **prop_array       = NULL;
15933         char *curr_pwwn         = NULL;
15934         char *curr_lun          = NULL;
15935         uint32_t prop_item      = 0;
15936         int idx                 = 0;
15937         int len                 = 0;
15938 
15939         ASSERT(mutex_owned(&fcp_global_mutex));
15940         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15941             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15942             LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15943                 return;
15944         }
15945 
15946         for (idx = 0; idx < prop_item; idx++) {
15947 
15948                 curr_pwwn = prop_array[idx];
15949                 while (*curr_pwwn == ' ') {
15950                         curr_pwwn++;
15951                 }
15952                 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15953                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15954                             ", please check.", curr_pwwn);
15955                         continue;
15956                 }
15957                 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15958                     (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15959                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15960                             ", please check.", curr_pwwn);
15961                         continue;
15962                 }
15963                 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15964                         if (isxdigit(curr_pwwn[len]) != TRUE) {
15965                                 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15966                                     "blacklist, please check.", curr_pwwn);
15967                                 break;
15968                         }
15969                 }
15970                 if (len != sizeof (la_wwn_t) * 2) {
15971                         continue;
15972                 }
15973 
15974                 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15975                 *(curr_lun - 1) = '\0';
15976                 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15977         }
15978 
15979         ddi_prop_free(prop_array);
15980 }
15981 
15982 /*
15983  * Get the masking info about one remote target port designated by wwn.
15984  * Lun ids could be separated by ',' or white spaces.
15985  */
15986 static void
15987 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15988     struct fcp_black_list_entry **pplun_blacklist) {
15989         int             idx                     = 0;
15990         uint32_t        offset                  = 0;
15991         unsigned long   lun_id                  = 0;
15992         char            lunid_buf[16];
15993         char            *pend                   = NULL;
15994         int             illegal_digit           = 0;
15995 
15996         while (offset < strlen(curr_lun)) {
15997                 while ((curr_lun[offset + idx] != ',') &&
15998                     (curr_lun[offset + idx] != '\0') &&
15999                     (curr_lun[offset + idx] != ' ')) {
16000                         if (isdigit(curr_lun[offset + idx]) == 0) {
16001                                 illegal_digit++;
16002                         }
16003                         idx++;
16004                 }
16005                 if (illegal_digit > 0) {
16006                         offset += (idx+1);      /* To the start of next lun */
16007                         idx = 0;
16008                         illegal_digit = 0;
16009                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16010                             "the blacklist, please check digits.",
16011                             curr_lun, curr_pwwn);
16012                         continue;
16013                 }
16014                 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16015                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16016                             "the blacklist, please check the length of LUN#.",
16017                             curr_lun, curr_pwwn);
16018                         break;
16019                 }
16020                 if (idx == 0) { /* ignore ' ' or ',' or '\0' */
16021                     offset++;
16022                     continue;
16023                 }
16024 
16025                 bcopy(curr_lun + offset, lunid_buf, idx);
16026                 lunid_buf[idx] = '\0';
16027                 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16028                         fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16029                 } else {
16030                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16031                             "the blacklist, please check %s.",
16032                             curr_lun, curr_pwwn, lunid_buf);
16033                 }
16034                 offset += (idx+1);      /* To the start of next lun */
16035                 idx = 0;
16036         }
16037 }
16038 
16039 /*
16040  * Add one masking record
16041  */
16042 static void
16043 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16044     struct fcp_black_list_entry **pplun_blacklist) {
16045         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16046         struct fcp_black_list_entry     *new_entry      = NULL;
16047         la_wwn_t                        wwn;
16048 
16049         fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16050         while (tmp_entry) {
16051                 if ((bcmp(&tmp_entry->wwn, &wwn,
16052                     sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16053                         return;
16054                 }
16055 
16056                 tmp_entry = tmp_entry->next;
16057         }
16058 
16059         /* add to black list */
16060         new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16061             (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16062         bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16063         new_entry->lun = lun_id;
16064         new_entry->masked = 0;
16065         new_entry->next = *pplun_blacklist;
16066         *pplun_blacklist = new_entry;
16067 }
16068 
16069 /*
16070  * Check if we should mask the specified lun of this fcp_tgt
16071  */
16072 static int
16073 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16074         struct fcp_black_list_entry *remote_port;
16075 
16076         remote_port = fcp_lun_blacklist;
16077         while (remote_port != NULL) {
16078                 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16079                         if (remote_port->lun == lun_id) {
16080                                 remote_port->masked++;
16081                                 if (remote_port->masked == 1) {
16082                                         fcp_log(CE_NOTE, NULL, "LUN %d of port "
16083                                             "%02x%02x%02x%02x%02x%02x%02x%02x "
16084                                             "is masked due to black listing.\n",
16085                                             lun_id, wwn->raw_wwn[0],
16086                                             wwn->raw_wwn[1], wwn->raw_wwn[2],
16087                                             wwn->raw_wwn[3], wwn->raw_wwn[4],
16088                                             wwn->raw_wwn[5], wwn->raw_wwn[6],
16089                                             wwn->raw_wwn[7]);
16090                                 }
16091                                 return (TRUE);
16092                         }
16093                 }
16094                 remote_port = remote_port->next;
16095         }
16096         return (FALSE);
16097 }
16098 
16099 /*
16100  * Release all allocated resources
16101  */
16102 static void
16103 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16104         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16105         struct fcp_black_list_entry     *current_entry  = NULL;
16106 
16107         ASSERT(mutex_owned(&fcp_global_mutex));
16108         /*
16109          * Traverse all luns
16110          */
16111         while (tmp_entry) {
16112                 current_entry = tmp_entry;
16113                 tmp_entry = tmp_entry->next;
16114                 kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16115         }
16116         *pplun_blacklist = NULL;
16117 }
16118 
16119 /*
16120  * In fcp module,
16121  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16122  */
16123 static struct scsi_pkt *
16124 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16125     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16126     int flags, int (*callback)(), caddr_t arg)
16127 {
16128         fcp_port_t      *pptr = ADDR2FCP(ap);
16129         fcp_pkt_t       *cmd  = NULL;
16130         fc_frame_hdr_t  *hp;
16131 
16132         /*
16133          * First step: get the packet
16134          */
16135         if (pkt == NULL) {
16136                 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16137                     tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16138                     callback, arg);
16139                 if (pkt == NULL) {
16140                         return (NULL);
16141                 }
16142 
16143                 /*
16144                  * All fields in scsi_pkt will be initialized properly or
16145                  * set to zero. We need do nothing for scsi_pkt.
16146                  */
16147                 /*
16148                  * But it's our responsibility to link other related data
16149                  * structures. Their initialization will be done, just
16150                  * before the scsi_pkt will be sent to FCA.
16151                  */
16152                 cmd             = PKT2CMD(pkt);
16153                 cmd->cmd_pkt = pkt;
16154                 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16155                 /*
16156                  * fc_packet_t
16157                  */
16158                 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16159                 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16160                     sizeof (struct fcp_pkt));
16161                 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16162                 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16163                 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16164                 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16165                 /*
16166                  * Fill in the Fabric Channel Header
16167                  */
16168                 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16169                 hp->r_ctl = R_CTL_COMMAND;
16170                 hp->rsvd = 0;
16171                 hp->type = FC_TYPE_SCSI_FCP;
16172                 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16173                 hp->seq_id = 0;
16174                 hp->df_ctl  = 0;
16175                 hp->seq_cnt = 0;
16176                 hp->ox_id = 0xffff;
16177                 hp->rx_id = 0xffff;
16178                 hp->ro = 0;
16179         } else {
16180                 /*
16181                  * We need think if we should reset any elements in
16182                  * related data structures.
16183                  */
16184                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
16185                     fcp_trace, FCP_BUF_LEVEL_6, 0,
16186                     "reusing pkt, flags %d", flags);
16187                 cmd = PKT2CMD(pkt);
16188                 if (cmd->cmd_fp_pkt->pkt_pd) {
16189                         cmd->cmd_fp_pkt->pkt_pd = NULL;
16190                 }
16191         }
16192 
16193         /*
16194          * Second step:  dma allocation/move
16195          */
16196         if (bp && bp->b_bcount != 0) {
16197                 /*
16198                  * Mark if it's read or write
16199                  */
16200                 if (bp->b_flags & B_READ) {
16201                         cmd->cmd_flags |= CFLAG_IS_READ;
16202                 } else {
16203                         cmd->cmd_flags &= ~CFLAG_IS_READ;
16204                 }
16205 
16206                 bp_mapin(bp);
16207                 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16208                 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16209                 cmd->cmd_fp_pkt->pkt_data_resid = 0;
16210         } else {
16211                 /*
16212                  * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16213                  * to send zero-length read/write.
16214                  */
16215                 cmd->cmd_fp_pkt->pkt_data = NULL;
16216                 cmd->cmd_fp_pkt->pkt_datalen = 0;
16217         }
16218 
16219         return (pkt);
16220 }
16221 
16222 static void
16223 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16224 {
16225         fcp_port_t      *pptr = ADDR2FCP(ap);
16226 
16227         /*
16228          * First we let FCA to uninitilize private part.
16229          */
16230         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16231             PKT2CMD(pkt)->cmd_fp_pkt);
16232 
16233         /*
16234          * Then we uninitialize fc_packet.
16235          */
16236 
16237         /*
16238          * Thirdly, we uninitializae fcp_pkt.
16239          */
16240 
16241         /*
16242          * In the end, we free scsi_pkt.
16243          */
16244         scsi_hba_pkt_free(ap, pkt);
16245 }
16246 
16247 static int
16248 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16249 {
16250         fcp_port_t      *pptr = ADDR2FCP(ap);
16251         fcp_lun_t       *plun = ADDR2LUN(ap);
16252         fcp_tgt_t       *ptgt = plun->lun_tgt;
16253         fcp_pkt_t       *cmd  = PKT2CMD(pkt);
16254         fcp_cmd_t       *fcmd = &cmd->cmd_fcp_cmd;
16255         fc_packet_t     *fpkt = cmd->cmd_fp_pkt;
16256         int              rval;
16257 
16258         fpkt->pkt_pd = ptgt->tgt_pd_handle;
16259         (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16260 
16261         /*
16262          * Firstly, we need initialize fcp_pkt_t
16263          * Secondly, we need initialize fcp_cmd_t.
16264          */
16265         bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16266         fcmd->fcp_data_len = fpkt->pkt_datalen;
16267         fcmd->fcp_ent_addr = plun->lun_addr;
16268         if (pkt->pkt_flags & FLAG_HTAG) {
16269                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16270         } else if (pkt->pkt_flags & FLAG_OTAG) {
16271                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16272         } else if (pkt->pkt_flags & FLAG_STAG) {
16273                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16274         } else {
16275                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16276         }
16277 
16278         if (cmd->cmd_flags & CFLAG_IS_READ) {
16279                 fcmd->fcp_cntl.cntl_read_data = 1;
16280                 fcmd->fcp_cntl.cntl_write_data = 0;
16281         } else {
16282                 fcmd->fcp_cntl.cntl_read_data = 0;
16283                 fcmd->fcp_cntl.cntl_write_data = 1;
16284         }
16285 
16286         /*
16287          * Then we need initialize fc_packet_t too.
16288          */
16289         fpkt->pkt_timeout = pkt->pkt_time + 2;
16290         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16291         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16292         if (cmd->cmd_flags & CFLAG_IS_READ) {
16293                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16294         } else {
16295                 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16296         }
16297 
16298         if (pkt->pkt_flags & FLAG_NOINTR) {
16299                 fpkt->pkt_comp = NULL;
16300                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16301         } else {
16302                 fpkt->pkt_comp = fcp_cmd_callback;
16303                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16304                 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16305                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16306                 }
16307         }
16308 
16309         /*
16310          * Lastly, we need initialize scsi_pkt
16311          */
16312         pkt->pkt_reason = CMD_CMPLT;
16313         pkt->pkt_state = 0;
16314         pkt->pkt_statistics = 0;
16315         pkt->pkt_resid = 0;
16316 
16317         /*
16318          * if interrupts aren't allowed (e.g. at dump time) then we'll
16319          * have to do polled I/O
16320          */
16321         if (pkt->pkt_flags & FLAG_NOINTR) {
16322                 return (fcp_dopoll(pptr, cmd));
16323         }
16324 
16325         cmd->cmd_state = FCP_PKT_ISSUED;
16326         rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16327         if (rval == FC_SUCCESS) {
16328                 return (TRAN_ACCEPT);
16329         }
16330 
16331         /*
16332          * Need more consideration
16333          *
16334          * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16335          */
16336         cmd->cmd_state = FCP_PKT_IDLE;
16337         if (rval == FC_TRAN_BUSY) {
16338                 return (TRAN_BUSY);
16339         } else {
16340                 return (TRAN_FATAL_ERROR);
16341         }
16342 }
16343 
16344 /*
16345  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16346  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16347  */
16348 static void
16349 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16350 {
16351         FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16352             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16353 }
16354 
16355 /*
16356  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16357  */
16358 static void
16359 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16360 {
16361         FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16362             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16363 }