1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 24 * Fibre Channel SCSI ULP Mapping driver 25 */ 26 27 #include <sys/scsi/scsi.h> 28 #include <sys/types.h> 29 #include <sys/varargs.h> 30 #include <sys/devctl.h> 31 #include <sys/thread.h> 32 #include <sys/thread.h> 33 #include <sys/open.h> 34 #include <sys/file.h> 35 #include <sys/sunndi.h> 36 #include <sys/console.h> 37 #include <sys/proc.h> 38 #include <sys/time.h> 39 #include <sys/utsname.h> 40 #include <sys/scsi/impl/scsi_reset_notify.h> 41 #include <sys/ndi_impldefs.h> 42 #include <sys/byteorder.h> 43 #include <sys/fs/dv_node.h> 44 #include <sys/ctype.h> 45 #include <sys/sunmdi.h> 46 47 #include <sys/fibre-channel/fc.h> 48 #include <sys/fibre-channel/impl/fc_ulpif.h> 49 #include <sys/fibre-channel/ulp/fcpvar.h> 50 51 /* 52 * Discovery Process 53 * ================= 54 * 55 * The discovery process is a major function of FCP. In order to help 56 * understand that function a flow diagram is given here. This diagram 57 * doesn't claim to cover all the cases and the events that can occur during 58 * the discovery process nor the subtleties of the code. The code paths shown 59 * are simplified. Its purpose is to help the reader (and potentially bug 60 * fixer) have an overall view of the logic of the code. For that reason the 61 * diagram covers the simple case of the line coming up cleanly or of a new 62 * port attaching to FCP the link being up. The reader must keep in mind 63 * that: 64 * 65 * - There are special cases where bringing devices online and offline 66 * is driven by Ioctl. 67 * 68 * - The behavior of the discovery process can be modified through the 69 * .conf file. 70 * 71 * - The line can go down and come back up at any time during the 72 * discovery process which explains some of the complexity of the code. 73 * 74 * ............................................................................ 75 * 76 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 77 * 78 * 79 * +-------------------------+ 80 * fp/fctl module --->| fcp_port_attach | 81 * +-------------------------+ 82 * | | 83 * | | 84 * | v 85 * | +-------------------------+ 86 * | | fcp_handle_port_attach | 87 * | +-------------------------+ 88 * | | 89 * | | 90 * +--------------------+ | 91 * | | 92 * v v 93 * +-------------------------+ 94 * | fcp_statec_callback | 95 * +-------------------------+ 96 * | 97 * | 98 * v 99 * +-------------------------+ 100 * | fcp_handle_devices | 101 * +-------------------------+ 102 * | 103 * | 104 * v 105 * +-------------------------+ 106 * | fcp_handle_mapflags | 107 * +-------------------------+ 108 * | 109 * | 110 * v 111 * +-------------------------+ 112 * | fcp_send_els | 113 * | | 114 * | PLOGI or PRLI To all the| 115 * | reachable devices. | 116 * +-------------------------+ 117 * 118 * 119 * ............................................................................ 120 * 121 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 122 * STEP 1 are called (it is actually the same function). 123 * 124 * 125 * +-------------------------+ 126 * | fcp_icmd_callback | 127 * fp/fctl module --->| | 128 * | callback for PLOGI and | 129 * | PRLI. | 130 * +-------------------------+ 131 * | 132 * | 133 * Received PLOGI Accept /-\ Received PRLI Accept 134 * _ _ _ _ _ _ / \_ _ _ _ _ _ 135 * | \ / | 136 * | \-/ | 137 * | | 138 * v v 139 * +-------------------------+ +-------------------------+ 140 * | fcp_send_els | | fcp_send_scsi | 141 * | | | | 142 * | PRLI | | REPORT_LUN | 143 * +-------------------------+ +-------------------------+ 144 * 145 * ............................................................................ 146 * 147 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 148 * (It is actually the same function). 149 * 150 * 151 * +-------------------------+ 152 * fp/fctl module ------->| fcp_scsi_callback | 153 * +-------------------------+ 154 * | 155 * | 156 * | 157 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 158 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 159 * | \ / | 160 * | \-/ | 161 * | | | 162 * | Receive INQUIRY reply| | 163 * | | | 164 * v v v 165 * +------------------------+ +----------------------+ +----------------------+ 166 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 167 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 168 * +------------------------+ +----------------------+ +----------------------+ 169 * | | | 170 * | | | 171 * | | | 172 * v v | 173 * +-----------------+ +-----------------+ | 174 * | fcp_send_scsi | | fcp_send_scsi | | 175 * | | | | | 176 * | INQUIRY | | INQUIRY PAGE83 | | 177 * | (To each LUN) | +-----------------+ | 178 * +-----------------+ | 179 * | 180 * v 181 * +------------------------+ 182 * | fcp_call_finish_init | 183 * +------------------------+ 184 * | 185 * v 186 * +-----------------------------+ 187 * | fcp_call_finish_init_held | 188 * +-----------------------------+ 189 * | 190 * | 191 * All LUNs scanned /-\ 192 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 193 * | \ / 194 * | \-/ 195 * v | 196 * +------------------+ | 197 * | fcp_finish_tgt | | 198 * +------------------+ | 199 * | Target Not Offline and | 200 * Target Not Offline and | not marked and tgt_node_state | 201 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 202 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 203 * | \ / | | 204 * | \-/ | | 205 * v v | 206 * +----------------------------+ +-------------------+ | 207 * | fcp_offline_target | | fcp_create_luns | | 208 * | | +-------------------+ | 209 * | A structure fcp_tgt_elem | | | 210 * | is created and queued in | v | 211 * | the FCP port list | +-------------------+ | 212 * | port_offline_tgts. It | | fcp_pass_to_hp | | 213 * | will be unqueued by the | | | | 214 * | watchdog timer. | | Called for each | | 215 * +----------------------------+ | LUN. Dispatches | | 216 * | | fcp_hp_task | | 217 * | +-------------------+ | 218 * | | | 219 * | | | 220 * | | | 221 * | +---------------->| 222 * | | 223 * +---------------------------------------------->| 224 * | 225 * | 226 * All the targets (devices) have been scanned /-\ 227 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 228 * | \ / 229 * | \-/ 230 * +-------------------------------------+ | 231 * | fcp_finish_init | | 232 * | | | 233 * | Signal broadcasts the condition | | 234 * | variable port_config_cv of the FCP | | 235 * | port. One potential code sequence | | 236 * | waiting on the condition variable | | 237 * | the code sequence handling | | 238 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 239 * | The other is in the function | | 240 * | fcp_reconfig_wait which is called | | 241 * | in the transmit path preventing IOs | | 242 * | from going through till the disco- | | 243 * | very process is over. | | 244 * +-------------------------------------+ | 245 * | | 246 * | | 247 * +--------------------------------->| 248 * | 249 * v 250 * Return 251 * 252 * ............................................................................ 253 * 254 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 255 * 256 * 257 * +-------------------------+ 258 * | fcp_hp_task | 259 * +-------------------------+ 260 * | 261 * | 262 * v 263 * +-------------------------+ 264 * | fcp_trigger_lun | 265 * +-------------------------+ 266 * | 267 * | 268 * v 269 * Bring offline /-\ Bring online 270 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 271 * | \ / | 272 * | \-/ | 273 * v v 274 * +---------------------+ +-----------------------+ 275 * | fcp_offline_child | | fcp_get_cip | 276 * +---------------------+ | | 277 * | Creates a dev_info_t | 278 * | or a mdi_pathinfo_t | 279 * | depending on whether | 280 * | mpxio is on or off. | 281 * +-----------------------+ 282 * | 283 * | 284 * v 285 * +-----------------------+ 286 * | fcp_online_child | 287 * | | 288 * | Set device online | 289 * | using NDI or MDI. | 290 * +-----------------------+ 291 * 292 * ............................................................................ 293 * 294 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 295 * what is described here. We only show the target offline path. 296 * 297 * 298 * +--------------------------+ 299 * | fcp_watch | 300 * +--------------------------+ 301 * | 302 * | 303 * v 304 * +--------------------------+ 305 * | fcp_scan_offline_tgts | 306 * +--------------------------+ 307 * | 308 * | 309 * v 310 * +--------------------------+ 311 * | fcp_offline_target_now | 312 * +--------------------------+ 313 * | 314 * | 315 * v 316 * +--------------------------+ 317 * | fcp_offline_tgt_luns | 318 * +--------------------------+ 319 * | 320 * | 321 * v 322 * +--------------------------+ 323 * | fcp_offline_lun | 324 * +--------------------------+ 325 * | 326 * | 327 * v 328 * +----------------------------------+ 329 * | fcp_offline_lun_now | 330 * | | 331 * | A request (or two if mpxio) is | 332 * | sent to the hot plug task using | 333 * | a fcp_hp_elem structure. | 334 * +----------------------------------+ 335 */ 336 337 /* 338 * Functions registered with DDI framework 339 */ 340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 345 cred_t *credp, int *rval); 346 347 /* 348 * Functions registered with FC Transport framework 349 */ 350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 351 fc_attach_cmd_t cmd, uint32_t s_id); 352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 353 fc_detach_cmd_t cmd); 354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 355 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 356 uint32_t claimed); 357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 358 fc_unsol_buf_t *buf, uint32_t claimed); 359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 360 fc_unsol_buf_t *buf, uint32_t claimed); 361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 362 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 363 uint32_t dev_cnt, uint32_t port_sid); 364 365 /* 366 * Functions registered with SCSA framework 367 */ 368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 369 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 371 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 373 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 376 static int fcp_scsi_reset(struct scsi_address *ap, int level); 377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 379 int whom); 380 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 382 void (*callback)(caddr_t), caddr_t arg); 383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 384 char *name, ddi_eventcookie_t *event_cookiep); 385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 386 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 387 ddi_callback_id_t *cb_id); 388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 389 ddi_callback_id_t cb_id); 390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 391 ddi_eventcookie_t eventid, void *impldata); 392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 393 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 395 ddi_bus_config_op_t op, void *arg); 396 397 /* 398 * Internal functions 399 */ 400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 401 int mode, int *rval); 402 403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 404 int mode, int *rval); 405 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 406 struct fcp_scsi_cmd *fscsi, int mode); 407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 408 caddr_t base_addr, int mode); 409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 410 411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 412 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 413 int *fc_pkt_reason, int *fc_pkt_action); 414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 415 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 416 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 417 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 422 423 static void fcp_handle_devices(struct fcp_port *pptr, 424 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 425 fcp_map_tag_t *map_tag, int cause); 426 static int fcp_handle_mapflags(struct fcp_port *pptr, 427 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 428 int tgt_cnt, int cause); 429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause); 430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 431 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 433 int cause); 434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 435 uint32_t state); 436 static struct fcp_port *fcp_get_port(opaque_t port_handle); 437 static void fcp_unsol_callback(fc_packet_t *fpkt); 438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 439 uchar_t r_ctl, uchar_t type); 440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 442 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 443 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 446 int nodma, int flags); 447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 449 uchar_t *wwn); 450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 451 uint32_t d_id); 452 static void fcp_icmd_callback(fc_packet_t *fpkt); 453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 454 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 456 static void fcp_scsi_callback(fc_packet_t *fpkt); 457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 461 uint16_t lun_num); 462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 463 int link_cnt, int tgt_cnt, int cause); 464 static void fcp_finish_init(struct fcp_port *pptr); 465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 466 int tgt_cnt, int cause); 467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 468 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 470 int link_cnt, int tgt_cnt, int nowait, int flags); 471 static void fcp_offline_target_now(struct fcp_port *pptr, 472 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 474 int tgt_cnt, int flags); 475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 476 int nowait, int flags); 477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 478 int tgt_cnt); 479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 480 int tgt_cnt, int flags); 481 static void fcp_scan_offline_luns(struct fcp_port *pptr); 482 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 483 static void fcp_update_offline_flags(struct fcp_lun *plun); 484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 485 static void fcp_abort_commands(struct fcp_pkt *head, struct 486 fcp_port *pptr); 487 static void fcp_cmd_callback(fc_packet_t *fpkt); 488 static void fcp_complete_pkt(fc_packet_t *fpkt); 489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 490 struct fcp_port *pptr); 491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 492 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 494 static void fcp_dealloc_lun(struct fcp_lun *plun); 495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 496 fc_portmap_t *map_entry, int link_cnt); 497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 500 int internal); 501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 503 uint32_t s_id, int instance); 504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 505 int instance); 506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 508 int); 509 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 512 int flags); 513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 514 static int fcp_reset_target(struct scsi_address *ap, int level); 515 static int fcp_commoncap(struct scsi_address *ap, char *cap, 516 int val, int tgtonly, int doset); 517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 520 int sleep); 521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 522 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 526 int lcount, int tcount); 527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 530 int tgt_cnt); 531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 532 dev_info_t *pdip, caddr_t name); 533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 534 int lcount, int tcount, int flags, int *circ); 535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 536 int lcount, int tcount, int flags, int *circ); 537 static void fcp_remove_child(struct fcp_lun *plun); 538 static void fcp_watch(void *arg); 539 static void fcp_check_reset_delay(struct fcp_port *pptr); 540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 541 struct fcp_lun *rlun, int tgt_cnt); 542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 544 uchar_t *wwn, uint16_t lun); 545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 546 struct fcp_lun *plun); 547 static void fcp_post_callback(struct fcp_pkt *cmd); 548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 549 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 551 child_info_t *cip); 552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 553 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 554 int tgt_cnt, int flags); 555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 556 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 557 int tgt_cnt, int flags, int wait); 558 static void fcp_retransport_cmd(struct fcp_port *pptr, 559 struct fcp_pkt *cmd); 560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 561 uint_t statistics); 562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 563 static void fcp_update_targets(struct fcp_port *pptr, 564 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 565 static int fcp_call_finish_init(struct fcp_port *pptr, 566 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 567 static int fcp_call_finish_init_held(struct fcp_port *pptr, 568 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 569 static void fcp_reconfigure_luns(void * tgt_handle); 570 static void fcp_free_targets(struct fcp_port *pptr); 571 static void fcp_free_target(struct fcp_tgt *ptgt); 572 static int fcp_is_retryable(struct fcp_ipkt *icmd); 573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 576 static void fcp_print_error(fc_packet_t *fpkt); 577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 578 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 581 uint32_t *dev_cnt); 582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 585 struct fcp_ioctl *, struct fcp_port **); 586 static char *fcp_get_lun_path(struct fcp_lun *plun); 587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 588 int *rval); 589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 591 static char *fcp_get_lun_path(struct fcp_lun *plun); 592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 593 int *rval); 594 static void fcp_reconfig_wait(struct fcp_port *pptr); 595 596 /* 597 * New functions added for mpxio support 598 */ 599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 600 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 602 int tcount); 603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 604 dev_info_t *pdip); 605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 610 int what); 611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 612 fc_packet_t *fpkt); 613 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 614 615 /* 616 * New functions added for lun masking support 617 */ 618 static void fcp_read_blacklist(dev_info_t *dip, 619 struct fcp_black_list_entry **pplun_blacklist); 620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 621 struct fcp_black_list_entry **pplun_blacklist); 622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 623 struct fcp_black_list_entry **pplun_blacklist); 624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 626 627 /* 628 * New functions to support software FCA (like fcoei) 629 */ 630 static struct scsi_pkt *fcp_pseudo_init_pkt( 631 struct scsi_address *ap, struct scsi_pkt *pkt, 632 struct buf *bp, int cmdlen, int statuslen, 633 int tgtlen, int flags, int (*callback)(), caddr_t arg); 634 static void fcp_pseudo_destroy_pkt( 635 struct scsi_address *ap, struct scsi_pkt *pkt); 636 static void fcp_pseudo_sync_pkt( 637 struct scsi_address *ap, struct scsi_pkt *pkt); 638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt); 639 static void fcp_pseudo_dmafree( 640 struct scsi_address *ap, struct scsi_pkt *pkt); 641 642 extern struct mod_ops mod_driverops; 643 /* 644 * This variable is defined in modctl.c and set to '1' after the root driver 645 * and fs are loaded. It serves as an indication that the root filesystem can 646 * be used. 647 */ 648 extern int modrootloaded; 649 /* 650 * This table contains strings associated with the SCSI sense key codes. It 651 * is used by FCP to print a clear explanation of the code returned in the 652 * sense information by a device. 653 */ 654 extern char *sense_keys[]; 655 /* 656 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 657 * under this device that the paths to a physical device are created when 658 * MPxIO is used. 659 */ 660 extern dev_info_t *scsi_vhci_dip; 661 662 /* 663 * Report lun processing 664 */ 665 #define FCP_LUN_ADDRESSING 0x80 666 #define FCP_PD_ADDRESSING 0x00 667 #define FCP_VOLUME_ADDRESSING 0x40 668 669 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 670 #define MAX_INT_DMA 0x7fffffff 671 /* 672 * Property definitions 673 */ 674 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 675 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 676 #define TARGET_PROP (char *)fcp_target_prop 677 #define LUN_PROP (char *)fcp_lun_prop 678 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 679 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 680 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 681 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 682 #define INIT_PORT_PROP (char *)fcp_init_port_prop 683 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 684 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 685 /* 686 * Short hand macros. 687 */ 688 #define LUN_PORT (plun->lun_tgt->tgt_port) 689 #define LUN_TGT (plun->lun_tgt) 690 691 /* 692 * Driver private macros 693 */ 694 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 695 ((x) >= 'a' && (x) <= 'f') ? \ 696 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 697 698 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 699 700 #define FCP_N_NDI_EVENTS \ 701 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 702 703 #define FCP_LINK_STATE_CHANGED(p, c) \ 704 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 705 706 #define FCP_TGT_STATE_CHANGED(t, c) \ 707 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 708 709 #define FCP_STATE_CHANGED(p, t, c) \ 710 (FCP_TGT_STATE_CHANGED(t, c)) 711 712 #define FCP_MUST_RETRY(fpkt) \ 713 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 714 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 715 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 716 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 717 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 718 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 719 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 720 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 721 722 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 723 ((es)->es_key == KEY_UNIT_ATTENTION && \ 724 (es)->es_add_code == 0x3f && \ 725 (es)->es_qual_code == 0x0e) 726 727 #define FCP_SENSE_NO_LUN(es) \ 728 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 729 (es)->es_add_code == 0x25 && \ 730 (es)->es_qual_code == 0x0) 731 732 #define FCP_VERSION "20091208-1.192" 733 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 734 735 #define FCP_NUM_ELEMENTS(array) \ 736 (sizeof (array) / sizeof ((array)[0])) 737 738 /* 739 * Debugging, Error reporting, and tracing 740 */ 741 #define FCP_LOG_SIZE 1024 * 1024 742 743 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 744 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 745 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 746 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 747 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 748 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 749 #define FCP_LEVEL_7 0x00040 750 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 751 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 752 753 754 755 /* 756 * Log contents to system messages file 757 */ 758 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 759 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 760 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 761 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 762 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 763 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 764 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 765 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 766 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 767 768 769 /* 770 * Log contents to trace buffer 771 */ 772 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 773 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 774 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 775 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 776 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 777 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 778 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 779 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 780 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 781 782 783 /* 784 * Log contents to both system messages file and trace buffer 785 */ 786 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 787 FC_TRACE_LOG_MSG) 788 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 789 FC_TRACE_LOG_MSG) 790 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 791 FC_TRACE_LOG_MSG) 792 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 793 FC_TRACE_LOG_MSG) 794 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 795 FC_TRACE_LOG_MSG) 796 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 797 FC_TRACE_LOG_MSG) 798 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 799 FC_TRACE_LOG_MSG) 800 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 801 FC_TRACE_LOG_MSG) 802 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 803 FC_TRACE_LOG_MSG) 804 #ifdef DEBUG 805 #define FCP_DTRACE fc_trace_debug 806 #else 807 #define FCP_DTRACE 808 #endif 809 810 #define FCP_TRACE fc_trace_debug 811 812 static struct cb_ops fcp_cb_ops = { 813 fcp_open, /* open */ 814 fcp_close, /* close */ 815 nodev, /* strategy */ 816 nodev, /* print */ 817 nodev, /* dump */ 818 nodev, /* read */ 819 nodev, /* write */ 820 fcp_ioctl, /* ioctl */ 821 nodev, /* devmap */ 822 nodev, /* mmap */ 823 nodev, /* segmap */ 824 nochpoll, /* chpoll */ 825 ddi_prop_op, /* cb_prop_op */ 826 0, /* streamtab */ 827 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 828 CB_REV, /* rev */ 829 nodev, /* aread */ 830 nodev /* awrite */ 831 }; 832 833 834 static struct dev_ops fcp_ops = { 835 DEVO_REV, 836 0, 837 ddi_getinfo_1to1, 838 nulldev, /* identify */ 839 nulldev, /* probe */ 840 fcp_attach, /* attach and detach are mandatory */ 841 fcp_detach, 842 nodev, /* reset */ 843 &fcp_cb_ops, /* cb_ops */ 844 NULL, /* bus_ops */ 845 NULL, /* power */ 846 }; 847 848 849 char *fcp_version = FCP_NAME_VERSION; 850 851 static struct modldrv modldrv = { 852 &mod_driverops, 853 FCP_NAME_VERSION, 854 &fcp_ops 855 }; 856 857 858 static struct modlinkage modlinkage = { 859 MODREV_1, 860 &modldrv, 861 NULL 862 }; 863 864 865 static fc_ulp_modinfo_t fcp_modinfo = { 866 &fcp_modinfo, /* ulp_handle */ 867 FCTL_ULP_MODREV_4, /* ulp_rev */ 868 FC4_SCSI_FCP, /* ulp_type */ 869 "fcp", /* ulp_name */ 870 FCP_STATEC_MASK, /* ulp_statec_mask */ 871 fcp_port_attach, /* ulp_port_attach */ 872 fcp_port_detach, /* ulp_port_detach */ 873 fcp_port_ioctl, /* ulp_port_ioctl */ 874 fcp_els_callback, /* ulp_els_callback */ 875 fcp_data_callback, /* ulp_data_callback */ 876 fcp_statec_callback /* ulp_statec_callback */ 877 }; 878 879 #ifdef DEBUG 880 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 881 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 882 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 883 FCP_LEVEL_6 | FCP_LEVEL_7) 884 #else 885 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 886 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 887 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 888 FCP_LEVEL_6 | FCP_LEVEL_7) 889 #endif 890 891 /* FCP global variables */ 892 int fcp_bus_config_debug = 0; 893 static int fcp_log_size = FCP_LOG_SIZE; 894 static int fcp_trace = FCP_TRACE_DEFAULT; 895 static fc_trace_logq_t *fcp_logq = NULL; 896 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 897 /* 898 * The auto-configuration is set by default. The only way of disabling it is 899 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 900 */ 901 static int fcp_enable_auto_configuration = 1; 902 static int fcp_max_bus_config_retries = 4; 903 static int fcp_lun_ready_retry = 300; 904 /* 905 * The value assigned to the following variable has changed several times due 906 * to a problem with the data underruns reporting of some firmware(s). The 907 * current value of 50 gives a timeout value of 25 seconds for a max number 908 * of 256 LUNs. 909 */ 910 static int fcp_max_target_retries = 50; 911 /* 912 * Watchdog variables 913 * ------------------ 914 * 915 * fcp_watchdog_init 916 * 917 * Indicates if the watchdog timer is running or not. This is actually 918 * a counter of the number of Fibre Channel ports that attached. When 919 * the first port attaches the watchdog is started. When the last port 920 * detaches the watchdog timer is stopped. 921 * 922 * fcp_watchdog_time 923 * 924 * This is the watchdog clock counter. It is incremented by 925 * fcp_watchdog_time each time the watchdog timer expires. 926 * 927 * fcp_watchdog_timeout 928 * 929 * Increment value of the variable fcp_watchdog_time as well as the 930 * the timeout value of the watchdog timer. The unit is 1 second. It 931 * is strange that this is not a #define but a variable since the code 932 * never changes this value. The reason why it can be said that the 933 * unit is 1 second is because the number of ticks for the watchdog 934 * timer is determined like this: 935 * 936 * fcp_watchdog_tick = fcp_watchdog_timeout * 937 * drv_usectohz(1000000); 938 * 939 * The value 1000000 is hard coded in the code. 940 * 941 * fcp_watchdog_tick 942 * 943 * Watchdog timer value in ticks. 944 */ 945 static int fcp_watchdog_init = 0; 946 static int fcp_watchdog_time = 0; 947 static int fcp_watchdog_timeout = 1; 948 static int fcp_watchdog_tick; 949 950 /* 951 * fcp_offline_delay is a global variable to enable customisation of 952 * the timeout on link offlines or RSCNs. The default value is set 953 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 954 * specified in FCP4 Chapter 11 (see www.t10.org). 955 * 956 * The variable fcp_offline_delay is specified in SECONDS. 957 * 958 * If we made this a static var then the user would not be able to 959 * change it. This variable is set in fcp_attach(). 960 */ 961 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 962 963 static void *fcp_softstate = NULL; /* for soft state */ 964 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 965 static kmutex_t fcp_global_mutex; 966 static kmutex_t fcp_ioctl_mutex; 967 static dev_info_t *fcp_global_dip = NULL; 968 static timeout_id_t fcp_watchdog_id; 969 const char *fcp_lun_prop = "lun"; 970 const char *fcp_sam_lun_prop = "sam-lun"; 971 const char *fcp_target_prop = "target"; 972 /* 973 * NOTE: consumers of "node-wwn" property include stmsboot in ON 974 * consolidation. 975 */ 976 const char *fcp_node_wwn_prop = "node-wwn"; 977 const char *fcp_port_wwn_prop = "port-wwn"; 978 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 979 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 980 const char *fcp_manual_config_only = "manual_configuration_only"; 981 const char *fcp_init_port_prop = "initiator-port"; 982 const char *fcp_tgt_port_prop = "target-port"; 983 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 984 985 static struct fcp_port *fcp_port_head = NULL; 986 static ddi_eventcookie_t fcp_insert_eid; 987 static ddi_eventcookie_t fcp_remove_eid; 988 989 static ndi_event_definition_t fcp_ndi_event_defs[] = { 990 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 991 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 992 }; 993 994 /* 995 * List of valid commands for the scsi_ioctl call 996 */ 997 static uint8_t scsi_ioctl_list[] = { 998 SCMD_INQUIRY, 999 SCMD_REPORT_LUN, 1000 SCMD_READ_CAPACITY 1001 }; 1002 1003 /* 1004 * this is used to dummy up a report lun response for cases 1005 * where the target doesn't support it 1006 */ 1007 static uchar_t fcp_dummy_lun[] = { 1008 0x00, /* MSB length (length = no of luns * 8) */ 1009 0x00, 1010 0x00, 1011 0x08, /* LSB length */ 1012 0x00, /* MSB reserved */ 1013 0x00, 1014 0x00, 1015 0x00, /* LSB reserved */ 1016 FCP_PD_ADDRESSING, 1017 0x00, /* LUN is ZERO at the first level */ 1018 0x00, 1019 0x00, /* second level is zero */ 1020 0x00, 1021 0x00, /* third level is zero */ 1022 0x00, 1023 0x00 /* fourth level is zero */ 1024 }; 1025 1026 static uchar_t fcp_alpa_to_switch[] = { 1027 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1029 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1030 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1031 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1032 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1033 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1034 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1035 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1036 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1037 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1038 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1039 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1040 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1041 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1042 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1043 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1044 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1045 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1047 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1048 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1049 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1050 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1051 }; 1052 1053 static caddr_t pid = "SESS01 "; 1054 1055 #if !defined(lint) 1056 1057 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1058 fcp_port::fcp_next fcp_watchdog_id)) 1059 1060 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1061 1062 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1063 fcp_insert_eid 1064 fcp_remove_eid 1065 fcp_watchdog_time)) 1066 1067 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1068 fcp_cb_ops 1069 fcp_ops 1070 callb_cpr)) 1071 1072 #endif /* lint */ 1073 1074 /* 1075 * This table is used to determine whether or not it's safe to copy in 1076 * the target node name for a lun. Since all luns behind the same target 1077 * have the same wwnn, only tagets that do not support multiple luns are 1078 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1079 */ 1080 1081 char *fcp_symmetric_disk_table[] = { 1082 "SEAGATE ST", 1083 "IBM DDYFT", 1084 "SUNW SUNWGS", /* Daktari enclosure */ 1085 "SUN SENA", /* SES device */ 1086 "SUN SESS01" /* VICOM SVE box */ 1087 }; 1088 1089 int fcp_symmetric_disk_table_size = 1090 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1091 1092 /* 1093 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1094 * will panic if you don't pass this in to the routine, this information. 1095 * Need to determine what the actual impact to the system is by providing 1096 * this information if any. Since dma allocation is done in pkt_init it may 1097 * not have any impact. These values are straight from the Writing Device 1098 * Driver manual. 1099 */ 1100 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1101 DMA_ATTR_V0, /* ddi_dma_attr version */ 1102 0, /* low address */ 1103 0xffffffff, /* high address */ 1104 0x00ffffff, /* counter upper bound */ 1105 1, /* alignment requirements */ 1106 0x3f, /* burst sizes */ 1107 1, /* minimum DMA access */ 1108 0xffffffff, /* maximum DMA access */ 1109 (1 << 24) - 1, /* segment boundary restrictions */ 1110 1, /* scater/gather list length */ 1111 512, /* device granularity */ 1112 0 /* DMA flags */ 1113 }; 1114 1115 /* 1116 * The _init(9e) return value should be that of mod_install(9f). Under 1117 * some circumstances, a failure may not be related mod_install(9f) and 1118 * one would then require a return value to indicate the failure. Looking 1119 * at mod_install(9f), it is expected to return 0 for success and non-zero 1120 * for failure. mod_install(9f) for device drivers, further goes down the 1121 * calling chain and ends up in ddi_installdrv(), whose return values are 1122 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1123 * calling chain of mod_install(9f) which return values like EINVAL and 1124 * in some even return -1. 1125 * 1126 * To work around the vagaries of the mod_install() calling chain, return 1127 * either 0 or ENODEV depending on the success or failure of mod_install() 1128 */ 1129 int 1130 _init(void) 1131 { 1132 int rval; 1133 1134 /* 1135 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1136 * before registering with the transport first. 1137 */ 1138 if (ddi_soft_state_init(&fcp_softstate, 1139 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1140 return (EINVAL); 1141 } 1142 1143 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1144 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1145 1146 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1147 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1148 mutex_destroy(&fcp_global_mutex); 1149 mutex_destroy(&fcp_ioctl_mutex); 1150 ddi_soft_state_fini(&fcp_softstate); 1151 return (ENODEV); 1152 } 1153 1154 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1155 1156 if ((rval = mod_install(&modlinkage)) != 0) { 1157 fc_trace_free_logq(fcp_logq); 1158 (void) fc_ulp_remove(&fcp_modinfo); 1159 mutex_destroy(&fcp_global_mutex); 1160 mutex_destroy(&fcp_ioctl_mutex); 1161 ddi_soft_state_fini(&fcp_softstate); 1162 rval = ENODEV; 1163 } 1164 1165 return (rval); 1166 } 1167 1168 1169 /* 1170 * the system is done with us as a driver, so clean up 1171 */ 1172 int 1173 _fini(void) 1174 { 1175 int rval; 1176 1177 /* 1178 * don't start cleaning up until we know that the module remove 1179 * has worked -- if this works, then we know that each instance 1180 * has successfully been DDI_DETACHed 1181 */ 1182 if ((rval = mod_remove(&modlinkage)) != 0) { 1183 return (rval); 1184 } 1185 1186 (void) fc_ulp_remove(&fcp_modinfo); 1187 1188 ddi_soft_state_fini(&fcp_softstate); 1189 mutex_destroy(&fcp_global_mutex); 1190 mutex_destroy(&fcp_ioctl_mutex); 1191 fc_trace_free_logq(fcp_logq); 1192 1193 return (rval); 1194 } 1195 1196 1197 int 1198 _info(struct modinfo *modinfop) 1199 { 1200 return (mod_info(&modlinkage, modinfop)); 1201 } 1202 1203 1204 /* 1205 * attach the module 1206 */ 1207 static int 1208 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1209 { 1210 int rval = DDI_SUCCESS; 1211 1212 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1213 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1214 1215 if (cmd == DDI_ATTACH) { 1216 /* The FCP pseudo device is created here. */ 1217 mutex_enter(&fcp_global_mutex); 1218 fcp_global_dip = devi; 1219 mutex_exit(&fcp_global_mutex); 1220 1221 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1222 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1223 ddi_report_dev(fcp_global_dip); 1224 } else { 1225 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1226 mutex_enter(&fcp_global_mutex); 1227 fcp_global_dip = NULL; 1228 mutex_exit(&fcp_global_mutex); 1229 1230 rval = DDI_FAILURE; 1231 } 1232 /* 1233 * We check the fcp_offline_delay property at this 1234 * point. This variable is global for the driver, 1235 * not specific to an instance. 1236 * 1237 * We do not recommend setting the value to less 1238 * than 10 seconds (RA_TOV_els), or greater than 1239 * 60 seconds. 1240 */ 1241 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1242 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1243 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1244 if ((fcp_offline_delay < 10) || 1245 (fcp_offline_delay > 60)) { 1246 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1247 "to %d second(s). This is outside the " 1248 "recommended range of 10..60 seconds.", 1249 fcp_offline_delay); 1250 } 1251 } 1252 1253 return (rval); 1254 } 1255 1256 1257 /*ARGSUSED*/ 1258 static int 1259 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1260 { 1261 int res = DDI_SUCCESS; 1262 1263 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1264 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1265 1266 if (cmd == DDI_DETACH) { 1267 /* 1268 * Check if there are active ports/threads. If there 1269 * are any, we will fail, else we will succeed (there 1270 * should not be much to clean up) 1271 */ 1272 mutex_enter(&fcp_global_mutex); 1273 FCP_DTRACE(fcp_logq, "fcp", 1274 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1275 (void *) fcp_port_head); 1276 1277 if (fcp_port_head == NULL) { 1278 ddi_remove_minor_node(fcp_global_dip, NULL); 1279 fcp_global_dip = NULL; 1280 mutex_exit(&fcp_global_mutex); 1281 } else { 1282 mutex_exit(&fcp_global_mutex); 1283 res = DDI_FAILURE; 1284 } 1285 } 1286 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1287 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1288 1289 return (res); 1290 } 1291 1292 1293 /* ARGSUSED */ 1294 static int 1295 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1296 { 1297 if (otype != OTYP_CHR) { 1298 return (EINVAL); 1299 } 1300 1301 /* 1302 * Allow only root to talk; 1303 */ 1304 if (drv_priv(credp)) { 1305 return (EPERM); 1306 } 1307 1308 mutex_enter(&fcp_global_mutex); 1309 if (fcp_oflag & FCP_EXCL) { 1310 mutex_exit(&fcp_global_mutex); 1311 return (EBUSY); 1312 } 1313 1314 if (flag & FEXCL) { 1315 if (fcp_oflag & FCP_OPEN) { 1316 mutex_exit(&fcp_global_mutex); 1317 return (EBUSY); 1318 } 1319 fcp_oflag |= FCP_EXCL; 1320 } 1321 fcp_oflag |= FCP_OPEN; 1322 mutex_exit(&fcp_global_mutex); 1323 1324 return (0); 1325 } 1326 1327 1328 /* ARGSUSED */ 1329 static int 1330 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1331 { 1332 if (otype != OTYP_CHR) { 1333 return (EINVAL); 1334 } 1335 1336 mutex_enter(&fcp_global_mutex); 1337 if (!(fcp_oflag & FCP_OPEN)) { 1338 mutex_exit(&fcp_global_mutex); 1339 return (ENODEV); 1340 } 1341 fcp_oflag = FCP_IDLE; 1342 mutex_exit(&fcp_global_mutex); 1343 1344 return (0); 1345 } 1346 1347 1348 /* 1349 * fcp_ioctl 1350 * Entry point for the FCP ioctls 1351 * 1352 * Input: 1353 * See ioctl(9E) 1354 * 1355 * Output: 1356 * See ioctl(9E) 1357 * 1358 * Returns: 1359 * See ioctl(9E) 1360 * 1361 * Context: 1362 * Kernel context. 1363 */ 1364 /* ARGSUSED */ 1365 static int 1366 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1367 int *rval) 1368 { 1369 int ret = 0; 1370 1371 mutex_enter(&fcp_global_mutex); 1372 if (!(fcp_oflag & FCP_OPEN)) { 1373 mutex_exit(&fcp_global_mutex); 1374 return (ENXIO); 1375 } 1376 mutex_exit(&fcp_global_mutex); 1377 1378 switch (cmd) { 1379 case FCP_TGT_INQUIRY: 1380 case FCP_TGT_CREATE: 1381 case FCP_TGT_DELETE: 1382 ret = fcp_setup_device_data_ioctl(cmd, 1383 (struct fcp_ioctl *)data, mode, rval); 1384 break; 1385 1386 case FCP_TGT_SEND_SCSI: 1387 mutex_enter(&fcp_ioctl_mutex); 1388 ret = fcp_setup_scsi_ioctl( 1389 (struct fcp_scsi_cmd *)data, mode, rval); 1390 mutex_exit(&fcp_ioctl_mutex); 1391 break; 1392 1393 case FCP_STATE_COUNT: 1394 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1395 mode, rval); 1396 break; 1397 case FCP_GET_TARGET_MAPPINGS: 1398 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1399 mode, rval); 1400 break; 1401 default: 1402 fcp_log(CE_WARN, NULL, 1403 "!Invalid ioctl opcode = 0x%x", cmd); 1404 ret = EINVAL; 1405 } 1406 1407 return (ret); 1408 } 1409 1410 1411 /* 1412 * fcp_setup_device_data_ioctl 1413 * Setup handler for the "device data" style of 1414 * ioctl for FCP. See "fcp_util.h" for data structure 1415 * definition. 1416 * 1417 * Input: 1418 * cmd = FCP ioctl command 1419 * data = ioctl data 1420 * mode = See ioctl(9E) 1421 * 1422 * Output: 1423 * data = ioctl data 1424 * rval = return value - see ioctl(9E) 1425 * 1426 * Returns: 1427 * See ioctl(9E) 1428 * 1429 * Context: 1430 * Kernel context. 1431 */ 1432 /* ARGSUSED */ 1433 static int 1434 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1435 int *rval) 1436 { 1437 struct fcp_port *pptr; 1438 struct device_data *dev_data; 1439 uint32_t link_cnt; 1440 la_wwn_t *wwn_ptr = NULL; 1441 struct fcp_tgt *ptgt = NULL; 1442 struct fcp_lun *plun = NULL; 1443 int i, error; 1444 struct fcp_ioctl fioctl; 1445 1446 #ifdef _MULTI_DATAMODEL 1447 switch (ddi_model_convert_from(mode & FMODELS)) { 1448 case DDI_MODEL_ILP32: { 1449 struct fcp32_ioctl f32_ioctl; 1450 1451 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1452 sizeof (struct fcp32_ioctl), mode)) { 1453 return (EFAULT); 1454 } 1455 fioctl.fp_minor = f32_ioctl.fp_minor; 1456 fioctl.listlen = f32_ioctl.listlen; 1457 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1458 break; 1459 } 1460 case DDI_MODEL_NONE: 1461 if (ddi_copyin((void *)data, (void *)&fioctl, 1462 sizeof (struct fcp_ioctl), mode)) { 1463 return (EFAULT); 1464 } 1465 break; 1466 } 1467 1468 #else /* _MULTI_DATAMODEL */ 1469 if (ddi_copyin((void *)data, (void *)&fioctl, 1470 sizeof (struct fcp_ioctl), mode)) { 1471 return (EFAULT); 1472 } 1473 #endif /* _MULTI_DATAMODEL */ 1474 1475 /* 1476 * Right now we can assume that the minor number matches with 1477 * this instance of fp. If this changes we will need to 1478 * revisit this logic. 1479 */ 1480 mutex_enter(&fcp_global_mutex); 1481 pptr = fcp_port_head; 1482 while (pptr) { 1483 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1484 break; 1485 } else { 1486 pptr = pptr->port_next; 1487 } 1488 } 1489 mutex_exit(&fcp_global_mutex); 1490 if (pptr == NULL) { 1491 return (ENXIO); 1492 } 1493 mutex_enter(&pptr->port_mutex); 1494 1495 1496 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1497 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1498 mutex_exit(&pptr->port_mutex); 1499 return (ENOMEM); 1500 } 1501 1502 if (ddi_copyin(fioctl.list, dev_data, 1503 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1504 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1505 mutex_exit(&pptr->port_mutex); 1506 return (EFAULT); 1507 } 1508 link_cnt = pptr->port_link_cnt; 1509 1510 if (cmd == FCP_TGT_INQUIRY) { 1511 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1512 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1513 sizeof (wwn_ptr->raw_wwn)) == 0) { 1514 /* This ioctl is requesting INQ info of local HBA */ 1515 mutex_exit(&pptr->port_mutex); 1516 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1517 dev_data[0].dev_status = 0; 1518 if (ddi_copyout(dev_data, fioctl.list, 1519 (sizeof (struct device_data)) * fioctl.listlen, 1520 mode)) { 1521 kmem_free(dev_data, 1522 sizeof (*dev_data) * fioctl.listlen); 1523 return (EFAULT); 1524 } 1525 kmem_free(dev_data, 1526 sizeof (*dev_data) * fioctl.listlen); 1527 #ifdef _MULTI_DATAMODEL 1528 switch (ddi_model_convert_from(mode & FMODELS)) { 1529 case DDI_MODEL_ILP32: { 1530 struct fcp32_ioctl f32_ioctl; 1531 f32_ioctl.fp_minor = fioctl.fp_minor; 1532 f32_ioctl.listlen = fioctl.listlen; 1533 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1534 if (ddi_copyout((void *)&f32_ioctl, 1535 (void *)data, 1536 sizeof (struct fcp32_ioctl), mode)) { 1537 return (EFAULT); 1538 } 1539 break; 1540 } 1541 case DDI_MODEL_NONE: 1542 if (ddi_copyout((void *)&fioctl, (void *)data, 1543 sizeof (struct fcp_ioctl), mode)) { 1544 return (EFAULT); 1545 } 1546 break; 1547 } 1548 #else /* _MULTI_DATAMODEL */ 1549 if (ddi_copyout((void *)&fioctl, (void *)data, 1550 sizeof (struct fcp_ioctl), mode)) { 1551 return (EFAULT); 1552 } 1553 #endif /* _MULTI_DATAMODEL */ 1554 return (0); 1555 } 1556 } 1557 1558 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1559 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1560 mutex_exit(&pptr->port_mutex); 1561 return (ENXIO); 1562 } 1563 1564 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1565 i++) { 1566 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1567 1568 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1569 1570 1571 dev_data[i].dev_status = ENXIO; 1572 1573 if ((ptgt = fcp_lookup_target(pptr, 1574 (uchar_t *)wwn_ptr)) == NULL) { 1575 mutex_exit(&pptr->port_mutex); 1576 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1577 wwn_ptr, &error, 0) == NULL) { 1578 dev_data[i].dev_status = ENODEV; 1579 mutex_enter(&pptr->port_mutex); 1580 continue; 1581 } else { 1582 1583 dev_data[i].dev_status = EAGAIN; 1584 1585 mutex_enter(&pptr->port_mutex); 1586 continue; 1587 } 1588 } else { 1589 mutex_enter(&ptgt->tgt_mutex); 1590 if (ptgt->tgt_state & (FCP_TGT_MARK | 1591 FCP_TGT_BUSY)) { 1592 dev_data[i].dev_status = EAGAIN; 1593 mutex_exit(&ptgt->tgt_mutex); 1594 continue; 1595 } 1596 1597 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1598 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1599 dev_data[i].dev_status = ENOTSUP; 1600 } else { 1601 dev_data[i].dev_status = ENXIO; 1602 } 1603 mutex_exit(&ptgt->tgt_mutex); 1604 continue; 1605 } 1606 1607 switch (cmd) { 1608 case FCP_TGT_INQUIRY: 1609 /* 1610 * The reason we give device type of 1611 * lun 0 only even though in some 1612 * cases(like maxstrat) lun 0 device 1613 * type may be 0x3f(invalid) is that 1614 * for bridge boxes target will appear 1615 * as luns and the first lun could be 1616 * a device that utility may not care 1617 * about (like a tape device). 1618 */ 1619 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1620 dev_data[i].dev_status = 0; 1621 mutex_exit(&ptgt->tgt_mutex); 1622 1623 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1624 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1625 } else { 1626 dev_data[i].dev0_type = plun->lun_type; 1627 } 1628 mutex_enter(&ptgt->tgt_mutex); 1629 break; 1630 1631 case FCP_TGT_CREATE: 1632 mutex_exit(&ptgt->tgt_mutex); 1633 mutex_exit(&pptr->port_mutex); 1634 1635 /* 1636 * serialize state change call backs. 1637 * only one call back will be handled 1638 * at a time. 1639 */ 1640 mutex_enter(&fcp_global_mutex); 1641 if (fcp_oflag & FCP_BUSY) { 1642 mutex_exit(&fcp_global_mutex); 1643 if (dev_data) { 1644 kmem_free(dev_data, 1645 sizeof (*dev_data) * 1646 fioctl.listlen); 1647 } 1648 return (EBUSY); 1649 } 1650 fcp_oflag |= FCP_BUSY; 1651 mutex_exit(&fcp_global_mutex); 1652 1653 dev_data[i].dev_status = 1654 fcp_create_on_demand(pptr, 1655 wwn_ptr->raw_wwn); 1656 1657 if (dev_data[i].dev_status != 0) { 1658 char buf[25]; 1659 1660 for (i = 0; i < FC_WWN_SIZE; i++) { 1661 (void) sprintf(&buf[i << 1], 1662 "%02x", 1663 wwn_ptr->raw_wwn[i]); 1664 } 1665 1666 fcp_log(CE_WARN, pptr->port_dip, 1667 "!Failed to create nodes for" 1668 " pwwn=%s; error=%x", buf, 1669 dev_data[i].dev_status); 1670 } 1671 1672 /* allow state change call backs again */ 1673 mutex_enter(&fcp_global_mutex); 1674 fcp_oflag &= ~FCP_BUSY; 1675 mutex_exit(&fcp_global_mutex); 1676 1677 mutex_enter(&pptr->port_mutex); 1678 mutex_enter(&ptgt->tgt_mutex); 1679 1680 break; 1681 1682 case FCP_TGT_DELETE: 1683 break; 1684 1685 default: 1686 fcp_log(CE_WARN, pptr->port_dip, 1687 "!Invalid device data ioctl " 1688 "opcode = 0x%x", cmd); 1689 } 1690 mutex_exit(&ptgt->tgt_mutex); 1691 } 1692 } 1693 mutex_exit(&pptr->port_mutex); 1694 1695 if (ddi_copyout(dev_data, fioctl.list, 1696 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1697 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1698 return (EFAULT); 1699 } 1700 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1701 1702 #ifdef _MULTI_DATAMODEL 1703 switch (ddi_model_convert_from(mode & FMODELS)) { 1704 case DDI_MODEL_ILP32: { 1705 struct fcp32_ioctl f32_ioctl; 1706 1707 f32_ioctl.fp_minor = fioctl.fp_minor; 1708 f32_ioctl.listlen = fioctl.listlen; 1709 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1710 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1711 sizeof (struct fcp32_ioctl), mode)) { 1712 return (EFAULT); 1713 } 1714 break; 1715 } 1716 case DDI_MODEL_NONE: 1717 if (ddi_copyout((void *)&fioctl, (void *)data, 1718 sizeof (struct fcp_ioctl), mode)) { 1719 return (EFAULT); 1720 } 1721 break; 1722 } 1723 #else /* _MULTI_DATAMODEL */ 1724 1725 if (ddi_copyout((void *)&fioctl, (void *)data, 1726 sizeof (struct fcp_ioctl), mode)) { 1727 return (EFAULT); 1728 } 1729 #endif /* _MULTI_DATAMODEL */ 1730 1731 return (0); 1732 } 1733 1734 /* 1735 * Fetch the target mappings (path, etc.) for all LUNs 1736 * on this port. 1737 */ 1738 /* ARGSUSED */ 1739 static int 1740 fcp_get_target_mappings(struct fcp_ioctl *data, 1741 int mode, int *rval) 1742 { 1743 struct fcp_port *pptr; 1744 fc_hba_target_mappings_t *mappings; 1745 fc_hba_mapping_entry_t *map; 1746 struct fcp_tgt *ptgt = NULL; 1747 struct fcp_lun *plun = NULL; 1748 int i, mapIndex, mappingSize; 1749 int listlen; 1750 struct fcp_ioctl fioctl; 1751 char *path; 1752 fcp_ent_addr_t sam_lun_addr; 1753 1754 #ifdef _MULTI_DATAMODEL 1755 switch (ddi_model_convert_from(mode & FMODELS)) { 1756 case DDI_MODEL_ILP32: { 1757 struct fcp32_ioctl f32_ioctl; 1758 1759 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1760 sizeof (struct fcp32_ioctl), mode)) { 1761 return (EFAULT); 1762 } 1763 fioctl.fp_minor = f32_ioctl.fp_minor; 1764 fioctl.listlen = f32_ioctl.listlen; 1765 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1766 break; 1767 } 1768 case DDI_MODEL_NONE: 1769 if (ddi_copyin((void *)data, (void *)&fioctl, 1770 sizeof (struct fcp_ioctl), mode)) { 1771 return (EFAULT); 1772 } 1773 break; 1774 } 1775 1776 #else /* _MULTI_DATAMODEL */ 1777 if (ddi_copyin((void *)data, (void *)&fioctl, 1778 sizeof (struct fcp_ioctl), mode)) { 1779 return (EFAULT); 1780 } 1781 #endif /* _MULTI_DATAMODEL */ 1782 1783 /* 1784 * Right now we can assume that the minor number matches with 1785 * this instance of fp. If this changes we will need to 1786 * revisit this logic. 1787 */ 1788 mutex_enter(&fcp_global_mutex); 1789 pptr = fcp_port_head; 1790 while (pptr) { 1791 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1792 break; 1793 } else { 1794 pptr = pptr->port_next; 1795 } 1796 } 1797 mutex_exit(&fcp_global_mutex); 1798 if (pptr == NULL) { 1799 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1800 fioctl.fp_minor); 1801 return (ENXIO); 1802 } 1803 1804 1805 /* We use listlen to show the total buffer size */ 1806 mappingSize = fioctl.listlen; 1807 1808 /* Now calculate how many mapping entries will fit */ 1809 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1810 - sizeof (fc_hba_target_mappings_t); 1811 if (listlen <= 0) { 1812 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1813 return (ENXIO); 1814 } 1815 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1816 1817 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1818 return (ENOMEM); 1819 } 1820 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1821 1822 /* Now get to work */ 1823 mapIndex = 0; 1824 1825 mutex_enter(&pptr->port_mutex); 1826 /* Loop through all targets on this port */ 1827 for (i = 0; i < FCP_NUM_HASH; i++) { 1828 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1829 ptgt = ptgt->tgt_next) { 1830 1831 mutex_enter(&ptgt->tgt_mutex); 1832 1833 /* Loop through all LUNs on this target */ 1834 for (plun = ptgt->tgt_lun; plun != NULL; 1835 plun = plun->lun_next) { 1836 if (plun->lun_state & FCP_LUN_OFFLINE) { 1837 continue; 1838 } 1839 1840 path = fcp_get_lun_path(plun); 1841 if (path == NULL) { 1842 continue; 1843 } 1844 1845 if (mapIndex >= listlen) { 1846 mapIndex ++; 1847 kmem_free(path, MAXPATHLEN); 1848 continue; 1849 } 1850 map = &mappings->entries[mapIndex++]; 1851 bcopy(path, map->targetDriver, 1852 sizeof (map->targetDriver)); 1853 map->d_id = ptgt->tgt_d_id; 1854 map->busNumber = 0; 1855 map->targetNumber = ptgt->tgt_d_id; 1856 map->osLUN = plun->lun_num; 1857 1858 /* 1859 * We had swapped lun when we stored it in 1860 * lun_addr. We need to swap it back before 1861 * returning it to user land 1862 */ 1863 1864 sam_lun_addr.ent_addr_0 = 1865 BE_16(plun->lun_addr.ent_addr_0); 1866 sam_lun_addr.ent_addr_1 = 1867 BE_16(plun->lun_addr.ent_addr_1); 1868 sam_lun_addr.ent_addr_2 = 1869 BE_16(plun->lun_addr.ent_addr_2); 1870 sam_lun_addr.ent_addr_3 = 1871 BE_16(plun->lun_addr.ent_addr_3); 1872 1873 bcopy(&sam_lun_addr, &map->samLUN, 1874 FCP_LUN_SIZE); 1875 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1876 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1877 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1878 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1879 1880 if (plun->lun_guid) { 1881 1882 /* convert ascii wwn to bytes */ 1883 fcp_ascii_to_wwn(plun->lun_guid, 1884 map->guid, sizeof (map->guid)); 1885 1886 if ((sizeof (map->guid)) < 1887 plun->lun_guid_size / 2) { 1888 cmn_err(CE_WARN, 1889 "fcp_get_target_mappings:" 1890 "guid copy space " 1891 "insufficient." 1892 "Copy Truncation - " 1893 "available %d; need %d", 1894 (int)sizeof (map->guid), 1895 (int) 1896 plun->lun_guid_size / 2); 1897 } 1898 } 1899 kmem_free(path, MAXPATHLEN); 1900 } 1901 mutex_exit(&ptgt->tgt_mutex); 1902 } 1903 } 1904 mutex_exit(&pptr->port_mutex); 1905 mappings->numLuns = mapIndex; 1906 1907 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1908 kmem_free(mappings, mappingSize); 1909 return (EFAULT); 1910 } 1911 kmem_free(mappings, mappingSize); 1912 1913 #ifdef _MULTI_DATAMODEL 1914 switch (ddi_model_convert_from(mode & FMODELS)) { 1915 case DDI_MODEL_ILP32: { 1916 struct fcp32_ioctl f32_ioctl; 1917 1918 f32_ioctl.fp_minor = fioctl.fp_minor; 1919 f32_ioctl.listlen = fioctl.listlen; 1920 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1921 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1922 sizeof (struct fcp32_ioctl), mode)) { 1923 return (EFAULT); 1924 } 1925 break; 1926 } 1927 case DDI_MODEL_NONE: 1928 if (ddi_copyout((void *)&fioctl, (void *)data, 1929 sizeof (struct fcp_ioctl), mode)) { 1930 return (EFAULT); 1931 } 1932 break; 1933 } 1934 #else /* _MULTI_DATAMODEL */ 1935 1936 if (ddi_copyout((void *)&fioctl, (void *)data, 1937 sizeof (struct fcp_ioctl), mode)) { 1938 return (EFAULT); 1939 } 1940 #endif /* _MULTI_DATAMODEL */ 1941 1942 return (0); 1943 } 1944 1945 /* 1946 * fcp_setup_scsi_ioctl 1947 * Setup handler for the "scsi passthru" style of 1948 * ioctl for FCP. See "fcp_util.h" for data structure 1949 * definition. 1950 * 1951 * Input: 1952 * u_fscsi = ioctl data (user address space) 1953 * mode = See ioctl(9E) 1954 * 1955 * Output: 1956 * u_fscsi = ioctl data (user address space) 1957 * rval = return value - see ioctl(9E) 1958 * 1959 * Returns: 1960 * 0 = OK 1961 * EAGAIN = See errno.h 1962 * EBUSY = See errno.h 1963 * EFAULT = See errno.h 1964 * EINTR = See errno.h 1965 * EINVAL = See errno.h 1966 * EIO = See errno.h 1967 * ENOMEM = See errno.h 1968 * ENXIO = See errno.h 1969 * 1970 * Context: 1971 * Kernel context. 1972 */ 1973 /* ARGSUSED */ 1974 static int 1975 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1976 int mode, int *rval) 1977 { 1978 int ret = 0; 1979 int temp_ret; 1980 caddr_t k_cdbbufaddr = NULL; 1981 caddr_t k_bufaddr = NULL; 1982 caddr_t k_rqbufaddr = NULL; 1983 caddr_t u_cdbbufaddr; 1984 caddr_t u_bufaddr; 1985 caddr_t u_rqbufaddr; 1986 struct fcp_scsi_cmd k_fscsi; 1987 1988 /* 1989 * Get fcp_scsi_cmd array element from user address space 1990 */ 1991 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1992 != 0) { 1993 return (ret); 1994 } 1995 1996 1997 /* 1998 * Even though kmem_alloc() checks the validity of the 1999 * buffer length, this check is needed when the 2000 * kmem_flags set and the zero buffer length is passed. 2001 */ 2002 if ((k_fscsi.scsi_cdblen <= 0) || 2003 (k_fscsi.scsi_buflen <= 0) || 2004 (k_fscsi.scsi_rqlen <= 0)) { 2005 return (EINVAL); 2006 } 2007 2008 /* 2009 * Allocate data for fcp_scsi_cmd pointer fields 2010 */ 2011 if (ret == 0) { 2012 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 2013 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 2014 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 2015 2016 if (k_cdbbufaddr == NULL || 2017 k_bufaddr == NULL || 2018 k_rqbufaddr == NULL) { 2019 ret = ENOMEM; 2020 } 2021 } 2022 2023 /* 2024 * Get fcp_scsi_cmd pointer fields from user 2025 * address space 2026 */ 2027 if (ret == 0) { 2028 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2029 u_bufaddr = k_fscsi.scsi_bufaddr; 2030 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2031 2032 if (ddi_copyin(u_cdbbufaddr, 2033 k_cdbbufaddr, 2034 k_fscsi.scsi_cdblen, 2035 mode)) { 2036 ret = EFAULT; 2037 } else if (ddi_copyin(u_bufaddr, 2038 k_bufaddr, 2039 k_fscsi.scsi_buflen, 2040 mode)) { 2041 ret = EFAULT; 2042 } else if (ddi_copyin(u_rqbufaddr, 2043 k_rqbufaddr, 2044 k_fscsi.scsi_rqlen, 2045 mode)) { 2046 ret = EFAULT; 2047 } 2048 } 2049 2050 /* 2051 * Send scsi command (blocking) 2052 */ 2053 if (ret == 0) { 2054 /* 2055 * Prior to sending the scsi command, the 2056 * fcp_scsi_cmd data structure must contain kernel, 2057 * not user, addresses. 2058 */ 2059 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2060 k_fscsi.scsi_bufaddr = k_bufaddr; 2061 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2062 2063 ret = fcp_send_scsi_ioctl(&k_fscsi); 2064 2065 /* 2066 * After sending the scsi command, the 2067 * fcp_scsi_cmd data structure must contain user, 2068 * not kernel, addresses. 2069 */ 2070 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2071 k_fscsi.scsi_bufaddr = u_bufaddr; 2072 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2073 } 2074 2075 /* 2076 * Put fcp_scsi_cmd pointer fields to user address space 2077 */ 2078 if (ret == 0) { 2079 if (ddi_copyout(k_cdbbufaddr, 2080 u_cdbbufaddr, 2081 k_fscsi.scsi_cdblen, 2082 mode)) { 2083 ret = EFAULT; 2084 } else if (ddi_copyout(k_bufaddr, 2085 u_bufaddr, 2086 k_fscsi.scsi_buflen, 2087 mode)) { 2088 ret = EFAULT; 2089 } else if (ddi_copyout(k_rqbufaddr, 2090 u_rqbufaddr, 2091 k_fscsi.scsi_rqlen, 2092 mode)) { 2093 ret = EFAULT; 2094 } 2095 } 2096 2097 /* 2098 * Free data for fcp_scsi_cmd pointer fields 2099 */ 2100 if (k_cdbbufaddr != NULL) { 2101 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2102 } 2103 if (k_bufaddr != NULL) { 2104 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2105 } 2106 if (k_rqbufaddr != NULL) { 2107 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2108 } 2109 2110 /* 2111 * Put fcp_scsi_cmd array element to user address space 2112 */ 2113 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2114 if (temp_ret != 0) { 2115 ret = temp_ret; 2116 } 2117 2118 /* 2119 * Return status 2120 */ 2121 return (ret); 2122 } 2123 2124 2125 /* 2126 * fcp_copyin_scsi_cmd 2127 * Copy in fcp_scsi_cmd data structure from user address space. 2128 * The data may be in 32 bit or 64 bit modes. 2129 * 2130 * Input: 2131 * base_addr = from address (user address space) 2132 * mode = See ioctl(9E) and ddi_copyin(9F) 2133 * 2134 * Output: 2135 * fscsi = to address (kernel address space) 2136 * 2137 * Returns: 2138 * 0 = OK 2139 * EFAULT = Error 2140 * 2141 * Context: 2142 * Kernel context. 2143 */ 2144 static int 2145 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2146 { 2147 #ifdef _MULTI_DATAMODEL 2148 struct fcp32_scsi_cmd f32scsi; 2149 2150 switch (ddi_model_convert_from(mode & FMODELS)) { 2151 case DDI_MODEL_ILP32: 2152 /* 2153 * Copy data from user address space 2154 */ 2155 if (ddi_copyin((void *)base_addr, 2156 &f32scsi, 2157 sizeof (struct fcp32_scsi_cmd), 2158 mode)) { 2159 return (EFAULT); 2160 } 2161 /* 2162 * Convert from 32 bit to 64 bit 2163 */ 2164 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2165 break; 2166 case DDI_MODEL_NONE: 2167 /* 2168 * Copy data from user address space 2169 */ 2170 if (ddi_copyin((void *)base_addr, 2171 fscsi, 2172 sizeof (struct fcp_scsi_cmd), 2173 mode)) { 2174 return (EFAULT); 2175 } 2176 break; 2177 } 2178 #else /* _MULTI_DATAMODEL */ 2179 /* 2180 * Copy data from user address space 2181 */ 2182 if (ddi_copyin((void *)base_addr, 2183 fscsi, 2184 sizeof (struct fcp_scsi_cmd), 2185 mode)) { 2186 return (EFAULT); 2187 } 2188 #endif /* _MULTI_DATAMODEL */ 2189 2190 return (0); 2191 } 2192 2193 2194 /* 2195 * fcp_copyout_scsi_cmd 2196 * Copy out fcp_scsi_cmd data structure to user address space. 2197 * The data may be in 32 bit or 64 bit modes. 2198 * 2199 * Input: 2200 * fscsi = to address (kernel address space) 2201 * mode = See ioctl(9E) and ddi_copyin(9F) 2202 * 2203 * Output: 2204 * base_addr = from address (user address space) 2205 * 2206 * Returns: 2207 * 0 = OK 2208 * EFAULT = Error 2209 * 2210 * Context: 2211 * Kernel context. 2212 */ 2213 static int 2214 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2215 { 2216 #ifdef _MULTI_DATAMODEL 2217 struct fcp32_scsi_cmd f32scsi; 2218 2219 switch (ddi_model_convert_from(mode & FMODELS)) { 2220 case DDI_MODEL_ILP32: 2221 /* 2222 * Convert from 64 bit to 32 bit 2223 */ 2224 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2225 /* 2226 * Copy data to user address space 2227 */ 2228 if (ddi_copyout(&f32scsi, 2229 (void *)base_addr, 2230 sizeof (struct fcp32_scsi_cmd), 2231 mode)) { 2232 return (EFAULT); 2233 } 2234 break; 2235 case DDI_MODEL_NONE: 2236 /* 2237 * Copy data to user address space 2238 */ 2239 if (ddi_copyout(fscsi, 2240 (void *)base_addr, 2241 sizeof (struct fcp_scsi_cmd), 2242 mode)) { 2243 return (EFAULT); 2244 } 2245 break; 2246 } 2247 #else /* _MULTI_DATAMODEL */ 2248 /* 2249 * Copy data to user address space 2250 */ 2251 if (ddi_copyout(fscsi, 2252 (void *)base_addr, 2253 sizeof (struct fcp_scsi_cmd), 2254 mode)) { 2255 return (EFAULT); 2256 } 2257 #endif /* _MULTI_DATAMODEL */ 2258 2259 return (0); 2260 } 2261 2262 2263 /* 2264 * fcp_send_scsi_ioctl 2265 * Sends the SCSI command in blocking mode. 2266 * 2267 * Input: 2268 * fscsi = SCSI command data structure 2269 * 2270 * Output: 2271 * fscsi = SCSI command data structure 2272 * 2273 * Returns: 2274 * 0 = OK 2275 * EAGAIN = See errno.h 2276 * EBUSY = See errno.h 2277 * EINTR = See errno.h 2278 * EINVAL = See errno.h 2279 * EIO = See errno.h 2280 * ENOMEM = See errno.h 2281 * ENXIO = See errno.h 2282 * 2283 * Context: 2284 * Kernel context. 2285 */ 2286 static int 2287 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2288 { 2289 struct fcp_lun *plun = NULL; 2290 struct fcp_port *pptr = NULL; 2291 struct fcp_tgt *ptgt = NULL; 2292 fc_packet_t *fpkt = NULL; 2293 struct fcp_ipkt *icmd = NULL; 2294 int target_created = FALSE; 2295 fc_frame_hdr_t *hp; 2296 struct fcp_cmd fcp_cmd; 2297 struct fcp_cmd *fcmd; 2298 union scsi_cdb *scsi_cdb; 2299 la_wwn_t *wwn_ptr; 2300 int nodma; 2301 struct fcp_rsp *rsp; 2302 struct fcp_rsp_info *rsp_info; 2303 caddr_t rsp_sense; 2304 int buf_len; 2305 int info_len; 2306 int sense_len; 2307 struct scsi_extended_sense *sense_to = NULL; 2308 timeout_id_t tid; 2309 uint8_t reconfig_lun = FALSE; 2310 uint8_t reconfig_pending = FALSE; 2311 uint8_t scsi_cmd; 2312 int rsp_len; 2313 int cmd_index; 2314 int fc_status; 2315 int pkt_state; 2316 int pkt_action; 2317 int pkt_reason; 2318 int ret, xport_retval = ~FC_SUCCESS; 2319 int lcount; 2320 int tcount; 2321 int reconfig_status; 2322 int port_busy = FALSE; 2323 uchar_t *lun_string; 2324 2325 /* 2326 * Check valid SCSI command 2327 */ 2328 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2329 ret = EINVAL; 2330 for (cmd_index = 0; 2331 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2332 ret != 0; 2333 cmd_index++) { 2334 /* 2335 * First byte of CDB is the SCSI command 2336 */ 2337 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2338 ret = 0; 2339 } 2340 } 2341 2342 /* 2343 * Check inputs 2344 */ 2345 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2346 ret = EINVAL; 2347 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2348 /* no larger than */ 2349 ret = EINVAL; 2350 } 2351 2352 2353 /* 2354 * Find FC port 2355 */ 2356 if (ret == 0) { 2357 /* 2358 * Acquire global mutex 2359 */ 2360 mutex_enter(&fcp_global_mutex); 2361 2362 pptr = fcp_port_head; 2363 while (pptr) { 2364 if (pptr->port_instance == 2365 (uint32_t)fscsi->scsi_fc_port_num) { 2366 break; 2367 } else { 2368 pptr = pptr->port_next; 2369 } 2370 } 2371 2372 if (pptr == NULL) { 2373 ret = ENXIO; 2374 } else { 2375 /* 2376 * fc_ulp_busy_port can raise power 2377 * so, we must not hold any mutexes involved in PM 2378 */ 2379 mutex_exit(&fcp_global_mutex); 2380 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2381 } 2382 2383 if (ret == 0) { 2384 2385 /* remember port is busy, so we will release later */ 2386 port_busy = TRUE; 2387 2388 /* 2389 * If there is a reconfiguration in progress, wait 2390 * for it to complete. 2391 */ 2392 2393 fcp_reconfig_wait(pptr); 2394 2395 /* reacquire mutexes in order */ 2396 mutex_enter(&fcp_global_mutex); 2397 mutex_enter(&pptr->port_mutex); 2398 2399 /* 2400 * Will port accept DMA? 2401 */ 2402 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2403 ? 1 : 0; 2404 2405 /* 2406 * If init or offline, device not known 2407 * 2408 * If we are discovering (onlining), we can 2409 * NOT obviously provide reliable data about 2410 * devices until it is complete 2411 */ 2412 if (pptr->port_state & (FCP_STATE_INIT | 2413 FCP_STATE_OFFLINE)) { 2414 ret = ENXIO; 2415 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2416 ret = EBUSY; 2417 } else { 2418 /* 2419 * Find target from pwwn 2420 * 2421 * The wwn must be put into a local 2422 * variable to ensure alignment. 2423 */ 2424 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2425 ptgt = fcp_lookup_target(pptr, 2426 (uchar_t *)wwn_ptr); 2427 2428 /* 2429 * If target not found, 2430 */ 2431 if (ptgt == NULL) { 2432 /* 2433 * Note: Still have global & 2434 * port mutexes 2435 */ 2436 mutex_exit(&pptr->port_mutex); 2437 ptgt = fcp_port_create_tgt(pptr, 2438 wwn_ptr, &ret, &fc_status, 2439 &pkt_state, &pkt_action, 2440 &pkt_reason); 2441 mutex_enter(&pptr->port_mutex); 2442 2443 fscsi->scsi_fc_status = fc_status; 2444 fscsi->scsi_pkt_state = 2445 (uchar_t)pkt_state; 2446 fscsi->scsi_pkt_reason = pkt_reason; 2447 fscsi->scsi_pkt_action = 2448 (uchar_t)pkt_action; 2449 2450 if (ptgt != NULL) { 2451 target_created = TRUE; 2452 } else if (ret == 0) { 2453 ret = ENOMEM; 2454 } 2455 } 2456 2457 if (ret == 0) { 2458 /* 2459 * Acquire target 2460 */ 2461 mutex_enter(&ptgt->tgt_mutex); 2462 2463 /* 2464 * If target is mark or busy, 2465 * then target can not be used 2466 */ 2467 if (ptgt->tgt_state & 2468 (FCP_TGT_MARK | 2469 FCP_TGT_BUSY)) { 2470 ret = EBUSY; 2471 } else { 2472 /* 2473 * Mark target as busy 2474 */ 2475 ptgt->tgt_state |= 2476 FCP_TGT_BUSY; 2477 } 2478 2479 /* 2480 * Release target 2481 */ 2482 lcount = pptr->port_link_cnt; 2483 tcount = ptgt->tgt_change_cnt; 2484 mutex_exit(&ptgt->tgt_mutex); 2485 } 2486 } 2487 2488 /* 2489 * Release port 2490 */ 2491 mutex_exit(&pptr->port_mutex); 2492 } 2493 2494 /* 2495 * Release global mutex 2496 */ 2497 mutex_exit(&fcp_global_mutex); 2498 } 2499 2500 if (ret == 0) { 2501 uint64_t belun = BE_64(fscsi->scsi_lun); 2502 2503 /* 2504 * If it's a target device, find lun from pwwn 2505 * The wwn must be put into a local 2506 * variable to ensure alignment. 2507 */ 2508 mutex_enter(&pptr->port_mutex); 2509 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2510 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2511 /* this is not a target */ 2512 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2513 ret = ENXIO; 2514 } else if ((belun << 16) != 0) { 2515 /* 2516 * Since fcp only support PD and LU addressing method 2517 * so far, the last 6 bytes of a valid LUN are expected 2518 * to be filled with 00h. 2519 */ 2520 fscsi->scsi_fc_status = FC_INVALID_LUN; 2521 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2522 " method 0x%02x with LUN number 0x%016" PRIx64, 2523 (uint8_t)(belun >> 62), belun); 2524 ret = ENXIO; 2525 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2526 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2527 /* 2528 * This is a SCSI target, but no LUN at this 2529 * address. 2530 * 2531 * In the future, we may want to send this to 2532 * the target, and let it respond 2533 * appropriately 2534 */ 2535 ret = ENXIO; 2536 } 2537 mutex_exit(&pptr->port_mutex); 2538 } 2539 2540 /* 2541 * Finished grabbing external resources 2542 * Allocate internal packet (icmd) 2543 */ 2544 if (ret == 0) { 2545 /* 2546 * Calc rsp len assuming rsp info included 2547 */ 2548 rsp_len = sizeof (struct fcp_rsp) + 2549 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2550 2551 icmd = fcp_icmd_alloc(pptr, ptgt, 2552 sizeof (struct fcp_cmd), 2553 rsp_len, 2554 fscsi->scsi_buflen, 2555 nodma, 2556 lcount, /* ipkt_link_cnt */ 2557 tcount, /* ipkt_change_cnt */ 2558 0, /* cause */ 2559 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2560 2561 if (icmd == NULL) { 2562 ret = ENOMEM; 2563 } else { 2564 /* 2565 * Setup internal packet as sema sync 2566 */ 2567 fcp_ipkt_sema_init(icmd); 2568 } 2569 } 2570 2571 if (ret == 0) { 2572 /* 2573 * Init fpkt pointer for use. 2574 */ 2575 2576 fpkt = icmd->ipkt_fpkt; 2577 2578 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2579 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2580 fpkt->pkt_timeout = fscsi->scsi_timeout; 2581 2582 /* 2583 * Init fcmd pointer for use by SCSI command 2584 */ 2585 2586 if (nodma) { 2587 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2588 } else { 2589 fcmd = &fcp_cmd; 2590 } 2591 bzero(fcmd, sizeof (struct fcp_cmd)); 2592 ptgt = plun->lun_tgt; 2593 2594 lun_string = (uchar_t *)&fscsi->scsi_lun; 2595 2596 fcmd->fcp_ent_addr.ent_addr_0 = 2597 BE_16(*(uint16_t *)&(lun_string[0])); 2598 fcmd->fcp_ent_addr.ent_addr_1 = 2599 BE_16(*(uint16_t *)&(lun_string[2])); 2600 fcmd->fcp_ent_addr.ent_addr_2 = 2601 BE_16(*(uint16_t *)&(lun_string[4])); 2602 fcmd->fcp_ent_addr.ent_addr_3 = 2603 BE_16(*(uint16_t *)&(lun_string[6])); 2604 2605 /* 2606 * Setup internal packet(icmd) 2607 */ 2608 icmd->ipkt_lun = plun; 2609 icmd->ipkt_restart = 0; 2610 icmd->ipkt_retries = 0; 2611 icmd->ipkt_opcode = 0; 2612 2613 /* 2614 * Init the frame HEADER Pointer for use 2615 */ 2616 hp = &fpkt->pkt_cmd_fhdr; 2617 2618 hp->s_id = pptr->port_id; 2619 hp->d_id = ptgt->tgt_d_id; 2620 hp->r_ctl = R_CTL_COMMAND; 2621 hp->type = FC_TYPE_SCSI_FCP; 2622 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2623 hp->rsvd = 0; 2624 hp->seq_id = 0; 2625 hp->seq_cnt = 0; 2626 hp->ox_id = 0xffff; 2627 hp->rx_id = 0xffff; 2628 hp->ro = 0; 2629 2630 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2631 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2632 fcmd->fcp_cntl.cntl_write_data = 0; 2633 fcmd->fcp_data_len = fscsi->scsi_buflen; 2634 2635 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2636 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2637 fscsi->scsi_cdblen); 2638 2639 if (!nodma) { 2640 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2641 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2642 } 2643 2644 /* 2645 * Send SCSI command to FC transport 2646 */ 2647 2648 if (ret == 0) { 2649 mutex_enter(&ptgt->tgt_mutex); 2650 2651 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2652 mutex_exit(&ptgt->tgt_mutex); 2653 fscsi->scsi_fc_status = xport_retval = 2654 fc_ulp_transport(pptr->port_fp_handle, 2655 fpkt); 2656 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2657 ret = EIO; 2658 } 2659 } else { 2660 mutex_exit(&ptgt->tgt_mutex); 2661 ret = EBUSY; 2662 } 2663 } 2664 } 2665 2666 /* 2667 * Wait for completion only if fc_ulp_transport was called and it 2668 * returned a success. This is the only time callback will happen. 2669 * Otherwise, there is no point in waiting 2670 */ 2671 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2672 ret = fcp_ipkt_sema_wait(icmd); 2673 } 2674 2675 /* 2676 * Copy data to IOCTL data structures 2677 */ 2678 rsp = NULL; 2679 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2680 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2681 2682 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2683 fcp_log(CE_WARN, pptr->port_dip, 2684 "!SCSI command to d_id=0x%x lun=0x%x" 2685 " failed, Bad FCP response values:" 2686 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2687 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2688 ptgt->tgt_d_id, plun->lun_num, 2689 rsp->reserved_0, rsp->reserved_1, 2690 rsp->fcp_u.fcp_status.reserved_0, 2691 rsp->fcp_u.fcp_status.reserved_1, 2692 rsp->fcp_response_len, rsp->fcp_sense_len); 2693 2694 ret = EIO; 2695 } 2696 } 2697 2698 if ((ret == 0) && (rsp != NULL)) { 2699 /* 2700 * Calc response lengths 2701 */ 2702 sense_len = 0; 2703 info_len = 0; 2704 2705 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2706 info_len = rsp->fcp_response_len; 2707 } 2708 2709 rsp_info = (struct fcp_rsp_info *) 2710 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2711 2712 /* 2713 * Get SCSI status 2714 */ 2715 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2716 /* 2717 * If a lun was just added or removed and the next command 2718 * comes through this interface, we need to capture the check 2719 * condition so we can discover the new topology. 2720 */ 2721 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2722 rsp->fcp_u.fcp_status.sense_len_set) { 2723 sense_len = rsp->fcp_sense_len; 2724 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2725 sense_to = (struct scsi_extended_sense *)rsp_sense; 2726 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2727 (FCP_SENSE_NO_LUN(sense_to))) { 2728 reconfig_lun = TRUE; 2729 } 2730 } 2731 2732 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2733 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2734 if (reconfig_lun == FALSE) { 2735 reconfig_status = 2736 fcp_is_reconfig_needed(ptgt, fpkt); 2737 } 2738 2739 if ((reconfig_lun == TRUE) || 2740 (reconfig_status == TRUE)) { 2741 mutex_enter(&ptgt->tgt_mutex); 2742 if (ptgt->tgt_tid == NULL) { 2743 /* 2744 * Either we've been notified the 2745 * REPORT_LUN data has changed, or 2746 * we've determined on our own that 2747 * we're out of date. Kick off 2748 * rediscovery. 2749 */ 2750 tid = timeout(fcp_reconfigure_luns, 2751 (caddr_t)ptgt, drv_usectohz(1)); 2752 2753 ptgt->tgt_tid = tid; 2754 ptgt->tgt_state |= FCP_TGT_BUSY; 2755 ret = EBUSY; 2756 reconfig_pending = TRUE; 2757 } 2758 mutex_exit(&ptgt->tgt_mutex); 2759 } 2760 } 2761 2762 /* 2763 * Calc residuals and buffer lengths 2764 */ 2765 2766 if (ret == 0) { 2767 buf_len = fscsi->scsi_buflen; 2768 fscsi->scsi_bufresid = 0; 2769 if (rsp->fcp_u.fcp_status.resid_under) { 2770 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2771 fscsi->scsi_bufresid = rsp->fcp_resid; 2772 } else { 2773 cmn_err(CE_WARN, "fcp: bad residue %x " 2774 "for txfer len %x", rsp->fcp_resid, 2775 fscsi->scsi_buflen); 2776 fscsi->scsi_bufresid = 2777 fscsi->scsi_buflen; 2778 } 2779 buf_len -= fscsi->scsi_bufresid; 2780 } 2781 if (rsp->fcp_u.fcp_status.resid_over) { 2782 fscsi->scsi_bufresid = -rsp->fcp_resid; 2783 } 2784 2785 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2786 if (fscsi->scsi_rqlen < sense_len) { 2787 sense_len = fscsi->scsi_rqlen; 2788 } 2789 2790 fscsi->scsi_fc_rspcode = 0; 2791 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2792 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2793 } 2794 fscsi->scsi_pkt_state = fpkt->pkt_state; 2795 fscsi->scsi_pkt_action = fpkt->pkt_action; 2796 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2797 2798 /* 2799 * Copy data and request sense 2800 * 2801 * Data must be copied by using the FCP_CP_IN macro. 2802 * This will ensure the proper byte order since the data 2803 * is being copied directly from the memory mapped 2804 * device register. 2805 * 2806 * The response (and request sense) will be in the 2807 * correct byte order. No special copy is necessary. 2808 */ 2809 2810 if (buf_len) { 2811 FCP_CP_IN(fpkt->pkt_data, 2812 fscsi->scsi_bufaddr, 2813 fpkt->pkt_data_acc, 2814 buf_len); 2815 } 2816 bcopy((void *)rsp_sense, 2817 (void *)fscsi->scsi_rqbufaddr, 2818 sense_len); 2819 } 2820 } 2821 2822 /* 2823 * Cleanup transport data structures if icmd was alloc-ed 2824 * So, cleanup happens in the same thread that icmd was alloc-ed 2825 */ 2826 if (icmd != NULL) { 2827 fcp_ipkt_sema_cleanup(icmd); 2828 } 2829 2830 /* restore pm busy/idle status */ 2831 if (port_busy) { 2832 fc_ulp_idle_port(pptr->port_fp_handle); 2833 } 2834 2835 /* 2836 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2837 * flag, it'll be cleared when the reconfig is complete. 2838 */ 2839 if ((ptgt != NULL) && !reconfig_pending) { 2840 /* 2841 * If target was created, 2842 */ 2843 if (target_created) { 2844 mutex_enter(&ptgt->tgt_mutex); 2845 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2846 mutex_exit(&ptgt->tgt_mutex); 2847 } else { 2848 /* 2849 * De-mark target as busy 2850 */ 2851 mutex_enter(&ptgt->tgt_mutex); 2852 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2853 mutex_exit(&ptgt->tgt_mutex); 2854 } 2855 } 2856 return (ret); 2857 } 2858 2859 2860 static int 2861 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2862 fc_packet_t *fpkt) 2863 { 2864 uchar_t *lun_string; 2865 uint16_t lun_num, i; 2866 int num_luns; 2867 int actual_luns; 2868 int num_masked_luns; 2869 int lun_buflen; 2870 struct fcp_lun *plun = NULL; 2871 struct fcp_reportlun_resp *report_lun; 2872 uint8_t reconfig_needed = FALSE; 2873 uint8_t lun_exists = FALSE; 2874 fcp_port_t *pptr = ptgt->tgt_port; 2875 2876 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2877 2878 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2879 fpkt->pkt_datalen); 2880 2881 /* get number of luns (which is supplied as LUNS * 8) */ 2882 num_luns = BE_32(report_lun->num_lun) >> 3; 2883 2884 /* 2885 * Figure out exactly how many lun strings our response buffer 2886 * can hold. 2887 */ 2888 lun_buflen = (fpkt->pkt_datalen - 2889 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2890 2891 /* 2892 * Is our response buffer full or not? We don't want to 2893 * potentially walk beyond the number of luns we have. 2894 */ 2895 if (num_luns <= lun_buflen) { 2896 actual_luns = num_luns; 2897 } else { 2898 actual_luns = lun_buflen; 2899 } 2900 2901 mutex_enter(&ptgt->tgt_mutex); 2902 2903 /* Scan each lun to see if we have masked it. */ 2904 num_masked_luns = 0; 2905 if (fcp_lun_blacklist != NULL) { 2906 for (i = 0; i < actual_luns; i++) { 2907 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2908 switch (lun_string[0] & 0xC0) { 2909 case FCP_LUN_ADDRESSING: 2910 case FCP_PD_ADDRESSING: 2911 case FCP_VOLUME_ADDRESSING: 2912 lun_num = ((lun_string[0] & 0x3F) << 8) 2913 | lun_string[1]; 2914 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2915 lun_num) == TRUE) { 2916 num_masked_luns++; 2917 } 2918 break; 2919 default: 2920 break; 2921 } 2922 } 2923 } 2924 2925 /* 2926 * The quick and easy check. If the number of LUNs reported 2927 * doesn't match the number we currently know about, we need 2928 * to reconfigure. 2929 */ 2930 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2931 mutex_exit(&ptgt->tgt_mutex); 2932 kmem_free(report_lun, fpkt->pkt_datalen); 2933 return (TRUE); 2934 } 2935 2936 /* 2937 * If the quick and easy check doesn't turn up anything, we walk 2938 * the list of luns from the REPORT_LUN response and look for 2939 * any luns we don't know about. If we find one, we know we need 2940 * to reconfigure. We will skip LUNs that are masked because of the 2941 * blacklist. 2942 */ 2943 for (i = 0; i < actual_luns; i++) { 2944 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2945 lun_exists = FALSE; 2946 switch (lun_string[0] & 0xC0) { 2947 case FCP_LUN_ADDRESSING: 2948 case FCP_PD_ADDRESSING: 2949 case FCP_VOLUME_ADDRESSING: 2950 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2951 2952 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2953 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2954 lun_exists = TRUE; 2955 break; 2956 } 2957 2958 for (plun = ptgt->tgt_lun; plun; 2959 plun = plun->lun_next) { 2960 if (plun->lun_num == lun_num) { 2961 lun_exists = TRUE; 2962 break; 2963 } 2964 } 2965 break; 2966 default: 2967 break; 2968 } 2969 2970 if (lun_exists == FALSE) { 2971 reconfig_needed = TRUE; 2972 break; 2973 } 2974 } 2975 2976 mutex_exit(&ptgt->tgt_mutex); 2977 kmem_free(report_lun, fpkt->pkt_datalen); 2978 2979 return (reconfig_needed); 2980 } 2981 2982 /* 2983 * This function is called by fcp_handle_page83 and uses inquiry response data 2984 * stored in plun->lun_inq to determine whether or not a device is a member of 2985 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2986 * otherwise 1. 2987 */ 2988 static int 2989 fcp_symmetric_device_probe(struct fcp_lun *plun) 2990 { 2991 struct scsi_inquiry *stdinq = &plun->lun_inq; 2992 char *devidptr; 2993 int i, len; 2994 2995 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2996 devidptr = fcp_symmetric_disk_table[i]; 2997 len = (int)strlen(devidptr); 2998 2999 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 3000 return (0); 3001 } 3002 } 3003 return (1); 3004 } 3005 3006 3007 /* 3008 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 3009 * It basically returns the current count of # of state change callbacks 3010 * i.e the value of tgt_change_cnt. 3011 * 3012 * INPUT: 3013 * fcp_ioctl.fp_minor -> The minor # of the fp port 3014 * fcp_ioctl.listlen -> 1 3015 * fcp_ioctl.list -> Pointer to a 32 bit integer 3016 */ 3017 /*ARGSUSED2*/ 3018 static int 3019 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3020 { 3021 int ret; 3022 uint32_t link_cnt; 3023 struct fcp_ioctl fioctl; 3024 struct fcp_port *pptr = NULL; 3025 3026 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3027 &pptr)) != 0) { 3028 return (ret); 3029 } 3030 3031 ASSERT(pptr != NULL); 3032 3033 if (fioctl.listlen != 1) { 3034 return (EINVAL); 3035 } 3036 3037 mutex_enter(&pptr->port_mutex); 3038 if (pptr->port_state & FCP_STATE_OFFLINE) { 3039 mutex_exit(&pptr->port_mutex); 3040 return (ENXIO); 3041 } 3042 3043 /* 3044 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3045 * When the fcp initially attaches to the port and there are nothing 3046 * hanging out of the port or if there was a repeat offline state change 3047 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3048 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3049 * will differentiate the 2 cases. 3050 */ 3051 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3052 mutex_exit(&pptr->port_mutex); 3053 return (ENXIO); 3054 } 3055 3056 link_cnt = pptr->port_link_cnt; 3057 mutex_exit(&pptr->port_mutex); 3058 3059 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3060 return (EFAULT); 3061 } 3062 3063 #ifdef _MULTI_DATAMODEL 3064 switch (ddi_model_convert_from(mode & FMODELS)) { 3065 case DDI_MODEL_ILP32: { 3066 struct fcp32_ioctl f32_ioctl; 3067 3068 f32_ioctl.fp_minor = fioctl.fp_minor; 3069 f32_ioctl.listlen = fioctl.listlen; 3070 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3071 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3072 sizeof (struct fcp32_ioctl), mode)) { 3073 return (EFAULT); 3074 } 3075 break; 3076 } 3077 case DDI_MODEL_NONE: 3078 if (ddi_copyout((void *)&fioctl, (void *)data, 3079 sizeof (struct fcp_ioctl), mode)) { 3080 return (EFAULT); 3081 } 3082 break; 3083 } 3084 #else /* _MULTI_DATAMODEL */ 3085 3086 if (ddi_copyout((void *)&fioctl, (void *)data, 3087 sizeof (struct fcp_ioctl), mode)) { 3088 return (EFAULT); 3089 } 3090 #endif /* _MULTI_DATAMODEL */ 3091 3092 return (0); 3093 } 3094 3095 /* 3096 * This function copies the fcp_ioctl structure passed in from user land 3097 * into kernel land. Handles 32 bit applications. 3098 */ 3099 /*ARGSUSED*/ 3100 static int 3101 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3102 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3103 { 3104 struct fcp_port *t_pptr; 3105 3106 #ifdef _MULTI_DATAMODEL 3107 switch (ddi_model_convert_from(mode & FMODELS)) { 3108 case DDI_MODEL_ILP32: { 3109 struct fcp32_ioctl f32_ioctl; 3110 3111 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3112 sizeof (struct fcp32_ioctl), mode)) { 3113 return (EFAULT); 3114 } 3115 fioctl->fp_minor = f32_ioctl.fp_minor; 3116 fioctl->listlen = f32_ioctl.listlen; 3117 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3118 break; 3119 } 3120 case DDI_MODEL_NONE: 3121 if (ddi_copyin((void *)data, (void *)fioctl, 3122 sizeof (struct fcp_ioctl), mode)) { 3123 return (EFAULT); 3124 } 3125 break; 3126 } 3127 3128 #else /* _MULTI_DATAMODEL */ 3129 if (ddi_copyin((void *)data, (void *)fioctl, 3130 sizeof (struct fcp_ioctl), mode)) { 3131 return (EFAULT); 3132 } 3133 #endif /* _MULTI_DATAMODEL */ 3134 3135 /* 3136 * Right now we can assume that the minor number matches with 3137 * this instance of fp. If this changes we will need to 3138 * revisit this logic. 3139 */ 3140 mutex_enter(&fcp_global_mutex); 3141 t_pptr = fcp_port_head; 3142 while (t_pptr) { 3143 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3144 break; 3145 } else { 3146 t_pptr = t_pptr->port_next; 3147 } 3148 } 3149 *pptr = t_pptr; 3150 mutex_exit(&fcp_global_mutex); 3151 if (t_pptr == NULL) { 3152 return (ENXIO); 3153 } 3154 3155 return (0); 3156 } 3157 3158 /* 3159 * Function: fcp_port_create_tgt 3160 * 3161 * Description: As the name suggest this function creates the target context 3162 * specified by the the WWN provided by the caller. If the 3163 * creation goes well and the target is known by fp/fctl a PLOGI 3164 * followed by a PRLI are issued. 3165 * 3166 * Argument: pptr fcp port structure 3167 * pwwn WWN of the target 3168 * ret_val Address of the return code. It could be: 3169 * EIO, ENOMEM or 0. 3170 * fc_status PLOGI or PRLI status completion 3171 * fc_pkt_state PLOGI or PRLI state completion 3172 * fc_pkt_reason PLOGI or PRLI reason completion 3173 * fc_pkt_action PLOGI or PRLI action completion 3174 * 3175 * Return Value: NULL if it failed 3176 * Target structure address if it succeeds 3177 */ 3178 static struct fcp_tgt * 3179 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3180 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3181 { 3182 struct fcp_tgt *ptgt = NULL; 3183 fc_portmap_t devlist; 3184 int lcount; 3185 int error; 3186 3187 *ret_val = 0; 3188 3189 /* 3190 * Check FC port device & get port map 3191 */ 3192 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3193 &error, 1) == NULL) { 3194 *ret_val = EIO; 3195 } else { 3196 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3197 &devlist) != FC_SUCCESS) { 3198 *ret_val = EIO; 3199 } 3200 } 3201 3202 /* Set port map flags */ 3203 devlist.map_type = PORT_DEVICE_USER_CREATE; 3204 3205 /* Allocate target */ 3206 if (*ret_val == 0) { 3207 lcount = pptr->port_link_cnt; 3208 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3209 if (ptgt == NULL) { 3210 fcp_log(CE_WARN, pptr->port_dip, 3211 "!FC target allocation failed"); 3212 *ret_val = ENOMEM; 3213 } else { 3214 /* Setup target */ 3215 mutex_enter(&ptgt->tgt_mutex); 3216 3217 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3218 ptgt->tgt_tmp_cnt = 1; 3219 ptgt->tgt_d_id = devlist.map_did.port_id; 3220 ptgt->tgt_hard_addr = 3221 devlist.map_hard_addr.hard_addr; 3222 ptgt->tgt_pd_handle = devlist.map_pd; 3223 ptgt->tgt_fca_dev = NULL; 3224 3225 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3226 FC_WWN_SIZE); 3227 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3228 FC_WWN_SIZE); 3229 3230 mutex_exit(&ptgt->tgt_mutex); 3231 } 3232 } 3233 3234 /* Release global mutex for PLOGI and PRLI */ 3235 mutex_exit(&fcp_global_mutex); 3236 3237 /* Send PLOGI (If necessary) */ 3238 if (*ret_val == 0) { 3239 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3240 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3241 } 3242 3243 /* Send PRLI (If necessary) */ 3244 if (*ret_val == 0) { 3245 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3246 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3247 } 3248 3249 mutex_enter(&fcp_global_mutex); 3250 3251 return (ptgt); 3252 } 3253 3254 /* 3255 * Function: fcp_tgt_send_plogi 3256 * 3257 * Description: This function sends a PLOGI to the target specified by the 3258 * caller and waits till it completes. 3259 * 3260 * Argument: ptgt Target to send the plogi to. 3261 * fc_status Status returned by fp/fctl in the PLOGI request. 3262 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3263 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3264 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3265 * 3266 * Return Value: 0 3267 * ENOMEM 3268 * EIO 3269 * 3270 * Context: User context. 3271 */ 3272 static int 3273 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3274 int *fc_pkt_reason, int *fc_pkt_action) 3275 { 3276 struct fcp_port *pptr; 3277 struct fcp_ipkt *icmd; 3278 struct fc_packet *fpkt; 3279 fc_frame_hdr_t *hp; 3280 struct la_els_logi logi; 3281 int tcount; 3282 int lcount; 3283 int ret, login_retval = ~FC_SUCCESS; 3284 3285 ret = 0; 3286 3287 pptr = ptgt->tgt_port; 3288 3289 lcount = pptr->port_link_cnt; 3290 tcount = ptgt->tgt_change_cnt; 3291 3292 /* Alloc internal packet */ 3293 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3294 sizeof (la_els_logi_t), 0, 3295 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3296 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3297 3298 if (icmd == NULL) { 3299 ret = ENOMEM; 3300 } else { 3301 /* 3302 * Setup internal packet as sema sync 3303 */ 3304 fcp_ipkt_sema_init(icmd); 3305 3306 /* 3307 * Setup internal packet (icmd) 3308 */ 3309 icmd->ipkt_lun = NULL; 3310 icmd->ipkt_restart = 0; 3311 icmd->ipkt_retries = 0; 3312 icmd->ipkt_opcode = LA_ELS_PLOGI; 3313 3314 /* 3315 * Setup fc_packet 3316 */ 3317 fpkt = icmd->ipkt_fpkt; 3318 3319 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3320 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3321 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3322 3323 /* 3324 * Setup FC frame header 3325 */ 3326 hp = &fpkt->pkt_cmd_fhdr; 3327 3328 hp->s_id = pptr->port_id; /* source ID */ 3329 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3330 hp->r_ctl = R_CTL_ELS_REQ; 3331 hp->type = FC_TYPE_EXTENDED_LS; 3332 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3333 hp->seq_id = 0; 3334 hp->rsvd = 0; 3335 hp->df_ctl = 0; 3336 hp->seq_cnt = 0; 3337 hp->ox_id = 0xffff; /* i.e. none */ 3338 hp->rx_id = 0xffff; /* i.e. none */ 3339 hp->ro = 0; 3340 3341 /* 3342 * Setup PLOGI 3343 */ 3344 bzero(&logi, sizeof (struct la_els_logi)); 3345 logi.ls_code.ls_code = LA_ELS_PLOGI; 3346 3347 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3348 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3349 3350 /* 3351 * Send PLOGI 3352 */ 3353 *fc_status = login_retval = 3354 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3355 if (*fc_status != FC_SUCCESS) { 3356 ret = EIO; 3357 } 3358 } 3359 3360 /* 3361 * Wait for completion 3362 */ 3363 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3364 ret = fcp_ipkt_sema_wait(icmd); 3365 3366 *fc_pkt_state = fpkt->pkt_state; 3367 *fc_pkt_reason = fpkt->pkt_reason; 3368 *fc_pkt_action = fpkt->pkt_action; 3369 } 3370 3371 /* 3372 * Cleanup transport data structures if icmd was alloc-ed AND if there 3373 * is going to be no callback (i.e if fc_ulp_login() failed). 3374 * Otherwise, cleanup happens in callback routine. 3375 */ 3376 if (icmd != NULL) { 3377 fcp_ipkt_sema_cleanup(icmd); 3378 } 3379 3380 return (ret); 3381 } 3382 3383 /* 3384 * Function: fcp_tgt_send_prli 3385 * 3386 * Description: Does nothing as of today. 3387 * 3388 * Argument: ptgt Target to send the prli to. 3389 * fc_status Status returned by fp/fctl in the PRLI request. 3390 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3391 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3392 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3393 * 3394 * Return Value: 0 3395 */ 3396 /*ARGSUSED*/ 3397 static int 3398 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3399 int *fc_pkt_reason, int *fc_pkt_action) 3400 { 3401 return (0); 3402 } 3403 3404 /* 3405 * Function: fcp_ipkt_sema_init 3406 * 3407 * Description: Initializes the semaphore contained in the internal packet. 3408 * 3409 * Argument: icmd Internal packet the semaphore of which must be 3410 * initialized. 3411 * 3412 * Return Value: None 3413 * 3414 * Context: User context only. 3415 */ 3416 static void 3417 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3418 { 3419 struct fc_packet *fpkt; 3420 3421 fpkt = icmd->ipkt_fpkt; 3422 3423 /* Create semaphore for sync */ 3424 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3425 3426 /* Setup the completion callback */ 3427 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3428 } 3429 3430 /* 3431 * Function: fcp_ipkt_sema_wait 3432 * 3433 * Description: Wait on the semaphore embedded in the internal packet. The 3434 * semaphore is released in the callback. 3435 * 3436 * Argument: icmd Internal packet to wait on for completion. 3437 * 3438 * Return Value: 0 3439 * EIO 3440 * EBUSY 3441 * EAGAIN 3442 * 3443 * Context: User context only. 3444 * 3445 * This function does a conversion between the field pkt_state of the fc_packet 3446 * embedded in the internal packet (icmd) and the code it returns. 3447 */ 3448 static int 3449 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3450 { 3451 struct fc_packet *fpkt; 3452 int ret; 3453 3454 ret = EIO; 3455 fpkt = icmd->ipkt_fpkt; 3456 3457 /* 3458 * Wait on semaphore 3459 */ 3460 sema_p(&(icmd->ipkt_sema)); 3461 3462 /* 3463 * Check the status of the FC packet 3464 */ 3465 switch (fpkt->pkt_state) { 3466 case FC_PKT_SUCCESS: 3467 ret = 0; 3468 break; 3469 case FC_PKT_LOCAL_RJT: 3470 switch (fpkt->pkt_reason) { 3471 case FC_REASON_SEQ_TIMEOUT: 3472 case FC_REASON_RX_BUF_TIMEOUT: 3473 ret = EAGAIN; 3474 break; 3475 case FC_REASON_PKT_BUSY: 3476 ret = EBUSY; 3477 break; 3478 } 3479 break; 3480 case FC_PKT_TIMEOUT: 3481 ret = EAGAIN; 3482 break; 3483 case FC_PKT_LOCAL_BSY: 3484 case FC_PKT_TRAN_BSY: 3485 case FC_PKT_NPORT_BSY: 3486 case FC_PKT_FABRIC_BSY: 3487 ret = EBUSY; 3488 break; 3489 case FC_PKT_LS_RJT: 3490 case FC_PKT_BA_RJT: 3491 switch (fpkt->pkt_reason) { 3492 case FC_REASON_LOGICAL_BSY: 3493 ret = EBUSY; 3494 break; 3495 } 3496 break; 3497 case FC_PKT_FS_RJT: 3498 switch (fpkt->pkt_reason) { 3499 case FC_REASON_FS_LOGICAL_BUSY: 3500 ret = EBUSY; 3501 break; 3502 } 3503 break; 3504 } 3505 3506 return (ret); 3507 } 3508 3509 /* 3510 * Function: fcp_ipkt_sema_callback 3511 * 3512 * Description: Registered as the completion callback function for the FC 3513 * transport when the ipkt semaphore is used for sync. This will 3514 * cleanup the used data structures, if necessary and wake up 3515 * the user thread to complete the transaction. 3516 * 3517 * Argument: fpkt FC packet (points to the icmd) 3518 * 3519 * Return Value: None 3520 * 3521 * Context: User context only 3522 */ 3523 static void 3524 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3525 { 3526 struct fcp_ipkt *icmd; 3527 3528 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3529 3530 /* 3531 * Wake up user thread 3532 */ 3533 sema_v(&(icmd->ipkt_sema)); 3534 } 3535 3536 /* 3537 * Function: fcp_ipkt_sema_cleanup 3538 * 3539 * Description: Called to cleanup (if necessary) the data structures used 3540 * when ipkt sema is used for sync. This function will detect 3541 * whether the caller is the last thread (via counter) and 3542 * cleanup only if necessary. 3543 * 3544 * Argument: icmd Internal command packet 3545 * 3546 * Return Value: None 3547 * 3548 * Context: User context only 3549 */ 3550 static void 3551 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3552 { 3553 struct fcp_tgt *ptgt; 3554 struct fcp_port *pptr; 3555 3556 ptgt = icmd->ipkt_tgt; 3557 pptr = icmd->ipkt_port; 3558 3559 /* 3560 * Acquire data structure 3561 */ 3562 mutex_enter(&ptgt->tgt_mutex); 3563 3564 /* 3565 * Destroy semaphore 3566 */ 3567 sema_destroy(&(icmd->ipkt_sema)); 3568 3569 /* 3570 * Cleanup internal packet 3571 */ 3572 mutex_exit(&ptgt->tgt_mutex); 3573 fcp_icmd_free(pptr, icmd); 3574 } 3575 3576 /* 3577 * Function: fcp_port_attach 3578 * 3579 * Description: Called by the transport framework to resume, suspend or 3580 * attach a new port. 3581 * 3582 * Argument: ulph Port handle 3583 * *pinfo Port information 3584 * cmd Command 3585 * s_id Port ID 3586 * 3587 * Return Value: FC_FAILURE or FC_SUCCESS 3588 */ 3589 /*ARGSUSED*/ 3590 static int 3591 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3592 fc_attach_cmd_t cmd, uint32_t s_id) 3593 { 3594 int instance; 3595 int res = FC_FAILURE; /* default result */ 3596 3597 ASSERT(pinfo != NULL); 3598 3599 instance = ddi_get_instance(pinfo->port_dip); 3600 3601 switch (cmd) { 3602 case FC_CMD_ATTACH: 3603 /* 3604 * this port instance attaching for the first time (or after 3605 * being detached before) 3606 */ 3607 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3608 instance) == DDI_SUCCESS) { 3609 res = FC_SUCCESS; 3610 } else { 3611 ASSERT(ddi_get_soft_state(fcp_softstate, 3612 instance) == NULL); 3613 } 3614 break; 3615 3616 case FC_CMD_RESUME: 3617 case FC_CMD_POWER_UP: 3618 /* 3619 * this port instance was attached and the suspended and 3620 * will now be resumed 3621 */ 3622 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3623 instance) == DDI_SUCCESS) { 3624 res = FC_SUCCESS; 3625 } 3626 break; 3627 3628 default: 3629 /* shouldn't happen */ 3630 FCP_TRACE(fcp_logq, "fcp", 3631 fcp_trace, FCP_BUF_LEVEL_2, 0, 3632 "port_attach: unknown cmdcommand: %d", cmd); 3633 break; 3634 } 3635 3636 /* return result */ 3637 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3638 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3639 3640 return (res); 3641 } 3642 3643 3644 /* 3645 * detach or suspend this port instance 3646 * 3647 * acquires and releases the global mutex 3648 * 3649 * acquires and releases the mutex for this port 3650 * 3651 * acquires and releases the hotplug mutex for this port 3652 */ 3653 /*ARGSUSED*/ 3654 static int 3655 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3656 fc_detach_cmd_t cmd) 3657 { 3658 int flag; 3659 int instance; 3660 struct fcp_port *pptr; 3661 3662 instance = ddi_get_instance(info->port_dip); 3663 pptr = ddi_get_soft_state(fcp_softstate, instance); 3664 3665 switch (cmd) { 3666 case FC_CMD_SUSPEND: 3667 FCP_DTRACE(fcp_logq, "fcp", 3668 fcp_trace, FCP_BUF_LEVEL_8, 0, 3669 "port suspend called for port %d", instance); 3670 flag = FCP_STATE_SUSPENDED; 3671 break; 3672 3673 case FC_CMD_POWER_DOWN: 3674 FCP_DTRACE(fcp_logq, "fcp", 3675 fcp_trace, FCP_BUF_LEVEL_8, 0, 3676 "port power down called for port %d", instance); 3677 flag = FCP_STATE_POWER_DOWN; 3678 break; 3679 3680 case FC_CMD_DETACH: 3681 FCP_DTRACE(fcp_logq, "fcp", 3682 fcp_trace, FCP_BUF_LEVEL_8, 0, 3683 "port detach called for port %d", instance); 3684 flag = FCP_STATE_DETACHING; 3685 break; 3686 3687 default: 3688 /* shouldn't happen */ 3689 return (FC_FAILURE); 3690 } 3691 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3692 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3693 3694 return (fcp_handle_port_detach(pptr, flag, instance)); 3695 } 3696 3697 3698 /* 3699 * called for ioctls on the transport's devctl interface, and the transport 3700 * has passed it to us 3701 * 3702 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3703 * 3704 * return FC_SUCCESS if we decide to claim the ioctl, 3705 * else return FC_UNCLAIMED 3706 * 3707 * *rval is set iff we decide to claim the ioctl 3708 */ 3709 /*ARGSUSED*/ 3710 static int 3711 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3712 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3713 { 3714 int retval = FC_UNCLAIMED; /* return value */ 3715 struct fcp_port *pptr = NULL; /* our soft state */ 3716 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3717 dev_info_t *cdip; 3718 mdi_pathinfo_t *pip = NULL; 3719 char *ndi_nm; /* NDI name */ 3720 char *ndi_addr; /* NDI addr */ 3721 int is_mpxio, circ; 3722 int devi_entered = 0; 3723 clock_t end_time; 3724 3725 ASSERT(rval != NULL); 3726 3727 FCP_DTRACE(fcp_logq, "fcp", 3728 fcp_trace, FCP_BUF_LEVEL_8, 0, 3729 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3730 3731 /* if already claimed then forget it */ 3732 if (claimed) { 3733 /* 3734 * for now, if this ioctl has already been claimed, then 3735 * we just ignore it 3736 */ 3737 return (retval); 3738 } 3739 3740 /* get our port info */ 3741 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3742 fcp_log(CE_WARN, NULL, 3743 "!fcp:Invalid port handle handle in ioctl"); 3744 *rval = ENXIO; 3745 return (retval); 3746 } 3747 is_mpxio = pptr->port_mpxio; 3748 3749 switch (cmd) { 3750 case DEVCTL_BUS_GETSTATE: 3751 case DEVCTL_BUS_QUIESCE: 3752 case DEVCTL_BUS_UNQUIESCE: 3753 case DEVCTL_BUS_RESET: 3754 case DEVCTL_BUS_RESETALL: 3755 3756 case DEVCTL_BUS_DEV_CREATE: 3757 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3758 return (retval); 3759 } 3760 break; 3761 3762 case DEVCTL_DEVICE_GETSTATE: 3763 case DEVCTL_DEVICE_OFFLINE: 3764 case DEVCTL_DEVICE_ONLINE: 3765 case DEVCTL_DEVICE_REMOVE: 3766 case DEVCTL_DEVICE_RESET: 3767 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3768 return (retval); 3769 } 3770 3771 ASSERT(dcp != NULL); 3772 3773 /* ensure we have a name and address */ 3774 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3775 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3776 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3777 fcp_trace, FCP_BUF_LEVEL_2, 0, 3778 "ioctl: can't get name (%s) or addr (%s)", 3779 ndi_nm ? ndi_nm : "<null ptr>", 3780 ndi_addr ? ndi_addr : "<null ptr>"); 3781 ndi_dc_freehdl(dcp); 3782 return (retval); 3783 } 3784 3785 3786 /* get our child's DIP */ 3787 ASSERT(pptr != NULL); 3788 if (is_mpxio) { 3789 mdi_devi_enter(pptr->port_dip, &circ); 3790 } else { 3791 ndi_devi_enter(pptr->port_dip, &circ); 3792 } 3793 devi_entered = 1; 3794 3795 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3796 ndi_addr)) == NULL) { 3797 /* Look for virtually enumerated devices. */ 3798 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3799 if (pip == NULL || 3800 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3801 *rval = ENXIO; 3802 goto out; 3803 } 3804 } 3805 break; 3806 3807 default: 3808 *rval = ENOTTY; 3809 return (retval); 3810 } 3811 3812 /* this ioctl is ours -- process it */ 3813 3814 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3815 3816 /* we assume it will be a success; else we'll set error value */ 3817 *rval = 0; 3818 3819 3820 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3821 fcp_trace, FCP_BUF_LEVEL_8, 0, 3822 "ioctl: claiming this one"); 3823 3824 /* handle ioctls now */ 3825 switch (cmd) { 3826 case DEVCTL_DEVICE_GETSTATE: 3827 ASSERT(cdip != NULL); 3828 ASSERT(dcp != NULL); 3829 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3830 *rval = EFAULT; 3831 } 3832 break; 3833 3834 case DEVCTL_DEVICE_REMOVE: 3835 case DEVCTL_DEVICE_OFFLINE: { 3836 int flag = 0; 3837 int lcount; 3838 int tcount; 3839 struct fcp_pkt *head = NULL; 3840 struct fcp_lun *plun; 3841 child_info_t *cip = CIP(cdip); 3842 int all = 1; 3843 struct fcp_lun *tplun; 3844 struct fcp_tgt *ptgt; 3845 3846 ASSERT(pptr != NULL); 3847 ASSERT(cdip != NULL); 3848 3849 mutex_enter(&pptr->port_mutex); 3850 if (pip != NULL) { 3851 cip = CIP(pip); 3852 } 3853 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3854 mutex_exit(&pptr->port_mutex); 3855 *rval = ENXIO; 3856 break; 3857 } 3858 3859 head = fcp_scan_commands(plun); 3860 if (head != NULL) { 3861 fcp_abort_commands(head, LUN_PORT); 3862 } 3863 lcount = pptr->port_link_cnt; 3864 tcount = plun->lun_tgt->tgt_change_cnt; 3865 mutex_exit(&pptr->port_mutex); 3866 3867 if (cmd == DEVCTL_DEVICE_REMOVE) { 3868 flag = NDI_DEVI_REMOVE; 3869 } 3870 3871 if (is_mpxio) { 3872 mdi_devi_exit(pptr->port_dip, circ); 3873 } else { 3874 ndi_devi_exit(pptr->port_dip, circ); 3875 } 3876 devi_entered = 0; 3877 3878 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3879 FCP_OFFLINE, lcount, tcount, flag); 3880 3881 if (*rval != NDI_SUCCESS) { 3882 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3883 break; 3884 } 3885 3886 fcp_update_offline_flags(plun); 3887 3888 ptgt = plun->lun_tgt; 3889 mutex_enter(&ptgt->tgt_mutex); 3890 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3891 tplun->lun_next) { 3892 mutex_enter(&tplun->lun_mutex); 3893 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3894 all = 0; 3895 } 3896 mutex_exit(&tplun->lun_mutex); 3897 } 3898 3899 if (all) { 3900 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3901 /* 3902 * The user is unconfiguring/offlining the device. 3903 * If fabric and the auto configuration is set 3904 * then make sure the user is the only one who 3905 * can reconfigure the device. 3906 */ 3907 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3908 fcp_enable_auto_configuration) { 3909 ptgt->tgt_manual_config_only = 1; 3910 } 3911 } 3912 mutex_exit(&ptgt->tgt_mutex); 3913 break; 3914 } 3915 3916 case DEVCTL_DEVICE_ONLINE: { 3917 int lcount; 3918 int tcount; 3919 struct fcp_lun *plun; 3920 child_info_t *cip = CIP(cdip); 3921 3922 ASSERT(cdip != NULL); 3923 ASSERT(pptr != NULL); 3924 3925 mutex_enter(&pptr->port_mutex); 3926 if (pip != NULL) { 3927 cip = CIP(pip); 3928 } 3929 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3930 mutex_exit(&pptr->port_mutex); 3931 *rval = ENXIO; 3932 break; 3933 } 3934 lcount = pptr->port_link_cnt; 3935 tcount = plun->lun_tgt->tgt_change_cnt; 3936 mutex_exit(&pptr->port_mutex); 3937 3938 /* 3939 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3940 * to allow the device attach to occur when the device is 3941 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3942 * from the scsi_probe()). 3943 */ 3944 mutex_enter(&LUN_TGT->tgt_mutex); 3945 plun->lun_state |= FCP_LUN_ONLINING; 3946 mutex_exit(&LUN_TGT->tgt_mutex); 3947 3948 if (is_mpxio) { 3949 mdi_devi_exit(pptr->port_dip, circ); 3950 } else { 3951 ndi_devi_exit(pptr->port_dip, circ); 3952 } 3953 devi_entered = 0; 3954 3955 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3956 FCP_ONLINE, lcount, tcount, 0); 3957 3958 if (*rval != NDI_SUCCESS) { 3959 /* Reset the FCP_LUN_ONLINING bit */ 3960 mutex_enter(&LUN_TGT->tgt_mutex); 3961 plun->lun_state &= ~FCP_LUN_ONLINING; 3962 mutex_exit(&LUN_TGT->tgt_mutex); 3963 *rval = EIO; 3964 break; 3965 } 3966 mutex_enter(&LUN_TGT->tgt_mutex); 3967 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3968 FCP_LUN_ONLINING); 3969 mutex_exit(&LUN_TGT->tgt_mutex); 3970 break; 3971 } 3972 3973 case DEVCTL_BUS_DEV_CREATE: { 3974 uchar_t *bytes = NULL; 3975 uint_t nbytes; 3976 struct fcp_tgt *ptgt = NULL; 3977 struct fcp_lun *plun = NULL; 3978 dev_info_t *useless_dip = NULL; 3979 3980 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3981 DEVCTL_CONSTRUCT, &useless_dip); 3982 if (*rval != 0 || useless_dip == NULL) { 3983 break; 3984 } 3985 3986 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3987 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3988 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3989 *rval = EINVAL; 3990 (void) ndi_devi_free(useless_dip); 3991 if (bytes != NULL) { 3992 ddi_prop_free(bytes); 3993 } 3994 break; 3995 } 3996 3997 *rval = fcp_create_on_demand(pptr, bytes); 3998 if (*rval == 0) { 3999 mutex_enter(&pptr->port_mutex); 4000 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 4001 if (ptgt) { 4002 /* 4003 * We now have a pointer to the target that 4004 * was created. Lets point to the first LUN on 4005 * this new target. 4006 */ 4007 mutex_enter(&ptgt->tgt_mutex); 4008 4009 plun = ptgt->tgt_lun; 4010 /* 4011 * There may be stale/offline LUN entries on 4012 * this list (this is by design) and so we have 4013 * to make sure we point to the first online 4014 * LUN 4015 */ 4016 while (plun && 4017 plun->lun_state & FCP_LUN_OFFLINE) { 4018 plun = plun->lun_next; 4019 } 4020 4021 mutex_exit(&ptgt->tgt_mutex); 4022 } 4023 mutex_exit(&pptr->port_mutex); 4024 } 4025 4026 if (*rval == 0 && ptgt && plun) { 4027 mutex_enter(&plun->lun_mutex); 4028 /* 4029 * Allow up to fcp_lun_ready_retry seconds to 4030 * configure all the luns behind the target. 4031 * 4032 * The intent here is to allow targets with long 4033 * reboot/reset-recovery times to become available 4034 * while limiting the maximum wait time for an 4035 * unresponsive target. 4036 */ 4037 end_time = ddi_get_lbolt() + 4038 SEC_TO_TICK(fcp_lun_ready_retry); 4039 4040 while (ddi_get_lbolt() < end_time) { 4041 retval = FC_SUCCESS; 4042 4043 /* 4044 * The new ndi interfaces for on-demand creation 4045 * are inflexible, Do some more work to pass on 4046 * a path name of some LUN (design is broken !) 4047 */ 4048 if (plun->lun_cip) { 4049 if (plun->lun_mpxio == 0) { 4050 cdip = DIP(plun->lun_cip); 4051 } else { 4052 cdip = mdi_pi_get_client( 4053 PIP(plun->lun_cip)); 4054 } 4055 if (cdip == NULL) { 4056 *rval = ENXIO; 4057 break; 4058 } 4059 4060 if (!i_ddi_devi_attached(cdip)) { 4061 mutex_exit(&plun->lun_mutex); 4062 delay(drv_usectohz(1000000)); 4063 mutex_enter(&plun->lun_mutex); 4064 } else { 4065 /* 4066 * This Lun is ready, lets 4067 * check the next one. 4068 */ 4069 mutex_exit(&plun->lun_mutex); 4070 plun = plun->lun_next; 4071 while (plun && (plun->lun_state 4072 & FCP_LUN_OFFLINE)) { 4073 plun = plun->lun_next; 4074 } 4075 if (!plun) { 4076 break; 4077 } 4078 mutex_enter(&plun->lun_mutex); 4079 } 4080 } else { 4081 /* 4082 * lun_cip field for a valid lun 4083 * should never be NULL. Fail the 4084 * command. 4085 */ 4086 *rval = ENXIO; 4087 break; 4088 } 4089 } 4090 if (plun) { 4091 mutex_exit(&plun->lun_mutex); 4092 } else { 4093 char devnm[MAXNAMELEN]; 4094 int nmlen; 4095 4096 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4097 ddi_node_name(cdip), 4098 ddi_get_name_addr(cdip)); 4099 4100 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4101 0) { 4102 *rval = EFAULT; 4103 } 4104 } 4105 } else { 4106 int i; 4107 char buf[25]; 4108 4109 for (i = 0; i < FC_WWN_SIZE; i++) { 4110 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4111 } 4112 4113 fcp_log(CE_WARN, pptr->port_dip, 4114 "!Failed to create nodes for pwwn=%s; error=%x", 4115 buf, *rval); 4116 } 4117 4118 (void) ndi_devi_free(useless_dip); 4119 ddi_prop_free(bytes); 4120 break; 4121 } 4122 4123 case DEVCTL_DEVICE_RESET: { 4124 struct fcp_lun *plun; 4125 child_info_t *cip = CIP(cdip); 4126 4127 ASSERT(cdip != NULL); 4128 ASSERT(pptr != NULL); 4129 mutex_enter(&pptr->port_mutex); 4130 if (pip != NULL) { 4131 cip = CIP(pip); 4132 } 4133 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4134 mutex_exit(&pptr->port_mutex); 4135 *rval = ENXIO; 4136 break; 4137 } 4138 mutex_exit(&pptr->port_mutex); 4139 4140 mutex_enter(&plun->lun_tgt->tgt_mutex); 4141 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4142 mutex_exit(&plun->lun_tgt->tgt_mutex); 4143 4144 *rval = ENXIO; 4145 break; 4146 } 4147 4148 if (plun->lun_sd == NULL) { 4149 mutex_exit(&plun->lun_tgt->tgt_mutex); 4150 4151 *rval = ENXIO; 4152 break; 4153 } 4154 mutex_exit(&plun->lun_tgt->tgt_mutex); 4155 4156 /* 4157 * set up ap so that fcp_reset can figure out 4158 * which target to reset 4159 */ 4160 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4161 RESET_TARGET) == FALSE) { 4162 *rval = EIO; 4163 } 4164 break; 4165 } 4166 4167 case DEVCTL_BUS_GETSTATE: 4168 ASSERT(dcp != NULL); 4169 ASSERT(pptr != NULL); 4170 ASSERT(pptr->port_dip != NULL); 4171 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4172 NDI_SUCCESS) { 4173 *rval = EFAULT; 4174 } 4175 break; 4176 4177 case DEVCTL_BUS_QUIESCE: 4178 case DEVCTL_BUS_UNQUIESCE: 4179 *rval = ENOTSUP; 4180 break; 4181 4182 case DEVCTL_BUS_RESET: 4183 case DEVCTL_BUS_RESETALL: 4184 ASSERT(pptr != NULL); 4185 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4186 break; 4187 4188 default: 4189 ASSERT(dcp != NULL); 4190 *rval = ENOTTY; 4191 break; 4192 } 4193 4194 /* all done -- clean up and return */ 4195 out: if (devi_entered) { 4196 if (is_mpxio) { 4197 mdi_devi_exit(pptr->port_dip, circ); 4198 } else { 4199 ndi_devi_exit(pptr->port_dip, circ); 4200 } 4201 } 4202 4203 if (dcp != NULL) { 4204 ndi_dc_freehdl(dcp); 4205 } 4206 4207 return (retval); 4208 } 4209 4210 4211 /*ARGSUSED*/ 4212 static int 4213 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4214 uint32_t claimed) 4215 { 4216 uchar_t r_ctl; 4217 uchar_t ls_code; 4218 struct fcp_port *pptr; 4219 4220 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4221 return (FC_UNCLAIMED); 4222 } 4223 4224 mutex_enter(&pptr->port_mutex); 4225 if (pptr->port_state & (FCP_STATE_DETACHING | 4226 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4227 mutex_exit(&pptr->port_mutex); 4228 return (FC_UNCLAIMED); 4229 } 4230 mutex_exit(&pptr->port_mutex); 4231 4232 r_ctl = buf->ub_frame.r_ctl; 4233 4234 switch (r_ctl & R_CTL_ROUTING) { 4235 case R_CTL_EXTENDED_SVC: 4236 if (r_ctl == R_CTL_ELS_REQ) { 4237 ls_code = buf->ub_buffer[0]; 4238 4239 switch (ls_code) { 4240 case LA_ELS_PRLI: 4241 /* 4242 * We really don't care if something fails. 4243 * If the PRLI was not sent out, then the 4244 * other end will time it out. 4245 */ 4246 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4247 return (FC_SUCCESS); 4248 } 4249 return (FC_UNCLAIMED); 4250 /* NOTREACHED */ 4251 4252 default: 4253 break; 4254 } 4255 } 4256 /* FALLTHROUGH */ 4257 4258 default: 4259 return (FC_UNCLAIMED); 4260 } 4261 } 4262 4263 4264 /*ARGSUSED*/ 4265 static int 4266 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4267 uint32_t claimed) 4268 { 4269 return (FC_UNCLAIMED); 4270 } 4271 4272 /* 4273 * Function: fcp_statec_callback 4274 * 4275 * Description: The purpose of this function is to handle a port state change. 4276 * It is called from fp/fctl and, in a few instances, internally. 4277 * 4278 * Argument: ulph fp/fctl port handle 4279 * port_handle fcp_port structure 4280 * port_state Physical state of the port 4281 * port_top Topology 4282 * *devlist Pointer to the first entry of a table 4283 * containing the remote ports that can be 4284 * reached. 4285 * dev_cnt Number of entries pointed by devlist. 4286 * port_sid Port ID of the local port. 4287 * 4288 * Return Value: None 4289 */ 4290 /*ARGSUSED*/ 4291 static void 4292 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4293 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4294 uint32_t dev_cnt, uint32_t port_sid) 4295 { 4296 uint32_t link_count; 4297 int map_len = 0; 4298 struct fcp_port *pptr; 4299 fcp_map_tag_t *map_tag = NULL; 4300 4301 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4302 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4303 return; /* nothing to work with! */ 4304 } 4305 4306 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4307 fcp_trace, FCP_BUF_LEVEL_2, 0, 4308 "fcp_statec_callback: port state/dev_cnt/top =" 4309 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4310 dev_cnt, port_top); 4311 4312 mutex_enter(&pptr->port_mutex); 4313 4314 /* 4315 * If a thread is in detach, don't do anything. 4316 */ 4317 if (pptr->port_state & (FCP_STATE_DETACHING | 4318 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4319 mutex_exit(&pptr->port_mutex); 4320 return; 4321 } 4322 4323 /* 4324 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4325 * init_pkt is called, it knows whether or not the target's status 4326 * (or pd) might be changing. 4327 */ 4328 4329 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4330 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4331 } 4332 4333 /* 4334 * the transport doesn't allocate or probe unless being 4335 * asked to by either the applications or ULPs 4336 * 4337 * in cases where the port is OFFLINE at the time of port 4338 * attach callback and the link comes ONLINE later, for 4339 * easier automatic node creation (i.e. without you having to 4340 * go out and run the utility to perform LOGINs) the 4341 * following conditional is helpful 4342 */ 4343 pptr->port_phys_state = port_state; 4344 4345 if (dev_cnt) { 4346 mutex_exit(&pptr->port_mutex); 4347 4348 map_len = sizeof (*map_tag) * dev_cnt; 4349 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4350 if (map_tag == NULL) { 4351 fcp_log(CE_WARN, pptr->port_dip, 4352 "!fcp%d: failed to allocate for map tags; " 4353 " state change will not be processed", 4354 pptr->port_instance); 4355 4356 mutex_enter(&pptr->port_mutex); 4357 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4358 mutex_exit(&pptr->port_mutex); 4359 4360 return; 4361 } 4362 4363 mutex_enter(&pptr->port_mutex); 4364 } 4365 4366 if (pptr->port_id != port_sid) { 4367 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4368 fcp_trace, FCP_BUF_LEVEL_3, 0, 4369 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4370 port_sid); 4371 /* 4372 * The local port changed ID. It is the first time a port ID 4373 * is assigned or something drastic happened. We might have 4374 * been unplugged and replugged on another loop or fabric port 4375 * or somebody grabbed the AL_PA we had or somebody rezoned 4376 * the fabric we were plugged into. 4377 */ 4378 pptr->port_id = port_sid; 4379 } 4380 4381 switch (FC_PORT_STATE_MASK(port_state)) { 4382 case FC_STATE_OFFLINE: 4383 case FC_STATE_RESET_REQUESTED: 4384 /* 4385 * link has gone from online to offline -- just update the 4386 * state of this port to BUSY and MARKed to go offline 4387 */ 4388 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4389 fcp_trace, FCP_BUF_LEVEL_3, 0, 4390 "link went offline"); 4391 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4392 /* 4393 * We were offline a while ago and this one 4394 * seems to indicate that the loop has gone 4395 * dead forever. 4396 */ 4397 pptr->port_tmp_cnt += dev_cnt; 4398 pptr->port_state &= ~FCP_STATE_OFFLINE; 4399 pptr->port_state |= FCP_STATE_INIT; 4400 link_count = pptr->port_link_cnt; 4401 fcp_handle_devices(pptr, devlist, dev_cnt, 4402 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4403 } else { 4404 pptr->port_link_cnt++; 4405 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4406 fcp_update_state(pptr, (FCP_LUN_BUSY | 4407 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4408 if (pptr->port_mpxio) { 4409 fcp_update_mpxio_path_verifybusy(pptr); 4410 } 4411 pptr->port_state |= FCP_STATE_OFFLINE; 4412 pptr->port_state &= 4413 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4414 pptr->port_tmp_cnt = 0; 4415 } 4416 mutex_exit(&pptr->port_mutex); 4417 break; 4418 4419 case FC_STATE_ONLINE: 4420 case FC_STATE_LIP: 4421 case FC_STATE_LIP_LBIT_SET: 4422 /* 4423 * link has gone from offline to online 4424 */ 4425 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4426 fcp_trace, FCP_BUF_LEVEL_3, 0, 4427 "link went online"); 4428 4429 pptr->port_link_cnt++; 4430 4431 while (pptr->port_ipkt_cnt) { 4432 mutex_exit(&pptr->port_mutex); 4433 delay(drv_usectohz(1000000)); 4434 mutex_enter(&pptr->port_mutex); 4435 } 4436 4437 pptr->port_topology = port_top; 4438 4439 /* 4440 * The state of the targets and luns accessible through this 4441 * port is updated. 4442 */ 4443 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4444 FCP_CAUSE_LINK_CHANGE); 4445 4446 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4447 pptr->port_state |= FCP_STATE_ONLINING; 4448 pptr->port_tmp_cnt = dev_cnt; 4449 link_count = pptr->port_link_cnt; 4450 4451 pptr->port_deadline = fcp_watchdog_time + 4452 FCP_ICMD_DEADLINE; 4453 4454 if (!dev_cnt) { 4455 /* 4456 * We go directly to the online state if no remote 4457 * ports were discovered. 4458 */ 4459 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4460 fcp_trace, FCP_BUF_LEVEL_3, 0, 4461 "No remote ports discovered"); 4462 4463 pptr->port_state &= ~FCP_STATE_ONLINING; 4464 pptr->port_state |= FCP_STATE_ONLINE; 4465 } 4466 4467 switch (port_top) { 4468 case FC_TOP_FABRIC: 4469 case FC_TOP_PUBLIC_LOOP: 4470 case FC_TOP_PRIVATE_LOOP: 4471 case FC_TOP_PT_PT: 4472 4473 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4474 fcp_retry_ns_registry(pptr, port_sid); 4475 } 4476 4477 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4478 map_tag, FCP_CAUSE_LINK_CHANGE); 4479 break; 4480 4481 default: 4482 /* 4483 * We got here because we were provided with an unknown 4484 * topology. 4485 */ 4486 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4487 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4488 } 4489 4490 pptr->port_tmp_cnt -= dev_cnt; 4491 fcp_log(CE_WARN, pptr->port_dip, 4492 "!unknown/unsupported topology (0x%x)", port_top); 4493 break; 4494 } 4495 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4496 fcp_trace, FCP_BUF_LEVEL_3, 0, 4497 "Notify ssd of the reset to reinstate the reservations"); 4498 4499 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4500 &pptr->port_reset_notify_listf); 4501 4502 mutex_exit(&pptr->port_mutex); 4503 4504 break; 4505 4506 case FC_STATE_RESET: 4507 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4508 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4509 fcp_trace, FCP_BUF_LEVEL_3, 0, 4510 "RESET state, waiting for Offline/Online state_cb"); 4511 mutex_exit(&pptr->port_mutex); 4512 break; 4513 4514 case FC_STATE_DEVICE_CHANGE: 4515 /* 4516 * We come here when an application has requested 4517 * Dynamic node creation/deletion in Fabric connectivity. 4518 */ 4519 if (pptr->port_state & (FCP_STATE_OFFLINE | 4520 FCP_STATE_INIT)) { 4521 /* 4522 * This case can happen when the FCTL is in the 4523 * process of giving us on online and the host on 4524 * the other side issues a PLOGI/PLOGO. Ideally 4525 * the state changes should be serialized unless 4526 * they are opposite (online-offline). 4527 * The transport will give us a final state change 4528 * so we can ignore this for the time being. 4529 */ 4530 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4531 mutex_exit(&pptr->port_mutex); 4532 break; 4533 } 4534 4535 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4536 fcp_retry_ns_registry(pptr, port_sid); 4537 } 4538 4539 /* 4540 * Extend the deadline under steady state conditions 4541 * to provide more time for the device-change-commands 4542 */ 4543 if (!pptr->port_ipkt_cnt) { 4544 pptr->port_deadline = fcp_watchdog_time + 4545 FCP_ICMD_DEADLINE; 4546 } 4547 4548 /* 4549 * There is another race condition here, where if we were 4550 * in ONLINEING state and a devices in the map logs out, 4551 * fp will give another state change as DEVICE_CHANGE 4552 * and OLD. This will result in that target being offlined. 4553 * The pd_handle is freed. If from the first statec callback 4554 * we were going to fire a PLOGI/PRLI, the system will 4555 * panic in fc_ulp_transport with invalid pd_handle. 4556 * The fix is to check for the link_cnt before issuing 4557 * any command down. 4558 */ 4559 fcp_update_targets(pptr, devlist, dev_cnt, 4560 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4561 4562 link_count = pptr->port_link_cnt; 4563 4564 fcp_handle_devices(pptr, devlist, dev_cnt, 4565 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4566 4567 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4568 4569 mutex_exit(&pptr->port_mutex); 4570 break; 4571 4572 case FC_STATE_TARGET_PORT_RESET: 4573 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4574 fcp_retry_ns_registry(pptr, port_sid); 4575 } 4576 4577 /* Do nothing else */ 4578 mutex_exit(&pptr->port_mutex); 4579 break; 4580 4581 default: 4582 fcp_log(CE_WARN, pptr->port_dip, 4583 "!Invalid state change=0x%x", port_state); 4584 mutex_exit(&pptr->port_mutex); 4585 break; 4586 } 4587 4588 if (map_tag) { 4589 kmem_free(map_tag, map_len); 4590 } 4591 } 4592 4593 /* 4594 * Function: fcp_handle_devices 4595 * 4596 * Description: This function updates the devices currently known by 4597 * walking the list provided by the caller. The list passed 4598 * by the caller is supposed to be the list of reachable 4599 * devices. 4600 * 4601 * Argument: *pptr Fcp port structure. 4602 * *devlist Pointer to the first entry of a table 4603 * containing the remote ports that can be 4604 * reached. 4605 * dev_cnt Number of entries pointed by devlist. 4606 * link_cnt Link state count. 4607 * *map_tag Array of fcp_map_tag_t structures. 4608 * cause What caused this function to be called. 4609 * 4610 * Return Value: None 4611 * 4612 * Notes: The pptr->port_mutex must be held. 4613 */ 4614 static void 4615 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4616 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4617 { 4618 int i; 4619 int check_finish_init = 0; 4620 fc_portmap_t *map_entry; 4621 struct fcp_tgt *ptgt = NULL; 4622 4623 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4624 fcp_trace, FCP_BUF_LEVEL_3, 0, 4625 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4626 4627 if (dev_cnt) { 4628 ASSERT(map_tag != NULL); 4629 } 4630 4631 /* 4632 * The following code goes through the list of remote ports that are 4633 * accessible through this (pptr) local port (The list walked is the 4634 * one provided by the caller which is the list of the remote ports 4635 * currently reachable). It checks if any of them was already 4636 * known by looking for the corresponding target structure based on 4637 * the world wide name. If a target is part of the list it is tagged 4638 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4639 * 4640 * Old comment 4641 * ----------- 4642 * Before we drop port mutex; we MUST get the tags updated; This 4643 * two step process is somewhat slow, but more reliable. 4644 */ 4645 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4646 map_entry = &(devlist[i]); 4647 4648 /* 4649 * get ptr to this map entry in our port's 4650 * list (if any) 4651 */ 4652 ptgt = fcp_lookup_target(pptr, 4653 (uchar_t *)&(map_entry->map_pwwn)); 4654 4655 if (ptgt) { 4656 map_tag[i] = ptgt->tgt_change_cnt; 4657 if (cause == FCP_CAUSE_LINK_CHANGE) { 4658 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4659 } 4660 } 4661 } 4662 4663 /* 4664 * At this point we know which devices of the new list were already 4665 * known (The field tgt_aux_state of the target structure has been 4666 * set to FCP_TGT_TAGGED). 4667 * 4668 * The following code goes through the list of targets currently known 4669 * by the local port (the list is actually a hashing table). If a 4670 * target is found and is not tagged, it means the target cannot 4671 * be reached anymore through the local port (pptr). It is offlined. 4672 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4673 */ 4674 for (i = 0; i < FCP_NUM_HASH; i++) { 4675 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4676 ptgt = ptgt->tgt_next) { 4677 mutex_enter(&ptgt->tgt_mutex); 4678 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4679 (cause == FCP_CAUSE_LINK_CHANGE) && 4680 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4681 fcp_offline_target_now(pptr, ptgt, 4682 link_cnt, ptgt->tgt_change_cnt, 0); 4683 } 4684 mutex_exit(&ptgt->tgt_mutex); 4685 } 4686 } 4687 4688 /* 4689 * At this point, the devices that were known but cannot be reached 4690 * anymore, have most likely been offlined. 4691 * 4692 * The following section of code seems to go through the list of 4693 * remote ports that can now be reached. For every single one it 4694 * checks if it is already known or if it is a new port. 4695 */ 4696 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4697 4698 if (check_finish_init) { 4699 ASSERT(i > 0); 4700 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4701 map_tag[i - 1], cause); 4702 check_finish_init = 0; 4703 } 4704 4705 /* get a pointer to this map entry */ 4706 map_entry = &(devlist[i]); 4707 4708 /* 4709 * Check for the duplicate map entry flag. If we have marked 4710 * this entry as a duplicate we skip it since the correct 4711 * (perhaps even same) state change will be encountered 4712 * later in the list. 4713 */ 4714 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4715 continue; 4716 } 4717 4718 /* get ptr to this map entry in our port's list (if any) */ 4719 ptgt = fcp_lookup_target(pptr, 4720 (uchar_t *)&(map_entry->map_pwwn)); 4721 4722 if (ptgt) { 4723 /* 4724 * This device was already known. The field 4725 * tgt_aux_state is reset (was probably set to 4726 * FCP_TGT_TAGGED previously in this routine). 4727 */ 4728 ptgt->tgt_aux_state = 0; 4729 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4730 fcp_trace, FCP_BUF_LEVEL_3, 0, 4731 "handle_devices: map did/state/type/flags = " 4732 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4733 "tgt_state=%d", 4734 map_entry->map_did.port_id, map_entry->map_state, 4735 map_entry->map_type, map_entry->map_flags, 4736 ptgt->tgt_d_id, ptgt->tgt_state); 4737 } 4738 4739 if (map_entry->map_type == PORT_DEVICE_OLD || 4740 map_entry->map_type == PORT_DEVICE_NEW || 4741 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4742 map_entry->map_type == PORT_DEVICE_CHANGED) { 4743 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4744 fcp_trace, FCP_BUF_LEVEL_2, 0, 4745 "map_type=%x, did = %x", 4746 map_entry->map_type, 4747 map_entry->map_did.port_id); 4748 } 4749 4750 switch (map_entry->map_type) { 4751 case PORT_DEVICE_NOCHANGE: 4752 case PORT_DEVICE_USER_CREATE: 4753 case PORT_DEVICE_USER_LOGIN: 4754 case PORT_DEVICE_NEW: 4755 case PORT_DEVICE_REPORTLUN_CHANGED: 4756 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4757 4758 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4759 link_cnt, (ptgt) ? map_tag[i] : 0, 4760 cause) == TRUE) { 4761 4762 FCP_TGT_TRACE(ptgt, map_tag[i], 4763 FCP_TGT_TRACE_2); 4764 check_finish_init++; 4765 } 4766 break; 4767 4768 case PORT_DEVICE_OLD: 4769 if (ptgt != NULL) { 4770 FCP_TGT_TRACE(ptgt, map_tag[i], 4771 FCP_TGT_TRACE_3); 4772 4773 mutex_enter(&ptgt->tgt_mutex); 4774 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4775 /* 4776 * Must do an in-line wait for I/Os 4777 * to get drained 4778 */ 4779 mutex_exit(&ptgt->tgt_mutex); 4780 mutex_exit(&pptr->port_mutex); 4781 4782 mutex_enter(&ptgt->tgt_mutex); 4783 while (ptgt->tgt_ipkt_cnt || 4784 fcp_outstanding_lun_cmds(ptgt) 4785 == FC_SUCCESS) { 4786 mutex_exit(&ptgt->tgt_mutex); 4787 delay(drv_usectohz(1000000)); 4788 mutex_enter(&ptgt->tgt_mutex); 4789 } 4790 mutex_exit(&ptgt->tgt_mutex); 4791 4792 mutex_enter(&pptr->port_mutex); 4793 mutex_enter(&ptgt->tgt_mutex); 4794 4795 (void) fcp_offline_target(pptr, ptgt, 4796 link_cnt, map_tag[i], 0, 0); 4797 } 4798 mutex_exit(&ptgt->tgt_mutex); 4799 } 4800 check_finish_init++; 4801 break; 4802 4803 case PORT_DEVICE_USER_DELETE: 4804 case PORT_DEVICE_USER_LOGOUT: 4805 if (ptgt != NULL) { 4806 FCP_TGT_TRACE(ptgt, map_tag[i], 4807 FCP_TGT_TRACE_4); 4808 4809 mutex_enter(&ptgt->tgt_mutex); 4810 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4811 (void) fcp_offline_target(pptr, ptgt, 4812 link_cnt, map_tag[i], 1, 0); 4813 } 4814 mutex_exit(&ptgt->tgt_mutex); 4815 } 4816 check_finish_init++; 4817 break; 4818 4819 case PORT_DEVICE_CHANGED: 4820 if (ptgt != NULL) { 4821 FCP_TGT_TRACE(ptgt, map_tag[i], 4822 FCP_TGT_TRACE_5); 4823 4824 if (fcp_device_changed(pptr, ptgt, 4825 map_entry, link_cnt, map_tag[i], 4826 cause) == TRUE) { 4827 check_finish_init++; 4828 } 4829 } else { 4830 if (fcp_handle_mapflags(pptr, ptgt, 4831 map_entry, link_cnt, 0, cause) == TRUE) { 4832 check_finish_init++; 4833 } 4834 } 4835 break; 4836 4837 default: 4838 fcp_log(CE_WARN, pptr->port_dip, 4839 "!Invalid map_type=0x%x", map_entry->map_type); 4840 check_finish_init++; 4841 break; 4842 } 4843 } 4844 4845 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4846 ASSERT(i > 0); 4847 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4848 map_tag[i-1], cause); 4849 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4850 fcp_offline_all(pptr, link_cnt, cause); 4851 } 4852 } 4853 4854 static int 4855 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4856 { 4857 struct fcp_lun *plun; 4858 struct fcp_port *pptr; 4859 int rscn_count; 4860 int lun0_newalloc; 4861 int ret = TRUE; 4862 4863 ASSERT(ptgt); 4864 pptr = ptgt->tgt_port; 4865 lun0_newalloc = 0; 4866 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4867 /* 4868 * no LUN struct for LUN 0 yet exists, 4869 * so create one 4870 */ 4871 plun = fcp_alloc_lun(ptgt); 4872 if (plun == NULL) { 4873 fcp_log(CE_WARN, pptr->port_dip, 4874 "!Failed to allocate lun 0 for" 4875 " D_ID=%x", ptgt->tgt_d_id); 4876 return (ret); 4877 } 4878 lun0_newalloc = 1; 4879 } 4880 4881 mutex_enter(&ptgt->tgt_mutex); 4882 /* 4883 * consider lun 0 as device not connected if it is 4884 * offlined or newly allocated 4885 */ 4886 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4887 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4888 } 4889 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4890 plun->lun_state &= ~FCP_LUN_OFFLINE; 4891 ptgt->tgt_lun_cnt = 1; 4892 ptgt->tgt_report_lun_cnt = 0; 4893 mutex_exit(&ptgt->tgt_mutex); 4894 4895 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4896 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4897 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4898 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4899 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4900 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4901 "to D_ID=%x", ptgt->tgt_d_id); 4902 } else { 4903 ret = FALSE; 4904 } 4905 4906 return (ret); 4907 } 4908 4909 /* 4910 * Function: fcp_handle_mapflags 4911 * 4912 * Description: This function creates a target structure if the ptgt passed 4913 * is NULL. It also kicks off the PLOGI if we are not logged 4914 * into the target yet or the PRLI if we are logged into the 4915 * target already. The rest of the treatment is done in the 4916 * callbacks of the PLOGI or PRLI. 4917 * 4918 * Argument: *pptr FCP Port structure. 4919 * *ptgt Target structure. 4920 * *map_entry Array of fc_portmap_t structures. 4921 * link_cnt Link state count. 4922 * tgt_cnt Target state count. 4923 * cause What caused this function to be called. 4924 * 4925 * Return Value: TRUE Failed 4926 * FALSE Succeeded 4927 * 4928 * Notes: pptr->port_mutex must be owned. 4929 */ 4930 static int 4931 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4932 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4933 { 4934 int lcount; 4935 int tcount; 4936 int ret = TRUE; 4937 int alloc; 4938 struct fcp_ipkt *icmd; 4939 struct fcp_lun *pseq_lun = NULL; 4940 uchar_t opcode; 4941 int valid_ptgt_was_passed = FALSE; 4942 4943 ASSERT(mutex_owned(&pptr->port_mutex)); 4944 4945 /* 4946 * This case is possible where the FCTL has come up and done discovery 4947 * before FCP was loaded and attached. FCTL would have discovered the 4948 * devices and later the ULP came online. In this case ULP's would get 4949 * PORT_DEVICE_NOCHANGE but target would be NULL. 4950 */ 4951 if (ptgt == NULL) { 4952 /* don't already have a target */ 4953 mutex_exit(&pptr->port_mutex); 4954 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4955 mutex_enter(&pptr->port_mutex); 4956 4957 if (ptgt == NULL) { 4958 fcp_log(CE_WARN, pptr->port_dip, 4959 "!FC target allocation failed"); 4960 return (ret); 4961 } 4962 mutex_enter(&ptgt->tgt_mutex); 4963 ptgt->tgt_statec_cause = cause; 4964 ptgt->tgt_tmp_cnt = 1; 4965 mutex_exit(&ptgt->tgt_mutex); 4966 } else { 4967 valid_ptgt_was_passed = TRUE; 4968 } 4969 4970 /* 4971 * Copy in the target parameters 4972 */ 4973 mutex_enter(&ptgt->tgt_mutex); 4974 ptgt->tgt_d_id = map_entry->map_did.port_id; 4975 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4976 ptgt->tgt_pd_handle = map_entry->map_pd; 4977 ptgt->tgt_fca_dev = NULL; 4978 4979 /* Copy port and node WWNs */ 4980 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4981 FC_WWN_SIZE); 4982 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4983 FC_WWN_SIZE); 4984 4985 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4986 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4987 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4988 valid_ptgt_was_passed) { 4989 /* 4990 * determine if there are any tape LUNs on this target 4991 */ 4992 for (pseq_lun = ptgt->tgt_lun; 4993 pseq_lun != NULL; 4994 pseq_lun = pseq_lun->lun_next) { 4995 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4996 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4997 fcp_update_tgt_state(ptgt, FCP_RESET, 4998 FCP_LUN_MARK); 4999 mutex_exit(&ptgt->tgt_mutex); 5000 return (ret); 5001 } 5002 } 5003 } 5004 5005 /* 5006 * if UA'REPORT_LUN_CHANGED received, 5007 * send out REPORT LUN promptly, skip PLOGI/PRLI process 5008 */ 5009 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 5010 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 5011 mutex_exit(&ptgt->tgt_mutex); 5012 mutex_exit(&pptr->port_mutex); 5013 5014 ret = fcp_handle_reportlun_changed(ptgt, cause); 5015 5016 mutex_enter(&pptr->port_mutex); 5017 return (ret); 5018 } 5019 5020 /* 5021 * If ptgt was NULL when this function was entered, then tgt_node_state 5022 * was never specifically initialized but zeroed out which means 5023 * FCP_TGT_NODE_NONE. 5024 */ 5025 switch (ptgt->tgt_node_state) { 5026 case FCP_TGT_NODE_NONE: 5027 case FCP_TGT_NODE_ON_DEMAND: 5028 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5029 !fcp_enable_auto_configuration && 5030 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5031 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5032 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5033 fcp_enable_auto_configuration && 5034 (ptgt->tgt_manual_config_only == 1) && 5035 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5036 /* 5037 * If auto configuration is set and 5038 * the tgt_manual_config_only flag is set then 5039 * we only want the user to be able to change 5040 * the state through create_on_demand. 5041 */ 5042 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5043 } else { 5044 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5045 } 5046 break; 5047 5048 case FCP_TGT_NODE_PRESENT: 5049 break; 5050 } 5051 /* 5052 * If we are booting from a fabric device, make sure we 5053 * mark the node state appropriately for this target to be 5054 * enumerated 5055 */ 5056 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5057 if (bcmp((caddr_t)pptr->port_boot_wwn, 5058 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5059 sizeof (ptgt->tgt_port_wwn)) == 0) { 5060 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5061 } 5062 } 5063 mutex_exit(&ptgt->tgt_mutex); 5064 5065 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5066 fcp_trace, FCP_BUF_LEVEL_3, 0, 5067 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5068 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5069 map_entry->map_rscn_info.ulp_rscn_count); 5070 5071 mutex_enter(&ptgt->tgt_mutex); 5072 5073 /* 5074 * Reset target OFFLINE state and mark the target BUSY 5075 */ 5076 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5077 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5078 5079 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5080 lcount = link_cnt; 5081 5082 mutex_exit(&ptgt->tgt_mutex); 5083 mutex_exit(&pptr->port_mutex); 5084 5085 /* 5086 * if we are already logged in, then we do a PRLI, else 5087 * we do a PLOGI first (to get logged in) 5088 * 5089 * We will not check if we are the PLOGI initiator 5090 */ 5091 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5092 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5093 5094 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5095 5096 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5097 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5098 cause, map_entry->map_rscn_info.ulp_rscn_count); 5099 5100 if (icmd == NULL) { 5101 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5102 /* 5103 * We've exited port_mutex before calling fcp_icmd_alloc, 5104 * we need to make sure we reacquire it before returning. 5105 */ 5106 mutex_enter(&pptr->port_mutex); 5107 return (FALSE); 5108 } 5109 5110 /* TRUE is only returned while target is intended skipped */ 5111 ret = FALSE; 5112 /* discover info about this target */ 5113 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5114 lcount, tcount, cause)) == DDI_SUCCESS) { 5115 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5116 } else { 5117 fcp_icmd_free(pptr, icmd); 5118 ret = TRUE; 5119 } 5120 mutex_enter(&pptr->port_mutex); 5121 5122 return (ret); 5123 } 5124 5125 /* 5126 * Function: fcp_send_els 5127 * 5128 * Description: Sends an ELS to the target specified by the caller. Supports 5129 * PLOGI and PRLI. 5130 * 5131 * Argument: *pptr Fcp port. 5132 * *ptgt Target to send the ELS to. 5133 * *icmd Internal packet 5134 * opcode ELS opcode 5135 * lcount Link state change counter 5136 * tcount Target state change counter 5137 * cause What caused the call 5138 * 5139 * Return Value: DDI_SUCCESS 5140 * Others 5141 */ 5142 static int 5143 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5144 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5145 { 5146 fc_packet_t *fpkt; 5147 fc_frame_hdr_t *hp; 5148 int internal = 0; 5149 int alloc; 5150 int cmd_len; 5151 int resp_len; 5152 int res = DDI_FAILURE; /* default result */ 5153 int rval = DDI_FAILURE; 5154 5155 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5156 ASSERT(ptgt->tgt_port == pptr); 5157 5158 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5159 fcp_trace, FCP_BUF_LEVEL_5, 0, 5160 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5161 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5162 5163 if (opcode == LA_ELS_PLOGI) { 5164 cmd_len = sizeof (la_els_logi_t); 5165 resp_len = sizeof (la_els_logi_t); 5166 } else { 5167 ASSERT(opcode == LA_ELS_PRLI); 5168 cmd_len = sizeof (la_els_prli_t); 5169 resp_len = sizeof (la_els_prli_t); 5170 } 5171 5172 if (icmd == NULL) { 5173 alloc = FCP_MAX(sizeof (la_els_logi_t), 5174 sizeof (la_els_prli_t)); 5175 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5176 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5177 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5178 if (icmd == NULL) { 5179 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5180 return (res); 5181 } 5182 internal++; 5183 } 5184 fpkt = icmd->ipkt_fpkt; 5185 5186 fpkt->pkt_cmdlen = cmd_len; 5187 fpkt->pkt_rsplen = resp_len; 5188 fpkt->pkt_datalen = 0; 5189 icmd->ipkt_retries = 0; 5190 5191 /* fill in fpkt info */ 5192 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5193 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5194 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5195 5196 /* get ptr to frame hdr in fpkt */ 5197 hp = &fpkt->pkt_cmd_fhdr; 5198 5199 /* 5200 * fill in frame hdr 5201 */ 5202 hp->r_ctl = R_CTL_ELS_REQ; 5203 hp->s_id = pptr->port_id; /* source ID */ 5204 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5205 hp->type = FC_TYPE_EXTENDED_LS; 5206 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5207 hp->seq_id = 0; 5208 hp->rsvd = 0; 5209 hp->df_ctl = 0; 5210 hp->seq_cnt = 0; 5211 hp->ox_id = 0xffff; /* i.e. none */ 5212 hp->rx_id = 0xffff; /* i.e. none */ 5213 hp->ro = 0; 5214 5215 /* 5216 * at this point we have a filled in cmd pkt 5217 * 5218 * fill in the respective info, then use the transport to send 5219 * the packet 5220 * 5221 * for a PLOGI call fc_ulp_login(), and 5222 * for a PRLI call fc_ulp_issue_els() 5223 */ 5224 switch (opcode) { 5225 case LA_ELS_PLOGI: { 5226 struct la_els_logi logi; 5227 5228 bzero(&logi, sizeof (struct la_els_logi)); 5229 5230 hp = &fpkt->pkt_cmd_fhdr; 5231 hp->r_ctl = R_CTL_ELS_REQ; 5232 logi.ls_code.ls_code = LA_ELS_PLOGI; 5233 logi.ls_code.mbz = 0; 5234 5235 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5236 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5237 5238 icmd->ipkt_opcode = LA_ELS_PLOGI; 5239 5240 mutex_enter(&pptr->port_mutex); 5241 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5242 5243 mutex_exit(&pptr->port_mutex); 5244 5245 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5246 if (rval == FC_SUCCESS) { 5247 res = DDI_SUCCESS; 5248 break; 5249 } 5250 5251 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5252 5253 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5254 rval, "PLOGI"); 5255 } else { 5256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5257 fcp_trace, FCP_BUF_LEVEL_5, 0, 5258 "fcp_send_els1: state change occured" 5259 " for D_ID=0x%x", ptgt->tgt_d_id); 5260 mutex_exit(&pptr->port_mutex); 5261 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5262 } 5263 break; 5264 } 5265 5266 case LA_ELS_PRLI: { 5267 struct la_els_prli prli; 5268 struct fcp_prli *fprli; 5269 5270 bzero(&prli, sizeof (struct la_els_prli)); 5271 5272 hp = &fpkt->pkt_cmd_fhdr; 5273 hp->r_ctl = R_CTL_ELS_REQ; 5274 5275 /* fill in PRLI cmd ELS fields */ 5276 prli.ls_code = LA_ELS_PRLI; 5277 prli.page_length = 0x10; /* huh? */ 5278 prli.payload_length = sizeof (struct la_els_prli); 5279 5280 icmd->ipkt_opcode = LA_ELS_PRLI; 5281 5282 /* get ptr to PRLI service params */ 5283 fprli = (struct fcp_prli *)prli.service_params; 5284 5285 /* fill in service params */ 5286 fprli->type = 0x08; 5287 fprli->resvd1 = 0; 5288 fprli->orig_process_assoc_valid = 0; 5289 fprli->resp_process_assoc_valid = 0; 5290 fprli->establish_image_pair = 1; 5291 fprli->resvd2 = 0; 5292 fprli->resvd3 = 0; 5293 fprli->obsolete_1 = 0; 5294 fprli->obsolete_2 = 0; 5295 fprli->data_overlay_allowed = 0; 5296 fprli->initiator_fn = 1; 5297 fprli->confirmed_compl_allowed = 1; 5298 5299 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5300 fprli->target_fn = 1; 5301 } else { 5302 fprli->target_fn = 0; 5303 } 5304 5305 fprli->retry = 1; 5306 fprli->read_xfer_rdy_disabled = 1; 5307 fprli->write_xfer_rdy_disabled = 0; 5308 5309 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5310 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5311 5312 /* issue the PRLI request */ 5313 5314 mutex_enter(&pptr->port_mutex); 5315 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5316 5317 mutex_exit(&pptr->port_mutex); 5318 5319 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5320 if (rval == FC_SUCCESS) { 5321 res = DDI_SUCCESS; 5322 break; 5323 } 5324 5325 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5326 5327 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5328 rval, "PRLI"); 5329 } else { 5330 mutex_exit(&pptr->port_mutex); 5331 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5332 } 5333 break; 5334 } 5335 5336 default: 5337 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5338 break; 5339 } 5340 5341 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5342 fcp_trace, FCP_BUF_LEVEL_5, 0, 5343 "fcp_send_els: returning %d", res); 5344 5345 if (res != DDI_SUCCESS) { 5346 if (internal) { 5347 fcp_icmd_free(pptr, icmd); 5348 } 5349 } 5350 5351 return (res); 5352 } 5353 5354 5355 /* 5356 * called internally update the state of all of the tgts and each LUN 5357 * for this port (i.e. each target known to be attached to this port) 5358 * if they are not already offline 5359 * 5360 * must be called with the port mutex owned 5361 * 5362 * acquires and releases the target mutexes for each target attached 5363 * to this port 5364 */ 5365 void 5366 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5367 { 5368 int i; 5369 struct fcp_tgt *ptgt; 5370 5371 ASSERT(mutex_owned(&pptr->port_mutex)); 5372 5373 for (i = 0; i < FCP_NUM_HASH; i++) { 5374 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5375 ptgt = ptgt->tgt_next) { 5376 mutex_enter(&ptgt->tgt_mutex); 5377 fcp_update_tgt_state(ptgt, FCP_SET, state); 5378 ptgt->tgt_change_cnt++; 5379 ptgt->tgt_statec_cause = cause; 5380 ptgt->tgt_tmp_cnt = 1; 5381 ptgt->tgt_done = 0; 5382 mutex_exit(&ptgt->tgt_mutex); 5383 } 5384 } 5385 } 5386 5387 5388 static void 5389 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5390 { 5391 int i; 5392 int ndevs; 5393 struct fcp_tgt *ptgt; 5394 5395 ASSERT(mutex_owned(&pptr->port_mutex)); 5396 5397 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5398 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5399 ptgt = ptgt->tgt_next) { 5400 ndevs++; 5401 } 5402 } 5403 5404 if (ndevs == 0) { 5405 return; 5406 } 5407 pptr->port_tmp_cnt = ndevs; 5408 5409 for (i = 0; i < FCP_NUM_HASH; i++) { 5410 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5411 ptgt = ptgt->tgt_next) { 5412 (void) fcp_call_finish_init_held(pptr, ptgt, 5413 lcount, ptgt->tgt_change_cnt, cause); 5414 } 5415 } 5416 } 5417 5418 /* 5419 * Function: fcp_update_tgt_state 5420 * 5421 * Description: This function updates the field tgt_state of a target. That 5422 * field is a bitmap and which bit can be set or reset 5423 * individually. The action applied to the target state is also 5424 * applied to all the LUNs belonging to the target (provided the 5425 * LUN is not offline). A side effect of applying the state 5426 * modification to the target and the LUNs is the field tgt_trace 5427 * of the target and lun_trace of the LUNs is set to zero. 5428 * 5429 * 5430 * Argument: *ptgt Target structure. 5431 * flag Flag indication what action to apply (set/reset). 5432 * state State bits to update. 5433 * 5434 * Return Value: None 5435 * 5436 * Context: Interrupt, Kernel or User context. 5437 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5438 * calling this function. 5439 */ 5440 void 5441 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5442 { 5443 struct fcp_lun *plun; 5444 5445 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5446 5447 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5448 /* The target is not offline. */ 5449 if (flag == FCP_SET) { 5450 ptgt->tgt_state |= state; 5451 ptgt->tgt_trace = 0; 5452 } else { 5453 ptgt->tgt_state &= ~state; 5454 } 5455 5456 for (plun = ptgt->tgt_lun; plun != NULL; 5457 plun = plun->lun_next) { 5458 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5459 /* The LUN is not offline. */ 5460 if (flag == FCP_SET) { 5461 plun->lun_state |= state; 5462 plun->lun_trace = 0; 5463 } else { 5464 plun->lun_state &= ~state; 5465 } 5466 } 5467 } 5468 } 5469 } 5470 5471 /* 5472 * Function: fcp_update_tgt_state 5473 * 5474 * Description: This function updates the field lun_state of a LUN. That 5475 * field is a bitmap and which bit can be set or reset 5476 * individually. 5477 * 5478 * Argument: *plun LUN structure. 5479 * flag Flag indication what action to apply (set/reset). 5480 * state State bits to update. 5481 * 5482 * Return Value: None 5483 * 5484 * Context: Interrupt, Kernel or User context. 5485 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5486 * calling this function. 5487 */ 5488 void 5489 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5490 { 5491 struct fcp_tgt *ptgt = plun->lun_tgt; 5492 5493 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5494 5495 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5496 if (flag == FCP_SET) { 5497 plun->lun_state |= state; 5498 } else { 5499 plun->lun_state &= ~state; 5500 } 5501 } 5502 } 5503 5504 /* 5505 * Function: fcp_get_port 5506 * 5507 * Description: This function returns the fcp_port structure from the opaque 5508 * handle passed by the caller. That opaque handle is the handle 5509 * used by fp/fctl to identify a particular local port. That 5510 * handle has been stored in the corresponding fcp_port 5511 * structure. This function is going to walk the global list of 5512 * fcp_port structures till one has a port_fp_handle that matches 5513 * the handle passed by the caller. This function enters the 5514 * mutex fcp_global_mutex while walking the global list and then 5515 * releases it. 5516 * 5517 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5518 * particular port. 5519 * 5520 * Return Value: NULL Not found. 5521 * Not NULL Pointer to the fcp_port structure. 5522 * 5523 * Context: Interrupt, Kernel or User context. 5524 */ 5525 static struct fcp_port * 5526 fcp_get_port(opaque_t port_handle) 5527 { 5528 struct fcp_port *pptr; 5529 5530 ASSERT(port_handle != NULL); 5531 5532 mutex_enter(&fcp_global_mutex); 5533 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5534 if (pptr->port_fp_handle == port_handle) { 5535 break; 5536 } 5537 } 5538 mutex_exit(&fcp_global_mutex); 5539 5540 return (pptr); 5541 } 5542 5543 5544 static void 5545 fcp_unsol_callback(fc_packet_t *fpkt) 5546 { 5547 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5548 struct fcp_port *pptr = icmd->ipkt_port; 5549 5550 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5551 caddr_t state, reason, action, expln; 5552 5553 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5554 &action, &expln); 5555 5556 fcp_log(CE_WARN, pptr->port_dip, 5557 "!couldn't post response to unsolicited request: " 5558 " state=%s reason=%s rx_id=%x ox_id=%x", 5559 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5560 fpkt->pkt_cmd_fhdr.rx_id); 5561 } 5562 fcp_icmd_free(pptr, icmd); 5563 } 5564 5565 5566 /* 5567 * Perform general purpose preparation of a response to an unsolicited request 5568 */ 5569 static void 5570 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5571 uchar_t r_ctl, uchar_t type) 5572 { 5573 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5574 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5575 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5576 pkt->pkt_cmd_fhdr.type = type; 5577 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5578 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5579 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5580 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5581 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5582 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5583 pkt->pkt_cmd_fhdr.ro = 0; 5584 pkt->pkt_cmd_fhdr.rsvd = 0; 5585 pkt->pkt_comp = fcp_unsol_callback; 5586 pkt->pkt_pd = NULL; 5587 pkt->pkt_ub_resp_token = (opaque_t)buf; 5588 } 5589 5590 5591 /*ARGSUSED*/ 5592 static int 5593 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5594 { 5595 fc_packet_t *fpkt; 5596 struct la_els_prli prli; 5597 struct fcp_prli *fprli; 5598 struct fcp_ipkt *icmd; 5599 struct la_els_prli *from; 5600 struct fcp_prli *orig; 5601 struct fcp_tgt *ptgt; 5602 int tcount = 0; 5603 int lcount; 5604 5605 from = (struct la_els_prli *)buf->ub_buffer; 5606 orig = (struct fcp_prli *)from->service_params; 5607 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5608 NULL) { 5609 mutex_enter(&ptgt->tgt_mutex); 5610 tcount = ptgt->tgt_change_cnt; 5611 mutex_exit(&ptgt->tgt_mutex); 5612 } 5613 5614 mutex_enter(&pptr->port_mutex); 5615 lcount = pptr->port_link_cnt; 5616 mutex_exit(&pptr->port_mutex); 5617 5618 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5619 sizeof (la_els_prli_t), 0, 5620 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5621 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5622 return (FC_FAILURE); 5623 } 5624 5625 fpkt = icmd->ipkt_fpkt; 5626 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5627 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5628 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5629 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5630 fpkt->pkt_rsplen = 0; 5631 fpkt->pkt_datalen = 0; 5632 5633 icmd->ipkt_opcode = LA_ELS_PRLI; 5634 5635 bzero(&prli, sizeof (struct la_els_prli)); 5636 fprli = (struct fcp_prli *)prli.service_params; 5637 prli.ls_code = LA_ELS_ACC; 5638 prli.page_length = 0x10; 5639 prli.payload_length = sizeof (struct la_els_prli); 5640 5641 /* fill in service params */ 5642 fprli->type = 0x08; 5643 fprli->resvd1 = 0; 5644 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5645 fprli->orig_process_associator = orig->orig_process_associator; 5646 fprli->resp_process_assoc_valid = 0; 5647 fprli->establish_image_pair = 1; 5648 fprli->resvd2 = 0; 5649 fprli->resvd3 = 0; 5650 fprli->obsolete_1 = 0; 5651 fprli->obsolete_2 = 0; 5652 fprli->data_overlay_allowed = 0; 5653 fprli->initiator_fn = 1; 5654 fprli->confirmed_compl_allowed = 1; 5655 5656 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5657 fprli->target_fn = 1; 5658 } else { 5659 fprli->target_fn = 0; 5660 } 5661 5662 fprli->retry = 1; 5663 fprli->read_xfer_rdy_disabled = 1; 5664 fprli->write_xfer_rdy_disabled = 0; 5665 5666 /* save the unsol prli payload first */ 5667 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5668 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5669 5670 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5671 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5672 5673 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5674 5675 mutex_enter(&pptr->port_mutex); 5676 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5677 int rval; 5678 mutex_exit(&pptr->port_mutex); 5679 5680 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5681 FC_SUCCESS) { 5682 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5683 ptgt != NULL) { 5684 fcp_queue_ipkt(pptr, fpkt); 5685 return (FC_SUCCESS); 5686 } 5687 /* Let it timeout */ 5688 fcp_icmd_free(pptr, icmd); 5689 return (FC_FAILURE); 5690 } 5691 } else { 5692 mutex_exit(&pptr->port_mutex); 5693 fcp_icmd_free(pptr, icmd); 5694 return (FC_FAILURE); 5695 } 5696 5697 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5698 5699 return (FC_SUCCESS); 5700 } 5701 5702 /* 5703 * Function: fcp_icmd_alloc 5704 * 5705 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5706 * field is initialized to fcp_icmd_callback. Sometimes it is 5707 * modified by the caller (such as fcp_send_scsi). The 5708 * structure is also tied to the state of the line and of the 5709 * target at a particular time. That link is established by 5710 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5711 * and tcount which came respectively from pptr->link_cnt and 5712 * ptgt->tgt_change_cnt. 5713 * 5714 * Argument: *pptr Fcp port. 5715 * *ptgt Target (destination of the command). 5716 * cmd_len Length of the command. 5717 * resp_len Length of the expected response. 5718 * data_len Length of the data. 5719 * nodma Indicates weither the command and response. 5720 * will be transfer through DMA or not. 5721 * lcount Link state change counter. 5722 * tcount Target state change counter. 5723 * cause Reason that lead to this call. 5724 * 5725 * Return Value: NULL Failed. 5726 * Not NULL Internal packet address. 5727 */ 5728 static struct fcp_ipkt * 5729 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5730 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5731 uint32_t rscn_count) 5732 { 5733 int dma_setup = 0; 5734 fc_packet_t *fpkt; 5735 struct fcp_ipkt *icmd = NULL; 5736 5737 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5738 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5739 KM_NOSLEEP); 5740 if (icmd == NULL) { 5741 fcp_log(CE_WARN, pptr->port_dip, 5742 "!internal packet allocation failed"); 5743 return (NULL); 5744 } 5745 5746 /* 5747 * initialize the allocated packet 5748 */ 5749 icmd->ipkt_nodma = nodma; 5750 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5751 icmd->ipkt_lun = NULL; 5752 5753 icmd->ipkt_link_cnt = lcount; 5754 icmd->ipkt_change_cnt = tcount; 5755 icmd->ipkt_cause = cause; 5756 5757 mutex_enter(&pptr->port_mutex); 5758 icmd->ipkt_port = pptr; 5759 mutex_exit(&pptr->port_mutex); 5760 5761 /* keep track of amt of data to be sent in pkt */ 5762 icmd->ipkt_cmdlen = cmd_len; 5763 icmd->ipkt_resplen = resp_len; 5764 icmd->ipkt_datalen = data_len; 5765 5766 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5767 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5768 5769 /* set pkt's private ptr to point to cmd pkt */ 5770 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5771 5772 /* set FCA private ptr to memory just beyond */ 5773 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5774 ((char *)icmd + sizeof (struct fcp_ipkt) + 5775 pptr->port_dmacookie_sz); 5776 5777 /* get ptr to fpkt substruct and fill it in */ 5778 fpkt = icmd->ipkt_fpkt; 5779 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5780 sizeof (struct fcp_ipkt)); 5781 5782 if (ptgt != NULL) { 5783 icmd->ipkt_tgt = ptgt; 5784 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5785 } 5786 5787 fpkt->pkt_comp = fcp_icmd_callback; 5788 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5789 fpkt->pkt_cmdlen = cmd_len; 5790 fpkt->pkt_rsplen = resp_len; 5791 fpkt->pkt_datalen = data_len; 5792 5793 /* 5794 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5795 * rscn_count as fcp knows down to the transport. If a valid count was 5796 * passed into this function, we allocate memory to actually pass down 5797 * this info. 5798 * 5799 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5800 * basically mean that fcp will not be able to help transport 5801 * distinguish if a new RSCN has come after fcp was last informed about 5802 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5803 * 5068068 where the device might end up going offline in case of RSCN 5804 * storms. 5805 */ 5806 fpkt->pkt_ulp_rscn_infop = NULL; 5807 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5808 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5809 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5810 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5811 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5812 fcp_trace, FCP_BUF_LEVEL_6, 0, 5813 "Failed to alloc memory to pass rscn info"); 5814 } 5815 } 5816 5817 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5818 fc_ulp_rscn_info_t *rscnp; 5819 5820 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5821 rscnp->ulp_rscn_count = rscn_count; 5822 } 5823 5824 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5825 goto fail; 5826 } 5827 dma_setup++; 5828 5829 /* 5830 * Must hold target mutex across setting of pkt_pd and call to 5831 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5832 * away while we're not looking. 5833 */ 5834 if (ptgt != NULL) { 5835 mutex_enter(&ptgt->tgt_mutex); 5836 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5837 5838 /* ask transport to do its initialization on this pkt */ 5839 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5840 != FC_SUCCESS) { 5841 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5842 fcp_trace, FCP_BUF_LEVEL_6, 0, 5843 "fc_ulp_init_packet failed"); 5844 mutex_exit(&ptgt->tgt_mutex); 5845 goto fail; 5846 } 5847 mutex_exit(&ptgt->tgt_mutex); 5848 } else { 5849 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5850 != FC_SUCCESS) { 5851 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5852 fcp_trace, FCP_BUF_LEVEL_6, 0, 5853 "fc_ulp_init_packet failed"); 5854 goto fail; 5855 } 5856 } 5857 5858 mutex_enter(&pptr->port_mutex); 5859 if (pptr->port_state & (FCP_STATE_DETACHING | 5860 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5861 int rval; 5862 5863 mutex_exit(&pptr->port_mutex); 5864 5865 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5866 ASSERT(rval == FC_SUCCESS); 5867 5868 goto fail; 5869 } 5870 5871 if (ptgt != NULL) { 5872 mutex_enter(&ptgt->tgt_mutex); 5873 ptgt->tgt_ipkt_cnt++; 5874 mutex_exit(&ptgt->tgt_mutex); 5875 } 5876 5877 pptr->port_ipkt_cnt++; 5878 5879 mutex_exit(&pptr->port_mutex); 5880 5881 return (icmd); 5882 5883 fail: 5884 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5885 kmem_free(fpkt->pkt_ulp_rscn_infop, 5886 sizeof (fc_ulp_rscn_info_t)); 5887 fpkt->pkt_ulp_rscn_infop = NULL; 5888 } 5889 5890 if (dma_setup) { 5891 fcp_free_dma(pptr, icmd); 5892 } 5893 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5894 (size_t)pptr->port_dmacookie_sz); 5895 5896 return (NULL); 5897 } 5898 5899 /* 5900 * Function: fcp_icmd_free 5901 * 5902 * Description: Frees the internal command passed by the caller. 5903 * 5904 * Argument: *pptr Fcp port. 5905 * *icmd Internal packet to free. 5906 * 5907 * Return Value: None 5908 */ 5909 static void 5910 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5911 { 5912 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5913 5914 /* Let the underlying layers do their cleanup. */ 5915 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5916 icmd->ipkt_fpkt); 5917 5918 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5919 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5920 sizeof (fc_ulp_rscn_info_t)); 5921 } 5922 5923 fcp_free_dma(pptr, icmd); 5924 5925 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5926 (size_t)pptr->port_dmacookie_sz); 5927 5928 mutex_enter(&pptr->port_mutex); 5929 5930 if (ptgt) { 5931 mutex_enter(&ptgt->tgt_mutex); 5932 ptgt->tgt_ipkt_cnt--; 5933 mutex_exit(&ptgt->tgt_mutex); 5934 } 5935 5936 pptr->port_ipkt_cnt--; 5937 mutex_exit(&pptr->port_mutex); 5938 } 5939 5940 /* 5941 * Function: fcp_alloc_dma 5942 * 5943 * Description: Allocated the DMA resources required for the internal 5944 * packet. 5945 * 5946 * Argument: *pptr FCP port. 5947 * *icmd Internal FCP packet. 5948 * nodma Indicates if the Cmd and Resp will be DMAed. 5949 * flags Allocation flags (Sleep or NoSleep). 5950 * 5951 * Return Value: FC_SUCCESS 5952 * FC_NOMEM 5953 */ 5954 static int 5955 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5956 int nodma, int flags) 5957 { 5958 int rval; 5959 size_t real_size; 5960 uint_t ccount; 5961 int bound = 0; 5962 int cmd_resp = 0; 5963 fc_packet_t *fpkt; 5964 ddi_dma_cookie_t pkt_data_cookie; 5965 ddi_dma_cookie_t *cp; 5966 uint32_t cnt; 5967 5968 fpkt = &icmd->ipkt_fc_packet; 5969 5970 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5971 fpkt->pkt_resp_dma == NULL); 5972 5973 icmd->ipkt_nodma = nodma; 5974 5975 if (nodma) { 5976 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5977 if (fpkt->pkt_cmd == NULL) { 5978 goto fail; 5979 } 5980 5981 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5982 if (fpkt->pkt_resp == NULL) { 5983 goto fail; 5984 } 5985 } else { 5986 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5987 5988 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5989 if (rval == FC_FAILURE) { 5990 ASSERT(fpkt->pkt_cmd_dma == NULL && 5991 fpkt->pkt_resp_dma == NULL); 5992 goto fail; 5993 } 5994 cmd_resp++; 5995 } 5996 5997 if ((fpkt->pkt_datalen != 0) && 5998 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 5999 /* 6000 * set up DMA handle and memory for the data in this packet 6001 */ 6002 if (ddi_dma_alloc_handle(pptr->port_dip, 6003 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 6004 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 6005 goto fail; 6006 } 6007 6008 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 6009 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 6010 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 6011 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 6012 goto fail; 6013 } 6014 6015 /* was DMA mem size gotten < size asked for/needed ?? */ 6016 if (real_size < fpkt->pkt_datalen) { 6017 goto fail; 6018 } 6019 6020 /* bind DMA address and handle together */ 6021 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6022 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6023 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6024 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6025 goto fail; 6026 } 6027 bound++; 6028 6029 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6030 goto fail; 6031 } 6032 6033 fpkt->pkt_data_cookie_cnt = ccount; 6034 6035 cp = fpkt->pkt_data_cookie; 6036 *cp = pkt_data_cookie; 6037 cp++; 6038 6039 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6040 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6041 &pkt_data_cookie); 6042 *cp = pkt_data_cookie; 6043 } 6044 6045 } else if (fpkt->pkt_datalen != 0) { 6046 /* 6047 * If it's a pseudo FCA, then it can't support DMA even in 6048 * SCSI data phase. 6049 */ 6050 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6051 if (fpkt->pkt_data == NULL) { 6052 goto fail; 6053 } 6054 6055 } 6056 6057 return (FC_SUCCESS); 6058 6059 fail: 6060 if (bound) { 6061 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6062 } 6063 6064 if (fpkt->pkt_data_dma) { 6065 if (fpkt->pkt_data) { 6066 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6067 } 6068 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6069 } else { 6070 if (fpkt->pkt_data) { 6071 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6072 } 6073 } 6074 6075 if (nodma) { 6076 if (fpkt->pkt_cmd) { 6077 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6078 } 6079 if (fpkt->pkt_resp) { 6080 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6081 } 6082 } else { 6083 if (cmd_resp) { 6084 fcp_free_cmd_resp(pptr, fpkt); 6085 } 6086 } 6087 6088 return (FC_NOMEM); 6089 } 6090 6091 6092 static void 6093 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6094 { 6095 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6096 6097 if (fpkt->pkt_data_dma) { 6098 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6099 if (fpkt->pkt_data) { 6100 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6101 } 6102 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6103 } else { 6104 if (fpkt->pkt_data) { 6105 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6106 } 6107 /* 6108 * Need we reset pkt_* to zero??? 6109 */ 6110 } 6111 6112 if (icmd->ipkt_nodma) { 6113 if (fpkt->pkt_cmd) { 6114 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6115 } 6116 if (fpkt->pkt_resp) { 6117 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6118 } 6119 } else { 6120 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6121 6122 fcp_free_cmd_resp(pptr, fpkt); 6123 } 6124 } 6125 6126 /* 6127 * Function: fcp_lookup_target 6128 * 6129 * Description: Finds a target given a WWN. 6130 * 6131 * Argument: *pptr FCP port. 6132 * *wwn World Wide Name of the device to look for. 6133 * 6134 * Return Value: NULL No target found 6135 * Not NULL Target structure 6136 * 6137 * Context: Interrupt context. 6138 * The mutex pptr->port_mutex must be owned. 6139 */ 6140 /* ARGSUSED */ 6141 static struct fcp_tgt * 6142 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6143 { 6144 int hash; 6145 struct fcp_tgt *ptgt; 6146 6147 ASSERT(mutex_owned(&pptr->port_mutex)); 6148 6149 hash = FCP_HASH(wwn); 6150 6151 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6152 ptgt = ptgt->tgt_next) { 6153 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6154 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6155 sizeof (ptgt->tgt_port_wwn)) == 0) { 6156 break; 6157 } 6158 } 6159 6160 return (ptgt); 6161 } 6162 6163 6164 /* 6165 * Find target structure given a port identifier 6166 */ 6167 static struct fcp_tgt * 6168 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6169 { 6170 fc_portid_t port_id; 6171 la_wwn_t pwwn; 6172 struct fcp_tgt *ptgt = NULL; 6173 6174 port_id.priv_lilp_posit = 0; 6175 port_id.port_id = d_id; 6176 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6177 &pwwn) == FC_SUCCESS) { 6178 mutex_enter(&pptr->port_mutex); 6179 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6180 mutex_exit(&pptr->port_mutex); 6181 } 6182 6183 return (ptgt); 6184 } 6185 6186 6187 /* 6188 * the packet completion callback routine for info cmd pkts 6189 * 6190 * this means fpkt pts to a response to either a PLOGI or a PRLI 6191 * 6192 * if there is an error an attempt is made to call a routine to resend 6193 * the command that failed 6194 */ 6195 static void 6196 fcp_icmd_callback(fc_packet_t *fpkt) 6197 { 6198 struct fcp_ipkt *icmd; 6199 struct fcp_port *pptr; 6200 struct fcp_tgt *ptgt; 6201 struct la_els_prli *prli; 6202 struct la_els_prli prli_s; 6203 struct fcp_prli *fprli; 6204 struct fcp_lun *plun; 6205 int free_pkt = 1; 6206 int rval; 6207 ls_code_t resp; 6208 uchar_t prli_acc = 0; 6209 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6210 int lun0_newalloc; 6211 6212 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6213 6214 /* get ptrs to the port and target structs for the cmd */ 6215 pptr = icmd->ipkt_port; 6216 ptgt = icmd->ipkt_tgt; 6217 6218 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6219 6220 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6221 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6222 sizeof (prli_s)); 6223 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6224 } 6225 6226 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6227 fcp_trace, FCP_BUF_LEVEL_2, 0, 6228 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6229 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6230 ptgt->tgt_d_id); 6231 6232 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6233 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6234 6235 mutex_enter(&ptgt->tgt_mutex); 6236 if (ptgt->tgt_pd_handle == NULL) { 6237 /* 6238 * in a fabric environment the port device handles 6239 * get created only after successful LOGIN into the 6240 * transport, so the transport makes this port 6241 * device (pd) handle available in this packet, so 6242 * save it now 6243 */ 6244 ASSERT(fpkt->pkt_pd != NULL); 6245 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6246 } 6247 mutex_exit(&ptgt->tgt_mutex); 6248 6249 /* which ELS cmd is this response for ?? */ 6250 switch (icmd->ipkt_opcode) { 6251 case LA_ELS_PLOGI: 6252 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6253 fcp_trace, FCP_BUF_LEVEL_5, 0, 6254 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6255 ptgt->tgt_d_id, 6256 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6257 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6258 6259 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6260 FCP_TGT_TRACE_15); 6261 6262 /* Note that we are not allocating a new icmd */ 6263 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6264 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6265 icmd->ipkt_cause) != DDI_SUCCESS) { 6266 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6267 FCP_TGT_TRACE_16); 6268 goto fail; 6269 } 6270 break; 6271 6272 case LA_ELS_PRLI: 6273 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6274 fcp_trace, FCP_BUF_LEVEL_5, 0, 6275 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6276 6277 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6278 FCP_TGT_TRACE_17); 6279 6280 prli = &prli_s; 6281 6282 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6283 sizeof (prli_s)); 6284 6285 fprli = (struct fcp_prli *)prli->service_params; 6286 6287 mutex_enter(&ptgt->tgt_mutex); 6288 ptgt->tgt_icap = fprli->initiator_fn; 6289 ptgt->tgt_tcap = fprli->target_fn; 6290 mutex_exit(&ptgt->tgt_mutex); 6291 6292 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6293 /* 6294 * this FCP device does not support target mode 6295 */ 6296 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6297 FCP_TGT_TRACE_18); 6298 goto fail; 6299 } 6300 if (fprli->retry == 1) { 6301 fc_ulp_disable_relogin(pptr->port_fp_handle, 6302 &ptgt->tgt_port_wwn); 6303 } 6304 6305 /* target is no longer offline */ 6306 mutex_enter(&pptr->port_mutex); 6307 mutex_enter(&ptgt->tgt_mutex); 6308 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6309 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6310 FCP_TGT_MARK); 6311 } else { 6312 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6313 fcp_trace, FCP_BUF_LEVEL_2, 0, 6314 "fcp_icmd_callback,1: state change " 6315 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6316 mutex_exit(&ptgt->tgt_mutex); 6317 mutex_exit(&pptr->port_mutex); 6318 goto fail; 6319 } 6320 mutex_exit(&ptgt->tgt_mutex); 6321 mutex_exit(&pptr->port_mutex); 6322 6323 /* 6324 * lun 0 should always respond to inquiry, so 6325 * get the LUN struct for LUN 0 6326 * 6327 * Currently we deal with first level of addressing. 6328 * If / when we start supporting 0x device types 6329 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6330 * this logic will need revisiting. 6331 */ 6332 lun0_newalloc = 0; 6333 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6334 /* 6335 * no LUN struct for LUN 0 yet exists, 6336 * so create one 6337 */ 6338 plun = fcp_alloc_lun(ptgt); 6339 if (plun == NULL) { 6340 fcp_log(CE_WARN, pptr->port_dip, 6341 "!Failed to allocate lun 0 for" 6342 " D_ID=%x", ptgt->tgt_d_id); 6343 goto fail; 6344 } 6345 lun0_newalloc = 1; 6346 } 6347 6348 /* fill in LUN info */ 6349 mutex_enter(&ptgt->tgt_mutex); 6350 /* 6351 * consider lun 0 as device not connected if it is 6352 * offlined or newly allocated 6353 */ 6354 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6355 lun0_newalloc) { 6356 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6357 } 6358 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6359 plun->lun_state &= ~FCP_LUN_OFFLINE; 6360 ptgt->tgt_lun_cnt = 1; 6361 ptgt->tgt_report_lun_cnt = 0; 6362 mutex_exit(&ptgt->tgt_mutex); 6363 6364 /* Retrieve the rscn count (if a valid one exists) */ 6365 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6366 rscn_count = ((fc_ulp_rscn_info_t *) 6367 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6368 ->ulp_rscn_count; 6369 } else { 6370 rscn_count = FC_INVALID_RSCN_COUNT; 6371 } 6372 6373 /* send Report Lun request to target */ 6374 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6375 sizeof (struct fcp_reportlun_resp), 6376 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6377 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6378 mutex_enter(&pptr->port_mutex); 6379 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6380 fcp_log(CE_WARN, pptr->port_dip, 6381 "!Failed to send REPORT LUN to" 6382 " D_ID=%x", ptgt->tgt_d_id); 6383 } else { 6384 FCP_TRACE(fcp_logq, 6385 pptr->port_instbuf, fcp_trace, 6386 FCP_BUF_LEVEL_5, 0, 6387 "fcp_icmd_callback,2:state change" 6388 " occured for D_ID=0x%x", 6389 ptgt->tgt_d_id); 6390 } 6391 mutex_exit(&pptr->port_mutex); 6392 6393 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6394 FCP_TGT_TRACE_19); 6395 6396 goto fail; 6397 } else { 6398 free_pkt = 0; 6399 fcp_icmd_free(pptr, icmd); 6400 } 6401 break; 6402 6403 default: 6404 fcp_log(CE_WARN, pptr->port_dip, 6405 "!fcp_icmd_callback Invalid opcode"); 6406 goto fail; 6407 } 6408 6409 return; 6410 } 6411 6412 6413 /* 6414 * Other PLOGI failures are not retried as the 6415 * transport does it already 6416 */ 6417 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6418 if (fcp_is_retryable(icmd) && 6419 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6420 6421 if (FCP_MUST_RETRY(fpkt)) { 6422 fcp_queue_ipkt(pptr, fpkt); 6423 return; 6424 } 6425 6426 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6427 fcp_trace, FCP_BUF_LEVEL_2, 0, 6428 "ELS PRLI is retried for d_id=0x%x, state=%x," 6429 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6430 fpkt->pkt_reason); 6431 6432 /* 6433 * Retry by recalling the routine that 6434 * originally queued this packet 6435 */ 6436 mutex_enter(&pptr->port_mutex); 6437 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6438 caddr_t msg; 6439 6440 mutex_exit(&pptr->port_mutex); 6441 6442 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6443 6444 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6445 fpkt->pkt_timeout += 6446 FCP_TIMEOUT_DELTA; 6447 } 6448 6449 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6450 fpkt); 6451 if (rval == FC_SUCCESS) { 6452 return; 6453 } 6454 6455 if (rval == FC_STATEC_BUSY || 6456 rval == FC_OFFLINE) { 6457 fcp_queue_ipkt(pptr, fpkt); 6458 return; 6459 } 6460 (void) fc_ulp_error(rval, &msg); 6461 6462 fcp_log(CE_NOTE, pptr->port_dip, 6463 "!ELS 0x%x failed to d_id=0x%x;" 6464 " %s", icmd->ipkt_opcode, 6465 ptgt->tgt_d_id, msg); 6466 } else { 6467 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6468 fcp_trace, FCP_BUF_LEVEL_2, 0, 6469 "fcp_icmd_callback,3: state change " 6470 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6471 mutex_exit(&pptr->port_mutex); 6472 } 6473 } 6474 } else { 6475 if (fcp_is_retryable(icmd) && 6476 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6477 if (FCP_MUST_RETRY(fpkt)) { 6478 fcp_queue_ipkt(pptr, fpkt); 6479 return; 6480 } 6481 } 6482 mutex_enter(&pptr->port_mutex); 6483 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6484 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6485 mutex_exit(&pptr->port_mutex); 6486 fcp_print_error(fpkt); 6487 } else { 6488 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6489 fcp_trace, FCP_BUF_LEVEL_2, 0, 6490 "fcp_icmd_callback,4: state change occured" 6491 " for D_ID=0x%x", ptgt->tgt_d_id); 6492 mutex_exit(&pptr->port_mutex); 6493 } 6494 } 6495 6496 fail: 6497 if (free_pkt) { 6498 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6499 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6500 fcp_icmd_free(pptr, icmd); 6501 } 6502 } 6503 6504 6505 /* 6506 * called internally to send an info cmd using the transport 6507 * 6508 * sends either an INQ or a REPORT_LUN 6509 * 6510 * when the packet is completed fcp_scsi_callback is called 6511 */ 6512 static int 6513 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6514 int lcount, int tcount, int cause, uint32_t rscn_count) 6515 { 6516 int nodma; 6517 struct fcp_ipkt *icmd; 6518 struct fcp_tgt *ptgt; 6519 struct fcp_port *pptr; 6520 fc_frame_hdr_t *hp; 6521 fc_packet_t *fpkt; 6522 struct fcp_cmd fcp_cmd; 6523 struct fcp_cmd *fcmd; 6524 union scsi_cdb *scsi_cdb; 6525 6526 ASSERT(plun != NULL); 6527 6528 ptgt = plun->lun_tgt; 6529 ASSERT(ptgt != NULL); 6530 6531 pptr = ptgt->tgt_port; 6532 ASSERT(pptr != NULL); 6533 6534 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6535 fcp_trace, FCP_BUF_LEVEL_5, 0, 6536 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6537 6538 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6539 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6540 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6541 rscn_count); 6542 6543 if (icmd == NULL) { 6544 return (DDI_FAILURE); 6545 } 6546 6547 fpkt = icmd->ipkt_fpkt; 6548 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6549 icmd->ipkt_retries = 0; 6550 icmd->ipkt_opcode = opcode; 6551 icmd->ipkt_lun = plun; 6552 6553 if (nodma) { 6554 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6555 } else { 6556 fcmd = &fcp_cmd; 6557 } 6558 bzero(fcmd, sizeof (struct fcp_cmd)); 6559 6560 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6561 6562 hp = &fpkt->pkt_cmd_fhdr; 6563 6564 hp->s_id = pptr->port_id; 6565 hp->d_id = ptgt->tgt_d_id; 6566 hp->r_ctl = R_CTL_COMMAND; 6567 hp->type = FC_TYPE_SCSI_FCP; 6568 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6569 hp->rsvd = 0; 6570 hp->seq_id = 0; 6571 hp->seq_cnt = 0; 6572 hp->ox_id = 0xffff; 6573 hp->rx_id = 0xffff; 6574 hp->ro = 0; 6575 6576 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6577 6578 /* 6579 * Request SCSI target for expedited processing 6580 */ 6581 6582 /* 6583 * Set up for untagged queuing because we do not 6584 * know if the fibre device supports queuing. 6585 */ 6586 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6587 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6588 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6589 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6590 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6591 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6592 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6593 6594 switch (opcode) { 6595 case SCMD_INQUIRY_PAGE83: 6596 /* 6597 * Prepare to get the Inquiry VPD page 83 information 6598 */ 6599 fcmd->fcp_cntl.cntl_read_data = 1; 6600 fcmd->fcp_cntl.cntl_write_data = 0; 6601 fcmd->fcp_data_len = alloc_len; 6602 6603 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6604 fpkt->pkt_comp = fcp_scsi_callback; 6605 6606 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6607 scsi_cdb->g0_addr2 = 0x01; 6608 scsi_cdb->g0_addr1 = 0x83; 6609 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6610 break; 6611 6612 case SCMD_INQUIRY: 6613 fcmd->fcp_cntl.cntl_read_data = 1; 6614 fcmd->fcp_cntl.cntl_write_data = 0; 6615 fcmd->fcp_data_len = alloc_len; 6616 6617 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6618 fpkt->pkt_comp = fcp_scsi_callback; 6619 6620 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6621 scsi_cdb->g0_count0 = SUN_INQSIZE; 6622 break; 6623 6624 case SCMD_REPORT_LUN: { 6625 fc_portid_t d_id; 6626 opaque_t fca_dev; 6627 6628 ASSERT(alloc_len >= 16); 6629 6630 d_id.priv_lilp_posit = 0; 6631 d_id.port_id = ptgt->tgt_d_id; 6632 6633 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6634 6635 mutex_enter(&ptgt->tgt_mutex); 6636 ptgt->tgt_fca_dev = fca_dev; 6637 mutex_exit(&ptgt->tgt_mutex); 6638 6639 fcmd->fcp_cntl.cntl_read_data = 1; 6640 fcmd->fcp_cntl.cntl_write_data = 0; 6641 fcmd->fcp_data_len = alloc_len; 6642 6643 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6644 fpkt->pkt_comp = fcp_scsi_callback; 6645 6646 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6647 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6648 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6649 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6650 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6651 break; 6652 } 6653 6654 default: 6655 fcp_log(CE_WARN, pptr->port_dip, 6656 "!fcp_send_scsi Invalid opcode"); 6657 break; 6658 } 6659 6660 if (!nodma) { 6661 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6662 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6663 } 6664 6665 mutex_enter(&pptr->port_mutex); 6666 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6667 6668 mutex_exit(&pptr->port_mutex); 6669 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6670 FC_SUCCESS) { 6671 fcp_icmd_free(pptr, icmd); 6672 return (DDI_FAILURE); 6673 } 6674 return (DDI_SUCCESS); 6675 } else { 6676 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6677 fcp_trace, FCP_BUF_LEVEL_2, 0, 6678 "fcp_send_scsi,1: state change occured" 6679 " for D_ID=0x%x", ptgt->tgt_d_id); 6680 mutex_exit(&pptr->port_mutex); 6681 fcp_icmd_free(pptr, icmd); 6682 return (DDI_FAILURE); 6683 } 6684 } 6685 6686 6687 /* 6688 * called by fcp_scsi_callback to check to handle the case where 6689 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6690 */ 6691 static int 6692 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6693 { 6694 uchar_t rqlen; 6695 int rval = DDI_FAILURE; 6696 struct scsi_extended_sense sense_info, *sense; 6697 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6698 fpkt->pkt_ulp_private; 6699 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6700 struct fcp_port *pptr = ptgt->tgt_port; 6701 6702 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6703 6704 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6705 /* 6706 * SCSI-II Reserve Release support. Some older FC drives return 6707 * Reservation conflict for Report Luns command. 6708 */ 6709 if (icmd->ipkt_nodma) { 6710 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6711 rsp->fcp_u.fcp_status.sense_len_set = 0; 6712 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6713 } else { 6714 fcp_rsp_t new_resp; 6715 6716 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6717 fpkt->pkt_resp_acc, sizeof (new_resp)); 6718 6719 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6720 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6721 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6722 6723 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6724 fpkt->pkt_resp_acc, sizeof (new_resp)); 6725 } 6726 6727 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6728 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6729 6730 return (DDI_SUCCESS); 6731 } 6732 6733 sense = &sense_info; 6734 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6735 /* no need to continue if sense length is not set */ 6736 return (rval); 6737 } 6738 6739 /* casting 64-bit integer to 8-bit */ 6740 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6741 sizeof (struct scsi_extended_sense)); 6742 6743 if (rqlen < 14) { 6744 /* no need to continue if request length isn't long enough */ 6745 return (rval); 6746 } 6747 6748 if (icmd->ipkt_nodma) { 6749 /* 6750 * We can safely use fcp_response_len here since the 6751 * only path that calls fcp_check_reportlun, 6752 * fcp_scsi_callback, has already called 6753 * fcp_validate_fcp_response. 6754 */ 6755 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6756 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6757 } else { 6758 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6759 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6760 sizeof (struct scsi_extended_sense)); 6761 } 6762 6763 if (!FCP_SENSE_NO_LUN(sense)) { 6764 mutex_enter(&ptgt->tgt_mutex); 6765 /* clear the flag if any */ 6766 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6767 mutex_exit(&ptgt->tgt_mutex); 6768 } 6769 6770 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6771 (sense->es_add_code == 0x20)) { 6772 if (icmd->ipkt_nodma) { 6773 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6774 rsp->fcp_u.fcp_status.sense_len_set = 0; 6775 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6776 } else { 6777 fcp_rsp_t new_resp; 6778 6779 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6780 fpkt->pkt_resp_acc, sizeof (new_resp)); 6781 6782 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6783 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6784 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6785 6786 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6787 fpkt->pkt_resp_acc, sizeof (new_resp)); 6788 } 6789 6790 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6791 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6792 6793 return (DDI_SUCCESS); 6794 } 6795 6796 /* 6797 * This is for the STK library which returns a check condition, 6798 * to indicate device is not ready, manual assistance needed. 6799 * This is to a report lun command when the door is open. 6800 */ 6801 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6802 if (icmd->ipkt_nodma) { 6803 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6804 rsp->fcp_u.fcp_status.sense_len_set = 0; 6805 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6806 } else { 6807 fcp_rsp_t new_resp; 6808 6809 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6810 fpkt->pkt_resp_acc, sizeof (new_resp)); 6811 6812 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6813 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6814 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6815 6816 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6817 fpkt->pkt_resp_acc, sizeof (new_resp)); 6818 } 6819 6820 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6821 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6822 6823 return (DDI_SUCCESS); 6824 } 6825 6826 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6827 (FCP_SENSE_NO_LUN(sense))) { 6828 mutex_enter(&ptgt->tgt_mutex); 6829 if ((FCP_SENSE_NO_LUN(sense)) && 6830 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6831 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6832 mutex_exit(&ptgt->tgt_mutex); 6833 /* 6834 * reconfig was triggred by ILLEGAL REQUEST but 6835 * got ILLEGAL REQUEST again 6836 */ 6837 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6838 fcp_trace, FCP_BUF_LEVEL_3, 0, 6839 "!FCP: Unable to obtain Report Lun data" 6840 " target=%x", ptgt->tgt_d_id); 6841 } else { 6842 if (ptgt->tgt_tid == NULL) { 6843 timeout_id_t tid; 6844 /* 6845 * REPORT LUN data has changed. Kick off 6846 * rediscovery 6847 */ 6848 tid = timeout(fcp_reconfigure_luns, 6849 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6850 6851 ptgt->tgt_tid = tid; 6852 ptgt->tgt_state |= FCP_TGT_BUSY; 6853 } 6854 if (FCP_SENSE_NO_LUN(sense)) { 6855 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6856 } 6857 mutex_exit(&ptgt->tgt_mutex); 6858 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6859 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6860 fcp_trace, FCP_BUF_LEVEL_3, 0, 6861 "!FCP:Report Lun Has Changed" 6862 " target=%x", ptgt->tgt_d_id); 6863 } else if (FCP_SENSE_NO_LUN(sense)) { 6864 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6865 fcp_trace, FCP_BUF_LEVEL_3, 0, 6866 "!FCP:LU Not Supported" 6867 " target=%x", ptgt->tgt_d_id); 6868 } 6869 } 6870 rval = DDI_SUCCESS; 6871 } 6872 6873 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6874 fcp_trace, FCP_BUF_LEVEL_5, 0, 6875 "D_ID=%x, sense=%x, status=%x", 6876 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6877 rsp->fcp_u.fcp_status.scsi_status); 6878 6879 return (rval); 6880 } 6881 6882 /* 6883 * Function: fcp_scsi_callback 6884 * 6885 * Description: This is the callback routine set by fcp_send_scsi() after 6886 * it calls fcp_icmd_alloc(). The SCSI command completed here 6887 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6888 * INQUIRY_PAGE83. 6889 * 6890 * Argument: *fpkt FC packet used to convey the command 6891 * 6892 * Return Value: None 6893 */ 6894 static void 6895 fcp_scsi_callback(fc_packet_t *fpkt) 6896 { 6897 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6898 fpkt->pkt_ulp_private; 6899 struct fcp_rsp_info fcp_rsp_err, *bep; 6900 struct fcp_port *pptr; 6901 struct fcp_tgt *ptgt; 6902 struct fcp_lun *plun; 6903 struct fcp_rsp response, *rsp; 6904 6905 ptgt = icmd->ipkt_tgt; 6906 pptr = ptgt->tgt_port; 6907 plun = icmd->ipkt_lun; 6908 6909 if (icmd->ipkt_nodma) { 6910 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6911 } else { 6912 rsp = &response; 6913 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6914 sizeof (struct fcp_rsp)); 6915 } 6916 6917 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6918 fcp_trace, FCP_BUF_LEVEL_2, 0, 6919 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6920 "status=%x, lun num=%x", 6921 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6922 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6923 6924 /* 6925 * Pre-init LUN GUID with NWWN if it is not a device that 6926 * supports multiple luns and we know it's not page83 6927 * compliant. Although using a NWWN is not lun unique, 6928 * we will be fine since there is only one lun behind the taget 6929 * in this case. 6930 */ 6931 if ((plun->lun_guid_size == 0) && 6932 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6933 (fcp_symmetric_device_probe(plun) == 0)) { 6934 6935 char ascii_wwn[FC_WWN_SIZE*2+1]; 6936 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6937 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6938 } 6939 6940 /* 6941 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6942 * when thay have more data than what is asked in CDB. An overrun 6943 * is really when FCP_DL is smaller than the data length in CDB. 6944 * In the case here we know that REPORT LUN command we formed within 6945 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6946 * behavior. In reality this is FC_SUCCESS. 6947 */ 6948 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6949 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6950 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6951 fpkt->pkt_state = FC_PKT_SUCCESS; 6952 } 6953 6954 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6955 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6956 fcp_trace, FCP_BUF_LEVEL_2, 0, 6957 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6958 ptgt->tgt_d_id); 6959 6960 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6961 /* 6962 * Inquiry VPD page command on A5K SES devices would 6963 * result in data CRC errors. 6964 */ 6965 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6966 (void) fcp_handle_page83(fpkt, icmd, 1); 6967 return; 6968 } 6969 } 6970 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6971 FCP_MUST_RETRY(fpkt)) { 6972 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6973 fcp_retry_scsi_cmd(fpkt); 6974 return; 6975 } 6976 6977 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6978 FCP_TGT_TRACE_20); 6979 6980 mutex_enter(&pptr->port_mutex); 6981 mutex_enter(&ptgt->tgt_mutex); 6982 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6983 mutex_exit(&ptgt->tgt_mutex); 6984 mutex_exit(&pptr->port_mutex); 6985 fcp_print_error(fpkt); 6986 } else { 6987 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6988 fcp_trace, FCP_BUF_LEVEL_2, 0, 6989 "fcp_scsi_callback,1: state change occured" 6990 " for D_ID=0x%x", ptgt->tgt_d_id); 6991 mutex_exit(&ptgt->tgt_mutex); 6992 mutex_exit(&pptr->port_mutex); 6993 } 6994 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6995 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6996 fcp_icmd_free(pptr, icmd); 6997 return; 6998 } 6999 7000 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 7001 7002 mutex_enter(&pptr->port_mutex); 7003 mutex_enter(&ptgt->tgt_mutex); 7004 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7005 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7006 fcp_trace, FCP_BUF_LEVEL_2, 0, 7007 "fcp_scsi_callback,2: state change occured" 7008 " for D_ID=0x%x", ptgt->tgt_d_id); 7009 mutex_exit(&ptgt->tgt_mutex); 7010 mutex_exit(&pptr->port_mutex); 7011 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7012 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7013 fcp_icmd_free(pptr, icmd); 7014 return; 7015 } 7016 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7017 7018 mutex_exit(&ptgt->tgt_mutex); 7019 mutex_exit(&pptr->port_mutex); 7020 7021 if (icmd->ipkt_nodma) { 7022 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7023 sizeof (struct fcp_rsp)); 7024 } else { 7025 bep = &fcp_rsp_err; 7026 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7027 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7028 } 7029 7030 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7031 fcp_retry_scsi_cmd(fpkt); 7032 return; 7033 } 7034 7035 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7036 FCP_NO_FAILURE) { 7037 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7038 fcp_trace, FCP_BUF_LEVEL_2, 0, 7039 "rsp_code=0x%x, rsp_len_set=0x%x", 7040 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7041 fcp_retry_scsi_cmd(fpkt); 7042 return; 7043 } 7044 7045 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7046 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7047 fcp_queue_ipkt(pptr, fpkt); 7048 return; 7049 } 7050 7051 /* 7052 * Devices that do not support INQUIRY_PAGE83, return check condition 7053 * with illegal request as per SCSI spec. 7054 * Crossbridge is one such device and Daktari's SES node is another. 7055 * We want to ideally enumerate these devices as a non-mpxio devices. 7056 * SES nodes (Daktari only currently) are an exception to this. 7057 */ 7058 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7059 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7060 7061 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7062 fcp_trace, FCP_BUF_LEVEL_3, 0, 7063 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7064 "check condition. May enumerate as non-mpxio device", 7065 ptgt->tgt_d_id, plun->lun_type); 7066 7067 /* 7068 * If we let Daktari's SES be enumerated as a non-mpxio 7069 * device, there will be a discrepency in that the other 7070 * internal FC disks will get enumerated as mpxio devices. 7071 * Applications like luxadm expect this to be consistent. 7072 * 7073 * So, we put in a hack here to check if this is an SES device 7074 * and handle it here. 7075 */ 7076 if (plun->lun_type == DTYPE_ESI) { 7077 /* 7078 * Since, pkt_state is actually FC_PKT_SUCCESS 7079 * at this stage, we fake a failure here so that 7080 * fcp_handle_page83 will create a device path using 7081 * the WWN instead of the GUID which is not there anyway 7082 */ 7083 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7084 (void) fcp_handle_page83(fpkt, icmd, 1); 7085 return; 7086 } 7087 7088 mutex_enter(&ptgt->tgt_mutex); 7089 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7090 FCP_LUN_MARK | FCP_LUN_BUSY); 7091 mutex_exit(&ptgt->tgt_mutex); 7092 7093 (void) fcp_call_finish_init(pptr, ptgt, 7094 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7095 icmd->ipkt_cause); 7096 fcp_icmd_free(pptr, icmd); 7097 return; 7098 } 7099 7100 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7101 int rval = DDI_FAILURE; 7102 7103 /* 7104 * handle cases where report lun isn't supported 7105 * by faking up our own REPORT_LUN response or 7106 * UNIT ATTENTION 7107 */ 7108 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7109 rval = fcp_check_reportlun(rsp, fpkt); 7110 7111 /* 7112 * fcp_check_reportlun might have modified the 7113 * FCP response. Copy it in again to get an updated 7114 * FCP response 7115 */ 7116 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7117 rsp = &response; 7118 7119 FCP_CP_IN(fpkt->pkt_resp, rsp, 7120 fpkt->pkt_resp_acc, 7121 sizeof (struct fcp_rsp)); 7122 } 7123 } 7124 7125 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7126 if (rval == DDI_SUCCESS) { 7127 (void) fcp_call_finish_init(pptr, ptgt, 7128 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7129 icmd->ipkt_cause); 7130 fcp_icmd_free(pptr, icmd); 7131 } else { 7132 fcp_retry_scsi_cmd(fpkt); 7133 } 7134 7135 return; 7136 } 7137 } else { 7138 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7139 mutex_enter(&ptgt->tgt_mutex); 7140 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7141 mutex_exit(&ptgt->tgt_mutex); 7142 } 7143 } 7144 7145 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7146 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7147 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7148 DDI_DMA_SYNC_FORCPU); 7149 } 7150 7151 switch (icmd->ipkt_opcode) { 7152 case SCMD_INQUIRY: 7153 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7154 fcp_handle_inquiry(fpkt, icmd); 7155 break; 7156 7157 case SCMD_REPORT_LUN: 7158 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7159 FCP_TGT_TRACE_22); 7160 fcp_handle_reportlun(fpkt, icmd); 7161 break; 7162 7163 case SCMD_INQUIRY_PAGE83: 7164 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7165 (void) fcp_handle_page83(fpkt, icmd, 0); 7166 break; 7167 7168 default: 7169 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7170 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7171 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7172 fcp_icmd_free(pptr, icmd); 7173 break; 7174 } 7175 } 7176 7177 7178 static void 7179 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7180 { 7181 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7182 fpkt->pkt_ulp_private; 7183 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7184 struct fcp_port *pptr = ptgt->tgt_port; 7185 7186 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7187 fcp_is_retryable(icmd)) { 7188 mutex_enter(&pptr->port_mutex); 7189 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7190 mutex_exit(&pptr->port_mutex); 7191 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7192 fcp_trace, FCP_BUF_LEVEL_3, 0, 7193 "Retrying %s to %x; state=%x, reason=%x", 7194 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7195 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7196 fpkt->pkt_state, fpkt->pkt_reason); 7197 7198 fcp_queue_ipkt(pptr, fpkt); 7199 } else { 7200 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7201 fcp_trace, FCP_BUF_LEVEL_3, 0, 7202 "fcp_retry_scsi_cmd,1: state change occured" 7203 " for D_ID=0x%x", ptgt->tgt_d_id); 7204 mutex_exit(&pptr->port_mutex); 7205 (void) fcp_call_finish_init(pptr, ptgt, 7206 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7207 icmd->ipkt_cause); 7208 fcp_icmd_free(pptr, icmd); 7209 } 7210 } else { 7211 fcp_print_error(fpkt); 7212 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7213 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7214 fcp_icmd_free(pptr, icmd); 7215 } 7216 } 7217 7218 /* 7219 * Function: fcp_handle_page83 7220 * 7221 * Description: Treats the response to INQUIRY_PAGE83. 7222 * 7223 * Argument: *fpkt FC packet used to convey the command. 7224 * *icmd Original fcp_ipkt structure. 7225 * ignore_page83_data 7226 * if it's 1, that means it's a special devices's 7227 * page83 response, it should be enumerated under mpxio 7228 * 7229 * Return Value: None 7230 */ 7231 static void 7232 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7233 int ignore_page83_data) 7234 { 7235 struct fcp_port *pptr; 7236 struct fcp_lun *plun; 7237 struct fcp_tgt *ptgt; 7238 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7239 int fail = 0; 7240 ddi_devid_t devid; 7241 char *guid = NULL; 7242 int ret; 7243 7244 ASSERT(icmd != NULL && fpkt != NULL); 7245 7246 pptr = icmd->ipkt_port; 7247 ptgt = icmd->ipkt_tgt; 7248 plun = icmd->ipkt_lun; 7249 7250 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7251 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7252 7253 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7254 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7255 7256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7257 fcp_trace, FCP_BUF_LEVEL_5, 0, 7258 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7259 "dtype=0x%x, lun num=%x", 7260 pptr->port_instance, ptgt->tgt_d_id, 7261 dev_id_page[0], plun->lun_num); 7262 7263 ret = ddi_devid_scsi_encode( 7264 DEVID_SCSI_ENCODE_VERSION_LATEST, 7265 NULL, /* driver name */ 7266 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7267 sizeof (plun->lun_inq), /* size of standard inquiry */ 7268 NULL, /* page 80 data */ 7269 0, /* page 80 len */ 7270 dev_id_page, /* page 83 data */ 7271 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7272 &devid); 7273 7274 if (ret == DDI_SUCCESS) { 7275 7276 guid = ddi_devid_to_guid(devid); 7277 7278 if (guid) { 7279 /* 7280 * Check our current guid. If it's non null 7281 * and it has changed, we need to copy it into 7282 * lun_old_guid since we might still need it. 7283 */ 7284 if (plun->lun_guid && 7285 strcmp(guid, plun->lun_guid)) { 7286 unsigned int len; 7287 7288 /* 7289 * If the guid of the LUN changes, 7290 * reconfiguration should be triggered 7291 * to reflect the changes. 7292 * i.e. we should offline the LUN with 7293 * the old guid, and online the LUN with 7294 * the new guid. 7295 */ 7296 plun->lun_state |= FCP_LUN_CHANGED; 7297 7298 if (plun->lun_old_guid) { 7299 kmem_free(plun->lun_old_guid, 7300 plun->lun_old_guid_size); 7301 } 7302 7303 len = plun->lun_guid_size; 7304 plun->lun_old_guid_size = len; 7305 7306 plun->lun_old_guid = kmem_zalloc(len, 7307 KM_NOSLEEP); 7308 7309 if (plun->lun_old_guid) { 7310 /* 7311 * The alloc was successful then 7312 * let's do the copy. 7313 */ 7314 bcopy(plun->lun_guid, 7315 plun->lun_old_guid, len); 7316 } else { 7317 fail = 1; 7318 plun->lun_old_guid_size = 0; 7319 } 7320 } 7321 if (!fail) { 7322 if (fcp_copy_guid_2_lun_block( 7323 plun, guid)) { 7324 fail = 1; 7325 } 7326 } 7327 ddi_devid_free_guid(guid); 7328 7329 } else { 7330 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7331 fcp_trace, FCP_BUF_LEVEL_2, 0, 7332 "fcp_handle_page83: unable to create " 7333 "GUID"); 7334 7335 /* couldn't create good guid from devid */ 7336 fail = 1; 7337 } 7338 ddi_devid_free(devid); 7339 7340 } else if (ret == DDI_NOT_WELL_FORMED) { 7341 /* NULL filled data for page 83 */ 7342 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7343 fcp_trace, FCP_BUF_LEVEL_2, 0, 7344 "fcp_handle_page83: retry GUID"); 7345 7346 icmd->ipkt_retries = 0; 7347 fcp_retry_scsi_cmd(fpkt); 7348 return; 7349 } else { 7350 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7351 fcp_trace, FCP_BUF_LEVEL_2, 0, 7352 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7353 ret); 7354 /* 7355 * Since the page83 validation 7356 * introduced late, we are being 7357 * tolerant to the existing devices 7358 * that already found to be working 7359 * under mpxio, like A5200's SES device, 7360 * its page83 response will not be standard-compliant, 7361 * but we still want it to be enumerated under mpxio. 7362 */ 7363 if (fcp_symmetric_device_probe(plun) != 0) { 7364 fail = 1; 7365 } 7366 } 7367 7368 } else { 7369 /* bad packet state */ 7370 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7371 7372 /* 7373 * For some special devices (A5K SES and Daktari's SES devices), 7374 * they should be enumerated under mpxio 7375 * or "luxadm dis" will fail 7376 */ 7377 if (ignore_page83_data) { 7378 fail = 0; 7379 } else { 7380 fail = 1; 7381 } 7382 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7383 fcp_trace, FCP_BUF_LEVEL_2, 0, 7384 "!Devid page cmd failed. " 7385 "fpkt_state: %x fpkt_reason: %x", 7386 "ignore_page83: %d", 7387 fpkt->pkt_state, fpkt->pkt_reason, 7388 ignore_page83_data); 7389 } 7390 7391 mutex_enter(&pptr->port_mutex); 7392 mutex_enter(&plun->lun_mutex); 7393 /* 7394 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7395 * mismatch between lun_cip and lun_mpxio. 7396 */ 7397 if (plun->lun_cip == NULL) { 7398 /* 7399 * If we don't have a guid for this lun it's because we were 7400 * unable to glean one from the page 83 response. Set the 7401 * control flag to 0 here to make sure that we don't attempt to 7402 * enumerate it under mpxio. 7403 */ 7404 if (fail || pptr->port_mpxio == 0) { 7405 plun->lun_mpxio = 0; 7406 } else { 7407 plun->lun_mpxio = 1; 7408 } 7409 } 7410 mutex_exit(&plun->lun_mutex); 7411 mutex_exit(&pptr->port_mutex); 7412 7413 mutex_enter(&ptgt->tgt_mutex); 7414 plun->lun_state &= 7415 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7416 mutex_exit(&ptgt->tgt_mutex); 7417 7418 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7419 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7420 7421 fcp_icmd_free(pptr, icmd); 7422 } 7423 7424 /* 7425 * Function: fcp_handle_inquiry 7426 * 7427 * Description: Called by fcp_scsi_callback to handle the response to an 7428 * INQUIRY request. 7429 * 7430 * Argument: *fpkt FC packet used to convey the command. 7431 * *icmd Original fcp_ipkt structure. 7432 * 7433 * Return Value: None 7434 */ 7435 static void 7436 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7437 { 7438 struct fcp_port *pptr; 7439 struct fcp_lun *plun; 7440 struct fcp_tgt *ptgt; 7441 uchar_t dtype; 7442 uchar_t pqual; 7443 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7444 7445 ASSERT(icmd != NULL && fpkt != NULL); 7446 7447 pptr = icmd->ipkt_port; 7448 ptgt = icmd->ipkt_tgt; 7449 plun = icmd->ipkt_lun; 7450 7451 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7452 sizeof (struct scsi_inquiry)); 7453 7454 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7455 pqual = plun->lun_inq.inq_dtype >> 5; 7456 7457 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7458 fcp_trace, FCP_BUF_LEVEL_5, 0, 7459 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7460 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7461 plun->lun_num, dtype, pqual); 7462 7463 if (pqual != 0) { 7464 /* 7465 * Non-zero peripheral qualifier 7466 */ 7467 fcp_log(CE_CONT, pptr->port_dip, 7468 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7469 "Device type=0x%x Peripheral qual=0x%x\n", 7470 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7471 7472 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7473 fcp_trace, FCP_BUF_LEVEL_5, 0, 7474 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7475 "Device type=0x%x Peripheral qual=0x%x\n", 7476 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7477 7478 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7479 7480 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7481 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7482 fcp_icmd_free(pptr, icmd); 7483 return; 7484 } 7485 7486 /* 7487 * If the device is already initialized, check the dtype 7488 * for a change. If it has changed then update the flags 7489 * so the create_luns will offline the old device and 7490 * create the new device. Refer to bug: 4764752 7491 */ 7492 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7493 plun->lun_state |= FCP_LUN_CHANGED; 7494 } 7495 plun->lun_type = plun->lun_inq.inq_dtype; 7496 7497 /* 7498 * This code is setting/initializing the throttling in the FCA 7499 * driver. 7500 */ 7501 mutex_enter(&pptr->port_mutex); 7502 if (!pptr->port_notify) { 7503 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7504 uint32_t cmd = 0; 7505 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7506 ((cmd & 0xFFFFFF00 >> 8) | 7507 FCP_SVE_THROTTLE << 8)); 7508 pptr->port_notify = 1; 7509 mutex_exit(&pptr->port_mutex); 7510 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7511 mutex_enter(&pptr->port_mutex); 7512 } 7513 } 7514 7515 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7516 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7517 fcp_trace, FCP_BUF_LEVEL_2, 0, 7518 "fcp_handle_inquiry,1:state change occured" 7519 " for D_ID=0x%x", ptgt->tgt_d_id); 7520 mutex_exit(&pptr->port_mutex); 7521 7522 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7523 (void) fcp_call_finish_init(pptr, ptgt, 7524 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7525 icmd->ipkt_cause); 7526 fcp_icmd_free(pptr, icmd); 7527 return; 7528 } 7529 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7530 mutex_exit(&pptr->port_mutex); 7531 7532 /* Retrieve the rscn count (if a valid one exists) */ 7533 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7534 rscn_count = ((fc_ulp_rscn_info_t *) 7535 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7536 } else { 7537 rscn_count = FC_INVALID_RSCN_COUNT; 7538 } 7539 7540 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7541 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7542 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7543 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7544 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7545 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7546 (void) fcp_call_finish_init(pptr, ptgt, 7547 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7548 icmd->ipkt_cause); 7549 } 7550 7551 /* 7552 * Read Inquiry VPD Page 0x83 to uniquely 7553 * identify this logical unit. 7554 */ 7555 fcp_icmd_free(pptr, icmd); 7556 } 7557 7558 /* 7559 * Function: fcp_handle_reportlun 7560 * 7561 * Description: Called by fcp_scsi_callback to handle the response to a 7562 * REPORT_LUN request. 7563 * 7564 * Argument: *fpkt FC packet used to convey the command. 7565 * *icmd Original fcp_ipkt structure. 7566 * 7567 * Return Value: None 7568 */ 7569 static void 7570 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7571 { 7572 int i; 7573 int nluns_claimed; 7574 int nluns_bufmax; 7575 int len; 7576 uint16_t lun_num; 7577 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7578 struct fcp_port *pptr; 7579 struct fcp_tgt *ptgt; 7580 struct fcp_lun *plun; 7581 struct fcp_reportlun_resp *report_lun; 7582 7583 pptr = icmd->ipkt_port; 7584 ptgt = icmd->ipkt_tgt; 7585 len = fpkt->pkt_datalen; 7586 7587 if ((len < FCP_LUN_HEADER) || 7588 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7589 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7590 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7591 fcp_icmd_free(pptr, icmd); 7592 return; 7593 } 7594 7595 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7596 fpkt->pkt_datalen); 7597 7598 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7599 fcp_trace, FCP_BUF_LEVEL_5, 0, 7600 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7601 pptr->port_instance, ptgt->tgt_d_id); 7602 7603 /* 7604 * Get the number of luns (which is supplied as LUNS * 8) the 7605 * device claims it has. 7606 */ 7607 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7608 7609 /* 7610 * Get the maximum number of luns the buffer submitted can hold. 7611 */ 7612 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7613 7614 /* 7615 * Due to limitations of certain hardware, we support only 16 bit LUNs 7616 */ 7617 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7618 kmem_free(report_lun, len); 7619 7620 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7621 " 0x%x number of LUNs for target=%x", nluns_claimed, 7622 ptgt->tgt_d_id); 7623 7624 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7625 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7626 fcp_icmd_free(pptr, icmd); 7627 return; 7628 } 7629 7630 /* 7631 * If there are more LUNs than we have allocated memory for, 7632 * allocate more space and send down yet another report lun if 7633 * the maximum number of attempts hasn't been reached. 7634 */ 7635 mutex_enter(&ptgt->tgt_mutex); 7636 7637 if ((nluns_claimed > nluns_bufmax) && 7638 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7639 7640 struct fcp_lun *plun; 7641 7642 ptgt->tgt_report_lun_cnt++; 7643 plun = ptgt->tgt_lun; 7644 ASSERT(plun != NULL); 7645 mutex_exit(&ptgt->tgt_mutex); 7646 7647 kmem_free(report_lun, len); 7648 7649 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7650 fcp_trace, FCP_BUF_LEVEL_5, 0, 7651 "!Dynamically discovered %d LUNs for D_ID=%x", 7652 nluns_claimed, ptgt->tgt_d_id); 7653 7654 /* Retrieve the rscn count (if a valid one exists) */ 7655 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7656 rscn_count = ((fc_ulp_rscn_info_t *) 7657 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7658 ulp_rscn_count; 7659 } else { 7660 rscn_count = FC_INVALID_RSCN_COUNT; 7661 } 7662 7663 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7664 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7665 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7666 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7667 (void) fcp_call_finish_init(pptr, ptgt, 7668 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7669 icmd->ipkt_cause); 7670 } 7671 7672 fcp_icmd_free(pptr, icmd); 7673 return; 7674 } 7675 7676 if (nluns_claimed > nluns_bufmax) { 7677 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7678 fcp_trace, FCP_BUF_LEVEL_5, 0, 7679 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7680 " Number of LUNs lost=%x", 7681 ptgt->tgt_port_wwn.raw_wwn[0], 7682 ptgt->tgt_port_wwn.raw_wwn[1], 7683 ptgt->tgt_port_wwn.raw_wwn[2], 7684 ptgt->tgt_port_wwn.raw_wwn[3], 7685 ptgt->tgt_port_wwn.raw_wwn[4], 7686 ptgt->tgt_port_wwn.raw_wwn[5], 7687 ptgt->tgt_port_wwn.raw_wwn[6], 7688 ptgt->tgt_port_wwn.raw_wwn[7], 7689 nluns_claimed - nluns_bufmax); 7690 7691 nluns_claimed = nluns_bufmax; 7692 } 7693 ptgt->tgt_lun_cnt = nluns_claimed; 7694 7695 /* 7696 * Identify missing LUNs and print warning messages 7697 */ 7698 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7699 int offline; 7700 int exists = 0; 7701 7702 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7703 7704 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7705 uchar_t *lun_string; 7706 7707 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7708 7709 switch (lun_string[0] & 0xC0) { 7710 case FCP_LUN_ADDRESSING: 7711 case FCP_PD_ADDRESSING: 7712 case FCP_VOLUME_ADDRESSING: 7713 lun_num = ((lun_string[0] & 0x3F) << 8) | 7714 lun_string[1]; 7715 if (plun->lun_num == lun_num) { 7716 exists++; 7717 break; 7718 } 7719 break; 7720 7721 default: 7722 break; 7723 } 7724 } 7725 7726 if (!exists && !offline) { 7727 mutex_exit(&ptgt->tgt_mutex); 7728 7729 mutex_enter(&pptr->port_mutex); 7730 mutex_enter(&ptgt->tgt_mutex); 7731 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7732 /* 7733 * set disappear flag when device was connected 7734 */ 7735 if (!(plun->lun_state & 7736 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7737 plun->lun_state |= FCP_LUN_DISAPPEARED; 7738 } 7739 mutex_exit(&ptgt->tgt_mutex); 7740 mutex_exit(&pptr->port_mutex); 7741 if (!(plun->lun_state & 7742 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7743 fcp_log(CE_NOTE, pptr->port_dip, 7744 "!Lun=%x for target=%x disappeared", 7745 plun->lun_num, ptgt->tgt_d_id); 7746 } 7747 mutex_enter(&ptgt->tgt_mutex); 7748 } else { 7749 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7750 fcp_trace, FCP_BUF_LEVEL_5, 0, 7751 "fcp_handle_reportlun,1: state change" 7752 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7753 mutex_exit(&ptgt->tgt_mutex); 7754 mutex_exit(&pptr->port_mutex); 7755 kmem_free(report_lun, len); 7756 (void) fcp_call_finish_init(pptr, ptgt, 7757 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7758 icmd->ipkt_cause); 7759 fcp_icmd_free(pptr, icmd); 7760 return; 7761 } 7762 } else if (exists) { 7763 /* 7764 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7765 * actually exists in REPORT_LUN response 7766 */ 7767 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7768 plun->lun_state &= 7769 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7770 } 7771 if (offline || plun->lun_num == 0) { 7772 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7773 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7774 mutex_exit(&ptgt->tgt_mutex); 7775 fcp_log(CE_NOTE, pptr->port_dip, 7776 "!Lun=%x for target=%x reappeared", 7777 plun->lun_num, ptgt->tgt_d_id); 7778 mutex_enter(&ptgt->tgt_mutex); 7779 } 7780 } 7781 } 7782 } 7783 7784 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7785 mutex_exit(&ptgt->tgt_mutex); 7786 7787 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7788 fcp_trace, FCP_BUF_LEVEL_5, 0, 7789 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7790 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7791 7792 /* scan each lun */ 7793 for (i = 0; i < nluns_claimed; i++) { 7794 uchar_t *lun_string; 7795 7796 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7797 7798 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7799 fcp_trace, FCP_BUF_LEVEL_5, 0, 7800 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7801 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7802 lun_string[0]); 7803 7804 switch (lun_string[0] & 0xC0) { 7805 case FCP_LUN_ADDRESSING: 7806 case FCP_PD_ADDRESSING: 7807 case FCP_VOLUME_ADDRESSING: 7808 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7809 7810 /* We will skip masked LUNs because of the blacklist. */ 7811 if (fcp_lun_blacklist != NULL) { 7812 mutex_enter(&ptgt->tgt_mutex); 7813 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7814 lun_num) == TRUE) { 7815 ptgt->tgt_lun_cnt--; 7816 mutex_exit(&ptgt->tgt_mutex); 7817 break; 7818 } 7819 mutex_exit(&ptgt->tgt_mutex); 7820 } 7821 7822 /* see if this LUN is already allocated */ 7823 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7824 plun = fcp_alloc_lun(ptgt); 7825 if (plun == NULL) { 7826 fcp_log(CE_NOTE, pptr->port_dip, 7827 "!Lun allocation failed" 7828 " target=%x lun=%x", 7829 ptgt->tgt_d_id, lun_num); 7830 break; 7831 } 7832 } 7833 7834 mutex_enter(&plun->lun_tgt->tgt_mutex); 7835 /* convert to LUN */ 7836 plun->lun_addr.ent_addr_0 = 7837 BE_16(*(uint16_t *)&(lun_string[0])); 7838 plun->lun_addr.ent_addr_1 = 7839 BE_16(*(uint16_t *)&(lun_string[2])); 7840 plun->lun_addr.ent_addr_2 = 7841 BE_16(*(uint16_t *)&(lun_string[4])); 7842 plun->lun_addr.ent_addr_3 = 7843 BE_16(*(uint16_t *)&(lun_string[6])); 7844 7845 plun->lun_num = lun_num; 7846 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7847 plun->lun_state &= ~FCP_LUN_OFFLINE; 7848 mutex_exit(&plun->lun_tgt->tgt_mutex); 7849 7850 /* Retrieve the rscn count (if a valid one exists) */ 7851 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7852 rscn_count = ((fc_ulp_rscn_info_t *) 7853 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7854 ulp_rscn_count; 7855 } else { 7856 rscn_count = FC_INVALID_RSCN_COUNT; 7857 } 7858 7859 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7860 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7861 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7862 mutex_enter(&pptr->port_mutex); 7863 mutex_enter(&plun->lun_tgt->tgt_mutex); 7864 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7865 fcp_log(CE_NOTE, pptr->port_dip, 7866 "!failed to send INQUIRY" 7867 " target=%x lun=%x", 7868 ptgt->tgt_d_id, plun->lun_num); 7869 } else { 7870 FCP_TRACE(fcp_logq, 7871 pptr->port_instbuf, fcp_trace, 7872 FCP_BUF_LEVEL_5, 0, 7873 "fcp_handle_reportlun,2: state" 7874 " change occured for D_ID=0x%x", 7875 ptgt->tgt_d_id); 7876 } 7877 mutex_exit(&plun->lun_tgt->tgt_mutex); 7878 mutex_exit(&pptr->port_mutex); 7879 } else { 7880 continue; 7881 } 7882 break; 7883 7884 default: 7885 fcp_log(CE_WARN, NULL, 7886 "!Unsupported LUN Addressing method %x " 7887 "in response to REPORT_LUN", lun_string[0]); 7888 break; 7889 } 7890 7891 /* 7892 * each time through this loop we should decrement 7893 * the tmp_cnt by one -- since we go through this loop 7894 * one time for each LUN, the tmp_cnt should never be <=0 7895 */ 7896 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7897 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7898 } 7899 7900 if (i == 0) { 7901 fcp_log(CE_WARN, pptr->port_dip, 7902 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7903 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7904 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7905 } 7906 7907 kmem_free(report_lun, len); 7908 fcp_icmd_free(pptr, icmd); 7909 } 7910 7911 7912 /* 7913 * called internally to return a LUN given a target and a LUN number 7914 */ 7915 static struct fcp_lun * 7916 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7917 { 7918 struct fcp_lun *plun; 7919 7920 mutex_enter(&ptgt->tgt_mutex); 7921 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7922 if (plun->lun_num == lun_num) { 7923 mutex_exit(&ptgt->tgt_mutex); 7924 return (plun); 7925 } 7926 } 7927 mutex_exit(&ptgt->tgt_mutex); 7928 7929 return (NULL); 7930 } 7931 7932 7933 /* 7934 * handle finishing one target for fcp_finish_init 7935 * 7936 * return true (non-zero) if we want finish_init to continue with the 7937 * next target 7938 * 7939 * called with the port mutex held 7940 */ 7941 /*ARGSUSED*/ 7942 static int 7943 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7944 int link_cnt, int tgt_cnt, int cause) 7945 { 7946 int rval = 1; 7947 ASSERT(pptr != NULL); 7948 ASSERT(ptgt != NULL); 7949 7950 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7951 fcp_trace, FCP_BUF_LEVEL_5, 0, 7952 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7953 ptgt->tgt_state); 7954 7955 ASSERT(mutex_owned(&pptr->port_mutex)); 7956 7957 if ((pptr->port_link_cnt != link_cnt) || 7958 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7959 /* 7960 * oh oh -- another link reset or target change 7961 * must have occurred while we are in here 7962 */ 7963 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7964 7965 return (0); 7966 } else { 7967 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7968 } 7969 7970 mutex_enter(&ptgt->tgt_mutex); 7971 7972 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7973 /* 7974 * tgt is not offline -- is it marked (i.e. needs 7975 * to be offlined) ?? 7976 */ 7977 if (ptgt->tgt_state & FCP_TGT_MARK) { 7978 /* 7979 * this target not offline *and* 7980 * marked 7981 */ 7982 ptgt->tgt_state &= ~FCP_TGT_MARK; 7983 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7984 tgt_cnt, 0, 0); 7985 } else { 7986 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7987 7988 /* create the LUNs */ 7989 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7990 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7991 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7992 cause); 7993 ptgt->tgt_device_created = 1; 7994 } else { 7995 fcp_update_tgt_state(ptgt, FCP_RESET, 7996 FCP_LUN_BUSY); 7997 } 7998 } 7999 } 8000 8001 mutex_exit(&ptgt->tgt_mutex); 8002 8003 return (rval); 8004 } 8005 8006 8007 /* 8008 * this routine is called to finish port initialization 8009 * 8010 * Each port has a "temp" counter -- when a state change happens (e.g. 8011 * port online), the temp count is set to the number of devices in the map. 8012 * Then, as each device gets "discovered", the temp counter is decremented 8013 * by one. When this count reaches zero we know that all of the devices 8014 * in the map have been discovered (or an error has occurred), so we can 8015 * then finish initialization -- which is done by this routine (well, this 8016 * and fcp-finish_tgt()) 8017 * 8018 * acquires and releases the global mutex 8019 * 8020 * called with the port mutex owned 8021 */ 8022 static void 8023 fcp_finish_init(struct fcp_port *pptr) 8024 { 8025 #ifdef DEBUG 8026 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8027 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8028 FCP_STACK_DEPTH); 8029 #endif /* DEBUG */ 8030 8031 ASSERT(mutex_owned(&pptr->port_mutex)); 8032 8033 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8034 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8035 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8036 8037 if ((pptr->port_state & FCP_STATE_ONLINING) && 8038 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8039 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8040 pptr->port_state &= ~FCP_STATE_ONLINING; 8041 pptr->port_state |= FCP_STATE_ONLINE; 8042 } 8043 8044 /* Wake up threads waiting on config done */ 8045 cv_broadcast(&pptr->port_config_cv); 8046 } 8047 8048 8049 /* 8050 * called from fcp_finish_init to create the LUNs for a target 8051 * 8052 * called with the port mutex owned 8053 */ 8054 static void 8055 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8056 { 8057 struct fcp_lun *plun; 8058 struct fcp_port *pptr; 8059 child_info_t *cip = NULL; 8060 8061 ASSERT(ptgt != NULL); 8062 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8063 8064 pptr = ptgt->tgt_port; 8065 8066 ASSERT(pptr != NULL); 8067 8068 /* scan all LUNs for this target */ 8069 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8070 if (plun->lun_state & FCP_LUN_OFFLINE) { 8071 continue; 8072 } 8073 8074 if (plun->lun_state & FCP_LUN_MARK) { 8075 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8076 fcp_trace, FCP_BUF_LEVEL_2, 0, 8077 "fcp_create_luns: offlining marked LUN!"); 8078 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8079 continue; 8080 } 8081 8082 plun->lun_state &= ~FCP_LUN_BUSY; 8083 8084 /* 8085 * There are conditions in which FCP_LUN_INIT flag is cleared 8086 * but we have a valid plun->lun_cip. To cover this case also 8087 * CLEAR_BUSY whenever we have a valid lun_cip. 8088 */ 8089 if (plun->lun_mpxio && plun->lun_cip && 8090 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8091 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8092 0, 0))) { 8093 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8094 fcp_trace, FCP_BUF_LEVEL_2, 0, 8095 "fcp_create_luns: enable lun %p failed!", 8096 plun); 8097 } 8098 8099 if (plun->lun_state & FCP_LUN_INIT && 8100 !(plun->lun_state & FCP_LUN_CHANGED)) { 8101 continue; 8102 } 8103 8104 if (cause == FCP_CAUSE_USER_CREATE) { 8105 continue; 8106 } 8107 8108 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8109 fcp_trace, FCP_BUF_LEVEL_6, 0, 8110 "create_luns: passing ONLINE elem to HP thread"); 8111 8112 /* 8113 * If lun has changed, prepare for offlining the old path. 8114 * Do not offline the old path right now, since it may be 8115 * still opened. 8116 */ 8117 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8118 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8119 } 8120 8121 /* pass an ONLINE element to the hotplug thread */ 8122 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8123 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8124 8125 /* 8126 * We can not synchronous attach (i.e pass 8127 * NDI_ONLINE_ATTACH) here as we might be 8128 * coming from an interrupt or callback 8129 * thread. 8130 */ 8131 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8132 link_cnt, tgt_cnt, 0, 0)) { 8133 fcp_log(CE_CONT, pptr->port_dip, 8134 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8135 plun->lun_tgt->tgt_d_id, plun->lun_num); 8136 } 8137 } 8138 } 8139 } 8140 8141 8142 /* 8143 * function to online/offline devices 8144 */ 8145 static int 8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8147 int online, int lcount, int tcount, int flags) 8148 { 8149 int rval = NDI_FAILURE; 8150 int circ; 8151 child_info_t *ccip; 8152 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8153 int is_mpxio = pptr->port_mpxio; 8154 dev_info_t *cdip, *pdip; 8155 char *devname; 8156 8157 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8158 /* 8159 * When this event gets serviced, lun_cip and lun_mpxio 8160 * has changed, so it should be invalidated now. 8161 */ 8162 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8163 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8164 "plun: %p, cip: %p, what:%d", plun, cip, online); 8165 return (rval); 8166 } 8167 8168 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8169 fcp_trace, FCP_BUF_LEVEL_2, 0, 8170 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8171 "flags=%x mpxio=%x\n", 8172 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8173 plun->lun_mpxio); 8174 8175 /* 8176 * lun_mpxio needs checking here because we can end up in a race 8177 * condition where this task has been dispatched while lun_mpxio is 8178 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8179 * enable MPXIO for the LUN, but was unable to, and hence cleared 8180 * the flag. We rely on the serialization of the tasks here. We return 8181 * NDI_SUCCESS so any callers continue without reporting spurious 8182 * errors, and the still think we're an MPXIO LUN. 8183 */ 8184 8185 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8186 online == FCP_MPXIO_PATH_SET_BUSY) { 8187 if (plun->lun_mpxio) { 8188 rval = fcp_update_mpxio_path(plun, cip, online); 8189 } else { 8190 rval = NDI_SUCCESS; 8191 } 8192 return (rval); 8193 } 8194 8195 /* 8196 * Explicit devfs_clean() due to ndi_devi_offline() not 8197 * executing devfs_clean() if parent lock is held. 8198 */ 8199 ASSERT(!servicing_interrupt()); 8200 if (online == FCP_OFFLINE) { 8201 if (plun->lun_mpxio == 0) { 8202 if (plun->lun_cip == cip) { 8203 cdip = DIP(plun->lun_cip); 8204 } else { 8205 cdip = DIP(cip); 8206 } 8207 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8208 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8209 } else if ((plun->lun_cip != cip) && cip) { 8210 /* 8211 * This means a DTYPE/GUID change, we shall get the 8212 * dip of the old cip instead of the current lun_cip. 8213 */ 8214 cdip = mdi_pi_get_client(PIP(cip)); 8215 } 8216 if (cdip) { 8217 if (i_ddi_devi_attached(cdip)) { 8218 pdip = ddi_get_parent(cdip); 8219 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8220 ndi_devi_enter(pdip, &circ); 8221 (void) ddi_deviname(cdip, devname); 8222 /* 8223 * Release parent lock before calling 8224 * devfs_clean(). 8225 */ 8226 ndi_devi_exit(pdip, circ); 8227 (void) devfs_clean(pdip, devname + 1, 8228 DV_CLEAN_FORCE); 8229 kmem_free(devname, MAXNAMELEN + 1); 8230 } 8231 } 8232 } 8233 8234 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8235 return (NDI_FAILURE); 8236 } 8237 8238 if (is_mpxio) { 8239 mdi_devi_enter(pptr->port_dip, &circ); 8240 } else { 8241 ndi_devi_enter(pptr->port_dip, &circ); 8242 } 8243 8244 mutex_enter(&pptr->port_mutex); 8245 mutex_enter(&plun->lun_mutex); 8246 8247 if (online == FCP_ONLINE) { 8248 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8249 if (ccip == NULL) { 8250 goto fail; 8251 } 8252 } else { 8253 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8254 goto fail; 8255 } 8256 ccip = cip; 8257 } 8258 8259 if (online == FCP_ONLINE) { 8260 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8261 &circ); 8262 fc_ulp_log_device_event(pptr->port_fp_handle, 8263 FC_ULP_DEVICE_ONLINE); 8264 } else { 8265 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8266 &circ); 8267 fc_ulp_log_device_event(pptr->port_fp_handle, 8268 FC_ULP_DEVICE_OFFLINE); 8269 } 8270 8271 fail: mutex_exit(&plun->lun_mutex); 8272 mutex_exit(&pptr->port_mutex); 8273 8274 if (is_mpxio) { 8275 mdi_devi_exit(pptr->port_dip, circ); 8276 } else { 8277 ndi_devi_exit(pptr->port_dip, circ); 8278 } 8279 8280 fc_ulp_idle_port(pptr->port_fp_handle); 8281 8282 return (rval); 8283 } 8284 8285 8286 /* 8287 * take a target offline by taking all of its LUNs offline 8288 */ 8289 /*ARGSUSED*/ 8290 static int 8291 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8292 int link_cnt, int tgt_cnt, int nowait, int flags) 8293 { 8294 struct fcp_tgt_elem *elem; 8295 8296 ASSERT(mutex_owned(&pptr->port_mutex)); 8297 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8298 8299 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8300 8301 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8302 ptgt->tgt_change_cnt)) { 8303 mutex_exit(&ptgt->tgt_mutex); 8304 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8305 mutex_enter(&ptgt->tgt_mutex); 8306 8307 return (0); 8308 } 8309 8310 ptgt->tgt_pd_handle = NULL; 8311 mutex_exit(&ptgt->tgt_mutex); 8312 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8313 mutex_enter(&ptgt->tgt_mutex); 8314 8315 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8316 8317 if (ptgt->tgt_tcap && 8318 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8319 elem->flags = flags; 8320 elem->time = fcp_watchdog_time; 8321 if (nowait == 0) { 8322 elem->time += fcp_offline_delay; 8323 } 8324 elem->ptgt = ptgt; 8325 elem->link_cnt = link_cnt; 8326 elem->tgt_cnt = tgt_cnt; 8327 elem->next = pptr->port_offline_tgts; 8328 pptr->port_offline_tgts = elem; 8329 } else { 8330 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8331 } 8332 8333 return (1); 8334 } 8335 8336 8337 static void 8338 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8339 int link_cnt, int tgt_cnt, int flags) 8340 { 8341 ASSERT(mutex_owned(&pptr->port_mutex)); 8342 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8343 8344 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8345 ptgt->tgt_state = FCP_TGT_OFFLINE; 8346 ptgt->tgt_pd_handle = NULL; 8347 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8348 } 8349 8350 8351 static void 8352 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8353 int flags) 8354 { 8355 struct fcp_lun *plun; 8356 8357 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8358 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8359 8360 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8361 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8362 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8363 } 8364 } 8365 } 8366 8367 8368 /* 8369 * take a LUN offline 8370 * 8371 * enters and leaves with the target mutex held, releasing it in the process 8372 * 8373 * allocates memory in non-sleep mode 8374 */ 8375 static void 8376 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8377 int nowait, int flags) 8378 { 8379 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8380 struct fcp_lun_elem *elem; 8381 8382 ASSERT(plun != NULL); 8383 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8384 8385 if (nowait) { 8386 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8387 return; 8388 } 8389 8390 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8391 elem->flags = flags; 8392 elem->time = fcp_watchdog_time; 8393 if (nowait == 0) { 8394 elem->time += fcp_offline_delay; 8395 } 8396 elem->plun = plun; 8397 elem->link_cnt = link_cnt; 8398 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8399 elem->next = pptr->port_offline_luns; 8400 pptr->port_offline_luns = elem; 8401 } else { 8402 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8403 } 8404 } 8405 8406 8407 static void 8408 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8409 { 8410 struct fcp_pkt *head = NULL; 8411 8412 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8413 8414 mutex_exit(&LUN_TGT->tgt_mutex); 8415 8416 head = fcp_scan_commands(plun); 8417 if (head != NULL) { 8418 fcp_abort_commands(head, LUN_PORT); 8419 } 8420 8421 mutex_enter(&LUN_TGT->tgt_mutex); 8422 8423 if (plun->lun_cip && plun->lun_mpxio) { 8424 /* 8425 * Intimate MPxIO lun busy is cleared 8426 */ 8427 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8428 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8429 0, 0)) { 8430 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8431 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8432 LUN_TGT->tgt_d_id, plun->lun_num); 8433 } 8434 /* 8435 * Intimate MPxIO that the lun is now marked for offline 8436 */ 8437 mutex_exit(&LUN_TGT->tgt_mutex); 8438 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8439 mutex_enter(&LUN_TGT->tgt_mutex); 8440 } 8441 } 8442 8443 static void 8444 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8445 int flags) 8446 { 8447 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8448 8449 mutex_exit(&LUN_TGT->tgt_mutex); 8450 fcp_update_offline_flags(plun); 8451 mutex_enter(&LUN_TGT->tgt_mutex); 8452 8453 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8454 8455 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8456 fcp_trace, FCP_BUF_LEVEL_4, 0, 8457 "offline_lun: passing OFFLINE elem to HP thread"); 8458 8459 if (plun->lun_cip) { 8460 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8461 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8462 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8463 LUN_TGT->tgt_trace); 8464 8465 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8466 link_cnt, tgt_cnt, flags, 0)) { 8467 fcp_log(CE_CONT, LUN_PORT->port_dip, 8468 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8469 LUN_TGT->tgt_d_id, plun->lun_num); 8470 } 8471 } 8472 } 8473 8474 static void 8475 fcp_scan_offline_luns(struct fcp_port *pptr) 8476 { 8477 struct fcp_lun_elem *elem; 8478 struct fcp_lun_elem *prev; 8479 struct fcp_lun_elem *next; 8480 8481 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8482 8483 prev = NULL; 8484 elem = pptr->port_offline_luns; 8485 while (elem) { 8486 next = elem->next; 8487 if (elem->time <= fcp_watchdog_time) { 8488 int changed = 1; 8489 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8490 8491 mutex_enter(&ptgt->tgt_mutex); 8492 if (pptr->port_link_cnt == elem->link_cnt && 8493 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8494 changed = 0; 8495 } 8496 8497 if (!changed && 8498 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8499 fcp_offline_lun_now(elem->plun, 8500 elem->link_cnt, elem->tgt_cnt, elem->flags); 8501 } 8502 mutex_exit(&ptgt->tgt_mutex); 8503 8504 kmem_free(elem, sizeof (*elem)); 8505 8506 if (prev) { 8507 prev->next = next; 8508 } else { 8509 pptr->port_offline_luns = next; 8510 } 8511 } else { 8512 prev = elem; 8513 } 8514 elem = next; 8515 } 8516 } 8517 8518 8519 static void 8520 fcp_scan_offline_tgts(struct fcp_port *pptr) 8521 { 8522 struct fcp_tgt_elem *elem; 8523 struct fcp_tgt_elem *prev; 8524 struct fcp_tgt_elem *next; 8525 8526 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8527 8528 prev = NULL; 8529 elem = pptr->port_offline_tgts; 8530 while (elem) { 8531 next = elem->next; 8532 if (elem->time <= fcp_watchdog_time) { 8533 int outdated = 1; 8534 struct fcp_tgt *ptgt = elem->ptgt; 8535 8536 mutex_enter(&ptgt->tgt_mutex); 8537 8538 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8539 /* No change on tgt since elem was created. */ 8540 outdated = 0; 8541 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8542 pptr->port_link_cnt == elem->link_cnt + 1 && 8543 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8544 /* 8545 * Exactly one thing happened to the target 8546 * inbetween: the local port went offline. 8547 * For fp the remote port is already gone so 8548 * it will not tell us again to offline the 8549 * target. We must offline it now. 8550 */ 8551 outdated = 0; 8552 } 8553 8554 if (!outdated && !(ptgt->tgt_state & 8555 FCP_TGT_OFFLINE)) { 8556 fcp_offline_target_now(pptr, 8557 ptgt, elem->link_cnt, elem->tgt_cnt, 8558 elem->flags); 8559 } 8560 8561 mutex_exit(&ptgt->tgt_mutex); 8562 8563 kmem_free(elem, sizeof (*elem)); 8564 8565 if (prev) { 8566 prev->next = next; 8567 } else { 8568 pptr->port_offline_tgts = next; 8569 } 8570 } else { 8571 prev = elem; 8572 } 8573 elem = next; 8574 } 8575 } 8576 8577 8578 static void 8579 fcp_update_offline_flags(struct fcp_lun *plun) 8580 { 8581 struct fcp_port *pptr = LUN_PORT; 8582 ASSERT(plun != NULL); 8583 8584 mutex_enter(&LUN_TGT->tgt_mutex); 8585 plun->lun_state |= FCP_LUN_OFFLINE; 8586 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8587 8588 mutex_enter(&plun->lun_mutex); 8589 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8590 dev_info_t *cdip = NULL; 8591 8592 mutex_exit(&LUN_TGT->tgt_mutex); 8593 8594 if (plun->lun_mpxio == 0) { 8595 cdip = DIP(plun->lun_cip); 8596 } else if (plun->lun_cip) { 8597 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8598 } 8599 8600 mutex_exit(&plun->lun_mutex); 8601 if (cdip) { 8602 (void) ndi_event_retrieve_cookie( 8603 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8604 &fcp_remove_eid, NDI_EVENT_NOPASS); 8605 (void) ndi_event_run_callbacks( 8606 pptr->port_ndi_event_hdl, cdip, 8607 fcp_remove_eid, NULL); 8608 } 8609 } else { 8610 mutex_exit(&plun->lun_mutex); 8611 mutex_exit(&LUN_TGT->tgt_mutex); 8612 } 8613 } 8614 8615 8616 /* 8617 * Scan all of the command pkts for this port, moving pkts that 8618 * match our LUN onto our own list (headed by "head") 8619 */ 8620 static struct fcp_pkt * 8621 fcp_scan_commands(struct fcp_lun *plun) 8622 { 8623 struct fcp_port *pptr = LUN_PORT; 8624 8625 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8626 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8627 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8628 8629 struct fcp_pkt *head = NULL; /* head of our list */ 8630 struct fcp_pkt *tail = NULL; /* tail of our list */ 8631 8632 int cmds_found = 0; 8633 8634 mutex_enter(&pptr->port_pkt_mutex); 8635 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8636 struct fcp_lun *tlun = 8637 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8638 8639 ncmd = cmd->cmd_next; /* set next command */ 8640 8641 /* 8642 * if this pkt is for a different LUN or the 8643 * command is sent down, skip it. 8644 */ 8645 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8646 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8647 pcmd = cmd; 8648 continue; 8649 } 8650 cmds_found++; 8651 if (pcmd != NULL) { 8652 ASSERT(pptr->port_pkt_head != cmd); 8653 pcmd->cmd_next = cmd->cmd_next; 8654 } else { 8655 ASSERT(cmd == pptr->port_pkt_head); 8656 pptr->port_pkt_head = cmd->cmd_next; 8657 } 8658 8659 if (cmd == pptr->port_pkt_tail) { 8660 pptr->port_pkt_tail = pcmd; 8661 if (pcmd) { 8662 pcmd->cmd_next = NULL; 8663 } 8664 } 8665 8666 if (head == NULL) { 8667 head = tail = cmd; 8668 } else { 8669 ASSERT(tail != NULL); 8670 8671 tail->cmd_next = cmd; 8672 tail = cmd; 8673 } 8674 cmd->cmd_next = NULL; 8675 } 8676 mutex_exit(&pptr->port_pkt_mutex); 8677 8678 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8679 fcp_trace, FCP_BUF_LEVEL_8, 0, 8680 "scan commands: %d cmd(s) found", cmds_found); 8681 8682 return (head); 8683 } 8684 8685 8686 /* 8687 * Abort all the commands in the command queue 8688 */ 8689 static void 8690 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8691 { 8692 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8693 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8694 8695 ASSERT(mutex_owned(&pptr->port_mutex)); 8696 8697 /* scan through the pkts and invalid them */ 8698 for (cmd = head; cmd != NULL; cmd = ncmd) { 8699 struct scsi_pkt *pkt = cmd->cmd_pkt; 8700 8701 ncmd = cmd->cmd_next; 8702 ASSERT(pkt != NULL); 8703 8704 /* 8705 * The lun is going to be marked offline. Indicate 8706 * the target driver not to requeue or retry this command 8707 * as the device is going to be offlined pretty soon. 8708 */ 8709 pkt->pkt_reason = CMD_DEV_GONE; 8710 pkt->pkt_statistics = 0; 8711 pkt->pkt_state = 0; 8712 8713 /* reset cmd flags/state */ 8714 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8715 cmd->cmd_state = FCP_PKT_IDLE; 8716 8717 /* 8718 * ensure we have a packet completion routine, 8719 * then call it. 8720 */ 8721 ASSERT(pkt->pkt_comp != NULL); 8722 8723 mutex_exit(&pptr->port_mutex); 8724 fcp_post_callback(cmd); 8725 mutex_enter(&pptr->port_mutex); 8726 } 8727 } 8728 8729 8730 /* 8731 * the pkt_comp callback for command packets 8732 */ 8733 static void 8734 fcp_cmd_callback(fc_packet_t *fpkt) 8735 { 8736 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8737 struct scsi_pkt *pkt = cmd->cmd_pkt; 8738 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8739 8740 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8741 8742 if (cmd->cmd_state == FCP_PKT_IDLE) { 8743 cmn_err(CE_PANIC, "Packet already completed %p", 8744 (void *)cmd); 8745 } 8746 8747 /* 8748 * Watch thread should be freeing the packet, ignore the pkt. 8749 */ 8750 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8751 fcp_log(CE_CONT, pptr->port_dip, 8752 "!FCP: Pkt completed while aborting\n"); 8753 return; 8754 } 8755 cmd->cmd_state = FCP_PKT_IDLE; 8756 8757 fcp_complete_pkt(fpkt); 8758 8759 #ifdef DEBUG 8760 mutex_enter(&pptr->port_pkt_mutex); 8761 pptr->port_npkts--; 8762 mutex_exit(&pptr->port_pkt_mutex); 8763 #endif /* DEBUG */ 8764 8765 fcp_post_callback(cmd); 8766 } 8767 8768 8769 static void 8770 fcp_complete_pkt(fc_packet_t *fpkt) 8771 { 8772 int error = 0; 8773 struct fcp_pkt *cmd = (struct fcp_pkt *) 8774 fpkt->pkt_ulp_private; 8775 struct scsi_pkt *pkt = cmd->cmd_pkt; 8776 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8777 struct fcp_lun *plun; 8778 struct fcp_tgt *ptgt; 8779 struct fcp_rsp *rsp; 8780 struct scsi_address save; 8781 8782 #ifdef DEBUG 8783 save = pkt->pkt_address; 8784 #endif /* DEBUG */ 8785 8786 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8787 8788 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8789 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8790 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8791 sizeof (struct fcp_rsp)); 8792 } 8793 8794 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8795 STATE_SENT_CMD | STATE_GOT_STATUS; 8796 8797 pkt->pkt_resid = 0; 8798 8799 if (fpkt->pkt_datalen) { 8800 pkt->pkt_state |= STATE_XFERRED_DATA; 8801 if (fpkt->pkt_data_resid) { 8802 error++; 8803 } 8804 } 8805 8806 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8807 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8808 /* 8809 * The next two checks make sure that if there 8810 * is no sense data or a valid response and 8811 * the command came back with check condition, 8812 * the command should be retried. 8813 */ 8814 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8815 !rsp->fcp_u.fcp_status.sense_len_set) { 8816 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8817 pkt->pkt_resid = cmd->cmd_dmacount; 8818 } 8819 } 8820 8821 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8822 return; 8823 } 8824 8825 plun = ADDR2LUN(&pkt->pkt_address); 8826 ptgt = plun->lun_tgt; 8827 ASSERT(ptgt != NULL); 8828 8829 /* 8830 * Update the transfer resid, if appropriate 8831 */ 8832 if (rsp->fcp_u.fcp_status.resid_over || 8833 rsp->fcp_u.fcp_status.resid_under) { 8834 pkt->pkt_resid = rsp->fcp_resid; 8835 } 8836 8837 /* 8838 * First see if we got a FCP protocol error. 8839 */ 8840 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8841 struct fcp_rsp_info *bep; 8842 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8843 sizeof (struct fcp_rsp)); 8844 8845 if (fcp_validate_fcp_response(rsp, pptr) != 8846 FC_SUCCESS) { 8847 pkt->pkt_reason = CMD_CMPLT; 8848 *(pkt->pkt_scbp) = STATUS_CHECK; 8849 8850 fcp_log(CE_WARN, pptr->port_dip, 8851 "!SCSI command to d_id=0x%x lun=0x%x" 8852 " failed, Bad FCP response values:" 8853 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8854 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8855 ptgt->tgt_d_id, plun->lun_num, 8856 rsp->reserved_0, rsp->reserved_1, 8857 rsp->fcp_u.fcp_status.reserved_0, 8858 rsp->fcp_u.fcp_status.reserved_1, 8859 rsp->fcp_response_len, rsp->fcp_sense_len); 8860 8861 return; 8862 } 8863 8864 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8865 FCP_CP_IN(fpkt->pkt_resp + 8866 sizeof (struct fcp_rsp), bep, 8867 fpkt->pkt_resp_acc, 8868 sizeof (struct fcp_rsp_info)); 8869 } 8870 8871 if (bep->rsp_code != FCP_NO_FAILURE) { 8872 child_info_t *cip; 8873 8874 pkt->pkt_reason = CMD_TRAN_ERR; 8875 8876 mutex_enter(&plun->lun_mutex); 8877 cip = plun->lun_cip; 8878 mutex_exit(&plun->lun_mutex); 8879 8880 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8881 fcp_trace, FCP_BUF_LEVEL_2, 0, 8882 "FCP response error on cmd=%p" 8883 " target=0x%x, cip=%p", cmd, 8884 ptgt->tgt_d_id, cip); 8885 } 8886 } 8887 8888 /* 8889 * See if we got a SCSI error with sense data 8890 */ 8891 if (rsp->fcp_u.fcp_status.sense_len_set) { 8892 uchar_t rqlen; 8893 caddr_t sense_from; 8894 child_info_t *cip; 8895 timeout_id_t tid; 8896 struct scsi_arq_status *arq; 8897 struct scsi_extended_sense *sense_to; 8898 8899 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8900 sense_to = &arq->sts_sensedata; 8901 8902 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8903 sizeof (struct scsi_extended_sense)); 8904 8905 sense_from = (caddr_t)fpkt->pkt_resp + 8906 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8907 8908 if (fcp_validate_fcp_response(rsp, pptr) != 8909 FC_SUCCESS) { 8910 pkt->pkt_reason = CMD_CMPLT; 8911 *(pkt->pkt_scbp) = STATUS_CHECK; 8912 8913 fcp_log(CE_WARN, pptr->port_dip, 8914 "!SCSI command to d_id=0x%x lun=0x%x" 8915 " failed, Bad FCP response values:" 8916 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8917 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8918 ptgt->tgt_d_id, plun->lun_num, 8919 rsp->reserved_0, rsp->reserved_1, 8920 rsp->fcp_u.fcp_status.reserved_0, 8921 rsp->fcp_u.fcp_status.reserved_1, 8922 rsp->fcp_response_len, rsp->fcp_sense_len); 8923 8924 return; 8925 } 8926 8927 /* 8928 * copy in sense information 8929 */ 8930 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8931 FCP_CP_IN(sense_from, sense_to, 8932 fpkt->pkt_resp_acc, rqlen); 8933 } else { 8934 bcopy(sense_from, sense_to, rqlen); 8935 } 8936 8937 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8938 (FCP_SENSE_NO_LUN(sense_to))) { 8939 mutex_enter(&ptgt->tgt_mutex); 8940 if (ptgt->tgt_tid == NULL) { 8941 /* 8942 * Kick off rediscovery 8943 */ 8944 tid = timeout(fcp_reconfigure_luns, 8945 (caddr_t)ptgt, drv_usectohz(1)); 8946 8947 ptgt->tgt_tid = tid; 8948 ptgt->tgt_state |= FCP_TGT_BUSY; 8949 } 8950 mutex_exit(&ptgt->tgt_mutex); 8951 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8952 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8953 fcp_trace, FCP_BUF_LEVEL_3, 0, 8954 "!FCP: Report Lun Has Changed" 8955 " target=%x", ptgt->tgt_d_id); 8956 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8957 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8958 fcp_trace, FCP_BUF_LEVEL_3, 0, 8959 "!FCP: LU Not Supported" 8960 " target=%x", ptgt->tgt_d_id); 8961 } 8962 } 8963 ASSERT(pkt->pkt_scbp != NULL); 8964 8965 pkt->pkt_state |= STATE_ARQ_DONE; 8966 8967 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8968 8969 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8970 arq->sts_rqpkt_reason = 0; 8971 arq->sts_rqpkt_statistics = 0; 8972 8973 arq->sts_rqpkt_state = STATE_GOT_BUS | 8974 STATE_GOT_TARGET | STATE_SENT_CMD | 8975 STATE_GOT_STATUS | STATE_ARQ_DONE | 8976 STATE_XFERRED_DATA; 8977 8978 mutex_enter(&plun->lun_mutex); 8979 cip = plun->lun_cip; 8980 mutex_exit(&plun->lun_mutex); 8981 8982 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8983 fcp_trace, FCP_BUF_LEVEL_8, 0, 8984 "SCSI Check condition on cmd=%p target=0x%x" 8985 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8986 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8987 cmd->cmd_fcp_cmd.fcp_cdb[0], 8988 rsp->fcp_u.fcp_status.scsi_status, 8989 sense_to->es_key, sense_to->es_add_code, 8990 sense_to->es_qual_code); 8991 } 8992 } else { 8993 plun = ADDR2LUN(&pkt->pkt_address); 8994 ptgt = plun->lun_tgt; 8995 ASSERT(ptgt != NULL); 8996 8997 /* 8998 * Work harder to translate errors into target driver 8999 * understandable ones. Note with despair that the target 9000 * drivers don't decode pkt_state and pkt_reason exhaustively 9001 * They resort to using the big hammer most often, which 9002 * may not get fixed in the life time of this driver. 9003 */ 9004 pkt->pkt_state = 0; 9005 pkt->pkt_statistics = 0; 9006 9007 switch (fpkt->pkt_state) { 9008 case FC_PKT_TRAN_ERROR: 9009 switch (fpkt->pkt_reason) { 9010 case FC_REASON_OVERRUN: 9011 pkt->pkt_reason = CMD_CMD_OVR; 9012 pkt->pkt_statistics |= STAT_ABORTED; 9013 break; 9014 9015 case FC_REASON_XCHG_BSY: { 9016 caddr_t ptr; 9017 9018 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9019 9020 ptr = (caddr_t)pkt->pkt_scbp; 9021 if (ptr) { 9022 *ptr = STATUS_BUSY; 9023 } 9024 break; 9025 } 9026 9027 case FC_REASON_ABORTED: 9028 pkt->pkt_reason = CMD_TRAN_ERR; 9029 pkt->pkt_statistics |= STAT_ABORTED; 9030 break; 9031 9032 case FC_REASON_ABORT_FAILED: 9033 pkt->pkt_reason = CMD_ABORT_FAIL; 9034 break; 9035 9036 case FC_REASON_NO_SEQ_INIT: 9037 case FC_REASON_CRC_ERROR: 9038 pkt->pkt_reason = CMD_TRAN_ERR; 9039 pkt->pkt_statistics |= STAT_ABORTED; 9040 break; 9041 default: 9042 pkt->pkt_reason = CMD_TRAN_ERR; 9043 break; 9044 } 9045 break; 9046 9047 case FC_PKT_PORT_OFFLINE: { 9048 dev_info_t *cdip = NULL; 9049 caddr_t ptr; 9050 9051 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9052 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9053 fcp_trace, FCP_BUF_LEVEL_8, 0, 9054 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9055 ptgt->tgt_d_id); 9056 } 9057 9058 mutex_enter(&plun->lun_mutex); 9059 if (plun->lun_mpxio == 0) { 9060 cdip = DIP(plun->lun_cip); 9061 } else if (plun->lun_cip) { 9062 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9063 } 9064 9065 mutex_exit(&plun->lun_mutex); 9066 9067 if (cdip) { 9068 (void) ndi_event_retrieve_cookie( 9069 pptr->port_ndi_event_hdl, cdip, 9070 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9071 NDI_EVENT_NOPASS); 9072 (void) ndi_event_run_callbacks( 9073 pptr->port_ndi_event_hdl, cdip, 9074 fcp_remove_eid, NULL); 9075 } 9076 9077 /* 9078 * If the link goes off-line for a lip, 9079 * this will cause a error to the ST SG 9080 * SGEN drivers. By setting BUSY we will 9081 * give the drivers the chance to retry 9082 * before it blows of the job. ST will 9083 * remember how many times it has retried. 9084 */ 9085 9086 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9087 (plun->lun_type == DTYPE_CHANGER)) { 9088 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9089 ptr = (caddr_t)pkt->pkt_scbp; 9090 if (ptr) { 9091 *ptr = STATUS_BUSY; 9092 } 9093 } else { 9094 pkt->pkt_reason = CMD_TRAN_ERR; 9095 pkt->pkt_statistics |= STAT_BUS_RESET; 9096 } 9097 break; 9098 } 9099 9100 case FC_PKT_TRAN_BSY: 9101 /* 9102 * Use the ssd Qfull handling here. 9103 */ 9104 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9105 pkt->pkt_state = STATE_GOT_BUS; 9106 break; 9107 9108 case FC_PKT_TIMEOUT: 9109 pkt->pkt_reason = CMD_TIMEOUT; 9110 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9111 pkt->pkt_statistics |= STAT_TIMEOUT; 9112 } else { 9113 pkt->pkt_statistics |= STAT_ABORTED; 9114 } 9115 break; 9116 9117 case FC_PKT_LOCAL_RJT: 9118 switch (fpkt->pkt_reason) { 9119 case FC_REASON_OFFLINE: { 9120 dev_info_t *cdip = NULL; 9121 9122 mutex_enter(&plun->lun_mutex); 9123 if (plun->lun_mpxio == 0) { 9124 cdip = DIP(plun->lun_cip); 9125 } else if (plun->lun_cip) { 9126 cdip = mdi_pi_get_client( 9127 PIP(plun->lun_cip)); 9128 } 9129 mutex_exit(&plun->lun_mutex); 9130 9131 if (cdip) { 9132 (void) ndi_event_retrieve_cookie( 9133 pptr->port_ndi_event_hdl, cdip, 9134 FCAL_REMOVE_EVENT, 9135 &fcp_remove_eid, 9136 NDI_EVENT_NOPASS); 9137 (void) ndi_event_run_callbacks( 9138 pptr->port_ndi_event_hdl, 9139 cdip, fcp_remove_eid, NULL); 9140 } 9141 9142 pkt->pkt_reason = CMD_TRAN_ERR; 9143 pkt->pkt_statistics |= STAT_BUS_RESET; 9144 9145 break; 9146 } 9147 9148 case FC_REASON_NOMEM: 9149 case FC_REASON_QFULL: { 9150 caddr_t ptr; 9151 9152 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9153 ptr = (caddr_t)pkt->pkt_scbp; 9154 if (ptr) { 9155 *ptr = STATUS_BUSY; 9156 } 9157 break; 9158 } 9159 9160 case FC_REASON_DMA_ERROR: 9161 pkt->pkt_reason = CMD_DMA_DERR; 9162 pkt->pkt_statistics |= STAT_ABORTED; 9163 break; 9164 9165 case FC_REASON_CRC_ERROR: 9166 case FC_REASON_UNDERRUN: { 9167 uchar_t status; 9168 /* 9169 * Work around for Bugid: 4240945. 9170 * IB on A5k doesn't set the Underrun bit 9171 * in the fcp status, when it is transferring 9172 * less than requested amount of data. Work 9173 * around the ses problem to keep luxadm 9174 * happy till ibfirmware is fixed. 9175 */ 9176 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9177 FCP_CP_IN(fpkt->pkt_resp, rsp, 9178 fpkt->pkt_resp_acc, 9179 sizeof (struct fcp_rsp)); 9180 } 9181 status = rsp->fcp_u.fcp_status.scsi_status; 9182 if (((plun->lun_type & DTYPE_MASK) == 9183 DTYPE_ESI) && (status == STATUS_GOOD)) { 9184 pkt->pkt_reason = CMD_CMPLT; 9185 *pkt->pkt_scbp = status; 9186 pkt->pkt_resid = 0; 9187 } else { 9188 pkt->pkt_reason = CMD_TRAN_ERR; 9189 pkt->pkt_statistics |= STAT_ABORTED; 9190 } 9191 break; 9192 } 9193 9194 case FC_REASON_NO_CONNECTION: 9195 case FC_REASON_UNSUPPORTED: 9196 case FC_REASON_ILLEGAL_REQ: 9197 case FC_REASON_BAD_SID: 9198 case FC_REASON_DIAG_BUSY: 9199 case FC_REASON_FCAL_OPN_FAIL: 9200 case FC_REASON_BAD_XID: 9201 default: 9202 pkt->pkt_reason = CMD_TRAN_ERR; 9203 pkt->pkt_statistics |= STAT_ABORTED; 9204 break; 9205 9206 } 9207 break; 9208 9209 case FC_PKT_NPORT_RJT: 9210 case FC_PKT_FABRIC_RJT: 9211 case FC_PKT_NPORT_BSY: 9212 case FC_PKT_FABRIC_BSY: 9213 default: 9214 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9215 fcp_trace, FCP_BUF_LEVEL_8, 0, 9216 "FC Status 0x%x, reason 0x%x", 9217 fpkt->pkt_state, fpkt->pkt_reason); 9218 pkt->pkt_reason = CMD_TRAN_ERR; 9219 pkt->pkt_statistics |= STAT_ABORTED; 9220 break; 9221 } 9222 9223 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9224 fcp_trace, FCP_BUF_LEVEL_9, 0, 9225 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9226 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9227 fpkt->pkt_reason); 9228 } 9229 9230 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9231 } 9232 9233 9234 static int 9235 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9236 { 9237 if (rsp->reserved_0 || rsp->reserved_1 || 9238 rsp->fcp_u.fcp_status.reserved_0 || 9239 rsp->fcp_u.fcp_status.reserved_1) { 9240 /* 9241 * These reserved fields should ideally be zero. FCP-2 does say 9242 * that the recipient need not check for reserved fields to be 9243 * zero. If they are not zero, we will not make a fuss about it 9244 * - just log it (in debug to both trace buffer and messages 9245 * file and to trace buffer only in non-debug) and move on. 9246 * 9247 * Non-zero reserved fields were seen with minnows. 9248 * 9249 * qlc takes care of some of this but we cannot assume that all 9250 * FCAs will do so. 9251 */ 9252 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9253 FCP_BUF_LEVEL_5, 0, 9254 "Got fcp response packet with non-zero reserved fields " 9255 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9256 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9257 rsp->reserved_0, rsp->reserved_1, 9258 rsp->fcp_u.fcp_status.reserved_0, 9259 rsp->fcp_u.fcp_status.reserved_1); 9260 } 9261 9262 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9263 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9264 return (FC_FAILURE); 9265 } 9266 9267 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9268 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9269 sizeof (struct fcp_rsp))) { 9270 return (FC_FAILURE); 9271 } 9272 9273 return (FC_SUCCESS); 9274 } 9275 9276 9277 /* 9278 * This is called when there is a change the in device state. The case we're 9279 * handling here is, if the d_id s does not match, offline this tgt and online 9280 * a new tgt with the new d_id. called from fcp_handle_devices with 9281 * port_mutex held. 9282 */ 9283 static int 9284 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9285 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9286 { 9287 ASSERT(mutex_owned(&pptr->port_mutex)); 9288 9289 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9290 fcp_trace, FCP_BUF_LEVEL_3, 0, 9291 "Starting fcp_device_changed..."); 9292 9293 /* 9294 * The two cases where the port_device_changed is called is 9295 * either it changes it's d_id or it's hard address. 9296 */ 9297 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9298 (FC_TOP_EXTERNAL(pptr->port_topology) && 9299 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9300 9301 /* offline this target */ 9302 mutex_enter(&ptgt->tgt_mutex); 9303 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9304 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9305 0, 1, NDI_DEVI_REMOVE); 9306 } 9307 mutex_exit(&ptgt->tgt_mutex); 9308 9309 fcp_log(CE_NOTE, pptr->port_dip, 9310 "Change in target properties: Old D_ID=%x New D_ID=%x" 9311 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9312 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9313 map_entry->map_hard_addr.hard_addr); 9314 } 9315 9316 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9317 link_cnt, tgt_cnt, cause)); 9318 } 9319 9320 /* 9321 * Function: fcp_alloc_lun 9322 * 9323 * Description: Creates a new lun structure and adds it to the list 9324 * of luns of the target. 9325 * 9326 * Argument: ptgt Target the lun will belong to. 9327 * 9328 * Return Value: NULL Failed 9329 * Not NULL Succeeded 9330 * 9331 * Context: Kernel context 9332 */ 9333 static struct fcp_lun * 9334 fcp_alloc_lun(struct fcp_tgt *ptgt) 9335 { 9336 struct fcp_lun *plun; 9337 9338 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9339 if (plun != NULL) { 9340 /* 9341 * Initialize the mutex before putting in the target list 9342 * especially before releasing the target mutex. 9343 */ 9344 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9345 plun->lun_tgt = ptgt; 9346 9347 mutex_enter(&ptgt->tgt_mutex); 9348 plun->lun_next = ptgt->tgt_lun; 9349 ptgt->tgt_lun = plun; 9350 plun->lun_old_guid = NULL; 9351 plun->lun_old_guid_size = 0; 9352 mutex_exit(&ptgt->tgt_mutex); 9353 } 9354 9355 return (plun); 9356 } 9357 9358 /* 9359 * Function: fcp_dealloc_lun 9360 * 9361 * Description: Frees the LUN structure passed by the caller. 9362 * 9363 * Argument: plun LUN structure to free. 9364 * 9365 * Return Value: None 9366 * 9367 * Context: Kernel context. 9368 */ 9369 static void 9370 fcp_dealloc_lun(struct fcp_lun *plun) 9371 { 9372 mutex_enter(&plun->lun_mutex); 9373 if (plun->lun_cip) { 9374 fcp_remove_child(plun); 9375 } 9376 mutex_exit(&plun->lun_mutex); 9377 9378 mutex_destroy(&plun->lun_mutex); 9379 if (plun->lun_guid) { 9380 kmem_free(plun->lun_guid, plun->lun_guid_size); 9381 } 9382 if (plun->lun_old_guid) { 9383 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9384 } 9385 kmem_free(plun, sizeof (*plun)); 9386 } 9387 9388 /* 9389 * Function: fcp_alloc_tgt 9390 * 9391 * Description: Creates a new target structure and adds it to the port 9392 * hash list. 9393 * 9394 * Argument: pptr fcp port structure 9395 * *map_entry entry describing the target to create 9396 * link_cnt Link state change counter 9397 * 9398 * Return Value: NULL Failed 9399 * Not NULL Succeeded 9400 * 9401 * Context: Kernel context. 9402 */ 9403 static struct fcp_tgt * 9404 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9405 { 9406 int hash; 9407 uchar_t *wwn; 9408 struct fcp_tgt *ptgt; 9409 9410 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9411 if (ptgt != NULL) { 9412 mutex_enter(&pptr->port_mutex); 9413 if (link_cnt != pptr->port_link_cnt) { 9414 /* 9415 * oh oh -- another link reset 9416 * in progress -- give up 9417 */ 9418 mutex_exit(&pptr->port_mutex); 9419 kmem_free(ptgt, sizeof (*ptgt)); 9420 ptgt = NULL; 9421 } else { 9422 /* 9423 * initialize the mutex before putting in the port 9424 * wwn list, especially before releasing the port 9425 * mutex. 9426 */ 9427 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9428 9429 /* add new target entry to the port's hash list */ 9430 wwn = (uchar_t *)&map_entry->map_pwwn; 9431 hash = FCP_HASH(wwn); 9432 9433 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9434 pptr->port_tgt_hash_table[hash] = ptgt; 9435 9436 /* save cross-ptr */ 9437 ptgt->tgt_port = pptr; 9438 9439 ptgt->tgt_change_cnt = 1; 9440 9441 /* initialize the target manual_config_only flag */ 9442 if (fcp_enable_auto_configuration) { 9443 ptgt->tgt_manual_config_only = 0; 9444 } else { 9445 ptgt->tgt_manual_config_only = 1; 9446 } 9447 9448 mutex_exit(&pptr->port_mutex); 9449 } 9450 } 9451 9452 return (ptgt); 9453 } 9454 9455 /* 9456 * Function: fcp_dealloc_tgt 9457 * 9458 * Description: Frees the target structure passed by the caller. 9459 * 9460 * Argument: ptgt Target structure to free. 9461 * 9462 * Return Value: None 9463 * 9464 * Context: Kernel context. 9465 */ 9466 static void 9467 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9468 { 9469 mutex_destroy(&ptgt->tgt_mutex); 9470 kmem_free(ptgt, sizeof (*ptgt)); 9471 } 9472 9473 9474 /* 9475 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9476 * 9477 * Device discovery commands will not be retried for-ever as 9478 * this will have repercussions on other devices that need to 9479 * be submitted to the hotplug thread. After a quick glance 9480 * at the SCSI-3 spec, it was found that the spec doesn't 9481 * mandate a forever retry, rather recommends a delayed retry. 9482 * 9483 * Since Photon IB is single threaded, STATUS_BUSY is common 9484 * in a 4+initiator environment. Make sure the total time 9485 * spent on retries (including command timeout) does not 9486 * 60 seconds 9487 */ 9488 static void 9489 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9490 { 9491 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9492 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9493 9494 mutex_enter(&pptr->port_mutex); 9495 mutex_enter(&ptgt->tgt_mutex); 9496 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9497 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9498 fcp_trace, FCP_BUF_LEVEL_2, 0, 9499 "fcp_queue_ipkt,1:state change occured" 9500 " for D_ID=0x%x", ptgt->tgt_d_id); 9501 mutex_exit(&ptgt->tgt_mutex); 9502 mutex_exit(&pptr->port_mutex); 9503 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9504 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9505 fcp_icmd_free(pptr, icmd); 9506 return; 9507 } 9508 mutex_exit(&ptgt->tgt_mutex); 9509 9510 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9511 9512 if (pptr->port_ipkt_list != NULL) { 9513 /* add pkt to front of doubly-linked list */ 9514 pptr->port_ipkt_list->ipkt_prev = icmd; 9515 icmd->ipkt_next = pptr->port_ipkt_list; 9516 pptr->port_ipkt_list = icmd; 9517 icmd->ipkt_prev = NULL; 9518 } else { 9519 /* this is the first/only pkt on the list */ 9520 pptr->port_ipkt_list = icmd; 9521 icmd->ipkt_next = NULL; 9522 icmd->ipkt_prev = NULL; 9523 } 9524 mutex_exit(&pptr->port_mutex); 9525 } 9526 9527 /* 9528 * Function: fcp_transport 9529 * 9530 * Description: This function submits the Fibre Channel packet to the transort 9531 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9532 * fails the submission, the treatment depends on the value of 9533 * the variable internal. 9534 * 9535 * Argument: port_handle fp/fctl port handle. 9536 * *fpkt Packet to submit to the transport layer. 9537 * internal Not zero when it's an internal packet. 9538 * 9539 * Return Value: FC_TRAN_BUSY 9540 * FC_STATEC_BUSY 9541 * FC_OFFLINE 9542 * FC_LOGINREQ 9543 * FC_DEVICE_BUSY 9544 * FC_SUCCESS 9545 */ 9546 static int 9547 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9548 { 9549 int rval; 9550 9551 rval = fc_ulp_transport(port_handle, fpkt); 9552 if (rval == FC_SUCCESS) { 9553 return (rval); 9554 } 9555 9556 /* 9557 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9558 * a command, if the underlying modules see that there is a state 9559 * change, or if a port is OFFLINE, that means, that state change 9560 * hasn't reached FCP yet, so re-queue the command for deferred 9561 * submission. 9562 */ 9563 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9564 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9565 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9566 /* 9567 * Defer packet re-submission. Life hang is possible on 9568 * internal commands if the port driver sends FC_STATEC_BUSY 9569 * for ever, but that shouldn't happen in a good environment. 9570 * Limiting re-transport for internal commands is probably a 9571 * good idea.. 9572 * A race condition can happen when a port sees barrage of 9573 * link transitions offline to online. If the FCTL has 9574 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9575 * internal commands should be queued to do the discovery. 9576 * The race condition is when an online comes and FCP starts 9577 * its internal discovery and the link goes offline. It is 9578 * possible that the statec_callback has not reached FCP 9579 * and FCP is carrying on with its internal discovery. 9580 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9581 * that the link has gone offline. At this point FCP should 9582 * drop all the internal commands and wait for the 9583 * statec_callback. It will be facilitated by incrementing 9584 * port_link_cnt. 9585 * 9586 * For external commands, the (FC)pkt_timeout is decremented 9587 * by the QUEUE Delay added by our driver, Care is taken to 9588 * ensure that it doesn't become zero (zero means no timeout) 9589 * If the time expires right inside driver queue itself, 9590 * the watch thread will return it to the original caller 9591 * indicating that the command has timed-out. 9592 */ 9593 if (internal) { 9594 char *op; 9595 struct fcp_ipkt *icmd; 9596 9597 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9598 switch (icmd->ipkt_opcode) { 9599 case SCMD_REPORT_LUN: 9600 op = "REPORT LUN"; 9601 break; 9602 9603 case SCMD_INQUIRY: 9604 op = "INQUIRY"; 9605 break; 9606 9607 case SCMD_INQUIRY_PAGE83: 9608 op = "INQUIRY-83"; 9609 break; 9610 9611 default: 9612 op = "Internal SCSI COMMAND"; 9613 break; 9614 } 9615 9616 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9617 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9618 rval = FC_SUCCESS; 9619 } 9620 } else { 9621 struct fcp_pkt *cmd; 9622 struct fcp_port *pptr; 9623 9624 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9625 cmd->cmd_state = FCP_PKT_IDLE; 9626 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9627 9628 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9629 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9630 fcp_trace, FCP_BUF_LEVEL_9, 0, 9631 "fcp_transport: xport busy for pkt %p", 9632 cmd->cmd_pkt); 9633 rval = FC_TRAN_BUSY; 9634 } else { 9635 fcp_queue_pkt(pptr, cmd); 9636 rval = FC_SUCCESS; 9637 } 9638 } 9639 } 9640 9641 return (rval); 9642 } 9643 9644 /*VARARGS3*/ 9645 static void 9646 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9647 { 9648 char buf[256]; 9649 va_list ap; 9650 9651 if (dip == NULL) { 9652 dip = fcp_global_dip; 9653 } 9654 9655 va_start(ap, fmt); 9656 (void) vsprintf(buf, fmt, ap); 9657 va_end(ap); 9658 9659 scsi_log(dip, "fcp", level, buf); 9660 } 9661 9662 /* 9663 * This function retries NS registry of FC4 type. 9664 * It assumes that fcp_mutex is held. 9665 * The function does nothing if topology is not fabric 9666 * So, the topology has to be set before this function can be called 9667 */ 9668 static void 9669 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9670 { 9671 int rval; 9672 9673 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9674 9675 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9676 ((pptr->port_topology != FC_TOP_FABRIC) && 9677 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9678 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9679 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9680 } 9681 return; 9682 } 9683 mutex_exit(&pptr->port_mutex); 9684 rval = fcp_do_ns_registry(pptr, s_id); 9685 mutex_enter(&pptr->port_mutex); 9686 9687 if (rval == 0) { 9688 /* Registry successful. Reset flag */ 9689 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9690 } 9691 } 9692 9693 /* 9694 * This function registers the ULP with the switch by calling transport i/f 9695 */ 9696 static int 9697 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9698 { 9699 fc_ns_cmd_t ns_cmd; 9700 ns_rfc_type_t rfc; 9701 uint32_t types[8]; 9702 9703 /* 9704 * Prepare the Name server structure to 9705 * register with the transport in case of 9706 * Fabric configuration. 9707 */ 9708 bzero(&rfc, sizeof (rfc)); 9709 bzero(types, sizeof (types)); 9710 9711 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9712 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9713 9714 rfc.rfc_port_id.port_id = s_id; 9715 bcopy(types, rfc.rfc_types, sizeof (types)); 9716 9717 ns_cmd.ns_flags = 0; 9718 ns_cmd.ns_cmd = NS_RFT_ID; 9719 ns_cmd.ns_req_len = sizeof (rfc); 9720 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9721 ns_cmd.ns_resp_len = 0; 9722 ns_cmd.ns_resp_payload = NULL; 9723 9724 /* 9725 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9726 */ 9727 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9728 fcp_log(CE_WARN, pptr->port_dip, 9729 "!ns_registry: failed name server registration"); 9730 return (1); 9731 } 9732 9733 return (0); 9734 } 9735 9736 /* 9737 * Function: fcp_handle_port_attach 9738 * 9739 * Description: This function is called from fcp_port_attach() to attach a 9740 * new port. This routine does the following: 9741 * 9742 * 1) Allocates an fcp_port structure and initializes it. 9743 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9744 * server. 9745 * 3) Kicks off the enumeration of the targets/luns visible 9746 * through this new port. That is done by calling 9747 * fcp_statec_callback() if the port is online. 9748 * 9749 * Argument: ulph fp/fctl port handle. 9750 * *pinfo Port information. 9751 * s_id Port ID. 9752 * instance Device instance number for the local port 9753 * (returned by ddi_get_instance()). 9754 * 9755 * Return Value: DDI_SUCCESS 9756 * DDI_FAILURE 9757 * 9758 * Context: User and Kernel context. 9759 */ 9760 /*ARGSUSED*/ 9761 int 9762 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9763 uint32_t s_id, int instance) 9764 { 9765 int res = DDI_FAILURE; 9766 scsi_hba_tran_t *tran; 9767 int mutex_initted = FALSE; 9768 int hba_attached = FALSE; 9769 int soft_state_linked = FALSE; 9770 int event_bind = FALSE; 9771 struct fcp_port *pptr; 9772 fc_portmap_t *tmp_list = NULL; 9773 uint32_t max_cnt, alloc_cnt; 9774 uchar_t *boot_wwn = NULL; 9775 uint_t nbytes; 9776 int manual_cfg; 9777 9778 /* 9779 * this port instance attaching for the first time (or after 9780 * being detached before) 9781 */ 9782 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9783 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9784 9785 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9786 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9787 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9788 instance); 9789 return (res); 9790 } 9791 9792 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9793 /* this shouldn't happen */ 9794 ddi_soft_state_free(fcp_softstate, instance); 9795 cmn_err(CE_WARN, "fcp: bad soft state"); 9796 return (res); 9797 } 9798 9799 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9800 9801 /* 9802 * Make a copy of ulp_port_info as fctl allocates 9803 * a temp struct. 9804 */ 9805 (void) fcp_cp_pinfo(pptr, pinfo); 9806 9807 /* 9808 * Check for manual_configuration_only property. 9809 * Enable manual configurtion if the property is 9810 * set to 1, otherwise disable manual configuration. 9811 */ 9812 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9813 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9814 MANUAL_CFG_ONLY, 9815 -1)) != -1) { 9816 if (manual_cfg == 1) { 9817 char *pathname; 9818 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9819 (void) ddi_pathname(pptr->port_dip, pathname); 9820 cmn_err(CE_NOTE, 9821 "%s (%s%d) %s is enabled via %s.conf.", 9822 pathname, 9823 ddi_driver_name(pptr->port_dip), 9824 ddi_get_instance(pptr->port_dip), 9825 MANUAL_CFG_ONLY, 9826 ddi_driver_name(pptr->port_dip)); 9827 fcp_enable_auto_configuration = 0; 9828 kmem_free(pathname, MAXPATHLEN); 9829 } 9830 } 9831 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9832 pptr->port_link_cnt = 1; 9833 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9834 pptr->port_id = s_id; 9835 pptr->port_instance = instance; 9836 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9837 pptr->port_state = FCP_STATE_INIT; 9838 if (pinfo->port_acc_attr == NULL) { 9839 /* 9840 * The corresponding FCA doesn't support DMA at all 9841 */ 9842 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9843 } 9844 9845 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9846 9847 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9848 /* 9849 * If FCA supports DMA in SCSI data phase, we need preallocate 9850 * dma cookie, so stash the cookie size 9851 */ 9852 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9853 pptr->port_data_dma_attr.dma_attr_sgllen; 9854 } 9855 9856 /* 9857 * The two mutexes of fcp_port are initialized. The variable 9858 * mutex_initted is incremented to remember that fact. That variable 9859 * is checked when the routine fails and the mutexes have to be 9860 * destroyed. 9861 */ 9862 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9863 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9864 mutex_initted++; 9865 9866 /* 9867 * The SCSI tran structure is allocate and initialized now. 9868 */ 9869 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9870 fcp_log(CE_WARN, pptr->port_dip, 9871 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9872 goto fail; 9873 } 9874 9875 /* link in the transport structure then fill it in */ 9876 pptr->port_tran = tran; 9877 tran->tran_hba_private = pptr; 9878 tran->tran_tgt_init = fcp_scsi_tgt_init; 9879 tran->tran_tgt_probe = NULL; 9880 tran->tran_tgt_free = fcp_scsi_tgt_free; 9881 tran->tran_start = fcp_scsi_start; 9882 tran->tran_reset = fcp_scsi_reset; 9883 tran->tran_abort = fcp_scsi_abort; 9884 tran->tran_getcap = fcp_scsi_getcap; 9885 tran->tran_setcap = fcp_scsi_setcap; 9886 tran->tran_init_pkt = NULL; 9887 tran->tran_destroy_pkt = NULL; 9888 tran->tran_dmafree = NULL; 9889 tran->tran_sync_pkt = NULL; 9890 tran->tran_reset_notify = fcp_scsi_reset_notify; 9891 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9892 tran->tran_get_name = fcp_scsi_get_name; 9893 tran->tran_clear_aca = NULL; 9894 tran->tran_clear_task_set = NULL; 9895 tran->tran_terminate_task = NULL; 9896 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9897 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9898 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9899 tran->tran_post_event = fcp_scsi_bus_post_event; 9900 tran->tran_quiesce = NULL; 9901 tran->tran_unquiesce = NULL; 9902 tran->tran_bus_reset = NULL; 9903 tran->tran_bus_config = fcp_scsi_bus_config; 9904 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9905 tran->tran_bus_power = NULL; 9906 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9907 9908 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9909 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9910 tran->tran_setup_pkt = fcp_pkt_setup; 9911 tran->tran_teardown_pkt = fcp_pkt_teardown; 9912 tran->tran_hba_len = pptr->port_priv_pkt_len + 9913 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9914 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9915 /* 9916 * If FCA don't support DMA, then we use different vectors to 9917 * minimize the effects on DMA code flow path 9918 */ 9919 tran->tran_start = fcp_pseudo_start; 9920 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9921 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9922 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9923 tran->tran_dmafree = fcp_pseudo_dmafree; 9924 tran->tran_setup_pkt = NULL; 9925 tran->tran_teardown_pkt = NULL; 9926 tran->tran_pkt_constructor = NULL; 9927 tran->tran_pkt_destructor = NULL; 9928 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9929 } 9930 9931 /* 9932 * Allocate an ndi event handle 9933 */ 9934 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9935 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9936 9937 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9938 sizeof (fcp_ndi_event_defs)); 9939 9940 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9941 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9942 9943 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9944 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9945 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9946 9947 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9948 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9949 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9950 goto fail; 9951 } 9952 event_bind++; /* Checked in fail case */ 9953 9954 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9955 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9956 != DDI_SUCCESS) { 9957 fcp_log(CE_WARN, pptr->port_dip, 9958 "!fcp%d: scsi_hba_attach_setup failed", instance); 9959 goto fail; 9960 } 9961 hba_attached++; /* Checked in fail case */ 9962 9963 pptr->port_mpxio = 0; 9964 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9965 MDI_SUCCESS) { 9966 pptr->port_mpxio++; 9967 } 9968 9969 /* 9970 * The following code is putting the new port structure in the global 9971 * list of ports and, if it is the first port to attach, it start the 9972 * fcp_watchdog_tick. 9973 * 9974 * Why put this new port in the global before we are done attaching it? 9975 * We are actually making the structure globally known before we are 9976 * done attaching it. The reason for that is: because of the code that 9977 * follows. At this point the resources to handle the port are 9978 * allocated. This function is now going to do the following: 9979 * 9980 * 1) It is going to try to register with the name server advertizing 9981 * the new FCP capability of the port. 9982 * 2) It is going to play the role of the fp/fctl layer by building 9983 * a list of worlwide names reachable through this port and call 9984 * itself on fcp_statec_callback(). That requires the port to 9985 * be part of the global list. 9986 */ 9987 mutex_enter(&fcp_global_mutex); 9988 if (fcp_port_head == NULL) { 9989 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9990 } 9991 pptr->port_next = fcp_port_head; 9992 fcp_port_head = pptr; 9993 soft_state_linked++; 9994 9995 if (fcp_watchdog_init++ == 0) { 9996 fcp_watchdog_tick = fcp_watchdog_timeout * 9997 drv_usectohz(1000000); 9998 fcp_watchdog_id = timeout(fcp_watch, NULL, 9999 fcp_watchdog_tick); 10000 } 10001 mutex_exit(&fcp_global_mutex); 10002 10003 /* 10004 * Here an attempt is made to register with the name server, the new 10005 * FCP capability. That is done using an RTF_ID to the name server. 10006 * It is done synchronously. The function fcp_do_ns_registry() 10007 * doesn't return till the name server responded. 10008 * On failures, just ignore it for now and it will get retried during 10009 * state change callbacks. We'll set a flag to show this failure 10010 */ 10011 if (fcp_do_ns_registry(pptr, s_id)) { 10012 mutex_enter(&pptr->port_mutex); 10013 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 10014 mutex_exit(&pptr->port_mutex); 10015 } else { 10016 mutex_enter(&pptr->port_mutex); 10017 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 10018 mutex_exit(&pptr->port_mutex); 10019 } 10020 10021 /* 10022 * Lookup for boot WWN property 10023 */ 10024 if (modrootloaded != 1) { 10025 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 10026 ddi_get_parent(pinfo->port_dip), 10027 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 10028 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 10029 (nbytes == FC_WWN_SIZE)) { 10030 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 10031 } 10032 if (boot_wwn) { 10033 ddi_prop_free(boot_wwn); 10034 } 10035 } 10036 10037 /* 10038 * Handle various topologies and link states. 10039 */ 10040 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10041 case FC_STATE_OFFLINE: 10042 10043 /* 10044 * we're attaching a port where the link is offline 10045 * 10046 * Wait for ONLINE, at which time a state 10047 * change will cause a statec_callback 10048 * 10049 * in the mean time, do not do anything 10050 */ 10051 res = DDI_SUCCESS; 10052 pptr->port_state |= FCP_STATE_OFFLINE; 10053 break; 10054 10055 case FC_STATE_ONLINE: { 10056 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10057 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10058 res = DDI_SUCCESS; 10059 break; 10060 } 10061 /* 10062 * discover devices and create nodes (a private 10063 * loop or point-to-point) 10064 */ 10065 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10066 10067 /* 10068 * At this point we are going to build a list of all the ports 10069 * that can be reached through this local port. It looks like 10070 * we cannot handle more than FCP_MAX_DEVICES per local port 10071 * (128). 10072 */ 10073 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10074 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10075 KM_NOSLEEP)) == NULL) { 10076 fcp_log(CE_WARN, pptr->port_dip, 10077 "!fcp%d: failed to allocate portmap", 10078 instance); 10079 goto fail; 10080 } 10081 10082 /* 10083 * fc_ulp_getportmap() is going to provide us with the list of 10084 * remote ports in the buffer we just allocated. The way the 10085 * list is going to be retrieved depends on the topology. 10086 * However, if we are connected to a Fabric, a name server 10087 * request may be sent to get the list of FCP capable ports. 10088 * It should be noted that is the case the request is 10089 * synchronous. This means we are stuck here till the name 10090 * server replies. A lot of things can change during that time 10091 * and including, may be, being called on 10092 * fcp_statec_callback() for different reasons. I'm not sure 10093 * the code can handle that. 10094 */ 10095 max_cnt = FCP_MAX_DEVICES; 10096 alloc_cnt = FCP_MAX_DEVICES; 10097 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10098 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10099 FC_SUCCESS) { 10100 caddr_t msg; 10101 10102 (void) fc_ulp_error(res, &msg); 10103 10104 /* 10105 * this just means the transport is 10106 * busy perhaps building a portmap so, 10107 * for now, succeed this port attach 10108 * when the transport has a new map, 10109 * it'll send us a state change then 10110 */ 10111 fcp_log(CE_WARN, pptr->port_dip, 10112 "!failed to get port map : %s", msg); 10113 10114 res = DDI_SUCCESS; 10115 break; /* go return result */ 10116 } 10117 if (max_cnt > alloc_cnt) { 10118 alloc_cnt = max_cnt; 10119 } 10120 10121 /* 10122 * We are now going to call fcp_statec_callback() ourselves. 10123 * By issuing this call we are trying to kick off the enumera- 10124 * tion process. 10125 */ 10126 /* 10127 * let the state change callback do the SCSI device 10128 * discovery and create the devinfos 10129 */ 10130 fcp_statec_callback(ulph, pptr->port_fp_handle, 10131 pptr->port_phys_state, pptr->port_topology, tmp_list, 10132 max_cnt, pptr->port_id); 10133 10134 res = DDI_SUCCESS; 10135 break; 10136 } 10137 10138 default: 10139 /* unknown port state */ 10140 fcp_log(CE_WARN, pptr->port_dip, 10141 "!fcp%d: invalid port state at attach=0x%x", 10142 instance, pptr->port_phys_state); 10143 10144 mutex_enter(&pptr->port_mutex); 10145 pptr->port_phys_state = FCP_STATE_OFFLINE; 10146 mutex_exit(&pptr->port_mutex); 10147 10148 res = DDI_SUCCESS; 10149 break; 10150 } 10151 10152 /* free temp list if used */ 10153 if (tmp_list != NULL) { 10154 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10155 } 10156 10157 /* note the attach time */ 10158 pptr->port_attach_time = ddi_get_lbolt64(); 10159 10160 /* all done */ 10161 return (res); 10162 10163 /* a failure we have to clean up after */ 10164 fail: 10165 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10166 10167 if (soft_state_linked) { 10168 /* remove this fcp_port from the linked list */ 10169 (void) fcp_soft_state_unlink(pptr); 10170 } 10171 10172 /* unbind and free event set */ 10173 if (pptr->port_ndi_event_hdl) { 10174 if (event_bind) { 10175 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10176 &pptr->port_ndi_events, NDI_SLEEP); 10177 } 10178 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10179 } 10180 10181 if (pptr->port_ndi_event_defs) { 10182 (void) kmem_free(pptr->port_ndi_event_defs, 10183 sizeof (fcp_ndi_event_defs)); 10184 } 10185 10186 /* 10187 * Clean up mpxio stuff 10188 */ 10189 if (pptr->port_mpxio) { 10190 (void) mdi_phci_unregister(pptr->port_dip, 0); 10191 pptr->port_mpxio--; 10192 } 10193 10194 /* undo SCSI HBA setup */ 10195 if (hba_attached) { 10196 (void) scsi_hba_detach(pptr->port_dip); 10197 } 10198 if (pptr->port_tran != NULL) { 10199 scsi_hba_tran_free(pptr->port_tran); 10200 } 10201 10202 mutex_enter(&fcp_global_mutex); 10203 10204 /* 10205 * We check soft_state_linked, because it is incremented right before 10206 * we call increment fcp_watchdog_init. Therefore, we know if 10207 * soft_state_linked is still FALSE, we do not want to decrement 10208 * fcp_watchdog_init or possibly call untimeout. 10209 */ 10210 10211 if (soft_state_linked) { 10212 if (--fcp_watchdog_init == 0) { 10213 timeout_id_t tid = fcp_watchdog_id; 10214 10215 mutex_exit(&fcp_global_mutex); 10216 (void) untimeout(tid); 10217 } else { 10218 mutex_exit(&fcp_global_mutex); 10219 } 10220 } else { 10221 mutex_exit(&fcp_global_mutex); 10222 } 10223 10224 if (mutex_initted) { 10225 mutex_destroy(&pptr->port_mutex); 10226 mutex_destroy(&pptr->port_pkt_mutex); 10227 } 10228 10229 if (tmp_list != NULL) { 10230 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10231 } 10232 10233 /* this makes pptr invalid */ 10234 ddi_soft_state_free(fcp_softstate, instance); 10235 10236 return (DDI_FAILURE); 10237 } 10238 10239 10240 static int 10241 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10242 { 10243 int count = 0; 10244 10245 mutex_enter(&pptr->port_mutex); 10246 10247 /* 10248 * if the port is powered down or suspended, nothing else 10249 * to do; just return. 10250 */ 10251 if (flag != FCP_STATE_DETACHING) { 10252 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10253 FCP_STATE_SUSPENDED)) { 10254 pptr->port_state |= flag; 10255 mutex_exit(&pptr->port_mutex); 10256 return (FC_SUCCESS); 10257 } 10258 } 10259 10260 if (pptr->port_state & FCP_STATE_IN_MDI) { 10261 mutex_exit(&pptr->port_mutex); 10262 return (FC_FAILURE); 10263 } 10264 10265 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10266 fcp_trace, FCP_BUF_LEVEL_2, 0, 10267 "fcp_handle_port_detach: port is detaching"); 10268 10269 pptr->port_state |= flag; 10270 10271 /* 10272 * Wait for any ongoing reconfig/ipkt to complete, that 10273 * ensures the freeing to targets/luns is safe. 10274 * No more ref to this port should happen from statec/ioctl 10275 * after that as it was removed from the global port list. 10276 */ 10277 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10278 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10279 /* 10280 * Let's give sufficient time for reconfig/ipkt 10281 * to complete. 10282 */ 10283 if (count++ >= FCP_ICMD_DEADLINE) { 10284 break; 10285 } 10286 mutex_exit(&pptr->port_mutex); 10287 delay(drv_usectohz(1000000)); 10288 mutex_enter(&pptr->port_mutex); 10289 } 10290 10291 /* 10292 * if the driver is still busy then fail to 10293 * suspend/power down. 10294 */ 10295 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10296 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10297 pptr->port_state &= ~flag; 10298 mutex_exit(&pptr->port_mutex); 10299 return (FC_FAILURE); 10300 } 10301 10302 if (flag == FCP_STATE_DETACHING) { 10303 pptr = fcp_soft_state_unlink(pptr); 10304 ASSERT(pptr != NULL); 10305 } 10306 10307 pptr->port_link_cnt++; 10308 pptr->port_state |= FCP_STATE_OFFLINE; 10309 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10310 10311 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10312 FCP_CAUSE_LINK_DOWN); 10313 mutex_exit(&pptr->port_mutex); 10314 10315 /* kill watch dog timer if we're the last */ 10316 mutex_enter(&fcp_global_mutex); 10317 if (--fcp_watchdog_init == 0) { 10318 timeout_id_t tid = fcp_watchdog_id; 10319 mutex_exit(&fcp_global_mutex); 10320 (void) untimeout(tid); 10321 } else { 10322 mutex_exit(&fcp_global_mutex); 10323 } 10324 10325 /* clean up the port structures */ 10326 if (flag == FCP_STATE_DETACHING) { 10327 fcp_cleanup_port(pptr, instance); 10328 } 10329 10330 return (FC_SUCCESS); 10331 } 10332 10333 10334 static void 10335 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10336 { 10337 ASSERT(pptr != NULL); 10338 10339 /* unbind and free event set */ 10340 if (pptr->port_ndi_event_hdl) { 10341 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10342 &pptr->port_ndi_events, NDI_SLEEP); 10343 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10344 } 10345 10346 if (pptr->port_ndi_event_defs) { 10347 (void) kmem_free(pptr->port_ndi_event_defs, 10348 sizeof (fcp_ndi_event_defs)); 10349 } 10350 10351 /* free the lun/target structures and devinfos */ 10352 fcp_free_targets(pptr); 10353 10354 /* 10355 * Clean up mpxio stuff 10356 */ 10357 if (pptr->port_mpxio) { 10358 (void) mdi_phci_unregister(pptr->port_dip, 0); 10359 pptr->port_mpxio--; 10360 } 10361 10362 /* clean up SCSA stuff */ 10363 (void) scsi_hba_detach(pptr->port_dip); 10364 if (pptr->port_tran != NULL) { 10365 scsi_hba_tran_free(pptr->port_tran); 10366 } 10367 10368 #ifdef KSTATS_CODE 10369 /* clean up kstats */ 10370 if (pptr->fcp_ksp != NULL) { 10371 kstat_delete(pptr->fcp_ksp); 10372 } 10373 #endif 10374 10375 /* clean up soft state mutexes/condition variables */ 10376 mutex_destroy(&pptr->port_mutex); 10377 mutex_destroy(&pptr->port_pkt_mutex); 10378 10379 /* all done with soft state */ 10380 ddi_soft_state_free(fcp_softstate, instance); 10381 } 10382 10383 /* 10384 * Function: fcp_kmem_cache_constructor 10385 * 10386 * Description: This function allocates and initializes the resources required 10387 * to build a scsi_pkt structure the target driver. The result 10388 * of the allocation and initialization will be cached in the 10389 * memory cache. As DMA resources may be allocated here, that 10390 * means DMA resources will be tied up in the cache manager. 10391 * This is a tradeoff that has been made for performance reasons. 10392 * 10393 * Argument: *buf Memory to preinitialize. 10394 * *arg FCP port structure (fcp_port). 10395 * kmflags Value passed to kmem_cache_alloc() and 10396 * propagated to the constructor. 10397 * 10398 * Return Value: 0 Allocation/Initialization was successful. 10399 * -1 Allocation or Initialization failed. 10400 * 10401 * 10402 * If the returned value is 0, the buffer is initialized like this: 10403 * 10404 * +================================+ 10405 * +----> | struct scsi_pkt | 10406 * | | | 10407 * | +--- | pkt_ha_private | 10408 * | | | | 10409 * | | +================================+ 10410 * | | 10411 * | | +================================+ 10412 * | +--> | struct fcp_pkt | <---------+ 10413 * | | | | 10414 * +----- | cmd_pkt | | 10415 * | cmd_fp_pkt | ---+ | 10416 * +-------->| cmd_fcp_rsp[] | | | 10417 * | +--->| cmd_fcp_cmd[] | | | 10418 * | | |--------------------------------| | | 10419 * | | | struct fc_packet | <--+ | 10420 * | | | | | 10421 * | | | pkt_ulp_private | ----------+ 10422 * | | | pkt_fca_private | -----+ 10423 * | | | pkt_data_cookie | ---+ | 10424 * | | | pkt_cmdlen | | | 10425 * | |(a) | pkt_rsplen | | | 10426 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10427 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10428 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10429 * | pkt_resp_cookie | ---|-|--+ | | | 10430 * | pkt_cmd_dma | | | | | | | 10431 * | pkt_cmd_acc | | | | | | | 10432 * +================================+ | | | | | | 10433 * | dma_cookies | <--+ | | | | | 10434 * | | | | | | | 10435 * +================================+ | | | | | 10436 * | fca_private | <----+ | | | | 10437 * | | | | | | 10438 * +================================+ | | | | 10439 * | | | | 10440 * | | | | 10441 * +================================+ (d) | | | | 10442 * | fcp_resp cookies | <-------+ | | | 10443 * | | | | | 10444 * +================================+ | | | 10445 * | | | 10446 * +================================+ (d) | | | 10447 * | fcp_resp | <-----------+ | | 10448 * | (DMA resources associated) | | | 10449 * +================================+ | | 10450 * | | 10451 * | | 10452 * | | 10453 * +================================+ (c) | | 10454 * | fcp_cmd cookies | <---------------+ | 10455 * | | | 10456 * +================================+ | 10457 * | 10458 * +================================+ (c) | 10459 * | fcp_cmd | <--------------------+ 10460 * | (DMA resources associated) | 10461 * +================================+ 10462 * 10463 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10464 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10465 * (c) Only if DMA is used for the FCP_CMD buffer. 10466 * (d) Only if DMA is used for the FCP_RESP buffer 10467 */ 10468 static int 10469 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10470 int kmflags) 10471 { 10472 struct fcp_pkt *cmd; 10473 struct fcp_port *pptr; 10474 fc_packet_t *fpkt; 10475 10476 pptr = (struct fcp_port *)tran->tran_hba_private; 10477 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10478 bzero(cmd, tran->tran_hba_len); 10479 10480 cmd->cmd_pkt = pkt; 10481 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10482 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10483 cmd->cmd_fp_pkt = fpkt; 10484 10485 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10486 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10487 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10488 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10489 10490 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10491 sizeof (struct fcp_pkt)); 10492 10493 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10494 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10495 10496 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10497 /* 10498 * The underlying HBA doesn't want to DMA the fcp_cmd or 10499 * fcp_resp. The transfer of information will be done by 10500 * bcopy. 10501 * The naming of the flags (that is actually a value) is 10502 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10503 * DMA" but instead "NO DMA". 10504 */ 10505 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10506 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10507 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10508 } else { 10509 /* 10510 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10511 * buffer. A buffer is allocated for each one the ddi_dma_* 10512 * interfaces. 10513 */ 10514 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10515 return (-1); 10516 } 10517 } 10518 10519 return (0); 10520 } 10521 10522 /* 10523 * Function: fcp_kmem_cache_destructor 10524 * 10525 * Description: Called by the destructor of the cache managed by SCSA. 10526 * All the resources pre-allocated in fcp_pkt_constructor 10527 * and the data also pre-initialized in fcp_pkt_constructor 10528 * are freed and uninitialized here. 10529 * 10530 * Argument: *buf Memory to uninitialize. 10531 * *arg FCP port structure (fcp_port). 10532 * 10533 * Return Value: None 10534 * 10535 * Context: kernel 10536 */ 10537 static void 10538 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10539 { 10540 struct fcp_pkt *cmd; 10541 struct fcp_port *pptr; 10542 10543 pptr = (struct fcp_port *)(tran->tran_hba_private); 10544 cmd = pkt->pkt_ha_private; 10545 10546 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10547 /* 10548 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10549 * buffer and DMA resources allocated to do so are released. 10550 */ 10551 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10552 } 10553 } 10554 10555 /* 10556 * Function: fcp_alloc_cmd_resp 10557 * 10558 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10559 * will be DMAed by the HBA. The buffer is allocated applying 10560 * the DMA requirements for the HBA. The buffers allocated will 10561 * also be bound. DMA resources are allocated in the process. 10562 * They will be released by fcp_free_cmd_resp(). 10563 * 10564 * Argument: *pptr FCP port. 10565 * *fpkt fc packet for which the cmd and resp packet should be 10566 * allocated. 10567 * flags Allocation flags. 10568 * 10569 * Return Value: FC_FAILURE 10570 * FC_SUCCESS 10571 * 10572 * Context: User or Kernel context only if flags == KM_SLEEP. 10573 * Interrupt context if the KM_SLEEP is not specified. 10574 */ 10575 static int 10576 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10577 { 10578 int rval; 10579 int cmd_len; 10580 int resp_len; 10581 ulong_t real_len; 10582 int (*cb) (caddr_t); 10583 ddi_dma_cookie_t pkt_cookie; 10584 ddi_dma_cookie_t *cp; 10585 uint32_t cnt; 10586 10587 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10588 10589 cmd_len = fpkt->pkt_cmdlen; 10590 resp_len = fpkt->pkt_rsplen; 10591 10592 ASSERT(fpkt->pkt_cmd_dma == NULL); 10593 10594 /* Allocation of a DMA handle used in subsequent calls. */ 10595 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10596 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10597 return (FC_FAILURE); 10598 } 10599 10600 /* A buffer is allocated that satisfies the DMA requirements. */ 10601 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10602 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10603 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10604 10605 if (rval != DDI_SUCCESS) { 10606 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10607 return (FC_FAILURE); 10608 } 10609 10610 if (real_len < cmd_len) { 10611 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10612 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10613 return (FC_FAILURE); 10614 } 10615 10616 /* The buffer allocated is DMA bound. */ 10617 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10618 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10619 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10620 10621 if (rval != DDI_DMA_MAPPED) { 10622 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10623 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10624 return (FC_FAILURE); 10625 } 10626 10627 if (fpkt->pkt_cmd_cookie_cnt > 10628 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10629 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10630 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10631 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10632 return (FC_FAILURE); 10633 } 10634 10635 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10636 10637 /* 10638 * The buffer where the scatter/gather list is going to be built is 10639 * allocated. 10640 */ 10641 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10642 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10643 KM_NOSLEEP); 10644 10645 if (cp == NULL) { 10646 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10647 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10648 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10649 return (FC_FAILURE); 10650 } 10651 10652 /* 10653 * The scatter/gather list for the buffer we just allocated is built 10654 * here. 10655 */ 10656 *cp = pkt_cookie; 10657 cp++; 10658 10659 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10660 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10661 &pkt_cookie); 10662 *cp = pkt_cookie; 10663 } 10664 10665 ASSERT(fpkt->pkt_resp_dma == NULL); 10666 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10667 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10668 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10669 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10670 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10671 return (FC_FAILURE); 10672 } 10673 10674 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10675 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10676 (caddr_t *)&fpkt->pkt_resp, &real_len, 10677 &fpkt->pkt_resp_acc); 10678 10679 if (rval != DDI_SUCCESS) { 10680 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 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 kmem_free(fpkt->pkt_cmd_cookie, 10685 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10686 return (FC_FAILURE); 10687 } 10688 10689 if (real_len < resp_len) { 10690 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10691 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10692 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10693 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10694 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10695 kmem_free(fpkt->pkt_cmd_cookie, 10696 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10697 return (FC_FAILURE); 10698 } 10699 10700 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10701 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10702 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10703 10704 if (rval != DDI_DMA_MAPPED) { 10705 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10706 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10707 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10708 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10709 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10710 kmem_free(fpkt->pkt_cmd_cookie, 10711 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10712 return (FC_FAILURE); 10713 } 10714 10715 if (fpkt->pkt_resp_cookie_cnt > 10716 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10717 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10718 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10719 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10720 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10721 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10722 kmem_free(fpkt->pkt_cmd_cookie, 10723 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10724 return (FC_FAILURE); 10725 } 10726 10727 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10728 10729 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10730 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10731 KM_NOSLEEP); 10732 10733 if (cp == NULL) { 10734 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10735 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10736 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10737 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10738 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10739 kmem_free(fpkt->pkt_cmd_cookie, 10740 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10741 return (FC_FAILURE); 10742 } 10743 10744 *cp = pkt_cookie; 10745 cp++; 10746 10747 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10748 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10749 &pkt_cookie); 10750 *cp = pkt_cookie; 10751 } 10752 10753 return (FC_SUCCESS); 10754 } 10755 10756 /* 10757 * Function: fcp_free_cmd_resp 10758 * 10759 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10760 * allocated by fcp_alloc_cmd_resp() and all the resources 10761 * associated with them. That includes the DMA resources and the 10762 * buffer allocated for the cookies of each one of them. 10763 * 10764 * Argument: *pptr FCP port context. 10765 * *fpkt fc packet containing the cmd and resp packet 10766 * to be released. 10767 * 10768 * Return Value: None 10769 * 10770 * Context: Interrupt, User and Kernel context. 10771 */ 10772 /* ARGSUSED */ 10773 static void 10774 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10775 { 10776 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10777 10778 if (fpkt->pkt_resp_dma) { 10779 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10780 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10781 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10782 } 10783 10784 if (fpkt->pkt_resp_cookie) { 10785 kmem_free(fpkt->pkt_resp_cookie, 10786 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10787 fpkt->pkt_resp_cookie = NULL; 10788 } 10789 10790 if (fpkt->pkt_cmd_dma) { 10791 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10792 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10793 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10794 } 10795 10796 if (fpkt->pkt_cmd_cookie) { 10797 kmem_free(fpkt->pkt_cmd_cookie, 10798 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10799 fpkt->pkt_cmd_cookie = NULL; 10800 } 10801 } 10802 10803 10804 /* 10805 * called by the transport to do our own target initialization 10806 * 10807 * can acquire and release the global mutex 10808 */ 10809 /* ARGSUSED */ 10810 static int 10811 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10812 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10813 { 10814 uchar_t *bytes; 10815 uint_t nbytes; 10816 uint16_t lun_num; 10817 struct fcp_tgt *ptgt; 10818 struct fcp_lun *plun; 10819 struct fcp_port *pptr = (struct fcp_port *) 10820 hba_tran->tran_hba_private; 10821 10822 ASSERT(pptr != NULL); 10823 10824 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10825 FCP_BUF_LEVEL_8, 0, 10826 "fcp_phys_tgt_init: called for %s (instance %d)", 10827 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10828 10829 /* get our port WWN property */ 10830 bytes = NULL; 10831 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10832 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10833 (nbytes != FC_WWN_SIZE)) { 10834 /* no port WWN property */ 10835 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10836 FCP_BUF_LEVEL_8, 0, 10837 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10838 " for %s (instance %d): bytes=%p nbytes=%x", 10839 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10840 nbytes); 10841 10842 if (bytes != NULL) { 10843 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10844 } 10845 10846 return (DDI_NOT_WELL_FORMED); 10847 } 10848 ASSERT(bytes != NULL); 10849 10850 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10851 LUN_PROP, 0xFFFF); 10852 if (lun_num == 0xFFFF) { 10853 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10854 FCP_BUF_LEVEL_8, 0, 10855 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10856 " for %s (instance %d)", ddi_get_name(tgt_dip), 10857 ddi_get_instance(tgt_dip)); 10858 10859 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10860 return (DDI_NOT_WELL_FORMED); 10861 } 10862 10863 mutex_enter(&pptr->port_mutex); 10864 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10865 mutex_exit(&pptr->port_mutex); 10866 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10867 FCP_BUF_LEVEL_8, 0, 10868 "fcp_phys_tgt_init: Returning DDI_FAILURE: No 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_FAILURE); 10874 } 10875 10876 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10877 FC_WWN_SIZE) == 0); 10878 ASSERT(plun->lun_num == lun_num); 10879 10880 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10881 10882 ptgt = plun->lun_tgt; 10883 10884 mutex_enter(&ptgt->tgt_mutex); 10885 plun->lun_tgt_count++; 10886 scsi_device_hba_private_set(sd, plun); 10887 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10888 plun->lun_sd = sd; 10889 mutex_exit(&ptgt->tgt_mutex); 10890 mutex_exit(&pptr->port_mutex); 10891 10892 return (DDI_SUCCESS); 10893 } 10894 10895 /*ARGSUSED*/ 10896 static int 10897 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10898 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10899 { 10900 uchar_t *bytes; 10901 uint_t nbytes; 10902 uint16_t lun_num; 10903 struct fcp_tgt *ptgt; 10904 struct fcp_lun *plun; 10905 struct fcp_port *pptr = (struct fcp_port *) 10906 hba_tran->tran_hba_private; 10907 child_info_t *cip; 10908 10909 ASSERT(pptr != NULL); 10910 10911 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10912 fcp_trace, FCP_BUF_LEVEL_8, 0, 10913 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10914 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10915 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10916 10917 cip = (child_info_t *)sd->sd_pathinfo; 10918 if (cip == NULL) { 10919 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10920 fcp_trace, FCP_BUF_LEVEL_8, 0, 10921 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10922 " for %s (instance %d)", ddi_get_name(tgt_dip), 10923 ddi_get_instance(tgt_dip)); 10924 10925 return (DDI_NOT_WELL_FORMED); 10926 } 10927 10928 /* get our port WWN property */ 10929 bytes = NULL; 10930 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10931 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10932 (nbytes != FC_WWN_SIZE)) { 10933 if (bytes) { 10934 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10935 } 10936 return (DDI_NOT_WELL_FORMED); 10937 } 10938 10939 ASSERT(bytes != NULL); 10940 10941 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10942 LUN_PROP, 0xFFFF); 10943 if (lun_num == 0xFFFF) { 10944 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10945 fcp_trace, FCP_BUF_LEVEL_8, 0, 10946 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10947 " for %s (instance %d)", ddi_get_name(tgt_dip), 10948 ddi_get_instance(tgt_dip)); 10949 10950 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10951 return (DDI_NOT_WELL_FORMED); 10952 } 10953 10954 mutex_enter(&pptr->port_mutex); 10955 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10956 mutex_exit(&pptr->port_mutex); 10957 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10958 fcp_trace, FCP_BUF_LEVEL_8, 0, 10959 "fcp_virt_tgt_init: Returning DDI_FAILURE: No 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_FAILURE); 10965 } 10966 10967 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10968 FC_WWN_SIZE) == 0); 10969 ASSERT(plun->lun_num == lun_num); 10970 10971 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10972 10973 ptgt = plun->lun_tgt; 10974 10975 mutex_enter(&ptgt->tgt_mutex); 10976 plun->lun_tgt_count++; 10977 scsi_device_hba_private_set(sd, plun); 10978 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10979 plun->lun_sd = sd; 10980 mutex_exit(&ptgt->tgt_mutex); 10981 mutex_exit(&pptr->port_mutex); 10982 10983 return (DDI_SUCCESS); 10984 } 10985 10986 10987 /* 10988 * called by the transport to do our own target initialization 10989 * 10990 * can acquire and release the global mutex 10991 */ 10992 /* ARGSUSED */ 10993 static int 10994 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10995 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10996 { 10997 struct fcp_port *pptr = (struct fcp_port *) 10998 hba_tran->tran_hba_private; 10999 int rval; 11000 11001 ASSERT(pptr != NULL); 11002 11003 /* 11004 * Child node is getting initialized. Look at the mpxio component 11005 * type on the child device to see if this device is mpxio managed 11006 * or not. 11007 */ 11008 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 11009 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11010 } else { 11011 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11012 } 11013 11014 return (rval); 11015 } 11016 11017 11018 /* ARGSUSED */ 11019 static void 11020 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11021 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11022 { 11023 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 11024 struct fcp_tgt *ptgt; 11025 11026 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 11027 fcp_trace, FCP_BUF_LEVEL_8, 0, 11028 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 11029 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 11030 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 11031 11032 if (plun == NULL) { 11033 return; 11034 } 11035 ptgt = plun->lun_tgt; 11036 11037 ASSERT(ptgt != NULL); 11038 11039 mutex_enter(&ptgt->tgt_mutex); 11040 ASSERT(plun->lun_tgt_count > 0); 11041 11042 if (--plun->lun_tgt_count == 0) { 11043 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11044 } 11045 plun->lun_sd = NULL; 11046 mutex_exit(&ptgt->tgt_mutex); 11047 } 11048 11049 /* 11050 * Function: fcp_scsi_start 11051 * 11052 * Description: This function is called by the target driver to request a 11053 * command to be sent. 11054 * 11055 * Argument: *ap SCSI address of the device. 11056 * *pkt SCSI packet containing the cmd to send. 11057 * 11058 * Return Value: TRAN_ACCEPT 11059 * TRAN_BUSY 11060 * TRAN_BADPKT 11061 * TRAN_FATAL_ERROR 11062 */ 11063 static int 11064 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11065 { 11066 struct fcp_port *pptr = ADDR2FCP(ap); 11067 struct fcp_lun *plun = ADDR2LUN(ap); 11068 struct fcp_pkt *cmd = PKT2CMD(pkt); 11069 struct fcp_tgt *ptgt = plun->lun_tgt; 11070 int rval; 11071 11072 /* ensure command isn't already issued */ 11073 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11074 11075 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11076 fcp_trace, FCP_BUF_LEVEL_9, 0, 11077 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11078 11079 /* 11080 * It is strange that we enter the fcp_port mutex and the target 11081 * mutex to check the lun state (which has a mutex of its own). 11082 */ 11083 mutex_enter(&pptr->port_mutex); 11084 mutex_enter(&ptgt->tgt_mutex); 11085 11086 /* 11087 * If the device is offline and is not in the process of coming 11088 * online, fail the request. 11089 */ 11090 11091 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11092 !(plun->lun_state & FCP_LUN_ONLINING)) { 11093 mutex_exit(&ptgt->tgt_mutex); 11094 mutex_exit(&pptr->port_mutex); 11095 11096 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11097 pkt->pkt_reason = CMD_DEV_GONE; 11098 } 11099 11100 return (TRAN_FATAL_ERROR); 11101 } 11102 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11103 11104 /* 11105 * If we are suspended, kernel is trying to dump, so don't 11106 * block, fail or defer requests - send them down right away. 11107 * NOTE: If we are in panic (i.e. trying to dump), we can't 11108 * assume we have been suspended. There is hardware such as 11109 * the v880 that doesn't do PM. Thus, the check for 11110 * ddi_in_panic. 11111 * 11112 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11113 * of changing. So, if we can queue the packet, do it. Eventually, 11114 * either the device will have gone away or changed and we can fail 11115 * the request, or we can proceed if the device didn't change. 11116 * 11117 * If the pd in the target or the packet is NULL it's probably 11118 * because the device has gone away, we allow the request to be 11119 * put on the internal queue here in case the device comes back within 11120 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11121 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11122 * could be NULL because the device was disappearing during or since 11123 * packet initialization. 11124 */ 11125 11126 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11127 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11128 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11129 (ptgt->tgt_pd_handle == NULL) || 11130 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11131 /* 11132 * If ((LUN is busy AND 11133 * LUN not suspended AND 11134 * The system is not in panic state) OR 11135 * (The port is coming up)) 11136 * 11137 * We check to see if the any of the flags FLAG_NOINTR or 11138 * FLAG_NOQUEUE is set. If one of them is set the value 11139 * returned will be TRAN_BUSY. If not, the request is queued. 11140 */ 11141 mutex_exit(&ptgt->tgt_mutex); 11142 mutex_exit(&pptr->port_mutex); 11143 11144 /* see if using interrupts is allowed (so queueing'll work) */ 11145 if (pkt->pkt_flags & FLAG_NOINTR) { 11146 pkt->pkt_resid = 0; 11147 return (TRAN_BUSY); 11148 } 11149 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11150 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11151 fcp_trace, FCP_BUF_LEVEL_9, 0, 11152 "fcp_scsi_start: lun busy for pkt %p", pkt); 11153 return (TRAN_BUSY); 11154 } 11155 #ifdef DEBUG 11156 mutex_enter(&pptr->port_pkt_mutex); 11157 pptr->port_npkts++; 11158 mutex_exit(&pptr->port_pkt_mutex); 11159 #endif /* DEBUG */ 11160 11161 /* got queue up the pkt for later */ 11162 fcp_queue_pkt(pptr, cmd); 11163 return (TRAN_ACCEPT); 11164 } 11165 cmd->cmd_state = FCP_PKT_ISSUED; 11166 11167 mutex_exit(&ptgt->tgt_mutex); 11168 mutex_exit(&pptr->port_mutex); 11169 11170 /* 11171 * Now that we released the mutexes, what was protected by them can 11172 * change. 11173 */ 11174 11175 /* 11176 * If there is a reconfiguration in progress, wait for it to complete. 11177 */ 11178 fcp_reconfig_wait(pptr); 11179 11180 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11181 pkt->pkt_time : 0; 11182 11183 /* prepare the packet */ 11184 11185 fcp_prepare_pkt(pptr, cmd, plun); 11186 11187 if (cmd->cmd_pkt->pkt_time) { 11188 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11189 } else { 11190 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11191 } 11192 11193 /* 11194 * if interrupts aren't allowed (e.g. at dump time) then we'll 11195 * have to do polled I/O 11196 */ 11197 if (pkt->pkt_flags & FLAG_NOINTR) { 11198 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11199 return (fcp_dopoll(pptr, cmd)); 11200 } 11201 11202 #ifdef DEBUG 11203 mutex_enter(&pptr->port_pkt_mutex); 11204 pptr->port_npkts++; 11205 mutex_exit(&pptr->port_pkt_mutex); 11206 #endif /* DEBUG */ 11207 11208 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11209 if (rval == FC_SUCCESS) { 11210 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11211 fcp_trace, FCP_BUF_LEVEL_9, 0, 11212 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11213 return (TRAN_ACCEPT); 11214 } 11215 11216 cmd->cmd_state = FCP_PKT_IDLE; 11217 11218 #ifdef DEBUG 11219 mutex_enter(&pptr->port_pkt_mutex); 11220 pptr->port_npkts--; 11221 mutex_exit(&pptr->port_pkt_mutex); 11222 #endif /* DEBUG */ 11223 11224 /* 11225 * For lack of clearer definitions, choose 11226 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11227 */ 11228 11229 if (rval == FC_TRAN_BUSY) { 11230 pkt->pkt_resid = 0; 11231 rval = TRAN_BUSY; 11232 } else { 11233 mutex_enter(&ptgt->tgt_mutex); 11234 if (plun->lun_state & FCP_LUN_OFFLINE) { 11235 child_info_t *cip; 11236 11237 mutex_enter(&plun->lun_mutex); 11238 cip = plun->lun_cip; 11239 mutex_exit(&plun->lun_mutex); 11240 11241 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11242 fcp_trace, FCP_BUF_LEVEL_6, 0, 11243 "fcp_transport failed 2 for %x: %x; dip=%p", 11244 plun->lun_tgt->tgt_d_id, rval, cip); 11245 11246 rval = TRAN_FATAL_ERROR; 11247 } else { 11248 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11249 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11250 fcp_trace, FCP_BUF_LEVEL_9, 0, 11251 "fcp_scsi_start: FC_BUSY for pkt %p", 11252 pkt); 11253 rval = TRAN_BUSY; 11254 } else { 11255 rval = TRAN_ACCEPT; 11256 fcp_queue_pkt(pptr, cmd); 11257 } 11258 } 11259 mutex_exit(&ptgt->tgt_mutex); 11260 } 11261 11262 return (rval); 11263 } 11264 11265 /* 11266 * called by the transport to abort a packet 11267 */ 11268 /*ARGSUSED*/ 11269 static int 11270 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11271 { 11272 int tgt_cnt; 11273 struct fcp_port *pptr = ADDR2FCP(ap); 11274 struct fcp_lun *plun = ADDR2LUN(ap); 11275 struct fcp_tgt *ptgt = plun->lun_tgt; 11276 11277 if (pkt == NULL) { 11278 if (ptgt) { 11279 mutex_enter(&ptgt->tgt_mutex); 11280 tgt_cnt = ptgt->tgt_change_cnt; 11281 mutex_exit(&ptgt->tgt_mutex); 11282 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11283 return (TRUE); 11284 } 11285 } 11286 return (FALSE); 11287 } 11288 11289 11290 /* 11291 * Perform reset 11292 */ 11293 int 11294 fcp_scsi_reset(struct scsi_address *ap, int level) 11295 { 11296 int rval = 0; 11297 struct fcp_port *pptr = ADDR2FCP(ap); 11298 struct fcp_lun *plun = ADDR2LUN(ap); 11299 struct fcp_tgt *ptgt = plun->lun_tgt; 11300 11301 if (level == RESET_ALL) { 11302 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11303 rval = 1; 11304 } 11305 } else if (level == RESET_TARGET || level == RESET_LUN) { 11306 /* 11307 * If we are in the middle of discovery, return 11308 * SUCCESS as this target will be rediscovered 11309 * anyway 11310 */ 11311 mutex_enter(&ptgt->tgt_mutex); 11312 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11313 mutex_exit(&ptgt->tgt_mutex); 11314 return (1); 11315 } 11316 mutex_exit(&ptgt->tgt_mutex); 11317 11318 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11319 rval = 1; 11320 } 11321 } 11322 return (rval); 11323 } 11324 11325 11326 /* 11327 * called by the framework to get a SCSI capability 11328 */ 11329 static int 11330 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11331 { 11332 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11333 } 11334 11335 11336 /* 11337 * called by the framework to set a SCSI capability 11338 */ 11339 static int 11340 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11341 { 11342 return (fcp_commoncap(ap, cap, value, whom, 1)); 11343 } 11344 11345 /* 11346 * Function: fcp_pkt_setup 11347 * 11348 * Description: This function sets up the scsi_pkt structure passed by the 11349 * caller. This function assumes fcp_pkt_constructor has been 11350 * called previously for the packet passed by the caller. If 11351 * successful this call will have the following results: 11352 * 11353 * - The resources needed that will be constant through out 11354 * the whole transaction are allocated. 11355 * - The fields that will be constant through out the whole 11356 * transaction are initialized. 11357 * - The scsi packet will be linked to the LUN structure 11358 * addressed by the transaction. 11359 * 11360 * Argument: 11361 * *pkt Pointer to a scsi_pkt structure. 11362 * callback 11363 * arg 11364 * 11365 * Return Value: 0 Success 11366 * !0 Failure 11367 * 11368 * Context: Kernel context or interrupt context 11369 */ 11370 /* ARGSUSED */ 11371 static int 11372 fcp_pkt_setup(struct scsi_pkt *pkt, 11373 int (*callback)(caddr_t arg), 11374 caddr_t arg) 11375 { 11376 struct fcp_pkt *cmd; 11377 struct fcp_port *pptr; 11378 struct fcp_lun *plun; 11379 struct fcp_tgt *ptgt; 11380 int kf; 11381 fc_packet_t *fpkt; 11382 fc_frame_hdr_t *hp; 11383 11384 pptr = ADDR2FCP(&pkt->pkt_address); 11385 plun = ADDR2LUN(&pkt->pkt_address); 11386 ptgt = plun->lun_tgt; 11387 11388 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11389 fpkt = cmd->cmd_fp_pkt; 11390 11391 /* 11392 * this request is for dma allocation only 11393 */ 11394 /* 11395 * First step of fcp_scsi_init_pkt: pkt allocation 11396 * We determine if the caller is willing to wait for the 11397 * resources. 11398 */ 11399 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11400 11401 /* 11402 * Selective zeroing of the pkt. 11403 */ 11404 cmd->cmd_back = NULL; 11405 cmd->cmd_next = NULL; 11406 11407 /* 11408 * Zero out fcp command 11409 */ 11410 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11411 11412 cmd->cmd_state = FCP_PKT_IDLE; 11413 11414 fpkt = cmd->cmd_fp_pkt; 11415 fpkt->pkt_data_acc = NULL; 11416 11417 /* 11418 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11419 * could be destroyed. We need fail pkt_setup. 11420 */ 11421 if (pptr->port_state & FCP_STATE_OFFLINE) { 11422 return (-1); 11423 } 11424 11425 mutex_enter(&ptgt->tgt_mutex); 11426 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11427 11428 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11429 != FC_SUCCESS) { 11430 mutex_exit(&ptgt->tgt_mutex); 11431 return (-1); 11432 } 11433 11434 mutex_exit(&ptgt->tgt_mutex); 11435 11436 /* Fill in the Fabric Channel Header */ 11437 hp = &fpkt->pkt_cmd_fhdr; 11438 hp->r_ctl = R_CTL_COMMAND; 11439 hp->rsvd = 0; 11440 hp->type = FC_TYPE_SCSI_FCP; 11441 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11442 hp->seq_id = 0; 11443 hp->df_ctl = 0; 11444 hp->seq_cnt = 0; 11445 hp->ox_id = 0xffff; 11446 hp->rx_id = 0xffff; 11447 hp->ro = 0; 11448 11449 /* 11450 * A doubly linked list (cmd_forw, cmd_back) is built 11451 * out of every allocated packet on a per-lun basis 11452 * 11453 * The packets are maintained in the list so as to satisfy 11454 * scsi_abort() requests. At present (which is unlikely to 11455 * change in the future) nobody performs a real scsi_abort 11456 * in the SCSI target drivers (as they don't keep the packets 11457 * after doing scsi_transport - so they don't know how to 11458 * abort a packet other than sending a NULL to abort all 11459 * outstanding packets) 11460 */ 11461 mutex_enter(&plun->lun_mutex); 11462 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11463 plun->lun_pkt_head->cmd_back = cmd; 11464 } else { 11465 plun->lun_pkt_tail = cmd; 11466 } 11467 plun->lun_pkt_head = cmd; 11468 mutex_exit(&plun->lun_mutex); 11469 return (0); 11470 } 11471 11472 /* 11473 * Function: fcp_pkt_teardown 11474 * 11475 * Description: This function releases a scsi_pkt structure and all the 11476 * resources attached to it. 11477 * 11478 * Argument: *pkt Pointer to a scsi_pkt structure. 11479 * 11480 * Return Value: None 11481 * 11482 * Context: User, Kernel or Interrupt context. 11483 */ 11484 static void 11485 fcp_pkt_teardown(struct scsi_pkt *pkt) 11486 { 11487 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11488 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11489 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11490 11491 /* 11492 * Remove the packet from the per-lun list 11493 */ 11494 mutex_enter(&plun->lun_mutex); 11495 if (cmd->cmd_back) { 11496 ASSERT(cmd != plun->lun_pkt_head); 11497 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11498 } else { 11499 ASSERT(cmd == plun->lun_pkt_head); 11500 plun->lun_pkt_head = cmd->cmd_forw; 11501 } 11502 11503 if (cmd->cmd_forw) { 11504 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11505 } else { 11506 ASSERT(cmd == plun->lun_pkt_tail); 11507 plun->lun_pkt_tail = cmd->cmd_back; 11508 } 11509 11510 mutex_exit(&plun->lun_mutex); 11511 11512 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11513 } 11514 11515 /* 11516 * Routine for reset notification setup, to register or cancel. 11517 * This function is called by SCSA 11518 */ 11519 /*ARGSUSED*/ 11520 static int 11521 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11522 void (*callback)(caddr_t), caddr_t arg) 11523 { 11524 struct fcp_port *pptr = ADDR2FCP(ap); 11525 11526 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11527 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11528 } 11529 11530 11531 static int 11532 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11533 ddi_eventcookie_t *event_cookiep) 11534 { 11535 struct fcp_port *pptr = fcp_dip2port(dip); 11536 11537 if (pptr == NULL) { 11538 return (DDI_FAILURE); 11539 } 11540 11541 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11542 event_cookiep, NDI_EVENT_NOPASS)); 11543 } 11544 11545 11546 static int 11547 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11548 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11549 ddi_callback_id_t *cb_id) 11550 { 11551 struct fcp_port *pptr = fcp_dip2port(dip); 11552 11553 if (pptr == NULL) { 11554 return (DDI_FAILURE); 11555 } 11556 11557 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11558 eventid, callback, arg, NDI_SLEEP, cb_id)); 11559 } 11560 11561 11562 static int 11563 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11564 { 11565 11566 struct fcp_port *pptr = fcp_dip2port(dip); 11567 11568 if (pptr == NULL) { 11569 return (DDI_FAILURE); 11570 } 11571 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11572 } 11573 11574 11575 /* 11576 * called by the transport to post an event 11577 */ 11578 static int 11579 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11580 ddi_eventcookie_t eventid, void *impldata) 11581 { 11582 struct fcp_port *pptr = fcp_dip2port(dip); 11583 11584 if (pptr == NULL) { 11585 return (DDI_FAILURE); 11586 } 11587 11588 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11589 eventid, impldata)); 11590 } 11591 11592 11593 /* 11594 * A target in in many cases in Fibre Channel has a one to one relation 11595 * with a port identifier (which is also known as D_ID and also as AL_PA 11596 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11597 * will most likely result in resetting all LUNs (which means a reset will 11598 * occur on all the SCSI devices connected at the other end of the bridge) 11599 * That is the latest favorite topic for discussion, for, one can debate as 11600 * hot as one likes and come up with arguably a best solution to one's 11601 * satisfaction 11602 * 11603 * To stay on track and not digress much, here are the problems stated 11604 * briefly: 11605 * 11606 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11607 * target drivers use RESET_TARGET even if their instance is on a 11608 * LUN. Doesn't that sound a bit broken ? 11609 * 11610 * FCP SCSI (the current spec) only defines RESET TARGET in the 11611 * control fields of an FCP_CMND structure. It should have been 11612 * fixed right there, giving flexibility to the initiators to 11613 * minimize havoc that could be caused by resetting a target. 11614 */ 11615 static int 11616 fcp_reset_target(struct scsi_address *ap, int level) 11617 { 11618 int rval = FC_FAILURE; 11619 char lun_id[25]; 11620 struct fcp_port *pptr = ADDR2FCP(ap); 11621 struct fcp_lun *plun = ADDR2LUN(ap); 11622 struct fcp_tgt *ptgt = plun->lun_tgt; 11623 struct scsi_pkt *pkt; 11624 struct fcp_pkt *cmd; 11625 struct fcp_rsp *rsp; 11626 uint32_t tgt_cnt; 11627 struct fcp_rsp_info *rsp_info; 11628 struct fcp_reset_elem *p; 11629 int bval; 11630 11631 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11632 KM_NOSLEEP)) == NULL) { 11633 return (rval); 11634 } 11635 11636 mutex_enter(&ptgt->tgt_mutex); 11637 if (level == RESET_TARGET) { 11638 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11639 mutex_exit(&ptgt->tgt_mutex); 11640 kmem_free(p, sizeof (struct fcp_reset_elem)); 11641 return (rval); 11642 } 11643 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11644 (void) strcpy(lun_id, " "); 11645 } else { 11646 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11647 mutex_exit(&ptgt->tgt_mutex); 11648 kmem_free(p, sizeof (struct fcp_reset_elem)); 11649 return (rval); 11650 } 11651 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11652 11653 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11654 } 11655 tgt_cnt = ptgt->tgt_change_cnt; 11656 11657 mutex_exit(&ptgt->tgt_mutex); 11658 11659 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11660 0, 0, NULL, 0)) == NULL) { 11661 kmem_free(p, sizeof (struct fcp_reset_elem)); 11662 mutex_enter(&ptgt->tgt_mutex); 11663 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11664 mutex_exit(&ptgt->tgt_mutex); 11665 return (rval); 11666 } 11667 pkt->pkt_time = FCP_POLL_TIMEOUT; 11668 11669 /* fill in cmd part of packet */ 11670 cmd = PKT2CMD(pkt); 11671 if (level == RESET_TARGET) { 11672 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11673 } else { 11674 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11675 } 11676 cmd->cmd_fp_pkt->pkt_comp = NULL; 11677 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11678 11679 /* prepare a packet for transport */ 11680 fcp_prepare_pkt(pptr, cmd, plun); 11681 11682 if (cmd->cmd_pkt->pkt_time) { 11683 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11684 } else { 11685 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11686 } 11687 11688 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11689 bval = fcp_dopoll(pptr, cmd); 11690 fc_ulp_idle_port(pptr->port_fp_handle); 11691 11692 /* submit the packet */ 11693 if (bval == TRAN_ACCEPT) { 11694 int error = 3; 11695 11696 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11697 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11698 sizeof (struct fcp_rsp)); 11699 11700 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11701 if (fcp_validate_fcp_response(rsp, pptr) == 11702 FC_SUCCESS) { 11703 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11704 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11705 sizeof (struct fcp_rsp), rsp_info, 11706 cmd->cmd_fp_pkt->pkt_resp_acc, 11707 sizeof (struct fcp_rsp_info)); 11708 } 11709 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11710 rval = FC_SUCCESS; 11711 error = 0; 11712 } else { 11713 error = 1; 11714 } 11715 } else { 11716 error = 2; 11717 } 11718 } 11719 11720 switch (error) { 11721 case 0: 11722 fcp_log(CE_WARN, pptr->port_dip, 11723 "!FCP: WWN 0x%08x%08x %s reset successfully", 11724 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11725 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11726 break; 11727 11728 case 1: 11729 fcp_log(CE_WARN, pptr->port_dip, 11730 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11731 " response code=%x", 11732 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11733 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11734 rsp_info->rsp_code); 11735 break; 11736 11737 case 2: 11738 fcp_log(CE_WARN, pptr->port_dip, 11739 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11740 " Bad FCP response values: rsvd1=%x," 11741 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11742 " rsplen=%x, senselen=%x", 11743 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11744 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11745 rsp->reserved_0, rsp->reserved_1, 11746 rsp->fcp_u.fcp_status.reserved_0, 11747 rsp->fcp_u.fcp_status.reserved_1, 11748 rsp->fcp_response_len, rsp->fcp_sense_len); 11749 break; 11750 11751 default: 11752 fcp_log(CE_WARN, pptr->port_dip, 11753 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11754 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11755 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11756 break; 11757 } 11758 } 11759 scsi_destroy_pkt(pkt); 11760 11761 if (rval == FC_FAILURE) { 11762 mutex_enter(&ptgt->tgt_mutex); 11763 if (level == RESET_TARGET) { 11764 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11765 } else { 11766 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11767 } 11768 mutex_exit(&ptgt->tgt_mutex); 11769 kmem_free(p, sizeof (struct fcp_reset_elem)); 11770 return (rval); 11771 } 11772 11773 mutex_enter(&pptr->port_mutex); 11774 if (level == RESET_TARGET) { 11775 p->tgt = ptgt; 11776 p->lun = NULL; 11777 } else { 11778 p->tgt = NULL; 11779 p->lun = plun; 11780 } 11781 p->tgt = ptgt; 11782 p->tgt_cnt = tgt_cnt; 11783 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11784 p->next = pptr->port_reset_list; 11785 pptr->port_reset_list = p; 11786 11787 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11788 fcp_trace, FCP_BUF_LEVEL_3, 0, 11789 "Notify ssd of the reset to reinstate the reservations"); 11790 11791 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11792 &pptr->port_reset_notify_listf); 11793 11794 mutex_exit(&pptr->port_mutex); 11795 11796 return (rval); 11797 } 11798 11799 11800 /* 11801 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11802 * SCSI capabilities 11803 */ 11804 /* ARGSUSED */ 11805 static int 11806 fcp_commoncap(struct scsi_address *ap, char *cap, 11807 int val, int tgtonly, int doset) 11808 { 11809 struct fcp_port *pptr = ADDR2FCP(ap); 11810 struct fcp_lun *plun = ADDR2LUN(ap); 11811 struct fcp_tgt *ptgt = plun->lun_tgt; 11812 int cidx; 11813 int rval = FALSE; 11814 11815 if (cap == (char *)0) { 11816 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11817 fcp_trace, FCP_BUF_LEVEL_3, 0, 11818 "fcp_commoncap: invalid arg"); 11819 return (rval); 11820 } 11821 11822 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11823 return (UNDEFINED); 11824 } 11825 11826 /* 11827 * Process setcap request. 11828 */ 11829 if (doset) { 11830 /* 11831 * At present, we can only set binary (0/1) values 11832 */ 11833 switch (cidx) { 11834 case SCSI_CAP_ARQ: 11835 if (val == 0) { 11836 rval = FALSE; 11837 } else { 11838 rval = TRUE; 11839 } 11840 break; 11841 11842 case SCSI_CAP_LUN_RESET: 11843 if (val) { 11844 plun->lun_cap |= FCP_LUN_CAP_RESET; 11845 } else { 11846 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11847 } 11848 rval = TRUE; 11849 break; 11850 11851 case SCSI_CAP_SECTOR_SIZE: 11852 rval = TRUE; 11853 break; 11854 default: 11855 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11856 fcp_trace, FCP_BUF_LEVEL_4, 0, 11857 "fcp_setcap: unsupported %d", cidx); 11858 rval = UNDEFINED; 11859 break; 11860 } 11861 11862 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11863 fcp_trace, FCP_BUF_LEVEL_5, 0, 11864 "set cap: cap=%s, val/tgtonly/doset/rval = " 11865 "0x%x/0x%x/0x%x/%d", 11866 cap, val, tgtonly, doset, rval); 11867 11868 } else { 11869 /* 11870 * Process getcap request. 11871 */ 11872 switch (cidx) { 11873 case SCSI_CAP_DMA_MAX: 11874 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11875 11876 /* 11877 * Need to make an adjustment qlc is uint_t 64 11878 * st is int, so we will make the adjustment here 11879 * being as nobody wants to touch this. 11880 * It still leaves the max single block length 11881 * of 2 gig. This should last . 11882 */ 11883 11884 if (rval == -1) { 11885 rval = MAX_INT_DMA; 11886 } 11887 11888 break; 11889 11890 case SCSI_CAP_INITIATOR_ID: 11891 rval = pptr->port_id; 11892 break; 11893 11894 case SCSI_CAP_ARQ: 11895 case SCSI_CAP_RESET_NOTIFICATION: 11896 case SCSI_CAP_TAGGED_QING: 11897 rval = TRUE; 11898 break; 11899 11900 case SCSI_CAP_SCSI_VERSION: 11901 rval = 3; 11902 break; 11903 11904 case SCSI_CAP_INTERCONNECT_TYPE: 11905 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11906 (ptgt->tgt_hard_addr == 0)) { 11907 rval = INTERCONNECT_FABRIC; 11908 } else { 11909 rval = INTERCONNECT_FIBRE; 11910 } 11911 break; 11912 11913 case SCSI_CAP_LUN_RESET: 11914 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11915 TRUE : FALSE; 11916 break; 11917 11918 default: 11919 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11920 fcp_trace, FCP_BUF_LEVEL_4, 0, 11921 "fcp_getcap: unsupported %d", cidx); 11922 rval = UNDEFINED; 11923 break; 11924 } 11925 11926 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11927 fcp_trace, FCP_BUF_LEVEL_8, 0, 11928 "get cap: cap=%s, val/tgtonly/doset/rval = " 11929 "0x%x/0x%x/0x%x/%d", 11930 cap, val, tgtonly, doset, rval); 11931 } 11932 11933 return (rval); 11934 } 11935 11936 /* 11937 * called by the transport to get the port-wwn and lun 11938 * properties of this device, and to create a "name" based on them 11939 * 11940 * these properties don't exist on sun4m 11941 * 11942 * return 1 for success else return 0 11943 */ 11944 /* ARGSUSED */ 11945 static int 11946 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11947 { 11948 int i; 11949 int *lun; 11950 int numChars; 11951 uint_t nlun; 11952 uint_t count; 11953 uint_t nbytes; 11954 uchar_t *bytes; 11955 uint16_t lun_num; 11956 uint32_t tgt_id; 11957 char **conf_wwn; 11958 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11959 uchar_t barray[FC_WWN_SIZE]; 11960 dev_info_t *tgt_dip; 11961 struct fcp_tgt *ptgt; 11962 struct fcp_port *pptr; 11963 struct fcp_lun *plun; 11964 11965 ASSERT(sd != NULL); 11966 ASSERT(name != NULL); 11967 11968 tgt_dip = sd->sd_dev; 11969 pptr = ddi_get_soft_state(fcp_softstate, 11970 ddi_get_instance(ddi_get_parent(tgt_dip))); 11971 if (pptr == NULL) { 11972 return (0); 11973 } 11974 11975 ASSERT(tgt_dip != NULL); 11976 11977 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11978 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11979 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11980 name[0] = '\0'; 11981 return (0); 11982 } 11983 11984 if (nlun == 0) { 11985 ddi_prop_free(lun); 11986 return (0); 11987 } 11988 11989 lun_num = lun[0]; 11990 ddi_prop_free(lun); 11991 11992 /* 11993 * Lookup for .conf WWN property 11994 */ 11995 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11996 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11997 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11998 ASSERT(count >= 1); 11999 12000 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 12001 ddi_prop_free(conf_wwn); 12002 mutex_enter(&pptr->port_mutex); 12003 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 12004 mutex_exit(&pptr->port_mutex); 12005 return (0); 12006 } 12007 ptgt = plun->lun_tgt; 12008 mutex_exit(&pptr->port_mutex); 12009 12010 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 12011 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 12012 12013 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12014 ptgt->tgt_hard_addr != 0) { 12015 tgt_id = (uint32_t)fcp_alpa_to_switch[ 12016 ptgt->tgt_hard_addr]; 12017 } else { 12018 tgt_id = ptgt->tgt_d_id; 12019 } 12020 12021 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 12022 TARGET_PROP, tgt_id); 12023 } 12024 12025 /* get the our port-wwn property */ 12026 bytes = NULL; 12027 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 12028 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12029 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 12030 if (bytes != NULL) { 12031 ddi_prop_free(bytes); 12032 } 12033 return (0); 12034 } 12035 12036 for (i = 0; i < FC_WWN_SIZE; i++) { 12037 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12038 } 12039 12040 /* Stick in the address of the form "wWWN,LUN" */ 12041 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12042 12043 ASSERT(numChars < len); 12044 if (numChars >= len) { 12045 fcp_log(CE_WARN, pptr->port_dip, 12046 "!fcp_scsi_get_name: " 12047 "name parameter length too small, it needs to be %d", 12048 numChars+1); 12049 } 12050 12051 ddi_prop_free(bytes); 12052 12053 return (1); 12054 } 12055 12056 12057 /* 12058 * called by the transport to get the SCSI target id value, returning 12059 * it in "name" 12060 * 12061 * this isn't needed/used on sun4m 12062 * 12063 * return 1 for success else return 0 12064 */ 12065 /* ARGSUSED */ 12066 static int 12067 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12068 { 12069 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12070 struct fcp_tgt *ptgt; 12071 int numChars; 12072 12073 if (plun == NULL) { 12074 return (0); 12075 } 12076 12077 if ((ptgt = plun->lun_tgt) == NULL) { 12078 return (0); 12079 } 12080 12081 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12082 12083 ASSERT(numChars < len); 12084 if (numChars >= len) { 12085 fcp_log(CE_WARN, NULL, 12086 "!fcp_scsi_get_bus_addr: " 12087 "name parameter length too small, it needs to be %d", 12088 numChars+1); 12089 } 12090 12091 return (1); 12092 } 12093 12094 12095 /* 12096 * called internally to reset the link where the specified port lives 12097 */ 12098 static int 12099 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12100 { 12101 la_wwn_t wwn; 12102 struct fcp_lun *plun; 12103 struct fcp_tgt *ptgt; 12104 12105 /* disable restart of lip if we're suspended */ 12106 mutex_enter(&pptr->port_mutex); 12107 12108 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12109 FCP_STATE_POWER_DOWN)) { 12110 mutex_exit(&pptr->port_mutex); 12111 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12112 fcp_trace, FCP_BUF_LEVEL_2, 0, 12113 "fcp_linkreset, fcp%d: link reset " 12114 "disabled due to DDI_SUSPEND", 12115 ddi_get_instance(pptr->port_dip)); 12116 return (FC_FAILURE); 12117 } 12118 12119 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12120 mutex_exit(&pptr->port_mutex); 12121 return (FC_SUCCESS); 12122 } 12123 12124 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12125 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12126 12127 /* 12128 * If ap == NULL assume local link reset. 12129 */ 12130 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12131 plun = ADDR2LUN(ap); 12132 ptgt = plun->lun_tgt; 12133 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12134 } else { 12135 bzero((caddr_t)&wwn, sizeof (wwn)); 12136 } 12137 mutex_exit(&pptr->port_mutex); 12138 12139 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12140 } 12141 12142 12143 /* 12144 * called from fcp_port_attach() to resume a port 12145 * return DDI_* success/failure status 12146 * acquires and releases the global mutex 12147 * acquires and releases the port mutex 12148 */ 12149 /*ARGSUSED*/ 12150 12151 static int 12152 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12153 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12154 { 12155 int res = DDI_FAILURE; /* default result */ 12156 struct fcp_port *pptr; /* port state ptr */ 12157 uint32_t alloc_cnt; 12158 uint32_t max_cnt; 12159 fc_portmap_t *tmp_list = NULL; 12160 12161 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12162 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12163 instance); 12164 12165 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12166 cmn_err(CE_WARN, "fcp: bad soft state"); 12167 return (res); 12168 } 12169 12170 mutex_enter(&pptr->port_mutex); 12171 switch (cmd) { 12172 case FC_CMD_RESUME: 12173 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12174 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12175 break; 12176 12177 case FC_CMD_POWER_UP: 12178 /* 12179 * If the port is DDI_SUSPENded, defer rediscovery 12180 * until DDI_RESUME occurs 12181 */ 12182 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12183 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12184 mutex_exit(&pptr->port_mutex); 12185 return (DDI_SUCCESS); 12186 } 12187 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12188 } 12189 pptr->port_id = s_id; 12190 pptr->port_state = FCP_STATE_INIT; 12191 mutex_exit(&pptr->port_mutex); 12192 12193 /* 12194 * Make a copy of ulp_port_info as fctl allocates 12195 * a temp struct. 12196 */ 12197 (void) fcp_cp_pinfo(pptr, pinfo); 12198 12199 mutex_enter(&fcp_global_mutex); 12200 if (fcp_watchdog_init++ == 0) { 12201 fcp_watchdog_tick = fcp_watchdog_timeout * 12202 drv_usectohz(1000000); 12203 fcp_watchdog_id = timeout(fcp_watch, 12204 NULL, fcp_watchdog_tick); 12205 } 12206 mutex_exit(&fcp_global_mutex); 12207 12208 /* 12209 * Handle various topologies and link states. 12210 */ 12211 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12212 case FC_STATE_OFFLINE: 12213 /* 12214 * Wait for ONLINE, at which time a state 12215 * change will cause a statec_callback 12216 */ 12217 res = DDI_SUCCESS; 12218 break; 12219 12220 case FC_STATE_ONLINE: 12221 12222 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12223 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12224 res = DDI_SUCCESS; 12225 break; 12226 } 12227 12228 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12229 !fcp_enable_auto_configuration) { 12230 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12231 if (tmp_list == NULL) { 12232 if (!alloc_cnt) { 12233 res = DDI_SUCCESS; 12234 } 12235 break; 12236 } 12237 max_cnt = alloc_cnt; 12238 } else { 12239 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12240 12241 alloc_cnt = FCP_MAX_DEVICES; 12242 12243 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12244 (sizeof (fc_portmap_t)) * alloc_cnt, 12245 KM_NOSLEEP)) == NULL) { 12246 fcp_log(CE_WARN, pptr->port_dip, 12247 "!fcp%d: failed to allocate portmap", 12248 instance); 12249 break; 12250 } 12251 12252 max_cnt = alloc_cnt; 12253 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12254 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12255 FC_SUCCESS) { 12256 caddr_t msg; 12257 12258 (void) fc_ulp_error(res, &msg); 12259 12260 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12261 fcp_trace, FCP_BUF_LEVEL_2, 0, 12262 "resume failed getportmap: reason=0x%x", 12263 res); 12264 12265 fcp_log(CE_WARN, pptr->port_dip, 12266 "!failed to get port map : %s", msg); 12267 break; 12268 } 12269 if (max_cnt > alloc_cnt) { 12270 alloc_cnt = max_cnt; 12271 } 12272 } 12273 12274 /* 12275 * do the SCSI device discovery and create 12276 * the devinfos 12277 */ 12278 fcp_statec_callback(ulph, pptr->port_fp_handle, 12279 pptr->port_phys_state, pptr->port_topology, tmp_list, 12280 max_cnt, pptr->port_id); 12281 12282 res = DDI_SUCCESS; 12283 break; 12284 12285 default: 12286 fcp_log(CE_WARN, pptr->port_dip, 12287 "!fcp%d: invalid port state at attach=0x%x", 12288 instance, pptr->port_phys_state); 12289 12290 mutex_enter(&pptr->port_mutex); 12291 pptr->port_phys_state = FCP_STATE_OFFLINE; 12292 mutex_exit(&pptr->port_mutex); 12293 res = DDI_SUCCESS; 12294 12295 break; 12296 } 12297 12298 if (tmp_list != NULL) { 12299 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12300 } 12301 12302 return (res); 12303 } 12304 12305 12306 static void 12307 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12308 { 12309 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12310 pptr->port_dip = pinfo->port_dip; 12311 pptr->port_fp_handle = pinfo->port_handle; 12312 if (pinfo->port_acc_attr != NULL) { 12313 /* 12314 * FCA supports DMA 12315 */ 12316 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12317 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12318 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12319 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12320 } 12321 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12322 pptr->port_max_exch = pinfo->port_fca_max_exch; 12323 pptr->port_phys_state = pinfo->port_state; 12324 pptr->port_topology = pinfo->port_flags; 12325 pptr->port_reset_action = pinfo->port_reset_action; 12326 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12327 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12328 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12329 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12330 12331 /* Clear FMA caps to avoid fm-capability ereport */ 12332 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12333 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12334 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12335 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12336 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12337 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12338 } 12339 12340 /* 12341 * If the elements wait field is set to 1 then 12342 * another thread is waiting for the operation to complete. Once 12343 * it is complete, the waiting thread is signaled and the element is 12344 * freed by the waiting thread. If the elements wait field is set to 0 12345 * the element is freed. 12346 */ 12347 static void 12348 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12349 { 12350 ASSERT(elem != NULL); 12351 mutex_enter(&elem->mutex); 12352 elem->result = result; 12353 if (elem->wait) { 12354 elem->wait = 0; 12355 cv_signal(&elem->cv); 12356 mutex_exit(&elem->mutex); 12357 } else { 12358 mutex_exit(&elem->mutex); 12359 cv_destroy(&elem->cv); 12360 mutex_destroy(&elem->mutex); 12361 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12362 } 12363 } 12364 12365 /* 12366 * This function is invoked from the taskq thread to allocate 12367 * devinfo nodes and to online/offline them. 12368 */ 12369 static void 12370 fcp_hp_task(void *arg) 12371 { 12372 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12373 struct fcp_lun *plun = elem->lun; 12374 struct fcp_port *pptr = elem->port; 12375 int result; 12376 12377 ASSERT(elem->what == FCP_ONLINE || 12378 elem->what == FCP_OFFLINE || 12379 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12380 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12381 12382 mutex_enter(&pptr->port_mutex); 12383 mutex_enter(&plun->lun_mutex); 12384 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12385 plun->lun_event_count != elem->event_cnt) || 12386 pptr->port_state & (FCP_STATE_SUSPENDED | 12387 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12388 mutex_exit(&plun->lun_mutex); 12389 mutex_exit(&pptr->port_mutex); 12390 fcp_process_elem(elem, NDI_FAILURE); 12391 return; 12392 } 12393 mutex_exit(&plun->lun_mutex); 12394 mutex_exit(&pptr->port_mutex); 12395 12396 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12397 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12398 fcp_process_elem(elem, result); 12399 } 12400 12401 12402 static child_info_t * 12403 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12404 int tcount) 12405 { 12406 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12407 12408 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12409 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12410 12411 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12412 /* 12413 * Child has not been created yet. Create the child device 12414 * based on the per-Lun flags. 12415 */ 12416 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12417 plun->lun_cip = 12418 CIP(fcp_create_dip(plun, lcount, tcount)); 12419 plun->lun_mpxio = 0; 12420 } else { 12421 plun->lun_cip = 12422 CIP(fcp_create_pip(plun, lcount, tcount)); 12423 plun->lun_mpxio = 1; 12424 } 12425 } else { 12426 plun->lun_cip = cip; 12427 } 12428 12429 return (plun->lun_cip); 12430 } 12431 12432 12433 static int 12434 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12435 { 12436 int rval = FC_FAILURE; 12437 dev_info_t *pdip; 12438 struct dev_info *dip; 12439 int circular; 12440 12441 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12442 12443 pdip = plun->lun_tgt->tgt_port->port_dip; 12444 12445 if (plun->lun_cip == NULL) { 12446 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12447 fcp_trace, FCP_BUF_LEVEL_3, 0, 12448 "fcp_is_dip_present: plun->lun_cip is NULL: " 12449 "plun: %p lun state: %x num: %d target state: %x", 12450 plun, plun->lun_state, plun->lun_num, 12451 plun->lun_tgt->tgt_port->port_state); 12452 return (rval); 12453 } 12454 ndi_devi_enter(pdip, &circular); 12455 dip = DEVI(pdip)->devi_child; 12456 while (dip) { 12457 if (dip == DEVI(cdip)) { 12458 rval = FC_SUCCESS; 12459 break; 12460 } 12461 dip = dip->devi_sibling; 12462 } 12463 ndi_devi_exit(pdip, circular); 12464 return (rval); 12465 } 12466 12467 static int 12468 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12469 { 12470 int rval = FC_FAILURE; 12471 12472 ASSERT(plun != NULL); 12473 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12474 12475 if (plun->lun_mpxio == 0) { 12476 rval = fcp_is_dip_present(plun, DIP(cip)); 12477 } else { 12478 rval = fcp_is_pip_present(plun, PIP(cip)); 12479 } 12480 12481 return (rval); 12482 } 12483 12484 /* 12485 * Function: fcp_create_dip 12486 * 12487 * Description: Creates a dev_info_t structure for the LUN specified by the 12488 * caller. 12489 * 12490 * Argument: plun Lun structure 12491 * link_cnt Link state count. 12492 * tgt_cnt Target state change count. 12493 * 12494 * Return Value: NULL if it failed 12495 * dev_info_t structure address if it succeeded 12496 * 12497 * Context: Kernel context 12498 */ 12499 static dev_info_t * 12500 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12501 { 12502 int failure = 0; 12503 uint32_t tgt_id; 12504 uint64_t sam_lun; 12505 struct fcp_tgt *ptgt = plun->lun_tgt; 12506 struct fcp_port *pptr = ptgt->tgt_port; 12507 dev_info_t *pdip = pptr->port_dip; 12508 dev_info_t *cdip = NULL; 12509 dev_info_t *old_dip = DIP(plun->lun_cip); 12510 char *nname = NULL; 12511 char **compatible = NULL; 12512 int ncompatible; 12513 char *scsi_binding_set; 12514 char t_pwwn[17]; 12515 12516 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12517 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12518 12519 /* get the 'scsi-binding-set' property */ 12520 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12521 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12522 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12523 scsi_binding_set = NULL; 12524 } 12525 12526 /* determine the node name and compatible */ 12527 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12528 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12529 if (scsi_binding_set) { 12530 ddi_prop_free(scsi_binding_set); 12531 } 12532 12533 if (nname == NULL) { 12534 #ifdef DEBUG 12535 cmn_err(CE_WARN, "%s%d: no driver for " 12536 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12537 " compatible: %s", 12538 ddi_driver_name(pdip), ddi_get_instance(pdip), 12539 ptgt->tgt_port_wwn.raw_wwn[0], 12540 ptgt->tgt_port_wwn.raw_wwn[1], 12541 ptgt->tgt_port_wwn.raw_wwn[2], 12542 ptgt->tgt_port_wwn.raw_wwn[3], 12543 ptgt->tgt_port_wwn.raw_wwn[4], 12544 ptgt->tgt_port_wwn.raw_wwn[5], 12545 ptgt->tgt_port_wwn.raw_wwn[6], 12546 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12547 *compatible); 12548 #endif /* DEBUG */ 12549 failure++; 12550 goto end_of_fcp_create_dip; 12551 } 12552 12553 cdip = fcp_find_existing_dip(plun, pdip, nname); 12554 12555 /* 12556 * if the old_dip does not match the cdip, that means there is 12557 * some property change. since we'll be using the cdip, we need 12558 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12559 * then the dtype for the device has been updated. Offline the 12560 * the old device and create a new device with the new device type 12561 * Refer to bug: 4764752 12562 */ 12563 if (old_dip && (cdip != old_dip || 12564 plun->lun_state & FCP_LUN_CHANGED)) { 12565 plun->lun_state &= ~(FCP_LUN_INIT); 12566 mutex_exit(&plun->lun_mutex); 12567 mutex_exit(&pptr->port_mutex); 12568 12569 mutex_enter(&ptgt->tgt_mutex); 12570 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12571 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12572 mutex_exit(&ptgt->tgt_mutex); 12573 12574 #ifdef DEBUG 12575 if (cdip != NULL) { 12576 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12577 fcp_trace, FCP_BUF_LEVEL_2, 0, 12578 "Old dip=%p; New dip=%p don't match", old_dip, 12579 cdip); 12580 } else { 12581 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12582 fcp_trace, FCP_BUF_LEVEL_2, 0, 12583 "Old dip=%p; New dip=NULL don't match", old_dip); 12584 } 12585 #endif 12586 12587 mutex_enter(&pptr->port_mutex); 12588 mutex_enter(&plun->lun_mutex); 12589 } 12590 12591 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12592 plun->lun_state &= ~(FCP_LUN_CHANGED); 12593 if (ndi_devi_alloc(pptr->port_dip, nname, 12594 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12595 failure++; 12596 goto end_of_fcp_create_dip; 12597 } 12598 } 12599 12600 /* 12601 * Previously all the properties for the devinfo were destroyed here 12602 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12603 * the devid property (and other properties established by the target 12604 * driver or framework) which the code does not always recreate, this 12605 * call was removed. 12606 * This opens a theoretical possibility that we may return with a 12607 * stale devid on the node if the scsi entity behind the fibre channel 12608 * lun has changed. 12609 */ 12610 12611 /* decorate the node with compatible */ 12612 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12613 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12614 failure++; 12615 goto end_of_fcp_create_dip; 12616 } 12617 12618 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12619 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12620 failure++; 12621 goto end_of_fcp_create_dip; 12622 } 12623 12624 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12625 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12626 failure++; 12627 goto end_of_fcp_create_dip; 12628 } 12629 12630 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12631 t_pwwn[16] = '\0'; 12632 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12633 != DDI_PROP_SUCCESS) { 12634 failure++; 12635 goto end_of_fcp_create_dip; 12636 } 12637 12638 /* 12639 * If there is no hard address - We might have to deal with 12640 * that by using WWN - Having said that it is important to 12641 * recognize this problem early so ssd can be informed of 12642 * the right interconnect type. 12643 */ 12644 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12645 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12646 } else { 12647 tgt_id = ptgt->tgt_d_id; 12648 } 12649 12650 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12651 tgt_id) != DDI_PROP_SUCCESS) { 12652 failure++; 12653 goto end_of_fcp_create_dip; 12654 } 12655 12656 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12657 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12658 failure++; 12659 goto end_of_fcp_create_dip; 12660 } 12661 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12662 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12663 sam_lun) != DDI_PROP_SUCCESS) { 12664 failure++; 12665 goto end_of_fcp_create_dip; 12666 } 12667 12668 end_of_fcp_create_dip: 12669 scsi_hba_nodename_compatible_free(nname, compatible); 12670 12671 if (cdip != NULL && failure) { 12672 (void) ndi_prop_remove_all(cdip); 12673 (void) ndi_devi_free(cdip); 12674 cdip = NULL; 12675 } 12676 12677 return (cdip); 12678 } 12679 12680 /* 12681 * Function: fcp_create_pip 12682 * 12683 * Description: Creates a Path Id for the LUN specified by the caller. 12684 * 12685 * Argument: plun Lun structure 12686 * link_cnt Link state count. 12687 * tgt_cnt Target state count. 12688 * 12689 * Return Value: NULL if it failed 12690 * mdi_pathinfo_t structure address if it succeeded 12691 * 12692 * Context: Kernel context 12693 */ 12694 static mdi_pathinfo_t * 12695 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12696 { 12697 int i; 12698 char buf[MAXNAMELEN]; 12699 char uaddr[MAXNAMELEN]; 12700 int failure = 0; 12701 uint32_t tgt_id; 12702 uint64_t sam_lun; 12703 struct fcp_tgt *ptgt = plun->lun_tgt; 12704 struct fcp_port *pptr = ptgt->tgt_port; 12705 dev_info_t *pdip = pptr->port_dip; 12706 mdi_pathinfo_t *pip = NULL; 12707 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12708 char *nname = NULL; 12709 char **compatible = NULL; 12710 int ncompatible; 12711 char *scsi_binding_set; 12712 char t_pwwn[17]; 12713 12714 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12715 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12716 12717 scsi_binding_set = "vhci"; 12718 12719 /* determine the node name and compatible */ 12720 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12721 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12722 12723 if (nname == NULL) { 12724 #ifdef DEBUG 12725 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12726 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12727 " compatible: %s", 12728 ddi_driver_name(pdip), ddi_get_instance(pdip), 12729 ptgt->tgt_port_wwn.raw_wwn[0], 12730 ptgt->tgt_port_wwn.raw_wwn[1], 12731 ptgt->tgt_port_wwn.raw_wwn[2], 12732 ptgt->tgt_port_wwn.raw_wwn[3], 12733 ptgt->tgt_port_wwn.raw_wwn[4], 12734 ptgt->tgt_port_wwn.raw_wwn[5], 12735 ptgt->tgt_port_wwn.raw_wwn[6], 12736 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12737 *compatible); 12738 #endif /* DEBUG */ 12739 failure++; 12740 goto end_of_fcp_create_pip; 12741 } 12742 12743 pip = fcp_find_existing_pip(plun, pdip); 12744 12745 /* 12746 * if the old_dip does not match the cdip, that means there is 12747 * some property change. since we'll be using the cdip, we need 12748 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12749 * then the dtype for the device has been updated. Offline the 12750 * the old device and create a new device with the new device type 12751 * Refer to bug: 4764752 12752 */ 12753 if (old_pip && (pip != old_pip || 12754 plun->lun_state & FCP_LUN_CHANGED)) { 12755 plun->lun_state &= ~(FCP_LUN_INIT); 12756 mutex_exit(&plun->lun_mutex); 12757 mutex_exit(&pptr->port_mutex); 12758 12759 mutex_enter(&ptgt->tgt_mutex); 12760 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12761 FCP_OFFLINE, lcount, tcount, 12762 NDI_DEVI_REMOVE, 0); 12763 mutex_exit(&ptgt->tgt_mutex); 12764 12765 if (pip != NULL) { 12766 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12767 fcp_trace, FCP_BUF_LEVEL_2, 0, 12768 "Old pip=%p; New pip=%p don't match", 12769 old_pip, pip); 12770 } else { 12771 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12772 fcp_trace, FCP_BUF_LEVEL_2, 0, 12773 "Old pip=%p; New pip=NULL don't match", 12774 old_pip); 12775 } 12776 12777 mutex_enter(&pptr->port_mutex); 12778 mutex_enter(&plun->lun_mutex); 12779 } 12780 12781 /* 12782 * Since FC_WWN_SIZE is 8 bytes and its not like the 12783 * lun_guid_size which is dependent on the target, I don't 12784 * believe the same trancation happens here UNLESS the standards 12785 * change the FC_WWN_SIZE value to something larger than 12786 * MAXNAMELEN(currently 255 bytes). 12787 */ 12788 12789 for (i = 0; i < FC_WWN_SIZE; i++) { 12790 (void) sprintf(&buf[i << 1], "%02x", 12791 ptgt->tgt_port_wwn.raw_wwn[i]); 12792 } 12793 12794 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12795 buf, plun->lun_num); 12796 12797 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12798 /* 12799 * Release the locks before calling into 12800 * mdi_pi_alloc_compatible() since this can result in a 12801 * callback into fcp which can result in a deadlock 12802 * (see bug # 4870272). 12803 * 12804 * Basically, what we are trying to avoid is the scenario where 12805 * one thread does ndi_devi_enter() and tries to grab 12806 * fcp_mutex and another does it the other way round. 12807 * 12808 * But before we do that, make sure that nobody releases the 12809 * port in the meantime. We can do this by setting a flag. 12810 */ 12811 plun->lun_state &= ~(FCP_LUN_CHANGED); 12812 pptr->port_state |= FCP_STATE_IN_MDI; 12813 mutex_exit(&plun->lun_mutex); 12814 mutex_exit(&pptr->port_mutex); 12815 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12816 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12817 fcp_log(CE_WARN, pptr->port_dip, 12818 "!path alloc failed:0x%x", plun); 12819 mutex_enter(&pptr->port_mutex); 12820 mutex_enter(&plun->lun_mutex); 12821 pptr->port_state &= ~FCP_STATE_IN_MDI; 12822 failure++; 12823 goto end_of_fcp_create_pip; 12824 } 12825 mutex_enter(&pptr->port_mutex); 12826 mutex_enter(&plun->lun_mutex); 12827 pptr->port_state &= ~FCP_STATE_IN_MDI; 12828 } else { 12829 (void) mdi_prop_remove(pip, NULL); 12830 } 12831 12832 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12833 12834 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12835 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12836 != DDI_PROP_SUCCESS) { 12837 failure++; 12838 goto end_of_fcp_create_pip; 12839 } 12840 12841 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12842 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12843 != DDI_PROP_SUCCESS) { 12844 failure++; 12845 goto end_of_fcp_create_pip; 12846 } 12847 12848 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12849 t_pwwn[16] = '\0'; 12850 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12851 != DDI_PROP_SUCCESS) { 12852 failure++; 12853 goto end_of_fcp_create_pip; 12854 } 12855 12856 /* 12857 * If there is no hard address - We might have to deal with 12858 * that by using WWN - Having said that it is important to 12859 * recognize this problem early so ssd can be informed of 12860 * the right interconnect type. 12861 */ 12862 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12863 ptgt->tgt_hard_addr != 0) { 12864 tgt_id = (uint32_t) 12865 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12866 } else { 12867 tgt_id = ptgt->tgt_d_id; 12868 } 12869 12870 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12871 != DDI_PROP_SUCCESS) { 12872 failure++; 12873 goto end_of_fcp_create_pip; 12874 } 12875 12876 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12877 != DDI_PROP_SUCCESS) { 12878 failure++; 12879 goto end_of_fcp_create_pip; 12880 } 12881 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12882 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12883 != DDI_PROP_SUCCESS) { 12884 failure++; 12885 goto end_of_fcp_create_pip; 12886 } 12887 12888 end_of_fcp_create_pip: 12889 scsi_hba_nodename_compatible_free(nname, compatible); 12890 12891 if (pip != NULL && failure) { 12892 (void) mdi_prop_remove(pip, NULL); 12893 mutex_exit(&plun->lun_mutex); 12894 mutex_exit(&pptr->port_mutex); 12895 (void) mdi_pi_free(pip, 0); 12896 mutex_enter(&pptr->port_mutex); 12897 mutex_enter(&plun->lun_mutex); 12898 pip = NULL; 12899 } 12900 12901 return (pip); 12902 } 12903 12904 static dev_info_t * 12905 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12906 { 12907 uint_t nbytes; 12908 uchar_t *bytes; 12909 uint_t nwords; 12910 uint32_t tgt_id; 12911 int *words; 12912 dev_info_t *cdip; 12913 dev_info_t *ndip; 12914 struct fcp_tgt *ptgt = plun->lun_tgt; 12915 struct fcp_port *pptr = ptgt->tgt_port; 12916 int circular; 12917 12918 ndi_devi_enter(pdip, &circular); 12919 12920 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12921 while ((cdip = ndip) != NULL) { 12922 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12923 12924 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12925 continue; 12926 } 12927 12928 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12929 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12930 &nbytes) != DDI_PROP_SUCCESS) { 12931 continue; 12932 } 12933 12934 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12935 if (bytes != NULL) { 12936 ddi_prop_free(bytes); 12937 } 12938 continue; 12939 } 12940 ASSERT(bytes != NULL); 12941 12942 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12943 ddi_prop_free(bytes); 12944 continue; 12945 } 12946 12947 ddi_prop_free(bytes); 12948 12949 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12950 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12951 &nbytes) != DDI_PROP_SUCCESS) { 12952 continue; 12953 } 12954 12955 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12956 if (bytes != NULL) { 12957 ddi_prop_free(bytes); 12958 } 12959 continue; 12960 } 12961 ASSERT(bytes != NULL); 12962 12963 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12964 ddi_prop_free(bytes); 12965 continue; 12966 } 12967 12968 ddi_prop_free(bytes); 12969 12970 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12971 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12972 &nwords) != DDI_PROP_SUCCESS) { 12973 continue; 12974 } 12975 12976 if (nwords != 1 || words == NULL) { 12977 if (words != NULL) { 12978 ddi_prop_free(words); 12979 } 12980 continue; 12981 } 12982 ASSERT(words != NULL); 12983 12984 /* 12985 * If there is no hard address - We might have to deal with 12986 * that by using WWN - Having said that it is important to 12987 * recognize this problem early so ssd can be informed of 12988 * the right interconnect type. 12989 */ 12990 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12991 ptgt->tgt_hard_addr != 0) { 12992 tgt_id = 12993 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12994 } else { 12995 tgt_id = ptgt->tgt_d_id; 12996 } 12997 12998 if (tgt_id != (uint32_t)*words) { 12999 ddi_prop_free(words); 13000 continue; 13001 } 13002 ddi_prop_free(words); 13003 13004 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 13005 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 13006 &nwords) != DDI_PROP_SUCCESS) { 13007 continue; 13008 } 13009 13010 if (nwords != 1 || words == NULL) { 13011 if (words != NULL) { 13012 ddi_prop_free(words); 13013 } 13014 continue; 13015 } 13016 ASSERT(words != NULL); 13017 13018 if (plun->lun_num == (uint16_t)*words) { 13019 ddi_prop_free(words); 13020 break; 13021 } 13022 ddi_prop_free(words); 13023 } 13024 ndi_devi_exit(pdip, circular); 13025 13026 return (cdip); 13027 } 13028 13029 13030 static int 13031 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 13032 { 13033 dev_info_t *pdip; 13034 char buf[MAXNAMELEN]; 13035 char uaddr[MAXNAMELEN]; 13036 int rval = FC_FAILURE; 13037 13038 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13039 13040 pdip = plun->lun_tgt->tgt_port->port_dip; 13041 13042 /* 13043 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13044 * non-NULL even when the LUN is not there as in the case when a LUN is 13045 * configured and then deleted on the device end (for T3/T4 case). In 13046 * such cases, pip will be NULL. 13047 * 13048 * If the device generates an RSCN, it will end up getting offlined when 13049 * it disappeared and a new LUN will get created when it is rediscovered 13050 * on the device. If we check for lun_cip here, the LUN will not end 13051 * up getting onlined since this function will end up returning a 13052 * FC_SUCCESS. 13053 * 13054 * The behavior is different on other devices. For instance, on a HDS, 13055 * there was no RSCN generated by the device but the next I/O generated 13056 * a check condition and rediscovery got triggered that way. So, in 13057 * such cases, this path will not be exercised 13058 */ 13059 if (pip == NULL) { 13060 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13061 fcp_trace, FCP_BUF_LEVEL_4, 0, 13062 "fcp_is_pip_present: plun->lun_cip is NULL: " 13063 "plun: %p lun state: %x num: %d target state: %x", 13064 plun, plun->lun_state, plun->lun_num, 13065 plun->lun_tgt->tgt_port->port_state); 13066 return (rval); 13067 } 13068 13069 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13070 13071 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13072 13073 if (plun->lun_old_guid) { 13074 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 13075 rval = FC_SUCCESS; 13076 } 13077 } else { 13078 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 13079 rval = FC_SUCCESS; 13080 } 13081 } 13082 return (rval); 13083 } 13084 13085 static mdi_pathinfo_t * 13086 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13087 { 13088 char buf[MAXNAMELEN]; 13089 char uaddr[MAXNAMELEN]; 13090 mdi_pathinfo_t *pip; 13091 struct fcp_tgt *ptgt = plun->lun_tgt; 13092 struct fcp_port *pptr = ptgt->tgt_port; 13093 13094 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13095 13096 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13097 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13098 13099 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13100 13101 return (pip); 13102 } 13103 13104 13105 static int 13106 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13107 int tcount, int flags, int *circ) 13108 { 13109 int rval; 13110 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13111 struct fcp_tgt *ptgt = plun->lun_tgt; 13112 dev_info_t *cdip = NULL; 13113 13114 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13115 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13116 13117 if (plun->lun_cip == NULL) { 13118 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13119 fcp_trace, FCP_BUF_LEVEL_3, 0, 13120 "fcp_online_child: plun->lun_cip is NULL: " 13121 "plun: %p state: %x num: %d target state: %x", 13122 plun, plun->lun_state, plun->lun_num, 13123 plun->lun_tgt->tgt_port->port_state); 13124 return (NDI_FAILURE); 13125 } 13126 again: 13127 if (plun->lun_mpxio == 0) { 13128 cdip = DIP(cip); 13129 mutex_exit(&plun->lun_mutex); 13130 mutex_exit(&pptr->port_mutex); 13131 13132 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13133 fcp_trace, FCP_BUF_LEVEL_3, 0, 13134 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13135 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13136 13137 /* 13138 * We could check for FCP_LUN_INIT here but chances 13139 * of getting here when it's already in FCP_LUN_INIT 13140 * is rare and a duplicate ndi_devi_online wouldn't 13141 * hurt either (as the node would already have been 13142 * in CF2) 13143 */ 13144 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13145 rval = ndi_devi_bind_driver(cdip, flags); 13146 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13147 fcp_trace, FCP_BUF_LEVEL_3, 0, 13148 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13149 } else { 13150 rval = ndi_devi_online(cdip, flags); 13151 } 13152 13153 /* 13154 * We log the message into trace buffer if the device 13155 * is "ses" and into syslog for any other device 13156 * type. This is to prevent the ndi_devi_online failure 13157 * message that appears for V880/A5K ses devices. 13158 */ 13159 if (rval == NDI_SUCCESS) { 13160 mutex_enter(&ptgt->tgt_mutex); 13161 plun->lun_state |= FCP_LUN_INIT; 13162 mutex_exit(&ptgt->tgt_mutex); 13163 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13164 fcp_log(CE_NOTE, pptr->port_dip, 13165 "!ndi_devi_online:" 13166 " failed for %s: target=%x lun=%x %x", 13167 ddi_get_name(cdip), ptgt->tgt_d_id, 13168 plun->lun_num, rval); 13169 } else { 13170 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13171 fcp_trace, FCP_BUF_LEVEL_3, 0, 13172 " !ndi_devi_online:" 13173 " failed for %s: target=%x lun=%x %x", 13174 ddi_get_name(cdip), ptgt->tgt_d_id, 13175 plun->lun_num, rval); 13176 } 13177 } else { 13178 cdip = mdi_pi_get_client(PIP(cip)); 13179 mutex_exit(&plun->lun_mutex); 13180 mutex_exit(&pptr->port_mutex); 13181 13182 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13183 fcp_trace, FCP_BUF_LEVEL_3, 0, 13184 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13185 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13186 13187 /* 13188 * Hold path and exit phci to avoid deadlock with power 13189 * management code during mdi_pi_online. 13190 */ 13191 mdi_hold_path(PIP(cip)); 13192 mdi_devi_exit_phci(pptr->port_dip, *circ); 13193 13194 rval = mdi_pi_online(PIP(cip), flags); 13195 13196 mdi_devi_enter_phci(pptr->port_dip, circ); 13197 mdi_rele_path(PIP(cip)); 13198 13199 if (rval == MDI_SUCCESS) { 13200 mutex_enter(&ptgt->tgt_mutex); 13201 plun->lun_state |= FCP_LUN_INIT; 13202 mutex_exit(&ptgt->tgt_mutex); 13203 13204 /* 13205 * Clear MPxIO path permanent disable in case 13206 * fcp hotplug dropped the offline event. 13207 */ 13208 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13209 13210 } else if (rval == MDI_NOT_SUPPORTED) { 13211 child_info_t *old_cip = cip; 13212 13213 /* 13214 * MPxIO does not support this device yet. 13215 * Enumerate in legacy mode. 13216 */ 13217 mutex_enter(&pptr->port_mutex); 13218 mutex_enter(&plun->lun_mutex); 13219 plun->lun_mpxio = 0; 13220 plun->lun_cip = NULL; 13221 cdip = fcp_create_dip(plun, lcount, tcount); 13222 plun->lun_cip = cip = CIP(cdip); 13223 if (cip == NULL) { 13224 fcp_log(CE_WARN, pptr->port_dip, 13225 "!fcp_online_child: " 13226 "Create devinfo failed for LU=%p", plun); 13227 mutex_exit(&plun->lun_mutex); 13228 13229 mutex_enter(&ptgt->tgt_mutex); 13230 plun->lun_state |= FCP_LUN_OFFLINE; 13231 mutex_exit(&ptgt->tgt_mutex); 13232 13233 mutex_exit(&pptr->port_mutex); 13234 13235 /* 13236 * free the mdi_pathinfo node 13237 */ 13238 (void) mdi_pi_free(PIP(old_cip), 0); 13239 } else { 13240 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13241 fcp_trace, FCP_BUF_LEVEL_3, 0, 13242 "fcp_online_child: creating devinfo " 13243 "node 0x%p for plun 0x%p", 13244 cip, plun); 13245 mutex_exit(&plun->lun_mutex); 13246 mutex_exit(&pptr->port_mutex); 13247 /* 13248 * free the mdi_pathinfo node 13249 */ 13250 (void) mdi_pi_free(PIP(old_cip), 0); 13251 mutex_enter(&pptr->port_mutex); 13252 mutex_enter(&plun->lun_mutex); 13253 goto again; 13254 } 13255 } else { 13256 if (cdip) { 13257 fcp_log(CE_NOTE, pptr->port_dip, 13258 "!fcp_online_child: mdi_pi_online:" 13259 " failed for %s: target=%x lun=%x %x", 13260 ddi_get_name(cdip), ptgt->tgt_d_id, 13261 plun->lun_num, rval); 13262 } 13263 } 13264 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13265 } 13266 13267 if (rval == NDI_SUCCESS) { 13268 if (cdip) { 13269 (void) ndi_event_retrieve_cookie( 13270 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13271 &fcp_insert_eid, NDI_EVENT_NOPASS); 13272 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13273 cdip, fcp_insert_eid, NULL); 13274 } 13275 } 13276 mutex_enter(&pptr->port_mutex); 13277 mutex_enter(&plun->lun_mutex); 13278 return (rval); 13279 } 13280 13281 /* ARGSUSED */ 13282 static int 13283 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13284 int tcount, int flags, int *circ) 13285 { 13286 int rval; 13287 int lun_mpxio; 13288 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13289 struct fcp_tgt *ptgt = plun->lun_tgt; 13290 dev_info_t *cdip; 13291 13292 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13293 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13294 13295 if (plun->lun_cip == NULL) { 13296 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13297 fcp_trace, FCP_BUF_LEVEL_3, 0, 13298 "fcp_offline_child: plun->lun_cip is NULL: " 13299 "plun: %p lun state: %x num: %d target state: %x", 13300 plun, plun->lun_state, plun->lun_num, 13301 plun->lun_tgt->tgt_port->port_state); 13302 return (NDI_FAILURE); 13303 } 13304 13305 /* 13306 * We will use this value twice. Make a copy to be sure we use 13307 * the same value in both places. 13308 */ 13309 lun_mpxio = plun->lun_mpxio; 13310 13311 if (lun_mpxio == 0) { 13312 cdip = DIP(cip); 13313 mutex_exit(&plun->lun_mutex); 13314 mutex_exit(&pptr->port_mutex); 13315 rval = ndi_devi_offline(DIP(cip), flags); 13316 if (rval != NDI_SUCCESS) { 13317 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13318 fcp_trace, FCP_BUF_LEVEL_3, 0, 13319 "fcp_offline_child: ndi_devi_offline failed " 13320 "rval=%x cip=%p", rval, cip); 13321 } 13322 } else { 13323 cdip = mdi_pi_get_client(PIP(cip)); 13324 mutex_exit(&plun->lun_mutex); 13325 mutex_exit(&pptr->port_mutex); 13326 13327 /* 13328 * Exit phci to avoid deadlock with power management code 13329 * during mdi_pi_offline 13330 */ 13331 mdi_hold_path(PIP(cip)); 13332 mdi_devi_exit_phci(pptr->port_dip, *circ); 13333 13334 rval = mdi_pi_offline(PIP(cip), flags); 13335 13336 mdi_devi_enter_phci(pptr->port_dip, circ); 13337 mdi_rele_path(PIP(cip)); 13338 13339 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13340 } 13341 13342 mutex_enter(&ptgt->tgt_mutex); 13343 plun->lun_state &= ~FCP_LUN_INIT; 13344 mutex_exit(&ptgt->tgt_mutex); 13345 13346 if (rval == NDI_SUCCESS) { 13347 cdip = NULL; 13348 if (flags & NDI_DEVI_REMOVE) { 13349 mutex_enter(&plun->lun_mutex); 13350 /* 13351 * If the guid of the LUN changes, lun_cip will not 13352 * equal to cip, and after offlining the LUN with the 13353 * old guid, we should keep lun_cip since it's the cip 13354 * of the LUN with the new guid. 13355 * Otherwise remove our reference to child node. 13356 * 13357 * This must be done before the child node is freed, 13358 * otherwise other threads could see a stale lun_cip 13359 * pointer. 13360 */ 13361 if (plun->lun_cip == cip) { 13362 plun->lun_cip = NULL; 13363 } 13364 if (plun->lun_old_guid) { 13365 kmem_free(plun->lun_old_guid, 13366 plun->lun_old_guid_size); 13367 plun->lun_old_guid = NULL; 13368 plun->lun_old_guid_size = 0; 13369 } 13370 mutex_exit(&plun->lun_mutex); 13371 } 13372 } 13373 13374 if (lun_mpxio != 0) { 13375 if (rval == NDI_SUCCESS) { 13376 /* 13377 * Clear MPxIO path permanent disable as the path is 13378 * already offlined. 13379 */ 13380 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13381 13382 if (flags & NDI_DEVI_REMOVE) { 13383 (void) mdi_pi_free(PIP(cip), 0); 13384 } 13385 } else { 13386 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13387 fcp_trace, FCP_BUF_LEVEL_3, 0, 13388 "fcp_offline_child: mdi_pi_offline failed " 13389 "rval=%x cip=%p", rval, cip); 13390 } 13391 } 13392 13393 mutex_enter(&pptr->port_mutex); 13394 mutex_enter(&plun->lun_mutex); 13395 13396 if (cdip) { 13397 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13398 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13399 " target=%x lun=%x", "ndi_offline", 13400 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13401 } 13402 13403 return (rval); 13404 } 13405 13406 static void 13407 fcp_remove_child(struct fcp_lun *plun) 13408 { 13409 child_info_t *cip; 13410 int circ; 13411 13412 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13413 13414 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13415 if (plun->lun_mpxio == 0) { 13416 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13417 (void) ndi_devi_free(DIP(plun->lun_cip)); 13418 plun->lun_cip = NULL; 13419 } else { 13420 /* 13421 * Clear reference to the child node in the lun. 13422 * This must be done before freeing it with mdi_pi_free 13423 * and with lun_mutex held so that other threads always 13424 * see either valid lun_cip or NULL when holding 13425 * lun_mutex. We keep a copy in cip. 13426 */ 13427 cip = plun->lun_cip; 13428 plun->lun_cip = NULL; 13429 13430 mutex_exit(&plun->lun_mutex); 13431 mutex_exit(&plun->lun_tgt->tgt_mutex); 13432 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13433 13434 mdi_devi_enter( 13435 plun->lun_tgt->tgt_port->port_dip, &circ); 13436 13437 /* 13438 * Exit phci to avoid deadlock with power management 13439 * code during mdi_pi_offline 13440 */ 13441 mdi_hold_path(PIP(cip)); 13442 mdi_devi_exit_phci( 13443 plun->lun_tgt->tgt_port->port_dip, circ); 13444 (void) mdi_pi_offline(PIP(cip), 13445 NDI_DEVI_REMOVE); 13446 mdi_devi_enter_phci( 13447 plun->lun_tgt->tgt_port->port_dip, &circ); 13448 mdi_rele_path(PIP(cip)); 13449 13450 mdi_devi_exit( 13451 plun->lun_tgt->tgt_port->port_dip, circ); 13452 13453 FCP_TRACE(fcp_logq, 13454 plun->lun_tgt->tgt_port->port_instbuf, 13455 fcp_trace, FCP_BUF_LEVEL_3, 0, 13456 "lun=%p pip freed %p", plun, cip); 13457 13458 (void) mdi_prop_remove(PIP(cip), NULL); 13459 (void) mdi_pi_free(PIP(cip), 0); 13460 13461 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13462 mutex_enter(&plun->lun_tgt->tgt_mutex); 13463 mutex_enter(&plun->lun_mutex); 13464 } 13465 } else { 13466 plun->lun_cip = NULL; 13467 } 13468 } 13469 13470 /* 13471 * called when a timeout occurs 13472 * 13473 * can be scheduled during an attach or resume (if not already running) 13474 * 13475 * one timeout is set up for all ports 13476 * 13477 * acquires and releases the global mutex 13478 */ 13479 /*ARGSUSED*/ 13480 static void 13481 fcp_watch(void *arg) 13482 { 13483 struct fcp_port *pptr; 13484 struct fcp_ipkt *icmd; 13485 struct fcp_ipkt *nicmd; 13486 struct fcp_pkt *cmd; 13487 struct fcp_pkt *ncmd; 13488 struct fcp_pkt *tail; 13489 struct fcp_pkt *pcmd; 13490 struct fcp_pkt *save_head; 13491 struct fcp_port *save_port; 13492 13493 /* increment global watchdog time */ 13494 fcp_watchdog_time += fcp_watchdog_timeout; 13495 13496 mutex_enter(&fcp_global_mutex); 13497 13498 /* scan each port in our list */ 13499 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13500 save_port = fcp_port_head; 13501 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13502 mutex_exit(&fcp_global_mutex); 13503 13504 mutex_enter(&pptr->port_mutex); 13505 if (pptr->port_ipkt_list == NULL && 13506 (pptr->port_state & (FCP_STATE_SUSPENDED | 13507 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13508 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13509 mutex_exit(&pptr->port_mutex); 13510 mutex_enter(&fcp_global_mutex); 13511 goto end_of_watchdog; 13512 } 13513 13514 /* 13515 * We check if a list of targets need to be offlined. 13516 */ 13517 if (pptr->port_offline_tgts) { 13518 fcp_scan_offline_tgts(pptr); 13519 } 13520 13521 /* 13522 * We check if a list of luns need to be offlined. 13523 */ 13524 if (pptr->port_offline_luns) { 13525 fcp_scan_offline_luns(pptr); 13526 } 13527 13528 /* 13529 * We check if a list of targets or luns need to be reset. 13530 */ 13531 if (pptr->port_reset_list) { 13532 fcp_check_reset_delay(pptr); 13533 } 13534 13535 mutex_exit(&pptr->port_mutex); 13536 13537 /* 13538 * This is where the pending commands (pkt) are checked for 13539 * timeout. 13540 */ 13541 mutex_enter(&pptr->port_pkt_mutex); 13542 tail = pptr->port_pkt_tail; 13543 13544 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13545 cmd != NULL; cmd = ncmd) { 13546 ncmd = cmd->cmd_next; 13547 /* 13548 * If a command is in this queue the bit CFLAG_IN_QUEUE 13549 * must be set. 13550 */ 13551 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13552 /* 13553 * FCP_INVALID_TIMEOUT will be set for those 13554 * command that need to be failed. Mostly those 13555 * cmds that could not be queued down for the 13556 * "timeout" value. cmd->cmd_timeout is used 13557 * to try and requeue the command regularly. 13558 */ 13559 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13560 /* 13561 * This command hasn't timed out yet. Let's 13562 * go to the next one. 13563 */ 13564 pcmd = cmd; 13565 goto end_of_loop; 13566 } 13567 13568 if (cmd == pptr->port_pkt_head) { 13569 ASSERT(pcmd == NULL); 13570 pptr->port_pkt_head = cmd->cmd_next; 13571 } else { 13572 ASSERT(pcmd != NULL); 13573 pcmd->cmd_next = cmd->cmd_next; 13574 } 13575 13576 if (cmd == pptr->port_pkt_tail) { 13577 ASSERT(cmd->cmd_next == NULL); 13578 pptr->port_pkt_tail = pcmd; 13579 if (pcmd) { 13580 pcmd->cmd_next = NULL; 13581 } 13582 } 13583 cmd->cmd_next = NULL; 13584 13585 /* 13586 * save the current head before dropping the 13587 * mutex - If the head doesn't remain the 13588 * same after re acquiring the mutex, just 13589 * bail out and revisit on next tick. 13590 * 13591 * PS: The tail pointer can change as the commands 13592 * get requeued after failure to retransport 13593 */ 13594 save_head = pptr->port_pkt_head; 13595 mutex_exit(&pptr->port_pkt_mutex); 13596 13597 if (cmd->cmd_fp_pkt->pkt_timeout == 13598 FCP_INVALID_TIMEOUT) { 13599 struct scsi_pkt *pkt = cmd->cmd_pkt; 13600 struct fcp_lun *plun; 13601 struct fcp_tgt *ptgt; 13602 13603 plun = ADDR2LUN(&pkt->pkt_address); 13604 ptgt = plun->lun_tgt; 13605 13606 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13607 fcp_trace, FCP_BUF_LEVEL_2, 0, 13608 "SCSI cmd 0x%x to D_ID=%x timed out", 13609 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13610 13611 cmd->cmd_state == FCP_PKT_ABORTING ? 13612 fcp_fail_cmd(cmd, CMD_RESET, 13613 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13614 CMD_TIMEOUT, STAT_ABORTED); 13615 } else { 13616 fcp_retransport_cmd(pptr, cmd); 13617 } 13618 mutex_enter(&pptr->port_pkt_mutex); 13619 if (save_head && save_head != pptr->port_pkt_head) { 13620 /* 13621 * Looks like linked list got changed (mostly 13622 * happens when an an OFFLINE LUN code starts 13623 * returning overflow queue commands in 13624 * parallel. So bail out and revisit during 13625 * next tick 13626 */ 13627 break; 13628 } 13629 end_of_loop: 13630 /* 13631 * Scan only upto the previously known tail pointer 13632 * to avoid excessive processing - lots of new packets 13633 * could have been added to the tail or the old ones 13634 * re-queued. 13635 */ 13636 if (cmd == tail) { 13637 break; 13638 } 13639 } 13640 mutex_exit(&pptr->port_pkt_mutex); 13641 13642 mutex_enter(&pptr->port_mutex); 13643 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13644 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13645 13646 nicmd = icmd->ipkt_next; 13647 if ((icmd->ipkt_restart != 0) && 13648 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13649 /* packet has not timed out */ 13650 continue; 13651 } 13652 13653 /* time for packet re-transport */ 13654 if (icmd == pptr->port_ipkt_list) { 13655 pptr->port_ipkt_list = icmd->ipkt_next; 13656 if (pptr->port_ipkt_list) { 13657 pptr->port_ipkt_list->ipkt_prev = 13658 NULL; 13659 } 13660 } else { 13661 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13662 if (icmd->ipkt_next) { 13663 icmd->ipkt_next->ipkt_prev = 13664 icmd->ipkt_prev; 13665 } 13666 } 13667 icmd->ipkt_next = NULL; 13668 icmd->ipkt_prev = NULL; 13669 mutex_exit(&pptr->port_mutex); 13670 13671 if (fcp_is_retryable(icmd)) { 13672 fc_ulp_rscn_info_t *rscnp = 13673 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13674 pkt_ulp_rscn_infop; 13675 13676 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13677 fcp_trace, FCP_BUF_LEVEL_2, 0, 13678 "%x to D_ID=%x Retrying..", 13679 icmd->ipkt_opcode, 13680 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13681 13682 /* 13683 * Update the RSCN count in the packet 13684 * before resending. 13685 */ 13686 13687 if (rscnp != NULL) { 13688 rscnp->ulp_rscn_count = 13689 fc_ulp_get_rscn_count(pptr-> 13690 port_fp_handle); 13691 } 13692 13693 mutex_enter(&pptr->port_mutex); 13694 mutex_enter(&ptgt->tgt_mutex); 13695 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13696 mutex_exit(&ptgt->tgt_mutex); 13697 mutex_exit(&pptr->port_mutex); 13698 switch (icmd->ipkt_opcode) { 13699 int rval; 13700 case LA_ELS_PLOGI: 13701 if ((rval = fc_ulp_login( 13702 pptr->port_fp_handle, 13703 &icmd->ipkt_fpkt, 1)) == 13704 FC_SUCCESS) { 13705 mutex_enter( 13706 &pptr->port_mutex); 13707 continue; 13708 } 13709 if (fcp_handle_ipkt_errors( 13710 pptr, ptgt, icmd, rval, 13711 "PLOGI") == DDI_SUCCESS) { 13712 mutex_enter( 13713 &pptr->port_mutex); 13714 continue; 13715 } 13716 break; 13717 13718 case LA_ELS_PRLI: 13719 if ((rval = fc_ulp_issue_els( 13720 pptr->port_fp_handle, 13721 icmd->ipkt_fpkt)) == 13722 FC_SUCCESS) { 13723 mutex_enter( 13724 &pptr->port_mutex); 13725 continue; 13726 } 13727 if (fcp_handle_ipkt_errors( 13728 pptr, ptgt, icmd, rval, 13729 "PRLI") == DDI_SUCCESS) { 13730 mutex_enter( 13731 &pptr->port_mutex); 13732 continue; 13733 } 13734 break; 13735 13736 default: 13737 if ((rval = fcp_transport( 13738 pptr->port_fp_handle, 13739 icmd->ipkt_fpkt, 1)) == 13740 FC_SUCCESS) { 13741 mutex_enter( 13742 &pptr->port_mutex); 13743 continue; 13744 } 13745 if (fcp_handle_ipkt_errors( 13746 pptr, ptgt, icmd, rval, 13747 "PRLI") == DDI_SUCCESS) { 13748 mutex_enter( 13749 &pptr->port_mutex); 13750 continue; 13751 } 13752 break; 13753 } 13754 } else { 13755 mutex_exit(&ptgt->tgt_mutex); 13756 mutex_exit(&pptr->port_mutex); 13757 } 13758 } else { 13759 fcp_print_error(icmd->ipkt_fpkt); 13760 } 13761 13762 (void) fcp_call_finish_init(pptr, ptgt, 13763 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13764 icmd->ipkt_cause); 13765 fcp_icmd_free(pptr, icmd); 13766 mutex_enter(&pptr->port_mutex); 13767 } 13768 13769 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13770 mutex_exit(&pptr->port_mutex); 13771 mutex_enter(&fcp_global_mutex); 13772 13773 end_of_watchdog: 13774 /* 13775 * Bail out early before getting into trouble 13776 */ 13777 if (save_port != fcp_port_head) { 13778 break; 13779 } 13780 } 13781 13782 if (fcp_watchdog_init > 0) { 13783 /* reschedule timeout to go again */ 13784 fcp_watchdog_id = 13785 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13786 } 13787 mutex_exit(&fcp_global_mutex); 13788 } 13789 13790 13791 static void 13792 fcp_check_reset_delay(struct fcp_port *pptr) 13793 { 13794 uint32_t tgt_cnt; 13795 int level; 13796 struct fcp_tgt *ptgt; 13797 struct fcp_lun *plun; 13798 struct fcp_reset_elem *cur = NULL; 13799 struct fcp_reset_elem *next = NULL; 13800 struct fcp_reset_elem *prev = NULL; 13801 13802 ASSERT(mutex_owned(&pptr->port_mutex)); 13803 13804 next = pptr->port_reset_list; 13805 while ((cur = next) != NULL) { 13806 next = cur->next; 13807 13808 if (cur->timeout < fcp_watchdog_time) { 13809 prev = cur; 13810 continue; 13811 } 13812 13813 ptgt = cur->tgt; 13814 plun = cur->lun; 13815 tgt_cnt = cur->tgt_cnt; 13816 13817 if (ptgt) { 13818 level = RESET_TARGET; 13819 } else { 13820 ASSERT(plun != NULL); 13821 level = RESET_LUN; 13822 ptgt = plun->lun_tgt; 13823 } 13824 if (prev) { 13825 prev->next = next; 13826 } else { 13827 /* 13828 * Because we drop port mutex while doing aborts for 13829 * packets, we can't rely on reset_list pointing to 13830 * our head 13831 */ 13832 if (cur == pptr->port_reset_list) { 13833 pptr->port_reset_list = next; 13834 } else { 13835 struct fcp_reset_elem *which; 13836 13837 which = pptr->port_reset_list; 13838 while (which && which->next != cur) { 13839 which = which->next; 13840 } 13841 ASSERT(which != NULL); 13842 13843 which->next = next; 13844 prev = which; 13845 } 13846 } 13847 13848 kmem_free(cur, sizeof (*cur)); 13849 13850 if (tgt_cnt == ptgt->tgt_change_cnt) { 13851 mutex_enter(&ptgt->tgt_mutex); 13852 if (level == RESET_TARGET) { 13853 fcp_update_tgt_state(ptgt, 13854 FCP_RESET, FCP_LUN_BUSY); 13855 } else { 13856 fcp_update_lun_state(plun, 13857 FCP_RESET, FCP_LUN_BUSY); 13858 } 13859 mutex_exit(&ptgt->tgt_mutex); 13860 13861 mutex_exit(&pptr->port_mutex); 13862 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13863 mutex_enter(&pptr->port_mutex); 13864 } 13865 } 13866 } 13867 13868 13869 static void 13870 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13871 struct fcp_lun *rlun, int tgt_cnt) 13872 { 13873 int rval; 13874 struct fcp_lun *tlun, *nlun; 13875 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13876 *cmd = NULL, *head = NULL, 13877 *tail = NULL; 13878 13879 mutex_enter(&pptr->port_pkt_mutex); 13880 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13881 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13882 struct fcp_tgt *ptgt = plun->lun_tgt; 13883 13884 ncmd = cmd->cmd_next; 13885 13886 if (ptgt != ttgt && plun != rlun) { 13887 pcmd = cmd; 13888 continue; 13889 } 13890 13891 if (pcmd != NULL) { 13892 ASSERT(pptr->port_pkt_head != cmd); 13893 pcmd->cmd_next = ncmd; 13894 } else { 13895 ASSERT(cmd == pptr->port_pkt_head); 13896 pptr->port_pkt_head = ncmd; 13897 } 13898 if (pptr->port_pkt_tail == cmd) { 13899 ASSERT(cmd->cmd_next == NULL); 13900 pptr->port_pkt_tail = pcmd; 13901 if (pcmd != NULL) { 13902 pcmd->cmd_next = NULL; 13903 } 13904 } 13905 13906 if (head == NULL) { 13907 head = tail = cmd; 13908 } else { 13909 ASSERT(tail != NULL); 13910 tail->cmd_next = cmd; 13911 tail = cmd; 13912 } 13913 cmd->cmd_next = NULL; 13914 } 13915 mutex_exit(&pptr->port_pkt_mutex); 13916 13917 for (cmd = head; cmd != NULL; cmd = ncmd) { 13918 struct scsi_pkt *pkt = cmd->cmd_pkt; 13919 13920 ncmd = cmd->cmd_next; 13921 ASSERT(pkt != NULL); 13922 13923 mutex_enter(&pptr->port_mutex); 13924 if (ttgt->tgt_change_cnt == tgt_cnt) { 13925 mutex_exit(&pptr->port_mutex); 13926 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13927 pkt->pkt_reason = CMD_RESET; 13928 pkt->pkt_statistics |= STAT_DEV_RESET; 13929 cmd->cmd_state = FCP_PKT_IDLE; 13930 fcp_post_callback(cmd); 13931 } else { 13932 mutex_exit(&pptr->port_mutex); 13933 } 13934 } 13935 13936 /* 13937 * If the FCA will return all the commands in its queue then our 13938 * work is easy, just return. 13939 */ 13940 13941 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13942 return; 13943 } 13944 13945 /* 13946 * For RESET_LUN get hold of target pointer 13947 */ 13948 if (ttgt == NULL) { 13949 ASSERT(rlun != NULL); 13950 13951 ttgt = rlun->lun_tgt; 13952 13953 ASSERT(ttgt != NULL); 13954 } 13955 13956 /* 13957 * There are some severe race conditions here. 13958 * While we are trying to abort the pkt, it might be completing 13959 * so mark it aborted and if the abort does not succeed then 13960 * handle it in the watch thread. 13961 */ 13962 mutex_enter(&ttgt->tgt_mutex); 13963 nlun = ttgt->tgt_lun; 13964 mutex_exit(&ttgt->tgt_mutex); 13965 while ((tlun = nlun) != NULL) { 13966 int restart = 0; 13967 if (rlun && rlun != tlun) { 13968 mutex_enter(&ttgt->tgt_mutex); 13969 nlun = tlun->lun_next; 13970 mutex_exit(&ttgt->tgt_mutex); 13971 continue; 13972 } 13973 mutex_enter(&tlun->lun_mutex); 13974 cmd = tlun->lun_pkt_head; 13975 while (cmd != NULL) { 13976 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13977 struct scsi_pkt *pkt; 13978 13979 restart = 1; 13980 cmd->cmd_state = FCP_PKT_ABORTING; 13981 mutex_exit(&tlun->lun_mutex); 13982 rval = fc_ulp_abort(pptr->port_fp_handle, 13983 cmd->cmd_fp_pkt, KM_SLEEP); 13984 if (rval == FC_SUCCESS) { 13985 pkt = cmd->cmd_pkt; 13986 pkt->pkt_reason = CMD_RESET; 13987 pkt->pkt_statistics |= STAT_DEV_RESET; 13988 cmd->cmd_state = FCP_PKT_IDLE; 13989 fcp_post_callback(cmd); 13990 } else { 13991 caddr_t msg; 13992 13993 (void) fc_ulp_error(rval, &msg); 13994 13995 /* 13996 * This part is tricky. The abort 13997 * failed and now the command could 13998 * be completing. The cmd_state == 13999 * FCP_PKT_ABORTING should save 14000 * us in fcp_cmd_callback. If we 14001 * are already aborting ignore the 14002 * command in fcp_cmd_callback. 14003 * Here we leave this packet for 20 14004 * sec to be aborted in the 14005 * fcp_watch thread. 14006 */ 14007 fcp_log(CE_WARN, pptr->port_dip, 14008 "!Abort failed after reset %s", 14009 msg); 14010 14011 cmd->cmd_timeout = 14012 fcp_watchdog_time + 14013 cmd->cmd_pkt->pkt_time + 14014 FCP_FAILED_DELAY; 14015 14016 cmd->cmd_fp_pkt->pkt_timeout = 14017 FCP_INVALID_TIMEOUT; 14018 /* 14019 * This is a hack, cmd is put in the 14020 * overflow queue so that it can be 14021 * timed out finally 14022 */ 14023 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14024 14025 mutex_enter(&pptr->port_pkt_mutex); 14026 if (pptr->port_pkt_head) { 14027 ASSERT(pptr->port_pkt_tail 14028 != NULL); 14029 pptr->port_pkt_tail->cmd_next 14030 = cmd; 14031 pptr->port_pkt_tail = cmd; 14032 } else { 14033 ASSERT(pptr->port_pkt_tail 14034 == NULL); 14035 pptr->port_pkt_head = 14036 pptr->port_pkt_tail 14037 = cmd; 14038 } 14039 cmd->cmd_next = NULL; 14040 mutex_exit(&pptr->port_pkt_mutex); 14041 } 14042 mutex_enter(&tlun->lun_mutex); 14043 cmd = tlun->lun_pkt_head; 14044 } else { 14045 cmd = cmd->cmd_forw; 14046 } 14047 } 14048 mutex_exit(&tlun->lun_mutex); 14049 14050 mutex_enter(&ttgt->tgt_mutex); 14051 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14052 mutex_exit(&ttgt->tgt_mutex); 14053 14054 mutex_enter(&pptr->port_mutex); 14055 if (tgt_cnt != ttgt->tgt_change_cnt) { 14056 mutex_exit(&pptr->port_mutex); 14057 return; 14058 } else { 14059 mutex_exit(&pptr->port_mutex); 14060 } 14061 } 14062 } 14063 14064 14065 /* 14066 * unlink the soft state, returning the soft state found (if any) 14067 * 14068 * acquires and releases the global mutex 14069 */ 14070 struct fcp_port * 14071 fcp_soft_state_unlink(struct fcp_port *pptr) 14072 { 14073 struct fcp_port *hptr; /* ptr index */ 14074 struct fcp_port *tptr; /* prev hptr */ 14075 14076 mutex_enter(&fcp_global_mutex); 14077 for (hptr = fcp_port_head, tptr = NULL; 14078 hptr != NULL; 14079 tptr = hptr, hptr = hptr->port_next) { 14080 if (hptr == pptr) { 14081 /* we found a match -- remove this item */ 14082 if (tptr == NULL) { 14083 /* we're at the head of the list */ 14084 fcp_port_head = hptr->port_next; 14085 } else { 14086 tptr->port_next = hptr->port_next; 14087 } 14088 break; /* success */ 14089 } 14090 } 14091 if (fcp_port_head == NULL) { 14092 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14093 } 14094 mutex_exit(&fcp_global_mutex); 14095 return (hptr); 14096 } 14097 14098 14099 /* 14100 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14101 * WWN and a LUN number 14102 */ 14103 /* ARGSUSED */ 14104 static struct fcp_lun * 14105 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14106 { 14107 int hash; 14108 struct fcp_tgt *ptgt; 14109 struct fcp_lun *plun; 14110 14111 ASSERT(mutex_owned(&pptr->port_mutex)); 14112 14113 hash = FCP_HASH(wwn); 14114 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14115 ptgt = ptgt->tgt_next) { 14116 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14117 sizeof (ptgt->tgt_port_wwn)) == 0) { 14118 mutex_enter(&ptgt->tgt_mutex); 14119 for (plun = ptgt->tgt_lun; 14120 plun != NULL; 14121 plun = plun->lun_next) { 14122 if (plun->lun_num == lun) { 14123 mutex_exit(&ptgt->tgt_mutex); 14124 return (plun); 14125 } 14126 } 14127 mutex_exit(&ptgt->tgt_mutex); 14128 return (NULL); 14129 } 14130 } 14131 return (NULL); 14132 } 14133 14134 /* 14135 * Function: fcp_prepare_pkt 14136 * 14137 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14138 * for fcp_start(). It binds the data or partially maps it. 14139 * Builds the FCP header and starts the initialization of the 14140 * Fibre Channel header. 14141 * 14142 * Argument: *pptr FCP port. 14143 * *cmd FCP packet. 14144 * *plun LUN the command will be sent to. 14145 * 14146 * Context: User, Kernel and Interrupt context. 14147 */ 14148 static void 14149 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14150 struct fcp_lun *plun) 14151 { 14152 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14153 struct fcp_tgt *ptgt = plun->lun_tgt; 14154 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14155 14156 ASSERT(cmd->cmd_pkt->pkt_comp || 14157 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14158 14159 if (cmd->cmd_pkt->pkt_numcookies) { 14160 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14161 fcmd->fcp_cntl.cntl_read_data = 1; 14162 fcmd->fcp_cntl.cntl_write_data = 0; 14163 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14164 } else { 14165 fcmd->fcp_cntl.cntl_read_data = 0; 14166 fcmd->fcp_cntl.cntl_write_data = 1; 14167 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14168 } 14169 14170 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14171 14172 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14173 ASSERT(fpkt->pkt_data_cookie_cnt <= 14174 pptr->port_data_dma_attr.dma_attr_sgllen); 14175 14176 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14177 14178 /* FCA needs pkt_datalen to be set */ 14179 fpkt->pkt_datalen = cmd->cmd_dmacount; 14180 fcmd->fcp_data_len = cmd->cmd_dmacount; 14181 } else { 14182 fcmd->fcp_cntl.cntl_read_data = 0; 14183 fcmd->fcp_cntl.cntl_write_data = 0; 14184 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14185 fpkt->pkt_datalen = 0; 14186 fcmd->fcp_data_len = 0; 14187 } 14188 14189 /* set up the Tagged Queuing type */ 14190 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14191 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14192 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14193 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14194 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14195 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14196 } else { 14197 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14198 } 14199 14200 fcmd->fcp_ent_addr = plun->lun_addr; 14201 14202 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14203 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14204 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14205 } else { 14206 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14207 } 14208 14209 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14210 cmd->cmd_pkt->pkt_state = 0; 14211 cmd->cmd_pkt->pkt_statistics = 0; 14212 cmd->cmd_pkt->pkt_resid = 0; 14213 14214 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14215 14216 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14217 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14218 fpkt->pkt_comp = NULL; 14219 } else { 14220 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14221 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14222 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14223 } 14224 fpkt->pkt_comp = fcp_cmd_callback; 14225 } 14226 14227 mutex_enter(&pptr->port_mutex); 14228 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14229 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14230 } 14231 mutex_exit(&pptr->port_mutex); 14232 14233 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14234 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14235 14236 /* 14237 * Save a few kernel cycles here 14238 */ 14239 #ifndef __lock_lint 14240 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14241 #endif /* __lock_lint */ 14242 } 14243 14244 static void 14245 fcp_post_callback(struct fcp_pkt *cmd) 14246 { 14247 scsi_hba_pkt_comp(cmd->cmd_pkt); 14248 } 14249 14250 14251 /* 14252 * called to do polled I/O by fcp_start() 14253 * 14254 * return a transport status value, i.e. TRAN_ACCECPT for success 14255 */ 14256 static int 14257 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14258 { 14259 int rval; 14260 14261 #ifdef DEBUG 14262 mutex_enter(&pptr->port_pkt_mutex); 14263 pptr->port_npkts++; 14264 mutex_exit(&pptr->port_pkt_mutex); 14265 #endif /* DEBUG */ 14266 14267 if (cmd->cmd_fp_pkt->pkt_timeout) { 14268 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14269 } else { 14270 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14271 } 14272 14273 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14274 14275 cmd->cmd_state = FCP_PKT_ISSUED; 14276 14277 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14278 14279 #ifdef DEBUG 14280 mutex_enter(&pptr->port_pkt_mutex); 14281 pptr->port_npkts--; 14282 mutex_exit(&pptr->port_pkt_mutex); 14283 #endif /* DEBUG */ 14284 14285 cmd->cmd_state = FCP_PKT_IDLE; 14286 14287 switch (rval) { 14288 case FC_SUCCESS: 14289 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14290 fcp_complete_pkt(cmd->cmd_fp_pkt); 14291 rval = TRAN_ACCEPT; 14292 } else { 14293 rval = TRAN_FATAL_ERROR; 14294 } 14295 break; 14296 14297 case FC_TRAN_BUSY: 14298 rval = TRAN_BUSY; 14299 cmd->cmd_pkt->pkt_resid = 0; 14300 break; 14301 14302 case FC_BADPACKET: 14303 rval = TRAN_BADPKT; 14304 break; 14305 14306 default: 14307 rval = TRAN_FATAL_ERROR; 14308 break; 14309 } 14310 14311 return (rval); 14312 } 14313 14314 14315 /* 14316 * called by some of the following transport-called routines to convert 14317 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14318 */ 14319 static struct fcp_port * 14320 fcp_dip2port(dev_info_t *dip) 14321 { 14322 int instance; 14323 14324 instance = ddi_get_instance(dip); 14325 return (ddi_get_soft_state(fcp_softstate, instance)); 14326 } 14327 14328 14329 /* 14330 * called internally to return a LUN given a dip 14331 */ 14332 struct fcp_lun * 14333 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14334 { 14335 struct fcp_tgt *ptgt; 14336 struct fcp_lun *plun; 14337 int i; 14338 14339 14340 ASSERT(mutex_owned(&pptr->port_mutex)); 14341 14342 for (i = 0; i < FCP_NUM_HASH; i++) { 14343 for (ptgt = pptr->port_tgt_hash_table[i]; 14344 ptgt != NULL; 14345 ptgt = ptgt->tgt_next) { 14346 mutex_enter(&ptgt->tgt_mutex); 14347 for (plun = ptgt->tgt_lun; plun != NULL; 14348 plun = plun->lun_next) { 14349 mutex_enter(&plun->lun_mutex); 14350 if (plun->lun_cip == cip) { 14351 mutex_exit(&plun->lun_mutex); 14352 mutex_exit(&ptgt->tgt_mutex); 14353 return (plun); /* match found */ 14354 } 14355 mutex_exit(&plun->lun_mutex); 14356 } 14357 mutex_exit(&ptgt->tgt_mutex); 14358 } 14359 } 14360 return (NULL); /* no LUN found */ 14361 } 14362 14363 /* 14364 * pass an element to the hotplug list, kick the hotplug thread 14365 * and wait for the element to get processed by the hotplug thread. 14366 * on return the element is freed. 14367 * 14368 * return zero success and non-zero on failure 14369 * 14370 * acquires/releases the target mutex 14371 * 14372 */ 14373 static int 14374 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14375 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14376 { 14377 struct fcp_hp_elem *elem; 14378 int rval; 14379 14380 mutex_enter(&plun->lun_tgt->tgt_mutex); 14381 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14382 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14383 mutex_exit(&plun->lun_tgt->tgt_mutex); 14384 fcp_log(CE_CONT, pptr->port_dip, 14385 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14386 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14387 return (NDI_FAILURE); 14388 } 14389 mutex_exit(&plun->lun_tgt->tgt_mutex); 14390 mutex_enter(&elem->mutex); 14391 if (elem->wait) { 14392 while (elem->wait) { 14393 cv_wait(&elem->cv, &elem->mutex); 14394 } 14395 } 14396 rval = (elem->result); 14397 mutex_exit(&elem->mutex); 14398 mutex_destroy(&elem->mutex); 14399 cv_destroy(&elem->cv); 14400 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14401 return (rval); 14402 } 14403 14404 /* 14405 * pass an element to the hotplug list, and then 14406 * kick the hotplug thread 14407 * 14408 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14409 * 14410 * acquires/releases the hotplug mutex 14411 * 14412 * called with the target mutex owned 14413 * 14414 * memory acquired in NOSLEEP mode 14415 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14416 * for the hp daemon to process the request and is responsible for 14417 * freeing the element 14418 */ 14419 static struct fcp_hp_elem * 14420 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14421 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14422 { 14423 struct fcp_hp_elem *elem; 14424 dev_info_t *pdip; 14425 14426 ASSERT(pptr != NULL); 14427 ASSERT(plun != NULL); 14428 ASSERT(plun->lun_tgt != NULL); 14429 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14430 14431 /* create space for a hotplug element */ 14432 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14433 == NULL) { 14434 fcp_log(CE_WARN, NULL, 14435 "!can't allocate memory for hotplug element"); 14436 return (NULL); 14437 } 14438 14439 /* fill in hotplug element */ 14440 elem->port = pptr; 14441 elem->lun = plun; 14442 elem->cip = cip; 14443 elem->old_lun_mpxio = plun->lun_mpxio; 14444 elem->what = what; 14445 elem->flags = flags; 14446 elem->link_cnt = link_cnt; 14447 elem->tgt_cnt = tgt_cnt; 14448 elem->wait = wait; 14449 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14450 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14451 14452 /* schedule the hotplug task */ 14453 pdip = pptr->port_dip; 14454 mutex_enter(&plun->lun_mutex); 14455 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14456 plun->lun_event_count++; 14457 elem->event_cnt = plun->lun_event_count; 14458 } 14459 mutex_exit(&plun->lun_mutex); 14460 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14461 (void *)elem, KM_NOSLEEP) == NULL) { 14462 mutex_enter(&plun->lun_mutex); 14463 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14464 plun->lun_event_count--; 14465 } 14466 mutex_exit(&plun->lun_mutex); 14467 kmem_free(elem, sizeof (*elem)); 14468 return (0); 14469 } 14470 14471 return (elem); 14472 } 14473 14474 14475 static void 14476 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14477 { 14478 int rval; 14479 struct scsi_address *ap; 14480 struct fcp_lun *plun; 14481 struct fcp_tgt *ptgt; 14482 fc_packet_t *fpkt; 14483 14484 ap = &cmd->cmd_pkt->pkt_address; 14485 plun = ADDR2LUN(ap); 14486 ptgt = plun->lun_tgt; 14487 14488 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14489 14490 cmd->cmd_state = FCP_PKT_IDLE; 14491 14492 mutex_enter(&pptr->port_mutex); 14493 mutex_enter(&ptgt->tgt_mutex); 14494 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14495 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14496 fc_ulp_rscn_info_t *rscnp; 14497 14498 cmd->cmd_state = FCP_PKT_ISSUED; 14499 14500 /* 14501 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14502 * originally NULL, hence we try to set it to the pd pointed 14503 * to by the SCSI device we're trying to get to. 14504 */ 14505 14506 fpkt = cmd->cmd_fp_pkt; 14507 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14508 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14509 /* 14510 * We need to notify the transport that we now have a 14511 * reference to the remote port handle. 14512 */ 14513 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14514 } 14515 14516 mutex_exit(&ptgt->tgt_mutex); 14517 mutex_exit(&pptr->port_mutex); 14518 14519 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14520 14521 /* prepare the packet */ 14522 14523 fcp_prepare_pkt(pptr, cmd, plun); 14524 14525 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14526 pkt_ulp_rscn_infop; 14527 14528 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14529 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14530 14531 if (rscnp != NULL) { 14532 rscnp->ulp_rscn_count = 14533 fc_ulp_get_rscn_count(pptr-> 14534 port_fp_handle); 14535 } 14536 14537 rval = fcp_transport(pptr->port_fp_handle, 14538 cmd->cmd_fp_pkt, 0); 14539 14540 if (rval == FC_SUCCESS) { 14541 return; 14542 } 14543 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14544 } else { 14545 mutex_exit(&ptgt->tgt_mutex); 14546 mutex_exit(&pptr->port_mutex); 14547 } 14548 14549 fcp_queue_pkt(pptr, cmd); 14550 } 14551 14552 14553 static void 14554 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14555 { 14556 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14557 14558 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14559 cmd->cmd_state = FCP_PKT_IDLE; 14560 14561 cmd->cmd_pkt->pkt_reason = reason; 14562 cmd->cmd_pkt->pkt_state = 0; 14563 cmd->cmd_pkt->pkt_statistics = statistics; 14564 14565 fcp_post_callback(cmd); 14566 } 14567 14568 /* 14569 * Function: fcp_queue_pkt 14570 * 14571 * Description: This function queues the packet passed by the caller into 14572 * the list of packets of the FCP port. 14573 * 14574 * Argument: *pptr FCP port. 14575 * *cmd FCP packet to queue. 14576 * 14577 * Return Value: None 14578 * 14579 * Context: User, Kernel and Interrupt context. 14580 */ 14581 static void 14582 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14583 { 14584 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14585 14586 mutex_enter(&pptr->port_pkt_mutex); 14587 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14588 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14589 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14590 14591 /* 14592 * zero pkt_time means hang around for ever 14593 */ 14594 if (cmd->cmd_pkt->pkt_time) { 14595 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14596 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14597 } else { 14598 /* 14599 * Indicate the watch thread to fail the 14600 * command by setting it to highest value 14601 */ 14602 cmd->cmd_timeout = fcp_watchdog_time; 14603 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14604 } 14605 } 14606 14607 if (pptr->port_pkt_head) { 14608 ASSERT(pptr->port_pkt_tail != NULL); 14609 14610 pptr->port_pkt_tail->cmd_next = cmd; 14611 pptr->port_pkt_tail = cmd; 14612 } else { 14613 ASSERT(pptr->port_pkt_tail == NULL); 14614 14615 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14616 } 14617 cmd->cmd_next = NULL; 14618 mutex_exit(&pptr->port_pkt_mutex); 14619 } 14620 14621 /* 14622 * Function: fcp_update_targets 14623 * 14624 * Description: This function applies the specified change of state to all 14625 * the targets listed. The operation applied is 'set'. 14626 * 14627 * Argument: *pptr FCP port. 14628 * *dev_list Array of fc_portmap_t structures. 14629 * count Length of dev_list. 14630 * state State bits to update. 14631 * cause Reason for the update. 14632 * 14633 * Return Value: None 14634 * 14635 * Context: User, Kernel and Interrupt context. 14636 * The mutex pptr->port_mutex must be held. 14637 */ 14638 static void 14639 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14640 uint32_t count, uint32_t state, int cause) 14641 { 14642 fc_portmap_t *map_entry; 14643 struct fcp_tgt *ptgt; 14644 14645 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14646 14647 while (count--) { 14648 map_entry = &(dev_list[count]); 14649 ptgt = fcp_lookup_target(pptr, 14650 (uchar_t *)&(map_entry->map_pwwn)); 14651 if (ptgt == NULL) { 14652 continue; 14653 } 14654 14655 mutex_enter(&ptgt->tgt_mutex); 14656 ptgt->tgt_trace = 0; 14657 ptgt->tgt_change_cnt++; 14658 ptgt->tgt_statec_cause = cause; 14659 ptgt->tgt_tmp_cnt = 1; 14660 fcp_update_tgt_state(ptgt, FCP_SET, state); 14661 mutex_exit(&ptgt->tgt_mutex); 14662 } 14663 } 14664 14665 static int 14666 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14667 int lcount, int tcount, int cause) 14668 { 14669 int rval; 14670 14671 mutex_enter(&pptr->port_mutex); 14672 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14673 mutex_exit(&pptr->port_mutex); 14674 14675 return (rval); 14676 } 14677 14678 14679 static int 14680 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14681 int lcount, int tcount, int cause) 14682 { 14683 int finish_init = 0; 14684 int finish_tgt = 0; 14685 int do_finish_init = 0; 14686 int rval = FCP_NO_CHANGE; 14687 14688 if (cause == FCP_CAUSE_LINK_CHANGE || 14689 cause == FCP_CAUSE_LINK_DOWN) { 14690 do_finish_init = 1; 14691 } 14692 14693 if (ptgt != NULL) { 14694 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14695 FCP_BUF_LEVEL_2, 0, 14696 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14697 " cause = %d, d_id = 0x%x, tgt_done = %d", 14698 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14699 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14700 ptgt->tgt_d_id, ptgt->tgt_done); 14701 14702 mutex_enter(&ptgt->tgt_mutex); 14703 14704 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14705 rval = FCP_DEV_CHANGE; 14706 if (do_finish_init && ptgt->tgt_done == 0) { 14707 ptgt->tgt_done++; 14708 finish_init = 1; 14709 } 14710 } else { 14711 if (--ptgt->tgt_tmp_cnt <= 0) { 14712 ptgt->tgt_tmp_cnt = 0; 14713 finish_tgt = 1; 14714 14715 if (do_finish_init) { 14716 finish_init = 1; 14717 } 14718 } 14719 } 14720 mutex_exit(&ptgt->tgt_mutex); 14721 } else { 14722 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14723 FCP_BUF_LEVEL_2, 0, 14724 "Call Finish Init for NO target"); 14725 14726 if (do_finish_init) { 14727 finish_init = 1; 14728 } 14729 } 14730 14731 if (finish_tgt) { 14732 ASSERT(ptgt != NULL); 14733 14734 mutex_enter(&ptgt->tgt_mutex); 14735 #ifdef DEBUG 14736 bzero(ptgt->tgt_tmp_cnt_stack, 14737 sizeof (ptgt->tgt_tmp_cnt_stack)); 14738 14739 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14740 FCP_STACK_DEPTH); 14741 #endif /* DEBUG */ 14742 mutex_exit(&ptgt->tgt_mutex); 14743 14744 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14745 } 14746 14747 if (finish_init && lcount == pptr->port_link_cnt) { 14748 ASSERT(pptr->port_tmp_cnt > 0); 14749 if (--pptr->port_tmp_cnt == 0) { 14750 fcp_finish_init(pptr); 14751 } 14752 } else if (lcount != pptr->port_link_cnt) { 14753 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14754 fcp_trace, FCP_BUF_LEVEL_2, 0, 14755 "fcp_call_finish_init_held,1: state change occured" 14756 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14757 } 14758 14759 return (rval); 14760 } 14761 14762 static void 14763 fcp_reconfigure_luns(void * tgt_handle) 14764 { 14765 uint32_t dev_cnt; 14766 fc_portmap_t *devlist; 14767 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14768 struct fcp_port *pptr = ptgt->tgt_port; 14769 14770 /* 14771 * If the timer that fires this off got canceled too late, the 14772 * target could have been destroyed. 14773 */ 14774 14775 if (ptgt->tgt_tid == NULL) { 14776 return; 14777 } 14778 14779 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14780 if (devlist == NULL) { 14781 fcp_log(CE_WARN, pptr->port_dip, 14782 "!fcp%d: failed to allocate for portmap", 14783 pptr->port_instance); 14784 return; 14785 } 14786 14787 dev_cnt = 1; 14788 devlist->map_pd = ptgt->tgt_pd_handle; 14789 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14790 devlist->map_did.port_id = ptgt->tgt_d_id; 14791 14792 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14793 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14794 14795 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14796 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14797 devlist->map_flags = 0; 14798 14799 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14800 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14801 14802 /* 14803 * Clear the tgt_tid after no more references to 14804 * the fcp_tgt 14805 */ 14806 mutex_enter(&ptgt->tgt_mutex); 14807 ptgt->tgt_tid = NULL; 14808 mutex_exit(&ptgt->tgt_mutex); 14809 14810 kmem_free(devlist, sizeof (*devlist)); 14811 } 14812 14813 14814 static void 14815 fcp_free_targets(struct fcp_port *pptr) 14816 { 14817 int i; 14818 struct fcp_tgt *ptgt; 14819 14820 mutex_enter(&pptr->port_mutex); 14821 for (i = 0; i < FCP_NUM_HASH; i++) { 14822 ptgt = pptr->port_tgt_hash_table[i]; 14823 while (ptgt != NULL) { 14824 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14825 14826 fcp_free_target(ptgt); 14827 ptgt = next_tgt; 14828 } 14829 } 14830 mutex_exit(&pptr->port_mutex); 14831 } 14832 14833 14834 static void 14835 fcp_free_target(struct fcp_tgt *ptgt) 14836 { 14837 struct fcp_lun *plun; 14838 timeout_id_t tid; 14839 14840 mutex_enter(&ptgt->tgt_mutex); 14841 tid = ptgt->tgt_tid; 14842 14843 /* 14844 * Cancel any pending timeouts for this target. 14845 */ 14846 14847 if (tid != NULL) { 14848 /* 14849 * Set tgt_tid to NULL first to avoid a race in the callback. 14850 * If tgt_tid is NULL, the callback will simply return. 14851 */ 14852 ptgt->tgt_tid = NULL; 14853 mutex_exit(&ptgt->tgt_mutex); 14854 (void) untimeout(tid); 14855 mutex_enter(&ptgt->tgt_mutex); 14856 } 14857 14858 plun = ptgt->tgt_lun; 14859 while (plun != NULL) { 14860 struct fcp_lun *next_lun = plun->lun_next; 14861 14862 fcp_dealloc_lun(plun); 14863 plun = next_lun; 14864 } 14865 14866 mutex_exit(&ptgt->tgt_mutex); 14867 fcp_dealloc_tgt(ptgt); 14868 } 14869 14870 /* 14871 * Function: fcp_is_retryable 14872 * 14873 * Description: Indicates if the internal packet is retryable. 14874 * 14875 * Argument: *icmd FCP internal packet. 14876 * 14877 * Return Value: 0 Not retryable 14878 * 1 Retryable 14879 * 14880 * Context: User, Kernel and Interrupt context 14881 */ 14882 static int 14883 fcp_is_retryable(struct fcp_ipkt *icmd) 14884 { 14885 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14886 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14887 return (0); 14888 } 14889 14890 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14891 icmd->ipkt_port->port_deadline) ? 1 : 0); 14892 } 14893 14894 /* 14895 * Function: fcp_create_on_demand 14896 * 14897 * Argument: *pptr FCP port. 14898 * *pwwn Port WWN. 14899 * 14900 * Return Value: 0 Success 14901 * EIO 14902 * ENOMEM 14903 * EBUSY 14904 * EINVAL 14905 * 14906 * Context: User and Kernel context 14907 */ 14908 static int 14909 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14910 { 14911 int wait_ms; 14912 int tcount; 14913 int lcount; 14914 int ret; 14915 int error; 14916 int rval = EIO; 14917 int ntries; 14918 fc_portmap_t *devlist; 14919 opaque_t pd; 14920 struct fcp_lun *plun; 14921 struct fcp_tgt *ptgt; 14922 int old_manual = 0; 14923 14924 /* Allocates the fc_portmap_t structure. */ 14925 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14926 14927 /* 14928 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14929 * in the commented statement below: 14930 * 14931 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14932 * 14933 * Below, the deadline for the discovery process is set. 14934 */ 14935 mutex_enter(&pptr->port_mutex); 14936 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14937 mutex_exit(&pptr->port_mutex); 14938 14939 /* 14940 * We try to find the remote port based on the WWN provided by the 14941 * caller. We actually ask fp/fctl if it has it. 14942 */ 14943 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14944 (la_wwn_t *)pwwn, &error, 1); 14945 14946 if (pd == NULL) { 14947 kmem_free(devlist, sizeof (*devlist)); 14948 return (rval); 14949 } 14950 14951 /* 14952 * The remote port was found. We ask fp/fctl to update our 14953 * fc_portmap_t structure. 14954 */ 14955 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14956 (la_wwn_t *)pwwn, devlist); 14957 if (ret != FC_SUCCESS) { 14958 kmem_free(devlist, sizeof (*devlist)); 14959 return (rval); 14960 } 14961 14962 /* 14963 * The map flag field is set to indicates that the creation is being 14964 * done at the user request (Ioclt probably luxadm or cfgadm). 14965 */ 14966 devlist->map_type = PORT_DEVICE_USER_CREATE; 14967 14968 mutex_enter(&pptr->port_mutex); 14969 14970 /* 14971 * We check to see if fcp already has a target that describes the 14972 * device being created. If not it is created. 14973 */ 14974 ptgt = fcp_lookup_target(pptr, pwwn); 14975 if (ptgt == NULL) { 14976 lcount = pptr->port_link_cnt; 14977 mutex_exit(&pptr->port_mutex); 14978 14979 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14980 if (ptgt == NULL) { 14981 fcp_log(CE_WARN, pptr->port_dip, 14982 "!FC target allocation failed"); 14983 return (ENOMEM); 14984 } 14985 14986 mutex_enter(&pptr->port_mutex); 14987 } 14988 14989 mutex_enter(&ptgt->tgt_mutex); 14990 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14991 ptgt->tgt_tmp_cnt = 1; 14992 ptgt->tgt_device_created = 0; 14993 /* 14994 * If fabric and auto config is set but the target was 14995 * manually unconfigured then reset to the manual_config_only to 14996 * 0 so the device will get configured. 14997 */ 14998 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14999 fcp_enable_auto_configuration && 15000 ptgt->tgt_manual_config_only == 1) { 15001 old_manual = 1; 15002 ptgt->tgt_manual_config_only = 0; 15003 } 15004 mutex_exit(&ptgt->tgt_mutex); 15005 15006 fcp_update_targets(pptr, devlist, 1, 15007 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 15008 15009 lcount = pptr->port_link_cnt; 15010 tcount = ptgt->tgt_change_cnt; 15011 15012 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 15013 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 15014 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15015 fcp_enable_auto_configuration && old_manual) { 15016 mutex_enter(&ptgt->tgt_mutex); 15017 ptgt->tgt_manual_config_only = 1; 15018 mutex_exit(&ptgt->tgt_mutex); 15019 } 15020 15021 if (pptr->port_link_cnt != lcount || 15022 ptgt->tgt_change_cnt != tcount) { 15023 rval = EBUSY; 15024 } 15025 mutex_exit(&pptr->port_mutex); 15026 15027 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15028 FCP_BUF_LEVEL_3, 0, 15029 "fcp_create_on_demand: mapflags ptgt=%x, " 15030 "lcount=%x::port_link_cnt=%x, " 15031 "tcount=%x: tgt_change_cnt=%x, rval=%x", 15032 ptgt, lcount, pptr->port_link_cnt, 15033 tcount, ptgt->tgt_change_cnt, rval); 15034 return (rval); 15035 } 15036 15037 /* 15038 * Due to lack of synchronization mechanisms, we perform 15039 * periodic monitoring of our request; Because requests 15040 * get dropped when another one supercedes (either because 15041 * of a link change or a target change), it is difficult to 15042 * provide a clean synchronization mechanism (such as a 15043 * semaphore or a conditional variable) without exhaustively 15044 * rewriting the mainline discovery code of this driver. 15045 */ 15046 wait_ms = 500; 15047 15048 ntries = fcp_max_target_retries; 15049 15050 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15051 FCP_BUF_LEVEL_3, 0, 15052 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15053 "lcount=%x::port_link_cnt=%x, " 15054 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15055 "tgt_tmp_cnt =%x", 15056 ntries, ptgt, lcount, pptr->port_link_cnt, 15057 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15058 ptgt->tgt_tmp_cnt); 15059 15060 mutex_enter(&ptgt->tgt_mutex); 15061 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15062 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15063 mutex_exit(&ptgt->tgt_mutex); 15064 mutex_exit(&pptr->port_mutex); 15065 15066 delay(drv_usectohz(wait_ms * 1000)); 15067 15068 mutex_enter(&pptr->port_mutex); 15069 mutex_enter(&ptgt->tgt_mutex); 15070 } 15071 15072 15073 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15074 rval = EBUSY; 15075 } else { 15076 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15077 FCP_TGT_NODE_PRESENT) { 15078 rval = 0; 15079 } 15080 } 15081 15082 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15083 FCP_BUF_LEVEL_3, 0, 15084 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15085 "lcount=%x::port_link_cnt=%x, " 15086 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15087 "tgt_tmp_cnt =%x", 15088 ntries, ptgt, lcount, pptr->port_link_cnt, 15089 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15090 ptgt->tgt_tmp_cnt); 15091 15092 if (rval) { 15093 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15094 fcp_enable_auto_configuration && old_manual) { 15095 ptgt->tgt_manual_config_only = 1; 15096 } 15097 mutex_exit(&ptgt->tgt_mutex); 15098 mutex_exit(&pptr->port_mutex); 15099 kmem_free(devlist, sizeof (*devlist)); 15100 15101 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15102 FCP_BUF_LEVEL_3, 0, 15103 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15104 "lcount=%x::port_link_cnt=%x, " 15105 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15106 "tgt_device_created=%x, tgt D_ID=%x", 15107 ntries, ptgt, lcount, pptr->port_link_cnt, 15108 tcount, ptgt->tgt_change_cnt, rval, 15109 ptgt->tgt_device_created, ptgt->tgt_d_id); 15110 return (rval); 15111 } 15112 15113 if ((plun = ptgt->tgt_lun) != NULL) { 15114 tcount = plun->lun_tgt->tgt_change_cnt; 15115 } else { 15116 rval = EINVAL; 15117 } 15118 lcount = pptr->port_link_cnt; 15119 15120 /* 15121 * Configuring the target with no LUNs will fail. We 15122 * should reset the node state so that it is not 15123 * automatically configured when the LUNs are added 15124 * to this target. 15125 */ 15126 if (ptgt->tgt_lun_cnt == 0) { 15127 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15128 } 15129 mutex_exit(&ptgt->tgt_mutex); 15130 mutex_exit(&pptr->port_mutex); 15131 15132 while (plun) { 15133 child_info_t *cip; 15134 15135 mutex_enter(&plun->lun_mutex); 15136 cip = plun->lun_cip; 15137 mutex_exit(&plun->lun_mutex); 15138 15139 mutex_enter(&ptgt->tgt_mutex); 15140 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15141 mutex_exit(&ptgt->tgt_mutex); 15142 15143 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15144 FCP_ONLINE, lcount, tcount, 15145 NDI_ONLINE_ATTACH); 15146 if (rval != NDI_SUCCESS) { 15147 FCP_TRACE(fcp_logq, 15148 pptr->port_instbuf, fcp_trace, 15149 FCP_BUF_LEVEL_3, 0, 15150 "fcp_create_on_demand: " 15151 "pass_to_hp_and_wait failed " 15152 "rval=%x", rval); 15153 rval = EIO; 15154 } else { 15155 mutex_enter(&LUN_TGT->tgt_mutex); 15156 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15157 FCP_LUN_BUSY); 15158 mutex_exit(&LUN_TGT->tgt_mutex); 15159 } 15160 mutex_enter(&ptgt->tgt_mutex); 15161 } 15162 15163 plun = plun->lun_next; 15164 mutex_exit(&ptgt->tgt_mutex); 15165 } 15166 15167 kmem_free(devlist, sizeof (*devlist)); 15168 15169 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15170 fcp_enable_auto_configuration && old_manual) { 15171 mutex_enter(&ptgt->tgt_mutex); 15172 /* if successful then set manual to 0 */ 15173 if (rval == 0) { 15174 ptgt->tgt_manual_config_only = 0; 15175 } else { 15176 /* reset to 1 so the user has to do the config */ 15177 ptgt->tgt_manual_config_only = 1; 15178 } 15179 mutex_exit(&ptgt->tgt_mutex); 15180 } 15181 15182 return (rval); 15183 } 15184 15185 15186 static void 15187 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15188 { 15189 int count; 15190 uchar_t byte; 15191 15192 count = 0; 15193 while (*string) { 15194 byte = FCP_ATOB(*string); string++; 15195 byte = byte << 4 | FCP_ATOB(*string); string++; 15196 bytes[count++] = byte; 15197 15198 if (count >= byte_len) { 15199 break; 15200 } 15201 } 15202 } 15203 15204 static void 15205 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15206 { 15207 int i; 15208 15209 for (i = 0; i < FC_WWN_SIZE; i++) { 15210 (void) sprintf(string + (i * 2), 15211 "%02x", wwn[i]); 15212 } 15213 15214 } 15215 15216 static void 15217 fcp_print_error(fc_packet_t *fpkt) 15218 { 15219 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15220 fpkt->pkt_ulp_private; 15221 struct fcp_port *pptr; 15222 struct fcp_tgt *ptgt; 15223 struct fcp_lun *plun; 15224 caddr_t buf; 15225 int scsi_cmd = 0; 15226 15227 ptgt = icmd->ipkt_tgt; 15228 plun = icmd->ipkt_lun; 15229 pptr = ptgt->tgt_port; 15230 15231 buf = kmem_zalloc(256, KM_NOSLEEP); 15232 if (buf == NULL) { 15233 return; 15234 } 15235 15236 switch (icmd->ipkt_opcode) { 15237 case SCMD_REPORT_LUN: 15238 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15239 " lun=0x%%x failed"); 15240 scsi_cmd++; 15241 break; 15242 15243 case SCMD_INQUIRY_PAGE83: 15244 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15245 " lun=0x%%x failed"); 15246 scsi_cmd++; 15247 break; 15248 15249 case SCMD_INQUIRY: 15250 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15251 " lun=0x%%x failed"); 15252 scsi_cmd++; 15253 break; 15254 15255 case LA_ELS_PLOGI: 15256 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15257 break; 15258 15259 case LA_ELS_PRLI: 15260 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15261 break; 15262 } 15263 15264 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15265 struct fcp_rsp response, *rsp; 15266 uchar_t asc, ascq; 15267 caddr_t sense_key = NULL; 15268 struct fcp_rsp_info fcp_rsp_err, *bep; 15269 15270 if (icmd->ipkt_nodma) { 15271 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15272 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15273 sizeof (struct fcp_rsp)); 15274 } else { 15275 rsp = &response; 15276 bep = &fcp_rsp_err; 15277 15278 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15279 sizeof (struct fcp_rsp)); 15280 15281 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15282 bep, fpkt->pkt_resp_acc, 15283 sizeof (struct fcp_rsp_info)); 15284 } 15285 15286 15287 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15288 (void) sprintf(buf + strlen(buf), 15289 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15290 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15291 " senselen=%%x. Giving up"); 15292 15293 fcp_log(CE_WARN, pptr->port_dip, buf, 15294 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15295 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15296 rsp->fcp_u.fcp_status.reserved_1, 15297 rsp->fcp_response_len, rsp->fcp_sense_len); 15298 15299 kmem_free(buf, 256); 15300 return; 15301 } 15302 15303 if (rsp->fcp_u.fcp_status.rsp_len_set && 15304 bep->rsp_code != FCP_NO_FAILURE) { 15305 (void) sprintf(buf + strlen(buf), 15306 " FCP Response code = 0x%x", bep->rsp_code); 15307 } 15308 15309 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15310 struct scsi_extended_sense sense_info, *sense_ptr; 15311 15312 if (icmd->ipkt_nodma) { 15313 sense_ptr = (struct scsi_extended_sense *) 15314 ((caddr_t)fpkt->pkt_resp + 15315 sizeof (struct fcp_rsp) + 15316 rsp->fcp_response_len); 15317 } else { 15318 sense_ptr = &sense_info; 15319 15320 FCP_CP_IN(fpkt->pkt_resp + 15321 sizeof (struct fcp_rsp) + 15322 rsp->fcp_response_len, &sense_info, 15323 fpkt->pkt_resp_acc, 15324 sizeof (struct scsi_extended_sense)); 15325 } 15326 15327 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15328 NUM_IMPL_SENSE_KEYS) { 15329 sense_key = sense_keys[sense_ptr->es_key]; 15330 } else { 15331 sense_key = "Undefined"; 15332 } 15333 15334 asc = sense_ptr->es_add_code; 15335 ascq = sense_ptr->es_qual_code; 15336 15337 (void) sprintf(buf + strlen(buf), 15338 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15339 " Giving up"); 15340 15341 fcp_log(CE_WARN, pptr->port_dip, buf, 15342 ptgt->tgt_d_id, plun->lun_num, sense_key, 15343 asc, ascq); 15344 } else { 15345 (void) sprintf(buf + strlen(buf), 15346 " : SCSI status=%%x. Giving up"); 15347 15348 fcp_log(CE_WARN, pptr->port_dip, buf, 15349 ptgt->tgt_d_id, plun->lun_num, 15350 rsp->fcp_u.fcp_status.scsi_status); 15351 } 15352 } else { 15353 caddr_t state, reason, action, expln; 15354 15355 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15356 &action, &expln); 15357 15358 (void) sprintf(buf + strlen(buf), ": State:%%s," 15359 " Reason:%%s. Giving up"); 15360 15361 if (scsi_cmd) { 15362 fcp_log(CE_WARN, pptr->port_dip, buf, 15363 ptgt->tgt_d_id, plun->lun_num, state, reason); 15364 } else { 15365 fcp_log(CE_WARN, pptr->port_dip, buf, 15366 ptgt->tgt_d_id, state, reason); 15367 } 15368 } 15369 15370 kmem_free(buf, 256); 15371 } 15372 15373 15374 static int 15375 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15376 struct fcp_ipkt *icmd, int rval, caddr_t op) 15377 { 15378 int ret = DDI_FAILURE; 15379 char *error; 15380 15381 switch (rval) { 15382 case FC_DEVICE_BUSY_NEW_RSCN: 15383 /* 15384 * This means that there was a new RSCN that the transport 15385 * knows about (which the ULP *may* know about too) but the 15386 * pkt that was sent down was related to an older RSCN. So, we 15387 * are just going to reset the retry count and deadline and 15388 * continue to retry. The idea is that transport is currently 15389 * working on the new RSCN and will soon let the ULPs know 15390 * about it and when it does the existing logic will kick in 15391 * where it will change the tcount to indicate that something 15392 * changed on the target. So, rediscovery will start and there 15393 * will not be an infinite retry. 15394 * 15395 * For a full flow of how the RSCN info is transferred back and 15396 * forth, see fp.c 15397 */ 15398 icmd->ipkt_retries = 0; 15399 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15400 FCP_ICMD_DEADLINE; 15401 15402 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15403 FCP_BUF_LEVEL_3, 0, 15404 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15405 rval, ptgt->tgt_d_id); 15406 /* FALLTHROUGH */ 15407 15408 case FC_STATEC_BUSY: 15409 case FC_DEVICE_BUSY: 15410 case FC_PBUSY: 15411 case FC_FBUSY: 15412 case FC_TRAN_BUSY: 15413 case FC_OFFLINE: 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 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15419 fcp_is_retryable(icmd)) { 15420 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15421 ret = DDI_SUCCESS; 15422 } 15423 break; 15424 15425 case FC_LOGINREQ: 15426 /* 15427 * FC_LOGINREQ used to be handled just like all the cases 15428 * above. It has been changed to handled a PRLI that fails 15429 * with FC_LOGINREQ different than other ipkts that fail 15430 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15431 * a simple matter to turn it into a PLOGI instead, so that's 15432 * exactly what we do here. 15433 */ 15434 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15435 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15436 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15437 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15438 } else { 15439 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15440 FCP_BUF_LEVEL_3, 0, 15441 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15442 rval, ptgt->tgt_d_id); 15443 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15444 fcp_is_retryable(icmd)) { 15445 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15446 ret = DDI_SUCCESS; 15447 } 15448 } 15449 break; 15450 15451 default: 15452 mutex_enter(&pptr->port_mutex); 15453 mutex_enter(&ptgt->tgt_mutex); 15454 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15455 mutex_exit(&ptgt->tgt_mutex); 15456 mutex_exit(&pptr->port_mutex); 15457 15458 (void) fc_ulp_error(rval, &error); 15459 fcp_log(CE_WARN, pptr->port_dip, 15460 "!Failed to send %s to D_ID=%x error=%s", 15461 op, ptgt->tgt_d_id, error); 15462 } else { 15463 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15464 fcp_trace, FCP_BUF_LEVEL_2, 0, 15465 "fcp_handle_ipkt_errors,1: state change occured" 15466 " for D_ID=0x%x", ptgt->tgt_d_id); 15467 mutex_exit(&ptgt->tgt_mutex); 15468 mutex_exit(&pptr->port_mutex); 15469 } 15470 break; 15471 } 15472 15473 return (ret); 15474 } 15475 15476 15477 /* 15478 * Check of outstanding commands on any LUN for this target 15479 */ 15480 static int 15481 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15482 { 15483 struct fcp_lun *plun; 15484 struct fcp_pkt *cmd; 15485 15486 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15487 mutex_enter(&plun->lun_mutex); 15488 for (cmd = plun->lun_pkt_head; cmd != NULL; 15489 cmd = cmd->cmd_forw) { 15490 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15491 mutex_exit(&plun->lun_mutex); 15492 return (FC_SUCCESS); 15493 } 15494 } 15495 mutex_exit(&plun->lun_mutex); 15496 } 15497 15498 return (FC_FAILURE); 15499 } 15500 15501 static fc_portmap_t * 15502 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15503 { 15504 int i; 15505 fc_portmap_t *devlist; 15506 fc_portmap_t *devptr = NULL; 15507 struct fcp_tgt *ptgt; 15508 15509 mutex_enter(&pptr->port_mutex); 15510 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15511 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15512 ptgt = ptgt->tgt_next) { 15513 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15514 ++*dev_cnt; 15515 } 15516 } 15517 } 15518 15519 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15520 KM_NOSLEEP); 15521 if (devlist == NULL) { 15522 mutex_exit(&pptr->port_mutex); 15523 fcp_log(CE_WARN, pptr->port_dip, 15524 "!fcp%d: failed to allocate for portmap for construct map", 15525 pptr->port_instance); 15526 return (devptr); 15527 } 15528 15529 for (i = 0; i < FCP_NUM_HASH; i++) { 15530 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15531 ptgt = ptgt->tgt_next) { 15532 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15533 int ret; 15534 15535 ret = fc_ulp_pwwn_to_portmap( 15536 pptr->port_fp_handle, 15537 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15538 devlist); 15539 15540 if (ret == FC_SUCCESS) { 15541 devlist++; 15542 continue; 15543 } 15544 15545 devlist->map_pd = NULL; 15546 devlist->map_did.port_id = ptgt->tgt_d_id; 15547 devlist->map_hard_addr.hard_addr = 15548 ptgt->tgt_hard_addr; 15549 15550 devlist->map_state = PORT_DEVICE_INVALID; 15551 devlist->map_type = PORT_DEVICE_OLD; 15552 15553 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15554 &devlist->map_nwwn, FC_WWN_SIZE); 15555 15556 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15557 &devlist->map_pwwn, FC_WWN_SIZE); 15558 15559 devlist++; 15560 } 15561 } 15562 } 15563 15564 mutex_exit(&pptr->port_mutex); 15565 15566 return (devptr); 15567 } 15568 /* 15569 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15570 */ 15571 static void 15572 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15573 { 15574 int i; 15575 struct fcp_tgt *ptgt; 15576 struct fcp_lun *plun; 15577 15578 for (i = 0; i < FCP_NUM_HASH; i++) { 15579 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15580 ptgt = ptgt->tgt_next) { 15581 mutex_enter(&ptgt->tgt_mutex); 15582 for (plun = ptgt->tgt_lun; plun != NULL; 15583 plun = plun->lun_next) { 15584 if (plun->lun_mpxio && 15585 plun->lun_state & FCP_LUN_BUSY) { 15586 if (!fcp_pass_to_hp(pptr, plun, 15587 plun->lun_cip, 15588 FCP_MPXIO_PATH_SET_BUSY, 15589 pptr->port_link_cnt, 15590 ptgt->tgt_change_cnt, 0, 0)) { 15591 FCP_TRACE(fcp_logq, 15592 pptr->port_instbuf, 15593 fcp_trace, 15594 FCP_BUF_LEVEL_2, 0, 15595 "path_verifybusy: " 15596 "disable lun %p failed!", 15597 plun); 15598 } 15599 } 15600 } 15601 mutex_exit(&ptgt->tgt_mutex); 15602 } 15603 } 15604 } 15605 15606 static int 15607 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15608 { 15609 dev_info_t *cdip = NULL; 15610 dev_info_t *pdip = NULL; 15611 15612 ASSERT(plun); 15613 15614 mutex_enter(&plun->lun_mutex); 15615 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15616 mutex_exit(&plun->lun_mutex); 15617 return (NDI_FAILURE); 15618 } 15619 mutex_exit(&plun->lun_mutex); 15620 cdip = mdi_pi_get_client(PIP(cip)); 15621 pdip = mdi_pi_get_phci(PIP(cip)); 15622 15623 ASSERT(cdip != NULL); 15624 ASSERT(pdip != NULL); 15625 15626 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15627 /* LUN ready for IO */ 15628 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15629 } else { 15630 /* LUN busy to accept IO */ 15631 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15632 } 15633 return (NDI_SUCCESS); 15634 } 15635 15636 /* 15637 * Caller must free the returned string of MAXPATHLEN len 15638 * If the device is offline (-1 instance number) NULL 15639 * will be returned. 15640 */ 15641 static char * 15642 fcp_get_lun_path(struct fcp_lun *plun) 15643 { 15644 dev_info_t *dip = NULL; 15645 char *path = NULL; 15646 mdi_pathinfo_t *pip = NULL; 15647 15648 if (plun == NULL) { 15649 return (NULL); 15650 } 15651 15652 mutex_enter(&plun->lun_mutex); 15653 if (plun->lun_mpxio == 0) { 15654 dip = DIP(plun->lun_cip); 15655 mutex_exit(&plun->lun_mutex); 15656 } else { 15657 /* 15658 * lun_cip must be accessed with lun_mutex held. Here 15659 * plun->lun_cip either points to a valid node or it is NULL. 15660 * Make a copy so that we can release lun_mutex. 15661 */ 15662 pip = PIP(plun->lun_cip); 15663 15664 /* 15665 * Increase ref count on the path so that we can release 15666 * lun_mutex and still be sure that the pathinfo node (and thus 15667 * also the client) is not deallocated. If pip is NULL, this 15668 * has no effect. 15669 */ 15670 mdi_hold_path(pip); 15671 15672 mutex_exit(&plun->lun_mutex); 15673 15674 /* Get the client. If pip is NULL, we get NULL. */ 15675 dip = mdi_pi_get_client(pip); 15676 } 15677 15678 if (dip == NULL) 15679 goto out; 15680 if (ddi_get_instance(dip) < 0) 15681 goto out; 15682 15683 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15684 if (path == NULL) 15685 goto out; 15686 15687 (void) ddi_pathname(dip, path); 15688 15689 /* Clean up. */ 15690 out: 15691 if (pip != NULL) 15692 mdi_rele_path(pip); 15693 15694 /* 15695 * In reality, the user wants a fully valid path (one they can open) 15696 * but this string is lacking the mount point, and the minor node. 15697 * It would be nice if we could "figure these out" somehow 15698 * and fill them in. Otherwise, the userland code has to understand 15699 * driver specific details of which minor node is the "best" or 15700 * "right" one to expose. (Ex: which slice is the whole disk, or 15701 * which tape doesn't rewind) 15702 */ 15703 return (path); 15704 } 15705 15706 static int 15707 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15708 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15709 { 15710 int64_t reset_delay; 15711 int rval, retry = 0; 15712 struct fcp_port *pptr = fcp_dip2port(parent); 15713 15714 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15715 (ddi_get_lbolt64() - pptr->port_attach_time); 15716 if (reset_delay < 0) { 15717 reset_delay = 0; 15718 } 15719 15720 if (fcp_bus_config_debug) { 15721 flag |= NDI_DEVI_DEBUG; 15722 } 15723 15724 switch (op) { 15725 case BUS_CONFIG_ONE: 15726 /* 15727 * Retry the command since we need to ensure 15728 * the fabric devices are available for root 15729 */ 15730 while (retry++ < fcp_max_bus_config_retries) { 15731 rval = (ndi_busop_bus_config(parent, 15732 flag | NDI_MDI_FALLBACK, op, 15733 arg, childp, (clock_t)reset_delay)); 15734 if (rval == 0) { 15735 return (rval); 15736 } 15737 } 15738 15739 /* 15740 * drain taskq to make sure nodes are created and then 15741 * try again. 15742 */ 15743 taskq_wait(DEVI(parent)->devi_taskq); 15744 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15745 op, arg, childp, 0)); 15746 15747 case BUS_CONFIG_DRIVER: 15748 case BUS_CONFIG_ALL: { 15749 /* 15750 * delay till all devices report in (port_tmp_cnt == 0) 15751 * or FCP_INIT_WAIT_TIMEOUT 15752 */ 15753 mutex_enter(&pptr->port_mutex); 15754 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15755 (void) cv_timedwait(&pptr->port_config_cv, 15756 &pptr->port_mutex, 15757 ddi_get_lbolt() + (clock_t)reset_delay); 15758 reset_delay = 15759 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15760 (ddi_get_lbolt64() - pptr->port_attach_time); 15761 } 15762 mutex_exit(&pptr->port_mutex); 15763 /* drain taskq to make sure nodes are created */ 15764 taskq_wait(DEVI(parent)->devi_taskq); 15765 return (ndi_busop_bus_config(parent, flag, op, 15766 arg, childp, 0)); 15767 } 15768 15769 default: 15770 return (NDI_FAILURE); 15771 } 15772 /*NOTREACHED*/ 15773 } 15774 15775 static int 15776 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15777 ddi_bus_config_op_t op, void *arg) 15778 { 15779 if (fcp_bus_config_debug) { 15780 flag |= NDI_DEVI_DEBUG; 15781 } 15782 15783 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15784 } 15785 15786 15787 /* 15788 * Routine to copy GUID into the lun structure. 15789 * returns 0 if copy was successful and 1 if encountered a 15790 * failure and did not copy the guid. 15791 */ 15792 static int 15793 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15794 { 15795 15796 int retval = 0; 15797 15798 /* add one for the null terminator */ 15799 const unsigned int len = strlen(guidp) + 1; 15800 15801 if ((guidp == NULL) || (plun == NULL)) { 15802 return (1); 15803 } 15804 15805 /* 15806 * if the plun->lun_guid already has been allocated, 15807 * then check the size. if the size is exact, reuse 15808 * it....if not free it an allocate the required size. 15809 * The reallocation should NOT typically happen 15810 * unless the GUIDs reported changes between passes. 15811 * We free up and alloc again even if the 15812 * size was more than required. This is due to the 15813 * fact that the field lun_guid_size - serves 15814 * dual role of indicating the size of the wwn 15815 * size and ALSO the allocation size. 15816 */ 15817 if (plun->lun_guid) { 15818 if (plun->lun_guid_size != len) { 15819 /* 15820 * free the allocated memory and 15821 * initialize the field 15822 * lun_guid_size to 0. 15823 */ 15824 kmem_free(plun->lun_guid, plun->lun_guid_size); 15825 plun->lun_guid = NULL; 15826 plun->lun_guid_size = 0; 15827 } 15828 } 15829 /* 15830 * alloc only if not already done. 15831 */ 15832 if (plun->lun_guid == NULL) { 15833 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15834 if (plun->lun_guid == NULL) { 15835 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15836 "Unable to allocate" 15837 "Memory for GUID!!! size %d", len); 15838 retval = 1; 15839 } else { 15840 plun->lun_guid_size = len; 15841 } 15842 } 15843 if (plun->lun_guid) { 15844 /* 15845 * now copy the GUID 15846 */ 15847 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15848 } 15849 return (retval); 15850 } 15851 15852 /* 15853 * fcp_reconfig_wait 15854 * 15855 * Wait for a rediscovery/reconfiguration to complete before continuing. 15856 */ 15857 15858 static void 15859 fcp_reconfig_wait(struct fcp_port *pptr) 15860 { 15861 clock_t reconfig_start, wait_timeout; 15862 15863 /* 15864 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15865 * reconfiguration in progress. 15866 */ 15867 15868 mutex_enter(&pptr->port_mutex); 15869 if (pptr->port_tmp_cnt == 0) { 15870 mutex_exit(&pptr->port_mutex); 15871 return; 15872 } 15873 mutex_exit(&pptr->port_mutex); 15874 15875 /* 15876 * If we cause a reconfig by raising power, delay until all devices 15877 * report in (port_tmp_cnt returns to 0) 15878 */ 15879 15880 reconfig_start = ddi_get_lbolt(); 15881 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15882 15883 mutex_enter(&pptr->port_mutex); 15884 15885 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15886 pptr->port_tmp_cnt) { 15887 15888 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15889 reconfig_start + wait_timeout); 15890 } 15891 15892 mutex_exit(&pptr->port_mutex); 15893 15894 /* 15895 * Even if fcp_tmp_count isn't 0, continue without error. The port 15896 * we want may still be ok. If not, it will error out later 15897 */ 15898 } 15899 15900 /* 15901 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15902 * We rely on the fcp_global_mutex to provide protection against changes to 15903 * the fcp_lun_blacklist. 15904 * 15905 * You can describe a list of target port WWNs and LUN numbers which will 15906 * not be configured. LUN numbers will be interpreted as decimal. White 15907 * spaces and ',' can be used in the list of LUN numbers. 15908 * 15909 * To prevent LUNs 1 and 2 from being configured for target 15910 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15911 * 15912 * pwwn-lun-blacklist= 15913 * "510000f010fd92a1,1,2", 15914 * "510000e012079df1,1,2"; 15915 */ 15916 static void 15917 fcp_read_blacklist(dev_info_t *dip, 15918 struct fcp_black_list_entry **pplun_blacklist) 15919 { 15920 char **prop_array = NULL; 15921 char *curr_pwwn = NULL; 15922 char *curr_lun = NULL; 15923 uint32_t prop_item = 0; 15924 int idx = 0; 15925 int len = 0; 15926 15927 ASSERT(mutex_owned(&fcp_global_mutex)); 15928 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15929 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15930 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15931 return; 15932 } 15933 15934 for (idx = 0; idx < prop_item; idx++) { 15935 15936 curr_pwwn = prop_array[idx]; 15937 while (*curr_pwwn == ' ') { 15938 curr_pwwn++; 15939 } 15940 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15941 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15942 ", please check.", curr_pwwn); 15943 continue; 15944 } 15945 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15946 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15947 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15948 ", please check.", curr_pwwn); 15949 continue; 15950 } 15951 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15952 if (isxdigit(curr_pwwn[len]) != TRUE) { 15953 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15954 "blacklist, please check.", curr_pwwn); 15955 break; 15956 } 15957 } 15958 if (len != sizeof (la_wwn_t) * 2) { 15959 continue; 15960 } 15961 15962 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15963 *(curr_lun - 1) = '\0'; 15964 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15965 } 15966 15967 ddi_prop_free(prop_array); 15968 } 15969 15970 /* 15971 * Get the masking info about one remote target port designated by wwn. 15972 * Lun ids could be separated by ',' or white spaces. 15973 */ 15974 static void 15975 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15976 struct fcp_black_list_entry **pplun_blacklist) 15977 { 15978 int idx = 0; 15979 uint32_t offset = 0; 15980 unsigned long lun_id = 0; 15981 char lunid_buf[16]; 15982 char *pend = NULL; 15983 int illegal_digit = 0; 15984 15985 while (offset < strlen(curr_lun)) { 15986 while ((curr_lun[offset + idx] != ',') && 15987 (curr_lun[offset + idx] != '\0') && 15988 (curr_lun[offset + idx] != ' ')) { 15989 if (isdigit(curr_lun[offset + idx]) == 0) { 15990 illegal_digit++; 15991 } 15992 idx++; 15993 } 15994 if (illegal_digit > 0) { 15995 offset += (idx+1); /* To the start of next lun */ 15996 idx = 0; 15997 illegal_digit = 0; 15998 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15999 "the blacklist, please check digits.", 16000 curr_lun, curr_pwwn); 16001 continue; 16002 } 16003 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 16004 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16005 "the blacklist, please check the length of LUN#.", 16006 curr_lun, curr_pwwn); 16007 break; 16008 } 16009 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 16010 offset++; 16011 continue; 16012 } 16013 16014 bcopy(curr_lun + offset, lunid_buf, idx); 16015 lunid_buf[idx] = '\0'; 16016 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 16017 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 16018 } else { 16019 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16020 "the blacklist, please check %s.", 16021 curr_lun, curr_pwwn, lunid_buf); 16022 } 16023 offset += (idx+1); /* To the start of next lun */ 16024 idx = 0; 16025 } 16026 } 16027 16028 /* 16029 * Add one masking record 16030 */ 16031 static void 16032 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 16033 struct fcp_black_list_entry **pplun_blacklist) 16034 { 16035 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16036 struct fcp_black_list_entry *new_entry = NULL; 16037 la_wwn_t wwn; 16038 16039 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16040 while (tmp_entry) { 16041 if ((bcmp(&tmp_entry->wwn, &wwn, 16042 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16043 return; 16044 } 16045 16046 tmp_entry = tmp_entry->next; 16047 } 16048 16049 /* add to black list */ 16050 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16051 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16052 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16053 new_entry->lun = lun_id; 16054 new_entry->masked = 0; 16055 new_entry->next = *pplun_blacklist; 16056 *pplun_blacklist = new_entry; 16057 } 16058 16059 /* 16060 * Check if we should mask the specified lun of this fcp_tgt 16061 */ 16062 static int 16063 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) 16064 { 16065 struct fcp_black_list_entry *remote_port; 16066 16067 remote_port = fcp_lun_blacklist; 16068 while (remote_port != NULL) { 16069 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16070 if (remote_port->lun == lun_id) { 16071 remote_port->masked++; 16072 if (remote_port->masked == 1) { 16073 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16074 "%02x%02x%02x%02x%02x%02x%02x%02x " 16075 "is masked due to black listing.\n", 16076 lun_id, wwn->raw_wwn[0], 16077 wwn->raw_wwn[1], wwn->raw_wwn[2], 16078 wwn->raw_wwn[3], wwn->raw_wwn[4], 16079 wwn->raw_wwn[5], wwn->raw_wwn[6], 16080 wwn->raw_wwn[7]); 16081 } 16082 return (TRUE); 16083 } 16084 } 16085 remote_port = remote_port->next; 16086 } 16087 return (FALSE); 16088 } 16089 16090 /* 16091 * Release all allocated resources 16092 */ 16093 static void 16094 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) 16095 { 16096 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16097 struct fcp_black_list_entry *current_entry = NULL; 16098 16099 ASSERT(mutex_owned(&fcp_global_mutex)); 16100 /* 16101 * Traverse all luns 16102 */ 16103 while (tmp_entry) { 16104 current_entry = tmp_entry; 16105 tmp_entry = tmp_entry->next; 16106 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16107 } 16108 *pplun_blacklist = NULL; 16109 } 16110 16111 /* 16112 * In fcp module, 16113 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16114 */ 16115 static struct scsi_pkt * 16116 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16117 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16118 int flags, int (*callback)(), caddr_t arg) 16119 { 16120 fcp_port_t *pptr = ADDR2FCP(ap); 16121 fcp_pkt_t *cmd = NULL; 16122 fc_frame_hdr_t *hp; 16123 16124 /* 16125 * First step: get the packet 16126 */ 16127 if (pkt == NULL) { 16128 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16129 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16130 callback, arg); 16131 if (pkt == NULL) { 16132 return (NULL); 16133 } 16134 16135 /* 16136 * All fields in scsi_pkt will be initialized properly or 16137 * set to zero. We need do nothing for scsi_pkt. 16138 */ 16139 /* 16140 * But it's our responsibility to link other related data 16141 * structures. Their initialization will be done, just 16142 * before the scsi_pkt will be sent to FCA. 16143 */ 16144 cmd = PKT2CMD(pkt); 16145 cmd->cmd_pkt = pkt; 16146 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16147 /* 16148 * fc_packet_t 16149 */ 16150 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16151 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16152 sizeof (struct fcp_pkt)); 16153 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16154 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16155 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16156 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16157 /* 16158 * Fill in the Fabric Channel Header 16159 */ 16160 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16161 hp->r_ctl = R_CTL_COMMAND; 16162 hp->rsvd = 0; 16163 hp->type = FC_TYPE_SCSI_FCP; 16164 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16165 hp->seq_id = 0; 16166 hp->df_ctl = 0; 16167 hp->seq_cnt = 0; 16168 hp->ox_id = 0xffff; 16169 hp->rx_id = 0xffff; 16170 hp->ro = 0; 16171 } else { 16172 /* 16173 * We need think if we should reset any elements in 16174 * related data structures. 16175 */ 16176 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16177 fcp_trace, FCP_BUF_LEVEL_6, 0, 16178 "reusing pkt, flags %d", flags); 16179 cmd = PKT2CMD(pkt); 16180 if (cmd->cmd_fp_pkt->pkt_pd) { 16181 cmd->cmd_fp_pkt->pkt_pd = NULL; 16182 } 16183 } 16184 16185 /* 16186 * Second step: dma allocation/move 16187 */ 16188 if (bp && bp->b_bcount != 0) { 16189 /* 16190 * Mark if it's read or write 16191 */ 16192 if (bp->b_flags & B_READ) { 16193 cmd->cmd_flags |= CFLAG_IS_READ; 16194 } else { 16195 cmd->cmd_flags &= ~CFLAG_IS_READ; 16196 } 16197 16198 bp_mapin(bp); 16199 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16200 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16201 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16202 } else { 16203 /* 16204 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16205 * to send zero-length read/write. 16206 */ 16207 cmd->cmd_fp_pkt->pkt_data = NULL; 16208 cmd->cmd_fp_pkt->pkt_datalen = 0; 16209 } 16210 16211 return (pkt); 16212 } 16213 16214 static void 16215 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16216 { 16217 fcp_port_t *pptr = ADDR2FCP(ap); 16218 16219 /* 16220 * First we let FCA to uninitilize private part. 16221 */ 16222 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16223 PKT2CMD(pkt)->cmd_fp_pkt); 16224 16225 /* 16226 * Then we uninitialize fc_packet. 16227 */ 16228 16229 /* 16230 * Thirdly, we uninitializae fcp_pkt. 16231 */ 16232 16233 /* 16234 * In the end, we free scsi_pkt. 16235 */ 16236 scsi_hba_pkt_free(ap, pkt); 16237 } 16238 16239 static int 16240 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16241 { 16242 fcp_port_t *pptr = ADDR2FCP(ap); 16243 fcp_lun_t *plun = ADDR2LUN(ap); 16244 fcp_tgt_t *ptgt = plun->lun_tgt; 16245 fcp_pkt_t *cmd = PKT2CMD(pkt); 16246 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16247 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16248 int rval; 16249 16250 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16251 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16252 16253 /* 16254 * Firstly, we need initialize fcp_pkt_t 16255 * Secondly, we need initialize fcp_cmd_t. 16256 */ 16257 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16258 fcmd->fcp_data_len = fpkt->pkt_datalen; 16259 fcmd->fcp_ent_addr = plun->lun_addr; 16260 if (pkt->pkt_flags & FLAG_HTAG) { 16261 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16262 } else if (pkt->pkt_flags & FLAG_OTAG) { 16263 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16264 } else if (pkt->pkt_flags & FLAG_STAG) { 16265 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16266 } else { 16267 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16268 } 16269 16270 if (cmd->cmd_flags & CFLAG_IS_READ) { 16271 fcmd->fcp_cntl.cntl_read_data = 1; 16272 fcmd->fcp_cntl.cntl_write_data = 0; 16273 } else { 16274 fcmd->fcp_cntl.cntl_read_data = 0; 16275 fcmd->fcp_cntl.cntl_write_data = 1; 16276 } 16277 16278 /* 16279 * Then we need initialize fc_packet_t too. 16280 */ 16281 fpkt->pkt_timeout = pkt->pkt_time + 2; 16282 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16283 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16284 if (cmd->cmd_flags & CFLAG_IS_READ) { 16285 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16286 } else { 16287 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16288 } 16289 16290 if (pkt->pkt_flags & FLAG_NOINTR) { 16291 fpkt->pkt_comp = NULL; 16292 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16293 } else { 16294 fpkt->pkt_comp = fcp_cmd_callback; 16295 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16296 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16297 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16298 } 16299 } 16300 16301 /* 16302 * Lastly, we need initialize scsi_pkt 16303 */ 16304 pkt->pkt_reason = CMD_CMPLT; 16305 pkt->pkt_state = 0; 16306 pkt->pkt_statistics = 0; 16307 pkt->pkt_resid = 0; 16308 16309 /* 16310 * if interrupts aren't allowed (e.g. at dump time) then we'll 16311 * have to do polled I/O 16312 */ 16313 if (pkt->pkt_flags & FLAG_NOINTR) { 16314 return (fcp_dopoll(pptr, cmd)); 16315 } 16316 16317 cmd->cmd_state = FCP_PKT_ISSUED; 16318 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16319 if (rval == FC_SUCCESS) { 16320 return (TRAN_ACCEPT); 16321 } 16322 16323 /* 16324 * Need more consideration 16325 * 16326 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16327 */ 16328 cmd->cmd_state = FCP_PKT_IDLE; 16329 if (rval == FC_TRAN_BUSY) { 16330 return (TRAN_BUSY); 16331 } else { 16332 return (TRAN_FATAL_ERROR); 16333 } 16334 } 16335 16336 /* 16337 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16338 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16339 */ 16340 static void 16341 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16342 { 16343 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16344 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16345 } 16346 16347 /* 16348 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16349 */ 16350 static void 16351 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16352 { 16353 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16354 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16355 } 16356