XXXX introduce drv_sectohz

   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_sectohz(1));
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_sectohz(1));
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_sectohz(1));
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 = drv_sectohz(fcp_watchdog_timeout);

10011                 fcp_watchdog_id = timeout(fcp_watch, NULL,
10012                     fcp_watchdog_tick);
10013         }
10014         mutex_exit(&fcp_global_mutex);
10015 
10016         /*
10017          * Here an attempt is made to register with the name server, the new
10018          * FCP capability.  That is done using an RTF_ID to the name server.
10019          * It is done synchronously.  The function fcp_do_ns_registry()
10020          * doesn't return till the name server responded.
10021          * On failures, just ignore it for now and it will get retried during
10022          * state change callbacks. We'll set a flag to show this failure
10023          */
10024         if (fcp_do_ns_registry(pptr, s_id)) {
10025                 mutex_enter(&pptr->port_mutex);
10026                 pptr->port_state |= FCP_STATE_NS_REG_FAILED;
10027                 mutex_exit(&pptr->port_mutex);
10028         } else {
10029                 mutex_enter(&pptr->port_mutex);
10030                 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED);
10031                 mutex_exit(&pptr->port_mutex);
10032         }
10033 
10034         /*
10035          * Lookup for boot WWN property
10036          */
10037         if (modrootloaded != 1) {
10038                 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
10039                     ddi_get_parent(pinfo->port_dip),
10040                     DDI_PROP_DONTPASS, OBP_BOOT_WWN,
10041                     &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) &&
10042                     (nbytes == FC_WWN_SIZE)) {
10043                         bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE);
10044                 }
10045                 if (boot_wwn) {
10046                         ddi_prop_free(boot_wwn);
10047                 }
10048         }
10049 
10050         /*
10051          * Handle various topologies and link states.
10052          */
10053         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
10054         case FC_STATE_OFFLINE:
10055 
10056                 /*
10057                  * we're attaching a port where the link is offline
10058                  *
10059                  * Wait for ONLINE, at which time a state
10060                  * change will cause a statec_callback
10061                  *
10062                  * in the mean time, do not do anything
10063                  */
10064                 res = DDI_SUCCESS;
10065                 pptr->port_state |= FCP_STATE_OFFLINE;
10066                 break;
10067 
10068         case FC_STATE_ONLINE: {
10069                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
10070                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
10071                         res = DDI_SUCCESS;
10072                         break;
10073                 }
10074                 /*
10075                  * discover devices and create nodes (a private
10076                  * loop or point-to-point)
10077                  */
10078                 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
10079 
10080                 /*
10081                  * At this point we are going to build a list of all the ports
10082                  * that can be reached through this local port.  It looks like
10083                  * we cannot handle more than FCP_MAX_DEVICES per local port
10084                  * (128).
10085                  */
10086                 if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
10087                     sizeof (fc_portmap_t) * FCP_MAX_DEVICES,
10088                     KM_NOSLEEP)) == NULL) {
10089                         fcp_log(CE_WARN, pptr->port_dip,
10090                             "!fcp%d: failed to allocate portmap",
10091                             instance);
10092                         goto fail;
10093                 }
10094 
10095                 /*
10096                  * fc_ulp_getportmap() is going to provide us with the list of
10097                  * remote ports in the buffer we just allocated.  The way the
10098                  * list is going to be retrieved depends on the topology.
10099                  * However, if we are connected to a Fabric, a name server
10100                  * request may be sent to get the list of FCP capable ports.
10101                  * It should be noted that is the case the request is
10102                  * synchronous.  This means we are stuck here till the name
10103                  * server replies.  A lot of things can change during that time
10104                  * and including, may be, being called on
10105                  * fcp_statec_callback() for different reasons. I'm not sure
10106                  * the code can handle that.
10107                  */
10108                 max_cnt = FCP_MAX_DEVICES;
10109                 alloc_cnt = FCP_MAX_DEVICES;
10110                 if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
10111                     &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
10112                     FC_SUCCESS) {
10113                         caddr_t msg;
10114 
10115                         (void) fc_ulp_error(res, &msg);
10116 
10117                         /*
10118                          * this  just means the transport is
10119                          * busy perhaps building a portmap so,
10120                          * for now, succeed this port attach
10121                          * when the transport has a new map,
10122                          * it'll send us a state change then
10123                          */
10124                         fcp_log(CE_WARN, pptr->port_dip,
10125                             "!failed to get port map : %s", msg);
10126 
10127                         res = DDI_SUCCESS;
10128                         break;  /* go return result */
10129                 }
10130                 if (max_cnt > alloc_cnt) {
10131                         alloc_cnt = max_cnt;
10132                 }
10133 
10134                 /*
10135                  * We are now going to call fcp_statec_callback() ourselves.
10136                  * By issuing this call we are trying to kick off the enumera-
10137                  * tion process.
10138                  */
10139                 /*
10140                  * let the state change callback do the SCSI device
10141                  * discovery and create the devinfos
10142                  */
10143                 fcp_statec_callback(ulph, pptr->port_fp_handle,
10144                     pptr->port_phys_state, pptr->port_topology, tmp_list,
10145                     max_cnt, pptr->port_id);
10146 
10147                 res = DDI_SUCCESS;
10148                 break;
10149         }
10150 
10151         default:
10152                 /* unknown port state */
10153                 fcp_log(CE_WARN, pptr->port_dip,
10154                     "!fcp%d: invalid port state at attach=0x%x",
10155                     instance, pptr->port_phys_state);
10156 
10157                 mutex_enter(&pptr->port_mutex);
10158                 pptr->port_phys_state = FCP_STATE_OFFLINE;
10159                 mutex_exit(&pptr->port_mutex);
10160 
10161                 res = DDI_SUCCESS;
10162                 break;
10163         }
10164 
10165         /* free temp list if used */
10166         if (tmp_list != NULL) {
10167                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10168         }
10169 
10170         /* note the attach time */
10171         pptr->port_attach_time = ddi_get_lbolt64();
10172 
10173         /* all done */
10174         return (res);
10175 
10176         /* a failure we have to clean up after */
10177 fail:
10178         fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port");
10179 
10180         if (soft_state_linked) {
10181                 /* remove this fcp_port from the linked list */
10182                 (void) fcp_soft_state_unlink(pptr);
10183         }
10184 
10185         /* unbind and free event set */
10186         if (pptr->port_ndi_event_hdl) {
10187                 if (event_bind) {
10188                         (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10189                             &pptr->port_ndi_events, NDI_SLEEP);
10190                 }
10191                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10192         }
10193 
10194         if (pptr->port_ndi_event_defs) {
10195                 (void) kmem_free(pptr->port_ndi_event_defs,
10196                     sizeof (fcp_ndi_event_defs));
10197         }
10198 
10199         /*
10200          * Clean up mpxio stuff
10201          */
10202         if (pptr->port_mpxio) {
10203                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10204                 pptr->port_mpxio--;
10205         }
10206 
10207         /* undo SCSI HBA setup */
10208         if (hba_attached) {
10209                 (void) scsi_hba_detach(pptr->port_dip);
10210         }
10211         if (pptr->port_tran != NULL) {
10212                 scsi_hba_tran_free(pptr->port_tran);
10213         }
10214 
10215         mutex_enter(&fcp_global_mutex);
10216 
10217         /*
10218          * We check soft_state_linked, because it is incremented right before
10219          * we call increment fcp_watchdog_init.  Therefore, we know if
10220          * soft_state_linked is still FALSE, we do not want to decrement
10221          * fcp_watchdog_init or possibly call untimeout.
10222          */
10223 
10224         if (soft_state_linked) {
10225                 if (--fcp_watchdog_init == 0) {
10226                         timeout_id_t    tid = fcp_watchdog_id;
10227 
10228                         mutex_exit(&fcp_global_mutex);
10229                         (void) untimeout(tid);
10230                 } else {
10231                         mutex_exit(&fcp_global_mutex);
10232                 }
10233         } else {
10234                 mutex_exit(&fcp_global_mutex);
10235         }
10236 
10237         if (mutex_initted) {
10238                 mutex_destroy(&pptr->port_mutex);
10239                 mutex_destroy(&pptr->port_pkt_mutex);
10240         }
10241 
10242         if (tmp_list != NULL) {
10243                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
10244         }
10245 
10246         /* this makes pptr invalid */
10247         ddi_soft_state_free(fcp_softstate, instance);
10248 
10249         return (DDI_FAILURE);
10250 }
10251 
10252 
10253 static int
10254 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance)
10255 {
10256         int count = 0;
10257 
10258         mutex_enter(&pptr->port_mutex);
10259 
10260         /*
10261          * if the port is powered down or suspended, nothing else
10262          * to do; just return.
10263          */
10264         if (flag != FCP_STATE_DETACHING) {
10265                 if (pptr->port_state & (FCP_STATE_POWER_DOWN |
10266                     FCP_STATE_SUSPENDED)) {
10267                         pptr->port_state |= flag;
10268                         mutex_exit(&pptr->port_mutex);
10269                         return (FC_SUCCESS);
10270                 }
10271         }
10272 
10273         if (pptr->port_state & FCP_STATE_IN_MDI) {
10274                 mutex_exit(&pptr->port_mutex);
10275                 return (FC_FAILURE);
10276         }
10277 
10278         FCP_TRACE(fcp_logq, pptr->port_instbuf,
10279             fcp_trace, FCP_BUF_LEVEL_2, 0,
10280             "fcp_handle_port_detach: port is detaching");
10281 
10282         pptr->port_state |= flag;
10283 
10284         /*
10285          * Wait for any ongoing reconfig/ipkt to complete, that
10286          * ensures the freeing to targets/luns is safe.
10287          * No more ref to this port should happen from statec/ioctl
10288          * after that as it was removed from the global port list.
10289          */
10290         while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10291             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10292                 /*
10293                  * Let's give sufficient time for reconfig/ipkt
10294                  * to complete.
10295                  */
10296                 if (count++ >= FCP_ICMD_DEADLINE) {
10297                         break;
10298                 }
10299                 mutex_exit(&pptr->port_mutex);
10300                 delay(drv_sectohz(1));
10301                 mutex_enter(&pptr->port_mutex);
10302         }
10303 
10304         /*
10305          * if the driver is still busy then fail to
10306          * suspend/power down.
10307          */
10308         if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt ||
10309             (pptr->port_state & FCP_STATE_IN_WATCHDOG)) {
10310                 pptr->port_state &= ~flag;
10311                 mutex_exit(&pptr->port_mutex);
10312                 return (FC_FAILURE);
10313         }
10314 
10315         if (flag == FCP_STATE_DETACHING) {
10316                 pptr = fcp_soft_state_unlink(pptr);
10317                 ASSERT(pptr != NULL);
10318         }
10319 
10320         pptr->port_link_cnt++;
10321         pptr->port_state |= FCP_STATE_OFFLINE;
10322         pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE);
10323 
10324         fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK),
10325             FCP_CAUSE_LINK_DOWN);
10326         mutex_exit(&pptr->port_mutex);
10327 
10328         /* kill watch dog timer if we're the last */
10329         mutex_enter(&fcp_global_mutex);
10330         if (--fcp_watchdog_init == 0) {
10331                 timeout_id_t    tid = fcp_watchdog_id;
10332                 mutex_exit(&fcp_global_mutex);
10333                 (void) untimeout(tid);
10334         } else {
10335                 mutex_exit(&fcp_global_mutex);
10336         }
10337 
10338         /* clean up the port structures */
10339         if (flag == FCP_STATE_DETACHING) {
10340                 fcp_cleanup_port(pptr, instance);
10341         }
10342 
10343         return (FC_SUCCESS);
10344 }
10345 
10346 
10347 static void
10348 fcp_cleanup_port(struct fcp_port *pptr, int instance)
10349 {
10350         ASSERT(pptr != NULL);
10351 
10352         /* unbind and free event set */
10353         if (pptr->port_ndi_event_hdl) {
10354                 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl,
10355                     &pptr->port_ndi_events, NDI_SLEEP);
10356                 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl);
10357         }
10358 
10359         if (pptr->port_ndi_event_defs) {
10360                 (void) kmem_free(pptr->port_ndi_event_defs,
10361                     sizeof (fcp_ndi_event_defs));
10362         }
10363 
10364         /* free the lun/target structures and devinfos */
10365         fcp_free_targets(pptr);
10366 
10367         /*
10368          * Clean up mpxio stuff
10369          */
10370         if (pptr->port_mpxio) {
10371                 (void) mdi_phci_unregister(pptr->port_dip, 0);
10372                 pptr->port_mpxio--;
10373         }
10374 
10375         /* clean up SCSA stuff */
10376         (void) scsi_hba_detach(pptr->port_dip);
10377         if (pptr->port_tran != NULL) {
10378                 scsi_hba_tran_free(pptr->port_tran);
10379         }
10380 
10381 #ifdef  KSTATS_CODE
10382         /* clean up kstats */
10383         if (pptr->fcp_ksp != NULL) {
10384                 kstat_delete(pptr->fcp_ksp);
10385         }
10386 #endif
10387 
10388         /* clean up soft state mutexes/condition variables */
10389         mutex_destroy(&pptr->port_mutex);
10390         mutex_destroy(&pptr->port_pkt_mutex);
10391 
10392         /* all done with soft state */
10393         ddi_soft_state_free(fcp_softstate, instance);
10394 }
10395 
10396 /*
10397  *     Function: fcp_kmem_cache_constructor
10398  *
10399  *  Description: This function allocates and initializes the resources required
10400  *               to build a scsi_pkt structure the target driver.  The result
10401  *               of the allocation and initialization will be cached in the
10402  *               memory cache.  As DMA resources may be allocated here, that
10403  *               means DMA resources will be tied up in the cache manager.
10404  *               This is a tradeoff that has been made for performance reasons.
10405  *
10406  *     Argument: *buf           Memory to preinitialize.
10407  *               *arg           FCP port structure (fcp_port).
10408  *               kmflags        Value passed to kmem_cache_alloc() and
10409  *                              propagated to the constructor.
10410  *
10411  * Return Value: 0      Allocation/Initialization was successful.
10412  *               -1     Allocation or Initialization failed.
10413  *
10414  *
10415  * If the returned value is 0, the buffer is initialized like this:
10416  *
10417  *                  +================================+
10418  *           +----> |              struct scsi_pkt        |
10419  *           |      |                                |
10420  *           | +--- | pkt_ha_private                 |
10421  *           | |    |                                |
10422  *           | |    +================================+
10423  *           | |
10424  *           | |    +================================+
10425  *           | +--> |            struct fcp_pkt           | <---------+
10426  *           |      |                                |           |
10427  *           +----- | cmd_pkt                        |           |
10428  *                  |                     cmd_fp_pkt | ---+      |
10429  *        +-------->| cmd_fcp_rsp[]               |    |      |
10430  *        |    +--->| cmd_fcp_cmd[]               |    |      |
10431  *        |    |    |--------------------------------|    |      |
10432  *        |    |    |         struct fc_packet       | <--+   |
10433  *        |    |    |                                |           |
10434  *        |    |    |                pkt_ulp_private | ----------+
10435  *        |    |    |                pkt_fca_private | -----+
10436  *        |    |    |                pkt_data_cookie | ---+ |
10437  *        |    |    | pkt_cmdlen                     |    | |
10438  *        |    |(a) | pkt_rsplen                     |    | |
10439  *        |    +----| .......... pkt_cmd ........... | ---|-|---------------+
10440  *        |     (b) |                 pkt_cmd_cookie | ---|-|----------+    |
10441  *        +---------| .......... pkt_resp .......... | ---|-|------+   |    |
10442  *                  |                pkt_resp_cookie | ---|-|--+   |   |    |
10443  *                  | pkt_cmd_dma                    |    | |  |   |   |    |
10444  *                  | pkt_cmd_acc                    |    | |  |   |   |    |
10445  *                  +================================+    | |  |   |   |    |
10446  *                  |         dma_cookies            | <--+ |  |   |   |    |
10447  *                  |                                |      |  |   |   |    |
10448  *                  +================================+      |  |   |   |    |
10449  *                  |         fca_private            | <----+  |   |   |    |
10450  *                  |                                |         |   |   |    |
10451  *                  +================================+         |   |   |    |
10452  *                                                             |   |   |    |
10453  *                                                             |   |   |    |
10454  *                  +================================+   (d)   |   |   |    |
10455  *                  |        fcp_resp cookies        | <-------+   |   |    |
10456  *                  |                                |             |   |    |
10457  *                  +================================+             |   |    |
10458  *                                                                 |   |    |
10459  *                  +================================+   (d)       |   |    |
10460  *                  |           fcp_resp             | <-----------+   |    |
10461  *                  |   (DMA resources associated)   |                 |    |
10462  *                  +================================+                 |    |
10463  *                                                                     |    |
10464  *                                                                     |    |
10465  *                                                                     |    |
10466  *                  +================================+   (c)           |    |
10467  *                  |        fcp_cmd cookies         | <---------------+    |
10468  *                  |                                |                      |
10469  *                  +================================+                      |
10470  *                                                                          |
10471  *                  +================================+   (c)                |
10472  *                  |            fcp_cmd             | <--------------------+
10473  *                  |   (DMA resources associated)   |
10474  *                  +================================+
10475  *
10476  * (a) Only if DMA is NOT used for the FCP_CMD buffer.
10477  * (b) Only if DMA is NOT used for the FCP_RESP buffer
10478  * (c) Only if DMA is used for the FCP_CMD buffer.
10479  * (d) Only if DMA is used for the FCP_RESP buffer
10480  */
10481 static int
10482 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran,
10483     int kmflags)
10484 {
10485         struct fcp_pkt  *cmd;
10486         struct fcp_port *pptr;
10487         fc_packet_t     *fpkt;
10488 
10489         pptr = (struct fcp_port *)tran->tran_hba_private;
10490         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
10491         bzero(cmd, tran->tran_hba_len);
10492 
10493         cmd->cmd_pkt = pkt;
10494         pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb;
10495         fpkt = (fc_packet_t *)&cmd->cmd_fc_packet;
10496         cmd->cmd_fp_pkt = fpkt;
10497 
10498         cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd;
10499         cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
10500         cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
10501             sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz);
10502 
10503         fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd +
10504             sizeof (struct fcp_pkt));
10505 
10506         fpkt->pkt_cmdlen = sizeof (struct fcp_cmd);
10507         fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
10508 
10509         if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) {
10510                 /*
10511                  * The underlying HBA doesn't want to DMA the fcp_cmd or
10512                  * fcp_resp.  The transfer of information will be done by
10513                  * bcopy.
10514                  * The naming of the flags (that is actually a value) is
10515                  * unfortunate.  FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL
10516                  * DMA" but instead "NO DMA".
10517                  */
10518                 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL;
10519                 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
10520                 fpkt->pkt_resp = cmd->cmd_fcp_rsp;
10521         } else {
10522                 /*
10523                  * The underlying HBA will dma the fcp_cmd buffer and fcp_resp
10524                  * buffer.  A buffer is allocated for each one the ddi_dma_*
10525                  * interfaces.
10526                  */
10527                 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) {
10528                         return (-1);
10529                 }
10530         }
10531 
10532         return (0);
10533 }
10534 
10535 /*
10536  *     Function: fcp_kmem_cache_destructor
10537  *
10538  *  Description: Called by the destructor of the cache managed by SCSA.
10539  *               All the resources pre-allocated in fcp_pkt_constructor
10540  *               and the data also pre-initialized in fcp_pkt_constructor
10541  *               are freed and uninitialized here.
10542  *
10543  *     Argument: *buf           Memory to uninitialize.
10544  *               *arg           FCP port structure (fcp_port).
10545  *
10546  * Return Value: None
10547  *
10548  *      Context: kernel
10549  */
10550 static void
10551 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran)
10552 {
10553         struct fcp_pkt  *cmd;
10554         struct fcp_port *pptr;
10555 
10556         pptr = (struct fcp_port *)(tran->tran_hba_private);
10557         cmd = pkt->pkt_ha_private;
10558 
10559         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
10560                 /*
10561                  * If DMA was used to transfer the FCP_CMD and FCP_RESP, the
10562                  * buffer and DMA resources allocated to do so are released.
10563                  */
10564                 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt);
10565         }
10566 }
10567 
10568 /*
10569  *     Function: fcp_alloc_cmd_resp
10570  *
10571  *  Description: This function allocated an FCP_CMD and FCP_RESP buffer that
10572  *               will be DMAed by the HBA.  The buffer is allocated applying
10573  *               the DMA requirements for the HBA.  The buffers allocated will
10574  *               also be bound.  DMA resources are allocated in the process.
10575  *               They will be released by fcp_free_cmd_resp().
10576  *
10577  *     Argument: *pptr  FCP port.
10578  *               *fpkt  fc packet for which the cmd and resp packet should be
10579  *                      allocated.
10580  *               flags  Allocation flags.
10581  *
10582  * Return Value: FC_FAILURE
10583  *               FC_SUCCESS
10584  *
10585  *      Context: User or Kernel context only if flags == KM_SLEEP.
10586  *               Interrupt context if the KM_SLEEP is not specified.
10587  */
10588 static int
10589 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags)
10590 {
10591         int                     rval;
10592         int                     cmd_len;
10593         int                     resp_len;
10594         ulong_t                 real_len;
10595         int                     (*cb) (caddr_t);
10596         ddi_dma_cookie_t        pkt_cookie;
10597         ddi_dma_cookie_t        *cp;
10598         uint32_t                cnt;
10599 
10600         cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
10601 
10602         cmd_len = fpkt->pkt_cmdlen;
10603         resp_len = fpkt->pkt_rsplen;
10604 
10605         ASSERT(fpkt->pkt_cmd_dma == NULL);
10606 
10607         /* Allocation of a DMA handle used in subsequent calls. */
10608         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr,
10609             cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) {
10610                 return (FC_FAILURE);
10611         }
10612 
10613         /* A buffer is allocated that satisfies the DMA requirements. */
10614         rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len,
10615             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10616             (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc);
10617 
10618         if (rval != DDI_SUCCESS) {
10619                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10620                 return (FC_FAILURE);
10621         }
10622 
10623         if (real_len < cmd_len) {
10624                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10625                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10626                 return (FC_FAILURE);
10627         }
10628 
10629         /* The buffer allocated is DMA bound. */
10630         rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL,
10631             fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
10632             cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt);
10633 
10634         if (rval != DDI_DMA_MAPPED) {
10635                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10636                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10637                 return (FC_FAILURE);
10638         }
10639 
10640         if (fpkt->pkt_cmd_cookie_cnt >
10641             pptr->port_cmd_dma_attr.dma_attr_sgllen) {
10642                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10643                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10644                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10645                 return (FC_FAILURE);
10646         }
10647 
10648         ASSERT(fpkt->pkt_cmd_cookie_cnt != 0);
10649 
10650         /*
10651          * The buffer where the scatter/gather list is going to be built is
10652          * allocated.
10653          */
10654         cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10655             fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie),
10656             KM_NOSLEEP);
10657 
10658         if (cp == NULL) {
10659                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10660                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10661                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10662                 return (FC_FAILURE);
10663         }
10664 
10665         /*
10666          * The scatter/gather list for the buffer we just allocated is built
10667          * here.
10668          */
10669         *cp = pkt_cookie;
10670         cp++;
10671 
10672         for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) {
10673                 ddi_dma_nextcookie(fpkt->pkt_cmd_dma,
10674                     &pkt_cookie);
10675                 *cp = pkt_cookie;
10676         }
10677 
10678         ASSERT(fpkt->pkt_resp_dma == NULL);
10679         if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr,
10680             cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) {
10681                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10682                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10683                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10684                 return (FC_FAILURE);
10685         }
10686 
10687         rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len,
10688             &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL,
10689             (caddr_t *)&fpkt->pkt_resp, &real_len,
10690             &fpkt->pkt_resp_acc);
10691 
10692         if (rval != DDI_SUCCESS) {
10693                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10694                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10695                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10696                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10697                 kmem_free(fpkt->pkt_cmd_cookie,
10698                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10699                 return (FC_FAILURE);
10700         }
10701 
10702         if (real_len < resp_len) {
10703                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10704                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10705                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10706                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10707                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10708                 kmem_free(fpkt->pkt_cmd_cookie,
10709                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10710                 return (FC_FAILURE);
10711         }
10712 
10713         rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL,
10714             fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
10715             cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt);
10716 
10717         if (rval != DDI_DMA_MAPPED) {
10718                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10719                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10720                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10721                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10722                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10723                 kmem_free(fpkt->pkt_cmd_cookie,
10724                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10725                 return (FC_FAILURE);
10726         }
10727 
10728         if (fpkt->pkt_resp_cookie_cnt >
10729             pptr->port_resp_dma_attr.dma_attr_sgllen) {
10730                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10731                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10732                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10733                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10734                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10735                 kmem_free(fpkt->pkt_cmd_cookie,
10736                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10737                 return (FC_FAILURE);
10738         }
10739 
10740         ASSERT(fpkt->pkt_resp_cookie_cnt != 0);
10741 
10742         cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc(
10743             fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie),
10744             KM_NOSLEEP);
10745 
10746         if (cp == NULL) {
10747                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10748                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10749                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10750                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10751                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10752                 kmem_free(fpkt->pkt_cmd_cookie,
10753                     fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie));
10754                 return (FC_FAILURE);
10755         }
10756 
10757         *cp = pkt_cookie;
10758         cp++;
10759 
10760         for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) {
10761                 ddi_dma_nextcookie(fpkt->pkt_resp_dma,
10762                     &pkt_cookie);
10763                 *cp = pkt_cookie;
10764         }
10765 
10766         return (FC_SUCCESS);
10767 }
10768 
10769 /*
10770  *     Function: fcp_free_cmd_resp
10771  *
10772  *  Description: This function releases the FCP_CMD and FCP_RESP buffer
10773  *               allocated by fcp_alloc_cmd_resp() and all the resources
10774  *               associated with them.  That includes the DMA resources and the
10775  *               buffer allocated for the cookies of each one of them.
10776  *
10777  *     Argument: *pptr          FCP port context.
10778  *               *fpkt          fc packet containing the cmd and resp packet
10779  *                              to be released.
10780  *
10781  * Return Value: None
10782  *
10783  *      Context: Interrupt, User and Kernel context.
10784  */
10785 /* ARGSUSED */
10786 static void
10787 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt)
10788 {
10789         ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL);
10790 
10791         if (fpkt->pkt_resp_dma) {
10792                 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma);
10793                 ddi_dma_mem_free(&fpkt->pkt_resp_acc);
10794                 ddi_dma_free_handle(&fpkt->pkt_resp_dma);
10795         }
10796 
10797         if (fpkt->pkt_resp_cookie) {
10798                 kmem_free(fpkt->pkt_resp_cookie,
10799                     fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t));
10800                 fpkt->pkt_resp_cookie = NULL;
10801         }
10802 
10803         if (fpkt->pkt_cmd_dma) {
10804                 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma);
10805                 ddi_dma_mem_free(&fpkt->pkt_cmd_acc);
10806                 ddi_dma_free_handle(&fpkt->pkt_cmd_dma);
10807         }
10808 
10809         if (fpkt->pkt_cmd_cookie) {
10810                 kmem_free(fpkt->pkt_cmd_cookie,
10811                     fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t));
10812                 fpkt->pkt_cmd_cookie = NULL;
10813         }
10814 }
10815 
10816 
10817 /*
10818  * called by the transport to do our own target initialization
10819  *
10820  * can acquire and release the global mutex
10821  */
10822 /* ARGSUSED */
10823 static int
10824 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10825     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10826 {
10827         uchar_t                 *bytes;
10828         uint_t                  nbytes;
10829         uint16_t                lun_num;
10830         struct fcp_tgt  *ptgt;
10831         struct fcp_lun  *plun;
10832         struct fcp_port *pptr = (struct fcp_port *)
10833             hba_tran->tran_hba_private;
10834 
10835         ASSERT(pptr != NULL);
10836 
10837         FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10838             FCP_BUF_LEVEL_8, 0,
10839             "fcp_phys_tgt_init: called for %s (instance %d)",
10840             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
10841 
10842         /* get our port WWN property */
10843         bytes = NULL;
10844         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10845             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10846             (nbytes != FC_WWN_SIZE)) {
10847                 /* no port WWN property */
10848                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10849                     FCP_BUF_LEVEL_8, 0,
10850                     "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED"
10851                     " for %s (instance %d): bytes=%p nbytes=%x",
10852                     ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes,
10853                     nbytes);
10854 
10855                 if (bytes != NULL) {
10856                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10857                 }
10858 
10859                 return (DDI_NOT_WELL_FORMED);
10860         }
10861         ASSERT(bytes != NULL);
10862 
10863         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10864             LUN_PROP, 0xFFFF);
10865         if (lun_num == 0xFFFF) {
10866                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10867                     FCP_BUF_LEVEL_8, 0,
10868                     "fcp_phys_tgt_init: Returning DDI_FAILURE:lun"
10869                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10870                     ddi_get_instance(tgt_dip));
10871 
10872                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10873                 return (DDI_NOT_WELL_FORMED);
10874         }
10875 
10876         mutex_enter(&pptr->port_mutex);
10877         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10878                 mutex_exit(&pptr->port_mutex);
10879                 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
10880                     FCP_BUF_LEVEL_8, 0,
10881                     "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun"
10882                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10883                     ddi_get_instance(tgt_dip));
10884 
10885                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10886                 return (DDI_FAILURE);
10887         }
10888 
10889         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10890             FC_WWN_SIZE) == 0);
10891         ASSERT(plun->lun_num == lun_num);
10892 
10893         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10894 
10895         ptgt = plun->lun_tgt;
10896 
10897         mutex_enter(&ptgt->tgt_mutex);
10898         plun->lun_tgt_count++;
10899         scsi_device_hba_private_set(sd, plun);
10900         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10901         plun->lun_sd = sd;
10902         mutex_exit(&ptgt->tgt_mutex);
10903         mutex_exit(&pptr->port_mutex);
10904 
10905         return (DDI_SUCCESS);
10906 }
10907 
10908 /*ARGSUSED*/
10909 static int
10910 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
10911     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
10912 {
10913         uchar_t                 *bytes;
10914         uint_t                  nbytes;
10915         uint16_t                lun_num;
10916         struct fcp_tgt  *ptgt;
10917         struct fcp_lun  *plun;
10918         struct fcp_port *pptr = (struct fcp_port *)
10919             hba_tran->tran_hba_private;
10920         child_info_t            *cip;
10921 
10922         ASSERT(pptr != NULL);
10923 
10924         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10925             fcp_trace, FCP_BUF_LEVEL_8, 0,
10926             "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p),"
10927             " (tgt_dip %p)", ddi_get_name(tgt_dip),
10928             ddi_get_instance(tgt_dip), hba_dip, tgt_dip);
10929 
10930         cip = (child_info_t *)sd->sd_pathinfo;
10931         if (cip == NULL) {
10932                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10933                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10934                     "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED"
10935                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10936                     ddi_get_instance(tgt_dip));
10937 
10938                 return (DDI_NOT_WELL_FORMED);
10939         }
10940 
10941         /* get our port WWN property */
10942         bytes = NULL;
10943         if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH,
10944             PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) ||
10945             (nbytes != FC_WWN_SIZE)) {
10946                 if (bytes) {
10947                         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10948                 }
10949                 return (DDI_NOT_WELL_FORMED);
10950         }
10951 
10952         ASSERT(bytes != NULL);
10953 
10954         lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH,
10955             LUN_PROP, 0xFFFF);
10956         if (lun_num == 0xFFFF) {
10957                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10958                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10959                     "fcp_virt_tgt_init: Returning DDI_FAILURE:lun"
10960                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10961                     ddi_get_instance(tgt_dip));
10962 
10963                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10964                 return (DDI_NOT_WELL_FORMED);
10965         }
10966 
10967         mutex_enter(&pptr->port_mutex);
10968         if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) {
10969                 mutex_exit(&pptr->port_mutex);
10970                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
10971                     fcp_trace, FCP_BUF_LEVEL_8, 0,
10972                     "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun"
10973                     " for %s (instance %d)", ddi_get_name(tgt_dip),
10974                     ddi_get_instance(tgt_dip));
10975 
10976                 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10977                 return (DDI_FAILURE);
10978         }
10979 
10980         ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes,
10981             FC_WWN_SIZE) == 0);
10982         ASSERT(plun->lun_num == lun_num);
10983 
10984         scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes);
10985 
10986         ptgt = plun->lun_tgt;
10987 
10988         mutex_enter(&ptgt->tgt_mutex);
10989         plun->lun_tgt_count++;
10990         scsi_device_hba_private_set(sd, plun);
10991         plun->lun_state |= FCP_SCSI_LUN_TGT_INIT;
10992         plun->lun_sd = sd;
10993         mutex_exit(&ptgt->tgt_mutex);
10994         mutex_exit(&pptr->port_mutex);
10995 
10996         return (DDI_SUCCESS);
10997 }
10998 
10999 
11000 /*
11001  * called by the transport to do our own target initialization
11002  *
11003  * can acquire and release the global mutex
11004  */
11005 /* ARGSUSED */
11006 static int
11007 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11008     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11009 {
11010         struct fcp_port *pptr = (struct fcp_port *)
11011             hba_tran->tran_hba_private;
11012         int                     rval;
11013 
11014         ASSERT(pptr != NULL);
11015 
11016         /*
11017          * Child node is getting initialized.  Look at the mpxio component
11018          * type on the child device to see if this device is mpxio managed
11019          * or not.
11020          */
11021         if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) {
11022                 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11023         } else {
11024                 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd);
11025         }
11026 
11027         return (rval);
11028 }
11029 
11030 
11031 /* ARGSUSED */
11032 static void
11033 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
11034     scsi_hba_tran_t *hba_tran, struct scsi_device *sd)
11035 {
11036         struct fcp_lun  *plun = scsi_device_hba_private_get(sd);
11037         struct fcp_tgt  *ptgt;
11038 
11039         FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf,
11040             fcp_trace, FCP_BUF_LEVEL_8, 0,
11041             "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d",
11042             ddi_get_name(hba_dip), ddi_get_instance(hba_dip),
11043             ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip));
11044 
11045         if (plun == NULL) {
11046                 return;
11047         }
11048         ptgt = plun->lun_tgt;
11049 
11050         ASSERT(ptgt != NULL);
11051 
11052         mutex_enter(&ptgt->tgt_mutex);
11053         ASSERT(plun->lun_tgt_count > 0);
11054 
11055         if (--plun->lun_tgt_count == 0) {
11056                 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT;
11057         }
11058         plun->lun_sd = NULL;
11059         mutex_exit(&ptgt->tgt_mutex);
11060 }
11061 
11062 /*
11063  *     Function: fcp_scsi_start
11064  *
11065  *  Description: This function is called by the target driver to request a
11066  *               command to be sent.
11067  *
11068  *     Argument: *ap            SCSI address of the device.
11069  *               *pkt           SCSI packet containing the cmd to send.
11070  *
11071  * Return Value: TRAN_ACCEPT
11072  *               TRAN_BUSY
11073  *               TRAN_BADPKT
11074  *               TRAN_FATAL_ERROR
11075  */
11076 static int
11077 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
11078 {
11079         struct fcp_port *pptr = ADDR2FCP(ap);
11080         struct fcp_lun  *plun = ADDR2LUN(ap);
11081         struct fcp_pkt  *cmd = PKT2CMD(pkt);
11082         struct fcp_tgt  *ptgt = plun->lun_tgt;
11083         int                     rval;
11084 
11085         /* ensure command isn't already issued */
11086         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
11087 
11088         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11089             fcp_trace, FCP_BUF_LEVEL_9, 0,
11090             "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id);
11091 
11092         /*
11093          * It is strange that we enter the fcp_port mutex and the target
11094          * mutex to check the lun state (which has a mutex of its own).
11095          */
11096         mutex_enter(&pptr->port_mutex);
11097         mutex_enter(&ptgt->tgt_mutex);
11098 
11099         /*
11100          * If the device is offline and is not in the process of coming
11101          * online, fail the request.
11102          */
11103 
11104         if ((plun->lun_state & FCP_LUN_OFFLINE) &&
11105             !(plun->lun_state & FCP_LUN_ONLINING)) {
11106                 mutex_exit(&ptgt->tgt_mutex);
11107                 mutex_exit(&pptr->port_mutex);
11108 
11109                 if (cmd->cmd_fp_pkt->pkt_pd == NULL) {
11110                         pkt->pkt_reason = CMD_DEV_GONE;
11111                 }
11112 
11113                 return (TRAN_FATAL_ERROR);
11114         }
11115         cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time;
11116 
11117         /*
11118          * If we are suspended, kernel is trying to dump, so don't
11119          * block, fail or defer requests - send them down right away.
11120          * NOTE: If we are in panic (i.e. trying to dump), we can't
11121          * assume we have been suspended.  There is hardware such as
11122          * the v880 that doesn't do PM.  Thus, the check for
11123          * ddi_in_panic.
11124          *
11125          * If FCP_STATE_IN_CB_DEVC is set, devices are in the process
11126          * of changing.  So, if we can queue the packet, do it.  Eventually,
11127          * either the device will have gone away or changed and we can fail
11128          * the request, or we can proceed if the device didn't change.
11129          *
11130          * If the pd in the target or the packet is NULL it's probably
11131          * because the device has gone away, we allow the request to be
11132          * put on the internal queue here in case the device comes back within
11133          * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle
11134          * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd
11135          * could be NULL because the device was disappearing during or since
11136          * packet initialization.
11137          */
11138 
11139         if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state &
11140             FCP_STATE_SUSPENDED)) && !ddi_in_panic()) ||
11141             (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) ||
11142             (ptgt->tgt_pd_handle == NULL) ||
11143             (cmd->cmd_fp_pkt->pkt_pd == NULL)) {
11144                 /*
11145                  * If ((LUN is busy AND
11146                  *      LUN not suspended AND
11147                  *      The system is not in panic state) OR
11148                  *      (The port is coming up))
11149                  *
11150                  * We check to see if the any of the flags FLAG_NOINTR or
11151                  * FLAG_NOQUEUE is set.  If one of them is set the value
11152                  * returned will be TRAN_BUSY.  If not, the request is queued.
11153                  */
11154                 mutex_exit(&ptgt->tgt_mutex);
11155                 mutex_exit(&pptr->port_mutex);
11156 
11157                 /* see if using interrupts is allowed (so queueing'll work) */
11158                 if (pkt->pkt_flags & FLAG_NOINTR) {
11159                         pkt->pkt_resid = 0;
11160                         return (TRAN_BUSY);
11161                 }
11162                 if (pkt->pkt_flags & FLAG_NOQUEUE) {
11163                         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11164                             fcp_trace, FCP_BUF_LEVEL_9, 0,
11165                             "fcp_scsi_start: lun busy for pkt %p", pkt);
11166                         return (TRAN_BUSY);
11167                 }
11168 #ifdef  DEBUG
11169                 mutex_enter(&pptr->port_pkt_mutex);
11170                 pptr->port_npkts++;
11171                 mutex_exit(&pptr->port_pkt_mutex);
11172 #endif /* DEBUG */
11173 
11174                 /* got queue up the pkt for later */
11175                 fcp_queue_pkt(pptr, cmd);
11176                 return (TRAN_ACCEPT);
11177         }
11178         cmd->cmd_state = FCP_PKT_ISSUED;
11179 
11180         mutex_exit(&ptgt->tgt_mutex);
11181         mutex_exit(&pptr->port_mutex);
11182 
11183         /*
11184          * Now that we released the mutexes, what was protected by them can
11185          * change.
11186          */
11187 
11188         /*
11189          * If there is a reconfiguration in progress, wait for it to complete.
11190          */
11191         fcp_reconfig_wait(pptr);
11192 
11193         cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time +
11194             pkt->pkt_time : 0;
11195 
11196         /* prepare the packet */
11197 
11198         fcp_prepare_pkt(pptr, cmd, plun);
11199 
11200         if (cmd->cmd_pkt->pkt_time) {
11201                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11202         } else {
11203                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11204         }
11205 
11206         /*
11207          * if interrupts aren't allowed (e.g. at dump time) then we'll
11208          * have to do polled I/O
11209          */
11210         if (pkt->pkt_flags & FLAG_NOINTR) {
11211                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
11212                 return (fcp_dopoll(pptr, cmd));
11213         }
11214 
11215 #ifdef  DEBUG
11216         mutex_enter(&pptr->port_pkt_mutex);
11217         pptr->port_npkts++;
11218         mutex_exit(&pptr->port_pkt_mutex);
11219 #endif /* DEBUG */
11220 
11221         rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0);
11222         if (rval == FC_SUCCESS) {
11223                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11224                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11225                     "fcp_transport success for %x", plun->lun_tgt->tgt_d_id);
11226                 return (TRAN_ACCEPT);
11227         }
11228 
11229         cmd->cmd_state = FCP_PKT_IDLE;
11230 
11231 #ifdef  DEBUG
11232         mutex_enter(&pptr->port_pkt_mutex);
11233         pptr->port_npkts--;
11234         mutex_exit(&pptr->port_pkt_mutex);
11235 #endif /* DEBUG */
11236 
11237         /*
11238          * For lack of clearer definitions, choose
11239          * between TRAN_BUSY and TRAN_FATAL_ERROR.
11240          */
11241 
11242         if (rval == FC_TRAN_BUSY) {
11243                 pkt->pkt_resid = 0;
11244                 rval = TRAN_BUSY;
11245         } else {
11246                 mutex_enter(&ptgt->tgt_mutex);
11247                 if (plun->lun_state & FCP_LUN_OFFLINE) {
11248                         child_info_t    *cip;
11249 
11250                         mutex_enter(&plun->lun_mutex);
11251                         cip = plun->lun_cip;
11252                         mutex_exit(&plun->lun_mutex);
11253 
11254                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11255                             fcp_trace, FCP_BUF_LEVEL_6, 0,
11256                             "fcp_transport failed 2 for %x: %x; dip=%p",
11257                             plun->lun_tgt->tgt_d_id, rval, cip);
11258 
11259                         rval = TRAN_FATAL_ERROR;
11260                 } else {
11261                         if (pkt->pkt_flags & FLAG_NOQUEUE) {
11262                                 FCP_DTRACE(fcp_logq, pptr->port_instbuf,
11263                                     fcp_trace, FCP_BUF_LEVEL_9, 0,
11264                                     "fcp_scsi_start: FC_BUSY for pkt %p",
11265                                     pkt);
11266                                 rval = TRAN_BUSY;
11267                         } else {
11268                                 rval = TRAN_ACCEPT;
11269                                 fcp_queue_pkt(pptr, cmd);
11270                         }
11271                 }
11272                 mutex_exit(&ptgt->tgt_mutex);
11273         }
11274 
11275         return (rval);
11276 }
11277 
11278 /*
11279  * called by the transport to abort a packet
11280  */
11281 /*ARGSUSED*/
11282 static int
11283 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
11284 {
11285         int tgt_cnt;
11286         struct fcp_port         *pptr = ADDR2FCP(ap);
11287         struct fcp_lun  *plun = ADDR2LUN(ap);
11288         struct fcp_tgt  *ptgt = plun->lun_tgt;
11289 
11290         if (pkt == NULL) {
11291                 if (ptgt) {
11292                         mutex_enter(&ptgt->tgt_mutex);
11293                         tgt_cnt = ptgt->tgt_change_cnt;
11294                         mutex_exit(&ptgt->tgt_mutex);
11295                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
11296                         return (TRUE);
11297                 }
11298         }
11299         return (FALSE);
11300 }
11301 
11302 
11303 /*
11304  * Perform reset
11305  */
11306 int
11307 fcp_scsi_reset(struct scsi_address *ap, int level)
11308 {
11309         int                     rval = 0;
11310         struct fcp_port         *pptr = ADDR2FCP(ap);
11311         struct fcp_lun  *plun = ADDR2LUN(ap);
11312         struct fcp_tgt  *ptgt = plun->lun_tgt;
11313 
11314         if (level == RESET_ALL) {
11315                 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) {
11316                         rval = 1;
11317                 }
11318         } else if (level == RESET_TARGET || level == RESET_LUN) {
11319                 /*
11320                  * If we are in the middle of discovery, return
11321                  * SUCCESS as this target will be rediscovered
11322                  * anyway
11323                  */
11324                 mutex_enter(&ptgt->tgt_mutex);
11325                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11326                         mutex_exit(&ptgt->tgt_mutex);
11327                         return (1);
11328                 }
11329                 mutex_exit(&ptgt->tgt_mutex);
11330 
11331                 if (fcp_reset_target(ap, level) == FC_SUCCESS) {
11332                         rval = 1;
11333                 }
11334         }
11335         return (rval);
11336 }
11337 
11338 
11339 /*
11340  * called by the framework to get a SCSI capability
11341  */
11342 static int
11343 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
11344 {
11345         return (fcp_commoncap(ap, cap, 0, whom, 0));
11346 }
11347 
11348 
11349 /*
11350  * called by the framework to set a SCSI capability
11351  */
11352 static int
11353 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
11354 {
11355         return (fcp_commoncap(ap, cap, value, whom, 1));
11356 }
11357 
11358 /*
11359  *     Function: fcp_pkt_setup
11360  *
11361  *  Description: This function sets up the scsi_pkt structure passed by the
11362  *               caller. This function assumes fcp_pkt_constructor has been
11363  *               called previously for the packet passed by the caller.  If
11364  *               successful this call will have the following results:
11365  *
11366  *                 - The resources needed that will be constant through out
11367  *                   the whole transaction are allocated.
11368  *                 - The fields that will be constant through out the whole
11369  *                   transaction are initialized.
11370  *                 - The scsi packet will be linked to the LUN structure
11371  *                   addressed by the transaction.
11372  *
11373  *     Argument:
11374  *               *pkt           Pointer to a scsi_pkt structure.
11375  *               callback
11376  *               arg
11377  *
11378  * Return Value: 0      Success
11379  *               !0     Failure
11380  *
11381  *      Context: Kernel context or interrupt context
11382  */
11383 /* ARGSUSED */
11384 static int
11385 fcp_pkt_setup(struct scsi_pkt *pkt,
11386     int (*callback)(caddr_t arg),
11387     caddr_t arg)
11388 {
11389         struct fcp_pkt  *cmd;
11390         struct fcp_port *pptr;
11391         struct fcp_lun  *plun;
11392         struct fcp_tgt  *ptgt;
11393         int             kf;
11394         fc_packet_t     *fpkt;
11395         fc_frame_hdr_t  *hp;
11396 
11397         pptr = ADDR2FCP(&pkt->pkt_address);
11398         plun = ADDR2LUN(&pkt->pkt_address);
11399         ptgt = plun->lun_tgt;
11400 
11401         cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11402         fpkt = cmd->cmd_fp_pkt;
11403 
11404         /*
11405          * this request is for dma allocation only
11406          */
11407         /*
11408          * First step of fcp_scsi_init_pkt: pkt allocation
11409          * We determine if the caller is willing to wait for the
11410          * resources.
11411          */
11412         kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP;
11413 
11414         /*
11415          * Selective zeroing of the pkt.
11416          */
11417         cmd->cmd_back = NULL;
11418         cmd->cmd_next = NULL;
11419 
11420         /*
11421          * Zero out fcp command
11422          */
11423         bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd));
11424 
11425         cmd->cmd_state = FCP_PKT_IDLE;
11426 
11427         fpkt = cmd->cmd_fp_pkt;
11428         fpkt->pkt_data_acc = NULL;
11429 
11430         /*
11431          * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle)
11432          * could be destroyed.  We need fail pkt_setup.
11433          */
11434         if (pptr->port_state & FCP_STATE_OFFLINE) {
11435                 return (-1);
11436         }
11437 
11438         mutex_enter(&ptgt->tgt_mutex);
11439         fpkt->pkt_pd = ptgt->tgt_pd_handle;
11440 
11441         if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf)
11442             != FC_SUCCESS) {
11443                 mutex_exit(&ptgt->tgt_mutex);
11444                 return (-1);
11445         }
11446 
11447         mutex_exit(&ptgt->tgt_mutex);
11448 
11449         /* Fill in the Fabric Channel Header */
11450         hp = &fpkt->pkt_cmd_fhdr;
11451         hp->r_ctl = R_CTL_COMMAND;
11452         hp->rsvd = 0;
11453         hp->type = FC_TYPE_SCSI_FCP;
11454         hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
11455         hp->seq_id = 0;
11456         hp->df_ctl  = 0;
11457         hp->seq_cnt = 0;
11458         hp->ox_id = 0xffff;
11459         hp->rx_id = 0xffff;
11460         hp->ro = 0;
11461 
11462         /*
11463          * A doubly linked list (cmd_forw, cmd_back) is built
11464          * out of every allocated packet on a per-lun basis
11465          *
11466          * The packets are maintained in the list so as to satisfy
11467          * scsi_abort() requests. At present (which is unlikely to
11468          * change in the future) nobody performs a real scsi_abort
11469          * in the SCSI target drivers (as they don't keep the packets
11470          * after doing scsi_transport - so they don't know how to
11471          * abort a packet other than sending a NULL to abort all
11472          * outstanding packets)
11473          */
11474         mutex_enter(&plun->lun_mutex);
11475         if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) {
11476                 plun->lun_pkt_head->cmd_back = cmd;
11477         } else {
11478                 plun->lun_pkt_tail = cmd;
11479         }
11480         plun->lun_pkt_head = cmd;
11481         mutex_exit(&plun->lun_mutex);
11482         return (0);
11483 }
11484 
11485 /*
11486  *     Function: fcp_pkt_teardown
11487  *
11488  *  Description: This function releases a scsi_pkt structure and all the
11489  *               resources attached to it.
11490  *
11491  *     Argument: *pkt           Pointer to a scsi_pkt structure.
11492  *
11493  * Return Value: None
11494  *
11495  *      Context: User, Kernel or Interrupt context.
11496  */
11497 static void
11498 fcp_pkt_teardown(struct scsi_pkt *pkt)
11499 {
11500         struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address);
11501         struct fcp_lun  *plun = ADDR2LUN(&pkt->pkt_address);
11502         struct fcp_pkt  *cmd = (struct fcp_pkt *)pkt->pkt_ha_private;
11503 
11504         /*
11505          * Remove the packet from the per-lun list
11506          */
11507         mutex_enter(&plun->lun_mutex);
11508         if (cmd->cmd_back) {
11509                 ASSERT(cmd != plun->lun_pkt_head);
11510                 cmd->cmd_back->cmd_forw = cmd->cmd_forw;
11511         } else {
11512                 ASSERT(cmd == plun->lun_pkt_head);
11513                 plun->lun_pkt_head = cmd->cmd_forw;
11514         }
11515 
11516         if (cmd->cmd_forw) {
11517                 cmd->cmd_forw->cmd_back = cmd->cmd_back;
11518         } else {
11519                 ASSERT(cmd == plun->lun_pkt_tail);
11520                 plun->lun_pkt_tail = cmd->cmd_back;
11521         }
11522 
11523         mutex_exit(&plun->lun_mutex);
11524 
11525         (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt);
11526 }
11527 
11528 /*
11529  * Routine for reset notification setup, to register or cancel.
11530  * This function is called by SCSA
11531  */
11532 /*ARGSUSED*/
11533 static int
11534 fcp_scsi_reset_notify(struct scsi_address *ap, int flag,
11535     void (*callback)(caddr_t), caddr_t arg)
11536 {
11537         struct fcp_port *pptr = ADDR2FCP(ap);
11538 
11539         return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
11540             &pptr->port_mutex, &pptr->port_reset_notify_listf));
11541 }
11542 
11543 
11544 static int
11545 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name,
11546     ddi_eventcookie_t *event_cookiep)
11547 {
11548         struct fcp_port *pptr = fcp_dip2port(dip);
11549 
11550         if (pptr == NULL) {
11551                 return (DDI_FAILURE);
11552         }
11553 
11554         return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name,
11555             event_cookiep, NDI_EVENT_NOPASS));
11556 }
11557 
11558 
11559 static int
11560 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
11561     ddi_eventcookie_t eventid, void (*callback)(), void *arg,
11562     ddi_callback_id_t *cb_id)
11563 {
11564         struct fcp_port *pptr = fcp_dip2port(dip);
11565 
11566         if (pptr == NULL) {
11567                 return (DDI_FAILURE);
11568         }
11569 
11570         return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip,
11571             eventid, callback, arg, NDI_SLEEP, cb_id));
11572 }
11573 
11574 
11575 static int
11576 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
11577 {
11578 
11579         struct fcp_port *pptr = fcp_dip2port(dip);
11580 
11581         if (pptr == NULL) {
11582                 return (DDI_FAILURE);
11583         }
11584         return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id));
11585 }
11586 
11587 
11588 /*
11589  * called by the transport to post an event
11590  */
11591 static int
11592 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip,
11593     ddi_eventcookie_t eventid, void *impldata)
11594 {
11595         struct fcp_port *pptr = fcp_dip2port(dip);
11596 
11597         if (pptr == NULL) {
11598                 return (DDI_FAILURE);
11599         }
11600 
11601         return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip,
11602             eventid, impldata));
11603 }
11604 
11605 
11606 /*
11607  * A target in in many cases in Fibre Channel has a one to one relation
11608  * with a port identifier (which is also known as D_ID and also as AL_PA
11609  * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset
11610  * will most likely result in resetting all LUNs (which means a reset will
11611  * occur on all the SCSI devices connected at the other end of the bridge)
11612  * That is the latest favorite topic for discussion, for, one can debate as
11613  * hot as one likes and come up with arguably a best solution to one's
11614  * satisfaction
11615  *
11616  * To stay on track and not digress much, here are the problems stated
11617  * briefly:
11618  *
11619  *      SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the
11620  *      target drivers use RESET_TARGET even if their instance is on a
11621  *      LUN. Doesn't that sound a bit broken ?
11622  *
11623  *      FCP SCSI (the current spec) only defines RESET TARGET in the
11624  *      control fields of an FCP_CMND structure. It should have been
11625  *      fixed right there, giving flexibility to the initiators to
11626  *      minimize havoc that could be caused by resetting a target.
11627  */
11628 static int
11629 fcp_reset_target(struct scsi_address *ap, int level)
11630 {
11631         int                     rval = FC_FAILURE;
11632         char                    lun_id[25];
11633         struct fcp_port         *pptr = ADDR2FCP(ap);
11634         struct fcp_lun  *plun = ADDR2LUN(ap);
11635         struct fcp_tgt  *ptgt = plun->lun_tgt;
11636         struct scsi_pkt         *pkt;
11637         struct fcp_pkt  *cmd;
11638         struct fcp_rsp          *rsp;
11639         uint32_t                tgt_cnt;
11640         struct fcp_rsp_info     *rsp_info;
11641         struct fcp_reset_elem   *p;
11642         int                     bval;
11643 
11644         if ((p = kmem_alloc(sizeof (struct fcp_reset_elem),
11645             KM_NOSLEEP)) == NULL) {
11646                 return (rval);
11647         }
11648 
11649         mutex_enter(&ptgt->tgt_mutex);
11650         if (level == RESET_TARGET) {
11651                 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) {
11652                         mutex_exit(&ptgt->tgt_mutex);
11653                         kmem_free(p, sizeof (struct fcp_reset_elem));
11654                         return (rval);
11655                 }
11656                 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY);
11657                 (void) strcpy(lun_id, " ");
11658         } else {
11659                 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) {
11660                         mutex_exit(&ptgt->tgt_mutex);
11661                         kmem_free(p, sizeof (struct fcp_reset_elem));
11662                         return (rval);
11663                 }
11664                 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY);
11665 
11666                 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num);
11667         }
11668         tgt_cnt = ptgt->tgt_change_cnt;
11669 
11670         mutex_exit(&ptgt->tgt_mutex);
11671 
11672         if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0,
11673             0, 0, NULL, 0)) == NULL) {
11674                 kmem_free(p, sizeof (struct fcp_reset_elem));
11675                 mutex_enter(&ptgt->tgt_mutex);
11676                 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11677                 mutex_exit(&ptgt->tgt_mutex);
11678                 return (rval);
11679         }
11680         pkt->pkt_time = FCP_POLL_TIMEOUT;
11681 
11682         /* fill in cmd part of packet */
11683         cmd = PKT2CMD(pkt);
11684         if (level == RESET_TARGET) {
11685                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1;
11686         } else {
11687                 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1;
11688         }
11689         cmd->cmd_fp_pkt->pkt_comp = NULL;
11690         cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR;
11691 
11692         /* prepare a packet for transport */
11693         fcp_prepare_pkt(pptr, cmd, plun);
11694 
11695         if (cmd->cmd_pkt->pkt_time) {
11696                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
11697         } else {
11698                 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60;
11699         }
11700 
11701         (void) fc_ulp_busy_port(pptr->port_fp_handle);
11702         bval = fcp_dopoll(pptr, cmd);
11703         fc_ulp_idle_port(pptr->port_fp_handle);
11704 
11705         /* submit the packet */
11706         if (bval == TRAN_ACCEPT) {
11707                 int error = 3;
11708 
11709                 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp;
11710                 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp +
11711                     sizeof (struct fcp_rsp));
11712 
11713                 if (rsp->fcp_u.fcp_status.rsp_len_set) {
11714                         if (fcp_validate_fcp_response(rsp, pptr) ==
11715                             FC_SUCCESS) {
11716                                 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
11717                                         FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp +
11718                                             sizeof (struct fcp_rsp), rsp_info,
11719                                             cmd->cmd_fp_pkt->pkt_resp_acc,
11720                                             sizeof (struct fcp_rsp_info));
11721                                 }
11722                                 if (rsp_info->rsp_code == FCP_NO_FAILURE) {
11723                                         rval = FC_SUCCESS;
11724                                         error = 0;
11725                                 } else {
11726                                         error = 1;
11727                                 }
11728                         } else {
11729                                 error = 2;
11730                         }
11731                 }
11732 
11733                 switch (error) {
11734                 case 0:
11735                         fcp_log(CE_WARN, pptr->port_dip,
11736                             "!FCP: WWN 0x%08x%08x %s reset successfully",
11737                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11738                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11739                         break;
11740 
11741                 case 1:
11742                         fcp_log(CE_WARN, pptr->port_dip,
11743                             "!FCP: Reset to WWN  0x%08x%08x %s failed,"
11744                             " response code=%x",
11745                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11746                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11747                             rsp_info->rsp_code);
11748                         break;
11749 
11750                 case 2:
11751                         fcp_log(CE_WARN, pptr->port_dip,
11752                             "!FCP: Reset to WWN 0x%08x%08x %s failed,"
11753                             " Bad FCP response values: rsvd1=%x,"
11754                             " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x,"
11755                             " rsplen=%x, senselen=%x",
11756                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11757                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id,
11758                             rsp->reserved_0, rsp->reserved_1,
11759                             rsp->fcp_u.fcp_status.reserved_0,
11760                             rsp->fcp_u.fcp_status.reserved_1,
11761                             rsp->fcp_response_len, rsp->fcp_sense_len);
11762                         break;
11763 
11764                 default:
11765                         fcp_log(CE_WARN, pptr->port_dip,
11766                             "!FCP: Reset to WWN  0x%08x%08x %s failed",
11767                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]),
11768                             *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id);
11769                         break;
11770                 }
11771         }
11772         scsi_destroy_pkt(pkt);
11773 
11774         if (rval == FC_FAILURE) {
11775                 mutex_enter(&ptgt->tgt_mutex);
11776                 if (level == RESET_TARGET) {
11777                         fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY);
11778                 } else {
11779                         fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY);
11780                 }
11781                 mutex_exit(&ptgt->tgt_mutex);
11782                 kmem_free(p, sizeof (struct fcp_reset_elem));
11783                 return (rval);
11784         }
11785 
11786         mutex_enter(&pptr->port_mutex);
11787         if (level == RESET_TARGET) {
11788                 p->tgt = ptgt;
11789                 p->lun = NULL;
11790         } else {
11791                 p->tgt = NULL;
11792                 p->lun = plun;
11793         }
11794         p->tgt = ptgt;
11795         p->tgt_cnt = tgt_cnt;
11796         p->timeout = fcp_watchdog_time + FCP_RESET_DELAY;
11797         p->next = pptr->port_reset_list;
11798         pptr->port_reset_list = p;
11799 
11800         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11801             fcp_trace, FCP_BUF_LEVEL_3, 0,
11802             "Notify ssd of the reset to reinstate the reservations");
11803 
11804         scsi_hba_reset_notify_callback(&pptr->port_mutex,
11805             &pptr->port_reset_notify_listf);
11806 
11807         mutex_exit(&pptr->port_mutex);
11808 
11809         return (rval);
11810 }
11811 
11812 
11813 /*
11814  * called by fcp_getcap and fcp_setcap to get and set (respectively)
11815  * SCSI capabilities
11816  */
11817 /* ARGSUSED */
11818 static int
11819 fcp_commoncap(struct scsi_address *ap, char *cap,
11820     int val, int tgtonly, int doset)
11821 {
11822         struct fcp_port         *pptr = ADDR2FCP(ap);
11823         struct fcp_lun  *plun = ADDR2LUN(ap);
11824         struct fcp_tgt  *ptgt = plun->lun_tgt;
11825         int                     cidx;
11826         int                     rval = FALSE;
11827 
11828         if (cap == (char *)0) {
11829                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11830                     fcp_trace, FCP_BUF_LEVEL_3, 0,
11831                     "fcp_commoncap: invalid arg");
11832                 return (rval);
11833         }
11834 
11835         if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) {
11836                 return (UNDEFINED);
11837         }
11838 
11839         /*
11840          * Process setcap request.
11841          */
11842         if (doset) {
11843                 /*
11844                  * At present, we can only set binary (0/1) values
11845                  */
11846                 switch (cidx) {
11847                 case SCSI_CAP_ARQ:
11848                         if (val == 0) {
11849                                 rval = FALSE;
11850                         } else {
11851                                 rval = TRUE;
11852                         }
11853                         break;
11854 
11855                 case SCSI_CAP_LUN_RESET:
11856                         if (val) {
11857                                 plun->lun_cap |= FCP_LUN_CAP_RESET;
11858                         } else {
11859                                 plun->lun_cap &= ~FCP_LUN_CAP_RESET;
11860                         }
11861                         rval = TRUE;
11862                         break;
11863 
11864                 case SCSI_CAP_SECTOR_SIZE:
11865                         rval = TRUE;
11866                         break;
11867                 default:
11868                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11869                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11870                             "fcp_setcap: unsupported %d", cidx);
11871                         rval = UNDEFINED;
11872                         break;
11873                 }
11874 
11875                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11876                     fcp_trace, FCP_BUF_LEVEL_5, 0,
11877                     "set cap: cap=%s, val/tgtonly/doset/rval = "
11878                     "0x%x/0x%x/0x%x/%d",
11879                     cap, val, tgtonly, doset, rval);
11880 
11881         } else {
11882                 /*
11883                  * Process getcap request.
11884                  */
11885                 switch (cidx) {
11886                 case SCSI_CAP_DMA_MAX:
11887                         rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer;
11888 
11889                         /*
11890                          * Need to make an adjustment qlc is uint_t 64
11891                          * st is int, so we will make the adjustment here
11892                          * being as nobody wants to touch this.
11893                          * It still leaves the max single block length
11894                          * of 2 gig. This should last .
11895                          */
11896 
11897                         if (rval == -1) {
11898                                 rval = MAX_INT_DMA;
11899                         }
11900 
11901                         break;
11902 
11903                 case SCSI_CAP_INITIATOR_ID:
11904                         rval = pptr->port_id;
11905                         break;
11906 
11907                 case SCSI_CAP_ARQ:
11908                 case SCSI_CAP_RESET_NOTIFICATION:
11909                 case SCSI_CAP_TAGGED_QING:
11910                         rval = TRUE;
11911                         break;
11912 
11913                 case SCSI_CAP_SCSI_VERSION:
11914                         rval = 3;
11915                         break;
11916 
11917                 case SCSI_CAP_INTERCONNECT_TYPE:
11918                         if (FC_TOP_EXTERNAL(pptr->port_topology) ||
11919                             (ptgt->tgt_hard_addr == 0)) {
11920                                 rval = INTERCONNECT_FABRIC;
11921                         } else {
11922                                 rval = INTERCONNECT_FIBRE;
11923                         }
11924                         break;
11925 
11926                 case SCSI_CAP_LUN_RESET:
11927                         rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ?
11928                             TRUE : FALSE;
11929                         break;
11930 
11931                 default:
11932                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
11933                             fcp_trace, FCP_BUF_LEVEL_4, 0,
11934                             "fcp_getcap: unsupported %d", cidx);
11935                         rval = UNDEFINED;
11936                         break;
11937                 }
11938 
11939                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
11940                     fcp_trace, FCP_BUF_LEVEL_8, 0,
11941                     "get cap: cap=%s, val/tgtonly/doset/rval = "
11942                     "0x%x/0x%x/0x%x/%d",
11943                     cap, val, tgtonly, doset, rval);
11944         }
11945 
11946         return (rval);
11947 }
11948 
11949 /*
11950  * called by the transport to get the port-wwn and lun
11951  * properties of this device, and to create a "name" based on them
11952  *
11953  * these properties don't exist on sun4m
11954  *
11955  * return 1 for success else return 0
11956  */
11957 /* ARGSUSED */
11958 static int
11959 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len)
11960 {
11961         int                     i;
11962         int                     *lun;
11963         int                     numChars;
11964         uint_t                  nlun;
11965         uint_t                  count;
11966         uint_t                  nbytes;
11967         uchar_t                 *bytes;
11968         uint16_t                lun_num;
11969         uint32_t                tgt_id;
11970         char                    **conf_wwn;
11971         char                    tbuf[(FC_WWN_SIZE << 1) + 1];
11972         uchar_t                 barray[FC_WWN_SIZE];
11973         dev_info_t              *tgt_dip;
11974         struct fcp_tgt  *ptgt;
11975         struct fcp_port *pptr;
11976         struct fcp_lun  *plun;
11977 
11978         ASSERT(sd != NULL);
11979         ASSERT(name != NULL);
11980 
11981         tgt_dip = sd->sd_dev;
11982         pptr = ddi_get_soft_state(fcp_softstate,
11983             ddi_get_instance(ddi_get_parent(tgt_dip)));
11984         if (pptr == NULL) {
11985                 return (0);
11986         }
11987 
11988         ASSERT(tgt_dip != NULL);
11989 
11990         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev,
11991             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
11992             LUN_PROP, &lun, &nlun) != DDI_SUCCESS) {
11993                 name[0] = '\0';
11994                 return (0);
11995         }
11996 
11997         if (nlun == 0) {
11998                 ddi_prop_free(lun);
11999                 return (0);
12000         }
12001 
12002         lun_num = lun[0];
12003         ddi_prop_free(lun);
12004 
12005         /*
12006          * Lookup for .conf WWN property
12007          */
12008         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip,
12009             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP,
12010             &conf_wwn, &count) == DDI_PROP_SUCCESS) {
12011                 ASSERT(count >= 1);
12012 
12013                 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE);
12014                 ddi_prop_free(conf_wwn);
12015                 mutex_enter(&pptr->port_mutex);
12016                 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) {
12017                         mutex_exit(&pptr->port_mutex);
12018                         return (0);
12019                 }
12020                 ptgt = plun->lun_tgt;
12021                 mutex_exit(&pptr->port_mutex);
12022 
12023                 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE,
12024                     tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE);
12025 
12026                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12027                     ptgt->tgt_hard_addr != 0) {
12028                         tgt_id = (uint32_t)fcp_alpa_to_switch[
12029                             ptgt->tgt_hard_addr];
12030                 } else {
12031                         tgt_id = ptgt->tgt_d_id;
12032                 }
12033 
12034                 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip,
12035                     TARGET_PROP, tgt_id);
12036         }
12037 
12038         /* get the our port-wwn property */
12039         bytes = NULL;
12040         if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip,
12041             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12042             &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) {
12043                 if (bytes != NULL) {
12044                         ddi_prop_free(bytes);
12045                 }
12046                 return (0);
12047         }
12048 
12049         for (i = 0; i < FC_WWN_SIZE; i++) {
12050                 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i));
12051         }
12052 
12053         /* Stick in the address of the form "wWWN,LUN" */
12054         numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num);
12055 
12056         ASSERT(numChars < len);
12057         if (numChars >= len) {
12058                 fcp_log(CE_WARN, pptr->port_dip,
12059                     "!fcp_scsi_get_name: "
12060                     "name parameter length too small, it needs to be %d",
12061                     numChars+1);
12062         }
12063 
12064         ddi_prop_free(bytes);
12065 
12066         return (1);
12067 }
12068 
12069 
12070 /*
12071  * called by the transport to get the SCSI target id value, returning
12072  * it in "name"
12073  *
12074  * this isn't needed/used on sun4m
12075  *
12076  * return 1 for success else return 0
12077  */
12078 /* ARGSUSED */
12079 static int
12080 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len)
12081 {
12082         struct fcp_lun  *plun = ADDR2LUN(&sd->sd_address);
12083         struct fcp_tgt  *ptgt;
12084         int    numChars;
12085 
12086         if (plun == NULL) {
12087                 return (0);
12088         }
12089 
12090         if ((ptgt = plun->lun_tgt) == NULL) {
12091                 return (0);
12092         }
12093 
12094         numChars = snprintf(name, len, "%x", ptgt->tgt_d_id);
12095 
12096         ASSERT(numChars < len);
12097         if (numChars >= len) {
12098                 fcp_log(CE_WARN, NULL,
12099                     "!fcp_scsi_get_bus_addr: "
12100                     "name parameter length too small, it needs to be %d",
12101                     numChars+1);
12102         }
12103 
12104         return (1);
12105 }
12106 
12107 
12108 /*
12109  * called internally to reset the link where the specified port lives
12110  */
12111 static int
12112 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep)
12113 {
12114         la_wwn_t                wwn;
12115         struct fcp_lun  *plun;
12116         struct fcp_tgt  *ptgt;
12117 
12118         /* disable restart of lip if we're suspended */
12119         mutex_enter(&pptr->port_mutex);
12120 
12121         if (pptr->port_state & (FCP_STATE_SUSPENDED |
12122             FCP_STATE_POWER_DOWN)) {
12123                 mutex_exit(&pptr->port_mutex);
12124                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12125                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12126                     "fcp_linkreset, fcp%d: link reset "
12127                     "disabled due to DDI_SUSPEND",
12128                     ddi_get_instance(pptr->port_dip));
12129                 return (FC_FAILURE);
12130         }
12131 
12132         if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) {
12133                 mutex_exit(&pptr->port_mutex);
12134                 return (FC_SUCCESS);
12135         }
12136 
12137         FCP_DTRACE(fcp_logq, pptr->port_instbuf,
12138             fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset");
12139 
12140         /*
12141          * If ap == NULL assume local link reset.
12142          */
12143         if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) {
12144                 plun = ADDR2LUN(ap);
12145                 ptgt = plun->lun_tgt;
12146                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn));
12147         } else {
12148                 bzero((caddr_t)&wwn, sizeof (wwn));
12149         }
12150         mutex_exit(&pptr->port_mutex);
12151 
12152         return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep));
12153 }
12154 
12155 
12156 /*
12157  * called from fcp_port_attach() to resume a port
12158  * return DDI_* success/failure status
12159  * acquires and releases the global mutex
12160  * acquires and releases the port mutex
12161  */
12162 /*ARGSUSED*/
12163 
12164 static int
12165 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo,
12166     uint32_t s_id, fc_attach_cmd_t cmd, int instance)
12167 {
12168         int                     res = DDI_FAILURE; /* default result */
12169         struct fcp_port *pptr;          /* port state ptr */
12170         uint32_t                alloc_cnt;
12171         uint32_t                max_cnt;
12172         fc_portmap_t            *tmp_list = NULL;
12173 
12174         FCP_DTRACE(fcp_logq, "fcp", fcp_trace,
12175             FCP_BUF_LEVEL_8, 0, "port resume: for port %d",
12176             instance);
12177 
12178         if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) {
12179                 cmn_err(CE_WARN, "fcp: bad soft state");
12180                 return (res);
12181         }
12182 
12183         mutex_enter(&pptr->port_mutex);
12184         switch (cmd) {
12185         case FC_CMD_RESUME:
12186                 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0);
12187                 pptr->port_state &= ~FCP_STATE_SUSPENDED;
12188                 break;
12189 
12190         case FC_CMD_POWER_UP:
12191                 /*
12192                  * If the port is DDI_SUSPENded, defer rediscovery
12193                  * until DDI_RESUME occurs
12194                  */
12195                 if (pptr->port_state & FCP_STATE_SUSPENDED) {
12196                         pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12197                         mutex_exit(&pptr->port_mutex);
12198                         return (DDI_SUCCESS);
12199                 }
12200                 pptr->port_state &= ~FCP_STATE_POWER_DOWN;
12201         }
12202         pptr->port_id = s_id;
12203         pptr->port_state = FCP_STATE_INIT;
12204         mutex_exit(&pptr->port_mutex);
12205 
12206         /*
12207          * Make a copy of ulp_port_info as fctl allocates
12208          * a temp struct.
12209          */
12210         (void) fcp_cp_pinfo(pptr, pinfo);
12211 
12212         mutex_enter(&fcp_global_mutex);
12213         if (fcp_watchdog_init++ == 0) {
12214                 fcp_watchdog_tick = drv_sectohz(fcp_watchdog_timeout);

12215                 fcp_watchdog_id = timeout(fcp_watch,
12216                     NULL, fcp_watchdog_tick);
12217         }
12218         mutex_exit(&fcp_global_mutex);
12219 
12220         /*
12221          * Handle various topologies and link states.
12222          */
12223         switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) {
12224         case FC_STATE_OFFLINE:
12225                 /*
12226                  * Wait for ONLINE, at which time a state
12227                  * change will cause a statec_callback
12228                  */
12229                 res = DDI_SUCCESS;
12230                 break;
12231 
12232         case FC_STATE_ONLINE:
12233 
12234                 if (pptr->port_topology == FC_TOP_UNKNOWN) {
12235                         (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP);
12236                         res = DDI_SUCCESS;
12237                         break;
12238                 }
12239 
12240                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
12241                     !fcp_enable_auto_configuration) {
12242                         tmp_list = fcp_construct_map(pptr, &alloc_cnt);
12243                         if (tmp_list == NULL) {
12244                                 if (!alloc_cnt) {
12245                                         res = DDI_SUCCESS;
12246                                 }
12247                                 break;
12248                         }
12249                         max_cnt = alloc_cnt;
12250                 } else {
12251                         ASSERT(pptr->port_topology != FC_TOP_UNKNOWN);
12252 
12253                         alloc_cnt = FCP_MAX_DEVICES;
12254 
12255                         if ((tmp_list = (fc_portmap_t *)kmem_zalloc(
12256                             (sizeof (fc_portmap_t)) * alloc_cnt,
12257                             KM_NOSLEEP)) == NULL) {
12258                                 fcp_log(CE_WARN, pptr->port_dip,
12259                                     "!fcp%d: failed to allocate portmap",
12260                                     instance);
12261                                 break;
12262                         }
12263 
12264                         max_cnt = alloc_cnt;
12265                         if ((res = fc_ulp_getportmap(pptr->port_fp_handle,
12266                             &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) !=
12267                             FC_SUCCESS) {
12268                                 caddr_t msg;
12269 
12270                                 (void) fc_ulp_error(res, &msg);
12271 
12272                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
12273                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
12274                                     "resume failed getportmap: reason=0x%x",
12275                                     res);
12276 
12277                                 fcp_log(CE_WARN, pptr->port_dip,
12278                                     "!failed to get port map : %s", msg);
12279                                 break;
12280                         }
12281                         if (max_cnt > alloc_cnt) {
12282                                 alloc_cnt = max_cnt;
12283                         }
12284                 }
12285 
12286                 /*
12287                  * do the SCSI device discovery and create
12288                  * the devinfos
12289                  */
12290                 fcp_statec_callback(ulph, pptr->port_fp_handle,
12291                     pptr->port_phys_state, pptr->port_topology, tmp_list,
12292                     max_cnt, pptr->port_id);
12293 
12294                 res = DDI_SUCCESS;
12295                 break;
12296 
12297         default:
12298                 fcp_log(CE_WARN, pptr->port_dip,
12299                     "!fcp%d: invalid port state at attach=0x%x",
12300                     instance, pptr->port_phys_state);
12301 
12302                 mutex_enter(&pptr->port_mutex);
12303                 pptr->port_phys_state = FCP_STATE_OFFLINE;
12304                 mutex_exit(&pptr->port_mutex);
12305                 res = DDI_SUCCESS;
12306 
12307                 break;
12308         }
12309 
12310         if (tmp_list != NULL) {
12311                 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt);
12312         }
12313 
12314         return (res);
12315 }
12316 
12317 
12318 static void
12319 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo)
12320 {
12321         pptr->port_fp_modlinkage = *pinfo->port_linkage;
12322         pptr->port_dip = pinfo->port_dip;
12323         pptr->port_fp_handle = pinfo->port_handle;
12324         if (pinfo->port_acc_attr != NULL) {
12325                 /*
12326                  * FCA supports DMA
12327                  */
12328                 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr;
12329                 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr;
12330                 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr;
12331                 pptr->port_dma_acc_attr = *pinfo->port_acc_attr;
12332         }
12333         pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size;
12334         pptr->port_max_exch = pinfo->port_fca_max_exch;
12335         pptr->port_phys_state = pinfo->port_state;
12336         pptr->port_topology = pinfo->port_flags;
12337         pptr->port_reset_action = pinfo->port_reset_action;
12338         pptr->port_cmds_dma_flags = pinfo->port_dma_behavior;
12339         pptr->port_fcp_dma = pinfo->port_fcp_dma;
12340         bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t));
12341         bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t));
12342 
12343         /* Clear FMA caps to avoid fm-capability ereport */
12344         if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12345                 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12346         if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12347                 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12348         if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR)
12349                 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
12350 }
12351 
12352 /*
12353  * If the elements wait field is set to 1 then
12354  * another thread is waiting for the operation to complete. Once
12355  * it is complete, the waiting thread is signaled and the element is
12356  * freed by the waiting thread. If the elements wait field is set to 0
12357  * the element is freed.
12358  */
12359 static void
12360 fcp_process_elem(struct fcp_hp_elem *elem, int result)
12361 {
12362         ASSERT(elem != NULL);
12363         mutex_enter(&elem->mutex);
12364         elem->result = result;
12365         if (elem->wait) {
12366                 elem->wait = 0;
12367                 cv_signal(&elem->cv);
12368                 mutex_exit(&elem->mutex);
12369         } else {
12370                 mutex_exit(&elem->mutex);
12371                 cv_destroy(&elem->cv);
12372                 mutex_destroy(&elem->mutex);
12373                 kmem_free(elem, sizeof (struct fcp_hp_elem));
12374         }
12375 }
12376 
12377 /*
12378  * This function is invoked from the taskq thread to allocate
12379  * devinfo nodes and to online/offline them.
12380  */
12381 static void
12382 fcp_hp_task(void *arg)
12383 {
12384         struct fcp_hp_elem      *elem = (struct fcp_hp_elem *)arg;
12385         struct fcp_lun  *plun = elem->lun;
12386         struct fcp_port         *pptr = elem->port;
12387         int                     result;
12388 
12389         ASSERT(elem->what == FCP_ONLINE ||
12390             elem->what == FCP_OFFLINE ||
12391             elem->what == FCP_MPXIO_PATH_CLEAR_BUSY ||
12392             elem->what == FCP_MPXIO_PATH_SET_BUSY);
12393 
12394         mutex_enter(&pptr->port_mutex);
12395         mutex_enter(&plun->lun_mutex);
12396         if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) &&
12397             plun->lun_event_count != elem->event_cnt) ||
12398             pptr->port_state & (FCP_STATE_SUSPENDED |
12399             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
12400                 mutex_exit(&plun->lun_mutex);
12401                 mutex_exit(&pptr->port_mutex);
12402                 fcp_process_elem(elem, NDI_FAILURE);
12403                 return;
12404         }
12405         mutex_exit(&plun->lun_mutex);
12406         mutex_exit(&pptr->port_mutex);
12407 
12408         result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio,
12409             elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags);
12410         fcp_process_elem(elem, result);
12411 }
12412 
12413 
12414 static child_info_t *
12415 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount,
12416     int tcount)
12417 {
12418         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12419 
12420         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
12421                 struct fcp_port *pptr = plun->lun_tgt->tgt_port;
12422 
12423                 ASSERT(MUTEX_HELD(&pptr->port_mutex));
12424                 /*
12425                  * Child has not been created yet. Create the child device
12426                  * based on the per-Lun flags.
12427                  */
12428                 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) {
12429                         plun->lun_cip =
12430                             CIP(fcp_create_dip(plun, lcount, tcount));
12431                         plun->lun_mpxio = 0;
12432                 } else {
12433                         plun->lun_cip =
12434                             CIP(fcp_create_pip(plun, lcount, tcount));
12435                         plun->lun_mpxio = 1;
12436                 }
12437         } else {
12438                 plun->lun_cip = cip;
12439         }
12440 
12441         return (plun->lun_cip);
12442 }
12443 
12444 
12445 static int
12446 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip)
12447 {
12448         int             rval = FC_FAILURE;
12449         dev_info_t      *pdip;
12450         struct dev_info *dip;
12451         int             circular;
12452 
12453         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12454 
12455         pdip = plun->lun_tgt->tgt_port->port_dip;
12456 
12457         if (plun->lun_cip == NULL) {
12458                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
12459                     fcp_trace, FCP_BUF_LEVEL_3, 0,
12460                     "fcp_is_dip_present: plun->lun_cip is NULL: "
12461                     "plun: %p lun state: %x num: %d target state: %x",
12462                     plun, plun->lun_state, plun->lun_num,
12463                     plun->lun_tgt->tgt_port->port_state);
12464                 return (rval);
12465         }
12466         ndi_devi_enter(pdip, &circular);
12467         dip = DEVI(pdip)->devi_child;
12468         while (dip) {
12469                 if (dip == DEVI(cdip)) {
12470                         rval = FC_SUCCESS;
12471                         break;
12472                 }
12473                 dip = dip->devi_sibling;
12474         }
12475         ndi_devi_exit(pdip, circular);
12476         return (rval);
12477 }
12478 
12479 static int
12480 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip)
12481 {
12482         int             rval = FC_FAILURE;
12483 
12484         ASSERT(plun != NULL);
12485         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12486 
12487         if (plun->lun_mpxio == 0) {
12488                 rval = fcp_is_dip_present(plun, DIP(cip));
12489         } else {
12490                 rval = fcp_is_pip_present(plun, PIP(cip));
12491         }
12492 
12493         return (rval);
12494 }
12495 
12496 /*
12497  *     Function: fcp_create_dip
12498  *
12499  *  Description: Creates a dev_info_t structure for the LUN specified by the
12500  *               caller.
12501  *
12502  *     Argument: plun           Lun structure
12503  *               link_cnt       Link state count.
12504  *               tgt_cnt        Target state change count.
12505  *
12506  * Return Value: NULL if it failed
12507  *               dev_info_t structure address if it succeeded
12508  *
12509  *      Context: Kernel context
12510  */
12511 static dev_info_t *
12512 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt)
12513 {
12514         int                     failure = 0;
12515         uint32_t                tgt_id;
12516         uint64_t                sam_lun;
12517         struct fcp_tgt  *ptgt = plun->lun_tgt;
12518         struct fcp_port *pptr = ptgt->tgt_port;
12519         dev_info_t              *pdip = pptr->port_dip;
12520         dev_info_t              *cdip = NULL;
12521         dev_info_t              *old_dip = DIP(plun->lun_cip);
12522         char                    *nname = NULL;
12523         char                    **compatible = NULL;
12524         int                     ncompatible;
12525         char                    *scsi_binding_set;
12526         char                    t_pwwn[17];
12527 
12528         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12529         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12530 
12531         /* get the 'scsi-binding-set' property */
12532         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
12533             DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
12534             &scsi_binding_set) != DDI_PROP_SUCCESS) {
12535                 scsi_binding_set = NULL;
12536         }
12537 
12538         /* determine the node name and compatible */
12539         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12540             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12541         if (scsi_binding_set) {
12542                 ddi_prop_free(scsi_binding_set);
12543         }
12544 
12545         if (nname == NULL) {
12546 #ifdef  DEBUG
12547                 cmn_err(CE_WARN, "%s%d: no driver for "
12548                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12549                     "    compatible: %s",
12550                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12551                     ptgt->tgt_port_wwn.raw_wwn[0],
12552                     ptgt->tgt_port_wwn.raw_wwn[1],
12553                     ptgt->tgt_port_wwn.raw_wwn[2],
12554                     ptgt->tgt_port_wwn.raw_wwn[3],
12555                     ptgt->tgt_port_wwn.raw_wwn[4],
12556                     ptgt->tgt_port_wwn.raw_wwn[5],
12557                     ptgt->tgt_port_wwn.raw_wwn[6],
12558                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12559                     *compatible);
12560 #endif  /* DEBUG */
12561                 failure++;
12562                 goto end_of_fcp_create_dip;
12563         }
12564 
12565         cdip = fcp_find_existing_dip(plun, pdip, nname);
12566 
12567         /*
12568          * if the old_dip does not match the cdip, that means there is
12569          * some property change. since we'll be using the cdip, we need
12570          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12571          * then the dtype for the device has been updated. Offline the
12572          * the old device and create a new device with the new device type
12573          * Refer to bug: 4764752
12574          */
12575         if (old_dip && (cdip != old_dip ||
12576             plun->lun_state & FCP_LUN_CHANGED)) {
12577                 plun->lun_state &= ~(FCP_LUN_INIT);
12578                 mutex_exit(&plun->lun_mutex);
12579                 mutex_exit(&pptr->port_mutex);
12580 
12581                 mutex_enter(&ptgt->tgt_mutex);
12582                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE,
12583                     link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0);
12584                 mutex_exit(&ptgt->tgt_mutex);
12585 
12586 #ifdef DEBUG
12587                 if (cdip != NULL) {
12588                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12589                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12590                             "Old dip=%p; New dip=%p don't match", old_dip,
12591                             cdip);
12592                 } else {
12593                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12594                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12595                             "Old dip=%p; New dip=NULL don't match", old_dip);
12596                 }
12597 #endif
12598 
12599                 mutex_enter(&pptr->port_mutex);
12600                 mutex_enter(&plun->lun_mutex);
12601         }
12602 
12603         if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12604                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12605                 if (ndi_devi_alloc(pptr->port_dip, nname,
12606                     DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) {
12607                         failure++;
12608                         goto end_of_fcp_create_dip;
12609                 }
12610         }
12611 
12612         /*
12613          * Previously all the properties for the devinfo were destroyed here
12614          * with a call to ndi_prop_remove_all(). Since this may cause loss of
12615          * the devid property (and other properties established by the target
12616          * driver or framework) which the code does not always recreate, this
12617          * call was removed.
12618          * This opens a theoretical possibility that we may return with a
12619          * stale devid on the node if the scsi entity behind the fibre channel
12620          * lun has changed.
12621          */
12622 
12623         /* decorate the node with compatible */
12624         if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
12625             "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) {
12626                 failure++;
12627                 goto end_of_fcp_create_dip;
12628         }
12629 
12630         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP,
12631             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12632                 failure++;
12633                 goto end_of_fcp_create_dip;
12634         }
12635 
12636         if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP,
12637             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) {
12638                 failure++;
12639                 goto end_of_fcp_create_dip;
12640         }
12641 
12642         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12643         t_pwwn[16] = '\0';
12644         if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn)
12645             != DDI_PROP_SUCCESS) {
12646                 failure++;
12647                 goto end_of_fcp_create_dip;
12648         }
12649 
12650         /*
12651          * If there is no hard address - We might have to deal with
12652          * that by using WWN - Having said that it is important to
12653          * recognize this problem early so ssd can be informed of
12654          * the right interconnect type.
12655          */
12656         if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) {
12657                 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12658         } else {
12659                 tgt_id = ptgt->tgt_d_id;
12660         }
12661 
12662         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP,
12663             tgt_id) != DDI_PROP_SUCCESS) {
12664                 failure++;
12665                 goto end_of_fcp_create_dip;
12666         }
12667 
12668         if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP,
12669             (int)plun->lun_num) != DDI_PROP_SUCCESS) {
12670                 failure++;
12671                 goto end_of_fcp_create_dip;
12672         }
12673         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12674         if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP,
12675             sam_lun) != DDI_PROP_SUCCESS) {
12676                 failure++;
12677                 goto end_of_fcp_create_dip;
12678         }
12679 
12680 end_of_fcp_create_dip:
12681         scsi_hba_nodename_compatible_free(nname, compatible);
12682 
12683         if (cdip != NULL && failure) {
12684                 (void) ndi_prop_remove_all(cdip);
12685                 (void) ndi_devi_free(cdip);
12686                 cdip = NULL;
12687         }
12688 
12689         return (cdip);
12690 }
12691 
12692 /*
12693  *     Function: fcp_create_pip
12694  *
12695  *  Description: Creates a Path Id for the LUN specified by the caller.
12696  *
12697  *     Argument: plun           Lun structure
12698  *               link_cnt       Link state count.
12699  *               tgt_cnt        Target state count.
12700  *
12701  * Return Value: NULL if it failed
12702  *               mdi_pathinfo_t structure address if it succeeded
12703  *
12704  *      Context: Kernel context
12705  */
12706 static mdi_pathinfo_t *
12707 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount)
12708 {
12709         int                     i;
12710         char                    buf[MAXNAMELEN];
12711         char                    uaddr[MAXNAMELEN];
12712         int                     failure = 0;
12713         uint32_t                tgt_id;
12714         uint64_t                sam_lun;
12715         struct fcp_tgt  *ptgt = plun->lun_tgt;
12716         struct fcp_port *pptr = ptgt->tgt_port;
12717         dev_info_t              *pdip = pptr->port_dip;
12718         mdi_pathinfo_t          *pip = NULL;
12719         mdi_pathinfo_t          *old_pip = PIP(plun->lun_cip);
12720         char                    *nname = NULL;
12721         char                    **compatible = NULL;
12722         int                     ncompatible;
12723         char                    *scsi_binding_set;
12724         char                    t_pwwn[17];
12725 
12726         ASSERT(MUTEX_HELD(&plun->lun_mutex));
12727         ASSERT(MUTEX_HELD(&pptr->port_mutex));
12728 
12729         scsi_binding_set = "vhci";
12730 
12731         /* determine the node name and compatible */
12732         scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set,
12733             plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible);
12734 
12735         if (nname == NULL) {
12736 #ifdef  DEBUG
12737                 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for "
12738                     "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:"
12739                     "    compatible: %s",
12740                     ddi_driver_name(pdip), ddi_get_instance(pdip),
12741                     ptgt->tgt_port_wwn.raw_wwn[0],
12742                     ptgt->tgt_port_wwn.raw_wwn[1],
12743                     ptgt->tgt_port_wwn.raw_wwn[2],
12744                     ptgt->tgt_port_wwn.raw_wwn[3],
12745                     ptgt->tgt_port_wwn.raw_wwn[4],
12746                     ptgt->tgt_port_wwn.raw_wwn[5],
12747                     ptgt->tgt_port_wwn.raw_wwn[6],
12748                     ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num,
12749                     *compatible);
12750 #endif  /* DEBUG */
12751                 failure++;
12752                 goto end_of_fcp_create_pip;
12753         }
12754 
12755         pip = fcp_find_existing_pip(plun, pdip);
12756 
12757         /*
12758          * if the old_dip does not match the cdip, that means there is
12759          * some property change. since we'll be using the cdip, we need
12760          * to offline the old_dip. If the state contains FCP_LUN_CHANGED
12761          * then the dtype for the device has been updated. Offline the
12762          * the old device and create a new device with the new device type
12763          * Refer to bug: 4764752
12764          */
12765         if (old_pip && (pip != old_pip ||
12766             plun->lun_state & FCP_LUN_CHANGED)) {
12767                 plun->lun_state &= ~(FCP_LUN_INIT);
12768                 mutex_exit(&plun->lun_mutex);
12769                 mutex_exit(&pptr->port_mutex);
12770 
12771                 mutex_enter(&ptgt->tgt_mutex);
12772                 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip),
12773                     FCP_OFFLINE, lcount, tcount,
12774                     NDI_DEVI_REMOVE, 0);
12775                 mutex_exit(&ptgt->tgt_mutex);
12776 
12777                 if (pip != NULL) {
12778                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12779                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12780                             "Old pip=%p; New pip=%p don't match",
12781                             old_pip, pip);
12782                 } else {
12783                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
12784                             fcp_trace, FCP_BUF_LEVEL_2, 0,
12785                             "Old pip=%p; New pip=NULL don't match",
12786                             old_pip);
12787                 }
12788 
12789                 mutex_enter(&pptr->port_mutex);
12790                 mutex_enter(&plun->lun_mutex);
12791         }
12792 
12793         /*
12794          * Since FC_WWN_SIZE is 8 bytes and its not like the
12795          * lun_guid_size which is dependent on the target, I don't
12796          * believe the same trancation happens here UNLESS the standards
12797          * change the FC_WWN_SIZE value to something larger than
12798          * MAXNAMELEN(currently 255 bytes).
12799          */
12800 
12801         for (i = 0; i < FC_WWN_SIZE; i++) {
12802                 (void) sprintf(&buf[i << 1], "%02x",
12803                     ptgt->tgt_port_wwn.raw_wwn[i]);
12804         }
12805 
12806         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x",
12807             buf, plun->lun_num);
12808 
12809         if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) {
12810                 /*
12811                  * Release the locks before calling into
12812                  * mdi_pi_alloc_compatible() since this can result in a
12813                  * callback into fcp which can result in a deadlock
12814                  * (see bug # 4870272).
12815                  *
12816                  * Basically, what we are trying to avoid is the scenario where
12817                  * one thread does ndi_devi_enter() and tries to grab
12818                  * fcp_mutex and another does it the other way round.
12819                  *
12820                  * But before we do that, make sure that nobody releases the
12821                  * port in the meantime. We can do this by setting a flag.
12822                  */
12823                 plun->lun_state &= ~(FCP_LUN_CHANGED);
12824                 pptr->port_state |= FCP_STATE_IN_MDI;
12825                 mutex_exit(&plun->lun_mutex);
12826                 mutex_exit(&pptr->port_mutex);
12827                 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid,
12828                     uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) {
12829                         fcp_log(CE_WARN, pptr->port_dip,
12830                             "!path alloc failed:0x%x", plun);
12831                         mutex_enter(&pptr->port_mutex);
12832                         mutex_enter(&plun->lun_mutex);
12833                         pptr->port_state &= ~FCP_STATE_IN_MDI;
12834                         failure++;
12835                         goto end_of_fcp_create_pip;
12836                 }
12837                 mutex_enter(&pptr->port_mutex);
12838                 mutex_enter(&plun->lun_mutex);
12839                 pptr->port_state &= ~FCP_STATE_IN_MDI;
12840         } else {
12841                 (void) mdi_prop_remove(pip, NULL);
12842         }
12843 
12844         mdi_pi_set_phci_private(pip, (caddr_t)plun);
12845 
12846         if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP,
12847             ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE)
12848             != DDI_PROP_SUCCESS) {
12849                 failure++;
12850                 goto end_of_fcp_create_pip;
12851         }
12852 
12853         if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP,
12854             ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE)
12855             != DDI_PROP_SUCCESS) {
12856                 failure++;
12857                 goto end_of_fcp_create_pip;
12858         }
12859 
12860         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn);
12861         t_pwwn[16] = '\0';
12862         if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn)
12863             != DDI_PROP_SUCCESS) {
12864                 failure++;
12865                 goto end_of_fcp_create_pip;
12866         }
12867 
12868         /*
12869          * If there is no hard address - We might have to deal with
12870          * that by using WWN - Having said that it is important to
12871          * recognize this problem early so ssd can be informed of
12872          * the right interconnect type.
12873          */
12874         if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
12875             ptgt->tgt_hard_addr != 0) {
12876                 tgt_id = (uint32_t)
12877                     fcp_alpa_to_switch[ptgt->tgt_hard_addr];
12878         } else {
12879                 tgt_id = ptgt->tgt_d_id;
12880         }
12881 
12882         if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id)
12883             != DDI_PROP_SUCCESS) {
12884                 failure++;
12885                 goto end_of_fcp_create_pip;
12886         }
12887 
12888         if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num)
12889             != DDI_PROP_SUCCESS) {
12890                 failure++;
12891                 goto end_of_fcp_create_pip;
12892         }
12893         bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE);
12894         if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun)
12895             != DDI_PROP_SUCCESS) {
12896                 failure++;
12897                 goto end_of_fcp_create_pip;
12898         }
12899 
12900 end_of_fcp_create_pip:
12901         scsi_hba_nodename_compatible_free(nname, compatible);
12902 
12903         if (pip != NULL && failure) {
12904                 (void) mdi_prop_remove(pip, NULL);
12905                 mutex_exit(&plun->lun_mutex);
12906                 mutex_exit(&pptr->port_mutex);
12907                 (void) mdi_pi_free(pip, 0);
12908                 mutex_enter(&pptr->port_mutex);
12909                 mutex_enter(&plun->lun_mutex);
12910                 pip = NULL;
12911         }
12912 
12913         return (pip);
12914 }
12915 
12916 static dev_info_t *
12917 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name)
12918 {
12919         uint_t                  nbytes;
12920         uchar_t                 *bytes;
12921         uint_t                  nwords;
12922         uint32_t                tgt_id;
12923         int                     *words;
12924         dev_info_t              *cdip;
12925         dev_info_t              *ndip;
12926         struct fcp_tgt  *ptgt = plun->lun_tgt;
12927         struct fcp_port *pptr = ptgt->tgt_port;
12928         int                     circular;
12929 
12930         ndi_devi_enter(pdip, &circular);
12931 
12932         ndip = (dev_info_t *)DEVI(pdip)->devi_child;
12933         while ((cdip = ndip) != NULL) {
12934                 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling;
12935 
12936                 if (strcmp(DEVI(cdip)->devi_node_name, name)) {
12937                         continue;
12938                 }
12939 
12940                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12941                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes,
12942                     &nbytes) != DDI_PROP_SUCCESS) {
12943                         continue;
12944                 }
12945 
12946                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12947                         if (bytes != NULL) {
12948                                 ddi_prop_free(bytes);
12949                         }
12950                         continue;
12951                 }
12952                 ASSERT(bytes != NULL);
12953 
12954                 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) {
12955                         ddi_prop_free(bytes);
12956                         continue;
12957                 }
12958 
12959                 ddi_prop_free(bytes);
12960 
12961                 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip,
12962                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes,
12963                     &nbytes) != DDI_PROP_SUCCESS) {
12964                         continue;
12965                 }
12966 
12967                 if (nbytes != FC_WWN_SIZE || bytes == NULL) {
12968                         if (bytes != NULL) {
12969                                 ddi_prop_free(bytes);
12970                         }
12971                         continue;
12972                 }
12973                 ASSERT(bytes != NULL);
12974 
12975                 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) {
12976                         ddi_prop_free(bytes);
12977                         continue;
12978                 }
12979 
12980                 ddi_prop_free(bytes);
12981 
12982                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
12983                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words,
12984                     &nwords) != DDI_PROP_SUCCESS) {
12985                         continue;
12986                 }
12987 
12988                 if (nwords != 1 || words == NULL) {
12989                         if (words != NULL) {
12990                                 ddi_prop_free(words);
12991                         }
12992                         continue;
12993                 }
12994                 ASSERT(words != NULL);
12995 
12996                 /*
12997                  * If there is no hard address - We might have to deal with
12998                  * that by using WWN - Having said that it is important to
12999                  * recognize this problem early so ssd can be informed of
13000                  * the right interconnect type.
13001                  */
13002                 if (!FC_TOP_EXTERNAL(pptr->port_topology) &&
13003                     ptgt->tgt_hard_addr != 0) {
13004                         tgt_id =
13005                             (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr];
13006                 } else {
13007                         tgt_id = ptgt->tgt_d_id;
13008                 }
13009 
13010                 if (tgt_id != (uint32_t)*words) {
13011                         ddi_prop_free(words);
13012                         continue;
13013                 }
13014                 ddi_prop_free(words);
13015 
13016                 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
13017                     DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words,
13018                     &nwords) != DDI_PROP_SUCCESS) {
13019                         continue;
13020                 }
13021 
13022                 if (nwords != 1 || words == NULL) {
13023                         if (words != NULL) {
13024                                 ddi_prop_free(words);
13025                         }
13026                         continue;
13027                 }
13028                 ASSERT(words != NULL);
13029 
13030                 if (plun->lun_num == (uint16_t)*words) {
13031                         ddi_prop_free(words);
13032                         break;
13033                 }
13034                 ddi_prop_free(words);
13035         }
13036         ndi_devi_exit(pdip, circular);
13037 
13038         return (cdip);
13039 }
13040 
13041 
13042 static int
13043 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip)
13044 {
13045         dev_info_t      *pdip;
13046         char            buf[MAXNAMELEN];
13047         char            uaddr[MAXNAMELEN];
13048         int             rval = FC_FAILURE;
13049 
13050         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13051 
13052         pdip = plun->lun_tgt->tgt_port->port_dip;
13053 
13054         /*
13055          * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be
13056          * non-NULL even when the LUN is not there as in the case when a LUN is
13057          * configured and then deleted on the device end (for T3/T4 case). In
13058          * such cases, pip will be NULL.
13059          *
13060          * If the device generates an RSCN, it will end up getting offlined when
13061          * it disappeared and a new LUN will get created when it is rediscovered
13062          * on the device. If we check for lun_cip here, the LUN will not end
13063          * up getting onlined since this function will end up returning a
13064          * FC_SUCCESS.
13065          *
13066          * The behavior is different on other devices. For instance, on a HDS,
13067          * there was no RSCN generated by the device but the next I/O generated
13068          * a check condition and rediscovery got triggered that way. So, in
13069          * such cases, this path will not be exercised
13070          */
13071         if (pip == NULL) {
13072                 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf,
13073                     fcp_trace, FCP_BUF_LEVEL_4, 0,
13074                     "fcp_is_pip_present: plun->lun_cip is NULL: "
13075                     "plun: %p lun state: %x num: %d target state: %x",
13076                     plun, plun->lun_state, plun->lun_num,
13077                     plun->lun_tgt->tgt_port->port_state);
13078                 return (rval);
13079         }
13080 
13081         fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf);
13082 
13083         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13084 
13085         if (plun->lun_old_guid) {
13086                 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) {
13087                         rval = FC_SUCCESS;
13088                 }
13089         } else {
13090                 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) {
13091                         rval = FC_SUCCESS;
13092                 }
13093         }
13094         return (rval);
13095 }
13096 
13097 static mdi_pathinfo_t *
13098 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip)
13099 {
13100         char                    buf[MAXNAMELEN];
13101         char                    uaddr[MAXNAMELEN];
13102         mdi_pathinfo_t          *pip;
13103         struct fcp_tgt  *ptgt = plun->lun_tgt;
13104         struct fcp_port *pptr = ptgt->tgt_port;
13105 
13106         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13107 
13108         fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf);
13109         (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num);
13110 
13111         pip = mdi_pi_find(pdip, plun->lun_guid, uaddr);
13112 
13113         return (pip);
13114 }
13115 
13116 
13117 static int
13118 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13119     int tcount, int flags, int *circ)
13120 {
13121         int                     rval;
13122         struct fcp_port         *pptr = plun->lun_tgt->tgt_port;
13123         struct fcp_tgt  *ptgt = plun->lun_tgt;
13124         dev_info_t              *cdip = NULL;
13125 
13126         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13127         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13128 
13129         if (plun->lun_cip == NULL) {
13130                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13131                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13132                     "fcp_online_child: plun->lun_cip is NULL: "
13133                     "plun: %p state: %x num: %d target state: %x",
13134                     plun, plun->lun_state, plun->lun_num,
13135                     plun->lun_tgt->tgt_port->port_state);
13136                 return (NDI_FAILURE);
13137         }
13138 again:
13139         if (plun->lun_mpxio == 0) {
13140                 cdip = DIP(cip);
13141                 mutex_exit(&plun->lun_mutex);
13142                 mutex_exit(&pptr->port_mutex);
13143 
13144                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13145                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13146                     "!Invoking ndi_devi_online for %s: target=%x lun=%x",
13147                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13148 
13149                 /*
13150                  * We could check for FCP_LUN_INIT here but chances
13151                  * of getting here when it's already in FCP_LUN_INIT
13152                  * is rare and a duplicate ndi_devi_online wouldn't
13153                  * hurt either (as the node would already have been
13154                  * in CF2)
13155                  */
13156                 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) {
13157                         rval = ndi_devi_bind_driver(cdip, flags);
13158                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13159                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13160                             "!Invoking ndi_devi_bind_driver: rval=%d", rval);
13161                 } else {
13162                         rval = ndi_devi_online(cdip, flags);
13163                 }
13164 
13165                 /*
13166                  * We log the message into trace buffer if the device
13167                  * is "ses" and into syslog for any other device
13168                  * type. This is to prevent the ndi_devi_online failure
13169                  * message that appears for V880/A5K ses devices.
13170                  */
13171                 if (rval == NDI_SUCCESS) {
13172                         mutex_enter(&ptgt->tgt_mutex);
13173                         plun->lun_state |= FCP_LUN_INIT;
13174                         mutex_exit(&ptgt->tgt_mutex);
13175                 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) {
13176                         fcp_log(CE_NOTE, pptr->port_dip,
13177                             "!ndi_devi_online:"
13178                             " failed for %s: target=%x lun=%x %x",
13179                             ddi_get_name(cdip), ptgt->tgt_d_id,
13180                             plun->lun_num, rval);
13181                 } else {
13182                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13183                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13184                             " !ndi_devi_online:"
13185                             " failed for %s: target=%x lun=%x %x",
13186                             ddi_get_name(cdip), ptgt->tgt_d_id,
13187                             plun->lun_num, rval);
13188                 }
13189         } else {
13190                 cdip = mdi_pi_get_client(PIP(cip));
13191                 mutex_exit(&plun->lun_mutex);
13192                 mutex_exit(&pptr->port_mutex);
13193 
13194                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13195                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13196                     "!Invoking mdi_pi_online for %s: target=%x lun=%x",
13197                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13198 
13199                 /*
13200                  * Hold path and exit phci to avoid deadlock with power
13201                  * management code during mdi_pi_online.
13202                  */
13203                 mdi_hold_path(PIP(cip));
13204                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13205 
13206                 rval = mdi_pi_online(PIP(cip), flags);
13207 
13208                 mdi_devi_enter_phci(pptr->port_dip, circ);
13209                 mdi_rele_path(PIP(cip));
13210 
13211                 if (rval == MDI_SUCCESS) {
13212                         mutex_enter(&ptgt->tgt_mutex);
13213                         plun->lun_state |= FCP_LUN_INIT;
13214                         mutex_exit(&ptgt->tgt_mutex);
13215 
13216                         /*
13217                          * Clear MPxIO path permanent disable in case
13218                          * fcp hotplug dropped the offline event.
13219                          */
13220                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13221 
13222                 } else if (rval == MDI_NOT_SUPPORTED) {
13223                         child_info_t    *old_cip = cip;
13224 
13225                         /*
13226                          * MPxIO does not support this device yet.
13227                          * Enumerate in legacy mode.
13228                          */
13229                         mutex_enter(&pptr->port_mutex);
13230                         mutex_enter(&plun->lun_mutex);
13231                         plun->lun_mpxio = 0;
13232                         plun->lun_cip = NULL;
13233                         cdip = fcp_create_dip(plun, lcount, tcount);
13234                         plun->lun_cip = cip = CIP(cdip);
13235                         if (cip == NULL) {
13236                                 fcp_log(CE_WARN, pptr->port_dip,
13237                                     "!fcp_online_child: "
13238                                     "Create devinfo failed for LU=%p", plun);
13239                                 mutex_exit(&plun->lun_mutex);
13240 
13241                                 mutex_enter(&ptgt->tgt_mutex);
13242                                 plun->lun_state |= FCP_LUN_OFFLINE;
13243                                 mutex_exit(&ptgt->tgt_mutex);
13244 
13245                                 mutex_exit(&pptr->port_mutex);
13246 
13247                                 /*
13248                                  * free the mdi_pathinfo node
13249                                  */
13250                                 (void) mdi_pi_free(PIP(old_cip), 0);
13251                         } else {
13252                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13253                                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13254                                     "fcp_online_child: creating devinfo "
13255                                     "node 0x%p for plun 0x%p",
13256                                     cip, plun);
13257                                 mutex_exit(&plun->lun_mutex);
13258                                 mutex_exit(&pptr->port_mutex);
13259                                 /*
13260                                  * free the mdi_pathinfo node
13261                                  */
13262                                 (void) mdi_pi_free(PIP(old_cip), 0);
13263                                 mutex_enter(&pptr->port_mutex);
13264                                 mutex_enter(&plun->lun_mutex);
13265                                 goto again;
13266                         }
13267                 } else {
13268                         if (cdip) {
13269                                 fcp_log(CE_NOTE, pptr->port_dip,
13270                                     "!fcp_online_child: mdi_pi_online:"
13271                                     " failed for %s: target=%x lun=%x %x",
13272                                     ddi_get_name(cdip), ptgt->tgt_d_id,
13273                                     plun->lun_num, rval);
13274                         }
13275                 }
13276                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13277         }
13278 
13279         if (rval == NDI_SUCCESS) {
13280                 if (cdip) {
13281                         (void) ndi_event_retrieve_cookie(
13282                             pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT,
13283                             &fcp_insert_eid, NDI_EVENT_NOPASS);
13284                         (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl,
13285                             cdip, fcp_insert_eid, NULL);
13286                 }
13287         }
13288         mutex_enter(&pptr->port_mutex);
13289         mutex_enter(&plun->lun_mutex);
13290         return (rval);
13291 }
13292 
13293 /* ARGSUSED */
13294 static int
13295 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount,
13296     int tcount, int flags, int *circ)
13297 {
13298         int             rval;
13299         int             lun_mpxio;
13300         struct fcp_port *pptr = plun->lun_tgt->tgt_port;
13301         struct fcp_tgt  *ptgt = plun->lun_tgt;
13302         dev_info_t      *cdip;
13303 
13304         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13305         ASSERT(MUTEX_HELD(&pptr->port_mutex));
13306 
13307         if (plun->lun_cip == NULL) {
13308                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13309                     fcp_trace, FCP_BUF_LEVEL_3, 0,
13310                     "fcp_offline_child: plun->lun_cip is NULL: "
13311                     "plun: %p lun state: %x num: %d target state: %x",
13312                     plun, plun->lun_state, plun->lun_num,
13313                     plun->lun_tgt->tgt_port->port_state);
13314                 return (NDI_FAILURE);
13315         }
13316 
13317         /*
13318          * We will use this value twice. Make a copy to be sure we use
13319          * the same value in both places.
13320          */
13321         lun_mpxio = plun->lun_mpxio;
13322 
13323         if (lun_mpxio == 0) {
13324                 cdip = DIP(cip);
13325                 mutex_exit(&plun->lun_mutex);
13326                 mutex_exit(&pptr->port_mutex);
13327                 rval = ndi_devi_offline(DIP(cip), flags);
13328                 if (rval != NDI_SUCCESS) {
13329                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13330                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13331                             "fcp_offline_child: ndi_devi_offline failed "
13332                             "rval=%x cip=%p", rval, cip);
13333                 }
13334         } else {
13335                 cdip = mdi_pi_get_client(PIP(cip));
13336                 mutex_exit(&plun->lun_mutex);
13337                 mutex_exit(&pptr->port_mutex);
13338 
13339                 /*
13340                  * Exit phci to avoid deadlock with power management code
13341                  * during mdi_pi_offline
13342                  */
13343                 mdi_hold_path(PIP(cip));
13344                 mdi_devi_exit_phci(pptr->port_dip, *circ);
13345 
13346                 rval = mdi_pi_offline(PIP(cip), flags);
13347 
13348                 mdi_devi_enter_phci(pptr->port_dip, circ);
13349                 mdi_rele_path(PIP(cip));
13350 
13351                 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE;
13352         }
13353 
13354         mutex_enter(&ptgt->tgt_mutex);
13355         plun->lun_state &= ~FCP_LUN_INIT;
13356         mutex_exit(&ptgt->tgt_mutex);
13357 
13358         if (rval == NDI_SUCCESS) {
13359                 cdip = NULL;
13360                 if (flags & NDI_DEVI_REMOVE) {
13361                         mutex_enter(&plun->lun_mutex);
13362                         /*
13363                          * If the guid of the LUN changes, lun_cip will not
13364                          * equal to cip, and after offlining the LUN with the
13365                          * old guid, we should keep lun_cip since it's the cip
13366                          * of the LUN with the new guid.
13367                          * Otherwise remove our reference to child node.
13368                          *
13369                          * This must be done before the child node is freed,
13370                          * otherwise other threads could see a stale lun_cip
13371                          * pointer.
13372                          */
13373                         if (plun->lun_cip == cip) {
13374                                 plun->lun_cip = NULL;
13375                         }
13376                         if (plun->lun_old_guid) {
13377                                 kmem_free(plun->lun_old_guid,
13378                                     plun->lun_old_guid_size);
13379                                 plun->lun_old_guid = NULL;
13380                                 plun->lun_old_guid_size = 0;
13381                         }
13382                         mutex_exit(&plun->lun_mutex);
13383                 }
13384         }
13385 
13386         if (lun_mpxio != 0) {
13387                 if (rval == NDI_SUCCESS) {
13388                         /*
13389                          * Clear MPxIO path permanent disable as the path is
13390                          * already offlined.
13391                          */
13392                         (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE);
13393 
13394                         if (flags & NDI_DEVI_REMOVE) {
13395                                 (void) mdi_pi_free(PIP(cip), 0);
13396                         }
13397                 } else {
13398                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
13399                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13400                             "fcp_offline_child: mdi_pi_offline failed "
13401                             "rval=%x cip=%p", rval, cip);
13402                 }
13403         }
13404 
13405         mutex_enter(&pptr->port_mutex);
13406         mutex_enter(&plun->lun_mutex);
13407 
13408         if (cdip) {
13409                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13410                     fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:"
13411                     " target=%x lun=%x", "ndi_offline",
13412                     ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num);
13413         }
13414 
13415         return (rval);
13416 }
13417 
13418 static void
13419 fcp_remove_child(struct fcp_lun *plun)
13420 {
13421         child_info_t *cip;
13422         int circ;
13423 
13424         ASSERT(MUTEX_HELD(&plun->lun_mutex));
13425 
13426         if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) {
13427                 if (plun->lun_mpxio == 0) {
13428                         (void) ndi_prop_remove_all(DIP(plun->lun_cip));
13429                         (void) ndi_devi_free(DIP(plun->lun_cip));
13430                         plun->lun_cip = NULL;
13431                 } else {
13432                         /*
13433                          * Clear reference to the child node in the lun.
13434                          * This must be done before freeing it with mdi_pi_free
13435                          * and with lun_mutex held so that other threads always
13436                          * see either valid lun_cip or NULL when holding
13437                          * lun_mutex. We keep a copy in cip.
13438                          */
13439                         cip = plun->lun_cip;
13440                         plun->lun_cip = NULL;
13441 
13442                         mutex_exit(&plun->lun_mutex);
13443                         mutex_exit(&plun->lun_tgt->tgt_mutex);
13444                         mutex_exit(&plun->lun_tgt->tgt_port->port_mutex);
13445 
13446                         mdi_devi_enter(
13447                             plun->lun_tgt->tgt_port->port_dip, &circ);
13448 
13449                         /*
13450                          * Exit phci to avoid deadlock with power management
13451                          * code during mdi_pi_offline
13452                          */
13453                         mdi_hold_path(PIP(cip));
13454                         mdi_devi_exit_phci(
13455                             plun->lun_tgt->tgt_port->port_dip, circ);
13456                         (void) mdi_pi_offline(PIP(cip),
13457                             NDI_DEVI_REMOVE);
13458                         mdi_devi_enter_phci(
13459                             plun->lun_tgt->tgt_port->port_dip, &circ);
13460                         mdi_rele_path(PIP(cip));
13461 
13462                         mdi_devi_exit(
13463                             plun->lun_tgt->tgt_port->port_dip, circ);
13464 
13465                         FCP_TRACE(fcp_logq,
13466                             plun->lun_tgt->tgt_port->port_instbuf,
13467                             fcp_trace, FCP_BUF_LEVEL_3, 0,
13468                             "lun=%p pip freed %p", plun, cip);
13469 
13470                         (void) mdi_prop_remove(PIP(cip), NULL);
13471                         (void) mdi_pi_free(PIP(cip), 0);
13472 
13473                         mutex_enter(&plun->lun_tgt->tgt_port->port_mutex);
13474                         mutex_enter(&plun->lun_tgt->tgt_mutex);
13475                         mutex_enter(&plun->lun_mutex);
13476                 }
13477         } else {
13478                 plun->lun_cip = NULL;
13479         }
13480 }
13481 
13482 /*
13483  * called when a timeout occurs
13484  *
13485  * can be scheduled during an attach or resume (if not already running)
13486  *
13487  * one timeout is set up for all ports
13488  *
13489  * acquires and releases the global mutex
13490  */
13491 /*ARGSUSED*/
13492 static void
13493 fcp_watch(void *arg)
13494 {
13495         struct fcp_port *pptr;
13496         struct fcp_ipkt *icmd;
13497         struct fcp_ipkt *nicmd;
13498         struct fcp_pkt  *cmd;
13499         struct fcp_pkt  *ncmd;
13500         struct fcp_pkt  *tail;
13501         struct fcp_pkt  *pcmd;
13502         struct fcp_pkt  *save_head;
13503         struct fcp_port *save_port;
13504 
13505         /* increment global watchdog time */
13506         fcp_watchdog_time += fcp_watchdog_timeout;
13507 
13508         mutex_enter(&fcp_global_mutex);
13509 
13510         /* scan each port in our list */
13511         for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) {
13512                 save_port = fcp_port_head;
13513                 pptr->port_state |= FCP_STATE_IN_WATCHDOG;
13514                 mutex_exit(&fcp_global_mutex);
13515 
13516                 mutex_enter(&pptr->port_mutex);
13517                 if (pptr->port_ipkt_list == NULL &&
13518                     (pptr->port_state & (FCP_STATE_SUSPENDED |
13519                     FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) {
13520                         pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13521                         mutex_exit(&pptr->port_mutex);
13522                         mutex_enter(&fcp_global_mutex);
13523                         goto end_of_watchdog;
13524                 }
13525 
13526                 /*
13527                  * We check if a list of targets need to be offlined.
13528                  */
13529                 if (pptr->port_offline_tgts) {
13530                         fcp_scan_offline_tgts(pptr);
13531                 }
13532 
13533                 /*
13534                  * We check if a list of luns need to be offlined.
13535                  */
13536                 if (pptr->port_offline_luns) {
13537                         fcp_scan_offline_luns(pptr);
13538                 }
13539 
13540                 /*
13541                  * We check if a list of targets or luns need to be reset.
13542                  */
13543                 if (pptr->port_reset_list) {
13544                         fcp_check_reset_delay(pptr);
13545                 }
13546 
13547                 mutex_exit(&pptr->port_mutex);
13548 
13549                 /*
13550                  * This is where the pending commands (pkt) are checked for
13551                  * timeout.
13552                  */
13553                 mutex_enter(&pptr->port_pkt_mutex);
13554                 tail = pptr->port_pkt_tail;
13555 
13556                 for (pcmd = NULL, cmd = pptr->port_pkt_head;
13557                     cmd != NULL; cmd = ncmd) {
13558                         ncmd = cmd->cmd_next;
13559                         /*
13560                          * If a command is in this queue the bit CFLAG_IN_QUEUE
13561                          * must be set.
13562                          */
13563                         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
13564                         /*
13565                          * FCP_INVALID_TIMEOUT will be set for those
13566                          * command that need to be failed. Mostly those
13567                          * cmds that could not be queued down for the
13568                          * "timeout" value. cmd->cmd_timeout is used
13569                          * to try and requeue the command regularly.
13570                          */
13571                         if (cmd->cmd_timeout >= fcp_watchdog_time) {
13572                                 /*
13573                                  * This command hasn't timed out yet.  Let's
13574                                  * go to the next one.
13575                                  */
13576                                 pcmd = cmd;
13577                                 goto end_of_loop;
13578                         }
13579 
13580                         if (cmd == pptr->port_pkt_head) {
13581                                 ASSERT(pcmd == NULL);
13582                                 pptr->port_pkt_head = cmd->cmd_next;
13583                         } else {
13584                                 ASSERT(pcmd != NULL);
13585                                 pcmd->cmd_next = cmd->cmd_next;
13586                         }
13587 
13588                         if (cmd == pptr->port_pkt_tail) {
13589                                 ASSERT(cmd->cmd_next == NULL);
13590                                 pptr->port_pkt_tail = pcmd;
13591                                 if (pcmd) {
13592                                         pcmd->cmd_next = NULL;
13593                                 }
13594                         }
13595                         cmd->cmd_next = NULL;
13596 
13597                         /*
13598                          * save the current head before dropping the
13599                          * mutex - If the head doesn't remain the
13600                          * same after re acquiring the mutex, just
13601                          * bail out and revisit on next tick.
13602                          *
13603                          * PS: The tail pointer can change as the commands
13604                          * get requeued after failure to retransport
13605                          */
13606                         save_head = pptr->port_pkt_head;
13607                         mutex_exit(&pptr->port_pkt_mutex);
13608 
13609                         if (cmd->cmd_fp_pkt->pkt_timeout ==
13610                             FCP_INVALID_TIMEOUT) {
13611                                 struct scsi_pkt         *pkt = cmd->cmd_pkt;
13612                                 struct fcp_lun  *plun;
13613                                 struct fcp_tgt  *ptgt;
13614 
13615                                 plun = ADDR2LUN(&pkt->pkt_address);
13616                                 ptgt = plun->lun_tgt;
13617 
13618                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13619                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13620                                     "SCSI cmd 0x%x to D_ID=%x timed out",
13621                                     pkt->pkt_cdbp[0], ptgt->tgt_d_id);
13622 
13623                                 cmd->cmd_state == FCP_PKT_ABORTING ?
13624                                     fcp_fail_cmd(cmd, CMD_RESET,
13625                                     STAT_DEV_RESET) : fcp_fail_cmd(cmd,
13626                                     CMD_TIMEOUT, STAT_ABORTED);
13627                         } else {
13628                                 fcp_retransport_cmd(pptr, cmd);
13629                         }
13630                         mutex_enter(&pptr->port_pkt_mutex);
13631                         if (save_head && save_head != pptr->port_pkt_head) {
13632                                 /*
13633                                  * Looks like linked list got changed (mostly
13634                                  * happens when an an OFFLINE LUN code starts
13635                                  * returning overflow queue commands in
13636                                  * parallel. So bail out and revisit during
13637                                  * next tick
13638                                  */
13639                                 break;
13640                         }
13641                 end_of_loop:
13642                         /*
13643                          * Scan only upto the previously known tail pointer
13644                          * to avoid excessive processing - lots of new packets
13645                          * could have been added to the tail or the old ones
13646                          * re-queued.
13647                          */
13648                         if (cmd == tail) {
13649                                 break;
13650                         }
13651                 }
13652                 mutex_exit(&pptr->port_pkt_mutex);
13653 
13654                 mutex_enter(&pptr->port_mutex);
13655                 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) {
13656                         struct fcp_tgt *ptgt = icmd->ipkt_tgt;
13657 
13658                         nicmd = icmd->ipkt_next;
13659                         if ((icmd->ipkt_restart != 0) &&
13660                             (icmd->ipkt_restart >= fcp_watchdog_time)) {
13661                                 /* packet has not timed out */
13662                                 continue;
13663                         }
13664 
13665                         /* time for packet re-transport */
13666                         if (icmd == pptr->port_ipkt_list) {
13667                                 pptr->port_ipkt_list = icmd->ipkt_next;
13668                                 if (pptr->port_ipkt_list) {
13669                                         pptr->port_ipkt_list->ipkt_prev =
13670                                             NULL;
13671                                 }
13672                         } else {
13673                                 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next;
13674                                 if (icmd->ipkt_next) {
13675                                         icmd->ipkt_next->ipkt_prev =
13676                                             icmd->ipkt_prev;
13677                                 }
13678                         }
13679                         icmd->ipkt_next = NULL;
13680                         icmd->ipkt_prev = NULL;
13681                         mutex_exit(&pptr->port_mutex);
13682 
13683                         if (fcp_is_retryable(icmd)) {
13684                                 fc_ulp_rscn_info_t *rscnp =
13685                                     (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt->
13686                                     pkt_ulp_rscn_infop;
13687 
13688                                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
13689                                     fcp_trace, FCP_BUF_LEVEL_2, 0,
13690                                     "%x to D_ID=%x Retrying..",
13691                                     icmd->ipkt_opcode,
13692                                     icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id);
13693 
13694                                 /*
13695                                  * Update the RSCN count in the packet
13696                                  * before resending.
13697                                  */
13698 
13699                                 if (rscnp != NULL) {
13700                                         rscnp->ulp_rscn_count =
13701                                             fc_ulp_get_rscn_count(pptr->
13702                                             port_fp_handle);
13703                                 }
13704 
13705                                 mutex_enter(&pptr->port_mutex);
13706                                 mutex_enter(&ptgt->tgt_mutex);
13707                                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
13708                                         mutex_exit(&ptgt->tgt_mutex);
13709                                         mutex_exit(&pptr->port_mutex);
13710                                         switch (icmd->ipkt_opcode) {
13711                                                 int rval;
13712                                         case LA_ELS_PLOGI:
13713                                                 if ((rval = fc_ulp_login(
13714                                                     pptr->port_fp_handle,
13715                                                     &icmd->ipkt_fpkt, 1)) ==
13716                                                     FC_SUCCESS) {
13717                                                         mutex_enter(
13718                                                             &pptr->port_mutex);
13719                                                         continue;
13720                                                 }
13721                                                 if (fcp_handle_ipkt_errors(
13722                                                     pptr, ptgt, icmd, rval,
13723                                                     "PLOGI") == DDI_SUCCESS) {
13724                                                         mutex_enter(
13725                                                             &pptr->port_mutex);
13726                                                         continue;
13727                                                 }
13728                                                 break;
13729 
13730                                         case LA_ELS_PRLI:
13731                                                 if ((rval = fc_ulp_issue_els(
13732                                                     pptr->port_fp_handle,
13733                                                     icmd->ipkt_fpkt)) ==
13734                                                     FC_SUCCESS) {
13735                                                         mutex_enter(
13736                                                             &pptr->port_mutex);
13737                                                         continue;
13738                                                 }
13739                                                 if (fcp_handle_ipkt_errors(
13740                                                     pptr, ptgt, icmd, rval,
13741                                                     "PRLI") == DDI_SUCCESS) {
13742                                                         mutex_enter(
13743                                                             &pptr->port_mutex);
13744                                                         continue;
13745                                                 }
13746                                                 break;
13747 
13748                                         default:
13749                                                 if ((rval = fcp_transport(
13750                                                     pptr->port_fp_handle,
13751                                                     icmd->ipkt_fpkt, 1)) ==
13752                                                     FC_SUCCESS) {
13753                                                         mutex_enter(
13754                                                             &pptr->port_mutex);
13755                                                         continue;
13756                                                 }
13757                                                 if (fcp_handle_ipkt_errors(
13758                                                     pptr, ptgt, icmd, rval,
13759                                                     "PRLI") == DDI_SUCCESS) {
13760                                                         mutex_enter(
13761                                                             &pptr->port_mutex);
13762                                                         continue;
13763                                                 }
13764                                                 break;
13765                                         }
13766                                 } else {
13767                                         mutex_exit(&ptgt->tgt_mutex);
13768                                         mutex_exit(&pptr->port_mutex);
13769                                 }
13770                         } else {
13771                                 fcp_print_error(icmd->ipkt_fpkt);
13772                         }
13773 
13774                         (void) fcp_call_finish_init(pptr, ptgt,
13775                             icmd->ipkt_link_cnt, icmd->ipkt_change_cnt,
13776                             icmd->ipkt_cause);
13777                         fcp_icmd_free(pptr, icmd);
13778                         mutex_enter(&pptr->port_mutex);
13779                 }
13780 
13781                 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG;
13782                 mutex_exit(&pptr->port_mutex);
13783                 mutex_enter(&fcp_global_mutex);
13784 
13785         end_of_watchdog:
13786                 /*
13787                  * Bail out early before getting into trouble
13788                  */
13789                 if (save_port != fcp_port_head) {
13790                         break;
13791                 }
13792         }
13793 
13794         if (fcp_watchdog_init > 0) {
13795                 /* reschedule timeout to go again */
13796                 fcp_watchdog_id =
13797                     timeout(fcp_watch, NULL, fcp_watchdog_tick);
13798         }
13799         mutex_exit(&fcp_global_mutex);
13800 }
13801 
13802 
13803 static void
13804 fcp_check_reset_delay(struct fcp_port *pptr)
13805 {
13806         uint32_t                tgt_cnt;
13807         int                     level;
13808         struct fcp_tgt  *ptgt;
13809         struct fcp_lun  *plun;
13810         struct fcp_reset_elem *cur = NULL;
13811         struct fcp_reset_elem *next = NULL;
13812         struct fcp_reset_elem *prev = NULL;
13813 
13814         ASSERT(mutex_owned(&pptr->port_mutex));
13815 
13816         next = pptr->port_reset_list;
13817         while ((cur = next) != NULL) {
13818                 next = cur->next;
13819 
13820                 if (cur->timeout < fcp_watchdog_time) {
13821                         prev = cur;
13822                         continue;
13823                 }
13824 
13825                 ptgt = cur->tgt;
13826                 plun = cur->lun;
13827                 tgt_cnt = cur->tgt_cnt;
13828 
13829                 if (ptgt) {
13830                         level = RESET_TARGET;
13831                 } else {
13832                         ASSERT(plun != NULL);
13833                         level = RESET_LUN;
13834                         ptgt = plun->lun_tgt;
13835                 }
13836                 if (prev) {
13837                         prev->next = next;
13838                 } else {
13839                         /*
13840                          * Because we drop port mutex while doing aborts for
13841                          * packets, we can't rely on reset_list pointing to
13842                          * our head
13843                          */
13844                         if (cur == pptr->port_reset_list) {
13845                                 pptr->port_reset_list = next;
13846                         } else {
13847                                 struct fcp_reset_elem *which;
13848 
13849                                 which = pptr->port_reset_list;
13850                                 while (which && which->next != cur) {
13851                                         which = which->next;
13852                                 }
13853                                 ASSERT(which != NULL);
13854 
13855                                 which->next = next;
13856                                 prev = which;
13857                         }
13858                 }
13859 
13860                 kmem_free(cur, sizeof (*cur));
13861 
13862                 if (tgt_cnt == ptgt->tgt_change_cnt) {
13863                         mutex_enter(&ptgt->tgt_mutex);
13864                         if (level == RESET_TARGET) {
13865                                 fcp_update_tgt_state(ptgt,
13866                                     FCP_RESET, FCP_LUN_BUSY);
13867                         } else {
13868                                 fcp_update_lun_state(plun,
13869                                     FCP_RESET, FCP_LUN_BUSY);
13870                         }
13871                         mutex_exit(&ptgt->tgt_mutex);
13872 
13873                         mutex_exit(&pptr->port_mutex);
13874                         fcp_abort_all(pptr, ptgt, plun, tgt_cnt);
13875                         mutex_enter(&pptr->port_mutex);
13876                 }
13877         }
13878 }
13879 
13880 
13881 static void
13882 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt,
13883     struct fcp_lun *rlun, int tgt_cnt)
13884 {
13885         int                     rval;
13886         struct fcp_lun  *tlun, *nlun;
13887         struct fcp_pkt  *pcmd = NULL, *ncmd = NULL,
13888             *cmd = NULL, *head = NULL,
13889             *tail = NULL;
13890 
13891         mutex_enter(&pptr->port_pkt_mutex);
13892         for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) {
13893                 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address);
13894                 struct fcp_tgt *ptgt = plun->lun_tgt;
13895 
13896                 ncmd = cmd->cmd_next;
13897 
13898                 if (ptgt != ttgt && plun != rlun) {
13899                         pcmd = cmd;
13900                         continue;
13901                 }
13902 
13903                 if (pcmd != NULL) {
13904                         ASSERT(pptr->port_pkt_head != cmd);
13905                         pcmd->cmd_next = ncmd;
13906                 } else {
13907                         ASSERT(cmd == pptr->port_pkt_head);
13908                         pptr->port_pkt_head = ncmd;
13909                 }
13910                 if (pptr->port_pkt_tail == cmd) {
13911                         ASSERT(cmd->cmd_next == NULL);
13912                         pptr->port_pkt_tail = pcmd;
13913                         if (pcmd != NULL) {
13914                                 pcmd->cmd_next = NULL;
13915                         }
13916                 }
13917 
13918                 if (head == NULL) {
13919                         head = tail = cmd;
13920                 } else {
13921                         ASSERT(tail != NULL);
13922                         tail->cmd_next = cmd;
13923                         tail = cmd;
13924                 }
13925                 cmd->cmd_next = NULL;
13926         }
13927         mutex_exit(&pptr->port_pkt_mutex);
13928 
13929         for (cmd = head; cmd != NULL; cmd = ncmd) {
13930                 struct scsi_pkt *pkt = cmd->cmd_pkt;
13931 
13932                 ncmd = cmd->cmd_next;
13933                 ASSERT(pkt != NULL);
13934 
13935                 mutex_enter(&pptr->port_mutex);
13936                 if (ttgt->tgt_change_cnt == tgt_cnt) {
13937                         mutex_exit(&pptr->port_mutex);
13938                         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
13939                         pkt->pkt_reason = CMD_RESET;
13940                         pkt->pkt_statistics |= STAT_DEV_RESET;
13941                         cmd->cmd_state = FCP_PKT_IDLE;
13942                         fcp_post_callback(cmd);
13943                 } else {
13944                         mutex_exit(&pptr->port_mutex);
13945                 }
13946         }
13947 
13948         /*
13949          * If the FCA will return all the commands in its queue then our
13950          * work is easy, just return.
13951          */
13952 
13953         if (pptr->port_reset_action == FC_RESET_RETURN_ALL) {
13954                 return;
13955         }
13956 
13957         /*
13958          * For RESET_LUN get hold of target pointer
13959          */
13960         if (ttgt == NULL) {
13961                 ASSERT(rlun != NULL);
13962 
13963                 ttgt = rlun->lun_tgt;
13964 
13965                 ASSERT(ttgt != NULL);
13966         }
13967 
13968         /*
13969          * There are some severe race conditions here.
13970          * While we are trying to abort the pkt, it might be completing
13971          * so mark it aborted and if the abort does not succeed then
13972          * handle it in the watch thread.
13973          */
13974         mutex_enter(&ttgt->tgt_mutex);
13975         nlun = ttgt->tgt_lun;
13976         mutex_exit(&ttgt->tgt_mutex);
13977         while ((tlun = nlun) != NULL) {
13978                 int restart = 0;
13979                 if (rlun && rlun != tlun) {
13980                         mutex_enter(&ttgt->tgt_mutex);
13981                         nlun = tlun->lun_next;
13982                         mutex_exit(&ttgt->tgt_mutex);
13983                         continue;
13984                 }
13985                 mutex_enter(&tlun->lun_mutex);
13986                 cmd = tlun->lun_pkt_head;
13987                 while (cmd != NULL) {
13988                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
13989                                 struct scsi_pkt *pkt;
13990 
13991                                 restart = 1;
13992                                 cmd->cmd_state = FCP_PKT_ABORTING;
13993                                 mutex_exit(&tlun->lun_mutex);
13994                                 rval = fc_ulp_abort(pptr->port_fp_handle,
13995                                     cmd->cmd_fp_pkt, KM_SLEEP);
13996                                 if (rval == FC_SUCCESS) {
13997                                         pkt = cmd->cmd_pkt;
13998                                         pkt->pkt_reason = CMD_RESET;
13999                                         pkt->pkt_statistics |= STAT_DEV_RESET;
14000                                         cmd->cmd_state = FCP_PKT_IDLE;
14001                                         fcp_post_callback(cmd);
14002                                 } else {
14003                                         caddr_t msg;
14004 
14005                                         (void) fc_ulp_error(rval, &msg);
14006 
14007                                         /*
14008                                          * This part is tricky. The abort
14009                                          * failed and now the command could
14010                                          * be completing.  The cmd_state ==
14011                                          * FCP_PKT_ABORTING should save
14012                                          * us in fcp_cmd_callback. If we
14013                                          * are already aborting ignore the
14014                                          * command in fcp_cmd_callback.
14015                                          * Here we leave this packet for 20
14016                                          * sec to be aborted in the
14017                                          * fcp_watch thread.
14018                                          */
14019                                         fcp_log(CE_WARN, pptr->port_dip,
14020                                             "!Abort failed after reset %s",
14021                                             msg);
14022 
14023                                         cmd->cmd_timeout =
14024                                             fcp_watchdog_time +
14025                                             cmd->cmd_pkt->pkt_time +
14026                                             FCP_FAILED_DELAY;
14027 
14028                                         cmd->cmd_fp_pkt->pkt_timeout =
14029                                             FCP_INVALID_TIMEOUT;
14030                                         /*
14031                                          * This is a hack, cmd is put in the
14032                                          * overflow queue so that it can be
14033                                          * timed out finally
14034                                          */
14035                                         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14036 
14037                                         mutex_enter(&pptr->port_pkt_mutex);
14038                                         if (pptr->port_pkt_head) {
14039                                                 ASSERT(pptr->port_pkt_tail
14040                                                     != NULL);
14041                                                 pptr->port_pkt_tail->cmd_next
14042                                                     = cmd;
14043                                                 pptr->port_pkt_tail = cmd;
14044                                         } else {
14045                                                 ASSERT(pptr->port_pkt_tail
14046                                                     == NULL);
14047                                                 pptr->port_pkt_head =
14048                                                     pptr->port_pkt_tail
14049                                                     = cmd;
14050                                         }
14051                                         cmd->cmd_next = NULL;
14052                                         mutex_exit(&pptr->port_pkt_mutex);
14053                                 }
14054                                 mutex_enter(&tlun->lun_mutex);
14055                                 cmd = tlun->lun_pkt_head;
14056                         } else {
14057                                 cmd = cmd->cmd_forw;
14058                         }
14059                 }
14060                 mutex_exit(&tlun->lun_mutex);
14061 
14062                 mutex_enter(&ttgt->tgt_mutex);
14063                 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next);
14064                 mutex_exit(&ttgt->tgt_mutex);
14065 
14066                 mutex_enter(&pptr->port_mutex);
14067                 if (tgt_cnt != ttgt->tgt_change_cnt) {
14068                         mutex_exit(&pptr->port_mutex);
14069                         return;
14070                 } else {
14071                         mutex_exit(&pptr->port_mutex);
14072                 }
14073         }
14074 }
14075 
14076 
14077 /*
14078  * unlink the soft state, returning the soft state found (if any)
14079  *
14080  * acquires and releases the global mutex
14081  */
14082 struct fcp_port *
14083 fcp_soft_state_unlink(struct fcp_port *pptr)
14084 {
14085         struct fcp_port *hptr;          /* ptr index */
14086         struct fcp_port *tptr;          /* prev hptr */
14087 
14088         mutex_enter(&fcp_global_mutex);
14089         for (hptr = fcp_port_head, tptr = NULL;
14090             hptr != NULL;
14091             tptr = hptr, hptr = hptr->port_next) {
14092                 if (hptr == pptr) {
14093                         /* we found a match -- remove this item */
14094                         if (tptr == NULL) {
14095                                 /* we're at the head of the list */
14096                                 fcp_port_head = hptr->port_next;
14097                         } else {
14098                                 tptr->port_next = hptr->port_next;
14099                         }
14100                         break;                  /* success */
14101                 }
14102         }
14103         if (fcp_port_head == NULL) {
14104                 fcp_cleanup_blacklist(&fcp_lun_blacklist);
14105         }
14106         mutex_exit(&fcp_global_mutex);
14107         return (hptr);
14108 }
14109 
14110 
14111 /*
14112  * called by fcp_scsi_hba_tgt_init to find a LUN given a
14113  * WWN and a LUN number
14114  */
14115 /* ARGSUSED */
14116 static struct fcp_lun *
14117 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun)
14118 {
14119         int hash;
14120         struct fcp_tgt *ptgt;
14121         struct fcp_lun *plun;
14122 
14123         ASSERT(mutex_owned(&pptr->port_mutex));
14124 
14125         hash = FCP_HASH(wwn);
14126         for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL;
14127             ptgt = ptgt->tgt_next) {
14128                 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0],
14129                     sizeof (ptgt->tgt_port_wwn)) == 0) {
14130                         mutex_enter(&ptgt->tgt_mutex);
14131                         for (plun = ptgt->tgt_lun;
14132                             plun != NULL;
14133                             plun = plun->lun_next) {
14134                                 if (plun->lun_num == lun) {
14135                                         mutex_exit(&ptgt->tgt_mutex);
14136                                         return (plun);
14137                                 }
14138                         }
14139                         mutex_exit(&ptgt->tgt_mutex);
14140                         return (NULL);
14141                 }
14142         }
14143         return (NULL);
14144 }
14145 
14146 /*
14147  *     Function: fcp_prepare_pkt
14148  *
14149  *  Description: This function prepares the SCSI cmd pkt, passed by the caller,
14150  *               for fcp_start(). It binds the data or partially maps it.
14151  *               Builds the FCP header and starts the initialization of the
14152  *               Fibre Channel header.
14153  *
14154  *     Argument: *pptr          FCP port.
14155  *               *cmd           FCP packet.
14156  *               *plun          LUN the command will be sent to.
14157  *
14158  *      Context: User, Kernel and Interrupt context.
14159  */
14160 static void
14161 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd,
14162     struct fcp_lun *plun)
14163 {
14164         fc_packet_t             *fpkt = cmd->cmd_fp_pkt;
14165         struct fcp_tgt          *ptgt = plun->lun_tgt;
14166         struct fcp_cmd          *fcmd = &cmd->cmd_fcp_cmd;
14167 
14168         ASSERT(cmd->cmd_pkt->pkt_comp ||
14169             (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR));
14170 
14171         if (cmd->cmd_pkt->pkt_numcookies) {
14172                 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) {
14173                         fcmd->fcp_cntl.cntl_read_data = 1;
14174                         fcmd->fcp_cntl.cntl_write_data = 0;
14175                         fpkt->pkt_tran_type = FC_PKT_FCP_READ;
14176                 } else {
14177                         fcmd->fcp_cntl.cntl_read_data = 0;
14178                         fcmd->fcp_cntl.cntl_write_data = 1;
14179                         fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
14180                 }
14181 
14182                 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies;
14183 
14184                 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies;
14185                 ASSERT(fpkt->pkt_data_cookie_cnt <=
14186                     pptr->port_data_dma_attr.dma_attr_sgllen);
14187 
14188                 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len;
14189 
14190                 /* FCA needs pkt_datalen to be set */
14191                 fpkt->pkt_datalen = cmd->cmd_dmacount;
14192                 fcmd->fcp_data_len = cmd->cmd_dmacount;
14193         } else {
14194                 fcmd->fcp_cntl.cntl_read_data = 0;
14195                 fcmd->fcp_cntl.cntl_write_data = 0;
14196                 fpkt->pkt_tran_type = FC_PKT_EXCHANGE;
14197                 fpkt->pkt_datalen = 0;
14198                 fcmd->fcp_data_len = 0;
14199         }
14200 
14201         /* set up the Tagged Queuing type */
14202         if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) {
14203                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
14204         } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) {
14205                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
14206         } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) {
14207                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
14208         } else {
14209                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
14210         }
14211 
14212         fcmd->fcp_ent_addr = plun->lun_addr;
14213 
14214         if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) {
14215                 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd,
14216                     fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd));
14217         } else {
14218                 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL);
14219         }
14220 
14221         cmd->cmd_pkt->pkt_reason = CMD_CMPLT;
14222         cmd->cmd_pkt->pkt_state = 0;
14223         cmd->cmd_pkt->pkt_statistics = 0;
14224         cmd->cmd_pkt->pkt_resid = 0;
14225 
14226         cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle;
14227 
14228         if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) {
14229                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
14230                 fpkt->pkt_comp = NULL;
14231         } else {
14232                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
14233                 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
14234                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
14235                 }
14236                 fpkt->pkt_comp = fcp_cmd_callback;
14237         }
14238 
14239         mutex_enter(&pptr->port_mutex);
14240         if (pptr->port_state & FCP_STATE_SUSPENDED) {
14241                 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING;
14242         }
14243         mutex_exit(&pptr->port_mutex);
14244 
14245         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
14246         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
14247 
14248         /*
14249          * Save a few kernel cycles here
14250          */
14251 #ifndef __lock_lint
14252         fpkt->pkt_fca_device = ptgt->tgt_fca_dev;
14253 #endif /* __lock_lint */
14254 }
14255 
14256 static void
14257 fcp_post_callback(struct fcp_pkt *cmd)
14258 {
14259         scsi_hba_pkt_comp(cmd->cmd_pkt);
14260 }
14261 
14262 
14263 /*
14264  * called to do polled I/O by fcp_start()
14265  *
14266  * return a transport status value, i.e. TRAN_ACCECPT for success
14267  */
14268 static int
14269 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd)
14270 {
14271         int     rval;
14272 
14273 #ifdef  DEBUG
14274         mutex_enter(&pptr->port_pkt_mutex);
14275         pptr->port_npkts++;
14276         mutex_exit(&pptr->port_pkt_mutex);
14277 #endif /* DEBUG */
14278 
14279         if (cmd->cmd_fp_pkt->pkt_timeout) {
14280                 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time;
14281         } else {
14282                 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT;
14283         }
14284 
14285         ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL);
14286 
14287         cmd->cmd_state = FCP_PKT_ISSUED;
14288 
14289         rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt);
14290 
14291 #ifdef  DEBUG
14292         mutex_enter(&pptr->port_pkt_mutex);
14293         pptr->port_npkts--;
14294         mutex_exit(&pptr->port_pkt_mutex);
14295 #endif /* DEBUG */
14296 
14297         cmd->cmd_state = FCP_PKT_IDLE;
14298 
14299         switch (rval) {
14300         case FC_SUCCESS:
14301                 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) {
14302                         fcp_complete_pkt(cmd->cmd_fp_pkt);
14303                         rval = TRAN_ACCEPT;
14304                 } else {
14305                         rval = TRAN_FATAL_ERROR;
14306                 }
14307                 break;
14308 
14309         case FC_TRAN_BUSY:
14310                 rval = TRAN_BUSY;
14311                 cmd->cmd_pkt->pkt_resid = 0;
14312                 break;
14313 
14314         case FC_BADPACKET:
14315                 rval = TRAN_BADPKT;
14316                 break;
14317 
14318         default:
14319                 rval = TRAN_FATAL_ERROR;
14320                 break;
14321         }
14322 
14323         return (rval);
14324 }
14325 
14326 
14327 /*
14328  * called by some of the following transport-called routines to convert
14329  * a supplied dip ptr to a port struct ptr (i.e. to the soft state)
14330  */
14331 static struct fcp_port *
14332 fcp_dip2port(dev_info_t *dip)
14333 {
14334         int     instance;
14335 
14336         instance = ddi_get_instance(dip);
14337         return (ddi_get_soft_state(fcp_softstate, instance));
14338 }
14339 
14340 
14341 /*
14342  * called internally to return a LUN given a dip
14343  */
14344 struct fcp_lun *
14345 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip)
14346 {
14347         struct fcp_tgt *ptgt;
14348         struct fcp_lun *plun;
14349         int i;
14350 
14351 
14352         ASSERT(mutex_owned(&pptr->port_mutex));
14353 
14354         for (i = 0; i < FCP_NUM_HASH; i++) {
14355                 for (ptgt = pptr->port_tgt_hash_table[i];
14356                     ptgt != NULL;
14357                     ptgt = ptgt->tgt_next) {
14358                         mutex_enter(&ptgt->tgt_mutex);
14359                         for (plun = ptgt->tgt_lun; plun != NULL;
14360                             plun = plun->lun_next) {
14361                                 mutex_enter(&plun->lun_mutex);
14362                                 if (plun->lun_cip == cip) {
14363                                         mutex_exit(&plun->lun_mutex);
14364                                         mutex_exit(&ptgt->tgt_mutex);
14365                                         return (plun); /* match found */
14366                                 }
14367                                 mutex_exit(&plun->lun_mutex);
14368                         }
14369                         mutex_exit(&ptgt->tgt_mutex);
14370                 }
14371         }
14372         return (NULL);                          /* no LUN found */
14373 }
14374 
14375 /*
14376  * pass an element to the hotplug list, kick the hotplug thread
14377  * and wait for the element to get processed by the hotplug thread.
14378  * on return the element is freed.
14379  *
14380  * return zero success and non-zero on failure
14381  *
14382  * acquires/releases the target mutex
14383  *
14384  */
14385 static int
14386 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun,
14387     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags)
14388 {
14389         struct fcp_hp_elem      *elem;
14390         int                     rval;
14391 
14392         mutex_enter(&plun->lun_tgt->tgt_mutex);
14393         if ((elem = fcp_pass_to_hp(pptr, plun, cip,
14394             what, link_cnt, tgt_cnt, flags, 1)) == NULL) {
14395                 mutex_exit(&plun->lun_tgt->tgt_mutex);
14396                 fcp_log(CE_CONT, pptr->port_dip,
14397                     "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n",
14398                     what, plun->lun_tgt->tgt_d_id, plun->lun_num);
14399                 return (NDI_FAILURE);
14400         }
14401         mutex_exit(&plun->lun_tgt->tgt_mutex);
14402         mutex_enter(&elem->mutex);
14403         if (elem->wait) {
14404                 while (elem->wait) {
14405                         cv_wait(&elem->cv, &elem->mutex);
14406                 }
14407         }
14408         rval = (elem->result);
14409         mutex_exit(&elem->mutex);
14410         mutex_destroy(&elem->mutex);
14411         cv_destroy(&elem->cv);
14412         kmem_free(elem, sizeof (struct fcp_hp_elem));
14413         return (rval);
14414 }
14415 
14416 /*
14417  * pass an element to the hotplug list, and then
14418  * kick the hotplug thread
14419  *
14420  * return Boolean success, i.e. non-zero if all goes well, else zero on error
14421  *
14422  * acquires/releases the hotplug mutex
14423  *
14424  * called with the target mutex owned
14425  *
14426  * memory acquired in NOSLEEP mode
14427  * NOTE: if wait is set to 1 then the caller is responsible for waiting on
14428  *       for the hp daemon to process the request and is responsible for
14429  *       freeing the element
14430  */
14431 static struct fcp_hp_elem *
14432 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun,
14433     child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait)
14434 {
14435         struct fcp_hp_elem      *elem;
14436         dev_info_t *pdip;
14437 
14438         ASSERT(pptr != NULL);
14439         ASSERT(plun != NULL);
14440         ASSERT(plun->lun_tgt != NULL);
14441         ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex));
14442 
14443         /* create space for a hotplug element */
14444         if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP))
14445             == NULL) {
14446                 fcp_log(CE_WARN, NULL,
14447                     "!can't allocate memory for hotplug element");
14448                 return (NULL);
14449         }
14450 
14451         /* fill in hotplug element */
14452         elem->port = pptr;
14453         elem->lun = plun;
14454         elem->cip = cip;
14455         elem->old_lun_mpxio = plun->lun_mpxio;
14456         elem->what = what;
14457         elem->flags = flags;
14458         elem->link_cnt = link_cnt;
14459         elem->tgt_cnt = tgt_cnt;
14460         elem->wait = wait;
14461         mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL);
14462         cv_init(&elem->cv, NULL, CV_DRIVER, NULL);
14463 
14464         /* schedule the hotplug task */
14465         pdip = pptr->port_dip;
14466         mutex_enter(&plun->lun_mutex);
14467         if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14468                 plun->lun_event_count++;
14469                 elem->event_cnt = plun->lun_event_count;
14470         }
14471         mutex_exit(&plun->lun_mutex);
14472         if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task,
14473             (void *)elem, KM_NOSLEEP) == NULL) {
14474                 mutex_enter(&plun->lun_mutex);
14475                 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) {
14476                         plun->lun_event_count--;
14477                 }
14478                 mutex_exit(&plun->lun_mutex);
14479                 kmem_free(elem, sizeof (*elem));
14480                 return (0);
14481         }
14482 
14483         return (elem);
14484 }
14485 
14486 
14487 static void
14488 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd)
14489 {
14490         int                     rval;
14491         struct scsi_address     *ap;
14492         struct fcp_lun  *plun;
14493         struct fcp_tgt  *ptgt;
14494         fc_packet_t     *fpkt;
14495 
14496         ap = &cmd->cmd_pkt->pkt_address;
14497         plun = ADDR2LUN(ap);
14498         ptgt = plun->lun_tgt;
14499 
14500         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14501 
14502         cmd->cmd_state = FCP_PKT_IDLE;
14503 
14504         mutex_enter(&pptr->port_mutex);
14505         mutex_enter(&ptgt->tgt_mutex);
14506         if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) &&
14507             (!(pptr->port_state & FCP_STATE_ONLINING))) {
14508                 fc_ulp_rscn_info_t *rscnp;
14509 
14510                 cmd->cmd_state = FCP_PKT_ISSUED;
14511 
14512                 /*
14513                  * It is possible for pkt_pd to be NULL if tgt_pd_handle was
14514                  * originally NULL, hence we try to set it to the pd pointed
14515                  * to by the SCSI device we're trying to get to.
14516                  */
14517 
14518                 fpkt = cmd->cmd_fp_pkt;
14519                 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) {
14520                         fpkt->pkt_pd = ptgt->tgt_pd_handle;
14521                         /*
14522                          * We need to notify the transport that we now have a
14523                          * reference to the remote port handle.
14524                          */
14525                         fc_ulp_hold_remote_port(ptgt->tgt_pd_handle);
14526                 }
14527 
14528                 mutex_exit(&ptgt->tgt_mutex);
14529                 mutex_exit(&pptr->port_mutex);
14530 
14531                 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0);
14532 
14533                 /* prepare the packet */
14534 
14535                 fcp_prepare_pkt(pptr, cmd, plun);
14536 
14537                 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt->
14538                     pkt_ulp_rscn_infop;
14539 
14540                 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ?
14541                     fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0;
14542 
14543                 if (rscnp != NULL) {
14544                         rscnp->ulp_rscn_count =
14545                             fc_ulp_get_rscn_count(pptr->
14546                             port_fp_handle);
14547                 }
14548 
14549                 rval = fcp_transport(pptr->port_fp_handle,
14550                     cmd->cmd_fp_pkt, 0);
14551 
14552                 if (rval == FC_SUCCESS) {
14553                         return;
14554                 }
14555                 cmd->cmd_state &= ~FCP_PKT_ISSUED;
14556         } else {
14557                 mutex_exit(&ptgt->tgt_mutex);
14558                 mutex_exit(&pptr->port_mutex);
14559         }
14560 
14561         fcp_queue_pkt(pptr, cmd);
14562 }
14563 
14564 
14565 static void
14566 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics)
14567 {
14568         ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE);
14569 
14570         cmd->cmd_flags &= ~CFLAG_IN_QUEUE;
14571         cmd->cmd_state = FCP_PKT_IDLE;
14572 
14573         cmd->cmd_pkt->pkt_reason = reason;
14574         cmd->cmd_pkt->pkt_state = 0;
14575         cmd->cmd_pkt->pkt_statistics = statistics;
14576 
14577         fcp_post_callback(cmd);
14578 }
14579 
14580 /*
14581  *     Function: fcp_queue_pkt
14582  *
14583  *  Description: This function queues the packet passed by the caller into
14584  *               the list of packets of the FCP port.
14585  *
14586  *     Argument: *pptr          FCP port.
14587  *               *cmd           FCP packet to queue.
14588  *
14589  * Return Value: None
14590  *
14591  *      Context: User, Kernel and Interrupt context.
14592  */
14593 static void
14594 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd)
14595 {
14596         ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL);
14597 
14598         mutex_enter(&pptr->port_pkt_mutex);
14599         cmd->cmd_flags |= CFLAG_IN_QUEUE;
14600         ASSERT(cmd->cmd_state != FCP_PKT_ISSUED);
14601         cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY;
14602 
14603         /*
14604          * zero pkt_time means hang around for ever
14605          */
14606         if (cmd->cmd_pkt->pkt_time) {
14607                 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) {
14608                         cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY;
14609                 } else {
14610                         /*
14611                          * Indicate the watch thread to fail the
14612                          * command by setting it to highest value
14613                          */
14614                         cmd->cmd_timeout = fcp_watchdog_time;
14615                         cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT;
14616                 }
14617         }
14618 
14619         if (pptr->port_pkt_head) {
14620                 ASSERT(pptr->port_pkt_tail != NULL);
14621 
14622                 pptr->port_pkt_tail->cmd_next = cmd;
14623                 pptr->port_pkt_tail = cmd;
14624         } else {
14625                 ASSERT(pptr->port_pkt_tail == NULL);
14626 
14627                 pptr->port_pkt_head = pptr->port_pkt_tail = cmd;
14628         }
14629         cmd->cmd_next = NULL;
14630         mutex_exit(&pptr->port_pkt_mutex);
14631 }
14632 
14633 /*
14634  *     Function: fcp_update_targets
14635  *
14636  *  Description: This function applies the specified change of state to all
14637  *               the targets listed.  The operation applied is 'set'.
14638  *
14639  *     Argument: *pptr          FCP port.
14640  *               *dev_list      Array of fc_portmap_t structures.
14641  *               count          Length of dev_list.
14642  *               state          State bits to update.
14643  *               cause          Reason for the update.
14644  *
14645  * Return Value: None
14646  *
14647  *      Context: User, Kernel and Interrupt context.
14648  *               The mutex pptr->port_mutex must be held.
14649  */
14650 static void
14651 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list,
14652     uint32_t count, uint32_t state, int cause)
14653 {
14654         fc_portmap_t            *map_entry;
14655         struct fcp_tgt  *ptgt;
14656 
14657         ASSERT(MUTEX_HELD(&pptr->port_mutex));
14658 
14659         while (count--) {
14660                 map_entry = &(dev_list[count]);
14661                 ptgt = fcp_lookup_target(pptr,
14662                     (uchar_t *)&(map_entry->map_pwwn));
14663                 if (ptgt == NULL) {
14664                         continue;
14665                 }
14666 
14667                 mutex_enter(&ptgt->tgt_mutex);
14668                 ptgt->tgt_trace = 0;
14669                 ptgt->tgt_change_cnt++;
14670                 ptgt->tgt_statec_cause = cause;
14671                 ptgt->tgt_tmp_cnt = 1;
14672                 fcp_update_tgt_state(ptgt, FCP_SET, state);
14673                 mutex_exit(&ptgt->tgt_mutex);
14674         }
14675 }
14676 
14677 static int
14678 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14679     int lcount, int tcount, int cause)
14680 {
14681         int rval;
14682 
14683         mutex_enter(&pptr->port_mutex);
14684         rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause);
14685         mutex_exit(&pptr->port_mutex);
14686 
14687         return (rval);
14688 }
14689 
14690 
14691 static int
14692 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt,
14693     int lcount, int tcount, int cause)
14694 {
14695         int     finish_init = 0;
14696         int     finish_tgt = 0;
14697         int     do_finish_init = 0;
14698         int     rval = FCP_NO_CHANGE;
14699 
14700         if (cause == FCP_CAUSE_LINK_CHANGE ||
14701             cause == FCP_CAUSE_LINK_DOWN) {
14702                 do_finish_init = 1;
14703         }
14704 
14705         if (ptgt != NULL) {
14706                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14707                     FCP_BUF_LEVEL_2, 0,
14708                     "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;"
14709                     " cause = %d, d_id = 0x%x, tgt_done = %d",
14710                     pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount,
14711                     pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause,
14712                     ptgt->tgt_d_id, ptgt->tgt_done);
14713 
14714                 mutex_enter(&ptgt->tgt_mutex);
14715 
14716                 if (tcount && (ptgt->tgt_change_cnt != tcount)) {
14717                         rval = FCP_DEV_CHANGE;
14718                         if (do_finish_init && ptgt->tgt_done == 0) {
14719                                 ptgt->tgt_done++;
14720                                 finish_init = 1;
14721                         }
14722                 } else {
14723                         if (--ptgt->tgt_tmp_cnt <= 0) {
14724                                 ptgt->tgt_tmp_cnt = 0;
14725                                 finish_tgt = 1;
14726 
14727                                 if (do_finish_init) {
14728                                         finish_init = 1;
14729                                 }
14730                         }
14731                 }
14732                 mutex_exit(&ptgt->tgt_mutex);
14733         } else {
14734                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
14735                     FCP_BUF_LEVEL_2, 0,
14736                     "Call Finish Init for NO target");
14737 
14738                 if (do_finish_init) {
14739                         finish_init = 1;
14740                 }
14741         }
14742 
14743         if (finish_tgt) {
14744                 ASSERT(ptgt != NULL);
14745 
14746                 mutex_enter(&ptgt->tgt_mutex);
14747 #ifdef  DEBUG
14748                 bzero(ptgt->tgt_tmp_cnt_stack,
14749                     sizeof (ptgt->tgt_tmp_cnt_stack));
14750 
14751                 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack,
14752                     FCP_STACK_DEPTH);
14753 #endif /* DEBUG */
14754                 mutex_exit(&ptgt->tgt_mutex);
14755 
14756                 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause);
14757         }
14758 
14759         if (finish_init && lcount == pptr->port_link_cnt) {
14760                 ASSERT(pptr->port_tmp_cnt > 0);
14761                 if (--pptr->port_tmp_cnt == 0) {
14762                         fcp_finish_init(pptr);
14763                 }
14764         } else if (lcount != pptr->port_link_cnt) {
14765                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
14766                     fcp_trace, FCP_BUF_LEVEL_2, 0,
14767                     "fcp_call_finish_init_held,1: state change occured"
14768                     " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0);
14769         }
14770 
14771         return (rval);
14772 }
14773 
14774 static void
14775 fcp_reconfigure_luns(void * tgt_handle)
14776 {
14777         uint32_t                dev_cnt;
14778         fc_portmap_t            *devlist;
14779         struct fcp_tgt  *ptgt = (struct fcp_tgt *)tgt_handle;
14780         struct fcp_port         *pptr = ptgt->tgt_port;
14781 
14782         /*
14783          * If the timer that fires this off got canceled too late, the
14784          * target could have been destroyed.
14785          */
14786 
14787         if (ptgt->tgt_tid == NULL) {
14788                 return;
14789         }
14790 
14791         devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP);
14792         if (devlist == NULL) {
14793                 fcp_log(CE_WARN, pptr->port_dip,
14794                     "!fcp%d: failed to allocate for portmap",
14795                     pptr->port_instance);
14796                 return;
14797         }
14798 
14799         dev_cnt = 1;
14800         devlist->map_pd = ptgt->tgt_pd_handle;
14801         devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr;
14802         devlist->map_did.port_id = ptgt->tgt_d_id;
14803 
14804         bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE);
14805         bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE);
14806 
14807         devlist->map_state = PORT_DEVICE_LOGGED_IN;
14808         devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED;
14809         devlist->map_flags = 0;
14810 
14811         fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE,
14812             pptr->port_topology, devlist, dev_cnt, pptr->port_id);
14813 
14814         /*
14815          * Clear the tgt_tid after no more references to
14816          * the fcp_tgt
14817          */
14818         mutex_enter(&ptgt->tgt_mutex);
14819         ptgt->tgt_tid = NULL;
14820         mutex_exit(&ptgt->tgt_mutex);
14821 
14822         kmem_free(devlist, sizeof (*devlist));
14823 }
14824 
14825 
14826 static void
14827 fcp_free_targets(struct fcp_port *pptr)
14828 {
14829         int                     i;
14830         struct fcp_tgt  *ptgt;
14831 
14832         mutex_enter(&pptr->port_mutex);
14833         for (i = 0; i < FCP_NUM_HASH; i++) {
14834                 ptgt = pptr->port_tgt_hash_table[i];
14835                 while (ptgt != NULL) {
14836                         struct fcp_tgt *next_tgt = ptgt->tgt_next;
14837 
14838                         fcp_free_target(ptgt);
14839                         ptgt = next_tgt;
14840                 }
14841         }
14842         mutex_exit(&pptr->port_mutex);
14843 }
14844 
14845 
14846 static void
14847 fcp_free_target(struct fcp_tgt *ptgt)
14848 {
14849         struct fcp_lun  *plun;
14850         timeout_id_t            tid;
14851 
14852         mutex_enter(&ptgt->tgt_mutex);
14853         tid = ptgt->tgt_tid;
14854 
14855         /*
14856          * Cancel any pending timeouts for this target.
14857          */
14858 
14859         if (tid != NULL) {
14860                 /*
14861                  * Set tgt_tid to NULL first to avoid a race in the callback.
14862                  * If tgt_tid is NULL, the callback will simply return.
14863                  */
14864                 ptgt->tgt_tid = NULL;
14865                 mutex_exit(&ptgt->tgt_mutex);
14866                 (void) untimeout(tid);
14867                 mutex_enter(&ptgt->tgt_mutex);
14868         }
14869 
14870         plun = ptgt->tgt_lun;
14871         while (plun != NULL) {
14872                 struct fcp_lun *next_lun = plun->lun_next;
14873 
14874                 fcp_dealloc_lun(plun);
14875                 plun = next_lun;
14876         }
14877 
14878         mutex_exit(&ptgt->tgt_mutex);
14879         fcp_dealloc_tgt(ptgt);
14880 }
14881 
14882 /*
14883  *     Function: fcp_is_retryable
14884  *
14885  *  Description: Indicates if the internal packet is retryable.
14886  *
14887  *     Argument: *icmd          FCP internal packet.
14888  *
14889  * Return Value: 0      Not retryable
14890  *               1      Retryable
14891  *
14892  *      Context: User, Kernel and Interrupt context
14893  */
14894 static int
14895 fcp_is_retryable(struct fcp_ipkt *icmd)
14896 {
14897         if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED |
14898             FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) {
14899                 return (0);
14900         }
14901 
14902         return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) <
14903             icmd->ipkt_port->port_deadline) ? 1 : 0);
14904 }
14905 
14906 /*
14907  *     Function: fcp_create_on_demand
14908  *
14909  *     Argument: *pptr          FCP port.
14910  *               *pwwn          Port WWN.
14911  *
14912  * Return Value: 0      Success
14913  *               EIO
14914  *               ENOMEM
14915  *               EBUSY
14916  *               EINVAL
14917  *
14918  *      Context: User and Kernel context
14919  */
14920 static int
14921 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn)
14922 {
14923         int                     wait_ms;
14924         int                     tcount;
14925         int                     lcount;
14926         int                     ret;
14927         int                     error;
14928         int                     rval = EIO;
14929         int                     ntries;
14930         fc_portmap_t            *devlist;
14931         opaque_t                pd;
14932         struct fcp_lun          *plun;
14933         struct fcp_tgt          *ptgt;
14934         int                     old_manual = 0;
14935 
14936         /* Allocates the fc_portmap_t structure. */
14937         devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP);
14938 
14939         /*
14940          * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown
14941          * in the commented statement below:
14942          *
14943          * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT;
14944          *
14945          * Below, the deadline for the discovery process is set.
14946          */
14947         mutex_enter(&pptr->port_mutex);
14948         pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE;
14949         mutex_exit(&pptr->port_mutex);
14950 
14951         /*
14952          * We try to find the remote port based on the WWN provided by the
14953          * caller.  We actually ask fp/fctl if it has it.
14954          */
14955         pd = fc_ulp_get_remote_port(pptr->port_fp_handle,
14956             (la_wwn_t *)pwwn, &error, 1);
14957 
14958         if (pd == NULL) {
14959                 kmem_free(devlist, sizeof (*devlist));
14960                 return (rval);
14961         }
14962 
14963         /*
14964          * The remote port was found.  We ask fp/fctl to update our
14965          * fc_portmap_t structure.
14966          */
14967         ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle,
14968             (la_wwn_t *)pwwn, devlist);
14969         if (ret != FC_SUCCESS) {
14970                 kmem_free(devlist, sizeof (*devlist));
14971                 return (rval);
14972         }
14973 
14974         /*
14975          * The map flag field is set to indicates that the creation is being
14976          * done at the user request (Ioclt probably luxadm or cfgadm).
14977          */
14978         devlist->map_type = PORT_DEVICE_USER_CREATE;
14979 
14980         mutex_enter(&pptr->port_mutex);
14981 
14982         /*
14983          * We check to see if fcp already has a target that describes the
14984          * device being created.  If not it is created.
14985          */
14986         ptgt = fcp_lookup_target(pptr, pwwn);
14987         if (ptgt == NULL) {
14988                 lcount = pptr->port_link_cnt;
14989                 mutex_exit(&pptr->port_mutex);
14990 
14991                 ptgt = fcp_alloc_tgt(pptr, devlist, lcount);
14992                 if (ptgt == NULL) {
14993                         fcp_log(CE_WARN, pptr->port_dip,
14994                             "!FC target allocation failed");
14995                         return (ENOMEM);
14996                 }
14997 
14998                 mutex_enter(&pptr->port_mutex);
14999         }
15000 
15001         mutex_enter(&ptgt->tgt_mutex);
15002         ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE;
15003         ptgt->tgt_tmp_cnt = 1;
15004         ptgt->tgt_device_created = 0;
15005         /*
15006          * If fabric and auto config is set but the target was
15007          * manually unconfigured then reset to the manual_config_only to
15008          * 0 so the device will get configured.
15009          */
15010         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15011             fcp_enable_auto_configuration &&
15012             ptgt->tgt_manual_config_only == 1) {
15013                 old_manual = 1;
15014                 ptgt->tgt_manual_config_only = 0;
15015         }
15016         mutex_exit(&ptgt->tgt_mutex);
15017 
15018         fcp_update_targets(pptr, devlist, 1,
15019             FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE);
15020 
15021         lcount = pptr->port_link_cnt;
15022         tcount = ptgt->tgt_change_cnt;
15023 
15024         if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount,
15025             tcount, FCP_CAUSE_USER_CREATE) == TRUE) {
15026                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15027                     fcp_enable_auto_configuration && old_manual) {
15028                         mutex_enter(&ptgt->tgt_mutex);
15029                         ptgt->tgt_manual_config_only = 1;
15030                         mutex_exit(&ptgt->tgt_mutex);
15031                 }
15032 
15033                 if (pptr->port_link_cnt != lcount ||
15034                     ptgt->tgt_change_cnt != tcount) {
15035                         rval = EBUSY;
15036                 }
15037                 mutex_exit(&pptr->port_mutex);
15038 
15039                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15040                     FCP_BUF_LEVEL_3, 0,
15041                     "fcp_create_on_demand: mapflags ptgt=%x, "
15042                     "lcount=%x::port_link_cnt=%x, "
15043                     "tcount=%x: tgt_change_cnt=%x, rval=%x",
15044                     ptgt, lcount, pptr->port_link_cnt,
15045                     tcount, ptgt->tgt_change_cnt, rval);
15046                 return (rval);
15047         }
15048 
15049         /*
15050          * Due to lack of synchronization mechanisms, we perform
15051          * periodic monitoring of our request; Because requests
15052          * get dropped when another one supercedes (either because
15053          * of a link change or a target change), it is difficult to
15054          * provide a clean synchronization mechanism (such as a
15055          * semaphore or a conditional variable) without exhaustively
15056          * rewriting the mainline discovery code of this driver.
15057          */
15058         wait_ms = 500;
15059 
15060         ntries = fcp_max_target_retries;
15061 
15062         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15063             FCP_BUF_LEVEL_3, 0,
15064             "fcp_create_on_demand(1): ntries=%x, ptgt=%x, "
15065             "lcount=%x::port_link_cnt=%x, "
15066             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15067             "tgt_tmp_cnt =%x",
15068             ntries, ptgt, lcount, pptr->port_link_cnt,
15069             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15070             ptgt->tgt_tmp_cnt);
15071 
15072         mutex_enter(&ptgt->tgt_mutex);
15073         while (ntries-- != 0 && pptr->port_link_cnt == lcount &&
15074             ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) {
15075                 mutex_exit(&ptgt->tgt_mutex);
15076                 mutex_exit(&pptr->port_mutex);
15077 
15078                 delay(drv_usectohz(wait_ms * 1000));
15079 
15080                 mutex_enter(&pptr->port_mutex);
15081                 mutex_enter(&ptgt->tgt_mutex);
15082         }
15083 
15084 
15085         if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) {
15086                 rval = EBUSY;
15087         } else {
15088                 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state ==
15089                     FCP_TGT_NODE_PRESENT) {
15090                         rval = 0;
15091                 }
15092         }
15093 
15094         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15095             FCP_BUF_LEVEL_3, 0,
15096             "fcp_create_on_demand(2): ntries=%x, ptgt=%x, "
15097             "lcount=%x::port_link_cnt=%x, "
15098             "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x "
15099             "tgt_tmp_cnt =%x",
15100             ntries, ptgt, lcount, pptr->port_link_cnt,
15101             tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created,
15102             ptgt->tgt_tmp_cnt);
15103 
15104         if (rval) {
15105                 if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15106                     fcp_enable_auto_configuration && old_manual) {
15107                         ptgt->tgt_manual_config_only = 1;
15108                 }
15109                 mutex_exit(&ptgt->tgt_mutex);
15110                 mutex_exit(&pptr->port_mutex);
15111                 kmem_free(devlist, sizeof (*devlist));
15112 
15113                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15114                     FCP_BUF_LEVEL_3, 0,
15115                     "fcp_create_on_demand(3): ntries=%x, ptgt=%x, "
15116                     "lcount=%x::port_link_cnt=%x, "
15117                     "tcount=%x::tgt_change_cnt=%x, rval=%x, "
15118                     "tgt_device_created=%x, tgt D_ID=%x",
15119                     ntries, ptgt, lcount, pptr->port_link_cnt,
15120                     tcount, ptgt->tgt_change_cnt, rval,
15121                     ptgt->tgt_device_created, ptgt->tgt_d_id);
15122                 return (rval);
15123         }
15124 
15125         if ((plun = ptgt->tgt_lun) != NULL) {
15126                 tcount = plun->lun_tgt->tgt_change_cnt;
15127         } else {
15128                 rval = EINVAL;
15129         }
15130         lcount = pptr->port_link_cnt;
15131 
15132         /*
15133          * Configuring the target with no LUNs will fail. We
15134          * should reset the node state so that it is not
15135          * automatically configured when the LUNs are added
15136          * to this target.
15137          */
15138         if (ptgt->tgt_lun_cnt == 0) {
15139                 ptgt->tgt_node_state = FCP_TGT_NODE_NONE;
15140         }
15141         mutex_exit(&ptgt->tgt_mutex);
15142         mutex_exit(&pptr->port_mutex);
15143 
15144         while (plun) {
15145                 child_info_t    *cip;
15146 
15147                 mutex_enter(&plun->lun_mutex);
15148                 cip = plun->lun_cip;
15149                 mutex_exit(&plun->lun_mutex);
15150 
15151                 mutex_enter(&ptgt->tgt_mutex);
15152                 if (!(plun->lun_state & FCP_LUN_OFFLINE)) {
15153                         mutex_exit(&ptgt->tgt_mutex);
15154 
15155                         rval = fcp_pass_to_hp_and_wait(pptr, plun, cip,
15156                             FCP_ONLINE, lcount, tcount,
15157                             NDI_ONLINE_ATTACH);
15158                         if (rval != NDI_SUCCESS) {
15159                                 FCP_TRACE(fcp_logq,
15160                                     pptr->port_instbuf, fcp_trace,
15161                                     FCP_BUF_LEVEL_3, 0,
15162                                     "fcp_create_on_demand: "
15163                                     "pass_to_hp_and_wait failed "
15164                                     "rval=%x", rval);
15165                                 rval = EIO;
15166                         } else {
15167                                 mutex_enter(&LUN_TGT->tgt_mutex);
15168                                 plun->lun_state &= ~(FCP_LUN_OFFLINE |
15169                                     FCP_LUN_BUSY);
15170                                 mutex_exit(&LUN_TGT->tgt_mutex);
15171                         }
15172                         mutex_enter(&ptgt->tgt_mutex);
15173                 }
15174 
15175                 plun = plun->lun_next;
15176                 mutex_exit(&ptgt->tgt_mutex);
15177         }
15178 
15179         kmem_free(devlist, sizeof (*devlist));
15180 
15181         if (FC_TOP_EXTERNAL(pptr->port_topology) &&
15182             fcp_enable_auto_configuration && old_manual) {
15183                 mutex_enter(&ptgt->tgt_mutex);
15184                 /* if successful then set manual to 0 */
15185                 if (rval == 0) {
15186                         ptgt->tgt_manual_config_only = 0;
15187                 } else {
15188                         /* reset to 1 so the user has to do the config */
15189                         ptgt->tgt_manual_config_only = 1;
15190                 }
15191                 mutex_exit(&ptgt->tgt_mutex);
15192         }
15193 
15194         return (rval);
15195 }
15196 
15197 
15198 static void
15199 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len)
15200 {
15201         int             count;
15202         uchar_t         byte;
15203 
15204         count = 0;
15205         while (*string) {
15206                 byte = FCP_ATOB(*string); string++;
15207                 byte = byte << 4 | FCP_ATOB(*string); string++;
15208                 bytes[count++] = byte;
15209 
15210                 if (count >= byte_len) {
15211                         break;
15212                 }
15213         }
15214 }
15215 
15216 static void
15217 fcp_wwn_to_ascii(uchar_t wwn[], char *string)
15218 {
15219         int             i;
15220 
15221         for (i = 0; i < FC_WWN_SIZE; i++) {
15222                 (void) sprintf(string + (i * 2),
15223                     "%02x", wwn[i]);
15224         }
15225 
15226 }
15227 
15228 static void
15229 fcp_print_error(fc_packet_t *fpkt)
15230 {
15231         struct fcp_ipkt *icmd = (struct fcp_ipkt *)
15232             fpkt->pkt_ulp_private;
15233         struct fcp_port *pptr;
15234         struct fcp_tgt  *ptgt;
15235         struct fcp_lun  *plun;
15236         caddr_t                 buf;
15237         int                     scsi_cmd = 0;
15238 
15239         ptgt = icmd->ipkt_tgt;
15240         plun = icmd->ipkt_lun;
15241         pptr = ptgt->tgt_port;
15242 
15243         buf = kmem_zalloc(256, KM_NOSLEEP);
15244         if (buf == NULL) {
15245                 return;
15246         }
15247 
15248         switch (icmd->ipkt_opcode) {
15249         case SCMD_REPORT_LUN:
15250                 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x"
15251                     " lun=0x%%x failed");
15252                 scsi_cmd++;
15253                 break;
15254 
15255         case SCMD_INQUIRY_PAGE83:
15256                 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x"
15257                     " lun=0x%%x failed");
15258                 scsi_cmd++;
15259                 break;
15260 
15261         case SCMD_INQUIRY:
15262                 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x"
15263                     " lun=0x%%x failed");
15264                 scsi_cmd++;
15265                 break;
15266 
15267         case LA_ELS_PLOGI:
15268                 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed");
15269                 break;
15270 
15271         case LA_ELS_PRLI:
15272                 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed");
15273                 break;
15274         }
15275 
15276         if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) {
15277                 struct fcp_rsp          response, *rsp;
15278                 uchar_t                 asc, ascq;
15279                 caddr_t                 sense_key = NULL;
15280                 struct fcp_rsp_info     fcp_rsp_err, *bep;
15281 
15282                 if (icmd->ipkt_nodma) {
15283                         rsp = (struct fcp_rsp *)fpkt->pkt_resp;
15284                         bep = (struct fcp_rsp_info *)((caddr_t)rsp +
15285                             sizeof (struct fcp_rsp));
15286                 } else {
15287                         rsp = &response;
15288                         bep = &fcp_rsp_err;
15289 
15290                         FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc,
15291                             sizeof (struct fcp_rsp));
15292 
15293                         FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp),
15294                             bep, fpkt->pkt_resp_acc,
15295                             sizeof (struct fcp_rsp_info));
15296                 }
15297 
15298 
15299                 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) {
15300                         (void) sprintf(buf + strlen(buf),
15301                             " : Bad FCP response values rsvd1=%%x, rsvd2=%%x,"
15302                             " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x,"
15303                             " senselen=%%x. Giving up");
15304 
15305                         fcp_log(CE_WARN, pptr->port_dip, buf,
15306                             ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0,
15307                             rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0,
15308                             rsp->fcp_u.fcp_status.reserved_1,
15309                             rsp->fcp_response_len, rsp->fcp_sense_len);
15310 
15311                         kmem_free(buf, 256);
15312                         return;
15313                 }
15314 
15315                 if (rsp->fcp_u.fcp_status.rsp_len_set &&
15316                     bep->rsp_code != FCP_NO_FAILURE) {
15317                         (void) sprintf(buf + strlen(buf),
15318                             " FCP Response code = 0x%x", bep->rsp_code);
15319                 }
15320 
15321                 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) {
15322                         struct scsi_extended_sense sense_info, *sense_ptr;
15323 
15324                         if (icmd->ipkt_nodma) {
15325                                 sense_ptr = (struct scsi_extended_sense *)
15326                                     ((caddr_t)fpkt->pkt_resp +
15327                                     sizeof (struct fcp_rsp) +
15328                                     rsp->fcp_response_len);
15329                         } else {
15330                                 sense_ptr = &sense_info;
15331 
15332                                 FCP_CP_IN(fpkt->pkt_resp +
15333                                     sizeof (struct fcp_rsp) +
15334                                     rsp->fcp_response_len, &sense_info,
15335                                     fpkt->pkt_resp_acc,
15336                                     sizeof (struct scsi_extended_sense));
15337                         }
15338 
15339                         if (sense_ptr->es_key < NUM_SENSE_KEYS +
15340                             NUM_IMPL_SENSE_KEYS) {
15341                                 sense_key = sense_keys[sense_ptr->es_key];
15342                         } else {
15343                                 sense_key = "Undefined";
15344                         }
15345 
15346                         asc = sense_ptr->es_add_code;
15347                         ascq = sense_ptr->es_qual_code;
15348 
15349                         (void) sprintf(buf + strlen(buf),
15350                             ": sense key=%%s, ASC=%%x," " ASCQ=%%x."
15351                             " Giving up");
15352 
15353                         fcp_log(CE_WARN, pptr->port_dip, buf,
15354                             ptgt->tgt_d_id, plun->lun_num, sense_key,
15355                             asc, ascq);
15356                 } else {
15357                         (void) sprintf(buf + strlen(buf),
15358                             " : SCSI status=%%x. Giving up");
15359 
15360                         fcp_log(CE_WARN, pptr->port_dip, buf,
15361                             ptgt->tgt_d_id, plun->lun_num,
15362                             rsp->fcp_u.fcp_status.scsi_status);
15363                 }
15364         } else {
15365                 caddr_t state, reason, action, expln;
15366 
15367                 (void) fc_ulp_pkt_error(fpkt, &state, &reason,
15368                     &action, &expln);
15369 
15370                 (void) sprintf(buf + strlen(buf), ": State:%%s,"
15371                     " Reason:%%s. Giving up");
15372 
15373                 if (scsi_cmd) {
15374                         fcp_log(CE_WARN, pptr->port_dip, buf,
15375                             ptgt->tgt_d_id, plun->lun_num, state, reason);
15376                 } else {
15377                         fcp_log(CE_WARN, pptr->port_dip, buf,
15378                             ptgt->tgt_d_id, state, reason);
15379                 }
15380         }
15381 
15382         kmem_free(buf, 256);
15383 }
15384 
15385 
15386 static int
15387 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt,
15388     struct fcp_ipkt *icmd, int rval, caddr_t op)
15389 {
15390         int     ret = DDI_FAILURE;
15391         char    *error;
15392 
15393         switch (rval) {
15394         case FC_DEVICE_BUSY_NEW_RSCN:
15395                 /*
15396                  * This means that there was a new RSCN that the transport
15397                  * knows about (which the ULP *may* know about too) but the
15398                  * pkt that was sent down was related to an older RSCN. So, we
15399                  * are just going to reset the retry count and deadline and
15400                  * continue to retry. The idea is that transport is currently
15401                  * working on the new RSCN and will soon let the ULPs know
15402                  * about it and when it does the existing logic will kick in
15403                  * where it will change the tcount to indicate that something
15404                  * changed on the target. So, rediscovery will start and there
15405                  * will not be an infinite retry.
15406                  *
15407                  * For a full flow of how the RSCN info is transferred back and
15408                  * forth, see fp.c
15409                  */
15410                 icmd->ipkt_retries = 0;
15411                 icmd->ipkt_port->port_deadline = fcp_watchdog_time +
15412                     FCP_ICMD_DEADLINE;
15413 
15414                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15415                     FCP_BUF_LEVEL_3, 0,
15416                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15417                     rval, ptgt->tgt_d_id);
15418                 /* FALLTHROUGH */
15419 
15420         case FC_STATEC_BUSY:
15421         case FC_DEVICE_BUSY:
15422         case FC_PBUSY:
15423         case FC_FBUSY:
15424         case FC_TRAN_BUSY:
15425         case FC_OFFLINE:
15426                 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15427                     FCP_BUF_LEVEL_3, 0,
15428                     "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15429                     rval, ptgt->tgt_d_id);
15430                 if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15431                     fcp_is_retryable(icmd)) {
15432                         fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15433                         ret = DDI_SUCCESS;
15434                 }
15435                 break;
15436 
15437         case FC_LOGINREQ:
15438                 /*
15439                  * FC_LOGINREQ used to be handled just like all the cases
15440                  * above. It has been changed to handled a PRLI that fails
15441                  * with FC_LOGINREQ different than other ipkts that fail
15442                  * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is
15443                  * a simple matter to turn it into a PLOGI instead, so that's
15444                  * exactly what we do here.
15445                  */
15446                 if (icmd->ipkt_opcode == LA_ELS_PRLI) {
15447                         ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt,
15448                             icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt,
15449                             icmd->ipkt_change_cnt, icmd->ipkt_cause);
15450                 } else {
15451                         FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace,
15452                             FCP_BUF_LEVEL_3, 0,
15453                             "fcp_handle_ipkt_errors: rval=%x  for D_ID=%x",
15454                             rval, ptgt->tgt_d_id);
15455                         if (icmd->ipkt_retries < FCP_MAX_RETRIES &&
15456                             fcp_is_retryable(icmd)) {
15457                                 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt);
15458                                 ret = DDI_SUCCESS;
15459                         }
15460                 }
15461                 break;
15462 
15463         default:
15464                 mutex_enter(&pptr->port_mutex);
15465                 mutex_enter(&ptgt->tgt_mutex);
15466                 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) {
15467                         mutex_exit(&ptgt->tgt_mutex);
15468                         mutex_exit(&pptr->port_mutex);
15469 
15470                         (void) fc_ulp_error(rval, &error);
15471                         fcp_log(CE_WARN, pptr->port_dip,
15472                             "!Failed to send %s to D_ID=%x error=%s",
15473                             op, ptgt->tgt_d_id, error);
15474                 } else {
15475                         FCP_TRACE(fcp_logq, pptr->port_instbuf,
15476                             fcp_trace, FCP_BUF_LEVEL_2, 0,
15477                             "fcp_handle_ipkt_errors,1: state change occured"
15478                             " for D_ID=0x%x", ptgt->tgt_d_id);
15479                         mutex_exit(&ptgt->tgt_mutex);
15480                         mutex_exit(&pptr->port_mutex);
15481                 }
15482                 break;
15483         }
15484 
15485         return (ret);
15486 }
15487 
15488 
15489 /*
15490  * Check of outstanding commands on any LUN for this target
15491  */
15492 static int
15493 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt)
15494 {
15495         struct  fcp_lun *plun;
15496         struct  fcp_pkt *cmd;
15497 
15498         for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) {
15499                 mutex_enter(&plun->lun_mutex);
15500                 for (cmd = plun->lun_pkt_head; cmd != NULL;
15501                     cmd = cmd->cmd_forw) {
15502                         if (cmd->cmd_state == FCP_PKT_ISSUED) {
15503                                 mutex_exit(&plun->lun_mutex);
15504                                 return (FC_SUCCESS);
15505                         }
15506                 }
15507                 mutex_exit(&plun->lun_mutex);
15508         }
15509 
15510         return (FC_FAILURE);
15511 }
15512 
15513 static fc_portmap_t *
15514 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt)
15515 {
15516         int                     i;
15517         fc_portmap_t            *devlist;
15518         fc_portmap_t            *devptr = NULL;
15519         struct fcp_tgt  *ptgt;
15520 
15521         mutex_enter(&pptr->port_mutex);
15522         for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) {
15523                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15524                     ptgt = ptgt->tgt_next) {
15525                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15526                                 ++*dev_cnt;
15527                         }
15528                 }
15529         }
15530 
15531         devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt,
15532             KM_NOSLEEP);
15533         if (devlist == NULL) {
15534                 mutex_exit(&pptr->port_mutex);
15535                 fcp_log(CE_WARN, pptr->port_dip,
15536                     "!fcp%d: failed to allocate for portmap for construct map",
15537                     pptr->port_instance);
15538                 return (devptr);
15539         }
15540 
15541         for (i = 0; i < FCP_NUM_HASH; i++) {
15542                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15543                     ptgt = ptgt->tgt_next) {
15544                         if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) {
15545                                 int ret;
15546 
15547                                 ret = fc_ulp_pwwn_to_portmap(
15548                                     pptr->port_fp_handle,
15549                                     (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0],
15550                                     devlist);
15551 
15552                                 if (ret == FC_SUCCESS) {
15553                                         devlist++;
15554                                         continue;
15555                                 }
15556 
15557                                 devlist->map_pd = NULL;
15558                                 devlist->map_did.port_id = ptgt->tgt_d_id;
15559                                 devlist->map_hard_addr.hard_addr =
15560                                     ptgt->tgt_hard_addr;
15561 
15562                                 devlist->map_state = PORT_DEVICE_INVALID;
15563                                 devlist->map_type = PORT_DEVICE_OLD;
15564 
15565                                 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0],
15566                                     &devlist->map_nwwn, FC_WWN_SIZE);
15567 
15568                                 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0],
15569                                     &devlist->map_pwwn, FC_WWN_SIZE);
15570 
15571                                 devlist++;
15572                         }
15573                 }
15574         }
15575 
15576         mutex_exit(&pptr->port_mutex);
15577 
15578         return (devptr);
15579 }
15580 /*
15581  * Inimate MPxIO that the lun is busy and cannot accept regular IO
15582  */
15583 static void
15584 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr)
15585 {
15586         int i;
15587         struct fcp_tgt  *ptgt;
15588         struct fcp_lun  *plun;
15589 
15590         for (i = 0; i < FCP_NUM_HASH; i++) {
15591                 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL;
15592                     ptgt = ptgt->tgt_next) {
15593                         mutex_enter(&ptgt->tgt_mutex);
15594                         for (plun = ptgt->tgt_lun; plun != NULL;
15595                             plun = plun->lun_next) {
15596                                 if (plun->lun_mpxio &&
15597                                     plun->lun_state & FCP_LUN_BUSY) {
15598                                         if (!fcp_pass_to_hp(pptr, plun,
15599                                             plun->lun_cip,
15600                                             FCP_MPXIO_PATH_SET_BUSY,
15601                                             pptr->port_link_cnt,
15602                                             ptgt->tgt_change_cnt, 0, 0)) {
15603                                                 FCP_TRACE(fcp_logq,
15604                                                     pptr->port_instbuf,
15605                                                     fcp_trace,
15606                                                     FCP_BUF_LEVEL_2, 0,
15607                                                     "path_verifybusy: "
15608                                                     "disable lun %p failed!",
15609                                                     plun);
15610                                         }
15611                                 }
15612                         }
15613                         mutex_exit(&ptgt->tgt_mutex);
15614                 }
15615         }
15616 }
15617 
15618 static int
15619 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what)
15620 {
15621         dev_info_t              *cdip = NULL;
15622         dev_info_t              *pdip = NULL;
15623 
15624         ASSERT(plun);
15625 
15626         mutex_enter(&plun->lun_mutex);
15627         if (fcp_is_child_present(plun, cip) == FC_FAILURE) {
15628                 mutex_exit(&plun->lun_mutex);
15629                 return (NDI_FAILURE);
15630         }
15631         mutex_exit(&plun->lun_mutex);
15632         cdip = mdi_pi_get_client(PIP(cip));
15633         pdip = mdi_pi_get_phci(PIP(cip));
15634 
15635         ASSERT(cdip != NULL);
15636         ASSERT(pdip != NULL);
15637 
15638         if (what == FCP_MPXIO_PATH_CLEAR_BUSY) {
15639                 /* LUN ready for IO */
15640                 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15641         } else {
15642                 /* LUN busy to accept IO */
15643                 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT);
15644         }
15645         return (NDI_SUCCESS);
15646 }
15647 
15648 /*
15649  * Caller must free the returned string of MAXPATHLEN len
15650  * If the device is offline (-1 instance number) NULL
15651  * will be returned.
15652  */
15653 static char *
15654 fcp_get_lun_path(struct fcp_lun *plun) {
15655         dev_info_t      *dip = NULL;
15656         char            *path = NULL;
15657         mdi_pathinfo_t  *pip = NULL;
15658 
15659         if (plun == NULL) {
15660                 return (NULL);
15661         }
15662 
15663         mutex_enter(&plun->lun_mutex);
15664         if (plun->lun_mpxio == 0) {
15665                 dip = DIP(plun->lun_cip);
15666                 mutex_exit(&plun->lun_mutex);
15667         } else {
15668                 /*
15669                  * lun_cip must be accessed with lun_mutex held. Here
15670                  * plun->lun_cip either points to a valid node or it is NULL.
15671                  * Make a copy so that we can release lun_mutex.
15672                  */
15673                 pip = PIP(plun->lun_cip);
15674 
15675                 /*
15676                  * Increase ref count on the path so that we can release
15677                  * lun_mutex and still be sure that the pathinfo node (and thus
15678                  * also the client) is not deallocated. If pip is NULL, this
15679                  * has no effect.
15680                  */
15681                 mdi_hold_path(pip);
15682 
15683                 mutex_exit(&plun->lun_mutex);
15684 
15685                 /* Get the client. If pip is NULL, we get NULL. */
15686                 dip = mdi_pi_get_client(pip);
15687         }
15688 
15689         if (dip == NULL)
15690                 goto out;
15691         if (ddi_get_instance(dip) < 0)
15692                 goto out;
15693 
15694         path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
15695         if (path == NULL)
15696                 goto out;
15697 
15698         (void) ddi_pathname(dip, path);
15699 
15700         /* Clean up. */
15701 out:
15702         if (pip != NULL)
15703                 mdi_rele_path(pip);
15704 
15705         /*
15706          * In reality, the user wants a fully valid path (one they can open)
15707          * but this string is lacking the mount point, and the minor node.
15708          * It would be nice if we could "figure these out" somehow
15709          * and fill them in.  Otherwise, the userland code has to understand
15710          * driver specific details of which minor node is the "best" or
15711          * "right" one to expose.  (Ex: which slice is the whole disk, or
15712          * which tape doesn't rewind)
15713          */
15714         return (path);
15715 }
15716 
15717 static int
15718 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag,
15719     ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
15720 {
15721         int64_t reset_delay;
15722         int rval, retry = 0;
15723         struct fcp_port *pptr = fcp_dip2port(parent);
15724 
15725         reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15726             (ddi_get_lbolt64() - pptr->port_attach_time);
15727         if (reset_delay < 0) {
15728                 reset_delay = 0;
15729         }
15730 
15731         if (fcp_bus_config_debug) {
15732                 flag |= NDI_DEVI_DEBUG;
15733         }
15734 
15735         switch (op) {
15736         case BUS_CONFIG_ONE:
15737                 /*
15738                  * Retry the command since we need to ensure
15739                  * the fabric devices are available for root
15740                  */
15741                 while (retry++ < fcp_max_bus_config_retries) {
15742                         rval =  (ndi_busop_bus_config(parent,
15743                             flag | NDI_MDI_FALLBACK, op,
15744                             arg, childp, (clock_t)reset_delay));
15745                         if (rval == 0) {
15746                                 return (rval);
15747                         }
15748                 }
15749 
15750                 /*
15751                  * drain taskq to make sure nodes are created and then
15752                  * try again.
15753                  */
15754                 taskq_wait(DEVI(parent)->devi_taskq);
15755                 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK,
15756                     op, arg, childp, 0));
15757 
15758         case BUS_CONFIG_DRIVER:
15759         case BUS_CONFIG_ALL: {
15760                 /*
15761                  * delay till all devices report in (port_tmp_cnt == 0)
15762                  * or FCP_INIT_WAIT_TIMEOUT
15763                  */
15764                 mutex_enter(&pptr->port_mutex);
15765                 while ((reset_delay > 0) && pptr->port_tmp_cnt) {
15766                         (void) cv_timedwait(&pptr->port_config_cv,
15767                             &pptr->port_mutex,
15768                             ddi_get_lbolt() + (clock_t)reset_delay);
15769                         reset_delay =
15770                             (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) -
15771                             (ddi_get_lbolt64() - pptr->port_attach_time);
15772                 }
15773                 mutex_exit(&pptr->port_mutex);
15774                 /* drain taskq to make sure nodes are created */
15775                 taskq_wait(DEVI(parent)->devi_taskq);
15776                 return (ndi_busop_bus_config(parent, flag, op,
15777                     arg, childp, 0));
15778         }
15779 
15780         default:
15781                 return (NDI_FAILURE);
15782         }
15783         /*NOTREACHED*/
15784 }
15785 
15786 static int
15787 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag,
15788     ddi_bus_config_op_t op, void *arg)
15789 {
15790         if (fcp_bus_config_debug) {
15791                 flag |= NDI_DEVI_DEBUG;
15792         }
15793 
15794         return (ndi_busop_bus_unconfig(parent, flag, op, arg));
15795 }
15796 
15797 
15798 /*
15799  * Routine to copy GUID into the lun structure.
15800  * returns 0 if copy was successful and 1 if encountered a
15801  * failure and did not copy the guid.
15802  */
15803 static int
15804 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp)
15805 {
15806 
15807         int retval = 0;
15808 
15809         /* add one for the null terminator */
15810         const unsigned int len = strlen(guidp) + 1;
15811 
15812         if ((guidp == NULL) || (plun == NULL)) {
15813                 return (1);
15814         }
15815 
15816         /*
15817          * if the plun->lun_guid already has been allocated,
15818          * then check the size. if the size is exact, reuse
15819          * it....if not free it an allocate the required size.
15820          * The reallocation should NOT typically happen
15821          * unless the GUIDs reported changes between passes.
15822          * We free up and alloc again even if the
15823          * size was more than required. This is due to the
15824          * fact that the field lun_guid_size - serves
15825          * dual role of indicating the size of the wwn
15826          * size and ALSO the allocation size.
15827          */
15828         if (plun->lun_guid) {
15829                 if (plun->lun_guid_size != len) {
15830                         /*
15831                          * free the allocated memory and
15832                          * initialize the field
15833                          * lun_guid_size to 0.
15834                          */
15835                         kmem_free(plun->lun_guid, plun->lun_guid_size);
15836                         plun->lun_guid = NULL;
15837                         plun->lun_guid_size = 0;
15838                 }
15839         }
15840         /*
15841          * alloc only if not already done.
15842          */
15843         if (plun->lun_guid == NULL) {
15844                 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP);
15845                 if (plun->lun_guid == NULL) {
15846                         cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:"
15847                             "Unable to allocate"
15848                             "Memory for GUID!!! size %d", len);
15849                         retval = 1;
15850                 } else {
15851                         plun->lun_guid_size = len;
15852                 }
15853         }
15854         if (plun->lun_guid) {
15855                 /*
15856                  * now copy the GUID
15857                  */
15858                 bcopy(guidp, plun->lun_guid, plun->lun_guid_size);
15859         }
15860         return (retval);
15861 }
15862 
15863 /*
15864  * fcp_reconfig_wait
15865  *
15866  * Wait for a rediscovery/reconfiguration to complete before continuing.
15867  */
15868 
15869 static void
15870 fcp_reconfig_wait(struct fcp_port *pptr)
15871 {
15872         clock_t         reconfig_start, wait_timeout;
15873 
15874         /*
15875          * Quick check.  If pptr->port_tmp_cnt is 0, there is no
15876          * reconfiguration in progress.
15877          */
15878 
15879         mutex_enter(&pptr->port_mutex);
15880         if (pptr->port_tmp_cnt == 0) {
15881                 mutex_exit(&pptr->port_mutex);
15882                 return;
15883         }
15884         mutex_exit(&pptr->port_mutex);
15885 
15886         /*
15887          * If we cause a reconfig by raising power, delay until all devices
15888          * report in (port_tmp_cnt returns to 0)
15889          */
15890 
15891         reconfig_start = ddi_get_lbolt();
15892         wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT);
15893 
15894         mutex_enter(&pptr->port_mutex);
15895 
15896         while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) &&
15897             pptr->port_tmp_cnt) {
15898 
15899                 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex,
15900                     reconfig_start + wait_timeout);
15901         }
15902 
15903         mutex_exit(&pptr->port_mutex);
15904 
15905         /*
15906          * Even if fcp_tmp_count isn't 0, continue without error.  The port
15907          * we want may still be ok.  If not, it will error out later
15908          */
15909 }
15910 
15911 /*
15912  * Read masking info from fp.conf and construct the global fcp_lun_blacklist.
15913  * We rely on the fcp_global_mutex to provide protection against changes to
15914  * the fcp_lun_blacklist.
15915  *
15916  * You can describe a list of target port WWNs and LUN numbers which will
15917  * not be configured. LUN numbers will be interpreted as decimal. White
15918  * spaces and ',' can be used in the list of LUN numbers.
15919  *
15920  * To prevent LUNs 1 and 2 from being configured for target
15921  * port 510000f010fd92a1 and target port 510000e012079df1, set:
15922  *
15923  * pwwn-lun-blacklist=
15924  * "510000f010fd92a1,1,2",
15925  * "510000e012079df1,1,2";
15926  */
15927 static void
15928 fcp_read_blacklist(dev_info_t *dip,
15929     struct fcp_black_list_entry **pplun_blacklist) {
15930         char **prop_array       = NULL;
15931         char *curr_pwwn         = NULL;
15932         char *curr_lun          = NULL;
15933         uint32_t prop_item      = 0;
15934         int idx                 = 0;
15935         int len                 = 0;
15936 
15937         ASSERT(mutex_owned(&fcp_global_mutex));
15938         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip,
15939             DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
15940             LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) {
15941                 return;
15942         }
15943 
15944         for (idx = 0; idx < prop_item; idx++) {
15945 
15946                 curr_pwwn = prop_array[idx];
15947                 while (*curr_pwwn == ' ') {
15948                         curr_pwwn++;
15949                 }
15950                 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) {
15951                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15952                             ", please check.", curr_pwwn);
15953                         continue;
15954                 }
15955                 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') &&
15956                     (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) {
15957                         fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist"
15958                             ", please check.", curr_pwwn);
15959                         continue;
15960                 }
15961                 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) {
15962                         if (isxdigit(curr_pwwn[len]) != TRUE) {
15963                                 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the "
15964                                     "blacklist, please check.", curr_pwwn);
15965                                 break;
15966                         }
15967                 }
15968                 if (len != sizeof (la_wwn_t) * 2) {
15969                         continue;
15970                 }
15971 
15972                 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1;
15973                 *(curr_lun - 1) = '\0';
15974                 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist);
15975         }
15976 
15977         ddi_prop_free(prop_array);
15978 }
15979 
15980 /*
15981  * Get the masking info about one remote target port designated by wwn.
15982  * Lun ids could be separated by ',' or white spaces.
15983  */
15984 static void
15985 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun,
15986     struct fcp_black_list_entry **pplun_blacklist) {
15987         int             idx                     = 0;
15988         uint32_t        offset                  = 0;
15989         unsigned long   lun_id                  = 0;
15990         char            lunid_buf[16];
15991         char            *pend                   = NULL;
15992         int             illegal_digit           = 0;
15993 
15994         while (offset < strlen(curr_lun)) {
15995                 while ((curr_lun[offset + idx] != ',') &&
15996                     (curr_lun[offset + idx] != '\0') &&
15997                     (curr_lun[offset + idx] != ' ')) {
15998                         if (isdigit(curr_lun[offset + idx]) == 0) {
15999                                 illegal_digit++;
16000                         }
16001                         idx++;
16002                 }
16003                 if (illegal_digit > 0) {
16004                         offset += (idx+1);      /* To the start of next lun */
16005                         idx = 0;
16006                         illegal_digit = 0;
16007                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16008                             "the blacklist, please check digits.",
16009                             curr_lun, curr_pwwn);
16010                         continue;
16011                 }
16012                 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) {
16013                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16014                             "the blacklist, please check the length of LUN#.",
16015                             curr_lun, curr_pwwn);
16016                         break;
16017                 }
16018                 if (idx == 0) { /* ignore ' ' or ',' or '\0' */
16019                     offset++;
16020                     continue;
16021                 }
16022 
16023                 bcopy(curr_lun + offset, lunid_buf, idx);
16024                 lunid_buf[idx] = '\0';
16025                 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) {
16026                         fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist);
16027                 } else {
16028                         fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in "
16029                             "the blacklist, please check %s.",
16030                             curr_lun, curr_pwwn, lunid_buf);
16031                 }
16032                 offset += (idx+1);      /* To the start of next lun */
16033                 idx = 0;
16034         }
16035 }
16036 
16037 /*
16038  * Add one masking record
16039  */
16040 static void
16041 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id,
16042     struct fcp_black_list_entry **pplun_blacklist) {
16043         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16044         struct fcp_black_list_entry     *new_entry      = NULL;
16045         la_wwn_t                        wwn;
16046 
16047         fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t));
16048         while (tmp_entry) {
16049                 if ((bcmp(&tmp_entry->wwn, &wwn,
16050                     sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) {
16051                         return;
16052                 }
16053 
16054                 tmp_entry = tmp_entry->next;
16055         }
16056 
16057         /* add to black list */
16058         new_entry = (struct fcp_black_list_entry *)kmem_zalloc
16059             (sizeof (struct fcp_black_list_entry), KM_SLEEP);
16060         bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t));
16061         new_entry->lun = lun_id;
16062         new_entry->masked = 0;
16063         new_entry->next = *pplun_blacklist;
16064         *pplun_blacklist = new_entry;
16065 }
16066 
16067 /*
16068  * Check if we should mask the specified lun of this fcp_tgt
16069  */
16070 static int
16071 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) {
16072         struct fcp_black_list_entry *remote_port;
16073 
16074         remote_port = fcp_lun_blacklist;
16075         while (remote_port != NULL) {
16076                 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) {
16077                         if (remote_port->lun == lun_id) {
16078                                 remote_port->masked++;
16079                                 if (remote_port->masked == 1) {
16080                                         fcp_log(CE_NOTE, NULL, "LUN %d of port "
16081                                             "%02x%02x%02x%02x%02x%02x%02x%02x "
16082                                             "is masked due to black listing.\n",
16083                                             lun_id, wwn->raw_wwn[0],
16084                                             wwn->raw_wwn[1], wwn->raw_wwn[2],
16085                                             wwn->raw_wwn[3], wwn->raw_wwn[4],
16086                                             wwn->raw_wwn[5], wwn->raw_wwn[6],
16087                                             wwn->raw_wwn[7]);
16088                                 }
16089                                 return (TRUE);
16090                         }
16091                 }
16092                 remote_port = remote_port->next;
16093         }
16094         return (FALSE);
16095 }
16096 
16097 /*
16098  * Release all allocated resources
16099  */
16100 static void
16101 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) {
16102         struct fcp_black_list_entry     *tmp_entry      = *pplun_blacklist;
16103         struct fcp_black_list_entry     *current_entry  = NULL;
16104 
16105         ASSERT(mutex_owned(&fcp_global_mutex));
16106         /*
16107          * Traverse all luns
16108          */
16109         while (tmp_entry) {
16110                 current_entry = tmp_entry;
16111                 tmp_entry = tmp_entry->next;
16112                 kmem_free(current_entry, sizeof (struct fcp_black_list_entry));
16113         }
16114         *pplun_blacklist = NULL;
16115 }
16116 
16117 /*
16118  * In fcp module,
16119  *   pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port
16120  */
16121 static struct scsi_pkt *
16122 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
16123     struct buf *bp, int cmdlen, int statuslen, int tgtlen,
16124     int flags, int (*callback)(), caddr_t arg)
16125 {
16126         fcp_port_t      *pptr = ADDR2FCP(ap);
16127         fcp_pkt_t       *cmd  = NULL;
16128         fc_frame_hdr_t  *hp;
16129 
16130         /*
16131          * First step: get the packet
16132          */
16133         if (pkt == NULL) {
16134                 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen,
16135                     tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len,
16136                     callback, arg);
16137                 if (pkt == NULL) {
16138                         return (NULL);
16139                 }
16140 
16141                 /*
16142                  * All fields in scsi_pkt will be initialized properly or
16143                  * set to zero. We need do nothing for scsi_pkt.
16144                  */
16145                 /*
16146                  * But it's our responsibility to link other related data
16147                  * structures. Their initialization will be done, just
16148                  * before the scsi_pkt will be sent to FCA.
16149                  */
16150                 cmd             = PKT2CMD(pkt);
16151                 cmd->cmd_pkt = pkt;
16152                 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet;
16153                 /*
16154                  * fc_packet_t
16155                  */
16156                 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd;
16157                 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd +
16158                     sizeof (struct fcp_pkt));
16159                 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd;
16160                 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd);
16161                 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp;
16162                 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE;
16163                 /*
16164                  * Fill in the Fabric Channel Header
16165                  */
16166                 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr;
16167                 hp->r_ctl = R_CTL_COMMAND;
16168                 hp->rsvd = 0;
16169                 hp->type = FC_TYPE_SCSI_FCP;
16170                 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ;
16171                 hp->seq_id = 0;
16172                 hp->df_ctl  = 0;
16173                 hp->seq_cnt = 0;
16174                 hp->ox_id = 0xffff;
16175                 hp->rx_id = 0xffff;
16176                 hp->ro = 0;
16177         } else {
16178                 /*
16179                  * We need think if we should reset any elements in
16180                  * related data structures.
16181                  */
16182                 FCP_TRACE(fcp_logq, pptr->port_instbuf,
16183                     fcp_trace, FCP_BUF_LEVEL_6, 0,
16184                     "reusing pkt, flags %d", flags);
16185                 cmd = PKT2CMD(pkt);
16186                 if (cmd->cmd_fp_pkt->pkt_pd) {
16187                         cmd->cmd_fp_pkt->pkt_pd = NULL;
16188                 }
16189         }
16190 
16191         /*
16192          * Second step:  dma allocation/move
16193          */
16194         if (bp && bp->b_bcount != 0) {
16195                 /*
16196                  * Mark if it's read or write
16197                  */
16198                 if (bp->b_flags & B_READ) {
16199                         cmd->cmd_flags |= CFLAG_IS_READ;
16200                 } else {
16201                         cmd->cmd_flags &= ~CFLAG_IS_READ;
16202                 }
16203 
16204                 bp_mapin(bp);
16205                 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr;
16206                 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount;
16207                 cmd->cmd_fp_pkt->pkt_data_resid = 0;
16208         } else {
16209                 /*
16210                  * It seldom happens, except when CLUSTER or SCSI_VHCI wants
16211                  * to send zero-length read/write.
16212                  */
16213                 cmd->cmd_fp_pkt->pkt_data = NULL;
16214                 cmd->cmd_fp_pkt->pkt_datalen = 0;
16215         }
16216 
16217         return (pkt);
16218 }
16219 
16220 static void
16221 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16222 {
16223         fcp_port_t      *pptr = ADDR2FCP(ap);
16224 
16225         /*
16226          * First we let FCA to uninitilize private part.
16227          */
16228         (void) fc_ulp_uninit_packet(pptr->port_fp_handle,
16229             PKT2CMD(pkt)->cmd_fp_pkt);
16230 
16231         /*
16232          * Then we uninitialize fc_packet.
16233          */
16234 
16235         /*
16236          * Thirdly, we uninitializae fcp_pkt.
16237          */
16238 
16239         /*
16240          * In the end, we free scsi_pkt.
16241          */
16242         scsi_hba_pkt_free(ap, pkt);
16243 }
16244 
16245 static int
16246 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt)
16247 {
16248         fcp_port_t      *pptr = ADDR2FCP(ap);
16249         fcp_lun_t       *plun = ADDR2LUN(ap);
16250         fcp_tgt_t       *ptgt = plun->lun_tgt;
16251         fcp_pkt_t       *cmd  = PKT2CMD(pkt);
16252         fcp_cmd_t       *fcmd = &cmd->cmd_fcp_cmd;
16253         fc_packet_t     *fpkt = cmd->cmd_fp_pkt;
16254         int              rval;
16255 
16256         fpkt->pkt_pd = ptgt->tgt_pd_handle;
16257         (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1);
16258 
16259         /*
16260          * Firstly, we need initialize fcp_pkt_t
16261          * Secondly, we need initialize fcp_cmd_t.
16262          */
16263         bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen);
16264         fcmd->fcp_data_len = fpkt->pkt_datalen;
16265         fcmd->fcp_ent_addr = plun->lun_addr;
16266         if (pkt->pkt_flags & FLAG_HTAG) {
16267                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q;
16268         } else if (pkt->pkt_flags & FLAG_OTAG) {
16269                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED;
16270         } else if (pkt->pkt_flags & FLAG_STAG) {
16271                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE;
16272         } else {
16273                 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED;
16274         }
16275 
16276         if (cmd->cmd_flags & CFLAG_IS_READ) {
16277                 fcmd->fcp_cntl.cntl_read_data = 1;
16278                 fcmd->fcp_cntl.cntl_write_data = 0;
16279         } else {
16280                 fcmd->fcp_cntl.cntl_read_data = 0;
16281                 fcmd->fcp_cntl.cntl_write_data = 1;
16282         }
16283 
16284         /*
16285          * Then we need initialize fc_packet_t too.
16286          */
16287         fpkt->pkt_timeout = pkt->pkt_time + 2;
16288         fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id;
16289         fpkt->pkt_cmd_fhdr.s_id = pptr->port_id;
16290         if (cmd->cmd_flags & CFLAG_IS_READ) {
16291                 fpkt->pkt_tran_type = FC_PKT_FCP_READ;
16292         } else {
16293                 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE;
16294         }
16295 
16296         if (pkt->pkt_flags & FLAG_NOINTR) {
16297                 fpkt->pkt_comp = NULL;
16298                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR);
16299         } else {
16300                 fpkt->pkt_comp = fcp_cmd_callback;
16301                 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR);
16302                 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) {
16303                         fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB;
16304                 }
16305         }
16306 
16307         /*
16308          * Lastly, we need initialize scsi_pkt
16309          */
16310         pkt->pkt_reason = CMD_CMPLT;
16311         pkt->pkt_state = 0;
16312         pkt->pkt_statistics = 0;
16313         pkt->pkt_resid = 0;
16314 
16315         /*
16316          * if interrupts aren't allowed (e.g. at dump time) then we'll
16317          * have to do polled I/O
16318          */
16319         if (pkt->pkt_flags & FLAG_NOINTR) {
16320                 return (fcp_dopoll(pptr, cmd));
16321         }
16322 
16323         cmd->cmd_state = FCP_PKT_ISSUED;
16324         rval = fcp_transport(pptr->port_fp_handle, fpkt, 0);
16325         if (rval == FC_SUCCESS) {
16326                 return (TRAN_ACCEPT);
16327         }
16328 
16329         /*
16330          * Need more consideration
16331          *
16332          * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt
16333          */
16334         cmd->cmd_state = FCP_PKT_IDLE;
16335         if (rval == FC_TRAN_BUSY) {
16336                 return (TRAN_BUSY);
16337         } else {
16338                 return (TRAN_FATAL_ERROR);
16339         }
16340 }
16341 
16342 /*
16343  * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs
16344  * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs
16345  */
16346 static void
16347 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
16348 {
16349         FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace,
16350             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16351 }
16352 
16353 /*
16354  * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE
16355  */
16356 static void
16357 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
16358 {
16359         FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace,
16360             FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt);
16361 }
--- EOF ---