1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2018 Nexenta Systems, Inc. 28 */ 29 30 /* 31 * Fibre Channel SCSI ULP Mapping driver 32 */ 33 34 #include <sys/scsi/scsi.h> 35 #include <sys/types.h> 36 #include <sys/varargs.h> 37 #include <sys/devctl.h> 38 #include <sys/thread.h> 39 #include <sys/thread.h> 40 #include <sys/open.h> 41 #include <sys/file.h> 42 #include <sys/sunndi.h> 43 #include <sys/console.h> 44 #include <sys/proc.h> 45 #include <sys/time.h> 46 #include <sys/utsname.h> 47 #include <sys/scsi/impl/scsi_reset_notify.h> 48 #include <sys/ndi_impldefs.h> 49 #include <sys/byteorder.h> 50 #include <sys/ctype.h> 51 #include <sys/sunmdi.h> 52 53 #include <sys/fibre-channel/fc.h> 54 #include <sys/fibre-channel/impl/fc_ulpif.h> 55 #include <sys/fibre-channel/ulp/fcpvar.h> 56 57 /* 58 * Discovery Process 59 * ================= 60 * 61 * The discovery process is a major function of FCP. In order to help 62 * understand that function a flow diagram is given here. This diagram 63 * doesn't claim to cover all the cases and the events that can occur during 64 * the discovery process nor the subtleties of the code. The code paths shown 65 * are simplified. Its purpose is to help the reader (and potentially bug 66 * fixer) have an overall view of the logic of the code. For that reason the 67 * diagram covers the simple case of the line coming up cleanly or of a new 68 * port attaching to FCP the link being up. The reader must keep in mind 69 * that: 70 * 71 * - There are special cases where bringing devices online and offline 72 * is driven by Ioctl. 73 * 74 * - The behavior of the discovery process can be modified through the 75 * .conf file. 76 * 77 * - The line can go down and come back up at any time during the 78 * discovery process which explains some of the complexity of the code. 79 * 80 * ............................................................................ 81 * 82 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 83 * 84 * 85 * +-------------------------+ 86 * fp/fctl module --->| fcp_port_attach | 87 * +-------------------------+ 88 * | | 89 * | | 90 * | v 91 * | +-------------------------+ 92 * | | fcp_handle_port_attach | 93 * | +-------------------------+ 94 * | | 95 * | | 96 * +--------------------+ | 97 * | | 98 * v v 99 * +-------------------------+ 100 * | fcp_statec_callback | 101 * +-------------------------+ 102 * | 103 * | 104 * v 105 * +-------------------------+ 106 * | fcp_handle_devices | 107 * +-------------------------+ 108 * | 109 * | 110 * v 111 * +-------------------------+ 112 * | fcp_handle_mapflags | 113 * +-------------------------+ 114 * | 115 * | 116 * v 117 * +-------------------------+ 118 * | fcp_send_els | 119 * | | 120 * | PLOGI or PRLI To all the| 121 * | reachable devices. | 122 * +-------------------------+ 123 * 124 * 125 * ............................................................................ 126 * 127 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 128 * STEP 1 are called (it is actually the same function). 129 * 130 * 131 * +-------------------------+ 132 * | fcp_icmd_callback | 133 * fp/fctl module --->| | 134 * | callback for PLOGI and | 135 * | PRLI. | 136 * +-------------------------+ 137 * | 138 * | 139 * Received PLOGI Accept /-\ Received PRLI Accept 140 * _ _ _ _ _ _ / \_ _ _ _ _ _ 141 * | \ / | 142 * | \-/ | 143 * | | 144 * v v 145 * +-------------------------+ +-------------------------+ 146 * | fcp_send_els | | fcp_send_scsi | 147 * | | | | 148 * | PRLI | | REPORT_LUN | 149 * +-------------------------+ +-------------------------+ 150 * 151 * ............................................................................ 152 * 153 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 154 * (It is actually the same function). 155 * 156 * 157 * +-------------------------+ 158 * fp/fctl module ------->| fcp_scsi_callback | 159 * +-------------------------+ 160 * | 161 * | 162 * | 163 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 164 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 165 * | \ / | 166 * | \-/ | 167 * | | | 168 * | Receive INQUIRY reply| | 169 * | | | 170 * v v v 171 * +------------------------+ +----------------------+ +----------------------+ 172 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 173 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 174 * +------------------------+ +----------------------+ +----------------------+ 175 * | | | 176 * | | | 177 * | | | 178 * v v | 179 * +-----------------+ +-----------------+ | 180 * | fcp_send_scsi | | fcp_send_scsi | | 181 * | | | | | 182 * | INQUIRY | | INQUIRY PAGE83 | | 183 * | (To each LUN) | +-----------------+ | 184 * +-----------------+ | 185 * | 186 * v 187 * +------------------------+ 188 * | fcp_call_finish_init | 189 * +------------------------+ 190 * | 191 * v 192 * +-----------------------------+ 193 * | fcp_call_finish_init_held | 194 * +-----------------------------+ 195 * | 196 * | 197 * All LUNs scanned /-\ 198 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 199 * | \ / 200 * | \-/ 201 * v | 202 * +------------------+ | 203 * | fcp_finish_tgt | | 204 * +------------------+ | 205 * | Target Not Offline and | 206 * Target Not Offline and | not marked and tgt_node_state | 207 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 208 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 209 * | \ / | | 210 * | \-/ | | 211 * v v | 212 * +----------------------------+ +-------------------+ | 213 * | fcp_offline_target | | fcp_create_luns | | 214 * | | +-------------------+ | 215 * | A structure fcp_tgt_elem | | | 216 * | is created and queued in | v | 217 * | the FCP port list | +-------------------+ | 218 * | port_offline_tgts. It | | fcp_pass_to_hp | | 219 * | will be unqueued by the | | | | 220 * | watchdog timer. | | Called for each | | 221 * +----------------------------+ | LUN. Dispatches | | 222 * | | fcp_hp_task | | 223 * | +-------------------+ | 224 * | | | 225 * | | | 226 * | | | 227 * | +---------------->| 228 * | | 229 * +---------------------------------------------->| 230 * | 231 * | 232 * All the targets (devices) have been scanned /-\ 233 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 234 * | \ / 235 * | \-/ 236 * +-------------------------------------+ | 237 * | fcp_finish_init | | 238 * | | | 239 * | Signal broadcasts the condition | | 240 * | variable port_config_cv of the FCP | | 241 * | port. One potential code sequence | | 242 * | waiting on the condition variable | | 243 * | the code sequence handling | | 244 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 245 * | The other is in the function | | 246 * | fcp_reconfig_wait which is called | | 247 * | in the transmit path preventing IOs | | 248 * | from going through till the disco- | | 249 * | very process is over. | | 250 * +-------------------------------------+ | 251 * | | 252 * | | 253 * +--------------------------------->| 254 * | 255 * v 256 * Return 257 * 258 * ............................................................................ 259 * 260 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 261 * 262 * 263 * +-------------------------+ 264 * | fcp_hp_task | 265 * +-------------------------+ 266 * | 267 * | 268 * v 269 * +-------------------------+ 270 * | fcp_trigger_lun | 271 * +-------------------------+ 272 * | 273 * | 274 * v 275 * Bring offline /-\ Bring online 276 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 277 * | \ / | 278 * | \-/ | 279 * v v 280 * +---------------------+ +-----------------------+ 281 * | fcp_offline_child | | fcp_get_cip | 282 * +---------------------+ | | 283 * | Creates a dev_info_t | 284 * | or a mdi_pathinfo_t | 285 * | depending on whether | 286 * | mpxio is on or off. | 287 * +-----------------------+ 288 * | 289 * | 290 * v 291 * +-----------------------+ 292 * | fcp_online_child | 293 * | | 294 * | Set device online | 295 * | using NDI or MDI. | 296 * +-----------------------+ 297 * 298 * ............................................................................ 299 * 300 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 301 * what is described here. We only show the target offline path. 302 * 303 * 304 * +--------------------------+ 305 * | fcp_watch | 306 * +--------------------------+ 307 * | 308 * | 309 * v 310 * +--------------------------+ 311 * | fcp_scan_offline_tgts | 312 * +--------------------------+ 313 * | 314 * | 315 * v 316 * +--------------------------+ 317 * | fcp_offline_target_now | 318 * +--------------------------+ 319 * | 320 * | 321 * v 322 * +--------------------------+ 323 * | fcp_offline_tgt_luns | 324 * +--------------------------+ 325 * | 326 * | 327 * v 328 * +--------------------------+ 329 * | fcp_offline_lun | 330 * +--------------------------+ 331 * | 332 * | 333 * v 334 * +----------------------------------+ 335 * | fcp_offline_lun_now | 336 * | | 337 * | A request (or two if mpxio) is | 338 * | sent to the hot plug task using | 339 * | a fcp_hp_elem structure. | 340 * +----------------------------------+ 341 */ 342 343 /* 344 * Functions registered with DDI framework 345 */ 346 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 347 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 348 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 349 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 350 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 351 cred_t *credp, int *rval); 352 353 /* 354 * Functions registered with FC Transport framework 355 */ 356 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 357 fc_attach_cmd_t cmd, uint32_t s_id); 358 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 359 fc_detach_cmd_t cmd); 360 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 361 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 362 uint32_t claimed); 363 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 364 fc_unsol_buf_t *buf, uint32_t claimed); 365 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 366 fc_unsol_buf_t *buf, uint32_t claimed); 367 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 368 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 369 uint32_t dev_cnt, uint32_t port_sid); 370 371 /* 372 * Functions registered with SCSA framework 373 */ 374 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 375 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 376 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 377 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 378 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 379 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 380 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 381 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 382 static int fcp_scsi_reset(struct scsi_address *ap, int level); 383 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 384 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 385 int whom); 386 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 387 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 388 void (*callback)(caddr_t), caddr_t arg); 389 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 390 char *name, ddi_eventcookie_t *event_cookiep); 391 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 392 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 393 ddi_callback_id_t *cb_id); 394 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 395 ddi_callback_id_t cb_id); 396 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 397 ddi_eventcookie_t eventid, void *impldata); 398 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 399 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 400 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 401 ddi_bus_config_op_t op, void *arg); 402 403 /* 404 * Internal functions 405 */ 406 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 407 int mode, int *rval); 408 409 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 410 int mode, int *rval); 411 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 412 struct fcp_scsi_cmd *fscsi, int mode); 413 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 414 caddr_t base_addr, int mode); 415 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 416 417 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 418 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 419 int *fc_pkt_reason, int *fc_pkt_action); 420 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 421 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 422 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 423 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 424 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 425 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 426 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 427 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 428 429 static void fcp_handle_devices(struct fcp_port *pptr, 430 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 431 fcp_map_tag_t *map_tag, int cause); 432 static int fcp_handle_mapflags(struct fcp_port *pptr, 433 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 434 int tgt_cnt, int cause); 435 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause); 436 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 437 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 438 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 439 int cause); 440 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 441 uint32_t state); 442 static struct fcp_port *fcp_get_port(opaque_t port_handle); 443 static void fcp_unsol_callback(fc_packet_t *fpkt); 444 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 445 uchar_t r_ctl, uchar_t type); 446 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 447 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 448 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 449 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 450 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 451 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 452 int nodma, int flags); 453 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 454 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 455 uchar_t *wwn); 456 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 457 uint32_t d_id); 458 static void fcp_icmd_callback(fc_packet_t *fpkt); 459 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 460 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 461 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 462 static void fcp_scsi_callback(fc_packet_t *fpkt); 463 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 464 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 465 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 466 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 467 uint16_t lun_num); 468 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 469 int link_cnt, int tgt_cnt, int cause); 470 static void fcp_finish_init(struct fcp_port *pptr); 471 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 472 int tgt_cnt, int cause); 473 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 474 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 475 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 476 int link_cnt, int tgt_cnt, int nowait, int flags); 477 static void fcp_offline_target_now(struct fcp_port *pptr, 478 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 479 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 480 int tgt_cnt, int flags); 481 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 482 int nowait, int flags); 483 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 484 int tgt_cnt); 485 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 486 int tgt_cnt, int flags); 487 static void fcp_scan_offline_luns(struct fcp_port *pptr); 488 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 489 static void fcp_update_offline_flags(struct fcp_lun *plun); 490 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 491 static void fcp_abort_commands(struct fcp_pkt *head, struct 492 fcp_port *pptr); 493 static void fcp_cmd_callback(fc_packet_t *fpkt); 494 static void fcp_complete_pkt(fc_packet_t *fpkt); 495 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 496 struct fcp_port *pptr); 497 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 498 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 499 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 500 static void fcp_dealloc_lun(struct fcp_lun *plun); 501 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 502 fc_portmap_t *map_entry, int link_cnt); 503 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 504 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 505 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 506 int internal); 507 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 508 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 509 uint32_t s_id, int instance); 510 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 511 int instance); 512 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 513 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 514 int); 515 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 516 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 517 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 518 int flags); 519 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 520 static int fcp_reset_target(struct scsi_address *ap, int level); 521 static int fcp_commoncap(struct scsi_address *ap, char *cap, 522 int val, int tgtonly, int doset); 523 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 524 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 525 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 526 int sleep); 527 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 528 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 529 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 530 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 531 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 532 int lcount, int tcount); 533 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 534 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 535 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 536 int tgt_cnt); 537 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 538 dev_info_t *pdip, caddr_t name); 539 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 540 int lcount, int tcount, int flags, int *circ); 541 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 542 int lcount, int tcount, int flags, int *circ); 543 static void fcp_remove_child(struct fcp_lun *plun); 544 static void fcp_watch(void *arg); 545 static void fcp_check_reset_delay(struct fcp_port *pptr); 546 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 547 struct fcp_lun *rlun, int tgt_cnt); 548 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 549 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 550 uchar_t *wwn, uint16_t lun); 551 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 552 struct fcp_lun *plun); 553 static void fcp_post_callback(struct fcp_pkt *cmd); 554 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 555 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 556 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 557 child_info_t *cip); 558 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 559 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 560 int tgt_cnt, int flags); 561 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 562 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 563 int tgt_cnt, int flags, int wait); 564 static void fcp_retransport_cmd(struct fcp_port *pptr, 565 struct fcp_pkt *cmd); 566 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 567 uint_t statistics); 568 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 569 static void fcp_update_targets(struct fcp_port *pptr, 570 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 571 static int fcp_call_finish_init(struct fcp_port *pptr, 572 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 573 static int fcp_call_finish_init_held(struct fcp_port *pptr, 574 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 575 static void fcp_reconfigure_luns(void * tgt_handle); 576 static void fcp_free_targets(struct fcp_port *pptr); 577 static void fcp_free_target(struct fcp_tgt *ptgt); 578 static int fcp_is_retryable(struct fcp_ipkt *icmd); 579 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 580 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 581 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 582 static void fcp_print_error(fc_packet_t *fpkt); 583 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 584 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 585 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 586 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 587 uint32_t *dev_cnt); 588 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 589 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 590 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 591 struct fcp_ioctl *, struct fcp_port **); 592 static char *fcp_get_lun_path(struct fcp_lun *plun); 593 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 594 int *rval); 595 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 596 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 597 static char *fcp_get_lun_path(struct fcp_lun *plun); 598 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 599 int *rval); 600 static void fcp_reconfig_wait(struct fcp_port *pptr); 601 602 /* 603 * New functions added for mpxio support 604 */ 605 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 606 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 607 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 608 int tcount); 609 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 610 dev_info_t *pdip); 611 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 612 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 613 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 614 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 615 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 616 int what); 617 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 618 fc_packet_t *fpkt); 619 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 620 621 /* 622 * New functions added for lun masking support 623 */ 624 static void fcp_read_blacklist(dev_info_t *dip, 625 struct fcp_black_list_entry **pplun_blacklist); 626 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 627 struct fcp_black_list_entry **pplun_blacklist); 628 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 629 struct fcp_black_list_entry **pplun_blacklist); 630 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 631 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 632 633 /* 634 * New functions to support software FCA (like fcoei) 635 */ 636 static struct scsi_pkt *fcp_pseudo_init_pkt( 637 struct scsi_address *ap, struct scsi_pkt *pkt, 638 struct buf *bp, int cmdlen, int statuslen, 639 int tgtlen, int flags, int (*callback)(), caddr_t arg); 640 static void fcp_pseudo_destroy_pkt( 641 struct scsi_address *ap, struct scsi_pkt *pkt); 642 static void fcp_pseudo_sync_pkt( 643 struct scsi_address *ap, struct scsi_pkt *pkt); 644 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt); 645 static void fcp_pseudo_dmafree( 646 struct scsi_address *ap, struct scsi_pkt *pkt); 647 648 extern struct mod_ops mod_driverops; 649 /* 650 * This variable is defined in modctl.c and set to '1' after the root driver 651 * and fs are loaded. It serves as an indication that the root filesystem can 652 * be used. 653 */ 654 extern int modrootloaded; 655 /* 656 * This table contains strings associated with the SCSI sense key codes. It 657 * is used by FCP to print a clear explanation of the code returned in the 658 * sense information by a device. 659 */ 660 extern char *sense_keys[]; 661 /* 662 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 663 * under this device that the paths to a physical device are created when 664 * MPxIO is used. 665 */ 666 extern dev_info_t *scsi_vhci_dip; 667 668 /* 669 * Report lun processing 670 */ 671 #define FCP_LUN_ADDRESSING 0x80 672 #define FCP_PD_ADDRESSING 0x00 673 #define FCP_VOLUME_ADDRESSING 0x40 674 675 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 676 #define MAX_INT_DMA 0x7fffffff 677 /* 678 * Property definitions 679 */ 680 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 681 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 682 #define TARGET_PROP (char *)fcp_target_prop 683 #define LUN_PROP (char *)fcp_lun_prop 684 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 685 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 686 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 687 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 688 #define INIT_PORT_PROP (char *)fcp_init_port_prop 689 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 690 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 691 /* 692 * Short hand macros. 693 */ 694 #define LUN_PORT (plun->lun_tgt->tgt_port) 695 #define LUN_TGT (plun->lun_tgt) 696 697 /* 698 * Driver private macros 699 */ 700 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 701 ((x) >= 'a' && (x) <= 'f') ? \ 702 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 703 704 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 705 706 #define FCP_N_NDI_EVENTS \ 707 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 708 709 #define FCP_LINK_STATE_CHANGED(p, c) \ 710 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 711 712 #define FCP_TGT_STATE_CHANGED(t, c) \ 713 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 714 715 #define FCP_STATE_CHANGED(p, t, c) \ 716 (FCP_TGT_STATE_CHANGED(t, c)) 717 718 #define FCP_MUST_RETRY(fpkt) \ 719 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 720 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 721 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 722 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 723 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 724 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 725 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 726 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 727 728 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 729 ((es)->es_key == KEY_UNIT_ATTENTION && \ 730 (es)->es_add_code == 0x3f && \ 731 (es)->es_qual_code == 0x0e) 732 733 #define FCP_SENSE_NO_LUN(es) \ 734 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 735 (es)->es_add_code == 0x25 && \ 736 (es)->es_qual_code == 0x0) 737 738 #define FCP_VERSION "20091208-1.192" 739 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 740 741 #define FCP_NUM_ELEMENTS(array) \ 742 (sizeof (array) / sizeof ((array)[0])) 743 744 /* 745 * Debugging, Error reporting, and tracing 746 */ 747 #define FCP_LOG_SIZE 1024 * 1024 748 749 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 750 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 751 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 752 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 753 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 754 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 755 #define FCP_LEVEL_7 0x00040 756 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 757 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 758 759 760 761 /* 762 * Log contents to system messages file 763 */ 764 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 765 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 766 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 767 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 768 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 769 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 770 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 771 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 772 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 773 774 775 /* 776 * Log contents to trace buffer 777 */ 778 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 779 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 780 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 781 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 782 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 783 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 784 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 785 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 786 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 787 788 789 /* 790 * Log contents to both system messages file and trace buffer 791 */ 792 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 793 FC_TRACE_LOG_MSG) 794 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 795 FC_TRACE_LOG_MSG) 796 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 797 FC_TRACE_LOG_MSG) 798 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 799 FC_TRACE_LOG_MSG) 800 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 801 FC_TRACE_LOG_MSG) 802 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 803 FC_TRACE_LOG_MSG) 804 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 805 FC_TRACE_LOG_MSG) 806 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 807 FC_TRACE_LOG_MSG) 808 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 809 FC_TRACE_LOG_MSG) 810 #ifdef DEBUG 811 #define FCP_DTRACE fc_trace_debug 812 #else 813 #define FCP_DTRACE 814 #endif 815 816 #define FCP_TRACE fc_trace_debug 817 818 static struct cb_ops fcp_cb_ops = { 819 fcp_open, /* open */ 820 fcp_close, /* close */ 821 nodev, /* strategy */ 822 nodev, /* print */ 823 nodev, /* dump */ 824 nodev, /* read */ 825 nodev, /* write */ 826 fcp_ioctl, /* ioctl */ 827 nodev, /* devmap */ 828 nodev, /* mmap */ 829 nodev, /* segmap */ 830 nochpoll, /* chpoll */ 831 ddi_prop_op, /* cb_prop_op */ 832 0, /* streamtab */ 833 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 834 CB_REV, /* rev */ 835 nodev, /* aread */ 836 nodev /* awrite */ 837 }; 838 839 840 static struct dev_ops fcp_ops = { 841 DEVO_REV, 842 0, 843 ddi_getinfo_1to1, 844 nulldev, /* identify */ 845 nulldev, /* probe */ 846 fcp_attach, /* attach and detach are mandatory */ 847 fcp_detach, 848 nodev, /* reset */ 849 &fcp_cb_ops, /* cb_ops */ 850 NULL, /* bus_ops */ 851 NULL, /* power */ 852 }; 853 854 855 char *fcp_version = FCP_NAME_VERSION; 856 857 static struct modldrv modldrv = { 858 &mod_driverops, 859 FCP_NAME_VERSION, 860 &fcp_ops 861 }; 862 863 864 static struct modlinkage modlinkage = { 865 MODREV_1, 866 &modldrv, 867 NULL 868 }; 869 870 871 static fc_ulp_modinfo_t fcp_modinfo = { 872 &fcp_modinfo, /* ulp_handle */ 873 FCTL_ULP_MODREV_4, /* ulp_rev */ 874 FC4_SCSI_FCP, /* ulp_type */ 875 "fcp", /* ulp_name */ 876 FCP_STATEC_MASK, /* ulp_statec_mask */ 877 fcp_port_attach, /* ulp_port_attach */ 878 fcp_port_detach, /* ulp_port_detach */ 879 fcp_port_ioctl, /* ulp_port_ioctl */ 880 fcp_els_callback, /* ulp_els_callback */ 881 fcp_data_callback, /* ulp_data_callback */ 882 fcp_statec_callback /* ulp_statec_callback */ 883 }; 884 885 #ifdef DEBUG 886 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 887 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 888 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 889 FCP_LEVEL_6 | FCP_LEVEL_7) 890 #else 891 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 892 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 893 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 894 FCP_LEVEL_6 | FCP_LEVEL_7) 895 #endif 896 897 /* FCP global variables */ 898 int fcp_bus_config_debug = 0; 899 static int fcp_log_size = FCP_LOG_SIZE; 900 static int fcp_trace = FCP_TRACE_DEFAULT; 901 static fc_trace_logq_t *fcp_logq = NULL; 902 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 903 /* 904 * The auto-configuration is set by default. The only way of disabling it is 905 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 906 */ 907 static int fcp_enable_auto_configuration = 1; 908 static int fcp_max_bus_config_retries = 4; 909 static int fcp_lun_ready_retry = 300; 910 /* 911 * The value assigned to the following variable has changed several times due 912 * to a problem with the data underruns reporting of some firmware(s). The 913 * current value of 50 gives a timeout value of 25 seconds for a max number 914 * of 256 LUNs. 915 */ 916 static int fcp_max_target_retries = 50; 917 /* 918 * Watchdog variables 919 * ------------------ 920 * 921 * fcp_watchdog_init 922 * 923 * Indicates if the watchdog timer is running or not. This is actually 924 * a counter of the number of Fibre Channel ports that attached. When 925 * the first port attaches the watchdog is started. When the last port 926 * detaches the watchdog timer is stopped. 927 * 928 * fcp_watchdog_time 929 * 930 * This is the watchdog clock counter. It is incremented by 931 * fcp_watchdog_time each time the watchdog timer expires. 932 * 933 * fcp_watchdog_timeout 934 * 935 * Increment value of the variable fcp_watchdog_time as well as the 936 * the timeout value of the watchdog timer. The unit is 1 second. It 937 * is strange that this is not a #define but a variable since the code 938 * never changes this value. The reason why it can be said that the 939 * unit is 1 second is because the number of ticks for the watchdog 940 * timer is determined like this: 941 * 942 * fcp_watchdog_tick = fcp_watchdog_timeout * 943 * drv_usectohz(1000000); 944 * 945 * The value 1000000 is hard coded in the code. 946 * 947 * fcp_watchdog_tick 948 * 949 * Watchdog timer value in ticks. 950 */ 951 static int fcp_watchdog_init = 0; 952 static int fcp_watchdog_time = 0; 953 static int fcp_watchdog_timeout = 1; 954 static int fcp_watchdog_tick; 955 956 /* 957 * fcp_offline_delay is a global variable to enable customisation of 958 * the timeout on link offlines or RSCNs. The default value is set 959 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 960 * specified in FCP4 Chapter 11 (see www.t10.org). 961 * 962 * The variable fcp_offline_delay is specified in SECONDS. 963 * 964 * If we made this a static var then the user would not be able to 965 * change it. This variable is set in fcp_attach(). 966 */ 967 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 968 969 static void *fcp_softstate = NULL; /* for soft state */ 970 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 971 static kmutex_t fcp_global_mutex; 972 static kmutex_t fcp_ioctl_mutex; 973 static dev_info_t *fcp_global_dip = NULL; 974 static timeout_id_t fcp_watchdog_id; 975 const char *fcp_lun_prop = "lun"; 976 const char *fcp_sam_lun_prop = "sam-lun"; 977 const char *fcp_target_prop = "target"; 978 /* 979 * NOTE: consumers of "node-wwn" property include stmsboot in ON 980 * consolidation. 981 */ 982 const char *fcp_node_wwn_prop = "node-wwn"; 983 const char *fcp_port_wwn_prop = "port-wwn"; 984 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 985 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 986 const char *fcp_manual_config_only = "manual_configuration_only"; 987 const char *fcp_init_port_prop = "initiator-port"; 988 const char *fcp_tgt_port_prop = "target-port"; 989 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 990 991 static struct fcp_port *fcp_port_head = NULL; 992 static ddi_eventcookie_t fcp_insert_eid; 993 static ddi_eventcookie_t fcp_remove_eid; 994 995 static ndi_event_definition_t fcp_ndi_event_defs[] = { 996 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 997 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 998 }; 999 1000 /* 1001 * List of valid commands for the scsi_ioctl call 1002 */ 1003 static uint8_t scsi_ioctl_list[] = { 1004 SCMD_INQUIRY, 1005 SCMD_REPORT_LUN, 1006 SCMD_READ_CAPACITY 1007 }; 1008 1009 /* 1010 * this is used to dummy up a report lun response for cases 1011 * where the target doesn't support it 1012 */ 1013 static uchar_t fcp_dummy_lun[] = { 1014 0x00, /* MSB length (length = no of luns * 8) */ 1015 0x00, 1016 0x00, 1017 0x08, /* LSB length */ 1018 0x00, /* MSB reserved */ 1019 0x00, 1020 0x00, 1021 0x00, /* LSB reserved */ 1022 FCP_PD_ADDRESSING, 1023 0x00, /* LUN is ZERO at the first level */ 1024 0x00, 1025 0x00, /* second level is zero */ 1026 0x00, 1027 0x00, /* third level is zero */ 1028 0x00, 1029 0x00 /* fourth level is zero */ 1030 }; 1031 1032 static uchar_t fcp_alpa_to_switch[] = { 1033 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1034 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1035 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1036 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1037 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1038 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1039 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1040 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1041 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1042 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1043 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1044 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1045 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1046 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1047 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1048 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1049 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1050 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1051 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1052 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1053 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1054 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1055 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1056 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1057 }; 1058 1059 static caddr_t pid = "SESS01 "; 1060 1061 #if !defined(lint) 1062 1063 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1064 fcp_port::fcp_next fcp_watchdog_id)) 1065 1066 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1067 1068 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1069 fcp_insert_eid 1070 fcp_remove_eid 1071 fcp_watchdog_time)) 1072 1073 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1074 fcp_cb_ops 1075 fcp_ops 1076 callb_cpr)) 1077 1078 #endif /* lint */ 1079 1080 /* 1081 * This table is used to determine whether or not it's safe to copy in 1082 * the target node name for a lun. Since all luns behind the same target 1083 * have the same wwnn, only tagets that do not support multiple luns are 1084 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1085 */ 1086 1087 char *fcp_symmetric_disk_table[] = { 1088 "SEAGATE ST", 1089 "IBM DDYFT", 1090 "SUNW SUNWGS", /* Daktari enclosure */ 1091 "SUN SENA", /* SES device */ 1092 "SUN SESS01" /* VICOM SVE box */ 1093 }; 1094 1095 int fcp_symmetric_disk_table_size = 1096 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1097 1098 /* 1099 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1100 * will panic if you don't pass this in to the routine, this information. 1101 * Need to determine what the actual impact to the system is by providing 1102 * this information if any. Since dma allocation is done in pkt_init it may 1103 * not have any impact. These values are straight from the Writing Device 1104 * Driver manual. 1105 */ 1106 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1107 DMA_ATTR_V0, /* ddi_dma_attr version */ 1108 0, /* low address */ 1109 0xffffffff, /* high address */ 1110 0x00ffffff, /* counter upper bound */ 1111 1, /* alignment requirements */ 1112 0x3f, /* burst sizes */ 1113 1, /* minimum DMA access */ 1114 0xffffffff, /* maximum DMA access */ 1115 (1 << 24) - 1, /* segment boundary restrictions */ 1116 1, /* scater/gather list length */ 1117 512, /* device granularity */ 1118 0 /* DMA flags */ 1119 }; 1120 1121 /* 1122 * The _init(9e) return value should be that of mod_install(9f). Under 1123 * some circumstances, a failure may not be related mod_install(9f) and 1124 * one would then require a return value to indicate the failure. Looking 1125 * at mod_install(9f), it is expected to return 0 for success and non-zero 1126 * for failure. mod_install(9f) for device drivers, further goes down the 1127 * calling chain and ends up in ddi_installdrv(), whose return values are 1128 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1129 * calling chain of mod_install(9f) which return values like EINVAL and 1130 * in some even return -1. 1131 * 1132 * To work around the vagaries of the mod_install() calling chain, return 1133 * either 0 or ENODEV depending on the success or failure of mod_install() 1134 */ 1135 int 1136 _init(void) 1137 { 1138 int rval; 1139 1140 /* 1141 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1142 * before registering with the transport first. 1143 */ 1144 if (ddi_soft_state_init(&fcp_softstate, 1145 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1146 return (EINVAL); 1147 } 1148 1149 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1150 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1151 1152 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1153 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1154 mutex_destroy(&fcp_global_mutex); 1155 mutex_destroy(&fcp_ioctl_mutex); 1156 ddi_soft_state_fini(&fcp_softstate); 1157 return (ENODEV); 1158 } 1159 1160 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1161 1162 if ((rval = mod_install(&modlinkage)) != 0) { 1163 fc_trace_free_logq(fcp_logq); 1164 (void) fc_ulp_remove(&fcp_modinfo); 1165 mutex_destroy(&fcp_global_mutex); 1166 mutex_destroy(&fcp_ioctl_mutex); 1167 ddi_soft_state_fini(&fcp_softstate); 1168 rval = ENODEV; 1169 } 1170 1171 return (rval); 1172 } 1173 1174 1175 /* 1176 * the system is done with us as a driver, so clean up 1177 */ 1178 int 1179 _fini(void) 1180 { 1181 int rval; 1182 1183 /* 1184 * don't start cleaning up until we know that the module remove 1185 * has worked -- if this works, then we know that each instance 1186 * has successfully been DDI_DETACHed 1187 */ 1188 if ((rval = mod_remove(&modlinkage)) != 0) { 1189 return (rval); 1190 } 1191 1192 (void) fc_ulp_remove(&fcp_modinfo); 1193 1194 ddi_soft_state_fini(&fcp_softstate); 1195 mutex_destroy(&fcp_global_mutex); 1196 mutex_destroy(&fcp_ioctl_mutex); 1197 fc_trace_free_logq(fcp_logq); 1198 1199 return (rval); 1200 } 1201 1202 1203 int 1204 _info(struct modinfo *modinfop) 1205 { 1206 return (mod_info(&modlinkage, modinfop)); 1207 } 1208 1209 1210 /* 1211 * attach the module 1212 */ 1213 static int 1214 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1215 { 1216 int rval = DDI_SUCCESS; 1217 1218 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1219 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1220 1221 if (cmd == DDI_ATTACH) { 1222 /* The FCP pseudo device is created here. */ 1223 mutex_enter(&fcp_global_mutex); 1224 fcp_global_dip = devi; 1225 mutex_exit(&fcp_global_mutex); 1226 1227 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1228 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1229 ddi_report_dev(fcp_global_dip); 1230 } else { 1231 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1232 mutex_enter(&fcp_global_mutex); 1233 fcp_global_dip = NULL; 1234 mutex_exit(&fcp_global_mutex); 1235 1236 rval = DDI_FAILURE; 1237 } 1238 /* 1239 * We check the fcp_offline_delay property at this 1240 * point. This variable is global for the driver, 1241 * not specific to an instance. 1242 * 1243 * We do not recommend setting the value to less 1244 * than 10 seconds (RA_TOV_els), or greater than 1245 * 60 seconds. 1246 */ 1247 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1248 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1249 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1250 if ((fcp_offline_delay < 10) || 1251 (fcp_offline_delay > 60)) { 1252 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1253 "to %d second(s). This is outside the " 1254 "recommended range of 10..60 seconds.", 1255 fcp_offline_delay); 1256 } 1257 } 1258 1259 return (rval); 1260 } 1261 1262 1263 /*ARGSUSED*/ 1264 static int 1265 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1266 { 1267 int res = DDI_SUCCESS; 1268 1269 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1270 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1271 1272 if (cmd == DDI_DETACH) { 1273 /* 1274 * Check if there are active ports/threads. If there 1275 * are any, we will fail, else we will succeed (there 1276 * should not be much to clean up) 1277 */ 1278 mutex_enter(&fcp_global_mutex); 1279 FCP_DTRACE(fcp_logq, "fcp", 1280 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1281 (void *) fcp_port_head); 1282 1283 if (fcp_port_head == NULL) { 1284 ddi_remove_minor_node(fcp_global_dip, NULL); 1285 fcp_global_dip = NULL; 1286 mutex_exit(&fcp_global_mutex); 1287 } else { 1288 mutex_exit(&fcp_global_mutex); 1289 res = DDI_FAILURE; 1290 } 1291 } 1292 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1293 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1294 1295 return (res); 1296 } 1297 1298 1299 /* ARGSUSED */ 1300 static int 1301 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1302 { 1303 if (otype != OTYP_CHR) { 1304 return (EINVAL); 1305 } 1306 1307 /* 1308 * Allow only root to talk; 1309 */ 1310 if (drv_priv(credp)) { 1311 return (EPERM); 1312 } 1313 1314 mutex_enter(&fcp_global_mutex); 1315 if (fcp_oflag & FCP_EXCL) { 1316 mutex_exit(&fcp_global_mutex); 1317 return (EBUSY); 1318 } 1319 1320 if (flag & FEXCL) { 1321 if (fcp_oflag & FCP_OPEN) { 1322 mutex_exit(&fcp_global_mutex); 1323 return (EBUSY); 1324 } 1325 fcp_oflag |= FCP_EXCL; 1326 } 1327 fcp_oflag |= FCP_OPEN; 1328 mutex_exit(&fcp_global_mutex); 1329 1330 return (0); 1331 } 1332 1333 1334 /* ARGSUSED */ 1335 static int 1336 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1337 { 1338 if (otype != OTYP_CHR) { 1339 return (EINVAL); 1340 } 1341 1342 mutex_enter(&fcp_global_mutex); 1343 if (!(fcp_oflag & FCP_OPEN)) { 1344 mutex_exit(&fcp_global_mutex); 1345 return (ENODEV); 1346 } 1347 fcp_oflag = FCP_IDLE; 1348 mutex_exit(&fcp_global_mutex); 1349 1350 return (0); 1351 } 1352 1353 1354 /* 1355 * fcp_ioctl 1356 * Entry point for the FCP ioctls 1357 * 1358 * Input: 1359 * See ioctl(9E) 1360 * 1361 * Output: 1362 * See ioctl(9E) 1363 * 1364 * Returns: 1365 * See ioctl(9E) 1366 * 1367 * Context: 1368 * Kernel context. 1369 */ 1370 /* ARGSUSED */ 1371 static int 1372 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1373 int *rval) 1374 { 1375 int ret = 0; 1376 1377 mutex_enter(&fcp_global_mutex); 1378 if (!(fcp_oflag & FCP_OPEN)) { 1379 mutex_exit(&fcp_global_mutex); 1380 return (ENXIO); 1381 } 1382 mutex_exit(&fcp_global_mutex); 1383 1384 switch (cmd) { 1385 case FCP_TGT_INQUIRY: 1386 case FCP_TGT_CREATE: 1387 case FCP_TGT_DELETE: 1388 ret = fcp_setup_device_data_ioctl(cmd, 1389 (struct fcp_ioctl *)data, mode, rval); 1390 break; 1391 1392 case FCP_TGT_SEND_SCSI: 1393 mutex_enter(&fcp_ioctl_mutex); 1394 ret = fcp_setup_scsi_ioctl( 1395 (struct fcp_scsi_cmd *)data, mode, rval); 1396 mutex_exit(&fcp_ioctl_mutex); 1397 break; 1398 1399 case FCP_STATE_COUNT: 1400 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1401 mode, rval); 1402 break; 1403 case FCP_GET_TARGET_MAPPINGS: 1404 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1405 mode, rval); 1406 break; 1407 default: 1408 fcp_log(CE_WARN, NULL, 1409 "!Invalid ioctl opcode = 0x%x", cmd); 1410 ret = EINVAL; 1411 } 1412 1413 return (ret); 1414 } 1415 1416 1417 /* 1418 * fcp_setup_device_data_ioctl 1419 * Setup handler for the "device data" style of 1420 * ioctl for FCP. See "fcp_util.h" for data structure 1421 * definition. 1422 * 1423 * Input: 1424 * cmd = FCP ioctl command 1425 * data = ioctl data 1426 * mode = See ioctl(9E) 1427 * 1428 * Output: 1429 * data = ioctl data 1430 * rval = return value - see ioctl(9E) 1431 * 1432 * Returns: 1433 * See ioctl(9E) 1434 * 1435 * Context: 1436 * Kernel context. 1437 */ 1438 /* ARGSUSED */ 1439 static int 1440 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1441 int *rval) 1442 { 1443 struct fcp_port *pptr; 1444 struct device_data *dev_data; 1445 uint32_t link_cnt; 1446 la_wwn_t *wwn_ptr = NULL; 1447 struct fcp_tgt *ptgt = NULL; 1448 struct fcp_lun *plun = NULL; 1449 int i, error; 1450 struct fcp_ioctl fioctl; 1451 1452 #ifdef _MULTI_DATAMODEL 1453 switch (ddi_model_convert_from(mode & FMODELS)) { 1454 case DDI_MODEL_ILP32: { 1455 struct fcp32_ioctl f32_ioctl; 1456 1457 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1458 sizeof (struct fcp32_ioctl), mode)) { 1459 return (EFAULT); 1460 } 1461 fioctl.fp_minor = f32_ioctl.fp_minor; 1462 fioctl.listlen = f32_ioctl.listlen; 1463 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1464 break; 1465 } 1466 case DDI_MODEL_NONE: 1467 if (ddi_copyin((void *)data, (void *)&fioctl, 1468 sizeof (struct fcp_ioctl), mode)) { 1469 return (EFAULT); 1470 } 1471 break; 1472 } 1473 1474 #else /* _MULTI_DATAMODEL */ 1475 if (ddi_copyin((void *)data, (void *)&fioctl, 1476 sizeof (struct fcp_ioctl), mode)) { 1477 return (EFAULT); 1478 } 1479 #endif /* _MULTI_DATAMODEL */ 1480 1481 /* 1482 * Right now we can assume that the minor number matches with 1483 * this instance of fp. If this changes we will need to 1484 * revisit this logic. 1485 */ 1486 mutex_enter(&fcp_global_mutex); 1487 pptr = fcp_port_head; 1488 while (pptr) { 1489 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1490 break; 1491 } else { 1492 pptr = pptr->port_next; 1493 } 1494 } 1495 mutex_exit(&fcp_global_mutex); 1496 if (pptr == NULL) { 1497 return (ENXIO); 1498 } 1499 mutex_enter(&pptr->port_mutex); 1500 1501 1502 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1503 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1504 mutex_exit(&pptr->port_mutex); 1505 return (ENOMEM); 1506 } 1507 1508 if (ddi_copyin(fioctl.list, dev_data, 1509 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1510 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1511 mutex_exit(&pptr->port_mutex); 1512 return (EFAULT); 1513 } 1514 link_cnt = pptr->port_link_cnt; 1515 1516 if (cmd == FCP_TGT_INQUIRY) { 1517 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1518 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1519 sizeof (wwn_ptr->raw_wwn)) == 0) { 1520 /* This ioctl is requesting INQ info of local HBA */ 1521 mutex_exit(&pptr->port_mutex); 1522 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1523 dev_data[0].dev_status = 0; 1524 if (ddi_copyout(dev_data, fioctl.list, 1525 (sizeof (struct device_data)) * fioctl.listlen, 1526 mode)) { 1527 kmem_free(dev_data, 1528 sizeof (*dev_data) * fioctl.listlen); 1529 return (EFAULT); 1530 } 1531 kmem_free(dev_data, 1532 sizeof (*dev_data) * fioctl.listlen); 1533 #ifdef _MULTI_DATAMODEL 1534 switch (ddi_model_convert_from(mode & FMODELS)) { 1535 case DDI_MODEL_ILP32: { 1536 struct fcp32_ioctl f32_ioctl; 1537 f32_ioctl.fp_minor = fioctl.fp_minor; 1538 f32_ioctl.listlen = fioctl.listlen; 1539 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1540 if (ddi_copyout((void *)&f32_ioctl, 1541 (void *)data, 1542 sizeof (struct fcp32_ioctl), mode)) { 1543 return (EFAULT); 1544 } 1545 break; 1546 } 1547 case DDI_MODEL_NONE: 1548 if (ddi_copyout((void *)&fioctl, (void *)data, 1549 sizeof (struct fcp_ioctl), mode)) { 1550 return (EFAULT); 1551 } 1552 break; 1553 } 1554 #else /* _MULTI_DATAMODEL */ 1555 if (ddi_copyout((void *)&fioctl, (void *)data, 1556 sizeof (struct fcp_ioctl), mode)) { 1557 return (EFAULT); 1558 } 1559 #endif /* _MULTI_DATAMODEL */ 1560 return (0); 1561 } 1562 } 1563 1564 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1565 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1566 mutex_exit(&pptr->port_mutex); 1567 return (ENXIO); 1568 } 1569 1570 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1571 i++) { 1572 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1573 1574 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1575 1576 1577 dev_data[i].dev_status = ENXIO; 1578 1579 if ((ptgt = fcp_lookup_target(pptr, 1580 (uchar_t *)wwn_ptr)) == NULL) { 1581 mutex_exit(&pptr->port_mutex); 1582 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1583 wwn_ptr, &error, 0) == NULL) { 1584 dev_data[i].dev_status = ENODEV; 1585 mutex_enter(&pptr->port_mutex); 1586 continue; 1587 } else { 1588 1589 dev_data[i].dev_status = EAGAIN; 1590 1591 mutex_enter(&pptr->port_mutex); 1592 continue; 1593 } 1594 } else { 1595 mutex_enter(&ptgt->tgt_mutex); 1596 if (ptgt->tgt_state & (FCP_TGT_MARK | 1597 FCP_TGT_BUSY)) { 1598 dev_data[i].dev_status = EAGAIN; 1599 mutex_exit(&ptgt->tgt_mutex); 1600 continue; 1601 } 1602 1603 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1604 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1605 dev_data[i].dev_status = ENOTSUP; 1606 } else { 1607 dev_data[i].dev_status = ENXIO; 1608 } 1609 mutex_exit(&ptgt->tgt_mutex); 1610 continue; 1611 } 1612 1613 switch (cmd) { 1614 case FCP_TGT_INQUIRY: 1615 /* 1616 * The reason we give device type of 1617 * lun 0 only even though in some 1618 * cases(like maxstrat) lun 0 device 1619 * type may be 0x3f(invalid) is that 1620 * for bridge boxes target will appear 1621 * as luns and the first lun could be 1622 * a device that utility may not care 1623 * about (like a tape device). 1624 */ 1625 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1626 dev_data[i].dev_status = 0; 1627 mutex_exit(&ptgt->tgt_mutex); 1628 1629 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1630 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1631 } else { 1632 dev_data[i].dev0_type = plun->lun_type; 1633 } 1634 mutex_enter(&ptgt->tgt_mutex); 1635 break; 1636 1637 case FCP_TGT_CREATE: 1638 mutex_exit(&ptgt->tgt_mutex); 1639 mutex_exit(&pptr->port_mutex); 1640 1641 /* 1642 * serialize state change call backs. 1643 * only one call back will be handled 1644 * at a time. 1645 */ 1646 mutex_enter(&fcp_global_mutex); 1647 if (fcp_oflag & FCP_BUSY) { 1648 mutex_exit(&fcp_global_mutex); 1649 if (dev_data) { 1650 kmem_free(dev_data, 1651 sizeof (*dev_data) * 1652 fioctl.listlen); 1653 } 1654 return (EBUSY); 1655 } 1656 fcp_oflag |= FCP_BUSY; 1657 mutex_exit(&fcp_global_mutex); 1658 1659 dev_data[i].dev_status = 1660 fcp_create_on_demand(pptr, 1661 wwn_ptr->raw_wwn); 1662 1663 if (dev_data[i].dev_status != 0) { 1664 char buf[25]; 1665 1666 for (i = 0; i < FC_WWN_SIZE; i++) { 1667 (void) sprintf(&buf[i << 1], 1668 "%02x", 1669 wwn_ptr->raw_wwn[i]); 1670 } 1671 1672 fcp_log(CE_WARN, pptr->port_dip, 1673 "!Failed to create nodes for" 1674 " pwwn=%s; error=%x", buf, 1675 dev_data[i].dev_status); 1676 } 1677 1678 /* allow state change call backs again */ 1679 mutex_enter(&fcp_global_mutex); 1680 fcp_oflag &= ~FCP_BUSY; 1681 mutex_exit(&fcp_global_mutex); 1682 1683 mutex_enter(&pptr->port_mutex); 1684 mutex_enter(&ptgt->tgt_mutex); 1685 1686 break; 1687 1688 case FCP_TGT_DELETE: 1689 break; 1690 1691 default: 1692 fcp_log(CE_WARN, pptr->port_dip, 1693 "!Invalid device data ioctl " 1694 "opcode = 0x%x", cmd); 1695 } 1696 mutex_exit(&ptgt->tgt_mutex); 1697 } 1698 } 1699 mutex_exit(&pptr->port_mutex); 1700 1701 if (ddi_copyout(dev_data, fioctl.list, 1702 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1703 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1704 return (EFAULT); 1705 } 1706 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1707 1708 #ifdef _MULTI_DATAMODEL 1709 switch (ddi_model_convert_from(mode & FMODELS)) { 1710 case DDI_MODEL_ILP32: { 1711 struct fcp32_ioctl f32_ioctl; 1712 1713 f32_ioctl.fp_minor = fioctl.fp_minor; 1714 f32_ioctl.listlen = fioctl.listlen; 1715 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1716 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1717 sizeof (struct fcp32_ioctl), mode)) { 1718 return (EFAULT); 1719 } 1720 break; 1721 } 1722 case DDI_MODEL_NONE: 1723 if (ddi_copyout((void *)&fioctl, (void *)data, 1724 sizeof (struct fcp_ioctl), mode)) { 1725 return (EFAULT); 1726 } 1727 break; 1728 } 1729 #else /* _MULTI_DATAMODEL */ 1730 1731 if (ddi_copyout((void *)&fioctl, (void *)data, 1732 sizeof (struct fcp_ioctl), mode)) { 1733 return (EFAULT); 1734 } 1735 #endif /* _MULTI_DATAMODEL */ 1736 1737 return (0); 1738 } 1739 1740 /* 1741 * Fetch the target mappings (path, etc.) for all LUNs 1742 * on this port. 1743 */ 1744 /* ARGSUSED */ 1745 static int 1746 fcp_get_target_mappings(struct fcp_ioctl *data, 1747 int mode, int *rval) 1748 { 1749 struct fcp_port *pptr; 1750 fc_hba_target_mappings_t *mappings; 1751 fc_hba_mapping_entry_t *map; 1752 struct fcp_tgt *ptgt = NULL; 1753 struct fcp_lun *plun = NULL; 1754 int i, mapIndex, mappingSize; 1755 int listlen; 1756 struct fcp_ioctl fioctl; 1757 char *path; 1758 fcp_ent_addr_t sam_lun_addr; 1759 1760 #ifdef _MULTI_DATAMODEL 1761 switch (ddi_model_convert_from(mode & FMODELS)) { 1762 case DDI_MODEL_ILP32: { 1763 struct fcp32_ioctl f32_ioctl; 1764 1765 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1766 sizeof (struct fcp32_ioctl), mode)) { 1767 return (EFAULT); 1768 } 1769 fioctl.fp_minor = f32_ioctl.fp_minor; 1770 fioctl.listlen = f32_ioctl.listlen; 1771 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1772 break; 1773 } 1774 case DDI_MODEL_NONE: 1775 if (ddi_copyin((void *)data, (void *)&fioctl, 1776 sizeof (struct fcp_ioctl), mode)) { 1777 return (EFAULT); 1778 } 1779 break; 1780 } 1781 1782 #else /* _MULTI_DATAMODEL */ 1783 if (ddi_copyin((void *)data, (void *)&fioctl, 1784 sizeof (struct fcp_ioctl), mode)) { 1785 return (EFAULT); 1786 } 1787 #endif /* _MULTI_DATAMODEL */ 1788 1789 /* 1790 * Right now we can assume that the minor number matches with 1791 * this instance of fp. If this changes we will need to 1792 * revisit this logic. 1793 */ 1794 mutex_enter(&fcp_global_mutex); 1795 pptr = fcp_port_head; 1796 while (pptr) { 1797 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1798 break; 1799 } else { 1800 pptr = pptr->port_next; 1801 } 1802 } 1803 mutex_exit(&fcp_global_mutex); 1804 if (pptr == NULL) { 1805 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1806 fioctl.fp_minor); 1807 return (ENXIO); 1808 } 1809 1810 1811 /* We use listlen to show the total buffer size */ 1812 mappingSize = fioctl.listlen; 1813 1814 /* Now calculate how many mapping entries will fit */ 1815 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1816 - sizeof (fc_hba_target_mappings_t); 1817 if (listlen <= 0) { 1818 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1819 return (ENXIO); 1820 } 1821 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1822 1823 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1824 return (ENOMEM); 1825 } 1826 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1827 1828 /* Now get to work */ 1829 mapIndex = 0; 1830 1831 mutex_enter(&pptr->port_mutex); 1832 /* Loop through all targets on this port */ 1833 for (i = 0; i < FCP_NUM_HASH; i++) { 1834 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1835 ptgt = ptgt->tgt_next) { 1836 1837 mutex_enter(&ptgt->tgt_mutex); 1838 1839 /* Loop through all LUNs on this target */ 1840 for (plun = ptgt->tgt_lun; plun != NULL; 1841 plun = plun->lun_next) { 1842 if (plun->lun_state & FCP_LUN_OFFLINE) { 1843 continue; 1844 } 1845 1846 path = fcp_get_lun_path(plun); 1847 if (path == NULL) { 1848 continue; 1849 } 1850 1851 if (mapIndex >= listlen) { 1852 mapIndex ++; 1853 kmem_free(path, MAXPATHLEN); 1854 continue; 1855 } 1856 map = &mappings->entries[mapIndex++]; 1857 bcopy(path, map->targetDriver, 1858 sizeof (map->targetDriver)); 1859 map->d_id = ptgt->tgt_d_id; 1860 map->busNumber = 0; 1861 map->targetNumber = ptgt->tgt_d_id; 1862 map->osLUN = plun->lun_num; 1863 1864 /* 1865 * We had swapped lun when we stored it in 1866 * lun_addr. We need to swap it back before 1867 * returning it to user land 1868 */ 1869 1870 sam_lun_addr.ent_addr_0 = 1871 BE_16(plun->lun_addr.ent_addr_0); 1872 sam_lun_addr.ent_addr_1 = 1873 BE_16(plun->lun_addr.ent_addr_1); 1874 sam_lun_addr.ent_addr_2 = 1875 BE_16(plun->lun_addr.ent_addr_2); 1876 sam_lun_addr.ent_addr_3 = 1877 BE_16(plun->lun_addr.ent_addr_3); 1878 1879 bcopy(&sam_lun_addr, &map->samLUN, 1880 FCP_LUN_SIZE); 1881 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1882 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1883 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1884 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1885 1886 if (plun->lun_guid) { 1887 1888 /* convert ascii wwn to bytes */ 1889 fcp_ascii_to_wwn(plun->lun_guid, 1890 map->guid, sizeof (map->guid)); 1891 1892 if ((sizeof (map->guid)) < 1893 plun->lun_guid_size / 2) { 1894 cmn_err(CE_WARN, 1895 "fcp_get_target_mappings:" 1896 "guid copy space " 1897 "insufficient." 1898 "Copy Truncation - " 1899 "available %d; need %d", 1900 (int)sizeof (map->guid), 1901 (int) 1902 plun->lun_guid_size / 2); 1903 } 1904 } 1905 kmem_free(path, MAXPATHLEN); 1906 } 1907 mutex_exit(&ptgt->tgt_mutex); 1908 } 1909 } 1910 mutex_exit(&pptr->port_mutex); 1911 mappings->numLuns = mapIndex; 1912 1913 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1914 kmem_free(mappings, mappingSize); 1915 return (EFAULT); 1916 } 1917 kmem_free(mappings, mappingSize); 1918 1919 #ifdef _MULTI_DATAMODEL 1920 switch (ddi_model_convert_from(mode & FMODELS)) { 1921 case DDI_MODEL_ILP32: { 1922 struct fcp32_ioctl f32_ioctl; 1923 1924 f32_ioctl.fp_minor = fioctl.fp_minor; 1925 f32_ioctl.listlen = fioctl.listlen; 1926 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1927 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1928 sizeof (struct fcp32_ioctl), mode)) { 1929 return (EFAULT); 1930 } 1931 break; 1932 } 1933 case DDI_MODEL_NONE: 1934 if (ddi_copyout((void *)&fioctl, (void *)data, 1935 sizeof (struct fcp_ioctl), mode)) { 1936 return (EFAULT); 1937 } 1938 break; 1939 } 1940 #else /* _MULTI_DATAMODEL */ 1941 1942 if (ddi_copyout((void *)&fioctl, (void *)data, 1943 sizeof (struct fcp_ioctl), mode)) { 1944 return (EFAULT); 1945 } 1946 #endif /* _MULTI_DATAMODEL */ 1947 1948 return (0); 1949 } 1950 1951 /* 1952 * fcp_setup_scsi_ioctl 1953 * Setup handler for the "scsi passthru" style of 1954 * ioctl for FCP. See "fcp_util.h" for data structure 1955 * definition. 1956 * 1957 * Input: 1958 * u_fscsi = ioctl data (user address space) 1959 * mode = See ioctl(9E) 1960 * 1961 * Output: 1962 * u_fscsi = ioctl data (user address space) 1963 * rval = return value - see ioctl(9E) 1964 * 1965 * Returns: 1966 * 0 = OK 1967 * EAGAIN = See errno.h 1968 * EBUSY = See errno.h 1969 * EFAULT = See errno.h 1970 * EINTR = See errno.h 1971 * EINVAL = See errno.h 1972 * EIO = See errno.h 1973 * ENOMEM = See errno.h 1974 * ENXIO = See errno.h 1975 * 1976 * Context: 1977 * Kernel context. 1978 */ 1979 /* ARGSUSED */ 1980 static int 1981 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1982 int mode, int *rval) 1983 { 1984 int ret = 0; 1985 int temp_ret; 1986 caddr_t k_cdbbufaddr = NULL; 1987 caddr_t k_bufaddr = NULL; 1988 caddr_t k_rqbufaddr = NULL; 1989 caddr_t u_cdbbufaddr; 1990 caddr_t u_bufaddr; 1991 caddr_t u_rqbufaddr; 1992 struct fcp_scsi_cmd k_fscsi; 1993 1994 /* 1995 * Get fcp_scsi_cmd array element from user address space 1996 */ 1997 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1998 != 0) { 1999 return (ret); 2000 } 2001 2002 2003 /* 2004 * Even though kmem_alloc() checks the validity of the 2005 * buffer length, this check is needed when the 2006 * kmem_flags set and the zero buffer length is passed. 2007 */ 2008 if ((k_fscsi.scsi_cdblen <= 0) || 2009 (k_fscsi.scsi_buflen <= 0) || 2010 (k_fscsi.scsi_rqlen <= 0)) { 2011 return (EINVAL); 2012 } 2013 2014 /* 2015 * Allocate data for fcp_scsi_cmd pointer fields 2016 */ 2017 if (ret == 0) { 2018 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 2019 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 2020 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 2021 2022 if (k_cdbbufaddr == NULL || 2023 k_bufaddr == NULL || 2024 k_rqbufaddr == NULL) { 2025 ret = ENOMEM; 2026 } 2027 } 2028 2029 /* 2030 * Get fcp_scsi_cmd pointer fields from user 2031 * address space 2032 */ 2033 if (ret == 0) { 2034 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2035 u_bufaddr = k_fscsi.scsi_bufaddr; 2036 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2037 2038 if (ddi_copyin(u_cdbbufaddr, 2039 k_cdbbufaddr, 2040 k_fscsi.scsi_cdblen, 2041 mode)) { 2042 ret = EFAULT; 2043 } else if (ddi_copyin(u_bufaddr, 2044 k_bufaddr, 2045 k_fscsi.scsi_buflen, 2046 mode)) { 2047 ret = EFAULT; 2048 } else if (ddi_copyin(u_rqbufaddr, 2049 k_rqbufaddr, 2050 k_fscsi.scsi_rqlen, 2051 mode)) { 2052 ret = EFAULT; 2053 } 2054 } 2055 2056 /* 2057 * Send scsi command (blocking) 2058 */ 2059 if (ret == 0) { 2060 /* 2061 * Prior to sending the scsi command, the 2062 * fcp_scsi_cmd data structure must contain kernel, 2063 * not user, addresses. 2064 */ 2065 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2066 k_fscsi.scsi_bufaddr = k_bufaddr; 2067 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2068 2069 ret = fcp_send_scsi_ioctl(&k_fscsi); 2070 2071 /* 2072 * After sending the scsi command, the 2073 * fcp_scsi_cmd data structure must contain user, 2074 * not kernel, addresses. 2075 */ 2076 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2077 k_fscsi.scsi_bufaddr = u_bufaddr; 2078 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2079 } 2080 2081 /* 2082 * Put fcp_scsi_cmd pointer fields to user address space 2083 */ 2084 if (ret == 0) { 2085 if (ddi_copyout(k_cdbbufaddr, 2086 u_cdbbufaddr, 2087 k_fscsi.scsi_cdblen, 2088 mode)) { 2089 ret = EFAULT; 2090 } else if (ddi_copyout(k_bufaddr, 2091 u_bufaddr, 2092 k_fscsi.scsi_buflen, 2093 mode)) { 2094 ret = EFAULT; 2095 } else if (ddi_copyout(k_rqbufaddr, 2096 u_rqbufaddr, 2097 k_fscsi.scsi_rqlen, 2098 mode)) { 2099 ret = EFAULT; 2100 } 2101 } 2102 2103 /* 2104 * Free data for fcp_scsi_cmd pointer fields 2105 */ 2106 if (k_cdbbufaddr != NULL) { 2107 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2108 } 2109 if (k_bufaddr != NULL) { 2110 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2111 } 2112 if (k_rqbufaddr != NULL) { 2113 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2114 } 2115 2116 /* 2117 * Put fcp_scsi_cmd array element to user address space 2118 */ 2119 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2120 if (temp_ret != 0) { 2121 ret = temp_ret; 2122 } 2123 2124 /* 2125 * Return status 2126 */ 2127 return (ret); 2128 } 2129 2130 2131 /* 2132 * fcp_copyin_scsi_cmd 2133 * Copy in fcp_scsi_cmd data structure from user address space. 2134 * The data may be in 32 bit or 64 bit modes. 2135 * 2136 * Input: 2137 * base_addr = from address (user address space) 2138 * mode = See ioctl(9E) and ddi_copyin(9F) 2139 * 2140 * Output: 2141 * fscsi = to address (kernel address space) 2142 * 2143 * Returns: 2144 * 0 = OK 2145 * EFAULT = Error 2146 * 2147 * Context: 2148 * Kernel context. 2149 */ 2150 static int 2151 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2152 { 2153 #ifdef _MULTI_DATAMODEL 2154 struct fcp32_scsi_cmd f32scsi; 2155 2156 switch (ddi_model_convert_from(mode & FMODELS)) { 2157 case DDI_MODEL_ILP32: 2158 /* 2159 * Copy data from user address space 2160 */ 2161 if (ddi_copyin((void *)base_addr, 2162 &f32scsi, 2163 sizeof (struct fcp32_scsi_cmd), 2164 mode)) { 2165 return (EFAULT); 2166 } 2167 /* 2168 * Convert from 32 bit to 64 bit 2169 */ 2170 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2171 break; 2172 case DDI_MODEL_NONE: 2173 /* 2174 * Copy data from user address space 2175 */ 2176 if (ddi_copyin((void *)base_addr, 2177 fscsi, 2178 sizeof (struct fcp_scsi_cmd), 2179 mode)) { 2180 return (EFAULT); 2181 } 2182 break; 2183 } 2184 #else /* _MULTI_DATAMODEL */ 2185 /* 2186 * Copy data from user address space 2187 */ 2188 if (ddi_copyin((void *)base_addr, 2189 fscsi, 2190 sizeof (struct fcp_scsi_cmd), 2191 mode)) { 2192 return (EFAULT); 2193 } 2194 #endif /* _MULTI_DATAMODEL */ 2195 2196 return (0); 2197 } 2198 2199 2200 /* 2201 * fcp_copyout_scsi_cmd 2202 * Copy out fcp_scsi_cmd data structure to user address space. 2203 * The data may be in 32 bit or 64 bit modes. 2204 * 2205 * Input: 2206 * fscsi = to address (kernel address space) 2207 * mode = See ioctl(9E) and ddi_copyin(9F) 2208 * 2209 * Output: 2210 * base_addr = from address (user address space) 2211 * 2212 * Returns: 2213 * 0 = OK 2214 * EFAULT = Error 2215 * 2216 * Context: 2217 * Kernel context. 2218 */ 2219 static int 2220 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2221 { 2222 #ifdef _MULTI_DATAMODEL 2223 struct fcp32_scsi_cmd f32scsi; 2224 2225 switch (ddi_model_convert_from(mode & FMODELS)) { 2226 case DDI_MODEL_ILP32: 2227 /* 2228 * Convert from 64 bit to 32 bit 2229 */ 2230 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2231 /* 2232 * Copy data to user address space 2233 */ 2234 if (ddi_copyout(&f32scsi, 2235 (void *)base_addr, 2236 sizeof (struct fcp32_scsi_cmd), 2237 mode)) { 2238 return (EFAULT); 2239 } 2240 break; 2241 case DDI_MODEL_NONE: 2242 /* 2243 * Copy data to user address space 2244 */ 2245 if (ddi_copyout(fscsi, 2246 (void *)base_addr, 2247 sizeof (struct fcp_scsi_cmd), 2248 mode)) { 2249 return (EFAULT); 2250 } 2251 break; 2252 } 2253 #else /* _MULTI_DATAMODEL */ 2254 /* 2255 * Copy data to user address space 2256 */ 2257 if (ddi_copyout(fscsi, 2258 (void *)base_addr, 2259 sizeof (struct fcp_scsi_cmd), 2260 mode)) { 2261 return (EFAULT); 2262 } 2263 #endif /* _MULTI_DATAMODEL */ 2264 2265 return (0); 2266 } 2267 2268 2269 /* 2270 * fcp_send_scsi_ioctl 2271 * Sends the SCSI command in blocking mode. 2272 * 2273 * Input: 2274 * fscsi = SCSI command data structure 2275 * 2276 * Output: 2277 * fscsi = SCSI command data structure 2278 * 2279 * Returns: 2280 * 0 = OK 2281 * EAGAIN = See errno.h 2282 * EBUSY = See errno.h 2283 * EINTR = See errno.h 2284 * EINVAL = See errno.h 2285 * EIO = See errno.h 2286 * ENOMEM = See errno.h 2287 * ENXIO = See errno.h 2288 * 2289 * Context: 2290 * Kernel context. 2291 */ 2292 static int 2293 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2294 { 2295 struct fcp_lun *plun = NULL; 2296 struct fcp_port *pptr = NULL; 2297 struct fcp_tgt *ptgt = NULL; 2298 fc_packet_t *fpkt = NULL; 2299 struct fcp_ipkt *icmd = NULL; 2300 int target_created = FALSE; 2301 fc_frame_hdr_t *hp; 2302 struct fcp_cmd fcp_cmd; 2303 struct fcp_cmd *fcmd; 2304 union scsi_cdb *scsi_cdb; 2305 la_wwn_t *wwn_ptr; 2306 int nodma; 2307 struct fcp_rsp *rsp; 2308 struct fcp_rsp_info *rsp_info; 2309 caddr_t rsp_sense; 2310 int buf_len; 2311 int info_len; 2312 int sense_len; 2313 struct scsi_extended_sense *sense_to = NULL; 2314 timeout_id_t tid; 2315 uint8_t reconfig_lun = FALSE; 2316 uint8_t reconfig_pending = FALSE; 2317 uint8_t scsi_cmd; 2318 int rsp_len; 2319 int cmd_index; 2320 int fc_status; 2321 int pkt_state; 2322 int pkt_action; 2323 int pkt_reason; 2324 int ret, xport_retval = ~FC_SUCCESS; 2325 int lcount; 2326 int tcount; 2327 int reconfig_status; 2328 int port_busy = FALSE; 2329 uchar_t *lun_string; 2330 2331 /* 2332 * Check valid SCSI command 2333 */ 2334 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2335 ret = EINVAL; 2336 for (cmd_index = 0; 2337 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2338 ret != 0; 2339 cmd_index++) { 2340 /* 2341 * First byte of CDB is the SCSI command 2342 */ 2343 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2344 ret = 0; 2345 } 2346 } 2347 2348 /* 2349 * Check inputs 2350 */ 2351 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2352 ret = EINVAL; 2353 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2354 /* no larger than */ 2355 ret = EINVAL; 2356 } 2357 2358 2359 /* 2360 * Find FC port 2361 */ 2362 if (ret == 0) { 2363 /* 2364 * Acquire global mutex 2365 */ 2366 mutex_enter(&fcp_global_mutex); 2367 2368 pptr = fcp_port_head; 2369 while (pptr) { 2370 if (pptr->port_instance == 2371 (uint32_t)fscsi->scsi_fc_port_num) { 2372 break; 2373 } else { 2374 pptr = pptr->port_next; 2375 } 2376 } 2377 2378 if (pptr == NULL) { 2379 ret = ENXIO; 2380 } else { 2381 /* 2382 * fc_ulp_busy_port can raise power 2383 * so, we must not hold any mutexes involved in PM 2384 */ 2385 mutex_exit(&fcp_global_mutex); 2386 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2387 } 2388 2389 if (ret == 0) { 2390 2391 /* remember port is busy, so we will release later */ 2392 port_busy = TRUE; 2393 2394 /* 2395 * If there is a reconfiguration in progress, wait 2396 * for it to complete. 2397 */ 2398 2399 fcp_reconfig_wait(pptr); 2400 2401 /* reacquire mutexes in order */ 2402 mutex_enter(&fcp_global_mutex); 2403 mutex_enter(&pptr->port_mutex); 2404 2405 /* 2406 * Will port accept DMA? 2407 */ 2408 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2409 ? 1 : 0; 2410 2411 /* 2412 * If init or offline, device not known 2413 * 2414 * If we are discovering (onlining), we can 2415 * NOT obviously provide reliable data about 2416 * devices until it is complete 2417 */ 2418 if (pptr->port_state & (FCP_STATE_INIT | 2419 FCP_STATE_OFFLINE)) { 2420 ret = ENXIO; 2421 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2422 ret = EBUSY; 2423 } else { 2424 /* 2425 * Find target from pwwn 2426 * 2427 * The wwn must be put into a local 2428 * variable to ensure alignment. 2429 */ 2430 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2431 ptgt = fcp_lookup_target(pptr, 2432 (uchar_t *)wwn_ptr); 2433 2434 /* 2435 * If target not found, 2436 */ 2437 if (ptgt == NULL) { 2438 /* 2439 * Note: Still have global & 2440 * port mutexes 2441 */ 2442 mutex_exit(&pptr->port_mutex); 2443 ptgt = fcp_port_create_tgt(pptr, 2444 wwn_ptr, &ret, &fc_status, 2445 &pkt_state, &pkt_action, 2446 &pkt_reason); 2447 mutex_enter(&pptr->port_mutex); 2448 2449 fscsi->scsi_fc_status = fc_status; 2450 fscsi->scsi_pkt_state = 2451 (uchar_t)pkt_state; 2452 fscsi->scsi_pkt_reason = pkt_reason; 2453 fscsi->scsi_pkt_action = 2454 (uchar_t)pkt_action; 2455 2456 if (ptgt != NULL) { 2457 target_created = TRUE; 2458 } else if (ret == 0) { 2459 ret = ENOMEM; 2460 } 2461 } 2462 2463 if (ret == 0) { 2464 /* 2465 * Acquire target 2466 */ 2467 mutex_enter(&ptgt->tgt_mutex); 2468 2469 /* 2470 * If target is mark or busy, 2471 * then target can not be used 2472 */ 2473 if (ptgt->tgt_state & 2474 (FCP_TGT_MARK | 2475 FCP_TGT_BUSY)) { 2476 ret = EBUSY; 2477 } else { 2478 /* 2479 * Mark target as busy 2480 */ 2481 ptgt->tgt_state |= 2482 FCP_TGT_BUSY; 2483 } 2484 2485 /* 2486 * Release target 2487 */ 2488 lcount = pptr->port_link_cnt; 2489 tcount = ptgt->tgt_change_cnt; 2490 mutex_exit(&ptgt->tgt_mutex); 2491 } 2492 } 2493 2494 /* 2495 * Release port 2496 */ 2497 mutex_exit(&pptr->port_mutex); 2498 } 2499 2500 /* 2501 * Release global mutex 2502 */ 2503 mutex_exit(&fcp_global_mutex); 2504 } 2505 2506 if (ret == 0) { 2507 uint64_t belun = BE_64(fscsi->scsi_lun); 2508 2509 /* 2510 * If it's a target device, find lun from pwwn 2511 * The wwn must be put into a local 2512 * variable to ensure alignment. 2513 */ 2514 mutex_enter(&pptr->port_mutex); 2515 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2516 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2517 /* this is not a target */ 2518 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2519 ret = ENXIO; 2520 } else if ((belun << 16) != 0) { 2521 /* 2522 * Since fcp only support PD and LU addressing method 2523 * so far, the last 6 bytes of a valid LUN are expected 2524 * to be filled with 00h. 2525 */ 2526 fscsi->scsi_fc_status = FC_INVALID_LUN; 2527 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2528 " method 0x%02x with LUN number 0x%016" PRIx64, 2529 (uint8_t)(belun >> 62), belun); 2530 ret = ENXIO; 2531 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2532 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2533 /* 2534 * This is a SCSI target, but no LUN at this 2535 * address. 2536 * 2537 * In the future, we may want to send this to 2538 * the target, and let it respond 2539 * appropriately 2540 */ 2541 ret = ENXIO; 2542 } 2543 mutex_exit(&pptr->port_mutex); 2544 } 2545 2546 /* 2547 * Finished grabbing external resources 2548 * Allocate internal packet (icmd) 2549 */ 2550 if (ret == 0) { 2551 /* 2552 * Calc rsp len assuming rsp info included 2553 */ 2554 rsp_len = sizeof (struct fcp_rsp) + 2555 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2556 2557 icmd = fcp_icmd_alloc(pptr, ptgt, 2558 sizeof (struct fcp_cmd), 2559 rsp_len, 2560 fscsi->scsi_buflen, 2561 nodma, 2562 lcount, /* ipkt_link_cnt */ 2563 tcount, /* ipkt_change_cnt */ 2564 0, /* cause */ 2565 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2566 2567 if (icmd == NULL) { 2568 ret = ENOMEM; 2569 } else { 2570 /* 2571 * Setup internal packet as sema sync 2572 */ 2573 fcp_ipkt_sema_init(icmd); 2574 } 2575 } 2576 2577 if (ret == 0) { 2578 /* 2579 * Init fpkt pointer for use. 2580 */ 2581 2582 fpkt = icmd->ipkt_fpkt; 2583 2584 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2585 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2586 fpkt->pkt_timeout = fscsi->scsi_timeout; 2587 2588 /* 2589 * Init fcmd pointer for use by SCSI command 2590 */ 2591 2592 if (nodma) { 2593 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2594 } else { 2595 fcmd = &fcp_cmd; 2596 } 2597 bzero(fcmd, sizeof (struct fcp_cmd)); 2598 ptgt = plun->lun_tgt; 2599 2600 lun_string = (uchar_t *)&fscsi->scsi_lun; 2601 2602 fcmd->fcp_ent_addr.ent_addr_0 = 2603 BE_16(*(uint16_t *)&(lun_string[0])); 2604 fcmd->fcp_ent_addr.ent_addr_1 = 2605 BE_16(*(uint16_t *)&(lun_string[2])); 2606 fcmd->fcp_ent_addr.ent_addr_2 = 2607 BE_16(*(uint16_t *)&(lun_string[4])); 2608 fcmd->fcp_ent_addr.ent_addr_3 = 2609 BE_16(*(uint16_t *)&(lun_string[6])); 2610 2611 /* 2612 * Setup internal packet(icmd) 2613 */ 2614 icmd->ipkt_lun = plun; 2615 icmd->ipkt_restart = 0; 2616 icmd->ipkt_retries = 0; 2617 icmd->ipkt_opcode = 0; 2618 2619 /* 2620 * Init the frame HEADER Pointer for use 2621 */ 2622 hp = &fpkt->pkt_cmd_fhdr; 2623 2624 hp->s_id = pptr->port_id; 2625 hp->d_id = ptgt->tgt_d_id; 2626 hp->r_ctl = R_CTL_COMMAND; 2627 hp->type = FC_TYPE_SCSI_FCP; 2628 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2629 hp->rsvd = 0; 2630 hp->seq_id = 0; 2631 hp->seq_cnt = 0; 2632 hp->ox_id = 0xffff; 2633 hp->rx_id = 0xffff; 2634 hp->ro = 0; 2635 2636 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2637 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2638 fcmd->fcp_cntl.cntl_write_data = 0; 2639 fcmd->fcp_data_len = fscsi->scsi_buflen; 2640 2641 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2642 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2643 fscsi->scsi_cdblen); 2644 2645 if (!nodma) { 2646 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2647 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2648 } 2649 2650 /* 2651 * Send SCSI command to FC transport 2652 */ 2653 2654 if (ret == 0) { 2655 mutex_enter(&ptgt->tgt_mutex); 2656 2657 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2658 mutex_exit(&ptgt->tgt_mutex); 2659 fscsi->scsi_fc_status = xport_retval = 2660 fc_ulp_transport(pptr->port_fp_handle, 2661 fpkt); 2662 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2663 ret = EIO; 2664 } 2665 } else { 2666 mutex_exit(&ptgt->tgt_mutex); 2667 ret = EBUSY; 2668 } 2669 } 2670 } 2671 2672 /* 2673 * Wait for completion only if fc_ulp_transport was called and it 2674 * returned a success. This is the only time callback will happen. 2675 * Otherwise, there is no point in waiting 2676 */ 2677 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2678 ret = fcp_ipkt_sema_wait(icmd); 2679 } 2680 2681 /* 2682 * Copy data to IOCTL data structures 2683 */ 2684 rsp = NULL; 2685 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2686 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2687 2688 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2689 fcp_log(CE_WARN, pptr->port_dip, 2690 "!SCSI command to d_id=0x%x lun=0x%x" 2691 " failed, Bad FCP response values:" 2692 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2693 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2694 ptgt->tgt_d_id, plun->lun_num, 2695 rsp->reserved_0, rsp->reserved_1, 2696 rsp->fcp_u.fcp_status.reserved_0, 2697 rsp->fcp_u.fcp_status.reserved_1, 2698 rsp->fcp_response_len, rsp->fcp_sense_len); 2699 2700 ret = EIO; 2701 } 2702 } 2703 2704 if ((ret == 0) && (rsp != NULL)) { 2705 /* 2706 * Calc response lengths 2707 */ 2708 sense_len = 0; 2709 info_len = 0; 2710 2711 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2712 info_len = rsp->fcp_response_len; 2713 } 2714 2715 rsp_info = (struct fcp_rsp_info *) 2716 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2717 2718 /* 2719 * Get SCSI status 2720 */ 2721 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2722 /* 2723 * If a lun was just added or removed and the next command 2724 * comes through this interface, we need to capture the check 2725 * condition so we can discover the new topology. 2726 */ 2727 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2728 rsp->fcp_u.fcp_status.sense_len_set) { 2729 sense_len = rsp->fcp_sense_len; 2730 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2731 sense_to = (struct scsi_extended_sense *)rsp_sense; 2732 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2733 (FCP_SENSE_NO_LUN(sense_to))) { 2734 reconfig_lun = TRUE; 2735 } 2736 } 2737 2738 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2739 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2740 if (reconfig_lun == FALSE) { 2741 reconfig_status = 2742 fcp_is_reconfig_needed(ptgt, fpkt); 2743 } 2744 2745 if ((reconfig_lun == TRUE) || 2746 (reconfig_status == TRUE)) { 2747 mutex_enter(&ptgt->tgt_mutex); 2748 if (ptgt->tgt_tid == NULL) { 2749 /* 2750 * Either we've been notified the 2751 * REPORT_LUN data has changed, or 2752 * we've determined on our own that 2753 * we're out of date. Kick off 2754 * rediscovery. 2755 */ 2756 tid = timeout(fcp_reconfigure_luns, 2757 (caddr_t)ptgt, drv_usectohz(1)); 2758 2759 ptgt->tgt_tid = tid; 2760 ptgt->tgt_state |= FCP_TGT_BUSY; 2761 ret = EBUSY; 2762 reconfig_pending = TRUE; 2763 } 2764 mutex_exit(&ptgt->tgt_mutex); 2765 } 2766 } 2767 2768 /* 2769 * Calc residuals and buffer lengths 2770 */ 2771 2772 if (ret == 0) { 2773 buf_len = fscsi->scsi_buflen; 2774 fscsi->scsi_bufresid = 0; 2775 if (rsp->fcp_u.fcp_status.resid_under) { 2776 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2777 fscsi->scsi_bufresid = rsp->fcp_resid; 2778 } else { 2779 cmn_err(CE_WARN, "fcp: bad residue %x " 2780 "for txfer len %x", rsp->fcp_resid, 2781 fscsi->scsi_buflen); 2782 fscsi->scsi_bufresid = 2783 fscsi->scsi_buflen; 2784 } 2785 buf_len -= fscsi->scsi_bufresid; 2786 } 2787 if (rsp->fcp_u.fcp_status.resid_over) { 2788 fscsi->scsi_bufresid = -rsp->fcp_resid; 2789 } 2790 2791 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2792 if (fscsi->scsi_rqlen < sense_len) { 2793 sense_len = fscsi->scsi_rqlen; 2794 } 2795 2796 fscsi->scsi_fc_rspcode = 0; 2797 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2798 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2799 } 2800 fscsi->scsi_pkt_state = fpkt->pkt_state; 2801 fscsi->scsi_pkt_action = fpkt->pkt_action; 2802 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2803 2804 /* 2805 * Copy data and request sense 2806 * 2807 * Data must be copied by using the FCP_CP_IN macro. 2808 * This will ensure the proper byte order since the data 2809 * is being copied directly from the memory mapped 2810 * device register. 2811 * 2812 * The response (and request sense) will be in the 2813 * correct byte order. No special copy is necessary. 2814 */ 2815 2816 if (buf_len) { 2817 FCP_CP_IN(fpkt->pkt_data, 2818 fscsi->scsi_bufaddr, 2819 fpkt->pkt_data_acc, 2820 buf_len); 2821 } 2822 bcopy((void *)rsp_sense, 2823 (void *)fscsi->scsi_rqbufaddr, 2824 sense_len); 2825 } 2826 } 2827 2828 /* 2829 * Cleanup transport data structures if icmd was alloc-ed 2830 * So, cleanup happens in the same thread that icmd was alloc-ed 2831 */ 2832 if (icmd != NULL) { 2833 fcp_ipkt_sema_cleanup(icmd); 2834 } 2835 2836 /* restore pm busy/idle status */ 2837 if (port_busy) { 2838 fc_ulp_idle_port(pptr->port_fp_handle); 2839 } 2840 2841 /* 2842 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2843 * flag, it'll be cleared when the reconfig is complete. 2844 */ 2845 if ((ptgt != NULL) && !reconfig_pending) { 2846 /* 2847 * If target was created, 2848 */ 2849 if (target_created) { 2850 mutex_enter(&ptgt->tgt_mutex); 2851 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2852 mutex_exit(&ptgt->tgt_mutex); 2853 } else { 2854 /* 2855 * De-mark target as busy 2856 */ 2857 mutex_enter(&ptgt->tgt_mutex); 2858 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2859 mutex_exit(&ptgt->tgt_mutex); 2860 } 2861 } 2862 return (ret); 2863 } 2864 2865 2866 static int 2867 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2868 fc_packet_t *fpkt) 2869 { 2870 uchar_t *lun_string; 2871 uint16_t lun_num, i; 2872 int num_luns; 2873 int actual_luns; 2874 int num_masked_luns; 2875 int lun_buflen; 2876 struct fcp_lun *plun = NULL; 2877 struct fcp_reportlun_resp *report_lun; 2878 uint8_t reconfig_needed = FALSE; 2879 uint8_t lun_exists = FALSE; 2880 fcp_port_t *pptr = ptgt->tgt_port; 2881 2882 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2883 2884 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2885 fpkt->pkt_datalen); 2886 2887 /* get number of luns (which is supplied as LUNS * 8) */ 2888 num_luns = BE_32(report_lun->num_lun) >> 3; 2889 2890 /* 2891 * Figure out exactly how many lun strings our response buffer 2892 * can hold. 2893 */ 2894 lun_buflen = (fpkt->pkt_datalen - 2895 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2896 2897 /* 2898 * Is our response buffer full or not? We don't want to 2899 * potentially walk beyond the number of luns we have. 2900 */ 2901 if (num_luns <= lun_buflen) { 2902 actual_luns = num_luns; 2903 } else { 2904 actual_luns = lun_buflen; 2905 } 2906 2907 mutex_enter(&ptgt->tgt_mutex); 2908 2909 /* Scan each lun to see if we have masked it. */ 2910 num_masked_luns = 0; 2911 if (fcp_lun_blacklist != NULL) { 2912 for (i = 0; i < actual_luns; i++) { 2913 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2914 switch (lun_string[0] & 0xC0) { 2915 case FCP_LUN_ADDRESSING: 2916 case FCP_PD_ADDRESSING: 2917 case FCP_VOLUME_ADDRESSING: 2918 lun_num = ((lun_string[0] & 0x3F) << 8) 2919 | lun_string[1]; 2920 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2921 lun_num) == TRUE) { 2922 num_masked_luns++; 2923 } 2924 break; 2925 default: 2926 break; 2927 } 2928 } 2929 } 2930 2931 /* 2932 * The quick and easy check. If the number of LUNs reported 2933 * doesn't match the number we currently know about, we need 2934 * to reconfigure. 2935 */ 2936 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2937 mutex_exit(&ptgt->tgt_mutex); 2938 kmem_free(report_lun, fpkt->pkt_datalen); 2939 return (TRUE); 2940 } 2941 2942 /* 2943 * If the quick and easy check doesn't turn up anything, we walk 2944 * the list of luns from the REPORT_LUN response and look for 2945 * any luns we don't know about. If we find one, we know we need 2946 * to reconfigure. We will skip LUNs that are masked because of the 2947 * blacklist. 2948 */ 2949 for (i = 0; i < actual_luns; i++) { 2950 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2951 lun_exists = FALSE; 2952 switch (lun_string[0] & 0xC0) { 2953 case FCP_LUN_ADDRESSING: 2954 case FCP_PD_ADDRESSING: 2955 case FCP_VOLUME_ADDRESSING: 2956 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2957 2958 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2959 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2960 lun_exists = TRUE; 2961 break; 2962 } 2963 2964 for (plun = ptgt->tgt_lun; plun; 2965 plun = plun->lun_next) { 2966 if (plun->lun_num == lun_num) { 2967 lun_exists = TRUE; 2968 break; 2969 } 2970 } 2971 break; 2972 default: 2973 break; 2974 } 2975 2976 if (lun_exists == FALSE) { 2977 reconfig_needed = TRUE; 2978 break; 2979 } 2980 } 2981 2982 mutex_exit(&ptgt->tgt_mutex); 2983 kmem_free(report_lun, fpkt->pkt_datalen); 2984 2985 return (reconfig_needed); 2986 } 2987 2988 /* 2989 * This function is called by fcp_handle_page83 and uses inquiry response data 2990 * stored in plun->lun_inq to determine whether or not a device is a member of 2991 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2992 * otherwise 1. 2993 */ 2994 static int 2995 fcp_symmetric_device_probe(struct fcp_lun *plun) 2996 { 2997 struct scsi_inquiry *stdinq = &plun->lun_inq; 2998 char *devidptr; 2999 int i, len; 3000 3001 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 3002 devidptr = fcp_symmetric_disk_table[i]; 3003 len = (int)strlen(devidptr); 3004 3005 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 3006 return (0); 3007 } 3008 } 3009 return (1); 3010 } 3011 3012 3013 /* 3014 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 3015 * It basically returns the current count of # of state change callbacks 3016 * i.e the value of tgt_change_cnt. 3017 * 3018 * INPUT: 3019 * fcp_ioctl.fp_minor -> The minor # of the fp port 3020 * fcp_ioctl.listlen -> 1 3021 * fcp_ioctl.list -> Pointer to a 32 bit integer 3022 */ 3023 /*ARGSUSED2*/ 3024 static int 3025 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3026 { 3027 int ret; 3028 uint32_t link_cnt; 3029 struct fcp_ioctl fioctl; 3030 struct fcp_port *pptr = NULL; 3031 3032 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3033 &pptr)) != 0) { 3034 return (ret); 3035 } 3036 3037 ASSERT(pptr != NULL); 3038 3039 if (fioctl.listlen != 1) { 3040 return (EINVAL); 3041 } 3042 3043 mutex_enter(&pptr->port_mutex); 3044 if (pptr->port_state & FCP_STATE_OFFLINE) { 3045 mutex_exit(&pptr->port_mutex); 3046 return (ENXIO); 3047 } 3048 3049 /* 3050 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3051 * When the fcp initially attaches to the port and there are nothing 3052 * hanging out of the port or if there was a repeat offline state change 3053 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3054 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3055 * will differentiate the 2 cases. 3056 */ 3057 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3058 mutex_exit(&pptr->port_mutex); 3059 return (ENXIO); 3060 } 3061 3062 link_cnt = pptr->port_link_cnt; 3063 mutex_exit(&pptr->port_mutex); 3064 3065 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3066 return (EFAULT); 3067 } 3068 3069 #ifdef _MULTI_DATAMODEL 3070 switch (ddi_model_convert_from(mode & FMODELS)) { 3071 case DDI_MODEL_ILP32: { 3072 struct fcp32_ioctl f32_ioctl; 3073 3074 f32_ioctl.fp_minor = fioctl.fp_minor; 3075 f32_ioctl.listlen = fioctl.listlen; 3076 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3077 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3078 sizeof (struct fcp32_ioctl), mode)) { 3079 return (EFAULT); 3080 } 3081 break; 3082 } 3083 case DDI_MODEL_NONE: 3084 if (ddi_copyout((void *)&fioctl, (void *)data, 3085 sizeof (struct fcp_ioctl), mode)) { 3086 return (EFAULT); 3087 } 3088 break; 3089 } 3090 #else /* _MULTI_DATAMODEL */ 3091 3092 if (ddi_copyout((void *)&fioctl, (void *)data, 3093 sizeof (struct fcp_ioctl), mode)) { 3094 return (EFAULT); 3095 } 3096 #endif /* _MULTI_DATAMODEL */ 3097 3098 return (0); 3099 } 3100 3101 /* 3102 * This function copies the fcp_ioctl structure passed in from user land 3103 * into kernel land. Handles 32 bit applications. 3104 */ 3105 /*ARGSUSED*/ 3106 static int 3107 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3108 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3109 { 3110 struct fcp_port *t_pptr; 3111 3112 #ifdef _MULTI_DATAMODEL 3113 switch (ddi_model_convert_from(mode & FMODELS)) { 3114 case DDI_MODEL_ILP32: { 3115 struct fcp32_ioctl f32_ioctl; 3116 3117 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3118 sizeof (struct fcp32_ioctl), mode)) { 3119 return (EFAULT); 3120 } 3121 fioctl->fp_minor = f32_ioctl.fp_minor; 3122 fioctl->listlen = f32_ioctl.listlen; 3123 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3124 break; 3125 } 3126 case DDI_MODEL_NONE: 3127 if (ddi_copyin((void *)data, (void *)fioctl, 3128 sizeof (struct fcp_ioctl), mode)) { 3129 return (EFAULT); 3130 } 3131 break; 3132 } 3133 3134 #else /* _MULTI_DATAMODEL */ 3135 if (ddi_copyin((void *)data, (void *)fioctl, 3136 sizeof (struct fcp_ioctl), mode)) { 3137 return (EFAULT); 3138 } 3139 #endif /* _MULTI_DATAMODEL */ 3140 3141 /* 3142 * Right now we can assume that the minor number matches with 3143 * this instance of fp. If this changes we will need to 3144 * revisit this logic. 3145 */ 3146 mutex_enter(&fcp_global_mutex); 3147 t_pptr = fcp_port_head; 3148 while (t_pptr) { 3149 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3150 break; 3151 } else { 3152 t_pptr = t_pptr->port_next; 3153 } 3154 } 3155 *pptr = t_pptr; 3156 mutex_exit(&fcp_global_mutex); 3157 if (t_pptr == NULL) { 3158 return (ENXIO); 3159 } 3160 3161 return (0); 3162 } 3163 3164 /* 3165 * Function: fcp_port_create_tgt 3166 * 3167 * Description: As the name suggest this function creates the target context 3168 * specified by the the WWN provided by the caller. If the 3169 * creation goes well and the target is known by fp/fctl a PLOGI 3170 * followed by a PRLI are issued. 3171 * 3172 * Argument: pptr fcp port structure 3173 * pwwn WWN of the target 3174 * ret_val Address of the return code. It could be: 3175 * EIO, ENOMEM or 0. 3176 * fc_status PLOGI or PRLI status completion 3177 * fc_pkt_state PLOGI or PRLI state completion 3178 * fc_pkt_reason PLOGI or PRLI reason completion 3179 * fc_pkt_action PLOGI or PRLI action completion 3180 * 3181 * Return Value: NULL if it failed 3182 * Target structure address if it succeeds 3183 */ 3184 static struct fcp_tgt * 3185 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3186 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3187 { 3188 struct fcp_tgt *ptgt = NULL; 3189 fc_portmap_t devlist; 3190 int lcount; 3191 int error; 3192 3193 *ret_val = 0; 3194 3195 /* 3196 * Check FC port device & get port map 3197 */ 3198 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3199 &error, 1) == NULL) { 3200 *ret_val = EIO; 3201 } else { 3202 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3203 &devlist) != FC_SUCCESS) { 3204 *ret_val = EIO; 3205 } 3206 } 3207 3208 /* Set port map flags */ 3209 devlist.map_type = PORT_DEVICE_USER_CREATE; 3210 3211 /* Allocate target */ 3212 if (*ret_val == 0) { 3213 lcount = pptr->port_link_cnt; 3214 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3215 if (ptgt == NULL) { 3216 fcp_log(CE_WARN, pptr->port_dip, 3217 "!FC target allocation failed"); 3218 *ret_val = ENOMEM; 3219 } else { 3220 /* Setup target */ 3221 mutex_enter(&ptgt->tgt_mutex); 3222 3223 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3224 ptgt->tgt_tmp_cnt = 1; 3225 ptgt->tgt_d_id = devlist.map_did.port_id; 3226 ptgt->tgt_hard_addr = 3227 devlist.map_hard_addr.hard_addr; 3228 ptgt->tgt_pd_handle = devlist.map_pd; 3229 ptgt->tgt_fca_dev = NULL; 3230 3231 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3232 FC_WWN_SIZE); 3233 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3234 FC_WWN_SIZE); 3235 3236 mutex_exit(&ptgt->tgt_mutex); 3237 } 3238 } 3239 3240 /* Release global mutex for PLOGI and PRLI */ 3241 mutex_exit(&fcp_global_mutex); 3242 3243 /* Send PLOGI (If necessary) */ 3244 if (*ret_val == 0) { 3245 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3246 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3247 } 3248 3249 /* Send PRLI (If necessary) */ 3250 if (*ret_val == 0) { 3251 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3252 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3253 } 3254 3255 mutex_enter(&fcp_global_mutex); 3256 3257 return (ptgt); 3258 } 3259 3260 /* 3261 * Function: fcp_tgt_send_plogi 3262 * 3263 * Description: This function sends a PLOGI to the target specified by the 3264 * caller and waits till it completes. 3265 * 3266 * Argument: ptgt Target to send the plogi to. 3267 * fc_status Status returned by fp/fctl in the PLOGI request. 3268 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3269 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3270 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3271 * 3272 * Return Value: 0 3273 * ENOMEM 3274 * EIO 3275 * 3276 * Context: User context. 3277 */ 3278 static int 3279 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3280 int *fc_pkt_reason, int *fc_pkt_action) 3281 { 3282 struct fcp_port *pptr; 3283 struct fcp_ipkt *icmd; 3284 struct fc_packet *fpkt; 3285 fc_frame_hdr_t *hp; 3286 struct la_els_logi logi; 3287 int tcount; 3288 int lcount; 3289 int ret, login_retval = ~FC_SUCCESS; 3290 3291 ret = 0; 3292 3293 pptr = ptgt->tgt_port; 3294 3295 lcount = pptr->port_link_cnt; 3296 tcount = ptgt->tgt_change_cnt; 3297 3298 /* Alloc internal packet */ 3299 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3300 sizeof (la_els_logi_t), 0, 3301 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3302 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3303 3304 if (icmd == NULL) { 3305 ret = ENOMEM; 3306 } else { 3307 /* 3308 * Setup internal packet as sema sync 3309 */ 3310 fcp_ipkt_sema_init(icmd); 3311 3312 /* 3313 * Setup internal packet (icmd) 3314 */ 3315 icmd->ipkt_lun = NULL; 3316 icmd->ipkt_restart = 0; 3317 icmd->ipkt_retries = 0; 3318 icmd->ipkt_opcode = LA_ELS_PLOGI; 3319 3320 /* 3321 * Setup fc_packet 3322 */ 3323 fpkt = icmd->ipkt_fpkt; 3324 3325 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3326 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3327 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3328 3329 /* 3330 * Setup FC frame header 3331 */ 3332 hp = &fpkt->pkt_cmd_fhdr; 3333 3334 hp->s_id = pptr->port_id; /* source ID */ 3335 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3336 hp->r_ctl = R_CTL_ELS_REQ; 3337 hp->type = FC_TYPE_EXTENDED_LS; 3338 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3339 hp->seq_id = 0; 3340 hp->rsvd = 0; 3341 hp->df_ctl = 0; 3342 hp->seq_cnt = 0; 3343 hp->ox_id = 0xffff; /* i.e. none */ 3344 hp->rx_id = 0xffff; /* i.e. none */ 3345 hp->ro = 0; 3346 3347 /* 3348 * Setup PLOGI 3349 */ 3350 bzero(&logi, sizeof (struct la_els_logi)); 3351 logi.ls_code.ls_code = LA_ELS_PLOGI; 3352 3353 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3354 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3355 3356 /* 3357 * Send PLOGI 3358 */ 3359 *fc_status = login_retval = 3360 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3361 if (*fc_status != FC_SUCCESS) { 3362 ret = EIO; 3363 } 3364 } 3365 3366 /* 3367 * Wait for completion 3368 */ 3369 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3370 ret = fcp_ipkt_sema_wait(icmd); 3371 3372 *fc_pkt_state = fpkt->pkt_state; 3373 *fc_pkt_reason = fpkt->pkt_reason; 3374 *fc_pkt_action = fpkt->pkt_action; 3375 } 3376 3377 /* 3378 * Cleanup transport data structures if icmd was alloc-ed AND if there 3379 * is going to be no callback (i.e if fc_ulp_login() failed). 3380 * Otherwise, cleanup happens in callback routine. 3381 */ 3382 if (icmd != NULL) { 3383 fcp_ipkt_sema_cleanup(icmd); 3384 } 3385 3386 return (ret); 3387 } 3388 3389 /* 3390 * Function: fcp_tgt_send_prli 3391 * 3392 * Description: Does nothing as of today. 3393 * 3394 * Argument: ptgt Target to send the prli to. 3395 * fc_status Status returned by fp/fctl in the PRLI request. 3396 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3397 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3398 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3399 * 3400 * Return Value: 0 3401 */ 3402 /*ARGSUSED*/ 3403 static int 3404 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3405 int *fc_pkt_reason, int *fc_pkt_action) 3406 { 3407 return (0); 3408 } 3409 3410 /* 3411 * Function: fcp_ipkt_sema_init 3412 * 3413 * Description: Initializes the semaphore contained in the internal packet. 3414 * 3415 * Argument: icmd Internal packet the semaphore of which must be 3416 * initialized. 3417 * 3418 * Return Value: None 3419 * 3420 * Context: User context only. 3421 */ 3422 static void 3423 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3424 { 3425 struct fc_packet *fpkt; 3426 3427 fpkt = icmd->ipkt_fpkt; 3428 3429 /* Create semaphore for sync */ 3430 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3431 3432 /* Setup the completion callback */ 3433 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3434 } 3435 3436 /* 3437 * Function: fcp_ipkt_sema_wait 3438 * 3439 * Description: Wait on the semaphore embedded in the internal packet. The 3440 * semaphore is released in the callback. 3441 * 3442 * Argument: icmd Internal packet to wait on for completion. 3443 * 3444 * Return Value: 0 3445 * EIO 3446 * EBUSY 3447 * EAGAIN 3448 * 3449 * Context: User context only. 3450 * 3451 * This function does a conversion between the field pkt_state of the fc_packet 3452 * embedded in the internal packet (icmd) and the code it returns. 3453 */ 3454 static int 3455 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3456 { 3457 struct fc_packet *fpkt; 3458 int ret; 3459 3460 ret = EIO; 3461 fpkt = icmd->ipkt_fpkt; 3462 3463 /* 3464 * Wait on semaphore 3465 */ 3466 sema_p(&(icmd->ipkt_sema)); 3467 3468 /* 3469 * Check the status of the FC packet 3470 */ 3471 switch (fpkt->pkt_state) { 3472 case FC_PKT_SUCCESS: 3473 ret = 0; 3474 break; 3475 case FC_PKT_LOCAL_RJT: 3476 switch (fpkt->pkt_reason) { 3477 case FC_REASON_SEQ_TIMEOUT: 3478 case FC_REASON_RX_BUF_TIMEOUT: 3479 ret = EAGAIN; 3480 break; 3481 case FC_REASON_PKT_BUSY: 3482 ret = EBUSY; 3483 break; 3484 } 3485 break; 3486 case FC_PKT_TIMEOUT: 3487 ret = EAGAIN; 3488 break; 3489 case FC_PKT_LOCAL_BSY: 3490 case FC_PKT_TRAN_BSY: 3491 case FC_PKT_NPORT_BSY: 3492 case FC_PKT_FABRIC_BSY: 3493 ret = EBUSY; 3494 break; 3495 case FC_PKT_LS_RJT: 3496 case FC_PKT_BA_RJT: 3497 switch (fpkt->pkt_reason) { 3498 case FC_REASON_LOGICAL_BSY: 3499 ret = EBUSY; 3500 break; 3501 } 3502 break; 3503 case FC_PKT_FS_RJT: 3504 switch (fpkt->pkt_reason) { 3505 case FC_REASON_FS_LOGICAL_BUSY: 3506 ret = EBUSY; 3507 break; 3508 } 3509 break; 3510 } 3511 3512 return (ret); 3513 } 3514 3515 /* 3516 * Function: fcp_ipkt_sema_callback 3517 * 3518 * Description: Registered as the completion callback function for the FC 3519 * transport when the ipkt semaphore is used for sync. This will 3520 * cleanup the used data structures, if necessary and wake up 3521 * the user thread to complete the transaction. 3522 * 3523 * Argument: fpkt FC packet (points to the icmd) 3524 * 3525 * Return Value: None 3526 * 3527 * Context: User context only 3528 */ 3529 static void 3530 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3531 { 3532 struct fcp_ipkt *icmd; 3533 3534 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3535 3536 /* 3537 * Wake up user thread 3538 */ 3539 sema_v(&(icmd->ipkt_sema)); 3540 } 3541 3542 /* 3543 * Function: fcp_ipkt_sema_cleanup 3544 * 3545 * Description: Called to cleanup (if necessary) the data structures used 3546 * when ipkt sema is used for sync. This function will detect 3547 * whether the caller is the last thread (via counter) and 3548 * cleanup only if necessary. 3549 * 3550 * Argument: icmd Internal command packet 3551 * 3552 * Return Value: None 3553 * 3554 * Context: User context only 3555 */ 3556 static void 3557 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3558 { 3559 struct fcp_tgt *ptgt; 3560 struct fcp_port *pptr; 3561 3562 ptgt = icmd->ipkt_tgt; 3563 pptr = icmd->ipkt_port; 3564 3565 /* 3566 * Acquire data structure 3567 */ 3568 mutex_enter(&ptgt->tgt_mutex); 3569 3570 /* 3571 * Destroy semaphore 3572 */ 3573 sema_destroy(&(icmd->ipkt_sema)); 3574 3575 /* 3576 * Cleanup internal packet 3577 */ 3578 mutex_exit(&ptgt->tgt_mutex); 3579 fcp_icmd_free(pptr, icmd); 3580 } 3581 3582 /* 3583 * Function: fcp_port_attach 3584 * 3585 * Description: Called by the transport framework to resume, suspend or 3586 * attach a new port. 3587 * 3588 * Argument: ulph Port handle 3589 * *pinfo Port information 3590 * cmd Command 3591 * s_id Port ID 3592 * 3593 * Return Value: FC_FAILURE or FC_SUCCESS 3594 */ 3595 /*ARGSUSED*/ 3596 static int 3597 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3598 fc_attach_cmd_t cmd, uint32_t s_id) 3599 { 3600 int instance; 3601 int res = FC_FAILURE; /* default result */ 3602 3603 ASSERT(pinfo != NULL); 3604 3605 instance = ddi_get_instance(pinfo->port_dip); 3606 3607 switch (cmd) { 3608 case FC_CMD_ATTACH: 3609 /* 3610 * this port instance attaching for the first time (or after 3611 * being detached before) 3612 */ 3613 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3614 instance) == DDI_SUCCESS) { 3615 res = FC_SUCCESS; 3616 } else { 3617 ASSERT(ddi_get_soft_state(fcp_softstate, 3618 instance) == NULL); 3619 } 3620 break; 3621 3622 case FC_CMD_RESUME: 3623 case FC_CMD_POWER_UP: 3624 /* 3625 * this port instance was attached and the suspended and 3626 * will now be resumed 3627 */ 3628 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3629 instance) == DDI_SUCCESS) { 3630 res = FC_SUCCESS; 3631 } 3632 break; 3633 3634 default: 3635 /* shouldn't happen */ 3636 FCP_TRACE(fcp_logq, "fcp", 3637 fcp_trace, FCP_BUF_LEVEL_2, 0, 3638 "port_attach: unknown cmdcommand: %d", cmd); 3639 break; 3640 } 3641 3642 /* return result */ 3643 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3644 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3645 3646 return (res); 3647 } 3648 3649 3650 /* 3651 * detach or suspend this port instance 3652 * 3653 * acquires and releases the global mutex 3654 * 3655 * acquires and releases the mutex for this port 3656 * 3657 * acquires and releases the hotplug mutex for this port 3658 */ 3659 /*ARGSUSED*/ 3660 static int 3661 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3662 fc_detach_cmd_t cmd) 3663 { 3664 int flag; 3665 int instance; 3666 struct fcp_port *pptr; 3667 3668 instance = ddi_get_instance(info->port_dip); 3669 pptr = ddi_get_soft_state(fcp_softstate, instance); 3670 3671 switch (cmd) { 3672 case FC_CMD_SUSPEND: 3673 FCP_DTRACE(fcp_logq, "fcp", 3674 fcp_trace, FCP_BUF_LEVEL_8, 0, 3675 "port suspend called for port %d", instance); 3676 flag = FCP_STATE_SUSPENDED; 3677 break; 3678 3679 case FC_CMD_POWER_DOWN: 3680 FCP_DTRACE(fcp_logq, "fcp", 3681 fcp_trace, FCP_BUF_LEVEL_8, 0, 3682 "port power down called for port %d", instance); 3683 flag = FCP_STATE_POWER_DOWN; 3684 break; 3685 3686 case FC_CMD_DETACH: 3687 FCP_DTRACE(fcp_logq, "fcp", 3688 fcp_trace, FCP_BUF_LEVEL_8, 0, 3689 "port detach called for port %d", instance); 3690 flag = FCP_STATE_DETACHING; 3691 break; 3692 3693 default: 3694 /* shouldn't happen */ 3695 return (FC_FAILURE); 3696 } 3697 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3698 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3699 3700 return (fcp_handle_port_detach(pptr, flag, instance)); 3701 } 3702 3703 3704 /* 3705 * called for ioctls on the transport's devctl interface, and the transport 3706 * has passed it to us 3707 * 3708 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3709 * 3710 * return FC_SUCCESS if we decide to claim the ioctl, 3711 * else return FC_UNCLAIMED 3712 * 3713 * *rval is set iff we decide to claim the ioctl 3714 */ 3715 /*ARGSUSED*/ 3716 static int 3717 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3718 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3719 { 3720 int retval = FC_UNCLAIMED; /* return value */ 3721 struct fcp_port *pptr = NULL; /* our soft state */ 3722 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3723 dev_info_t *cdip; 3724 mdi_pathinfo_t *pip = NULL; 3725 char *ndi_nm; /* NDI name */ 3726 char *ndi_addr; /* NDI addr */ 3727 int is_mpxio, circ; 3728 int devi_entered = 0; 3729 clock_t end_time; 3730 3731 ASSERT(rval != NULL); 3732 3733 FCP_DTRACE(fcp_logq, "fcp", 3734 fcp_trace, FCP_BUF_LEVEL_8, 0, 3735 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3736 3737 /* if already claimed then forget it */ 3738 if (claimed) { 3739 /* 3740 * for now, if this ioctl has already been claimed, then 3741 * we just ignore it 3742 */ 3743 return (retval); 3744 } 3745 3746 /* get our port info */ 3747 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3748 fcp_log(CE_WARN, NULL, 3749 "!fcp:Invalid port handle handle in ioctl"); 3750 *rval = ENXIO; 3751 return (retval); 3752 } 3753 is_mpxio = pptr->port_mpxio; 3754 3755 switch (cmd) { 3756 case DEVCTL_BUS_GETSTATE: 3757 case DEVCTL_BUS_QUIESCE: 3758 case DEVCTL_BUS_UNQUIESCE: 3759 case DEVCTL_BUS_RESET: 3760 case DEVCTL_BUS_RESETALL: 3761 3762 case DEVCTL_BUS_DEV_CREATE: 3763 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3764 return (retval); 3765 } 3766 break; 3767 3768 case DEVCTL_DEVICE_GETSTATE: 3769 case DEVCTL_DEVICE_OFFLINE: 3770 case DEVCTL_DEVICE_ONLINE: 3771 case DEVCTL_DEVICE_REMOVE: 3772 case DEVCTL_DEVICE_RESET: 3773 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3774 return (retval); 3775 } 3776 3777 ASSERT(dcp != NULL); 3778 3779 /* ensure we have a name and address */ 3780 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3781 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3782 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3783 fcp_trace, FCP_BUF_LEVEL_2, 0, 3784 "ioctl: can't get name (%s) or addr (%s)", 3785 ndi_nm ? ndi_nm : "<null ptr>", 3786 ndi_addr ? ndi_addr : "<null ptr>"); 3787 ndi_dc_freehdl(dcp); 3788 return (retval); 3789 } 3790 3791 3792 /* get our child's DIP */ 3793 ASSERT(pptr != NULL); 3794 if (is_mpxio) { 3795 mdi_devi_enter(pptr->port_dip, &circ); 3796 } else { 3797 ndi_devi_enter(pptr->port_dip, &circ); 3798 } 3799 devi_entered = 1; 3800 3801 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3802 ndi_addr)) == NULL) { 3803 /* Look for virtually enumerated devices. */ 3804 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3805 if (pip == NULL || 3806 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3807 *rval = ENXIO; 3808 goto out; 3809 } 3810 } 3811 break; 3812 3813 default: 3814 *rval = ENOTTY; 3815 return (retval); 3816 } 3817 3818 /* this ioctl is ours -- process it */ 3819 3820 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3821 3822 /* we assume it will be a success; else we'll set error value */ 3823 *rval = 0; 3824 3825 3826 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3827 fcp_trace, FCP_BUF_LEVEL_8, 0, 3828 "ioctl: claiming this one"); 3829 3830 /* handle ioctls now */ 3831 switch (cmd) { 3832 case DEVCTL_DEVICE_GETSTATE: 3833 ASSERT(cdip != NULL); 3834 ASSERT(dcp != NULL); 3835 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3836 *rval = EFAULT; 3837 } 3838 break; 3839 3840 case DEVCTL_DEVICE_REMOVE: 3841 case DEVCTL_DEVICE_OFFLINE: { 3842 int flag = 0; 3843 int lcount; 3844 int tcount; 3845 struct fcp_pkt *head = NULL; 3846 struct fcp_lun *plun; 3847 child_info_t *cip = CIP(cdip); 3848 int all = 1; 3849 struct fcp_lun *tplun; 3850 struct fcp_tgt *ptgt; 3851 3852 ASSERT(pptr != NULL); 3853 ASSERT(cdip != NULL); 3854 3855 mutex_enter(&pptr->port_mutex); 3856 if (pip != NULL) { 3857 cip = CIP(pip); 3858 } 3859 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3860 mutex_exit(&pptr->port_mutex); 3861 *rval = ENXIO; 3862 break; 3863 } 3864 3865 head = fcp_scan_commands(plun); 3866 if (head != NULL) { 3867 fcp_abort_commands(head, LUN_PORT); 3868 } 3869 lcount = pptr->port_link_cnt; 3870 tcount = plun->lun_tgt->tgt_change_cnt; 3871 mutex_exit(&pptr->port_mutex); 3872 3873 if (cmd == DEVCTL_DEVICE_REMOVE) { 3874 flag = NDI_DEVI_REMOVE; 3875 if (is_mpxio) 3876 flag |= NDI_USER_REQ; 3877 } 3878 3879 if (is_mpxio) { 3880 mdi_devi_exit(pptr->port_dip, circ); 3881 } else { 3882 ndi_devi_exit(pptr->port_dip, circ); 3883 } 3884 devi_entered = 0; 3885 3886 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3887 FCP_OFFLINE, lcount, tcount, flag); 3888 3889 if (*rval != NDI_SUCCESS) { 3890 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3891 break; 3892 } 3893 3894 fcp_update_offline_flags(plun); 3895 3896 ptgt = plun->lun_tgt; 3897 mutex_enter(&ptgt->tgt_mutex); 3898 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3899 tplun->lun_next) { 3900 mutex_enter(&tplun->lun_mutex); 3901 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3902 all = 0; 3903 } 3904 mutex_exit(&tplun->lun_mutex); 3905 } 3906 3907 if (all) { 3908 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3909 /* 3910 * The user is unconfiguring/offlining the device. 3911 * If fabric and the auto configuration is set 3912 * then make sure the user is the only one who 3913 * can reconfigure the device. 3914 */ 3915 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3916 fcp_enable_auto_configuration) { 3917 ptgt->tgt_manual_config_only = 1; 3918 } 3919 } 3920 mutex_exit(&ptgt->tgt_mutex); 3921 break; 3922 } 3923 3924 case DEVCTL_DEVICE_ONLINE: { 3925 int lcount; 3926 int tcount; 3927 struct fcp_lun *plun; 3928 child_info_t *cip = CIP(cdip); 3929 3930 ASSERT(cdip != NULL); 3931 ASSERT(pptr != NULL); 3932 3933 mutex_enter(&pptr->port_mutex); 3934 if (pip != NULL) { 3935 cip = CIP(pip); 3936 } 3937 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3938 mutex_exit(&pptr->port_mutex); 3939 *rval = ENXIO; 3940 break; 3941 } 3942 lcount = pptr->port_link_cnt; 3943 tcount = plun->lun_tgt->tgt_change_cnt; 3944 mutex_exit(&pptr->port_mutex); 3945 3946 /* 3947 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3948 * to allow the device attach to occur when the device is 3949 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3950 * from the scsi_probe()). 3951 */ 3952 mutex_enter(&LUN_TGT->tgt_mutex); 3953 plun->lun_state |= FCP_LUN_ONLINING; 3954 mutex_exit(&LUN_TGT->tgt_mutex); 3955 3956 if (is_mpxio) { 3957 mdi_devi_exit(pptr->port_dip, circ); 3958 } else { 3959 ndi_devi_exit(pptr->port_dip, circ); 3960 } 3961 devi_entered = 0; 3962 3963 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3964 FCP_ONLINE, lcount, tcount, 0); 3965 3966 if (*rval != NDI_SUCCESS) { 3967 /* Reset the FCP_LUN_ONLINING bit */ 3968 mutex_enter(&LUN_TGT->tgt_mutex); 3969 plun->lun_state &= ~FCP_LUN_ONLINING; 3970 mutex_exit(&LUN_TGT->tgt_mutex); 3971 *rval = EIO; 3972 break; 3973 } 3974 mutex_enter(&LUN_TGT->tgt_mutex); 3975 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3976 FCP_LUN_ONLINING); 3977 mutex_exit(&LUN_TGT->tgt_mutex); 3978 break; 3979 } 3980 3981 case DEVCTL_BUS_DEV_CREATE: { 3982 uchar_t *bytes = NULL; 3983 uint_t nbytes; 3984 struct fcp_tgt *ptgt = NULL; 3985 struct fcp_lun *plun = NULL; 3986 dev_info_t *useless_dip = NULL; 3987 3988 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3989 DEVCTL_CONSTRUCT, &useless_dip); 3990 if (*rval != 0 || useless_dip == NULL) { 3991 break; 3992 } 3993 3994 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3995 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3996 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3997 *rval = EINVAL; 3998 (void) ndi_devi_free(useless_dip); 3999 if (bytes != NULL) { 4000 ddi_prop_free(bytes); 4001 } 4002 break; 4003 } 4004 4005 *rval = fcp_create_on_demand(pptr, bytes); 4006 if (*rval == 0) { 4007 mutex_enter(&pptr->port_mutex); 4008 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 4009 if (ptgt) { 4010 /* 4011 * We now have a pointer to the target that 4012 * was created. Lets point to the first LUN on 4013 * this new target. 4014 */ 4015 mutex_enter(&ptgt->tgt_mutex); 4016 4017 plun = ptgt->tgt_lun; 4018 /* 4019 * There may be stale/offline LUN entries on 4020 * this list (this is by design) and so we have 4021 * to make sure we point to the first online 4022 * LUN 4023 */ 4024 while (plun && 4025 plun->lun_state & FCP_LUN_OFFLINE) { 4026 plun = plun->lun_next; 4027 } 4028 4029 mutex_exit(&ptgt->tgt_mutex); 4030 } 4031 mutex_exit(&pptr->port_mutex); 4032 } 4033 4034 if (*rval == 0 && ptgt && plun) { 4035 mutex_enter(&plun->lun_mutex); 4036 /* 4037 * Allow up to fcp_lun_ready_retry seconds to 4038 * configure all the luns behind the target. 4039 * 4040 * The intent here is to allow targets with long 4041 * reboot/reset-recovery times to become available 4042 * while limiting the maximum wait time for an 4043 * unresponsive target. 4044 */ 4045 end_time = ddi_get_lbolt() + 4046 SEC_TO_TICK(fcp_lun_ready_retry); 4047 4048 while (ddi_get_lbolt() < end_time) { 4049 retval = FC_SUCCESS; 4050 4051 /* 4052 * The new ndi interfaces for on-demand creation 4053 * are inflexible, Do some more work to pass on 4054 * a path name of some LUN (design is broken !) 4055 */ 4056 if (plun->lun_cip) { 4057 if (plun->lun_mpxio == 0) { 4058 cdip = DIP(plun->lun_cip); 4059 } else { 4060 cdip = mdi_pi_get_client( 4061 PIP(plun->lun_cip)); 4062 } 4063 if (cdip == NULL) { 4064 *rval = ENXIO; 4065 break; 4066 } 4067 4068 if (!i_ddi_devi_attached(cdip)) { 4069 mutex_exit(&plun->lun_mutex); 4070 delay(drv_usectohz(1000000)); 4071 mutex_enter(&plun->lun_mutex); 4072 } else { 4073 /* 4074 * This Lun is ready, lets 4075 * check the next one. 4076 */ 4077 mutex_exit(&plun->lun_mutex); 4078 plun = plun->lun_next; 4079 while (plun && (plun->lun_state 4080 & FCP_LUN_OFFLINE)) { 4081 plun = plun->lun_next; 4082 } 4083 if (!plun) { 4084 break; 4085 } 4086 mutex_enter(&plun->lun_mutex); 4087 } 4088 } else { 4089 /* 4090 * lun_cip field for a valid lun 4091 * should never be NULL. Fail the 4092 * command. 4093 */ 4094 *rval = ENXIO; 4095 break; 4096 } 4097 } 4098 if (plun) { 4099 mutex_exit(&plun->lun_mutex); 4100 } else { 4101 char devnm[MAXNAMELEN]; 4102 int nmlen; 4103 4104 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4105 ddi_node_name(cdip), 4106 ddi_get_name_addr(cdip)); 4107 4108 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4109 0) { 4110 *rval = EFAULT; 4111 } 4112 } 4113 } else { 4114 int i; 4115 char buf[25]; 4116 4117 for (i = 0; i < FC_WWN_SIZE; i++) { 4118 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4119 } 4120 4121 fcp_log(CE_WARN, pptr->port_dip, 4122 "!Failed to create nodes for pwwn=%s; error=%x", 4123 buf, *rval); 4124 } 4125 4126 (void) ndi_devi_free(useless_dip); 4127 ddi_prop_free(bytes); 4128 break; 4129 } 4130 4131 case DEVCTL_DEVICE_RESET: { 4132 struct fcp_lun *plun; 4133 child_info_t *cip = CIP(cdip); 4134 4135 ASSERT(cdip != NULL); 4136 ASSERT(pptr != NULL); 4137 mutex_enter(&pptr->port_mutex); 4138 if (pip != NULL) { 4139 cip = CIP(pip); 4140 } 4141 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4142 mutex_exit(&pptr->port_mutex); 4143 *rval = ENXIO; 4144 break; 4145 } 4146 mutex_exit(&pptr->port_mutex); 4147 4148 mutex_enter(&plun->lun_tgt->tgt_mutex); 4149 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4150 mutex_exit(&plun->lun_tgt->tgt_mutex); 4151 4152 *rval = ENXIO; 4153 break; 4154 } 4155 4156 if (plun->lun_sd == NULL) { 4157 mutex_exit(&plun->lun_tgt->tgt_mutex); 4158 4159 *rval = ENXIO; 4160 break; 4161 } 4162 mutex_exit(&plun->lun_tgt->tgt_mutex); 4163 4164 /* 4165 * set up ap so that fcp_reset can figure out 4166 * which target to reset 4167 */ 4168 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4169 RESET_TARGET) == FALSE) { 4170 *rval = EIO; 4171 } 4172 break; 4173 } 4174 4175 case DEVCTL_BUS_GETSTATE: 4176 ASSERT(dcp != NULL); 4177 ASSERT(pptr != NULL); 4178 ASSERT(pptr->port_dip != NULL); 4179 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4180 NDI_SUCCESS) { 4181 *rval = EFAULT; 4182 } 4183 break; 4184 4185 case DEVCTL_BUS_QUIESCE: 4186 case DEVCTL_BUS_UNQUIESCE: 4187 *rval = ENOTSUP; 4188 break; 4189 4190 case DEVCTL_BUS_RESET: 4191 case DEVCTL_BUS_RESETALL: 4192 ASSERT(pptr != NULL); 4193 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4194 break; 4195 4196 default: 4197 ASSERT(dcp != NULL); 4198 *rval = ENOTTY; 4199 break; 4200 } 4201 4202 /* all done -- clean up and return */ 4203 out: if (devi_entered) { 4204 if (is_mpxio) { 4205 mdi_devi_exit(pptr->port_dip, circ); 4206 } else { 4207 ndi_devi_exit(pptr->port_dip, circ); 4208 } 4209 } 4210 4211 if (dcp != NULL) { 4212 ndi_dc_freehdl(dcp); 4213 } 4214 4215 return (retval); 4216 } 4217 4218 4219 /*ARGSUSED*/ 4220 static int 4221 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4222 uint32_t claimed) 4223 { 4224 uchar_t r_ctl; 4225 uchar_t ls_code; 4226 struct fcp_port *pptr; 4227 4228 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4229 return (FC_UNCLAIMED); 4230 } 4231 4232 mutex_enter(&pptr->port_mutex); 4233 if (pptr->port_state & (FCP_STATE_DETACHING | 4234 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4235 mutex_exit(&pptr->port_mutex); 4236 return (FC_UNCLAIMED); 4237 } 4238 mutex_exit(&pptr->port_mutex); 4239 4240 r_ctl = buf->ub_frame.r_ctl; 4241 4242 switch (r_ctl & R_CTL_ROUTING) { 4243 case R_CTL_EXTENDED_SVC: 4244 if (r_ctl == R_CTL_ELS_REQ) { 4245 ls_code = buf->ub_buffer[0]; 4246 4247 switch (ls_code) { 4248 case LA_ELS_PRLI: 4249 /* 4250 * We really don't care if something fails. 4251 * If the PRLI was not sent out, then the 4252 * other end will time it out. 4253 */ 4254 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4255 return (FC_SUCCESS); 4256 } 4257 return (FC_UNCLAIMED); 4258 /* NOTREACHED */ 4259 4260 default: 4261 break; 4262 } 4263 } 4264 /* FALLTHROUGH */ 4265 4266 default: 4267 return (FC_UNCLAIMED); 4268 } 4269 } 4270 4271 4272 /*ARGSUSED*/ 4273 static int 4274 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4275 uint32_t claimed) 4276 { 4277 return (FC_UNCLAIMED); 4278 } 4279 4280 /* 4281 * Function: fcp_statec_callback 4282 * 4283 * Description: The purpose of this function is to handle a port state change. 4284 * It is called from fp/fctl and, in a few instances, internally. 4285 * 4286 * Argument: ulph fp/fctl port handle 4287 * port_handle fcp_port structure 4288 * port_state Physical state of the port 4289 * port_top Topology 4290 * *devlist Pointer to the first entry of a table 4291 * containing the remote ports that can be 4292 * reached. 4293 * dev_cnt Number of entries pointed by devlist. 4294 * port_sid Port ID of the local port. 4295 * 4296 * Return Value: None 4297 */ 4298 /*ARGSUSED*/ 4299 static void 4300 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4301 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4302 uint32_t dev_cnt, uint32_t port_sid) 4303 { 4304 uint32_t link_count; 4305 int map_len = 0; 4306 struct fcp_port *pptr; 4307 fcp_map_tag_t *map_tag = NULL; 4308 4309 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4310 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4311 return; /* nothing to work with! */ 4312 } 4313 4314 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4315 fcp_trace, FCP_BUF_LEVEL_2, 0, 4316 "fcp_statec_callback: port state/dev_cnt/top =" 4317 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4318 dev_cnt, port_top); 4319 4320 mutex_enter(&pptr->port_mutex); 4321 4322 /* 4323 * If a thread is in detach, don't do anything. 4324 */ 4325 if (pptr->port_state & (FCP_STATE_DETACHING | 4326 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4327 mutex_exit(&pptr->port_mutex); 4328 return; 4329 } 4330 4331 /* 4332 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4333 * init_pkt is called, it knows whether or not the target's status 4334 * (or pd) might be changing. 4335 */ 4336 4337 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4338 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4339 } 4340 4341 /* 4342 * the transport doesn't allocate or probe unless being 4343 * asked to by either the applications or ULPs 4344 * 4345 * in cases where the port is OFFLINE at the time of port 4346 * attach callback and the link comes ONLINE later, for 4347 * easier automatic node creation (i.e. without you having to 4348 * go out and run the utility to perform LOGINs) the 4349 * following conditional is helpful 4350 */ 4351 pptr->port_phys_state = port_state; 4352 4353 if (dev_cnt) { 4354 mutex_exit(&pptr->port_mutex); 4355 4356 map_len = sizeof (*map_tag) * dev_cnt; 4357 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4358 if (map_tag == NULL) { 4359 fcp_log(CE_WARN, pptr->port_dip, 4360 "!fcp%d: failed to allocate for map tags; " 4361 " state change will not be processed", 4362 pptr->port_instance); 4363 4364 mutex_enter(&pptr->port_mutex); 4365 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4366 mutex_exit(&pptr->port_mutex); 4367 4368 return; 4369 } 4370 4371 mutex_enter(&pptr->port_mutex); 4372 } 4373 4374 if (pptr->port_id != port_sid) { 4375 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4376 fcp_trace, FCP_BUF_LEVEL_3, 0, 4377 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4378 port_sid); 4379 /* 4380 * The local port changed ID. It is the first time a port ID 4381 * is assigned or something drastic happened. We might have 4382 * been unplugged and replugged on another loop or fabric port 4383 * or somebody grabbed the AL_PA we had or somebody rezoned 4384 * the fabric we were plugged into. 4385 */ 4386 pptr->port_id = port_sid; 4387 } 4388 4389 switch (FC_PORT_STATE_MASK(port_state)) { 4390 case FC_STATE_OFFLINE: 4391 case FC_STATE_RESET_REQUESTED: 4392 /* 4393 * link has gone from online to offline -- just update the 4394 * state of this port to BUSY and MARKed to go offline 4395 */ 4396 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4397 fcp_trace, FCP_BUF_LEVEL_3, 0, 4398 "link went offline"); 4399 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4400 /* 4401 * We were offline a while ago and this one 4402 * seems to indicate that the loop has gone 4403 * dead forever. 4404 */ 4405 pptr->port_tmp_cnt += dev_cnt; 4406 pptr->port_state &= ~FCP_STATE_OFFLINE; 4407 pptr->port_state |= FCP_STATE_INIT; 4408 link_count = pptr->port_link_cnt; 4409 fcp_handle_devices(pptr, devlist, dev_cnt, 4410 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4411 } else { 4412 pptr->port_link_cnt++; 4413 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4414 fcp_update_state(pptr, (FCP_LUN_BUSY | 4415 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4416 if (pptr->port_mpxio) { 4417 fcp_update_mpxio_path_verifybusy(pptr); 4418 } 4419 pptr->port_state |= FCP_STATE_OFFLINE; 4420 pptr->port_state &= 4421 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4422 pptr->port_tmp_cnt = 0; 4423 } 4424 mutex_exit(&pptr->port_mutex); 4425 break; 4426 4427 case FC_STATE_ONLINE: 4428 case FC_STATE_LIP: 4429 case FC_STATE_LIP_LBIT_SET: 4430 /* 4431 * link has gone from offline to online 4432 */ 4433 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4434 fcp_trace, FCP_BUF_LEVEL_3, 0, 4435 "link went online"); 4436 4437 pptr->port_link_cnt++; 4438 4439 while (pptr->port_ipkt_cnt) { 4440 mutex_exit(&pptr->port_mutex); 4441 delay(drv_usectohz(1000000)); 4442 mutex_enter(&pptr->port_mutex); 4443 } 4444 4445 pptr->port_topology = port_top; 4446 4447 /* 4448 * The state of the targets and luns accessible through this 4449 * port is updated. 4450 */ 4451 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4452 FCP_CAUSE_LINK_CHANGE); 4453 4454 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4455 pptr->port_state |= FCP_STATE_ONLINING; 4456 pptr->port_tmp_cnt = dev_cnt; 4457 link_count = pptr->port_link_cnt; 4458 4459 pptr->port_deadline = fcp_watchdog_time + 4460 FCP_ICMD_DEADLINE; 4461 4462 if (!dev_cnt) { 4463 /* 4464 * We go directly to the online state if no remote 4465 * ports were discovered. 4466 */ 4467 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4468 fcp_trace, FCP_BUF_LEVEL_3, 0, 4469 "No remote ports discovered"); 4470 4471 pptr->port_state &= ~FCP_STATE_ONLINING; 4472 pptr->port_state |= FCP_STATE_ONLINE; 4473 } 4474 4475 switch (port_top) { 4476 case FC_TOP_FABRIC: 4477 case FC_TOP_PUBLIC_LOOP: 4478 case FC_TOP_PRIVATE_LOOP: 4479 case FC_TOP_PT_PT: 4480 4481 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4482 fcp_retry_ns_registry(pptr, port_sid); 4483 } 4484 4485 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4486 map_tag, FCP_CAUSE_LINK_CHANGE); 4487 break; 4488 4489 default: 4490 /* 4491 * We got here because we were provided with an unknown 4492 * topology. 4493 */ 4494 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4495 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4496 } 4497 4498 pptr->port_tmp_cnt -= dev_cnt; 4499 fcp_log(CE_WARN, pptr->port_dip, 4500 "!unknown/unsupported topology (0x%x)", port_top); 4501 break; 4502 } 4503 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4504 fcp_trace, FCP_BUF_LEVEL_3, 0, 4505 "Notify ssd of the reset to reinstate the reservations"); 4506 4507 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4508 &pptr->port_reset_notify_listf); 4509 4510 mutex_exit(&pptr->port_mutex); 4511 4512 break; 4513 4514 case FC_STATE_RESET: 4515 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4516 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4517 fcp_trace, FCP_BUF_LEVEL_3, 0, 4518 "RESET state, waiting for Offline/Online state_cb"); 4519 mutex_exit(&pptr->port_mutex); 4520 break; 4521 4522 case FC_STATE_DEVICE_CHANGE: 4523 /* 4524 * We come here when an application has requested 4525 * Dynamic node creation/deletion in Fabric connectivity. 4526 */ 4527 if (pptr->port_state & (FCP_STATE_OFFLINE | 4528 FCP_STATE_INIT)) { 4529 /* 4530 * This case can happen when the FCTL is in the 4531 * process of giving us on online and the host on 4532 * the other side issues a PLOGI/PLOGO. Ideally 4533 * the state changes should be serialized unless 4534 * they are opposite (online-offline). 4535 * The transport will give us a final state change 4536 * so we can ignore this for the time being. 4537 */ 4538 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4539 mutex_exit(&pptr->port_mutex); 4540 break; 4541 } 4542 4543 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4544 fcp_retry_ns_registry(pptr, port_sid); 4545 } 4546 4547 /* 4548 * Extend the deadline under steady state conditions 4549 * to provide more time for the device-change-commands 4550 */ 4551 if (!pptr->port_ipkt_cnt) { 4552 pptr->port_deadline = fcp_watchdog_time + 4553 FCP_ICMD_DEADLINE; 4554 } 4555 4556 /* 4557 * There is another race condition here, where if we were 4558 * in ONLINEING state and a devices in the map logs out, 4559 * fp will give another state change as DEVICE_CHANGE 4560 * and OLD. This will result in that target being offlined. 4561 * The pd_handle is freed. If from the first statec callback 4562 * we were going to fire a PLOGI/PRLI, the system will 4563 * panic in fc_ulp_transport with invalid pd_handle. 4564 * The fix is to check for the link_cnt before issuing 4565 * any command down. 4566 */ 4567 fcp_update_targets(pptr, devlist, dev_cnt, 4568 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4569 4570 link_count = pptr->port_link_cnt; 4571 4572 fcp_handle_devices(pptr, devlist, dev_cnt, 4573 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4574 4575 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4576 4577 mutex_exit(&pptr->port_mutex); 4578 break; 4579 4580 case FC_STATE_TARGET_PORT_RESET: 4581 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4582 fcp_retry_ns_registry(pptr, port_sid); 4583 } 4584 4585 /* Do nothing else */ 4586 mutex_exit(&pptr->port_mutex); 4587 break; 4588 4589 default: 4590 fcp_log(CE_WARN, pptr->port_dip, 4591 "!Invalid state change=0x%x", port_state); 4592 mutex_exit(&pptr->port_mutex); 4593 break; 4594 } 4595 4596 if (map_tag) { 4597 kmem_free(map_tag, map_len); 4598 } 4599 } 4600 4601 /* 4602 * Function: fcp_handle_devices 4603 * 4604 * Description: This function updates the devices currently known by 4605 * walking the list provided by the caller. The list passed 4606 * by the caller is supposed to be the list of reachable 4607 * devices. 4608 * 4609 * Argument: *pptr Fcp port structure. 4610 * *devlist Pointer to the first entry of a table 4611 * containing the remote ports that can be 4612 * reached. 4613 * dev_cnt Number of entries pointed by devlist. 4614 * link_cnt Link state count. 4615 * *map_tag Array of fcp_map_tag_t structures. 4616 * cause What caused this function to be called. 4617 * 4618 * Return Value: None 4619 * 4620 * Notes: The pptr->port_mutex must be held. 4621 */ 4622 static void 4623 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4624 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4625 { 4626 int i; 4627 int check_finish_init = 0; 4628 fc_portmap_t *map_entry; 4629 struct fcp_tgt *ptgt = NULL; 4630 4631 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4632 fcp_trace, FCP_BUF_LEVEL_3, 0, 4633 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4634 4635 if (dev_cnt) { 4636 ASSERT(map_tag != NULL); 4637 } 4638 4639 /* 4640 * The following code goes through the list of remote ports that are 4641 * accessible through this (pptr) local port (The list walked is the 4642 * one provided by the caller which is the list of the remote ports 4643 * currently reachable). It checks if any of them was already 4644 * known by looking for the corresponding target structure based on 4645 * the world wide name. If a target is part of the list it is tagged 4646 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4647 * 4648 * Old comment 4649 * ----------- 4650 * Before we drop port mutex; we MUST get the tags updated; This 4651 * two step process is somewhat slow, but more reliable. 4652 */ 4653 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4654 map_entry = &(devlist[i]); 4655 4656 /* 4657 * get ptr to this map entry in our port's 4658 * list (if any) 4659 */ 4660 ptgt = fcp_lookup_target(pptr, 4661 (uchar_t *)&(map_entry->map_pwwn)); 4662 4663 if (ptgt) { 4664 map_tag[i] = ptgt->tgt_change_cnt; 4665 if (cause == FCP_CAUSE_LINK_CHANGE) { 4666 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4667 } 4668 } 4669 } 4670 4671 /* 4672 * At this point we know which devices of the new list were already 4673 * known (The field tgt_aux_state of the target structure has been 4674 * set to FCP_TGT_TAGGED). 4675 * 4676 * The following code goes through the list of targets currently known 4677 * by the local port (the list is actually a hashing table). If a 4678 * target is found and is not tagged, it means the target cannot 4679 * be reached anymore through the local port (pptr). It is offlined. 4680 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4681 */ 4682 for (i = 0; i < FCP_NUM_HASH; i++) { 4683 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4684 ptgt = ptgt->tgt_next) { 4685 mutex_enter(&ptgt->tgt_mutex); 4686 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4687 (cause == FCP_CAUSE_LINK_CHANGE) && 4688 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4689 fcp_offline_target_now(pptr, ptgt, 4690 link_cnt, ptgt->tgt_change_cnt, 0); 4691 } 4692 mutex_exit(&ptgt->tgt_mutex); 4693 } 4694 } 4695 4696 /* 4697 * At this point, the devices that were known but cannot be reached 4698 * anymore, have most likely been offlined. 4699 * 4700 * The following section of code seems to go through the list of 4701 * remote ports that can now be reached. For every single one it 4702 * checks if it is already known or if it is a new port. 4703 */ 4704 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4705 4706 if (check_finish_init) { 4707 ASSERT(i > 0); 4708 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4709 map_tag[i - 1], cause); 4710 check_finish_init = 0; 4711 } 4712 4713 /* get a pointer to this map entry */ 4714 map_entry = &(devlist[i]); 4715 4716 /* 4717 * Check for the duplicate map entry flag. If we have marked 4718 * this entry as a duplicate we skip it since the correct 4719 * (perhaps even same) state change will be encountered 4720 * later in the list. 4721 */ 4722 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4723 continue; 4724 } 4725 4726 /* get ptr to this map entry in our port's list (if any) */ 4727 ptgt = fcp_lookup_target(pptr, 4728 (uchar_t *)&(map_entry->map_pwwn)); 4729 4730 if (ptgt) { 4731 /* 4732 * This device was already known. The field 4733 * tgt_aux_state is reset (was probably set to 4734 * FCP_TGT_TAGGED previously in this routine). 4735 */ 4736 ptgt->tgt_aux_state = 0; 4737 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4738 fcp_trace, FCP_BUF_LEVEL_3, 0, 4739 "handle_devices: map did/state/type/flags = " 4740 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4741 "tgt_state=%d", 4742 map_entry->map_did.port_id, map_entry->map_state, 4743 map_entry->map_type, map_entry->map_flags, 4744 ptgt->tgt_d_id, ptgt->tgt_state); 4745 } 4746 4747 if (map_entry->map_type == PORT_DEVICE_OLD || 4748 map_entry->map_type == PORT_DEVICE_NEW || 4749 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4750 map_entry->map_type == PORT_DEVICE_CHANGED) { 4751 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4752 fcp_trace, FCP_BUF_LEVEL_2, 0, 4753 "map_type=%x, did = %x", 4754 map_entry->map_type, 4755 map_entry->map_did.port_id); 4756 } 4757 4758 switch (map_entry->map_type) { 4759 case PORT_DEVICE_NOCHANGE: 4760 case PORT_DEVICE_USER_CREATE: 4761 case PORT_DEVICE_USER_LOGIN: 4762 case PORT_DEVICE_NEW: 4763 case PORT_DEVICE_REPORTLUN_CHANGED: 4764 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4765 4766 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4767 link_cnt, (ptgt) ? map_tag[i] : 0, 4768 cause) == TRUE) { 4769 4770 FCP_TGT_TRACE(ptgt, map_tag[i], 4771 FCP_TGT_TRACE_2); 4772 check_finish_init++; 4773 } 4774 break; 4775 4776 case PORT_DEVICE_OLD: 4777 if (ptgt != NULL) { 4778 FCP_TGT_TRACE(ptgt, map_tag[i], 4779 FCP_TGT_TRACE_3); 4780 4781 mutex_enter(&ptgt->tgt_mutex); 4782 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4783 /* 4784 * Must do an in-line wait for I/Os 4785 * to get drained 4786 */ 4787 mutex_exit(&ptgt->tgt_mutex); 4788 mutex_exit(&pptr->port_mutex); 4789 4790 mutex_enter(&ptgt->tgt_mutex); 4791 while (ptgt->tgt_ipkt_cnt || 4792 fcp_outstanding_lun_cmds(ptgt) 4793 == FC_SUCCESS) { 4794 mutex_exit(&ptgt->tgt_mutex); 4795 delay(drv_usectohz(1000000)); 4796 mutex_enter(&ptgt->tgt_mutex); 4797 } 4798 mutex_exit(&ptgt->tgt_mutex); 4799 4800 mutex_enter(&pptr->port_mutex); 4801 mutex_enter(&ptgt->tgt_mutex); 4802 4803 (void) fcp_offline_target(pptr, ptgt, 4804 link_cnt, map_tag[i], 0, 0); 4805 } 4806 mutex_exit(&ptgt->tgt_mutex); 4807 } 4808 check_finish_init++; 4809 break; 4810 4811 case PORT_DEVICE_USER_DELETE: 4812 case PORT_DEVICE_USER_LOGOUT: 4813 if (ptgt != NULL) { 4814 FCP_TGT_TRACE(ptgt, map_tag[i], 4815 FCP_TGT_TRACE_4); 4816 4817 mutex_enter(&ptgt->tgt_mutex); 4818 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4819 (void) fcp_offline_target(pptr, ptgt, 4820 link_cnt, map_tag[i], 1, 0); 4821 } 4822 mutex_exit(&ptgt->tgt_mutex); 4823 } 4824 check_finish_init++; 4825 break; 4826 4827 case PORT_DEVICE_CHANGED: 4828 if (ptgt != NULL) { 4829 FCP_TGT_TRACE(ptgt, map_tag[i], 4830 FCP_TGT_TRACE_5); 4831 4832 if (fcp_device_changed(pptr, ptgt, 4833 map_entry, link_cnt, map_tag[i], 4834 cause) == TRUE) { 4835 check_finish_init++; 4836 } 4837 } else { 4838 if (fcp_handle_mapflags(pptr, ptgt, 4839 map_entry, link_cnt, 0, cause) == TRUE) { 4840 check_finish_init++; 4841 } 4842 } 4843 break; 4844 4845 default: 4846 fcp_log(CE_WARN, pptr->port_dip, 4847 "!Invalid map_type=0x%x", map_entry->map_type); 4848 check_finish_init++; 4849 break; 4850 } 4851 } 4852 4853 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4854 ASSERT(i > 0); 4855 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4856 map_tag[i-1], cause); 4857 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4858 fcp_offline_all(pptr, link_cnt, cause); 4859 } 4860 } 4861 4862 static int 4863 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4864 { 4865 struct fcp_lun *plun; 4866 struct fcp_port *pptr; 4867 int rscn_count; 4868 int lun0_newalloc; 4869 int ret = TRUE; 4870 4871 ASSERT(ptgt); 4872 pptr = ptgt->tgt_port; 4873 lun0_newalloc = 0; 4874 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4875 /* 4876 * no LUN struct for LUN 0 yet exists, 4877 * so create one 4878 */ 4879 plun = fcp_alloc_lun(ptgt); 4880 if (plun == NULL) { 4881 fcp_log(CE_WARN, pptr->port_dip, 4882 "!Failed to allocate lun 0 for" 4883 " D_ID=%x", ptgt->tgt_d_id); 4884 return (ret); 4885 } 4886 lun0_newalloc = 1; 4887 } 4888 4889 mutex_enter(&ptgt->tgt_mutex); 4890 /* 4891 * consider lun 0 as device not connected if it is 4892 * offlined or newly allocated 4893 */ 4894 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4895 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4896 } 4897 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4898 plun->lun_state &= ~FCP_LUN_OFFLINE; 4899 ptgt->tgt_lun_cnt = 1; 4900 ptgt->tgt_report_lun_cnt = 0; 4901 mutex_exit(&ptgt->tgt_mutex); 4902 4903 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4904 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4905 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4906 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4907 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4908 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4909 "to D_ID=%x", ptgt->tgt_d_id); 4910 } else { 4911 ret = FALSE; 4912 } 4913 4914 return (ret); 4915 } 4916 4917 /* 4918 * Function: fcp_handle_mapflags 4919 * 4920 * Description: This function creates a target structure if the ptgt passed 4921 * is NULL. It also kicks off the PLOGI if we are not logged 4922 * into the target yet or the PRLI if we are logged into the 4923 * target already. The rest of the treatment is done in the 4924 * callbacks of the PLOGI or PRLI. 4925 * 4926 * Argument: *pptr FCP Port structure. 4927 * *ptgt Target structure. 4928 * *map_entry Array of fc_portmap_t structures. 4929 * link_cnt Link state count. 4930 * tgt_cnt Target state count. 4931 * cause What caused this function to be called. 4932 * 4933 * Return Value: TRUE Failed 4934 * FALSE Succeeded 4935 * 4936 * Notes: pptr->port_mutex must be owned. 4937 */ 4938 static int 4939 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4940 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4941 { 4942 int lcount; 4943 int tcount; 4944 int ret = TRUE; 4945 int alloc; 4946 struct fcp_ipkt *icmd; 4947 struct fcp_lun *pseq_lun = NULL; 4948 uchar_t opcode; 4949 int valid_ptgt_was_passed = FALSE; 4950 4951 ASSERT(mutex_owned(&pptr->port_mutex)); 4952 4953 /* 4954 * This case is possible where the FCTL has come up and done discovery 4955 * before FCP was loaded and attached. FCTL would have discovered the 4956 * devices and later the ULP came online. In this case ULP's would get 4957 * PORT_DEVICE_NOCHANGE but target would be NULL. 4958 */ 4959 if (ptgt == NULL) { 4960 /* don't already have a target */ 4961 mutex_exit(&pptr->port_mutex); 4962 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4963 mutex_enter(&pptr->port_mutex); 4964 4965 if (ptgt == NULL) { 4966 fcp_log(CE_WARN, pptr->port_dip, 4967 "!FC target allocation failed"); 4968 return (ret); 4969 } 4970 mutex_enter(&ptgt->tgt_mutex); 4971 ptgt->tgt_statec_cause = cause; 4972 ptgt->tgt_tmp_cnt = 1; 4973 mutex_exit(&ptgt->tgt_mutex); 4974 } else { 4975 valid_ptgt_was_passed = TRUE; 4976 } 4977 4978 /* 4979 * Copy in the target parameters 4980 */ 4981 mutex_enter(&ptgt->tgt_mutex); 4982 ptgt->tgt_d_id = map_entry->map_did.port_id; 4983 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4984 ptgt->tgt_pd_handle = map_entry->map_pd; 4985 ptgt->tgt_fca_dev = NULL; 4986 4987 /* Copy port and node WWNs */ 4988 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4989 FC_WWN_SIZE); 4990 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4991 FC_WWN_SIZE); 4992 4993 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4994 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4995 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4996 valid_ptgt_was_passed) { 4997 /* 4998 * determine if there are any tape LUNs on this target 4999 */ 5000 for (pseq_lun = ptgt->tgt_lun; 5001 pseq_lun != NULL; 5002 pseq_lun = pseq_lun->lun_next) { 5003 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 5004 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 5005 fcp_update_tgt_state(ptgt, FCP_RESET, 5006 FCP_LUN_MARK); 5007 mutex_exit(&ptgt->tgt_mutex); 5008 return (ret); 5009 } 5010 } 5011 } 5012 5013 /* 5014 * if UA'REPORT_LUN_CHANGED received, 5015 * send out REPORT LUN promptly, skip PLOGI/PRLI process 5016 */ 5017 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 5018 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 5019 mutex_exit(&ptgt->tgt_mutex); 5020 mutex_exit(&pptr->port_mutex); 5021 5022 ret = fcp_handle_reportlun_changed(ptgt, cause); 5023 5024 mutex_enter(&pptr->port_mutex); 5025 return (ret); 5026 } 5027 5028 /* 5029 * If ptgt was NULL when this function was entered, then tgt_node_state 5030 * was never specifically initialized but zeroed out which means 5031 * FCP_TGT_NODE_NONE. 5032 */ 5033 switch (ptgt->tgt_node_state) { 5034 case FCP_TGT_NODE_NONE: 5035 case FCP_TGT_NODE_ON_DEMAND: 5036 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5037 !fcp_enable_auto_configuration && 5038 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5039 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5040 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5041 fcp_enable_auto_configuration && 5042 (ptgt->tgt_manual_config_only == 1) && 5043 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5044 /* 5045 * If auto configuration is set and 5046 * the tgt_manual_config_only flag is set then 5047 * we only want the user to be able to change 5048 * the state through create_on_demand. 5049 */ 5050 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5051 } else { 5052 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5053 } 5054 break; 5055 5056 case FCP_TGT_NODE_PRESENT: 5057 break; 5058 } 5059 /* 5060 * If we are booting from a fabric device, make sure we 5061 * mark the node state appropriately for this target to be 5062 * enumerated 5063 */ 5064 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5065 if (bcmp((caddr_t)pptr->port_boot_wwn, 5066 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5067 sizeof (ptgt->tgt_port_wwn)) == 0) { 5068 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5069 } 5070 } 5071 mutex_exit(&ptgt->tgt_mutex); 5072 5073 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5074 fcp_trace, FCP_BUF_LEVEL_3, 0, 5075 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5076 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5077 map_entry->map_rscn_info.ulp_rscn_count); 5078 5079 mutex_enter(&ptgt->tgt_mutex); 5080 5081 /* 5082 * Reset target OFFLINE state and mark the target BUSY 5083 */ 5084 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5085 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5086 5087 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5088 lcount = link_cnt; 5089 5090 mutex_exit(&ptgt->tgt_mutex); 5091 mutex_exit(&pptr->port_mutex); 5092 5093 /* 5094 * if we are already logged in, then we do a PRLI, else 5095 * we do a PLOGI first (to get logged in) 5096 * 5097 * We will not check if we are the PLOGI initiator 5098 */ 5099 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5100 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5101 5102 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5103 5104 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5105 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5106 cause, map_entry->map_rscn_info.ulp_rscn_count); 5107 5108 if (icmd == NULL) { 5109 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5110 /* 5111 * We've exited port_mutex before calling fcp_icmd_alloc, 5112 * we need to make sure we reacquire it before returning. 5113 */ 5114 mutex_enter(&pptr->port_mutex); 5115 return (FALSE); 5116 } 5117 5118 /* TRUE is only returned while target is intended skipped */ 5119 ret = FALSE; 5120 /* discover info about this target */ 5121 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5122 lcount, tcount, cause)) == DDI_SUCCESS) { 5123 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5124 } else { 5125 fcp_icmd_free(pptr, icmd); 5126 ret = TRUE; 5127 } 5128 mutex_enter(&pptr->port_mutex); 5129 5130 return (ret); 5131 } 5132 5133 /* 5134 * Function: fcp_send_els 5135 * 5136 * Description: Sends an ELS to the target specified by the caller. Supports 5137 * PLOGI and PRLI. 5138 * 5139 * Argument: *pptr Fcp port. 5140 * *ptgt Target to send the ELS to. 5141 * *icmd Internal packet 5142 * opcode ELS opcode 5143 * lcount Link state change counter 5144 * tcount Target state change counter 5145 * cause What caused the call 5146 * 5147 * Return Value: DDI_SUCCESS 5148 * Others 5149 */ 5150 static int 5151 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5152 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5153 { 5154 fc_packet_t *fpkt; 5155 fc_frame_hdr_t *hp; 5156 int internal = 0; 5157 int alloc; 5158 int cmd_len; 5159 int resp_len; 5160 int res = DDI_FAILURE; /* default result */ 5161 int rval = DDI_FAILURE; 5162 5163 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5164 ASSERT(ptgt->tgt_port == pptr); 5165 5166 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5167 fcp_trace, FCP_BUF_LEVEL_5, 0, 5168 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5169 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5170 5171 if (opcode == LA_ELS_PLOGI) { 5172 cmd_len = sizeof (la_els_logi_t); 5173 resp_len = sizeof (la_els_logi_t); 5174 } else { 5175 ASSERT(opcode == LA_ELS_PRLI); 5176 cmd_len = sizeof (la_els_prli_t); 5177 resp_len = sizeof (la_els_prli_t); 5178 } 5179 5180 if (icmd == NULL) { 5181 alloc = FCP_MAX(sizeof (la_els_logi_t), 5182 sizeof (la_els_prli_t)); 5183 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5184 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5185 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5186 if (icmd == NULL) { 5187 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5188 return (res); 5189 } 5190 internal++; 5191 } 5192 fpkt = icmd->ipkt_fpkt; 5193 5194 fpkt->pkt_cmdlen = cmd_len; 5195 fpkt->pkt_rsplen = resp_len; 5196 fpkt->pkt_datalen = 0; 5197 icmd->ipkt_retries = 0; 5198 5199 /* fill in fpkt info */ 5200 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5201 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5202 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5203 5204 /* get ptr to frame hdr in fpkt */ 5205 hp = &fpkt->pkt_cmd_fhdr; 5206 5207 /* 5208 * fill in frame hdr 5209 */ 5210 hp->r_ctl = R_CTL_ELS_REQ; 5211 hp->s_id = pptr->port_id; /* source ID */ 5212 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5213 hp->type = FC_TYPE_EXTENDED_LS; 5214 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5215 hp->seq_id = 0; 5216 hp->rsvd = 0; 5217 hp->df_ctl = 0; 5218 hp->seq_cnt = 0; 5219 hp->ox_id = 0xffff; /* i.e. none */ 5220 hp->rx_id = 0xffff; /* i.e. none */ 5221 hp->ro = 0; 5222 5223 /* 5224 * at this point we have a filled in cmd pkt 5225 * 5226 * fill in the respective info, then use the transport to send 5227 * the packet 5228 * 5229 * for a PLOGI call fc_ulp_login(), and 5230 * for a PRLI call fc_ulp_issue_els() 5231 */ 5232 switch (opcode) { 5233 case LA_ELS_PLOGI: { 5234 struct la_els_logi logi; 5235 5236 bzero(&logi, sizeof (struct la_els_logi)); 5237 5238 hp = &fpkt->pkt_cmd_fhdr; 5239 hp->r_ctl = R_CTL_ELS_REQ; 5240 logi.ls_code.ls_code = LA_ELS_PLOGI; 5241 logi.ls_code.mbz = 0; 5242 5243 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5244 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5245 5246 icmd->ipkt_opcode = LA_ELS_PLOGI; 5247 5248 mutex_enter(&pptr->port_mutex); 5249 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5250 5251 mutex_exit(&pptr->port_mutex); 5252 5253 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5254 if (rval == FC_SUCCESS) { 5255 res = DDI_SUCCESS; 5256 break; 5257 } 5258 5259 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5260 5261 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5262 rval, "PLOGI"); 5263 } else { 5264 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5265 fcp_trace, FCP_BUF_LEVEL_5, 0, 5266 "fcp_send_els1: state change occured" 5267 " for D_ID=0x%x", ptgt->tgt_d_id); 5268 mutex_exit(&pptr->port_mutex); 5269 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5270 } 5271 break; 5272 } 5273 5274 case LA_ELS_PRLI: { 5275 struct la_els_prli prli; 5276 struct fcp_prli *fprli; 5277 5278 bzero(&prli, sizeof (struct la_els_prli)); 5279 5280 hp = &fpkt->pkt_cmd_fhdr; 5281 hp->r_ctl = R_CTL_ELS_REQ; 5282 5283 /* fill in PRLI cmd ELS fields */ 5284 prli.ls_code = LA_ELS_PRLI; 5285 prli.page_length = 0x10; /* huh? */ 5286 prli.payload_length = sizeof (struct la_els_prli); 5287 5288 icmd->ipkt_opcode = LA_ELS_PRLI; 5289 5290 /* get ptr to PRLI service params */ 5291 fprli = (struct fcp_prli *)prli.service_params; 5292 5293 /* fill in service params */ 5294 fprli->type = 0x08; 5295 fprli->resvd1 = 0; 5296 fprli->orig_process_assoc_valid = 0; 5297 fprli->resp_process_assoc_valid = 0; 5298 fprli->establish_image_pair = 1; 5299 fprli->resvd2 = 0; 5300 fprli->resvd3 = 0; 5301 fprli->obsolete_1 = 0; 5302 fprli->obsolete_2 = 0; 5303 fprli->data_overlay_allowed = 0; 5304 fprli->initiator_fn = 1; 5305 fprli->confirmed_compl_allowed = 1; 5306 5307 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5308 fprli->target_fn = 1; 5309 } else { 5310 fprli->target_fn = 0; 5311 } 5312 5313 fprli->retry = 1; 5314 fprli->read_xfer_rdy_disabled = 1; 5315 fprli->write_xfer_rdy_disabled = 0; 5316 5317 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5318 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5319 5320 /* issue the PRLI request */ 5321 5322 mutex_enter(&pptr->port_mutex); 5323 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5324 5325 mutex_exit(&pptr->port_mutex); 5326 5327 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5328 if (rval == FC_SUCCESS) { 5329 res = DDI_SUCCESS; 5330 break; 5331 } 5332 5333 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5334 5335 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5336 rval, "PRLI"); 5337 } else { 5338 mutex_exit(&pptr->port_mutex); 5339 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5340 } 5341 break; 5342 } 5343 5344 default: 5345 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5346 break; 5347 } 5348 5349 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5350 fcp_trace, FCP_BUF_LEVEL_5, 0, 5351 "fcp_send_els: returning %d", res); 5352 5353 if (res != DDI_SUCCESS) { 5354 if (internal) { 5355 fcp_icmd_free(pptr, icmd); 5356 } 5357 } 5358 5359 return (res); 5360 } 5361 5362 5363 /* 5364 * called internally update the state of all of the tgts and each LUN 5365 * for this port (i.e. each target known to be attached to this port) 5366 * if they are not already offline 5367 * 5368 * must be called with the port mutex owned 5369 * 5370 * acquires and releases the target mutexes for each target attached 5371 * to this port 5372 */ 5373 void 5374 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5375 { 5376 int i; 5377 struct fcp_tgt *ptgt; 5378 5379 ASSERT(mutex_owned(&pptr->port_mutex)); 5380 5381 for (i = 0; i < FCP_NUM_HASH; i++) { 5382 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5383 ptgt = ptgt->tgt_next) { 5384 mutex_enter(&ptgt->tgt_mutex); 5385 fcp_update_tgt_state(ptgt, FCP_SET, state); 5386 ptgt->tgt_change_cnt++; 5387 ptgt->tgt_statec_cause = cause; 5388 ptgt->tgt_tmp_cnt = 1; 5389 ptgt->tgt_done = 0; 5390 mutex_exit(&ptgt->tgt_mutex); 5391 } 5392 } 5393 } 5394 5395 5396 static void 5397 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5398 { 5399 int i; 5400 int ndevs; 5401 struct fcp_tgt *ptgt; 5402 5403 ASSERT(mutex_owned(&pptr->port_mutex)); 5404 5405 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5406 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5407 ptgt = ptgt->tgt_next) { 5408 ndevs++; 5409 } 5410 } 5411 5412 if (ndevs == 0) { 5413 return; 5414 } 5415 pptr->port_tmp_cnt = ndevs; 5416 5417 for (i = 0; i < FCP_NUM_HASH; i++) { 5418 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5419 ptgt = ptgt->tgt_next) { 5420 (void) fcp_call_finish_init_held(pptr, ptgt, 5421 lcount, ptgt->tgt_change_cnt, cause); 5422 } 5423 } 5424 } 5425 5426 /* 5427 * Function: fcp_update_tgt_state 5428 * 5429 * Description: This function updates the field tgt_state of a target. That 5430 * field is a bitmap and which bit can be set or reset 5431 * individually. The action applied to the target state is also 5432 * applied to all the LUNs belonging to the target (provided the 5433 * LUN is not offline). A side effect of applying the state 5434 * modification to the target and the LUNs is the field tgt_trace 5435 * of the target and lun_trace of the LUNs is set to zero. 5436 * 5437 * 5438 * Argument: *ptgt Target structure. 5439 * flag Flag indication what action to apply (set/reset). 5440 * state State bits to update. 5441 * 5442 * Return Value: None 5443 * 5444 * Context: Interrupt, Kernel or User context. 5445 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5446 * calling this function. 5447 */ 5448 void 5449 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5450 { 5451 struct fcp_lun *plun; 5452 5453 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5454 5455 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5456 /* The target is not offline. */ 5457 if (flag == FCP_SET) { 5458 ptgt->tgt_state |= state; 5459 ptgt->tgt_trace = 0; 5460 } else { 5461 ptgt->tgt_state &= ~state; 5462 } 5463 5464 for (plun = ptgt->tgt_lun; plun != NULL; 5465 plun = plun->lun_next) { 5466 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5467 /* The LUN is not offline. */ 5468 if (flag == FCP_SET) { 5469 plun->lun_state |= state; 5470 plun->lun_trace = 0; 5471 } else { 5472 plun->lun_state &= ~state; 5473 } 5474 } 5475 } 5476 } 5477 } 5478 5479 /* 5480 * Function: fcp_update_tgt_state 5481 * 5482 * Description: This function updates the field lun_state of a LUN. That 5483 * field is a bitmap and which bit can be set or reset 5484 * individually. 5485 * 5486 * Argument: *plun LUN structure. 5487 * flag Flag indication what action to apply (set/reset). 5488 * state State bits to update. 5489 * 5490 * Return Value: None 5491 * 5492 * Context: Interrupt, Kernel or User context. 5493 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5494 * calling this function. 5495 */ 5496 void 5497 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5498 { 5499 struct fcp_tgt *ptgt = plun->lun_tgt; 5500 5501 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5502 5503 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5504 if (flag == FCP_SET) { 5505 plun->lun_state |= state; 5506 } else { 5507 plun->lun_state &= ~state; 5508 } 5509 } 5510 } 5511 5512 /* 5513 * Function: fcp_get_port 5514 * 5515 * Description: This function returns the fcp_port structure from the opaque 5516 * handle passed by the caller. That opaque handle is the handle 5517 * used by fp/fctl to identify a particular local port. That 5518 * handle has been stored in the corresponding fcp_port 5519 * structure. This function is going to walk the global list of 5520 * fcp_port structures till one has a port_fp_handle that matches 5521 * the handle passed by the caller. This function enters the 5522 * mutex fcp_global_mutex while walking the global list and then 5523 * releases it. 5524 * 5525 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5526 * particular port. 5527 * 5528 * Return Value: NULL Not found. 5529 * Not NULL Pointer to the fcp_port structure. 5530 * 5531 * Context: Interrupt, Kernel or User context. 5532 */ 5533 static struct fcp_port * 5534 fcp_get_port(opaque_t port_handle) 5535 { 5536 struct fcp_port *pptr; 5537 5538 ASSERT(port_handle != NULL); 5539 5540 mutex_enter(&fcp_global_mutex); 5541 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5542 if (pptr->port_fp_handle == port_handle) { 5543 break; 5544 } 5545 } 5546 mutex_exit(&fcp_global_mutex); 5547 5548 return (pptr); 5549 } 5550 5551 5552 static void 5553 fcp_unsol_callback(fc_packet_t *fpkt) 5554 { 5555 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5556 struct fcp_port *pptr = icmd->ipkt_port; 5557 5558 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5559 caddr_t state, reason, action, expln; 5560 5561 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5562 &action, &expln); 5563 5564 fcp_log(CE_WARN, pptr->port_dip, 5565 "!couldn't post response to unsolicited request: " 5566 " state=%s reason=%s rx_id=%x ox_id=%x", 5567 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5568 fpkt->pkt_cmd_fhdr.rx_id); 5569 } 5570 fcp_icmd_free(pptr, icmd); 5571 } 5572 5573 5574 /* 5575 * Perform general purpose preparation of a response to an unsolicited request 5576 */ 5577 static void 5578 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5579 uchar_t r_ctl, uchar_t type) 5580 { 5581 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5582 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5583 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5584 pkt->pkt_cmd_fhdr.type = type; 5585 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5586 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5587 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5588 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5589 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5590 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5591 pkt->pkt_cmd_fhdr.ro = 0; 5592 pkt->pkt_cmd_fhdr.rsvd = 0; 5593 pkt->pkt_comp = fcp_unsol_callback; 5594 pkt->pkt_pd = NULL; 5595 pkt->pkt_ub_resp_token = (opaque_t)buf; 5596 } 5597 5598 5599 /*ARGSUSED*/ 5600 static int 5601 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5602 { 5603 fc_packet_t *fpkt; 5604 struct la_els_prli prli; 5605 struct fcp_prli *fprli; 5606 struct fcp_ipkt *icmd; 5607 struct la_els_prli *from; 5608 struct fcp_prli *orig; 5609 struct fcp_tgt *ptgt; 5610 int tcount = 0; 5611 int lcount; 5612 5613 from = (struct la_els_prli *)buf->ub_buffer; 5614 orig = (struct fcp_prli *)from->service_params; 5615 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5616 NULL) { 5617 mutex_enter(&ptgt->tgt_mutex); 5618 tcount = ptgt->tgt_change_cnt; 5619 mutex_exit(&ptgt->tgt_mutex); 5620 } 5621 5622 mutex_enter(&pptr->port_mutex); 5623 lcount = pptr->port_link_cnt; 5624 mutex_exit(&pptr->port_mutex); 5625 5626 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5627 sizeof (la_els_prli_t), 0, 5628 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5629 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5630 return (FC_FAILURE); 5631 } 5632 5633 fpkt = icmd->ipkt_fpkt; 5634 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5635 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5636 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5637 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5638 fpkt->pkt_rsplen = 0; 5639 fpkt->pkt_datalen = 0; 5640 5641 icmd->ipkt_opcode = LA_ELS_PRLI; 5642 5643 bzero(&prli, sizeof (struct la_els_prli)); 5644 fprli = (struct fcp_prli *)prli.service_params; 5645 prli.ls_code = LA_ELS_ACC; 5646 prli.page_length = 0x10; 5647 prli.payload_length = sizeof (struct la_els_prli); 5648 5649 /* fill in service params */ 5650 fprli->type = 0x08; 5651 fprli->resvd1 = 0; 5652 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5653 fprli->orig_process_associator = orig->orig_process_associator; 5654 fprli->resp_process_assoc_valid = 0; 5655 fprli->establish_image_pair = 1; 5656 fprli->resvd2 = 0; 5657 fprli->resvd3 = 0; 5658 fprli->obsolete_1 = 0; 5659 fprli->obsolete_2 = 0; 5660 fprli->data_overlay_allowed = 0; 5661 fprli->initiator_fn = 1; 5662 fprli->confirmed_compl_allowed = 1; 5663 5664 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5665 fprli->target_fn = 1; 5666 } else { 5667 fprli->target_fn = 0; 5668 } 5669 5670 fprli->retry = 1; 5671 fprli->read_xfer_rdy_disabled = 1; 5672 fprli->write_xfer_rdy_disabled = 0; 5673 5674 /* save the unsol prli payload first */ 5675 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5676 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5677 5678 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5679 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5680 5681 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5682 5683 mutex_enter(&pptr->port_mutex); 5684 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5685 int rval; 5686 mutex_exit(&pptr->port_mutex); 5687 5688 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5689 FC_SUCCESS) { 5690 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5691 ptgt != NULL) { 5692 fcp_queue_ipkt(pptr, fpkt); 5693 return (FC_SUCCESS); 5694 } 5695 /* Let it timeout */ 5696 fcp_icmd_free(pptr, icmd); 5697 return (FC_FAILURE); 5698 } 5699 } else { 5700 mutex_exit(&pptr->port_mutex); 5701 fcp_icmd_free(pptr, icmd); 5702 return (FC_FAILURE); 5703 } 5704 5705 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5706 5707 return (FC_SUCCESS); 5708 } 5709 5710 /* 5711 * Function: fcp_icmd_alloc 5712 * 5713 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5714 * field is initialized to fcp_icmd_callback. Sometimes it is 5715 * modified by the caller (such as fcp_send_scsi). The 5716 * structure is also tied to the state of the line and of the 5717 * target at a particular time. That link is established by 5718 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5719 * and tcount which came respectively from pptr->link_cnt and 5720 * ptgt->tgt_change_cnt. 5721 * 5722 * Argument: *pptr Fcp port. 5723 * *ptgt Target (destination of the command). 5724 * cmd_len Length of the command. 5725 * resp_len Length of the expected response. 5726 * data_len Length of the data. 5727 * nodma Indicates weither the command and response. 5728 * will be transfer through DMA or not. 5729 * lcount Link state change counter. 5730 * tcount Target state change counter. 5731 * cause Reason that lead to this call. 5732 * 5733 * Return Value: NULL Failed. 5734 * Not NULL Internal packet address. 5735 */ 5736 static struct fcp_ipkt * 5737 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5738 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5739 uint32_t rscn_count) 5740 { 5741 int dma_setup = 0; 5742 fc_packet_t *fpkt; 5743 struct fcp_ipkt *icmd = NULL; 5744 5745 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5746 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5747 KM_NOSLEEP); 5748 if (icmd == NULL) { 5749 fcp_log(CE_WARN, pptr->port_dip, 5750 "!internal packet allocation failed"); 5751 return (NULL); 5752 } 5753 5754 /* 5755 * initialize the allocated packet 5756 */ 5757 icmd->ipkt_nodma = nodma; 5758 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5759 icmd->ipkt_lun = NULL; 5760 5761 icmd->ipkt_link_cnt = lcount; 5762 icmd->ipkt_change_cnt = tcount; 5763 icmd->ipkt_cause = cause; 5764 5765 mutex_enter(&pptr->port_mutex); 5766 icmd->ipkt_port = pptr; 5767 mutex_exit(&pptr->port_mutex); 5768 5769 /* keep track of amt of data to be sent in pkt */ 5770 icmd->ipkt_cmdlen = cmd_len; 5771 icmd->ipkt_resplen = resp_len; 5772 icmd->ipkt_datalen = data_len; 5773 5774 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5775 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5776 5777 /* set pkt's private ptr to point to cmd pkt */ 5778 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5779 5780 /* set FCA private ptr to memory just beyond */ 5781 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5782 ((char *)icmd + sizeof (struct fcp_ipkt) + 5783 pptr->port_dmacookie_sz); 5784 5785 /* get ptr to fpkt substruct and fill it in */ 5786 fpkt = icmd->ipkt_fpkt; 5787 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5788 sizeof (struct fcp_ipkt)); 5789 5790 if (ptgt != NULL) { 5791 icmd->ipkt_tgt = ptgt; 5792 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5793 } 5794 5795 fpkt->pkt_comp = fcp_icmd_callback; 5796 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5797 fpkt->pkt_cmdlen = cmd_len; 5798 fpkt->pkt_rsplen = resp_len; 5799 fpkt->pkt_datalen = data_len; 5800 5801 /* 5802 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5803 * rscn_count as fcp knows down to the transport. If a valid count was 5804 * passed into this function, we allocate memory to actually pass down 5805 * this info. 5806 * 5807 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5808 * basically mean that fcp will not be able to help transport 5809 * distinguish if a new RSCN has come after fcp was last informed about 5810 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5811 * 5068068 where the device might end up going offline in case of RSCN 5812 * storms. 5813 */ 5814 fpkt->pkt_ulp_rscn_infop = NULL; 5815 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5816 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5817 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5818 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5819 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5820 fcp_trace, FCP_BUF_LEVEL_6, 0, 5821 "Failed to alloc memory to pass rscn info"); 5822 } 5823 } 5824 5825 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5826 fc_ulp_rscn_info_t *rscnp; 5827 5828 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5829 rscnp->ulp_rscn_count = rscn_count; 5830 } 5831 5832 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5833 goto fail; 5834 } 5835 dma_setup++; 5836 5837 /* 5838 * Must hold target mutex across setting of pkt_pd and call to 5839 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5840 * away while we're not looking. 5841 */ 5842 if (ptgt != NULL) { 5843 mutex_enter(&ptgt->tgt_mutex); 5844 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5845 5846 /* ask transport to do its initialization on this pkt */ 5847 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5848 != FC_SUCCESS) { 5849 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5850 fcp_trace, FCP_BUF_LEVEL_6, 0, 5851 "fc_ulp_init_packet failed"); 5852 mutex_exit(&ptgt->tgt_mutex); 5853 goto fail; 5854 } 5855 mutex_exit(&ptgt->tgt_mutex); 5856 } else { 5857 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5858 != FC_SUCCESS) { 5859 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5860 fcp_trace, FCP_BUF_LEVEL_6, 0, 5861 "fc_ulp_init_packet failed"); 5862 goto fail; 5863 } 5864 } 5865 5866 mutex_enter(&pptr->port_mutex); 5867 if (pptr->port_state & (FCP_STATE_DETACHING | 5868 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5869 int rval; 5870 5871 mutex_exit(&pptr->port_mutex); 5872 5873 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5874 ASSERT(rval == FC_SUCCESS); 5875 5876 goto fail; 5877 } 5878 5879 if (ptgt != NULL) { 5880 mutex_enter(&ptgt->tgt_mutex); 5881 ptgt->tgt_ipkt_cnt++; 5882 mutex_exit(&ptgt->tgt_mutex); 5883 } 5884 5885 pptr->port_ipkt_cnt++; 5886 5887 mutex_exit(&pptr->port_mutex); 5888 5889 return (icmd); 5890 5891 fail: 5892 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5893 kmem_free(fpkt->pkt_ulp_rscn_infop, 5894 sizeof (fc_ulp_rscn_info_t)); 5895 fpkt->pkt_ulp_rscn_infop = NULL; 5896 } 5897 5898 if (dma_setup) { 5899 fcp_free_dma(pptr, icmd); 5900 } 5901 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5902 (size_t)pptr->port_dmacookie_sz); 5903 5904 return (NULL); 5905 } 5906 5907 /* 5908 * Function: fcp_icmd_free 5909 * 5910 * Description: Frees the internal command passed by the caller. 5911 * 5912 * Argument: *pptr Fcp port. 5913 * *icmd Internal packet to free. 5914 * 5915 * Return Value: None 5916 */ 5917 static void 5918 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5919 { 5920 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5921 5922 /* Let the underlying layers do their cleanup. */ 5923 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5924 icmd->ipkt_fpkt); 5925 5926 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5927 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5928 sizeof (fc_ulp_rscn_info_t)); 5929 } 5930 5931 fcp_free_dma(pptr, icmd); 5932 5933 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5934 (size_t)pptr->port_dmacookie_sz); 5935 5936 mutex_enter(&pptr->port_mutex); 5937 5938 if (ptgt) { 5939 mutex_enter(&ptgt->tgt_mutex); 5940 ptgt->tgt_ipkt_cnt--; 5941 mutex_exit(&ptgt->tgt_mutex); 5942 } 5943 5944 pptr->port_ipkt_cnt--; 5945 mutex_exit(&pptr->port_mutex); 5946 } 5947 5948 /* 5949 * Function: fcp_alloc_dma 5950 * 5951 * Description: Allocated the DMA resources required for the internal 5952 * packet. 5953 * 5954 * Argument: *pptr FCP port. 5955 * *icmd Internal FCP packet. 5956 * nodma Indicates if the Cmd and Resp will be DMAed. 5957 * flags Allocation flags (Sleep or NoSleep). 5958 * 5959 * Return Value: FC_SUCCESS 5960 * FC_NOMEM 5961 */ 5962 static int 5963 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5964 int nodma, int flags) 5965 { 5966 int rval; 5967 size_t real_size; 5968 uint_t ccount; 5969 int bound = 0; 5970 int cmd_resp = 0; 5971 fc_packet_t *fpkt; 5972 ddi_dma_cookie_t pkt_data_cookie; 5973 ddi_dma_cookie_t *cp; 5974 uint32_t cnt; 5975 5976 fpkt = &icmd->ipkt_fc_packet; 5977 5978 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5979 fpkt->pkt_resp_dma == NULL); 5980 5981 icmd->ipkt_nodma = nodma; 5982 5983 if (nodma) { 5984 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5985 if (fpkt->pkt_cmd == NULL) { 5986 goto fail; 5987 } 5988 5989 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5990 if (fpkt->pkt_resp == NULL) { 5991 goto fail; 5992 } 5993 } else { 5994 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5995 5996 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5997 if (rval == FC_FAILURE) { 5998 ASSERT(fpkt->pkt_cmd_dma == NULL && 5999 fpkt->pkt_resp_dma == NULL); 6000 goto fail; 6001 } 6002 cmd_resp++; 6003 } 6004 6005 if ((fpkt->pkt_datalen != 0) && 6006 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 6007 /* 6008 * set up DMA handle and memory for the data in this packet 6009 */ 6010 if (ddi_dma_alloc_handle(pptr->port_dip, 6011 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 6012 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 6013 goto fail; 6014 } 6015 6016 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 6017 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 6018 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 6019 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 6020 goto fail; 6021 } 6022 6023 /* was DMA mem size gotten < size asked for/needed ?? */ 6024 if (real_size < fpkt->pkt_datalen) { 6025 goto fail; 6026 } 6027 6028 /* bind DMA address and handle together */ 6029 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6030 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6031 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6032 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6033 goto fail; 6034 } 6035 bound++; 6036 6037 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6038 goto fail; 6039 } 6040 6041 fpkt->pkt_data_cookie_cnt = ccount; 6042 6043 cp = fpkt->pkt_data_cookie; 6044 *cp = pkt_data_cookie; 6045 cp++; 6046 6047 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6048 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6049 &pkt_data_cookie); 6050 *cp = pkt_data_cookie; 6051 } 6052 6053 } else if (fpkt->pkt_datalen != 0) { 6054 /* 6055 * If it's a pseudo FCA, then it can't support DMA even in 6056 * SCSI data phase. 6057 */ 6058 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6059 if (fpkt->pkt_data == NULL) { 6060 goto fail; 6061 } 6062 6063 } 6064 6065 return (FC_SUCCESS); 6066 6067 fail: 6068 if (bound) { 6069 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6070 } 6071 6072 if (fpkt->pkt_data_dma) { 6073 if (fpkt->pkt_data) { 6074 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6075 } 6076 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6077 } else { 6078 if (fpkt->pkt_data) { 6079 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6080 } 6081 } 6082 6083 if (nodma) { 6084 if (fpkt->pkt_cmd) { 6085 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6086 } 6087 if (fpkt->pkt_resp) { 6088 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6089 } 6090 } else { 6091 if (cmd_resp) { 6092 fcp_free_cmd_resp(pptr, fpkt); 6093 } 6094 } 6095 6096 return (FC_NOMEM); 6097 } 6098 6099 6100 static void 6101 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6102 { 6103 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6104 6105 if (fpkt->pkt_data_dma) { 6106 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6107 if (fpkt->pkt_data) { 6108 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6109 } 6110 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6111 } else { 6112 if (fpkt->pkt_data) { 6113 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6114 } 6115 /* 6116 * Need we reset pkt_* to zero??? 6117 */ 6118 } 6119 6120 if (icmd->ipkt_nodma) { 6121 if (fpkt->pkt_cmd) { 6122 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6123 } 6124 if (fpkt->pkt_resp) { 6125 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6126 } 6127 } else { 6128 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6129 6130 fcp_free_cmd_resp(pptr, fpkt); 6131 } 6132 } 6133 6134 /* 6135 * Function: fcp_lookup_target 6136 * 6137 * Description: Finds a target given a WWN. 6138 * 6139 * Argument: *pptr FCP port. 6140 * *wwn World Wide Name of the device to look for. 6141 * 6142 * Return Value: NULL No target found 6143 * Not NULL Target structure 6144 * 6145 * Context: Interrupt context. 6146 * The mutex pptr->port_mutex must be owned. 6147 */ 6148 /* ARGSUSED */ 6149 static struct fcp_tgt * 6150 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6151 { 6152 int hash; 6153 struct fcp_tgt *ptgt; 6154 6155 ASSERT(mutex_owned(&pptr->port_mutex)); 6156 6157 hash = FCP_HASH(wwn); 6158 6159 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6160 ptgt = ptgt->tgt_next) { 6161 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6162 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6163 sizeof (ptgt->tgt_port_wwn)) == 0) { 6164 break; 6165 } 6166 } 6167 6168 return (ptgt); 6169 } 6170 6171 6172 /* 6173 * Find target structure given a port identifier 6174 */ 6175 static struct fcp_tgt * 6176 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6177 { 6178 fc_portid_t port_id; 6179 la_wwn_t pwwn; 6180 struct fcp_tgt *ptgt = NULL; 6181 6182 port_id.priv_lilp_posit = 0; 6183 port_id.port_id = d_id; 6184 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6185 &pwwn) == FC_SUCCESS) { 6186 mutex_enter(&pptr->port_mutex); 6187 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6188 mutex_exit(&pptr->port_mutex); 6189 } 6190 6191 return (ptgt); 6192 } 6193 6194 6195 /* 6196 * the packet completion callback routine for info cmd pkts 6197 * 6198 * this means fpkt pts to a response to either a PLOGI or a PRLI 6199 * 6200 * if there is an error an attempt is made to call a routine to resend 6201 * the command that failed 6202 */ 6203 static void 6204 fcp_icmd_callback(fc_packet_t *fpkt) 6205 { 6206 struct fcp_ipkt *icmd; 6207 struct fcp_port *pptr; 6208 struct fcp_tgt *ptgt; 6209 struct la_els_prli *prli; 6210 struct la_els_prli prli_s; 6211 struct fcp_prli *fprli; 6212 struct fcp_lun *plun; 6213 int free_pkt = 1; 6214 int rval; 6215 ls_code_t resp; 6216 uchar_t prli_acc = 0; 6217 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6218 int lun0_newalloc; 6219 6220 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6221 6222 /* get ptrs to the port and target structs for the cmd */ 6223 pptr = icmd->ipkt_port; 6224 ptgt = icmd->ipkt_tgt; 6225 6226 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6227 6228 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6229 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6230 sizeof (prli_s)); 6231 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6232 } 6233 6234 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6235 fcp_trace, FCP_BUF_LEVEL_2, 0, 6236 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6237 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6238 ptgt->tgt_d_id); 6239 6240 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6241 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6242 6243 mutex_enter(&ptgt->tgt_mutex); 6244 if (ptgt->tgt_pd_handle == NULL) { 6245 /* 6246 * in a fabric environment the port device handles 6247 * get created only after successful LOGIN into the 6248 * transport, so the transport makes this port 6249 * device (pd) handle available in this packet, so 6250 * save it now 6251 */ 6252 ASSERT(fpkt->pkt_pd != NULL); 6253 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6254 } 6255 mutex_exit(&ptgt->tgt_mutex); 6256 6257 /* which ELS cmd is this response for ?? */ 6258 switch (icmd->ipkt_opcode) { 6259 case LA_ELS_PLOGI: 6260 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6261 fcp_trace, FCP_BUF_LEVEL_5, 0, 6262 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6263 ptgt->tgt_d_id, 6264 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6265 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6266 6267 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6268 FCP_TGT_TRACE_15); 6269 6270 /* Note that we are not allocating a new icmd */ 6271 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6272 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6273 icmd->ipkt_cause) != DDI_SUCCESS) { 6274 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6275 FCP_TGT_TRACE_16); 6276 goto fail; 6277 } 6278 break; 6279 6280 case LA_ELS_PRLI: 6281 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6282 fcp_trace, FCP_BUF_LEVEL_5, 0, 6283 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6284 6285 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6286 FCP_TGT_TRACE_17); 6287 6288 prli = &prli_s; 6289 6290 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6291 sizeof (prli_s)); 6292 6293 fprli = (struct fcp_prli *)prli->service_params; 6294 6295 mutex_enter(&ptgt->tgt_mutex); 6296 ptgt->tgt_icap = fprli->initiator_fn; 6297 ptgt->tgt_tcap = fprli->target_fn; 6298 mutex_exit(&ptgt->tgt_mutex); 6299 6300 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6301 /* 6302 * this FCP device does not support target mode 6303 */ 6304 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6305 FCP_TGT_TRACE_18); 6306 goto fail; 6307 } 6308 if (fprli->retry == 1) { 6309 fc_ulp_disable_relogin(pptr->port_fp_handle, 6310 &ptgt->tgt_port_wwn); 6311 } 6312 6313 /* target is no longer offline */ 6314 mutex_enter(&pptr->port_mutex); 6315 mutex_enter(&ptgt->tgt_mutex); 6316 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6317 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6318 FCP_TGT_MARK); 6319 } else { 6320 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6321 fcp_trace, FCP_BUF_LEVEL_2, 0, 6322 "fcp_icmd_callback,1: state change " 6323 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6324 mutex_exit(&ptgt->tgt_mutex); 6325 mutex_exit(&pptr->port_mutex); 6326 goto fail; 6327 } 6328 mutex_exit(&ptgt->tgt_mutex); 6329 mutex_exit(&pptr->port_mutex); 6330 6331 /* 6332 * lun 0 should always respond to inquiry, so 6333 * get the LUN struct for LUN 0 6334 * 6335 * Currently we deal with first level of addressing. 6336 * If / when we start supporting 0x device types 6337 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6338 * this logic will need revisiting. 6339 */ 6340 lun0_newalloc = 0; 6341 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6342 /* 6343 * no LUN struct for LUN 0 yet exists, 6344 * so create one 6345 */ 6346 plun = fcp_alloc_lun(ptgt); 6347 if (plun == NULL) { 6348 fcp_log(CE_WARN, pptr->port_dip, 6349 "!Failed to allocate lun 0 for" 6350 " D_ID=%x", ptgt->tgt_d_id); 6351 goto fail; 6352 } 6353 lun0_newalloc = 1; 6354 } 6355 6356 /* fill in LUN info */ 6357 mutex_enter(&ptgt->tgt_mutex); 6358 /* 6359 * consider lun 0 as device not connected if it is 6360 * offlined or newly allocated 6361 */ 6362 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6363 lun0_newalloc) { 6364 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6365 } 6366 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6367 plun->lun_state &= ~FCP_LUN_OFFLINE; 6368 ptgt->tgt_lun_cnt = 1; 6369 ptgt->tgt_report_lun_cnt = 0; 6370 mutex_exit(&ptgt->tgt_mutex); 6371 6372 /* Retrieve the rscn count (if a valid one exists) */ 6373 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6374 rscn_count = ((fc_ulp_rscn_info_t *) 6375 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6376 ->ulp_rscn_count; 6377 } else { 6378 rscn_count = FC_INVALID_RSCN_COUNT; 6379 } 6380 6381 /* send Report Lun request to target */ 6382 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6383 sizeof (struct fcp_reportlun_resp), 6384 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6385 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6386 mutex_enter(&pptr->port_mutex); 6387 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6388 fcp_log(CE_WARN, pptr->port_dip, 6389 "!Failed to send REPORT LUN to" 6390 " D_ID=%x", ptgt->tgt_d_id); 6391 } else { 6392 FCP_TRACE(fcp_logq, 6393 pptr->port_instbuf, fcp_trace, 6394 FCP_BUF_LEVEL_5, 0, 6395 "fcp_icmd_callback,2:state change" 6396 " occured for D_ID=0x%x", 6397 ptgt->tgt_d_id); 6398 } 6399 mutex_exit(&pptr->port_mutex); 6400 6401 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6402 FCP_TGT_TRACE_19); 6403 6404 goto fail; 6405 } else { 6406 free_pkt = 0; 6407 fcp_icmd_free(pptr, icmd); 6408 } 6409 break; 6410 6411 default: 6412 fcp_log(CE_WARN, pptr->port_dip, 6413 "!fcp_icmd_callback Invalid opcode"); 6414 goto fail; 6415 } 6416 6417 return; 6418 } 6419 6420 6421 /* 6422 * Other PLOGI failures are not retried as the 6423 * transport does it already 6424 */ 6425 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6426 if (fcp_is_retryable(icmd) && 6427 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6428 6429 if (FCP_MUST_RETRY(fpkt)) { 6430 fcp_queue_ipkt(pptr, fpkt); 6431 return; 6432 } 6433 6434 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6435 fcp_trace, FCP_BUF_LEVEL_2, 0, 6436 "ELS PRLI is retried for d_id=0x%x, state=%x," 6437 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6438 fpkt->pkt_reason); 6439 6440 /* 6441 * Retry by recalling the routine that 6442 * originally queued this packet 6443 */ 6444 mutex_enter(&pptr->port_mutex); 6445 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6446 caddr_t msg; 6447 6448 mutex_exit(&pptr->port_mutex); 6449 6450 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6451 6452 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6453 fpkt->pkt_timeout += 6454 FCP_TIMEOUT_DELTA; 6455 } 6456 6457 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6458 fpkt); 6459 if (rval == FC_SUCCESS) { 6460 return; 6461 } 6462 6463 if (rval == FC_STATEC_BUSY || 6464 rval == FC_OFFLINE) { 6465 fcp_queue_ipkt(pptr, fpkt); 6466 return; 6467 } 6468 (void) fc_ulp_error(rval, &msg); 6469 6470 fcp_log(CE_NOTE, pptr->port_dip, 6471 "!ELS 0x%x failed to d_id=0x%x;" 6472 " %s", icmd->ipkt_opcode, 6473 ptgt->tgt_d_id, msg); 6474 } else { 6475 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6476 fcp_trace, FCP_BUF_LEVEL_2, 0, 6477 "fcp_icmd_callback,3: state change " 6478 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6479 mutex_exit(&pptr->port_mutex); 6480 } 6481 } 6482 } else { 6483 if (fcp_is_retryable(icmd) && 6484 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6485 if (FCP_MUST_RETRY(fpkt)) { 6486 fcp_queue_ipkt(pptr, fpkt); 6487 return; 6488 } 6489 } 6490 mutex_enter(&pptr->port_mutex); 6491 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6492 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6493 mutex_exit(&pptr->port_mutex); 6494 fcp_print_error(fpkt); 6495 } else { 6496 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6497 fcp_trace, FCP_BUF_LEVEL_2, 0, 6498 "fcp_icmd_callback,4: state change occured" 6499 " for D_ID=0x%x", ptgt->tgt_d_id); 6500 mutex_exit(&pptr->port_mutex); 6501 } 6502 } 6503 6504 fail: 6505 if (free_pkt) { 6506 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6507 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6508 fcp_icmd_free(pptr, icmd); 6509 } 6510 } 6511 6512 6513 /* 6514 * called internally to send an info cmd using the transport 6515 * 6516 * sends either an INQ or a REPORT_LUN 6517 * 6518 * when the packet is completed fcp_scsi_callback is called 6519 */ 6520 static int 6521 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6522 int lcount, int tcount, int cause, uint32_t rscn_count) 6523 { 6524 int nodma; 6525 struct fcp_ipkt *icmd; 6526 struct fcp_tgt *ptgt; 6527 struct fcp_port *pptr; 6528 fc_frame_hdr_t *hp; 6529 fc_packet_t *fpkt; 6530 struct fcp_cmd fcp_cmd; 6531 struct fcp_cmd *fcmd; 6532 union scsi_cdb *scsi_cdb; 6533 6534 ASSERT(plun != NULL); 6535 6536 ptgt = plun->lun_tgt; 6537 ASSERT(ptgt != NULL); 6538 6539 pptr = ptgt->tgt_port; 6540 ASSERT(pptr != NULL); 6541 6542 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6543 fcp_trace, FCP_BUF_LEVEL_5, 0, 6544 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6545 6546 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6547 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6548 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6549 rscn_count); 6550 6551 if (icmd == NULL) { 6552 return (DDI_FAILURE); 6553 } 6554 6555 fpkt = icmd->ipkt_fpkt; 6556 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6557 icmd->ipkt_retries = 0; 6558 icmd->ipkt_opcode = opcode; 6559 icmd->ipkt_lun = plun; 6560 6561 if (nodma) { 6562 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6563 } else { 6564 fcmd = &fcp_cmd; 6565 } 6566 bzero(fcmd, sizeof (struct fcp_cmd)); 6567 6568 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6569 6570 hp = &fpkt->pkt_cmd_fhdr; 6571 6572 hp->s_id = pptr->port_id; 6573 hp->d_id = ptgt->tgt_d_id; 6574 hp->r_ctl = R_CTL_COMMAND; 6575 hp->type = FC_TYPE_SCSI_FCP; 6576 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6577 hp->rsvd = 0; 6578 hp->seq_id = 0; 6579 hp->seq_cnt = 0; 6580 hp->ox_id = 0xffff; 6581 hp->rx_id = 0xffff; 6582 hp->ro = 0; 6583 6584 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6585 6586 /* 6587 * Request SCSI target for expedited processing 6588 */ 6589 6590 /* 6591 * Set up for untagged queuing because we do not 6592 * know if the fibre device supports queuing. 6593 */ 6594 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6595 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6596 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6597 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6598 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6599 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6600 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6601 6602 switch (opcode) { 6603 case SCMD_INQUIRY_PAGE83: 6604 /* 6605 * Prepare to get the Inquiry VPD page 83 information 6606 */ 6607 fcmd->fcp_cntl.cntl_read_data = 1; 6608 fcmd->fcp_cntl.cntl_write_data = 0; 6609 fcmd->fcp_data_len = alloc_len; 6610 6611 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6612 fpkt->pkt_comp = fcp_scsi_callback; 6613 6614 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6615 scsi_cdb->g0_addr2 = 0x01; 6616 scsi_cdb->g0_addr1 = 0x83; 6617 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6618 break; 6619 6620 case SCMD_INQUIRY: 6621 fcmd->fcp_cntl.cntl_read_data = 1; 6622 fcmd->fcp_cntl.cntl_write_data = 0; 6623 fcmd->fcp_data_len = alloc_len; 6624 6625 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6626 fpkt->pkt_comp = fcp_scsi_callback; 6627 6628 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6629 scsi_cdb->g0_count0 = SUN_INQSIZE; 6630 break; 6631 6632 case SCMD_REPORT_LUN: { 6633 fc_portid_t d_id; 6634 opaque_t fca_dev; 6635 6636 ASSERT(alloc_len >= 16); 6637 6638 d_id.priv_lilp_posit = 0; 6639 d_id.port_id = ptgt->tgt_d_id; 6640 6641 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6642 6643 mutex_enter(&ptgt->tgt_mutex); 6644 ptgt->tgt_fca_dev = fca_dev; 6645 mutex_exit(&ptgt->tgt_mutex); 6646 6647 fcmd->fcp_cntl.cntl_read_data = 1; 6648 fcmd->fcp_cntl.cntl_write_data = 0; 6649 fcmd->fcp_data_len = alloc_len; 6650 6651 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6652 fpkt->pkt_comp = fcp_scsi_callback; 6653 6654 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6655 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6656 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6657 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6658 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6659 break; 6660 } 6661 6662 default: 6663 fcp_log(CE_WARN, pptr->port_dip, 6664 "!fcp_send_scsi Invalid opcode"); 6665 break; 6666 } 6667 6668 if (!nodma) { 6669 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6670 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6671 } 6672 6673 mutex_enter(&pptr->port_mutex); 6674 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6675 6676 mutex_exit(&pptr->port_mutex); 6677 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6678 FC_SUCCESS) { 6679 fcp_icmd_free(pptr, icmd); 6680 return (DDI_FAILURE); 6681 } 6682 return (DDI_SUCCESS); 6683 } else { 6684 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6685 fcp_trace, FCP_BUF_LEVEL_2, 0, 6686 "fcp_send_scsi,1: state change occured" 6687 " for D_ID=0x%x", ptgt->tgt_d_id); 6688 mutex_exit(&pptr->port_mutex); 6689 fcp_icmd_free(pptr, icmd); 6690 return (DDI_FAILURE); 6691 } 6692 } 6693 6694 6695 /* 6696 * called by fcp_scsi_callback to check to handle the case where 6697 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6698 */ 6699 static int 6700 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6701 { 6702 uchar_t rqlen; 6703 int rval = DDI_FAILURE; 6704 struct scsi_extended_sense sense_info, *sense; 6705 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6706 fpkt->pkt_ulp_private; 6707 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6708 struct fcp_port *pptr = ptgt->tgt_port; 6709 6710 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6711 6712 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6713 /* 6714 * SCSI-II Reserve Release support. Some older FC drives return 6715 * Reservation conflict for Report Luns command. 6716 */ 6717 if (icmd->ipkt_nodma) { 6718 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6719 rsp->fcp_u.fcp_status.sense_len_set = 0; 6720 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6721 } else { 6722 fcp_rsp_t new_resp; 6723 6724 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6725 fpkt->pkt_resp_acc, sizeof (new_resp)); 6726 6727 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6728 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6729 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6730 6731 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6732 fpkt->pkt_resp_acc, sizeof (new_resp)); 6733 } 6734 6735 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6736 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6737 6738 return (DDI_SUCCESS); 6739 } 6740 6741 sense = &sense_info; 6742 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6743 /* no need to continue if sense length is not set */ 6744 return (rval); 6745 } 6746 6747 /* casting 64-bit integer to 8-bit */ 6748 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6749 sizeof (struct scsi_extended_sense)); 6750 6751 if (rqlen < 14) { 6752 /* no need to continue if request length isn't long enough */ 6753 return (rval); 6754 } 6755 6756 if (icmd->ipkt_nodma) { 6757 /* 6758 * We can safely use fcp_response_len here since the 6759 * only path that calls fcp_check_reportlun, 6760 * fcp_scsi_callback, has already called 6761 * fcp_validate_fcp_response. 6762 */ 6763 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6764 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6765 } else { 6766 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6767 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6768 sizeof (struct scsi_extended_sense)); 6769 } 6770 6771 if (!FCP_SENSE_NO_LUN(sense)) { 6772 mutex_enter(&ptgt->tgt_mutex); 6773 /* clear the flag if any */ 6774 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6775 mutex_exit(&ptgt->tgt_mutex); 6776 } 6777 6778 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6779 (sense->es_add_code == 0x20)) { 6780 if (icmd->ipkt_nodma) { 6781 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6782 rsp->fcp_u.fcp_status.sense_len_set = 0; 6783 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6784 } else { 6785 fcp_rsp_t new_resp; 6786 6787 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6788 fpkt->pkt_resp_acc, sizeof (new_resp)); 6789 6790 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6791 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6792 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6793 6794 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6795 fpkt->pkt_resp_acc, sizeof (new_resp)); 6796 } 6797 6798 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6799 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6800 6801 return (DDI_SUCCESS); 6802 } 6803 6804 /* 6805 * This is for the STK library which returns a check condition, 6806 * to indicate device is not ready, manual assistance needed. 6807 * This is to a report lun command when the door is open. 6808 */ 6809 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6810 if (icmd->ipkt_nodma) { 6811 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6812 rsp->fcp_u.fcp_status.sense_len_set = 0; 6813 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6814 } else { 6815 fcp_rsp_t new_resp; 6816 6817 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6818 fpkt->pkt_resp_acc, sizeof (new_resp)); 6819 6820 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6821 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6822 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6823 6824 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6825 fpkt->pkt_resp_acc, sizeof (new_resp)); 6826 } 6827 6828 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6829 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6830 6831 return (DDI_SUCCESS); 6832 } 6833 6834 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6835 (FCP_SENSE_NO_LUN(sense))) { 6836 mutex_enter(&ptgt->tgt_mutex); 6837 if ((FCP_SENSE_NO_LUN(sense)) && 6838 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6839 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6840 mutex_exit(&ptgt->tgt_mutex); 6841 /* 6842 * reconfig was triggred by ILLEGAL REQUEST but 6843 * got ILLEGAL REQUEST again 6844 */ 6845 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6846 fcp_trace, FCP_BUF_LEVEL_3, 0, 6847 "!FCP: Unable to obtain Report Lun data" 6848 " target=%x", ptgt->tgt_d_id); 6849 } else { 6850 if (ptgt->tgt_tid == NULL) { 6851 timeout_id_t tid; 6852 /* 6853 * REPORT LUN data has changed. Kick off 6854 * rediscovery 6855 */ 6856 tid = timeout(fcp_reconfigure_luns, 6857 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6858 6859 ptgt->tgt_tid = tid; 6860 ptgt->tgt_state |= FCP_TGT_BUSY; 6861 } 6862 if (FCP_SENSE_NO_LUN(sense)) { 6863 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6864 } 6865 mutex_exit(&ptgt->tgt_mutex); 6866 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6867 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6868 fcp_trace, FCP_BUF_LEVEL_3, 0, 6869 "!FCP:Report Lun Has Changed" 6870 " target=%x", ptgt->tgt_d_id); 6871 } else if (FCP_SENSE_NO_LUN(sense)) { 6872 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6873 fcp_trace, FCP_BUF_LEVEL_3, 0, 6874 "!FCP:LU Not Supported" 6875 " target=%x", ptgt->tgt_d_id); 6876 } 6877 } 6878 rval = DDI_SUCCESS; 6879 } 6880 6881 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6882 fcp_trace, FCP_BUF_LEVEL_5, 0, 6883 "D_ID=%x, sense=%x, status=%x", 6884 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6885 rsp->fcp_u.fcp_status.scsi_status); 6886 6887 return (rval); 6888 } 6889 6890 /* 6891 * Function: fcp_scsi_callback 6892 * 6893 * Description: This is the callback routine set by fcp_send_scsi() after 6894 * it calls fcp_icmd_alloc(). The SCSI command completed here 6895 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6896 * INQUIRY_PAGE83. 6897 * 6898 * Argument: *fpkt FC packet used to convey the command 6899 * 6900 * Return Value: None 6901 */ 6902 static void 6903 fcp_scsi_callback(fc_packet_t *fpkt) 6904 { 6905 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6906 fpkt->pkt_ulp_private; 6907 struct fcp_rsp_info fcp_rsp_err, *bep; 6908 struct fcp_port *pptr; 6909 struct fcp_tgt *ptgt; 6910 struct fcp_lun *plun; 6911 struct fcp_rsp response, *rsp; 6912 6913 ptgt = icmd->ipkt_tgt; 6914 pptr = ptgt->tgt_port; 6915 plun = icmd->ipkt_lun; 6916 6917 if (icmd->ipkt_nodma) { 6918 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6919 } else { 6920 rsp = &response; 6921 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6922 sizeof (struct fcp_rsp)); 6923 } 6924 6925 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6926 fcp_trace, FCP_BUF_LEVEL_2, 0, 6927 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6928 "status=%x, lun num=%x", 6929 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6930 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6931 6932 /* 6933 * Pre-init LUN GUID with NWWN if it is not a device that 6934 * supports multiple luns and we know it's not page83 6935 * compliant. Although using a NWWN is not lun unique, 6936 * we will be fine since there is only one lun behind the taget 6937 * in this case. 6938 */ 6939 if ((plun->lun_guid_size == 0) && 6940 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6941 (fcp_symmetric_device_probe(plun) == 0)) { 6942 6943 char ascii_wwn[FC_WWN_SIZE*2+1]; 6944 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6945 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6946 } 6947 6948 /* 6949 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6950 * when thay have more data than what is asked in CDB. An overrun 6951 * is really when FCP_DL is smaller than the data length in CDB. 6952 * In the case here we know that REPORT LUN command we formed within 6953 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6954 * behavior. In reality this is FC_SUCCESS. 6955 */ 6956 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6957 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6958 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6959 fpkt->pkt_state = FC_PKT_SUCCESS; 6960 } 6961 6962 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6963 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6964 fcp_trace, FCP_BUF_LEVEL_2, 0, 6965 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6966 ptgt->tgt_d_id); 6967 6968 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6969 /* 6970 * Inquiry VPD page command on A5K SES devices would 6971 * result in data CRC errors. 6972 */ 6973 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6974 (void) fcp_handle_page83(fpkt, icmd, 1); 6975 return; 6976 } 6977 } 6978 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6979 FCP_MUST_RETRY(fpkt)) { 6980 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6981 fcp_retry_scsi_cmd(fpkt); 6982 return; 6983 } 6984 6985 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6986 FCP_TGT_TRACE_20); 6987 6988 mutex_enter(&pptr->port_mutex); 6989 mutex_enter(&ptgt->tgt_mutex); 6990 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6991 mutex_exit(&ptgt->tgt_mutex); 6992 mutex_exit(&pptr->port_mutex); 6993 fcp_print_error(fpkt); 6994 } else { 6995 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6996 fcp_trace, FCP_BUF_LEVEL_2, 0, 6997 "fcp_scsi_callback,1: state change occured" 6998 " for D_ID=0x%x", ptgt->tgt_d_id); 6999 mutex_exit(&ptgt->tgt_mutex); 7000 mutex_exit(&pptr->port_mutex); 7001 } 7002 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7003 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7004 fcp_icmd_free(pptr, icmd); 7005 return; 7006 } 7007 7008 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 7009 7010 mutex_enter(&pptr->port_mutex); 7011 mutex_enter(&ptgt->tgt_mutex); 7012 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7013 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7014 fcp_trace, FCP_BUF_LEVEL_2, 0, 7015 "fcp_scsi_callback,2: state change occured" 7016 " for D_ID=0x%x", ptgt->tgt_d_id); 7017 mutex_exit(&ptgt->tgt_mutex); 7018 mutex_exit(&pptr->port_mutex); 7019 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7020 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7021 fcp_icmd_free(pptr, icmd); 7022 return; 7023 } 7024 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7025 7026 mutex_exit(&ptgt->tgt_mutex); 7027 mutex_exit(&pptr->port_mutex); 7028 7029 if (icmd->ipkt_nodma) { 7030 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7031 sizeof (struct fcp_rsp)); 7032 } else { 7033 bep = &fcp_rsp_err; 7034 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7035 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7036 } 7037 7038 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7039 fcp_retry_scsi_cmd(fpkt); 7040 return; 7041 } 7042 7043 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7044 FCP_NO_FAILURE) { 7045 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7046 fcp_trace, FCP_BUF_LEVEL_2, 0, 7047 "rsp_code=0x%x, rsp_len_set=0x%x", 7048 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7049 fcp_retry_scsi_cmd(fpkt); 7050 return; 7051 } 7052 7053 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7054 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7055 fcp_queue_ipkt(pptr, fpkt); 7056 return; 7057 } 7058 7059 /* 7060 * Devices that do not support INQUIRY_PAGE83, return check condition 7061 * with illegal request as per SCSI spec. 7062 * Crossbridge is one such device and Daktari's SES node is another. 7063 * We want to ideally enumerate these devices as a non-mpxio devices. 7064 * SES nodes (Daktari only currently) are an exception to this. 7065 */ 7066 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7067 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7068 7069 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7070 fcp_trace, FCP_BUF_LEVEL_3, 0, 7071 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7072 "check condition. May enumerate as non-mpxio device", 7073 ptgt->tgt_d_id, plun->lun_type); 7074 7075 /* 7076 * If we let Daktari's SES be enumerated as a non-mpxio 7077 * device, there will be a discrepency in that the other 7078 * internal FC disks will get enumerated as mpxio devices. 7079 * Applications like luxadm expect this to be consistent. 7080 * 7081 * So, we put in a hack here to check if this is an SES device 7082 * and handle it here. 7083 */ 7084 if (plun->lun_type == DTYPE_ESI) { 7085 /* 7086 * Since, pkt_state is actually FC_PKT_SUCCESS 7087 * at this stage, we fake a failure here so that 7088 * fcp_handle_page83 will create a device path using 7089 * the WWN instead of the GUID which is not there anyway 7090 */ 7091 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7092 (void) fcp_handle_page83(fpkt, icmd, 1); 7093 return; 7094 } 7095 7096 mutex_enter(&ptgt->tgt_mutex); 7097 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7098 FCP_LUN_MARK | FCP_LUN_BUSY); 7099 mutex_exit(&ptgt->tgt_mutex); 7100 7101 (void) fcp_call_finish_init(pptr, ptgt, 7102 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7103 icmd->ipkt_cause); 7104 fcp_icmd_free(pptr, icmd); 7105 return; 7106 } 7107 7108 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7109 int rval = DDI_FAILURE; 7110 7111 /* 7112 * handle cases where report lun isn't supported 7113 * by faking up our own REPORT_LUN response or 7114 * UNIT ATTENTION 7115 */ 7116 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7117 rval = fcp_check_reportlun(rsp, fpkt); 7118 7119 /* 7120 * fcp_check_reportlun might have modified the 7121 * FCP response. Copy it in again to get an updated 7122 * FCP response 7123 */ 7124 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7125 rsp = &response; 7126 7127 FCP_CP_IN(fpkt->pkt_resp, rsp, 7128 fpkt->pkt_resp_acc, 7129 sizeof (struct fcp_rsp)); 7130 } 7131 } 7132 7133 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7134 if (rval == DDI_SUCCESS) { 7135 (void) fcp_call_finish_init(pptr, ptgt, 7136 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7137 icmd->ipkt_cause); 7138 fcp_icmd_free(pptr, icmd); 7139 } else { 7140 fcp_retry_scsi_cmd(fpkt); 7141 } 7142 7143 return; 7144 } 7145 } else { 7146 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7147 mutex_enter(&ptgt->tgt_mutex); 7148 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7149 mutex_exit(&ptgt->tgt_mutex); 7150 } 7151 } 7152 7153 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7154 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7155 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7156 DDI_DMA_SYNC_FORCPU); 7157 } 7158 7159 switch (icmd->ipkt_opcode) { 7160 case SCMD_INQUIRY: 7161 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7162 fcp_handle_inquiry(fpkt, icmd); 7163 break; 7164 7165 case SCMD_REPORT_LUN: 7166 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7167 FCP_TGT_TRACE_22); 7168 fcp_handle_reportlun(fpkt, icmd); 7169 break; 7170 7171 case SCMD_INQUIRY_PAGE83: 7172 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7173 (void) fcp_handle_page83(fpkt, icmd, 0); 7174 break; 7175 7176 default: 7177 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7178 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7179 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7180 fcp_icmd_free(pptr, icmd); 7181 break; 7182 } 7183 } 7184 7185 7186 static void 7187 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7188 { 7189 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7190 fpkt->pkt_ulp_private; 7191 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7192 struct fcp_port *pptr = ptgt->tgt_port; 7193 7194 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7195 fcp_is_retryable(icmd)) { 7196 mutex_enter(&pptr->port_mutex); 7197 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7198 mutex_exit(&pptr->port_mutex); 7199 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7200 fcp_trace, FCP_BUF_LEVEL_3, 0, 7201 "Retrying %s to %x; state=%x, reason=%x", 7202 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7203 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7204 fpkt->pkt_state, fpkt->pkt_reason); 7205 7206 fcp_queue_ipkt(pptr, fpkt); 7207 } else { 7208 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7209 fcp_trace, FCP_BUF_LEVEL_3, 0, 7210 "fcp_retry_scsi_cmd,1: state change occured" 7211 " for D_ID=0x%x", ptgt->tgt_d_id); 7212 mutex_exit(&pptr->port_mutex); 7213 (void) fcp_call_finish_init(pptr, ptgt, 7214 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7215 icmd->ipkt_cause); 7216 fcp_icmd_free(pptr, icmd); 7217 } 7218 } else { 7219 fcp_print_error(fpkt); 7220 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7221 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7222 fcp_icmd_free(pptr, icmd); 7223 } 7224 } 7225 7226 /* 7227 * Function: fcp_handle_page83 7228 * 7229 * Description: Treats the response to INQUIRY_PAGE83. 7230 * 7231 * Argument: *fpkt FC packet used to convey the command. 7232 * *icmd Original fcp_ipkt structure. 7233 * ignore_page83_data 7234 * if it's 1, that means it's a special devices's 7235 * page83 response, it should be enumerated under mpxio 7236 * 7237 * Return Value: None 7238 */ 7239 static void 7240 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7241 int ignore_page83_data) 7242 { 7243 struct fcp_port *pptr; 7244 struct fcp_lun *plun; 7245 struct fcp_tgt *ptgt; 7246 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7247 int fail = 0; 7248 ddi_devid_t devid; 7249 char *guid = NULL; 7250 int ret; 7251 7252 ASSERT(icmd != NULL && fpkt != NULL); 7253 7254 pptr = icmd->ipkt_port; 7255 ptgt = icmd->ipkt_tgt; 7256 plun = icmd->ipkt_lun; 7257 7258 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7259 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7260 7261 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7262 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7263 7264 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7265 fcp_trace, FCP_BUF_LEVEL_5, 0, 7266 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7267 "dtype=0x%x, lun num=%x", 7268 pptr->port_instance, ptgt->tgt_d_id, 7269 dev_id_page[0], plun->lun_num); 7270 7271 ret = ddi_devid_scsi_encode( 7272 DEVID_SCSI_ENCODE_VERSION_LATEST, 7273 NULL, /* driver name */ 7274 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7275 sizeof (plun->lun_inq), /* size of standard inquiry */ 7276 NULL, /* page 80 data */ 7277 0, /* page 80 len */ 7278 dev_id_page, /* page 83 data */ 7279 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7280 &devid); 7281 7282 if (ret == DDI_SUCCESS) { 7283 7284 guid = ddi_devid_to_guid(devid); 7285 7286 if (guid) { 7287 /* 7288 * Check our current guid. If it's non null 7289 * and it has changed, we need to copy it into 7290 * lun_old_guid since we might still need it. 7291 */ 7292 if (plun->lun_guid && 7293 strcmp(guid, plun->lun_guid)) { 7294 unsigned int len; 7295 7296 /* 7297 * If the guid of the LUN changes, 7298 * reconfiguration should be triggered 7299 * to reflect the changes. 7300 * i.e. we should offline the LUN with 7301 * the old guid, and online the LUN with 7302 * the new guid. 7303 */ 7304 plun->lun_state |= FCP_LUN_CHANGED; 7305 7306 if (plun->lun_old_guid) { 7307 kmem_free(plun->lun_old_guid, 7308 plun->lun_old_guid_size); 7309 } 7310 7311 len = plun->lun_guid_size; 7312 plun->lun_old_guid_size = len; 7313 7314 plun->lun_old_guid = kmem_zalloc(len, 7315 KM_NOSLEEP); 7316 7317 if (plun->lun_old_guid) { 7318 /* 7319 * The alloc was successful then 7320 * let's do the copy. 7321 */ 7322 bcopy(plun->lun_guid, 7323 plun->lun_old_guid, len); 7324 } else { 7325 fail = 1; 7326 plun->lun_old_guid_size = 0; 7327 } 7328 } 7329 if (!fail) { 7330 if (fcp_copy_guid_2_lun_block( 7331 plun, guid)) { 7332 fail = 1; 7333 } 7334 } 7335 ddi_devid_free_guid(guid); 7336 7337 } else { 7338 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7339 fcp_trace, FCP_BUF_LEVEL_2, 0, 7340 "fcp_handle_page83: unable to create " 7341 "GUID"); 7342 7343 /* couldn't create good guid from devid */ 7344 fail = 1; 7345 } 7346 ddi_devid_free(devid); 7347 7348 } else if (ret == DDI_NOT_WELL_FORMED) { 7349 /* NULL filled data for page 83 */ 7350 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7351 fcp_trace, FCP_BUF_LEVEL_2, 0, 7352 "fcp_handle_page83: retry GUID"); 7353 7354 icmd->ipkt_retries = 0; 7355 fcp_retry_scsi_cmd(fpkt); 7356 return; 7357 } else { 7358 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7359 fcp_trace, FCP_BUF_LEVEL_2, 0, 7360 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7361 ret); 7362 /* 7363 * Since the page83 validation 7364 * introduced late, we are being 7365 * tolerant to the existing devices 7366 * that already found to be working 7367 * under mpxio, like A5200's SES device, 7368 * its page83 response will not be standard-compliant, 7369 * but we still want it to be enumerated under mpxio. 7370 */ 7371 if (fcp_symmetric_device_probe(plun) != 0) { 7372 fail = 1; 7373 } 7374 } 7375 7376 } else { 7377 /* bad packet state */ 7378 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7379 7380 /* 7381 * For some special devices (A5K SES and Daktari's SES devices), 7382 * they should be enumerated under mpxio 7383 * or "luxadm dis" will fail 7384 */ 7385 if (ignore_page83_data) { 7386 fail = 0; 7387 } else { 7388 fail = 1; 7389 } 7390 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7391 fcp_trace, FCP_BUF_LEVEL_2, 0, 7392 "!Devid page cmd failed. " 7393 "fpkt_state: %x fpkt_reason: %x", 7394 "ignore_page83: %d", 7395 fpkt->pkt_state, fpkt->pkt_reason, 7396 ignore_page83_data); 7397 } 7398 7399 mutex_enter(&pptr->port_mutex); 7400 mutex_enter(&plun->lun_mutex); 7401 /* 7402 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7403 * mismatch between lun_cip and lun_mpxio. 7404 */ 7405 if (plun->lun_cip == NULL) { 7406 /* 7407 * If we don't have a guid for this lun it's because we were 7408 * unable to glean one from the page 83 response. Set the 7409 * control flag to 0 here to make sure that we don't attempt to 7410 * enumerate it under mpxio. 7411 */ 7412 if (fail || pptr->port_mpxio == 0) { 7413 plun->lun_mpxio = 0; 7414 } else { 7415 plun->lun_mpxio = 1; 7416 } 7417 } 7418 mutex_exit(&plun->lun_mutex); 7419 mutex_exit(&pptr->port_mutex); 7420 7421 mutex_enter(&ptgt->tgt_mutex); 7422 plun->lun_state &= 7423 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7424 mutex_exit(&ptgt->tgt_mutex); 7425 7426 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7427 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7428 7429 fcp_icmd_free(pptr, icmd); 7430 } 7431 7432 /* 7433 * Function: fcp_handle_inquiry 7434 * 7435 * Description: Called by fcp_scsi_callback to handle the response to an 7436 * INQUIRY request. 7437 * 7438 * Argument: *fpkt FC packet used to convey the command. 7439 * *icmd Original fcp_ipkt structure. 7440 * 7441 * Return Value: None 7442 */ 7443 static void 7444 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7445 { 7446 struct fcp_port *pptr; 7447 struct fcp_lun *plun; 7448 struct fcp_tgt *ptgt; 7449 uchar_t dtype; 7450 uchar_t pqual; 7451 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7452 7453 ASSERT(icmd != NULL && fpkt != NULL); 7454 7455 pptr = icmd->ipkt_port; 7456 ptgt = icmd->ipkt_tgt; 7457 plun = icmd->ipkt_lun; 7458 7459 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7460 sizeof (struct scsi_inquiry)); 7461 7462 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7463 pqual = plun->lun_inq.inq_dtype >> 5; 7464 7465 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7466 fcp_trace, FCP_BUF_LEVEL_5, 0, 7467 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7468 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7469 plun->lun_num, dtype, pqual); 7470 7471 if (pqual != 0) { 7472 /* 7473 * Non-zero peripheral qualifier 7474 */ 7475 fcp_log(CE_CONT, pptr->port_dip, 7476 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7477 "Device type=0x%x Peripheral qual=0x%x\n", 7478 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7479 7480 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7481 fcp_trace, FCP_BUF_LEVEL_5, 0, 7482 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7483 "Device type=0x%x Peripheral qual=0x%x\n", 7484 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7485 7486 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7487 7488 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7489 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7490 fcp_icmd_free(pptr, icmd); 7491 return; 7492 } 7493 7494 /* 7495 * If the device is already initialized, check the dtype 7496 * for a change. If it has changed then update the flags 7497 * so the create_luns will offline the old device and 7498 * create the new device. Refer to bug: 4764752 7499 */ 7500 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7501 plun->lun_state |= FCP_LUN_CHANGED; 7502 } 7503 plun->lun_type = plun->lun_inq.inq_dtype; 7504 7505 /* 7506 * This code is setting/initializing the throttling in the FCA 7507 * driver. 7508 */ 7509 mutex_enter(&pptr->port_mutex); 7510 if (!pptr->port_notify) { 7511 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7512 uint32_t cmd = 0; 7513 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7514 ((cmd & 0xFFFFFF00 >> 8) | 7515 FCP_SVE_THROTTLE << 8)); 7516 pptr->port_notify = 1; 7517 mutex_exit(&pptr->port_mutex); 7518 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7519 mutex_enter(&pptr->port_mutex); 7520 } 7521 } 7522 7523 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7524 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7525 fcp_trace, FCP_BUF_LEVEL_2, 0, 7526 "fcp_handle_inquiry,1:state change occured" 7527 " for D_ID=0x%x", ptgt->tgt_d_id); 7528 mutex_exit(&pptr->port_mutex); 7529 7530 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7531 (void) fcp_call_finish_init(pptr, ptgt, 7532 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7533 icmd->ipkt_cause); 7534 fcp_icmd_free(pptr, icmd); 7535 return; 7536 } 7537 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7538 mutex_exit(&pptr->port_mutex); 7539 7540 /* Retrieve the rscn count (if a valid one exists) */ 7541 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7542 rscn_count = ((fc_ulp_rscn_info_t *) 7543 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7544 } else { 7545 rscn_count = FC_INVALID_RSCN_COUNT; 7546 } 7547 7548 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7549 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7550 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7551 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7552 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7553 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7554 (void) fcp_call_finish_init(pptr, ptgt, 7555 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7556 icmd->ipkt_cause); 7557 } 7558 7559 /* 7560 * Read Inquiry VPD Page 0x83 to uniquely 7561 * identify this logical unit. 7562 */ 7563 fcp_icmd_free(pptr, icmd); 7564 } 7565 7566 /* 7567 * Function: fcp_handle_reportlun 7568 * 7569 * Description: Called by fcp_scsi_callback to handle the response to a 7570 * REPORT_LUN request. 7571 * 7572 * Argument: *fpkt FC packet used to convey the command. 7573 * *icmd Original fcp_ipkt structure. 7574 * 7575 * Return Value: None 7576 */ 7577 static void 7578 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7579 { 7580 int i; 7581 int nluns_claimed; 7582 int nluns_bufmax; 7583 int len; 7584 uint16_t lun_num; 7585 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7586 struct fcp_port *pptr; 7587 struct fcp_tgt *ptgt; 7588 struct fcp_lun *plun; 7589 struct fcp_reportlun_resp *report_lun; 7590 7591 pptr = icmd->ipkt_port; 7592 ptgt = icmd->ipkt_tgt; 7593 len = fpkt->pkt_datalen; 7594 7595 if ((len < FCP_LUN_HEADER) || 7596 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7597 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7598 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7599 fcp_icmd_free(pptr, icmd); 7600 return; 7601 } 7602 7603 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7604 fpkt->pkt_datalen); 7605 7606 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7607 fcp_trace, FCP_BUF_LEVEL_5, 0, 7608 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7609 pptr->port_instance, ptgt->tgt_d_id); 7610 7611 /* 7612 * Get the number of luns (which is supplied as LUNS * 8) the 7613 * device claims it has. 7614 */ 7615 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7616 7617 /* 7618 * Get the maximum number of luns the buffer submitted can hold. 7619 */ 7620 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7621 7622 /* 7623 * Due to limitations of certain hardware, we support only 16 bit LUNs 7624 */ 7625 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7626 kmem_free(report_lun, len); 7627 7628 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7629 " 0x%x number of LUNs for target=%x", nluns_claimed, 7630 ptgt->tgt_d_id); 7631 7632 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7633 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7634 fcp_icmd_free(pptr, icmd); 7635 return; 7636 } 7637 7638 /* 7639 * If there are more LUNs than we have allocated memory for, 7640 * allocate more space and send down yet another report lun if 7641 * the maximum number of attempts hasn't been reached. 7642 */ 7643 mutex_enter(&ptgt->tgt_mutex); 7644 7645 if ((nluns_claimed > nluns_bufmax) && 7646 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7647 7648 struct fcp_lun *plun; 7649 7650 ptgt->tgt_report_lun_cnt++; 7651 plun = ptgt->tgt_lun; 7652 ASSERT(plun != NULL); 7653 mutex_exit(&ptgt->tgt_mutex); 7654 7655 kmem_free(report_lun, len); 7656 7657 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7658 fcp_trace, FCP_BUF_LEVEL_5, 0, 7659 "!Dynamically discovered %d LUNs for D_ID=%x", 7660 nluns_claimed, ptgt->tgt_d_id); 7661 7662 /* Retrieve the rscn count (if a valid one exists) */ 7663 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7664 rscn_count = ((fc_ulp_rscn_info_t *) 7665 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7666 ulp_rscn_count; 7667 } else { 7668 rscn_count = FC_INVALID_RSCN_COUNT; 7669 } 7670 7671 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7672 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7673 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7674 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7675 (void) fcp_call_finish_init(pptr, ptgt, 7676 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7677 icmd->ipkt_cause); 7678 } 7679 7680 fcp_icmd_free(pptr, icmd); 7681 return; 7682 } 7683 7684 if (nluns_claimed > nluns_bufmax) { 7685 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7686 fcp_trace, FCP_BUF_LEVEL_5, 0, 7687 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7688 " Number of LUNs lost=%x", 7689 ptgt->tgt_port_wwn.raw_wwn[0], 7690 ptgt->tgt_port_wwn.raw_wwn[1], 7691 ptgt->tgt_port_wwn.raw_wwn[2], 7692 ptgt->tgt_port_wwn.raw_wwn[3], 7693 ptgt->tgt_port_wwn.raw_wwn[4], 7694 ptgt->tgt_port_wwn.raw_wwn[5], 7695 ptgt->tgt_port_wwn.raw_wwn[6], 7696 ptgt->tgt_port_wwn.raw_wwn[7], 7697 nluns_claimed - nluns_bufmax); 7698 7699 nluns_claimed = nluns_bufmax; 7700 } 7701 ptgt->tgt_lun_cnt = nluns_claimed; 7702 7703 /* 7704 * Identify missing LUNs and print warning messages 7705 */ 7706 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7707 int offline; 7708 int exists = 0; 7709 7710 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7711 7712 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7713 uchar_t *lun_string; 7714 7715 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7716 7717 switch (lun_string[0] & 0xC0) { 7718 case FCP_LUN_ADDRESSING: 7719 case FCP_PD_ADDRESSING: 7720 case FCP_VOLUME_ADDRESSING: 7721 lun_num = ((lun_string[0] & 0x3F) << 8) | 7722 lun_string[1]; 7723 if (plun->lun_num == lun_num) { 7724 exists++; 7725 break; 7726 } 7727 break; 7728 7729 default: 7730 break; 7731 } 7732 } 7733 7734 if (!exists && !offline) { 7735 mutex_exit(&ptgt->tgt_mutex); 7736 7737 mutex_enter(&pptr->port_mutex); 7738 mutex_enter(&ptgt->tgt_mutex); 7739 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7740 /* 7741 * set disappear flag when device was connected 7742 */ 7743 if (!(plun->lun_state & 7744 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7745 plun->lun_state |= FCP_LUN_DISAPPEARED; 7746 } 7747 mutex_exit(&ptgt->tgt_mutex); 7748 mutex_exit(&pptr->port_mutex); 7749 if (!(plun->lun_state & 7750 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7751 fcp_log(CE_NOTE, pptr->port_dip, 7752 "!Lun=%x for target=%x disappeared", 7753 plun->lun_num, ptgt->tgt_d_id); 7754 } 7755 mutex_enter(&ptgt->tgt_mutex); 7756 } else { 7757 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7758 fcp_trace, FCP_BUF_LEVEL_5, 0, 7759 "fcp_handle_reportlun,1: state change" 7760 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7761 mutex_exit(&ptgt->tgt_mutex); 7762 mutex_exit(&pptr->port_mutex); 7763 kmem_free(report_lun, len); 7764 (void) fcp_call_finish_init(pptr, ptgt, 7765 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7766 icmd->ipkt_cause); 7767 fcp_icmd_free(pptr, icmd); 7768 return; 7769 } 7770 } else if (exists) { 7771 /* 7772 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7773 * actually exists in REPORT_LUN response 7774 */ 7775 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7776 plun->lun_state &= 7777 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7778 } 7779 if (offline || plun->lun_num == 0) { 7780 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7781 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7782 mutex_exit(&ptgt->tgt_mutex); 7783 fcp_log(CE_NOTE, pptr->port_dip, 7784 "!Lun=%x for target=%x reappeared", 7785 plun->lun_num, ptgt->tgt_d_id); 7786 mutex_enter(&ptgt->tgt_mutex); 7787 } 7788 } 7789 } 7790 } 7791 7792 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7793 mutex_exit(&ptgt->tgt_mutex); 7794 7795 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7796 fcp_trace, FCP_BUF_LEVEL_5, 0, 7797 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7798 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7799 7800 /* scan each lun */ 7801 for (i = 0; i < nluns_claimed; i++) { 7802 uchar_t *lun_string; 7803 7804 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7805 7806 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7807 fcp_trace, FCP_BUF_LEVEL_5, 0, 7808 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7809 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7810 lun_string[0]); 7811 7812 switch (lun_string[0] & 0xC0) { 7813 case FCP_LUN_ADDRESSING: 7814 case FCP_PD_ADDRESSING: 7815 case FCP_VOLUME_ADDRESSING: 7816 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7817 7818 /* We will skip masked LUNs because of the blacklist. */ 7819 if (fcp_lun_blacklist != NULL) { 7820 mutex_enter(&ptgt->tgt_mutex); 7821 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7822 lun_num) == TRUE) { 7823 ptgt->tgt_lun_cnt--; 7824 mutex_exit(&ptgt->tgt_mutex); 7825 break; 7826 } 7827 mutex_exit(&ptgt->tgt_mutex); 7828 } 7829 7830 /* see if this LUN is already allocated */ 7831 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7832 plun = fcp_alloc_lun(ptgt); 7833 if (plun == NULL) { 7834 fcp_log(CE_NOTE, pptr->port_dip, 7835 "!Lun allocation failed" 7836 " target=%x lun=%x", 7837 ptgt->tgt_d_id, lun_num); 7838 break; 7839 } 7840 } 7841 7842 mutex_enter(&plun->lun_tgt->tgt_mutex); 7843 /* convert to LUN */ 7844 plun->lun_addr.ent_addr_0 = 7845 BE_16(*(uint16_t *)&(lun_string[0])); 7846 plun->lun_addr.ent_addr_1 = 7847 BE_16(*(uint16_t *)&(lun_string[2])); 7848 plun->lun_addr.ent_addr_2 = 7849 BE_16(*(uint16_t *)&(lun_string[4])); 7850 plun->lun_addr.ent_addr_3 = 7851 BE_16(*(uint16_t *)&(lun_string[6])); 7852 7853 plun->lun_num = lun_num; 7854 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7855 plun->lun_state &= ~FCP_LUN_OFFLINE; 7856 mutex_exit(&plun->lun_tgt->tgt_mutex); 7857 7858 /* Retrieve the rscn count (if a valid one exists) */ 7859 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7860 rscn_count = ((fc_ulp_rscn_info_t *) 7861 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7862 ulp_rscn_count; 7863 } else { 7864 rscn_count = FC_INVALID_RSCN_COUNT; 7865 } 7866 7867 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7868 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7869 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7870 mutex_enter(&pptr->port_mutex); 7871 mutex_enter(&plun->lun_tgt->tgt_mutex); 7872 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7873 fcp_log(CE_NOTE, pptr->port_dip, 7874 "!failed to send INQUIRY" 7875 " target=%x lun=%x", 7876 ptgt->tgt_d_id, plun->lun_num); 7877 } else { 7878 FCP_TRACE(fcp_logq, 7879 pptr->port_instbuf, fcp_trace, 7880 FCP_BUF_LEVEL_5, 0, 7881 "fcp_handle_reportlun,2: state" 7882 " change occured for D_ID=0x%x", 7883 ptgt->tgt_d_id); 7884 } 7885 mutex_exit(&plun->lun_tgt->tgt_mutex); 7886 mutex_exit(&pptr->port_mutex); 7887 } else { 7888 continue; 7889 } 7890 break; 7891 7892 default: 7893 fcp_log(CE_WARN, NULL, 7894 "!Unsupported LUN Addressing method %x " 7895 "in response to REPORT_LUN", lun_string[0]); 7896 break; 7897 } 7898 7899 /* 7900 * each time through this loop we should decrement 7901 * the tmp_cnt by one -- since we go through this loop 7902 * one time for each LUN, the tmp_cnt should never be <=0 7903 */ 7904 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7905 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7906 } 7907 7908 if (i == 0) { 7909 fcp_log(CE_WARN, pptr->port_dip, 7910 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7911 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7912 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7913 } 7914 7915 kmem_free(report_lun, len); 7916 fcp_icmd_free(pptr, icmd); 7917 } 7918 7919 7920 /* 7921 * called internally to return a LUN given a target and a LUN number 7922 */ 7923 static struct fcp_lun * 7924 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7925 { 7926 struct fcp_lun *plun; 7927 7928 mutex_enter(&ptgt->tgt_mutex); 7929 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7930 if (plun->lun_num == lun_num) { 7931 mutex_exit(&ptgt->tgt_mutex); 7932 return (plun); 7933 } 7934 } 7935 mutex_exit(&ptgt->tgt_mutex); 7936 7937 return (NULL); 7938 } 7939 7940 7941 /* 7942 * handle finishing one target for fcp_finish_init 7943 * 7944 * return true (non-zero) if we want finish_init to continue with the 7945 * next target 7946 * 7947 * called with the port mutex held 7948 */ 7949 /*ARGSUSED*/ 7950 static int 7951 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7952 int link_cnt, int tgt_cnt, int cause) 7953 { 7954 int rval = 1; 7955 ASSERT(pptr != NULL); 7956 ASSERT(ptgt != NULL); 7957 7958 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7959 fcp_trace, FCP_BUF_LEVEL_5, 0, 7960 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7961 ptgt->tgt_state); 7962 7963 ASSERT(mutex_owned(&pptr->port_mutex)); 7964 7965 if ((pptr->port_link_cnt != link_cnt) || 7966 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7967 /* 7968 * oh oh -- another link reset or target change 7969 * must have occurred while we are in here 7970 */ 7971 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7972 7973 return (0); 7974 } else { 7975 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7976 } 7977 7978 mutex_enter(&ptgt->tgt_mutex); 7979 7980 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7981 /* 7982 * tgt is not offline -- is it marked (i.e. needs 7983 * to be offlined) ?? 7984 */ 7985 if (ptgt->tgt_state & FCP_TGT_MARK) { 7986 /* 7987 * this target not offline *and* 7988 * marked 7989 */ 7990 ptgt->tgt_state &= ~FCP_TGT_MARK; 7991 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7992 tgt_cnt, 0, 0); 7993 } else { 7994 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7995 7996 /* create the LUNs */ 7997 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7998 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7999 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 8000 cause); 8001 ptgt->tgt_device_created = 1; 8002 } else { 8003 fcp_update_tgt_state(ptgt, FCP_RESET, 8004 FCP_LUN_BUSY); 8005 } 8006 } 8007 } 8008 8009 mutex_exit(&ptgt->tgt_mutex); 8010 8011 return (rval); 8012 } 8013 8014 8015 /* 8016 * this routine is called to finish port initialization 8017 * 8018 * Each port has a "temp" counter -- when a state change happens (e.g. 8019 * port online), the temp count is set to the number of devices in the map. 8020 * Then, as each device gets "discovered", the temp counter is decremented 8021 * by one. When this count reaches zero we know that all of the devices 8022 * in the map have been discovered (or an error has occurred), so we can 8023 * then finish initialization -- which is done by this routine (well, this 8024 * and fcp-finish_tgt()) 8025 * 8026 * acquires and releases the global mutex 8027 * 8028 * called with the port mutex owned 8029 */ 8030 static void 8031 fcp_finish_init(struct fcp_port *pptr) 8032 { 8033 #ifdef DEBUG 8034 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8035 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8036 FCP_STACK_DEPTH); 8037 #endif /* DEBUG */ 8038 8039 ASSERT(mutex_owned(&pptr->port_mutex)); 8040 8041 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8042 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8043 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8044 8045 if ((pptr->port_state & FCP_STATE_ONLINING) && 8046 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8047 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8048 pptr->port_state &= ~FCP_STATE_ONLINING; 8049 pptr->port_state |= FCP_STATE_ONLINE; 8050 } 8051 8052 /* Wake up threads waiting on config done */ 8053 cv_broadcast(&pptr->port_config_cv); 8054 } 8055 8056 8057 /* 8058 * called from fcp_finish_init to create the LUNs for a target 8059 * 8060 * called with the port mutex owned 8061 */ 8062 static void 8063 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8064 { 8065 struct fcp_lun *plun; 8066 struct fcp_port *pptr; 8067 child_info_t *cip = NULL; 8068 8069 ASSERT(ptgt != NULL); 8070 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8071 8072 pptr = ptgt->tgt_port; 8073 8074 ASSERT(pptr != NULL); 8075 8076 /* scan all LUNs for this target */ 8077 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8078 if (plun->lun_state & FCP_LUN_OFFLINE) { 8079 continue; 8080 } 8081 8082 if (plun->lun_state & FCP_LUN_MARK) { 8083 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8084 fcp_trace, FCP_BUF_LEVEL_2, 0, 8085 "fcp_create_luns: offlining marked LUN!"); 8086 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8087 continue; 8088 } 8089 8090 plun->lun_state &= ~FCP_LUN_BUSY; 8091 8092 /* 8093 * There are conditions in which FCP_LUN_INIT flag is cleared 8094 * but we have a valid plun->lun_cip. To cover this case also 8095 * CLEAR_BUSY whenever we have a valid lun_cip. 8096 */ 8097 if (plun->lun_mpxio && plun->lun_cip && 8098 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8099 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8100 0, 0))) { 8101 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8102 fcp_trace, FCP_BUF_LEVEL_2, 0, 8103 "fcp_create_luns: enable lun %p failed!", 8104 plun); 8105 } 8106 8107 if (plun->lun_state & FCP_LUN_INIT && 8108 !(plun->lun_state & FCP_LUN_CHANGED)) { 8109 continue; 8110 } 8111 8112 if (cause == FCP_CAUSE_USER_CREATE) { 8113 continue; 8114 } 8115 8116 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8117 fcp_trace, FCP_BUF_LEVEL_6, 0, 8118 "create_luns: passing ONLINE elem to HP thread"); 8119 8120 /* 8121 * If lun has changed, prepare for offlining the old path. 8122 * Do not offline the old path right now, since it may be 8123 * still opened. 8124 */ 8125 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8126 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8127 } 8128 8129 /* pass an ONLINE element to the hotplug thread */ 8130 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8131 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8132 8133 /* 8134 * We can not synchronous attach (i.e pass 8135 * NDI_ONLINE_ATTACH) here as we might be 8136 * coming from an interrupt or callback 8137 * thread. 8138 */ 8139 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8140 link_cnt, tgt_cnt, 0, 0)) { 8141 fcp_log(CE_CONT, pptr->port_dip, 8142 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8143 plun->lun_tgt->tgt_d_id, plun->lun_num); 8144 } 8145 } 8146 } 8147 } 8148 8149 8150 /* 8151 * function to online/offline devices 8152 */ 8153 static int 8154 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8155 int online, int lcount, int tcount, int flags) 8156 { 8157 int rval = NDI_FAILURE; 8158 int circ; 8159 child_info_t *ccip; 8160 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8161 int is_mpxio = pptr->port_mpxio; 8162 8163 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8164 /* 8165 * When this event gets serviced, lun_cip and lun_mpxio 8166 * has changed, so it should be invalidated now. 8167 */ 8168 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8169 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8170 "plun: %p, cip: %p, what:%d", plun, cip, online); 8171 return (rval); 8172 } 8173 8174 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8175 fcp_trace, FCP_BUF_LEVEL_2, 0, 8176 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8177 "flags=%x mpxio=%x\n", 8178 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8179 plun->lun_mpxio); 8180 8181 /* 8182 * lun_mpxio needs checking here because we can end up in a race 8183 * condition where this task has been dispatched while lun_mpxio is 8184 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8185 * enable MPXIO for the LUN, but was unable to, and hence cleared 8186 * the flag. We rely on the serialization of the tasks here. We return 8187 * NDI_SUCCESS so any callers continue without reporting spurious 8188 * errors, and the still think we're an MPXIO LUN. 8189 */ 8190 8191 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8192 online == FCP_MPXIO_PATH_SET_BUSY) { 8193 if (plun->lun_mpxio) { 8194 rval = fcp_update_mpxio_path(plun, cip, online); 8195 } else { 8196 rval = NDI_SUCCESS; 8197 } 8198 return (rval); 8199 } 8200 8201 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8202 return (NDI_FAILURE); 8203 } 8204 8205 if (is_mpxio) { 8206 mdi_devi_enter(pptr->port_dip, &circ); 8207 } else { 8208 ndi_devi_enter(pptr->port_dip, &circ); 8209 } 8210 8211 mutex_enter(&pptr->port_mutex); 8212 mutex_enter(&plun->lun_mutex); 8213 8214 if (online == FCP_ONLINE) { 8215 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8216 if (ccip == NULL) { 8217 goto fail; 8218 } 8219 } else { 8220 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8221 goto fail; 8222 } 8223 ccip = cip; 8224 } 8225 8226 if (online == FCP_ONLINE) { 8227 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8228 &circ); 8229 fc_ulp_log_device_event(pptr->port_fp_handle, 8230 FC_ULP_DEVICE_ONLINE); 8231 } else { 8232 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8233 &circ); 8234 fc_ulp_log_device_event(pptr->port_fp_handle, 8235 FC_ULP_DEVICE_OFFLINE); 8236 } 8237 8238 fail: mutex_exit(&plun->lun_mutex); 8239 mutex_exit(&pptr->port_mutex); 8240 8241 if (is_mpxio) { 8242 mdi_devi_exit(pptr->port_dip, circ); 8243 } else { 8244 ndi_devi_exit(pptr->port_dip, circ); 8245 } 8246 8247 fc_ulp_idle_port(pptr->port_fp_handle); 8248 8249 return (rval); 8250 } 8251 8252 8253 /* 8254 * take a target offline by taking all of its LUNs offline 8255 */ 8256 /*ARGSUSED*/ 8257 static int 8258 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8259 int link_cnt, int tgt_cnt, int nowait, int flags) 8260 { 8261 struct fcp_tgt_elem *elem; 8262 8263 ASSERT(mutex_owned(&pptr->port_mutex)); 8264 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8265 8266 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8267 8268 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8269 ptgt->tgt_change_cnt)) { 8270 mutex_exit(&ptgt->tgt_mutex); 8271 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8272 mutex_enter(&ptgt->tgt_mutex); 8273 8274 return (0); 8275 } 8276 8277 ptgt->tgt_pd_handle = NULL; 8278 mutex_exit(&ptgt->tgt_mutex); 8279 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8280 mutex_enter(&ptgt->tgt_mutex); 8281 8282 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8283 8284 if (ptgt->tgt_tcap && 8285 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8286 elem->flags = flags; 8287 elem->time = fcp_watchdog_time; 8288 if (nowait == 0) { 8289 elem->time += fcp_offline_delay; 8290 } 8291 elem->ptgt = ptgt; 8292 elem->link_cnt = link_cnt; 8293 elem->tgt_cnt = tgt_cnt; 8294 elem->next = pptr->port_offline_tgts; 8295 pptr->port_offline_tgts = elem; 8296 } else { 8297 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8298 } 8299 8300 return (1); 8301 } 8302 8303 8304 static void 8305 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8306 int link_cnt, int tgt_cnt, int flags) 8307 { 8308 ASSERT(mutex_owned(&pptr->port_mutex)); 8309 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8310 8311 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8312 ptgt->tgt_state = FCP_TGT_OFFLINE; 8313 ptgt->tgt_pd_handle = NULL; 8314 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8315 } 8316 8317 8318 static void 8319 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8320 int flags) 8321 { 8322 struct fcp_lun *plun; 8323 8324 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8325 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8326 8327 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8328 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8329 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8330 } 8331 } 8332 } 8333 8334 8335 /* 8336 * take a LUN offline 8337 * 8338 * enters and leaves with the target mutex held, releasing it in the process 8339 * 8340 * allocates memory in non-sleep mode 8341 */ 8342 static void 8343 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8344 int nowait, int flags) 8345 { 8346 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8347 struct fcp_lun_elem *elem; 8348 8349 ASSERT(plun != NULL); 8350 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8351 8352 if (nowait) { 8353 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8354 return; 8355 } 8356 8357 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8358 elem->flags = flags; 8359 elem->time = fcp_watchdog_time; 8360 if (nowait == 0) { 8361 elem->time += fcp_offline_delay; 8362 } 8363 elem->plun = plun; 8364 elem->link_cnt = link_cnt; 8365 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8366 elem->next = pptr->port_offline_luns; 8367 pptr->port_offline_luns = elem; 8368 } else { 8369 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8370 } 8371 } 8372 8373 8374 static void 8375 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8376 { 8377 struct fcp_pkt *head = NULL; 8378 8379 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8380 8381 mutex_exit(&LUN_TGT->tgt_mutex); 8382 8383 head = fcp_scan_commands(plun); 8384 if (head != NULL) { 8385 fcp_abort_commands(head, LUN_PORT); 8386 } 8387 8388 mutex_enter(&LUN_TGT->tgt_mutex); 8389 8390 if (plun->lun_cip && plun->lun_mpxio) { 8391 /* 8392 * Intimate MPxIO lun busy is cleared 8393 */ 8394 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8395 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8396 0, 0)) { 8397 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8398 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8399 LUN_TGT->tgt_d_id, plun->lun_num); 8400 } 8401 /* 8402 * Intimate MPxIO that the lun is now marked for offline 8403 */ 8404 mutex_exit(&LUN_TGT->tgt_mutex); 8405 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8406 mutex_enter(&LUN_TGT->tgt_mutex); 8407 } 8408 } 8409 8410 static void 8411 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8412 int flags) 8413 { 8414 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8415 8416 mutex_exit(&LUN_TGT->tgt_mutex); 8417 fcp_update_offline_flags(plun); 8418 mutex_enter(&LUN_TGT->tgt_mutex); 8419 8420 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8421 8422 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8423 fcp_trace, FCP_BUF_LEVEL_4, 0, 8424 "offline_lun: passing OFFLINE elem to HP thread"); 8425 8426 if (plun->lun_cip) { 8427 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8428 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8429 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8430 LUN_TGT->tgt_trace); 8431 8432 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8433 link_cnt, tgt_cnt, flags, 0)) { 8434 fcp_log(CE_CONT, LUN_PORT->port_dip, 8435 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8436 LUN_TGT->tgt_d_id, plun->lun_num); 8437 } 8438 } 8439 } 8440 8441 static void 8442 fcp_scan_offline_luns(struct fcp_port *pptr) 8443 { 8444 struct fcp_lun_elem *elem; 8445 struct fcp_lun_elem *prev; 8446 struct fcp_lun_elem *next; 8447 8448 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8449 8450 prev = NULL; 8451 elem = pptr->port_offline_luns; 8452 while (elem) { 8453 next = elem->next; 8454 if (elem->time <= fcp_watchdog_time) { 8455 int changed = 1; 8456 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8457 8458 mutex_enter(&ptgt->tgt_mutex); 8459 if (pptr->port_link_cnt == elem->link_cnt && 8460 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8461 changed = 0; 8462 } 8463 8464 if (!changed && 8465 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8466 fcp_offline_lun_now(elem->plun, 8467 elem->link_cnt, elem->tgt_cnt, elem->flags); 8468 } 8469 mutex_exit(&ptgt->tgt_mutex); 8470 8471 kmem_free(elem, sizeof (*elem)); 8472 8473 if (prev) { 8474 prev->next = next; 8475 } else { 8476 pptr->port_offline_luns = next; 8477 } 8478 } else { 8479 prev = elem; 8480 } 8481 elem = next; 8482 } 8483 } 8484 8485 8486 static void 8487 fcp_scan_offline_tgts(struct fcp_port *pptr) 8488 { 8489 struct fcp_tgt_elem *elem; 8490 struct fcp_tgt_elem *prev; 8491 struct fcp_tgt_elem *next; 8492 8493 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8494 8495 prev = NULL; 8496 elem = pptr->port_offline_tgts; 8497 while (elem) { 8498 next = elem->next; 8499 if (elem->time <= fcp_watchdog_time) { 8500 int outdated = 1; 8501 struct fcp_tgt *ptgt = elem->ptgt; 8502 8503 mutex_enter(&ptgt->tgt_mutex); 8504 8505 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8506 /* No change on tgt since elem was created. */ 8507 outdated = 0; 8508 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8509 pptr->port_link_cnt == elem->link_cnt + 1 && 8510 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8511 /* 8512 * Exactly one thing happened to the target 8513 * inbetween: the local port went offline. 8514 * For fp the remote port is already gone so 8515 * it will not tell us again to offline the 8516 * target. We must offline it now. 8517 */ 8518 outdated = 0; 8519 } 8520 8521 if (!outdated && !(ptgt->tgt_state & 8522 FCP_TGT_OFFLINE)) { 8523 fcp_offline_target_now(pptr, 8524 ptgt, elem->link_cnt, elem->tgt_cnt, 8525 elem->flags); 8526 } 8527 8528 mutex_exit(&ptgt->tgt_mutex); 8529 8530 kmem_free(elem, sizeof (*elem)); 8531 8532 if (prev) { 8533 prev->next = next; 8534 } else { 8535 pptr->port_offline_tgts = next; 8536 } 8537 } else { 8538 prev = elem; 8539 } 8540 elem = next; 8541 } 8542 } 8543 8544 8545 static void 8546 fcp_update_offline_flags(struct fcp_lun *plun) 8547 { 8548 struct fcp_port *pptr = LUN_PORT; 8549 ASSERT(plun != NULL); 8550 8551 mutex_enter(&LUN_TGT->tgt_mutex); 8552 plun->lun_state |= FCP_LUN_OFFLINE; 8553 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8554 8555 mutex_enter(&plun->lun_mutex); 8556 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8557 dev_info_t *cdip = NULL; 8558 8559 mutex_exit(&LUN_TGT->tgt_mutex); 8560 8561 if (plun->lun_mpxio == 0) { 8562 cdip = DIP(plun->lun_cip); 8563 } else if (plun->lun_cip) { 8564 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8565 } 8566 8567 mutex_exit(&plun->lun_mutex); 8568 if (cdip) { 8569 (void) ndi_event_retrieve_cookie( 8570 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8571 &fcp_remove_eid, NDI_EVENT_NOPASS); 8572 (void) ndi_event_run_callbacks( 8573 pptr->port_ndi_event_hdl, cdip, 8574 fcp_remove_eid, NULL); 8575 } 8576 } else { 8577 mutex_exit(&plun->lun_mutex); 8578 mutex_exit(&LUN_TGT->tgt_mutex); 8579 } 8580 } 8581 8582 8583 /* 8584 * Scan all of the command pkts for this port, moving pkts that 8585 * match our LUN onto our own list (headed by "head") 8586 */ 8587 static struct fcp_pkt * 8588 fcp_scan_commands(struct fcp_lun *plun) 8589 { 8590 struct fcp_port *pptr = LUN_PORT; 8591 8592 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8593 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8594 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8595 8596 struct fcp_pkt *head = NULL; /* head of our list */ 8597 struct fcp_pkt *tail = NULL; /* tail of our list */ 8598 8599 int cmds_found = 0; 8600 8601 mutex_enter(&pptr->port_pkt_mutex); 8602 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8603 struct fcp_lun *tlun = 8604 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8605 8606 ncmd = cmd->cmd_next; /* set next command */ 8607 8608 /* 8609 * if this pkt is for a different LUN or the 8610 * command is sent down, skip it. 8611 */ 8612 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8613 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8614 pcmd = cmd; 8615 continue; 8616 } 8617 cmds_found++; 8618 if (pcmd != NULL) { 8619 ASSERT(pptr->port_pkt_head != cmd); 8620 pcmd->cmd_next = cmd->cmd_next; 8621 } else { 8622 ASSERT(cmd == pptr->port_pkt_head); 8623 pptr->port_pkt_head = cmd->cmd_next; 8624 } 8625 8626 if (cmd == pptr->port_pkt_tail) { 8627 pptr->port_pkt_tail = pcmd; 8628 if (pcmd) { 8629 pcmd->cmd_next = NULL; 8630 } 8631 } 8632 8633 if (head == NULL) { 8634 head = tail = cmd; 8635 } else { 8636 ASSERT(tail != NULL); 8637 8638 tail->cmd_next = cmd; 8639 tail = cmd; 8640 } 8641 cmd->cmd_next = NULL; 8642 } 8643 mutex_exit(&pptr->port_pkt_mutex); 8644 8645 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8646 fcp_trace, FCP_BUF_LEVEL_8, 0, 8647 "scan commands: %d cmd(s) found", cmds_found); 8648 8649 return (head); 8650 } 8651 8652 8653 /* 8654 * Abort all the commands in the command queue 8655 */ 8656 static void 8657 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8658 { 8659 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8660 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8661 8662 ASSERT(mutex_owned(&pptr->port_mutex)); 8663 8664 /* scan through the pkts and invalid them */ 8665 for (cmd = head; cmd != NULL; cmd = ncmd) { 8666 struct scsi_pkt *pkt = cmd->cmd_pkt; 8667 8668 ncmd = cmd->cmd_next; 8669 ASSERT(pkt != NULL); 8670 8671 /* 8672 * The lun is going to be marked offline. Indicate 8673 * the target driver not to requeue or retry this command 8674 * as the device is going to be offlined pretty soon. 8675 */ 8676 pkt->pkt_reason = CMD_DEV_GONE; 8677 pkt->pkt_statistics = 0; 8678 pkt->pkt_state = 0; 8679 8680 /* reset cmd flags/state */ 8681 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8682 cmd->cmd_state = FCP_PKT_IDLE; 8683 8684 /* 8685 * ensure we have a packet completion routine, 8686 * then call it. 8687 */ 8688 ASSERT(pkt->pkt_comp != NULL); 8689 8690 mutex_exit(&pptr->port_mutex); 8691 fcp_post_callback(cmd); 8692 mutex_enter(&pptr->port_mutex); 8693 } 8694 } 8695 8696 8697 /* 8698 * the pkt_comp callback for command packets 8699 */ 8700 static void 8701 fcp_cmd_callback(fc_packet_t *fpkt) 8702 { 8703 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8704 struct scsi_pkt *pkt = cmd->cmd_pkt; 8705 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8706 8707 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8708 8709 if (cmd->cmd_state == FCP_PKT_IDLE) { 8710 cmn_err(CE_PANIC, "Packet already completed %p", 8711 (void *)cmd); 8712 } 8713 8714 /* 8715 * Watch thread should be freeing the packet, ignore the pkt. 8716 */ 8717 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8718 fcp_log(CE_CONT, pptr->port_dip, 8719 "!FCP: Pkt completed while aborting\n"); 8720 return; 8721 } 8722 cmd->cmd_state = FCP_PKT_IDLE; 8723 8724 fcp_complete_pkt(fpkt); 8725 8726 #ifdef DEBUG 8727 mutex_enter(&pptr->port_pkt_mutex); 8728 pptr->port_npkts--; 8729 mutex_exit(&pptr->port_pkt_mutex); 8730 #endif /* DEBUG */ 8731 8732 fcp_post_callback(cmd); 8733 } 8734 8735 8736 static void 8737 fcp_complete_pkt(fc_packet_t *fpkt) 8738 { 8739 int error = 0; 8740 struct fcp_pkt *cmd = (struct fcp_pkt *) 8741 fpkt->pkt_ulp_private; 8742 struct scsi_pkt *pkt = cmd->cmd_pkt; 8743 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8744 struct fcp_lun *plun; 8745 struct fcp_tgt *ptgt; 8746 struct fcp_rsp *rsp; 8747 struct scsi_address save; 8748 8749 #ifdef DEBUG 8750 save = pkt->pkt_address; 8751 #endif /* DEBUG */ 8752 8753 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8754 8755 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8756 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8757 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8758 sizeof (struct fcp_rsp)); 8759 } 8760 8761 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8762 STATE_SENT_CMD | STATE_GOT_STATUS; 8763 8764 pkt->pkt_resid = 0; 8765 8766 if (fpkt->pkt_datalen) { 8767 pkt->pkt_state |= STATE_XFERRED_DATA; 8768 if (fpkt->pkt_data_resid) { 8769 error++; 8770 } 8771 } 8772 8773 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8774 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8775 /* 8776 * The next two checks make sure that if there 8777 * is no sense data or a valid response and 8778 * the command came back with check condition, 8779 * the command should be retried. 8780 */ 8781 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8782 !rsp->fcp_u.fcp_status.sense_len_set) { 8783 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8784 pkt->pkt_resid = cmd->cmd_dmacount; 8785 } 8786 } 8787 8788 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8789 return; 8790 } 8791 8792 plun = ADDR2LUN(&pkt->pkt_address); 8793 ptgt = plun->lun_tgt; 8794 ASSERT(ptgt != NULL); 8795 8796 /* 8797 * Update the transfer resid, if appropriate 8798 */ 8799 if (rsp->fcp_u.fcp_status.resid_over || 8800 rsp->fcp_u.fcp_status.resid_under) { 8801 pkt->pkt_resid = rsp->fcp_resid; 8802 } 8803 8804 /* 8805 * First see if we got a FCP protocol error. 8806 */ 8807 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8808 struct fcp_rsp_info *bep; 8809 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8810 sizeof (struct fcp_rsp)); 8811 8812 if (fcp_validate_fcp_response(rsp, pptr) != 8813 FC_SUCCESS) { 8814 pkt->pkt_reason = CMD_CMPLT; 8815 *(pkt->pkt_scbp) = STATUS_CHECK; 8816 8817 fcp_log(CE_WARN, pptr->port_dip, 8818 "!SCSI command to d_id=0x%x lun=0x%x" 8819 " failed, Bad FCP response values:" 8820 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8821 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8822 ptgt->tgt_d_id, plun->lun_num, 8823 rsp->reserved_0, rsp->reserved_1, 8824 rsp->fcp_u.fcp_status.reserved_0, 8825 rsp->fcp_u.fcp_status.reserved_1, 8826 rsp->fcp_response_len, rsp->fcp_sense_len); 8827 8828 return; 8829 } 8830 8831 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8832 FCP_CP_IN(fpkt->pkt_resp + 8833 sizeof (struct fcp_rsp), bep, 8834 fpkt->pkt_resp_acc, 8835 sizeof (struct fcp_rsp_info)); 8836 } 8837 8838 if (bep->rsp_code != FCP_NO_FAILURE) { 8839 child_info_t *cip; 8840 8841 pkt->pkt_reason = CMD_TRAN_ERR; 8842 8843 mutex_enter(&plun->lun_mutex); 8844 cip = plun->lun_cip; 8845 mutex_exit(&plun->lun_mutex); 8846 8847 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8848 fcp_trace, FCP_BUF_LEVEL_2, 0, 8849 "FCP response error on cmd=%p" 8850 " target=0x%x, cip=%p", cmd, 8851 ptgt->tgt_d_id, cip); 8852 } 8853 } 8854 8855 /* 8856 * See if we got a SCSI error with sense data 8857 */ 8858 if (rsp->fcp_u.fcp_status.sense_len_set) { 8859 uchar_t rqlen; 8860 caddr_t sense_from; 8861 child_info_t *cip; 8862 timeout_id_t tid; 8863 struct scsi_arq_status *arq; 8864 struct scsi_extended_sense *sense_to; 8865 8866 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8867 sense_to = &arq->sts_sensedata; 8868 8869 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8870 sizeof (struct scsi_extended_sense)); 8871 8872 sense_from = (caddr_t)fpkt->pkt_resp + 8873 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8874 8875 if (fcp_validate_fcp_response(rsp, pptr) != 8876 FC_SUCCESS) { 8877 pkt->pkt_reason = CMD_CMPLT; 8878 *(pkt->pkt_scbp) = STATUS_CHECK; 8879 8880 fcp_log(CE_WARN, pptr->port_dip, 8881 "!SCSI command to d_id=0x%x lun=0x%x" 8882 " failed, Bad FCP response values:" 8883 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8884 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8885 ptgt->tgt_d_id, plun->lun_num, 8886 rsp->reserved_0, rsp->reserved_1, 8887 rsp->fcp_u.fcp_status.reserved_0, 8888 rsp->fcp_u.fcp_status.reserved_1, 8889 rsp->fcp_response_len, rsp->fcp_sense_len); 8890 8891 return; 8892 } 8893 8894 /* 8895 * copy in sense information 8896 */ 8897 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8898 FCP_CP_IN(sense_from, sense_to, 8899 fpkt->pkt_resp_acc, rqlen); 8900 } else { 8901 bcopy(sense_from, sense_to, rqlen); 8902 } 8903 8904 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8905 (FCP_SENSE_NO_LUN(sense_to))) { 8906 mutex_enter(&ptgt->tgt_mutex); 8907 if (ptgt->tgt_tid == NULL) { 8908 /* 8909 * Kick off rediscovery 8910 */ 8911 tid = timeout(fcp_reconfigure_luns, 8912 (caddr_t)ptgt, drv_usectohz(1)); 8913 8914 ptgt->tgt_tid = tid; 8915 ptgt->tgt_state |= FCP_TGT_BUSY; 8916 } 8917 mutex_exit(&ptgt->tgt_mutex); 8918 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8919 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8920 fcp_trace, FCP_BUF_LEVEL_3, 0, 8921 "!FCP: Report Lun Has Changed" 8922 " target=%x", ptgt->tgt_d_id); 8923 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8924 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8925 fcp_trace, FCP_BUF_LEVEL_3, 0, 8926 "!FCP: LU Not Supported" 8927 " target=%x", ptgt->tgt_d_id); 8928 } 8929 } 8930 ASSERT(pkt->pkt_scbp != NULL); 8931 8932 pkt->pkt_state |= STATE_ARQ_DONE; 8933 8934 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8935 8936 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8937 arq->sts_rqpkt_reason = 0; 8938 arq->sts_rqpkt_statistics = 0; 8939 8940 arq->sts_rqpkt_state = STATE_GOT_BUS | 8941 STATE_GOT_TARGET | STATE_SENT_CMD | 8942 STATE_GOT_STATUS | STATE_ARQ_DONE | 8943 STATE_XFERRED_DATA; 8944 8945 mutex_enter(&plun->lun_mutex); 8946 cip = plun->lun_cip; 8947 mutex_exit(&plun->lun_mutex); 8948 8949 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8950 fcp_trace, FCP_BUF_LEVEL_8, 0, 8951 "SCSI Check condition on cmd=%p target=0x%x" 8952 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8953 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8954 cmd->cmd_fcp_cmd.fcp_cdb[0], 8955 rsp->fcp_u.fcp_status.scsi_status, 8956 sense_to->es_key, sense_to->es_add_code, 8957 sense_to->es_qual_code); 8958 } 8959 } else { 8960 plun = ADDR2LUN(&pkt->pkt_address); 8961 ptgt = plun->lun_tgt; 8962 ASSERT(ptgt != NULL); 8963 8964 /* 8965 * Work harder to translate errors into target driver 8966 * understandable ones. Note with despair that the target 8967 * drivers don't decode pkt_state and pkt_reason exhaustively 8968 * They resort to using the big hammer most often, which 8969 * may not get fixed in the life time of this driver. 8970 */ 8971 pkt->pkt_state = 0; 8972 pkt->pkt_statistics = 0; 8973 8974 switch (fpkt->pkt_state) { 8975 case FC_PKT_TRAN_ERROR: 8976 switch (fpkt->pkt_reason) { 8977 case FC_REASON_OVERRUN: 8978 pkt->pkt_reason = CMD_CMD_OVR; 8979 pkt->pkt_statistics |= STAT_ABORTED; 8980 break; 8981 8982 case FC_REASON_XCHG_BSY: { 8983 caddr_t ptr; 8984 8985 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8986 8987 ptr = (caddr_t)pkt->pkt_scbp; 8988 if (ptr) { 8989 *ptr = STATUS_BUSY; 8990 } 8991 break; 8992 } 8993 8994 case FC_REASON_ABORTED: 8995 pkt->pkt_reason = CMD_TRAN_ERR; 8996 pkt->pkt_statistics |= STAT_ABORTED; 8997 break; 8998 8999 case FC_REASON_ABORT_FAILED: 9000 pkt->pkt_reason = CMD_ABORT_FAIL; 9001 break; 9002 9003 case FC_REASON_NO_SEQ_INIT: 9004 case FC_REASON_CRC_ERROR: 9005 pkt->pkt_reason = CMD_TRAN_ERR; 9006 pkt->pkt_statistics |= STAT_ABORTED; 9007 break; 9008 default: 9009 pkt->pkt_reason = CMD_TRAN_ERR; 9010 break; 9011 } 9012 break; 9013 9014 case FC_PKT_PORT_OFFLINE: { 9015 dev_info_t *cdip = NULL; 9016 caddr_t ptr; 9017 9018 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9019 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9020 fcp_trace, FCP_BUF_LEVEL_8, 0, 9021 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9022 ptgt->tgt_d_id); 9023 } 9024 9025 mutex_enter(&plun->lun_mutex); 9026 if (plun->lun_mpxio == 0) { 9027 cdip = DIP(plun->lun_cip); 9028 } else if (plun->lun_cip) { 9029 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9030 } 9031 9032 mutex_exit(&plun->lun_mutex); 9033 9034 if (cdip) { 9035 (void) ndi_event_retrieve_cookie( 9036 pptr->port_ndi_event_hdl, cdip, 9037 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9038 NDI_EVENT_NOPASS); 9039 (void) ndi_event_run_callbacks( 9040 pptr->port_ndi_event_hdl, cdip, 9041 fcp_remove_eid, NULL); 9042 } 9043 9044 /* 9045 * If the link goes off-line for a lip, 9046 * this will cause a error to the ST SG 9047 * SGEN drivers. By setting BUSY we will 9048 * give the drivers the chance to retry 9049 * before it blows of the job. ST will 9050 * remember how many times it has retried. 9051 */ 9052 9053 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9054 (plun->lun_type == DTYPE_CHANGER)) { 9055 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9056 ptr = (caddr_t)pkt->pkt_scbp; 9057 if (ptr) { 9058 *ptr = STATUS_BUSY; 9059 } 9060 } else { 9061 pkt->pkt_reason = CMD_TRAN_ERR; 9062 pkt->pkt_statistics |= STAT_BUS_RESET; 9063 } 9064 break; 9065 } 9066 9067 case FC_PKT_TRAN_BSY: 9068 /* 9069 * Use the ssd Qfull handling here. 9070 */ 9071 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9072 pkt->pkt_state = STATE_GOT_BUS; 9073 break; 9074 9075 case FC_PKT_TIMEOUT: 9076 pkt->pkt_reason = CMD_TIMEOUT; 9077 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9078 pkt->pkt_statistics |= STAT_TIMEOUT; 9079 } else { 9080 pkt->pkt_statistics |= STAT_ABORTED; 9081 } 9082 break; 9083 9084 case FC_PKT_LOCAL_RJT: 9085 switch (fpkt->pkt_reason) { 9086 case FC_REASON_OFFLINE: { 9087 dev_info_t *cdip = NULL; 9088 9089 mutex_enter(&plun->lun_mutex); 9090 if (plun->lun_mpxio == 0) { 9091 cdip = DIP(plun->lun_cip); 9092 } else if (plun->lun_cip) { 9093 cdip = mdi_pi_get_client( 9094 PIP(plun->lun_cip)); 9095 } 9096 mutex_exit(&plun->lun_mutex); 9097 9098 if (cdip) { 9099 (void) ndi_event_retrieve_cookie( 9100 pptr->port_ndi_event_hdl, cdip, 9101 FCAL_REMOVE_EVENT, 9102 &fcp_remove_eid, 9103 NDI_EVENT_NOPASS); 9104 (void) ndi_event_run_callbacks( 9105 pptr->port_ndi_event_hdl, 9106 cdip, fcp_remove_eid, NULL); 9107 } 9108 9109 pkt->pkt_reason = CMD_TRAN_ERR; 9110 pkt->pkt_statistics |= STAT_BUS_RESET; 9111 9112 break; 9113 } 9114 9115 case FC_REASON_NOMEM: 9116 case FC_REASON_QFULL: { 9117 caddr_t ptr; 9118 9119 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9120 ptr = (caddr_t)pkt->pkt_scbp; 9121 if (ptr) { 9122 *ptr = STATUS_BUSY; 9123 } 9124 break; 9125 } 9126 9127 case FC_REASON_DMA_ERROR: 9128 pkt->pkt_reason = CMD_DMA_DERR; 9129 pkt->pkt_statistics |= STAT_ABORTED; 9130 break; 9131 9132 case FC_REASON_CRC_ERROR: 9133 case FC_REASON_UNDERRUN: { 9134 uchar_t status; 9135 /* 9136 * Work around for Bugid: 4240945. 9137 * IB on A5k doesn't set the Underrun bit 9138 * in the fcp status, when it is transferring 9139 * less than requested amount of data. Work 9140 * around the ses problem to keep luxadm 9141 * happy till ibfirmware is fixed. 9142 */ 9143 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9144 FCP_CP_IN(fpkt->pkt_resp, rsp, 9145 fpkt->pkt_resp_acc, 9146 sizeof (struct fcp_rsp)); 9147 } 9148 status = rsp->fcp_u.fcp_status.scsi_status; 9149 if (((plun->lun_type & DTYPE_MASK) == 9150 DTYPE_ESI) && (status == STATUS_GOOD)) { 9151 pkt->pkt_reason = CMD_CMPLT; 9152 *pkt->pkt_scbp = status; 9153 pkt->pkt_resid = 0; 9154 } else { 9155 pkt->pkt_reason = CMD_TRAN_ERR; 9156 pkt->pkt_statistics |= STAT_ABORTED; 9157 } 9158 break; 9159 } 9160 9161 case FC_REASON_NO_CONNECTION: 9162 case FC_REASON_UNSUPPORTED: 9163 case FC_REASON_ILLEGAL_REQ: 9164 case FC_REASON_BAD_SID: 9165 case FC_REASON_DIAG_BUSY: 9166 case FC_REASON_FCAL_OPN_FAIL: 9167 case FC_REASON_BAD_XID: 9168 default: 9169 pkt->pkt_reason = CMD_TRAN_ERR; 9170 pkt->pkt_statistics |= STAT_ABORTED; 9171 break; 9172 9173 } 9174 break; 9175 9176 case FC_PKT_NPORT_RJT: 9177 case FC_PKT_FABRIC_RJT: 9178 case FC_PKT_NPORT_BSY: 9179 case FC_PKT_FABRIC_BSY: 9180 default: 9181 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9182 fcp_trace, FCP_BUF_LEVEL_8, 0, 9183 "FC Status 0x%x, reason 0x%x", 9184 fpkt->pkt_state, fpkt->pkt_reason); 9185 pkt->pkt_reason = CMD_TRAN_ERR; 9186 pkt->pkt_statistics |= STAT_ABORTED; 9187 break; 9188 } 9189 9190 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9191 fcp_trace, FCP_BUF_LEVEL_9, 0, 9192 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9193 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9194 fpkt->pkt_reason); 9195 } 9196 9197 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9198 } 9199 9200 9201 static int 9202 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9203 { 9204 if (rsp->reserved_0 || rsp->reserved_1 || 9205 rsp->fcp_u.fcp_status.reserved_0 || 9206 rsp->fcp_u.fcp_status.reserved_1) { 9207 /* 9208 * These reserved fields should ideally be zero. FCP-2 does say 9209 * that the recipient need not check for reserved fields to be 9210 * zero. If they are not zero, we will not make a fuss about it 9211 * - just log it (in debug to both trace buffer and messages 9212 * file and to trace buffer only in non-debug) and move on. 9213 * 9214 * Non-zero reserved fields were seen with minnows. 9215 * 9216 * qlc takes care of some of this but we cannot assume that all 9217 * FCAs will do so. 9218 */ 9219 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9220 FCP_BUF_LEVEL_5, 0, 9221 "Got fcp response packet with non-zero reserved fields " 9222 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9223 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9224 rsp->reserved_0, rsp->reserved_1, 9225 rsp->fcp_u.fcp_status.reserved_0, 9226 rsp->fcp_u.fcp_status.reserved_1); 9227 } 9228 9229 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9230 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9231 return (FC_FAILURE); 9232 } 9233 9234 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9235 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9236 sizeof (struct fcp_rsp))) { 9237 return (FC_FAILURE); 9238 } 9239 9240 return (FC_SUCCESS); 9241 } 9242 9243 9244 /* 9245 * This is called when there is a change the in device state. The case we're 9246 * handling here is, if the d_id s does not match, offline this tgt and online 9247 * a new tgt with the new d_id. called from fcp_handle_devices with 9248 * port_mutex held. 9249 */ 9250 static int 9251 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9252 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9253 { 9254 ASSERT(mutex_owned(&pptr->port_mutex)); 9255 9256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9257 fcp_trace, FCP_BUF_LEVEL_3, 0, 9258 "Starting fcp_device_changed..."); 9259 9260 /* 9261 * The two cases where the port_device_changed is called is 9262 * either it changes it's d_id or it's hard address. 9263 */ 9264 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9265 (FC_TOP_EXTERNAL(pptr->port_topology) && 9266 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9267 9268 /* offline this target */ 9269 mutex_enter(&ptgt->tgt_mutex); 9270 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9271 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9272 0, 1, NDI_DEVI_REMOVE); 9273 } 9274 mutex_exit(&ptgt->tgt_mutex); 9275 9276 fcp_log(CE_NOTE, pptr->port_dip, 9277 "Change in target properties: Old D_ID=%x New D_ID=%x" 9278 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9279 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9280 map_entry->map_hard_addr.hard_addr); 9281 } 9282 9283 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9284 link_cnt, tgt_cnt, cause)); 9285 } 9286 9287 /* 9288 * Function: fcp_alloc_lun 9289 * 9290 * Description: Creates a new lun structure and adds it to the list 9291 * of luns of the target. 9292 * 9293 * Argument: ptgt Target the lun will belong to. 9294 * 9295 * Return Value: NULL Failed 9296 * Not NULL Succeeded 9297 * 9298 * Context: Kernel context 9299 */ 9300 static struct fcp_lun * 9301 fcp_alloc_lun(struct fcp_tgt *ptgt) 9302 { 9303 struct fcp_lun *plun; 9304 9305 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9306 if (plun != NULL) { 9307 /* 9308 * Initialize the mutex before putting in the target list 9309 * especially before releasing the target mutex. 9310 */ 9311 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9312 plun->lun_tgt = ptgt; 9313 9314 mutex_enter(&ptgt->tgt_mutex); 9315 plun->lun_next = ptgt->tgt_lun; 9316 ptgt->tgt_lun = plun; 9317 plun->lun_old_guid = NULL; 9318 plun->lun_old_guid_size = 0; 9319 mutex_exit(&ptgt->tgt_mutex); 9320 } 9321 9322 return (plun); 9323 } 9324 9325 /* 9326 * Function: fcp_dealloc_lun 9327 * 9328 * Description: Frees the LUN structure passed by the caller. 9329 * 9330 * Argument: plun LUN structure to free. 9331 * 9332 * Return Value: None 9333 * 9334 * Context: Kernel context. 9335 */ 9336 static void 9337 fcp_dealloc_lun(struct fcp_lun *plun) 9338 { 9339 mutex_enter(&plun->lun_mutex); 9340 if (plun->lun_cip) { 9341 fcp_remove_child(plun); 9342 } 9343 mutex_exit(&plun->lun_mutex); 9344 9345 mutex_destroy(&plun->lun_mutex); 9346 if (plun->lun_guid) { 9347 kmem_free(plun->lun_guid, plun->lun_guid_size); 9348 } 9349 if (plun->lun_old_guid) { 9350 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9351 } 9352 kmem_free(plun, sizeof (*plun)); 9353 } 9354 9355 /* 9356 * Function: fcp_alloc_tgt 9357 * 9358 * Description: Creates a new target structure and adds it to the port 9359 * hash list. 9360 * 9361 * Argument: pptr fcp port structure 9362 * *map_entry entry describing the target to create 9363 * link_cnt Link state change counter 9364 * 9365 * Return Value: NULL Failed 9366 * Not NULL Succeeded 9367 * 9368 * Context: Kernel context. 9369 */ 9370 static struct fcp_tgt * 9371 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9372 { 9373 int hash; 9374 uchar_t *wwn; 9375 struct fcp_tgt *ptgt; 9376 9377 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9378 if (ptgt != NULL) { 9379 mutex_enter(&pptr->port_mutex); 9380 if (link_cnt != pptr->port_link_cnt) { 9381 /* 9382 * oh oh -- another link reset 9383 * in progress -- give up 9384 */ 9385 mutex_exit(&pptr->port_mutex); 9386 kmem_free(ptgt, sizeof (*ptgt)); 9387 ptgt = NULL; 9388 } else { 9389 /* 9390 * initialize the mutex before putting in the port 9391 * wwn list, especially before releasing the port 9392 * mutex. 9393 */ 9394 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9395 9396 /* add new target entry to the port's hash list */ 9397 wwn = (uchar_t *)&map_entry->map_pwwn; 9398 hash = FCP_HASH(wwn); 9399 9400 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9401 pptr->port_tgt_hash_table[hash] = ptgt; 9402 9403 /* save cross-ptr */ 9404 ptgt->tgt_port = pptr; 9405 9406 ptgt->tgt_change_cnt = 1; 9407 9408 /* initialize the target manual_config_only flag */ 9409 if (fcp_enable_auto_configuration) { 9410 ptgt->tgt_manual_config_only = 0; 9411 } else { 9412 ptgt->tgt_manual_config_only = 1; 9413 } 9414 9415 mutex_exit(&pptr->port_mutex); 9416 } 9417 } 9418 9419 return (ptgt); 9420 } 9421 9422 /* 9423 * Function: fcp_dealloc_tgt 9424 * 9425 * Description: Frees the target structure passed by the caller. 9426 * 9427 * Argument: ptgt Target structure to free. 9428 * 9429 * Return Value: None 9430 * 9431 * Context: Kernel context. 9432 */ 9433 static void 9434 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9435 { 9436 mutex_destroy(&ptgt->tgt_mutex); 9437 kmem_free(ptgt, sizeof (*ptgt)); 9438 } 9439 9440 9441 /* 9442 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9443 * 9444 * Device discovery commands will not be retried for-ever as 9445 * this will have repercussions on other devices that need to 9446 * be submitted to the hotplug thread. After a quick glance 9447 * at the SCSI-3 spec, it was found that the spec doesn't 9448 * mandate a forever retry, rather recommends a delayed retry. 9449 * 9450 * Since Photon IB is single threaded, STATUS_BUSY is common 9451 * in a 4+initiator environment. Make sure the total time 9452 * spent on retries (including command timeout) does not 9453 * 60 seconds 9454 */ 9455 static void 9456 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9457 { 9458 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9459 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9460 9461 mutex_enter(&pptr->port_mutex); 9462 mutex_enter(&ptgt->tgt_mutex); 9463 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9464 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9465 fcp_trace, FCP_BUF_LEVEL_2, 0, 9466 "fcp_queue_ipkt,1:state change occured" 9467 " for D_ID=0x%x", ptgt->tgt_d_id); 9468 mutex_exit(&ptgt->tgt_mutex); 9469 mutex_exit(&pptr->port_mutex); 9470 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9471 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9472 fcp_icmd_free(pptr, icmd); 9473 return; 9474 } 9475 mutex_exit(&ptgt->tgt_mutex); 9476 9477 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9478 9479 if (pptr->port_ipkt_list != NULL) { 9480 /* add pkt to front of doubly-linked list */ 9481 pptr->port_ipkt_list->ipkt_prev = icmd; 9482 icmd->ipkt_next = pptr->port_ipkt_list; 9483 pptr->port_ipkt_list = icmd; 9484 icmd->ipkt_prev = NULL; 9485 } else { 9486 /* this is the first/only pkt on the list */ 9487 pptr->port_ipkt_list = icmd; 9488 icmd->ipkt_next = NULL; 9489 icmd->ipkt_prev = NULL; 9490 } 9491 mutex_exit(&pptr->port_mutex); 9492 } 9493 9494 /* 9495 * Function: fcp_transport 9496 * 9497 * Description: This function submits the Fibre Channel packet to the transort 9498 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9499 * fails the submission, the treatment depends on the value of 9500 * the variable internal. 9501 * 9502 * Argument: port_handle fp/fctl port handle. 9503 * *fpkt Packet to submit to the transport layer. 9504 * internal Not zero when it's an internal packet. 9505 * 9506 * Return Value: FC_TRAN_BUSY 9507 * FC_STATEC_BUSY 9508 * FC_OFFLINE 9509 * FC_LOGINREQ 9510 * FC_DEVICE_BUSY 9511 * FC_SUCCESS 9512 */ 9513 static int 9514 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9515 { 9516 int rval; 9517 9518 rval = fc_ulp_transport(port_handle, fpkt); 9519 if (rval == FC_SUCCESS) { 9520 return (rval); 9521 } 9522 9523 /* 9524 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9525 * a command, if the underlying modules see that there is a state 9526 * change, or if a port is OFFLINE, that means, that state change 9527 * hasn't reached FCP yet, so re-queue the command for deferred 9528 * submission. 9529 */ 9530 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9531 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9532 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9533 /* 9534 * Defer packet re-submission. Life hang is possible on 9535 * internal commands if the port driver sends FC_STATEC_BUSY 9536 * for ever, but that shouldn't happen in a good environment. 9537 * Limiting re-transport for internal commands is probably a 9538 * good idea.. 9539 * A race condition can happen when a port sees barrage of 9540 * link transitions offline to online. If the FCTL has 9541 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9542 * internal commands should be queued to do the discovery. 9543 * The race condition is when an online comes and FCP starts 9544 * its internal discovery and the link goes offline. It is 9545 * possible that the statec_callback has not reached FCP 9546 * and FCP is carrying on with its internal discovery. 9547 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9548 * that the link has gone offline. At this point FCP should 9549 * drop all the internal commands and wait for the 9550 * statec_callback. It will be facilitated by incrementing 9551 * port_link_cnt. 9552 * 9553 * For external commands, the (FC)pkt_timeout is decremented 9554 * by the QUEUE Delay added by our driver, Care is taken to 9555 * ensure that it doesn't become zero (zero means no timeout) 9556 * If the time expires right inside driver queue itself, 9557 * the watch thread will return it to the original caller 9558 * indicating that the command has timed-out. 9559 */ 9560 if (internal) { 9561 char *op; 9562 struct fcp_ipkt *icmd; 9563 9564 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9565 switch (icmd->ipkt_opcode) { 9566 case SCMD_REPORT_LUN: 9567 op = "REPORT LUN"; 9568 break; 9569 9570 case SCMD_INQUIRY: 9571 op = "INQUIRY"; 9572 break; 9573 9574 case SCMD_INQUIRY_PAGE83: 9575 op = "INQUIRY-83"; 9576 break; 9577 9578 default: 9579 op = "Internal SCSI COMMAND"; 9580 break; 9581 } 9582 9583 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9584 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9585 rval = FC_SUCCESS; 9586 } 9587 } else { 9588 struct fcp_pkt *cmd; 9589 struct fcp_port *pptr; 9590 9591 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9592 cmd->cmd_state = FCP_PKT_IDLE; 9593 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9594 9595 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9596 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9597 fcp_trace, FCP_BUF_LEVEL_9, 0, 9598 "fcp_transport: xport busy for pkt %p", 9599 cmd->cmd_pkt); 9600 rval = FC_TRAN_BUSY; 9601 } else { 9602 fcp_queue_pkt(pptr, cmd); 9603 rval = FC_SUCCESS; 9604 } 9605 } 9606 } 9607 9608 return (rval); 9609 } 9610 9611 /*VARARGS3*/ 9612 static void 9613 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9614 { 9615 char buf[256]; 9616 va_list ap; 9617 9618 if (dip == NULL) { 9619 dip = fcp_global_dip; 9620 } 9621 9622 va_start(ap, fmt); 9623 (void) vsprintf(buf, fmt, ap); 9624 va_end(ap); 9625 9626 scsi_log(dip, "fcp", level, buf); 9627 } 9628 9629 /* 9630 * This function retries NS registry of FC4 type. 9631 * It assumes that fcp_mutex is held. 9632 * The function does nothing if topology is not fabric 9633 * So, the topology has to be set before this function can be called 9634 */ 9635 static void 9636 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9637 { 9638 int rval; 9639 9640 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9641 9642 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9643 ((pptr->port_topology != FC_TOP_FABRIC) && 9644 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9645 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9646 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9647 } 9648 return; 9649 } 9650 mutex_exit(&pptr->port_mutex); 9651 rval = fcp_do_ns_registry(pptr, s_id); 9652 mutex_enter(&pptr->port_mutex); 9653 9654 if (rval == 0) { 9655 /* Registry successful. Reset flag */ 9656 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9657 } 9658 } 9659 9660 /* 9661 * This function registers the ULP with the switch by calling transport i/f 9662 */ 9663 static int 9664 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9665 { 9666 fc_ns_cmd_t ns_cmd; 9667 ns_rfc_type_t rfc; 9668 uint32_t types[8]; 9669 9670 /* 9671 * Prepare the Name server structure to 9672 * register with the transport in case of 9673 * Fabric configuration. 9674 */ 9675 bzero(&rfc, sizeof (rfc)); 9676 bzero(types, sizeof (types)); 9677 9678 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9679 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9680 9681 rfc.rfc_port_id.port_id = s_id; 9682 bcopy(types, rfc.rfc_types, sizeof (types)); 9683 9684 ns_cmd.ns_flags = 0; 9685 ns_cmd.ns_cmd = NS_RFT_ID; 9686 ns_cmd.ns_req_len = sizeof (rfc); 9687 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9688 ns_cmd.ns_resp_len = 0; 9689 ns_cmd.ns_resp_payload = NULL; 9690 9691 /* 9692 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9693 */ 9694 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9695 fcp_log(CE_WARN, pptr->port_dip, 9696 "!ns_registry: failed name server registration"); 9697 return (1); 9698 } 9699 9700 return (0); 9701 } 9702 9703 /* 9704 * Function: fcp_handle_port_attach 9705 * 9706 * Description: This function is called from fcp_port_attach() to attach a 9707 * new port. This routine does the following: 9708 * 9709 * 1) Allocates an fcp_port structure and initializes it. 9710 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9711 * server. 9712 * 3) Kicks off the enumeration of the targets/luns visible 9713 * through this new port. That is done by calling 9714 * fcp_statec_callback() if the port is online. 9715 * 9716 * Argument: ulph fp/fctl port handle. 9717 * *pinfo Port information. 9718 * s_id Port ID. 9719 * instance Device instance number for the local port 9720 * (returned by ddi_get_instance()). 9721 * 9722 * Return Value: DDI_SUCCESS 9723 * DDI_FAILURE 9724 * 9725 * Context: User and Kernel context. 9726 */ 9727 /*ARGSUSED*/ 9728 int 9729 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9730 uint32_t s_id, int instance) 9731 { 9732 int res = DDI_FAILURE; 9733 scsi_hba_tran_t *tran; 9734 int mutex_initted = FALSE; 9735 int hba_attached = FALSE; 9736 int soft_state_linked = FALSE; 9737 int event_bind = FALSE; 9738 struct fcp_port *pptr; 9739 fc_portmap_t *tmp_list = NULL; 9740 uint32_t max_cnt, alloc_cnt; 9741 uchar_t *boot_wwn = NULL; 9742 uint_t nbytes; 9743 int manual_cfg; 9744 9745 /* 9746 * this port instance attaching for the first time (or after 9747 * being detached before) 9748 */ 9749 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9750 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9751 9752 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9753 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9754 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9755 instance); 9756 return (res); 9757 } 9758 9759 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9760 /* this shouldn't happen */ 9761 ddi_soft_state_free(fcp_softstate, instance); 9762 cmn_err(CE_WARN, "fcp: bad soft state"); 9763 return (res); 9764 } 9765 9766 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9767 9768 /* 9769 * Make a copy of ulp_port_info as fctl allocates 9770 * a temp struct. 9771 */ 9772 (void) fcp_cp_pinfo(pptr, pinfo); 9773 9774 /* 9775 * Check for manual_configuration_only property. 9776 * Enable manual configurtion if the property is 9777 * set to 1, otherwise disable manual configuration. 9778 */ 9779 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9780 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9781 MANUAL_CFG_ONLY, 9782 -1)) != -1) { 9783 if (manual_cfg == 1) { 9784 char *pathname; 9785 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9786 (void) ddi_pathname(pptr->port_dip, pathname); 9787 cmn_err(CE_NOTE, 9788 "%s (%s%d) %s is enabled via %s.conf.", 9789 pathname, 9790 ddi_driver_name(pptr->port_dip), 9791 ddi_get_instance(pptr->port_dip), 9792 MANUAL_CFG_ONLY, 9793 ddi_driver_name(pptr->port_dip)); 9794 fcp_enable_auto_configuration = 0; 9795 kmem_free(pathname, MAXPATHLEN); 9796 } 9797 } 9798 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9799 pptr->port_link_cnt = 1; 9800 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9801 pptr->port_id = s_id; 9802 pptr->port_instance = instance; 9803 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9804 pptr->port_state = FCP_STATE_INIT; 9805 if (pinfo->port_acc_attr == NULL) { 9806 /* 9807 * The corresponding FCA doesn't support DMA at all 9808 */ 9809 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9810 } 9811 9812 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9813 9814 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9815 /* 9816 * If FCA supports DMA in SCSI data phase, we need preallocate 9817 * dma cookie, so stash the cookie size 9818 */ 9819 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9820 pptr->port_data_dma_attr.dma_attr_sgllen; 9821 } 9822 9823 /* 9824 * The two mutexes of fcp_port are initialized. The variable 9825 * mutex_initted is incremented to remember that fact. That variable 9826 * is checked when the routine fails and the mutexes have to be 9827 * destroyed. 9828 */ 9829 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9830 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9831 mutex_initted++; 9832 9833 /* 9834 * The SCSI tran structure is allocate and initialized now. 9835 */ 9836 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9837 fcp_log(CE_WARN, pptr->port_dip, 9838 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9839 goto fail; 9840 } 9841 9842 /* link in the transport structure then fill it in */ 9843 pptr->port_tran = tran; 9844 tran->tran_hba_private = pptr; 9845 tran->tran_tgt_init = fcp_scsi_tgt_init; 9846 tran->tran_tgt_probe = NULL; 9847 tran->tran_tgt_free = fcp_scsi_tgt_free; 9848 tran->tran_start = fcp_scsi_start; 9849 tran->tran_reset = fcp_scsi_reset; 9850 tran->tran_abort = fcp_scsi_abort; 9851 tran->tran_getcap = fcp_scsi_getcap; 9852 tran->tran_setcap = fcp_scsi_setcap; 9853 tran->tran_init_pkt = NULL; 9854 tran->tran_destroy_pkt = NULL; 9855 tran->tran_dmafree = NULL; 9856 tran->tran_sync_pkt = NULL; 9857 tran->tran_reset_notify = fcp_scsi_reset_notify; 9858 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9859 tran->tran_get_name = fcp_scsi_get_name; 9860 tran->tran_clear_aca = NULL; 9861 tran->tran_clear_task_set = NULL; 9862 tran->tran_terminate_task = NULL; 9863 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9864 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9865 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9866 tran->tran_post_event = fcp_scsi_bus_post_event; 9867 tran->tran_quiesce = NULL; 9868 tran->tran_unquiesce = NULL; 9869 tran->tran_bus_reset = NULL; 9870 tran->tran_bus_config = fcp_scsi_bus_config; 9871 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9872 tran->tran_bus_power = NULL; 9873 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9874 9875 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9876 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9877 tran->tran_setup_pkt = fcp_pkt_setup; 9878 tran->tran_teardown_pkt = fcp_pkt_teardown; 9879 tran->tran_hba_len = pptr->port_priv_pkt_len + 9880 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9881 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9882 /* 9883 * If FCA don't support DMA, then we use different vectors to 9884 * minimize the effects on DMA code flow path 9885 */ 9886 tran->tran_start = fcp_pseudo_start; 9887 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9888 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9889 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9890 tran->tran_dmafree = fcp_pseudo_dmafree; 9891 tran->tran_setup_pkt = NULL; 9892 tran->tran_teardown_pkt = NULL; 9893 tran->tran_pkt_constructor = NULL; 9894 tran->tran_pkt_destructor = NULL; 9895 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9896 } 9897 9898 /* 9899 * Allocate an ndi event handle 9900 */ 9901 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9902 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9903 9904 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9905 sizeof (fcp_ndi_event_defs)); 9906 9907 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9908 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9909 9910 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9911 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9912 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9913 9914 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9915 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9916 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9917 goto fail; 9918 } 9919 event_bind++; /* Checked in fail case */ 9920 9921 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9922 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9923 != DDI_SUCCESS) { 9924 fcp_log(CE_WARN, pptr->port_dip, 9925 "!fcp%d: scsi_hba_attach_setup failed", instance); 9926 goto fail; 9927 } 9928 hba_attached++; /* Checked in fail case */ 9929 9930 pptr->port_mpxio = 0; 9931 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9932 MDI_SUCCESS) { 9933 pptr->port_mpxio++; 9934 } 9935 9936 /* 9937 * The following code is putting the new port structure in the global 9938 * list of ports and, if it is the first port to attach, it start the 9939 * fcp_watchdog_tick. 9940 * 9941 * Why put this new port in the global before we are done attaching it? 9942 * We are actually making the structure globally known before we are 9943 * done attaching it. The reason for that is: because of the code that 9944 * follows. At this point the resources to handle the port are 9945 * allocated. This function is now going to do the following: 9946 * 9947 * 1) It is going to try to register with the name server advertizing 9948 * the new FCP capability of the port. 9949 * 2) It is going to play the role of the fp/fctl layer by building 9950 * a list of worlwide names reachable through this port and call 9951 * itself on fcp_statec_callback(). That requires the port to 9952 * be part of the global list. 9953 */ 9954 mutex_enter(&fcp_global_mutex); 9955 if (fcp_port_head == NULL) { 9956 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9957 } 9958 pptr->port_next = fcp_port_head; 9959 fcp_port_head = pptr; 9960 soft_state_linked++; 9961 9962 if (fcp_watchdog_init++ == 0) { 9963 fcp_watchdog_tick = fcp_watchdog_timeout * 9964 drv_usectohz(1000000); 9965 fcp_watchdog_id = timeout(fcp_watch, NULL, 9966 fcp_watchdog_tick); 9967 } 9968 mutex_exit(&fcp_global_mutex); 9969 9970 /* 9971 * Here an attempt is made to register with the name server, the new 9972 * FCP capability. That is done using an RTF_ID to the name server. 9973 * It is done synchronously. The function fcp_do_ns_registry() 9974 * doesn't return till the name server responded. 9975 * On failures, just ignore it for now and it will get retried during 9976 * state change callbacks. We'll set a flag to show this failure 9977 */ 9978 if (fcp_do_ns_registry(pptr, s_id)) { 9979 mutex_enter(&pptr->port_mutex); 9980 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 9981 mutex_exit(&pptr->port_mutex); 9982 } else { 9983 mutex_enter(&pptr->port_mutex); 9984 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9985 mutex_exit(&pptr->port_mutex); 9986 } 9987 9988 /* 9989 * Lookup for boot WWN property 9990 */ 9991 if (modrootloaded != 1) { 9992 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 9993 ddi_get_parent(pinfo->port_dip), 9994 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 9995 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 9996 (nbytes == FC_WWN_SIZE)) { 9997 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 9998 } 9999 if (boot_wwn) { 10000 ddi_prop_free(boot_wwn); 10001 } 10002 } 10003 10004 /* 10005 * Handle various topologies and link states. 10006 */ 10007 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10008 case FC_STATE_OFFLINE: 10009 10010 /* 10011 * we're attaching a port where the link is offline 10012 * 10013 * Wait for ONLINE, at which time a state 10014 * change will cause a statec_callback 10015 * 10016 * in the mean time, do not do anything 10017 */ 10018 res = DDI_SUCCESS; 10019 pptr->port_state |= FCP_STATE_OFFLINE; 10020 break; 10021 10022 case FC_STATE_ONLINE: { 10023 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10024 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10025 res = DDI_SUCCESS; 10026 break; 10027 } 10028 /* 10029 * discover devices and create nodes (a private 10030 * loop or point-to-point) 10031 */ 10032 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10033 10034 /* 10035 * At this point we are going to build a list of all the ports 10036 * that can be reached through this local port. It looks like 10037 * we cannot handle more than FCP_MAX_DEVICES per local port 10038 * (128). 10039 */ 10040 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10041 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10042 KM_NOSLEEP)) == NULL) { 10043 fcp_log(CE_WARN, pptr->port_dip, 10044 "!fcp%d: failed to allocate portmap", 10045 instance); 10046 goto fail; 10047 } 10048 10049 /* 10050 * fc_ulp_getportmap() is going to provide us with the list of 10051 * remote ports in the buffer we just allocated. The way the 10052 * list is going to be retrieved depends on the topology. 10053 * However, if we are connected to a Fabric, a name server 10054 * request may be sent to get the list of FCP capable ports. 10055 * It should be noted that is the case the request is 10056 * synchronous. This means we are stuck here till the name 10057 * server replies. A lot of things can change during that time 10058 * and including, may be, being called on 10059 * fcp_statec_callback() for different reasons. I'm not sure 10060 * the code can handle that. 10061 */ 10062 max_cnt = FCP_MAX_DEVICES; 10063 alloc_cnt = FCP_MAX_DEVICES; 10064 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10065 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10066 FC_SUCCESS) { 10067 caddr_t msg; 10068 10069 (void) fc_ulp_error(res, &msg); 10070 10071 /* 10072 * this just means the transport is 10073 * busy perhaps building a portmap so, 10074 * for now, succeed this port attach 10075 * when the transport has a new map, 10076 * it'll send us a state change then 10077 */ 10078 fcp_log(CE_WARN, pptr->port_dip, 10079 "!failed to get port map : %s", msg); 10080 10081 res = DDI_SUCCESS; 10082 break; /* go return result */ 10083 } 10084 if (max_cnt > alloc_cnt) { 10085 alloc_cnt = max_cnt; 10086 } 10087 10088 /* 10089 * We are now going to call fcp_statec_callback() ourselves. 10090 * By issuing this call we are trying to kick off the enumera- 10091 * tion process. 10092 */ 10093 /* 10094 * let the state change callback do the SCSI device 10095 * discovery and create the devinfos 10096 */ 10097 fcp_statec_callback(ulph, pptr->port_fp_handle, 10098 pptr->port_phys_state, pptr->port_topology, tmp_list, 10099 max_cnt, pptr->port_id); 10100 10101 res = DDI_SUCCESS; 10102 break; 10103 } 10104 10105 default: 10106 /* unknown port state */ 10107 fcp_log(CE_WARN, pptr->port_dip, 10108 "!fcp%d: invalid port state at attach=0x%x", 10109 instance, pptr->port_phys_state); 10110 10111 mutex_enter(&pptr->port_mutex); 10112 pptr->port_phys_state = FCP_STATE_OFFLINE; 10113 mutex_exit(&pptr->port_mutex); 10114 10115 res = DDI_SUCCESS; 10116 break; 10117 } 10118 10119 /* free temp list if used */ 10120 if (tmp_list != NULL) { 10121 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10122 } 10123 10124 /* note the attach time */ 10125 pptr->port_attach_time = ddi_get_lbolt64(); 10126 10127 /* all done */ 10128 return (res); 10129 10130 /* a failure we have to clean up after */ 10131 fail: 10132 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10133 10134 if (soft_state_linked) { 10135 /* remove this fcp_port from the linked list */ 10136 (void) fcp_soft_state_unlink(pptr); 10137 } 10138 10139 /* unbind and free event set */ 10140 if (pptr->port_ndi_event_hdl) { 10141 if (event_bind) { 10142 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10143 &pptr->port_ndi_events, NDI_SLEEP); 10144 } 10145 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10146 } 10147 10148 if (pptr->port_ndi_event_defs) { 10149 (void) kmem_free(pptr->port_ndi_event_defs, 10150 sizeof (fcp_ndi_event_defs)); 10151 } 10152 10153 /* 10154 * Clean up mpxio stuff 10155 */ 10156 if (pptr->port_mpxio) { 10157 (void) mdi_phci_unregister(pptr->port_dip, 0); 10158 pptr->port_mpxio--; 10159 } 10160 10161 /* undo SCSI HBA setup */ 10162 if (hba_attached) { 10163 (void) scsi_hba_detach(pptr->port_dip); 10164 } 10165 if (pptr->port_tran != NULL) { 10166 scsi_hba_tran_free(pptr->port_tran); 10167 } 10168 10169 mutex_enter(&fcp_global_mutex); 10170 10171 /* 10172 * We check soft_state_linked, because it is incremented right before 10173 * we call increment fcp_watchdog_init. Therefore, we know if 10174 * soft_state_linked is still FALSE, we do not want to decrement 10175 * fcp_watchdog_init or possibly call untimeout. 10176 */ 10177 10178 if (soft_state_linked) { 10179 if (--fcp_watchdog_init == 0) { 10180 timeout_id_t tid = fcp_watchdog_id; 10181 10182 mutex_exit(&fcp_global_mutex); 10183 (void) untimeout(tid); 10184 } else { 10185 mutex_exit(&fcp_global_mutex); 10186 } 10187 } else { 10188 mutex_exit(&fcp_global_mutex); 10189 } 10190 10191 if (mutex_initted) { 10192 mutex_destroy(&pptr->port_mutex); 10193 mutex_destroy(&pptr->port_pkt_mutex); 10194 } 10195 10196 if (tmp_list != NULL) { 10197 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10198 } 10199 10200 /* this makes pptr invalid */ 10201 ddi_soft_state_free(fcp_softstate, instance); 10202 10203 return (DDI_FAILURE); 10204 } 10205 10206 10207 static int 10208 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10209 { 10210 int count = 0; 10211 10212 mutex_enter(&pptr->port_mutex); 10213 10214 /* 10215 * if the port is powered down or suspended, nothing else 10216 * to do; just return. 10217 */ 10218 if (flag != FCP_STATE_DETACHING) { 10219 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10220 FCP_STATE_SUSPENDED)) { 10221 pptr->port_state |= flag; 10222 mutex_exit(&pptr->port_mutex); 10223 return (FC_SUCCESS); 10224 } 10225 } 10226 10227 if (pptr->port_state & FCP_STATE_IN_MDI) { 10228 mutex_exit(&pptr->port_mutex); 10229 return (FC_FAILURE); 10230 } 10231 10232 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10233 fcp_trace, FCP_BUF_LEVEL_2, 0, 10234 "fcp_handle_port_detach: port is detaching"); 10235 10236 pptr->port_state |= flag; 10237 10238 /* 10239 * Wait for any ongoing reconfig/ipkt to complete, that 10240 * ensures the freeing to targets/luns is safe. 10241 * No more ref to this port should happen from statec/ioctl 10242 * after that as it was removed from the global port list. 10243 */ 10244 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10245 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10246 /* 10247 * Let's give sufficient time for reconfig/ipkt 10248 * to complete. 10249 */ 10250 if (count++ >= FCP_ICMD_DEADLINE) { 10251 break; 10252 } 10253 mutex_exit(&pptr->port_mutex); 10254 delay(drv_usectohz(1000000)); 10255 mutex_enter(&pptr->port_mutex); 10256 } 10257 10258 /* 10259 * if the driver is still busy then fail to 10260 * suspend/power down. 10261 */ 10262 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10263 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10264 pptr->port_state &= ~flag; 10265 mutex_exit(&pptr->port_mutex); 10266 return (FC_FAILURE); 10267 } 10268 10269 if (flag == FCP_STATE_DETACHING) { 10270 pptr = fcp_soft_state_unlink(pptr); 10271 ASSERT(pptr != NULL); 10272 } 10273 10274 pptr->port_link_cnt++; 10275 pptr->port_state |= FCP_STATE_OFFLINE; 10276 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10277 10278 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10279 FCP_CAUSE_LINK_DOWN); 10280 mutex_exit(&pptr->port_mutex); 10281 10282 /* kill watch dog timer if we're the last */ 10283 mutex_enter(&fcp_global_mutex); 10284 if (--fcp_watchdog_init == 0) { 10285 timeout_id_t tid = fcp_watchdog_id; 10286 mutex_exit(&fcp_global_mutex); 10287 (void) untimeout(tid); 10288 } else { 10289 mutex_exit(&fcp_global_mutex); 10290 } 10291 10292 /* clean up the port structures */ 10293 if (flag == FCP_STATE_DETACHING) { 10294 fcp_cleanup_port(pptr, instance); 10295 } 10296 10297 return (FC_SUCCESS); 10298 } 10299 10300 10301 static void 10302 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10303 { 10304 ASSERT(pptr != NULL); 10305 10306 /* unbind and free event set */ 10307 if (pptr->port_ndi_event_hdl) { 10308 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10309 &pptr->port_ndi_events, NDI_SLEEP); 10310 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10311 } 10312 10313 if (pptr->port_ndi_event_defs) { 10314 (void) kmem_free(pptr->port_ndi_event_defs, 10315 sizeof (fcp_ndi_event_defs)); 10316 } 10317 10318 /* free the lun/target structures and devinfos */ 10319 fcp_free_targets(pptr); 10320 10321 /* 10322 * Clean up mpxio stuff 10323 */ 10324 if (pptr->port_mpxio) { 10325 (void) mdi_phci_unregister(pptr->port_dip, 0); 10326 pptr->port_mpxio--; 10327 } 10328 10329 /* clean up SCSA stuff */ 10330 (void) scsi_hba_detach(pptr->port_dip); 10331 if (pptr->port_tran != NULL) { 10332 scsi_hba_tran_free(pptr->port_tran); 10333 } 10334 10335 #ifdef KSTATS_CODE 10336 /* clean up kstats */ 10337 if (pptr->fcp_ksp != NULL) { 10338 kstat_delete(pptr->fcp_ksp); 10339 } 10340 #endif 10341 10342 /* clean up soft state mutexes/condition variables */ 10343 mutex_destroy(&pptr->port_mutex); 10344 mutex_destroy(&pptr->port_pkt_mutex); 10345 10346 /* all done with soft state */ 10347 ddi_soft_state_free(fcp_softstate, instance); 10348 } 10349 10350 /* 10351 * Function: fcp_kmem_cache_constructor 10352 * 10353 * Description: This function allocates and initializes the resources required 10354 * to build a scsi_pkt structure the target driver. The result 10355 * of the allocation and initialization will be cached in the 10356 * memory cache. As DMA resources may be allocated here, that 10357 * means DMA resources will be tied up in the cache manager. 10358 * This is a tradeoff that has been made for performance reasons. 10359 * 10360 * Argument: *buf Memory to preinitialize. 10361 * *arg FCP port structure (fcp_port). 10362 * kmflags Value passed to kmem_cache_alloc() and 10363 * propagated to the constructor. 10364 * 10365 * Return Value: 0 Allocation/Initialization was successful. 10366 * -1 Allocation or Initialization failed. 10367 * 10368 * 10369 * If the returned value is 0, the buffer is initialized like this: 10370 * 10371 * +================================+ 10372 * +----> | struct scsi_pkt | 10373 * | | | 10374 * | +--- | pkt_ha_private | 10375 * | | | | 10376 * | | +================================+ 10377 * | | 10378 * | | +================================+ 10379 * | +--> | struct fcp_pkt | <---------+ 10380 * | | | | 10381 * +----- | cmd_pkt | | 10382 * | cmd_fp_pkt | ---+ | 10383 * +-------->| cmd_fcp_rsp[] | | | 10384 * | +--->| cmd_fcp_cmd[] | | | 10385 * | | |--------------------------------| | | 10386 * | | | struct fc_packet | <--+ | 10387 * | | | | | 10388 * | | | pkt_ulp_private | ----------+ 10389 * | | | pkt_fca_private | -----+ 10390 * | | | pkt_data_cookie | ---+ | 10391 * | | | pkt_cmdlen | | | 10392 * | |(a) | pkt_rsplen | | | 10393 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10394 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10395 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10396 * | pkt_resp_cookie | ---|-|--+ | | | 10397 * | pkt_cmd_dma | | | | | | | 10398 * | pkt_cmd_acc | | | | | | | 10399 * +================================+ | | | | | | 10400 * | dma_cookies | <--+ | | | | | 10401 * | | | | | | | 10402 * +================================+ | | | | | 10403 * | fca_private | <----+ | | | | 10404 * | | | | | | 10405 * +================================+ | | | | 10406 * | | | | 10407 * | | | | 10408 * +================================+ (d) | | | | 10409 * | fcp_resp cookies | <-------+ | | | 10410 * | | | | | 10411 * +================================+ | | | 10412 * | | | 10413 * +================================+ (d) | | | 10414 * | fcp_resp | <-----------+ | | 10415 * | (DMA resources associated) | | | 10416 * +================================+ | | 10417 * | | 10418 * | | 10419 * | | 10420 * +================================+ (c) | | 10421 * | fcp_cmd cookies | <---------------+ | 10422 * | | | 10423 * +================================+ | 10424 * | 10425 * +================================+ (c) | 10426 * | fcp_cmd | <--------------------+ 10427 * | (DMA resources associated) | 10428 * +================================+ 10429 * 10430 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10431 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10432 * (c) Only if DMA is used for the FCP_CMD buffer. 10433 * (d) Only if DMA is used for the FCP_RESP buffer 10434 */ 10435 static int 10436 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10437 int kmflags) 10438 { 10439 struct fcp_pkt *cmd; 10440 struct fcp_port *pptr; 10441 fc_packet_t *fpkt; 10442 10443 pptr = (struct fcp_port *)tran->tran_hba_private; 10444 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10445 bzero(cmd, tran->tran_hba_len); 10446 10447 cmd->cmd_pkt = pkt; 10448 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10449 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10450 cmd->cmd_fp_pkt = fpkt; 10451 10452 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10453 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10454 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10455 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10456 10457 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10458 sizeof (struct fcp_pkt)); 10459 10460 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10461 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10462 10463 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10464 /* 10465 * The underlying HBA doesn't want to DMA the fcp_cmd or 10466 * fcp_resp. The transfer of information will be done by 10467 * bcopy. 10468 * The naming of the flags (that is actually a value) is 10469 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10470 * DMA" but instead "NO DMA". 10471 */ 10472 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10473 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10474 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10475 } else { 10476 /* 10477 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10478 * buffer. A buffer is allocated for each one the ddi_dma_* 10479 * interfaces. 10480 */ 10481 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10482 return (-1); 10483 } 10484 } 10485 10486 return (0); 10487 } 10488 10489 /* 10490 * Function: fcp_kmem_cache_destructor 10491 * 10492 * Description: Called by the destructor of the cache managed by SCSA. 10493 * All the resources pre-allocated in fcp_pkt_constructor 10494 * and the data also pre-initialized in fcp_pkt_constructor 10495 * are freed and uninitialized here. 10496 * 10497 * Argument: *buf Memory to uninitialize. 10498 * *arg FCP port structure (fcp_port). 10499 * 10500 * Return Value: None 10501 * 10502 * Context: kernel 10503 */ 10504 static void 10505 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10506 { 10507 struct fcp_pkt *cmd; 10508 struct fcp_port *pptr; 10509 10510 pptr = (struct fcp_port *)(tran->tran_hba_private); 10511 cmd = pkt->pkt_ha_private; 10512 10513 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10514 /* 10515 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10516 * buffer and DMA resources allocated to do so are released. 10517 */ 10518 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10519 } 10520 } 10521 10522 /* 10523 * Function: fcp_alloc_cmd_resp 10524 * 10525 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10526 * will be DMAed by the HBA. The buffer is allocated applying 10527 * the DMA requirements for the HBA. The buffers allocated will 10528 * also be bound. DMA resources are allocated in the process. 10529 * They will be released by fcp_free_cmd_resp(). 10530 * 10531 * Argument: *pptr FCP port. 10532 * *fpkt fc packet for which the cmd and resp packet should be 10533 * allocated. 10534 * flags Allocation flags. 10535 * 10536 * Return Value: FC_FAILURE 10537 * FC_SUCCESS 10538 * 10539 * Context: User or Kernel context only if flags == KM_SLEEP. 10540 * Interrupt context if the KM_SLEEP is not specified. 10541 */ 10542 static int 10543 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10544 { 10545 int rval; 10546 int cmd_len; 10547 int resp_len; 10548 ulong_t real_len; 10549 int (*cb) (caddr_t); 10550 ddi_dma_cookie_t pkt_cookie; 10551 ddi_dma_cookie_t *cp; 10552 uint32_t cnt; 10553 10554 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10555 10556 cmd_len = fpkt->pkt_cmdlen; 10557 resp_len = fpkt->pkt_rsplen; 10558 10559 ASSERT(fpkt->pkt_cmd_dma == NULL); 10560 10561 /* Allocation of a DMA handle used in subsequent calls. */ 10562 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10563 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10564 return (FC_FAILURE); 10565 } 10566 10567 /* A buffer is allocated that satisfies the DMA requirements. */ 10568 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10569 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10570 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10571 10572 if (rval != DDI_SUCCESS) { 10573 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10574 return (FC_FAILURE); 10575 } 10576 10577 if (real_len < cmd_len) { 10578 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10579 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10580 return (FC_FAILURE); 10581 } 10582 10583 /* The buffer allocated is DMA bound. */ 10584 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10585 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10586 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10587 10588 if (rval != DDI_DMA_MAPPED) { 10589 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10590 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10591 return (FC_FAILURE); 10592 } 10593 10594 if (fpkt->pkt_cmd_cookie_cnt > 10595 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10596 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10597 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10598 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10599 return (FC_FAILURE); 10600 } 10601 10602 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10603 10604 /* 10605 * The buffer where the scatter/gather list is going to be built is 10606 * allocated. 10607 */ 10608 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10609 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10610 KM_NOSLEEP); 10611 10612 if (cp == NULL) { 10613 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10614 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10615 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10616 return (FC_FAILURE); 10617 } 10618 10619 /* 10620 * The scatter/gather list for the buffer we just allocated is built 10621 * here. 10622 */ 10623 *cp = pkt_cookie; 10624 cp++; 10625 10626 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10627 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10628 &pkt_cookie); 10629 *cp = pkt_cookie; 10630 } 10631 10632 ASSERT(fpkt->pkt_resp_dma == NULL); 10633 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10634 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10635 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10636 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10637 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10638 return (FC_FAILURE); 10639 } 10640 10641 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10642 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10643 (caddr_t *)&fpkt->pkt_resp, &real_len, 10644 &fpkt->pkt_resp_acc); 10645 10646 if (rval != DDI_SUCCESS) { 10647 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10648 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10649 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10650 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10651 kmem_free(fpkt->pkt_cmd_cookie, 10652 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10653 return (FC_FAILURE); 10654 } 10655 10656 if (real_len < resp_len) { 10657 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10658 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10659 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10660 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10661 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10662 kmem_free(fpkt->pkt_cmd_cookie, 10663 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10664 return (FC_FAILURE); 10665 } 10666 10667 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10668 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10669 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10670 10671 if (rval != DDI_DMA_MAPPED) { 10672 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10673 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10674 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10675 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10676 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10677 kmem_free(fpkt->pkt_cmd_cookie, 10678 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10679 return (FC_FAILURE); 10680 } 10681 10682 if (fpkt->pkt_resp_cookie_cnt > 10683 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10684 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10685 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10686 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10687 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10688 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10689 kmem_free(fpkt->pkt_cmd_cookie, 10690 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10691 return (FC_FAILURE); 10692 } 10693 10694 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10695 10696 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10697 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10698 KM_NOSLEEP); 10699 10700 if (cp == NULL) { 10701 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10702 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10703 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10704 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10705 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10706 kmem_free(fpkt->pkt_cmd_cookie, 10707 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10708 return (FC_FAILURE); 10709 } 10710 10711 *cp = pkt_cookie; 10712 cp++; 10713 10714 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10715 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10716 &pkt_cookie); 10717 *cp = pkt_cookie; 10718 } 10719 10720 return (FC_SUCCESS); 10721 } 10722 10723 /* 10724 * Function: fcp_free_cmd_resp 10725 * 10726 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10727 * allocated by fcp_alloc_cmd_resp() and all the resources 10728 * associated with them. That includes the DMA resources and the 10729 * buffer allocated for the cookies of each one of them. 10730 * 10731 * Argument: *pptr FCP port context. 10732 * *fpkt fc packet containing the cmd and resp packet 10733 * to be released. 10734 * 10735 * Return Value: None 10736 * 10737 * Context: Interrupt, User and Kernel context. 10738 */ 10739 /* ARGSUSED */ 10740 static void 10741 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10742 { 10743 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10744 10745 if (fpkt->pkt_resp_dma) { 10746 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10747 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10748 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10749 } 10750 10751 if (fpkt->pkt_resp_cookie) { 10752 kmem_free(fpkt->pkt_resp_cookie, 10753 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10754 fpkt->pkt_resp_cookie = NULL; 10755 } 10756 10757 if (fpkt->pkt_cmd_dma) { 10758 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10759 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10760 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10761 } 10762 10763 if (fpkt->pkt_cmd_cookie) { 10764 kmem_free(fpkt->pkt_cmd_cookie, 10765 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10766 fpkt->pkt_cmd_cookie = NULL; 10767 } 10768 } 10769 10770 10771 /* 10772 * called by the transport to do our own target initialization 10773 * 10774 * can acquire and release the global mutex 10775 */ 10776 /* ARGSUSED */ 10777 static int 10778 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10779 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10780 { 10781 uchar_t *bytes; 10782 uint_t nbytes; 10783 uint16_t lun_num; 10784 struct fcp_tgt *ptgt; 10785 struct fcp_lun *plun; 10786 struct fcp_port *pptr = (struct fcp_port *) 10787 hba_tran->tran_hba_private; 10788 10789 ASSERT(pptr != NULL); 10790 10791 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10792 FCP_BUF_LEVEL_8, 0, 10793 "fcp_phys_tgt_init: called for %s (instance %d)", 10794 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10795 10796 /* get our port WWN property */ 10797 bytes = NULL; 10798 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10799 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10800 (nbytes != FC_WWN_SIZE)) { 10801 /* no port WWN property */ 10802 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10803 FCP_BUF_LEVEL_8, 0, 10804 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10805 " for %s (instance %d): bytes=%p nbytes=%x", 10806 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10807 nbytes); 10808 10809 if (bytes != NULL) { 10810 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10811 } 10812 10813 return (DDI_NOT_WELL_FORMED); 10814 } 10815 ASSERT(bytes != NULL); 10816 10817 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10818 LUN_PROP, 0xFFFF); 10819 if (lun_num == 0xFFFF) { 10820 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10821 FCP_BUF_LEVEL_8, 0, 10822 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10823 " for %s (instance %d)", ddi_get_name(tgt_dip), 10824 ddi_get_instance(tgt_dip)); 10825 10826 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10827 return (DDI_NOT_WELL_FORMED); 10828 } 10829 10830 mutex_enter(&pptr->port_mutex); 10831 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10832 mutex_exit(&pptr->port_mutex); 10833 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10834 FCP_BUF_LEVEL_8, 0, 10835 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10836 " for %s (instance %d)", ddi_get_name(tgt_dip), 10837 ddi_get_instance(tgt_dip)); 10838 10839 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10840 return (DDI_FAILURE); 10841 } 10842 10843 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10844 FC_WWN_SIZE) == 0); 10845 ASSERT(plun->lun_num == lun_num); 10846 10847 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10848 10849 ptgt = plun->lun_tgt; 10850 10851 mutex_enter(&ptgt->tgt_mutex); 10852 plun->lun_tgt_count++; 10853 scsi_device_hba_private_set(sd, plun); 10854 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10855 plun->lun_sd = sd; 10856 mutex_exit(&ptgt->tgt_mutex); 10857 mutex_exit(&pptr->port_mutex); 10858 10859 return (DDI_SUCCESS); 10860 } 10861 10862 /*ARGSUSED*/ 10863 static int 10864 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10865 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10866 { 10867 uchar_t *bytes; 10868 uint_t nbytes; 10869 uint16_t lun_num; 10870 struct fcp_tgt *ptgt; 10871 struct fcp_lun *plun; 10872 struct fcp_port *pptr = (struct fcp_port *) 10873 hba_tran->tran_hba_private; 10874 child_info_t *cip; 10875 10876 ASSERT(pptr != NULL); 10877 10878 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10879 fcp_trace, FCP_BUF_LEVEL_8, 0, 10880 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10881 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10882 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10883 10884 cip = (child_info_t *)sd->sd_pathinfo; 10885 if (cip == NULL) { 10886 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10887 fcp_trace, FCP_BUF_LEVEL_8, 0, 10888 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10889 " for %s (instance %d)", ddi_get_name(tgt_dip), 10890 ddi_get_instance(tgt_dip)); 10891 10892 return (DDI_NOT_WELL_FORMED); 10893 } 10894 10895 /* get our port WWN property */ 10896 bytes = NULL; 10897 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10898 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10899 (nbytes != FC_WWN_SIZE)) { 10900 if (bytes) { 10901 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10902 } 10903 return (DDI_NOT_WELL_FORMED); 10904 } 10905 10906 ASSERT(bytes != NULL); 10907 10908 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10909 LUN_PROP, 0xFFFF); 10910 if (lun_num == 0xFFFF) { 10911 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10912 fcp_trace, FCP_BUF_LEVEL_8, 0, 10913 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10914 " for %s (instance %d)", ddi_get_name(tgt_dip), 10915 ddi_get_instance(tgt_dip)); 10916 10917 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10918 return (DDI_NOT_WELL_FORMED); 10919 } 10920 10921 mutex_enter(&pptr->port_mutex); 10922 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10923 mutex_exit(&pptr->port_mutex); 10924 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10925 fcp_trace, FCP_BUF_LEVEL_8, 0, 10926 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10927 " for %s (instance %d)", ddi_get_name(tgt_dip), 10928 ddi_get_instance(tgt_dip)); 10929 10930 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10931 return (DDI_FAILURE); 10932 } 10933 10934 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10935 FC_WWN_SIZE) == 0); 10936 ASSERT(plun->lun_num == lun_num); 10937 10938 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10939 10940 ptgt = plun->lun_tgt; 10941 10942 mutex_enter(&ptgt->tgt_mutex); 10943 plun->lun_tgt_count++; 10944 scsi_device_hba_private_set(sd, plun); 10945 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10946 plun->lun_sd = sd; 10947 mutex_exit(&ptgt->tgt_mutex); 10948 mutex_exit(&pptr->port_mutex); 10949 10950 return (DDI_SUCCESS); 10951 } 10952 10953 10954 /* 10955 * called by the transport to do our own target initialization 10956 * 10957 * can acquire and release the global mutex 10958 */ 10959 /* ARGSUSED */ 10960 static int 10961 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10962 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10963 { 10964 struct fcp_port *pptr = (struct fcp_port *) 10965 hba_tran->tran_hba_private; 10966 int rval; 10967 10968 ASSERT(pptr != NULL); 10969 10970 /* 10971 * Child node is getting initialized. Look at the mpxio component 10972 * type on the child device to see if this device is mpxio managed 10973 * or not. 10974 */ 10975 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 10976 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10977 } else { 10978 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10979 } 10980 10981 return (rval); 10982 } 10983 10984 10985 /* ARGSUSED */ 10986 static void 10987 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10988 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10989 { 10990 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 10991 struct fcp_tgt *ptgt; 10992 10993 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 10994 fcp_trace, FCP_BUF_LEVEL_8, 0, 10995 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 10996 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 10997 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10998 10999 if (plun == NULL) { 11000 return; 11001 } 11002 ptgt = plun->lun_tgt; 11003 11004 ASSERT(ptgt != NULL); 11005 11006 mutex_enter(&ptgt->tgt_mutex); 11007 ASSERT(plun->lun_tgt_count > 0); 11008 11009 if (--plun->lun_tgt_count == 0) { 11010 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11011 } 11012 plun->lun_sd = NULL; 11013 mutex_exit(&ptgt->tgt_mutex); 11014 } 11015 11016 /* 11017 * Function: fcp_scsi_start 11018 * 11019 * Description: This function is called by the target driver to request a 11020 * command to be sent. 11021 * 11022 * Argument: *ap SCSI address of the device. 11023 * *pkt SCSI packet containing the cmd to send. 11024 * 11025 * Return Value: TRAN_ACCEPT 11026 * TRAN_BUSY 11027 * TRAN_BADPKT 11028 * TRAN_FATAL_ERROR 11029 */ 11030 static int 11031 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11032 { 11033 struct fcp_port *pptr = ADDR2FCP(ap); 11034 struct fcp_lun *plun = ADDR2LUN(ap); 11035 struct fcp_pkt *cmd = PKT2CMD(pkt); 11036 struct fcp_tgt *ptgt = plun->lun_tgt; 11037 int rval; 11038 11039 /* ensure command isn't already issued */ 11040 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11041 11042 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11043 fcp_trace, FCP_BUF_LEVEL_9, 0, 11044 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11045 11046 /* 11047 * It is strange that we enter the fcp_port mutex and the target 11048 * mutex to check the lun state (which has a mutex of its own). 11049 */ 11050 mutex_enter(&pptr->port_mutex); 11051 mutex_enter(&ptgt->tgt_mutex); 11052 11053 /* 11054 * If the device is offline and is not in the process of coming 11055 * online, fail the request. 11056 */ 11057 11058 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11059 !(plun->lun_state & FCP_LUN_ONLINING)) { 11060 mutex_exit(&ptgt->tgt_mutex); 11061 mutex_exit(&pptr->port_mutex); 11062 11063 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11064 pkt->pkt_reason = CMD_DEV_GONE; 11065 } 11066 11067 return (TRAN_FATAL_ERROR); 11068 } 11069 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11070 11071 /* 11072 * If we are suspended, kernel is trying to dump, so don't 11073 * block, fail or defer requests - send them down right away. 11074 * NOTE: If we are in panic (i.e. trying to dump), we can't 11075 * assume we have been suspended. There is hardware such as 11076 * the v880 that doesn't do PM. Thus, the check for 11077 * ddi_in_panic. 11078 * 11079 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11080 * of changing. So, if we can queue the packet, do it. Eventually, 11081 * either the device will have gone away or changed and we can fail 11082 * the request, or we can proceed if the device didn't change. 11083 * 11084 * If the pd in the target or the packet is NULL it's probably 11085 * because the device has gone away, we allow the request to be 11086 * put on the internal queue here in case the device comes back within 11087 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11088 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11089 * could be NULL because the device was disappearing during or since 11090 * packet initialization. 11091 */ 11092 11093 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11094 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11095 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11096 (ptgt->tgt_pd_handle == NULL) || 11097 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11098 /* 11099 * If ((LUN is busy AND 11100 * LUN not suspended AND 11101 * The system is not in panic state) OR 11102 * (The port is coming up)) 11103 * 11104 * We check to see if the any of the flags FLAG_NOINTR or 11105 * FLAG_NOQUEUE is set. If one of them is set the value 11106 * returned will be TRAN_BUSY. If not, the request is queued. 11107 */ 11108 mutex_exit(&ptgt->tgt_mutex); 11109 mutex_exit(&pptr->port_mutex); 11110 11111 /* see if using interrupts is allowed (so queueing'll work) */ 11112 if (pkt->pkt_flags & FLAG_NOINTR) { 11113 pkt->pkt_resid = 0; 11114 return (TRAN_BUSY); 11115 } 11116 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11117 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11118 fcp_trace, FCP_BUF_LEVEL_9, 0, 11119 "fcp_scsi_start: lun busy for pkt %p", pkt); 11120 return (TRAN_BUSY); 11121 } 11122 #ifdef DEBUG 11123 mutex_enter(&pptr->port_pkt_mutex); 11124 pptr->port_npkts++; 11125 mutex_exit(&pptr->port_pkt_mutex); 11126 #endif /* DEBUG */ 11127 11128 /* got queue up the pkt for later */ 11129 fcp_queue_pkt(pptr, cmd); 11130 return (TRAN_ACCEPT); 11131 } 11132 cmd->cmd_state = FCP_PKT_ISSUED; 11133 11134 mutex_exit(&ptgt->tgt_mutex); 11135 mutex_exit(&pptr->port_mutex); 11136 11137 /* 11138 * Now that we released the mutexes, what was protected by them can 11139 * change. 11140 */ 11141 11142 /* 11143 * If there is a reconfiguration in progress, wait for it to complete. 11144 */ 11145 fcp_reconfig_wait(pptr); 11146 11147 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11148 pkt->pkt_time : 0; 11149 11150 /* prepare the packet */ 11151 11152 fcp_prepare_pkt(pptr, cmd, plun); 11153 11154 if (cmd->cmd_pkt->pkt_time) { 11155 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11156 } else { 11157 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11158 } 11159 11160 /* 11161 * if interrupts aren't allowed (e.g. at dump time) then we'll 11162 * have to do polled I/O 11163 */ 11164 if (pkt->pkt_flags & FLAG_NOINTR) { 11165 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11166 return (fcp_dopoll(pptr, cmd)); 11167 } 11168 11169 #ifdef DEBUG 11170 mutex_enter(&pptr->port_pkt_mutex); 11171 pptr->port_npkts++; 11172 mutex_exit(&pptr->port_pkt_mutex); 11173 #endif /* DEBUG */ 11174 11175 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11176 if (rval == FC_SUCCESS) { 11177 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11178 fcp_trace, FCP_BUF_LEVEL_9, 0, 11179 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11180 return (TRAN_ACCEPT); 11181 } 11182 11183 cmd->cmd_state = FCP_PKT_IDLE; 11184 11185 #ifdef DEBUG 11186 mutex_enter(&pptr->port_pkt_mutex); 11187 pptr->port_npkts--; 11188 mutex_exit(&pptr->port_pkt_mutex); 11189 #endif /* DEBUG */ 11190 11191 /* 11192 * For lack of clearer definitions, choose 11193 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11194 */ 11195 11196 if (rval == FC_TRAN_BUSY) { 11197 pkt->pkt_resid = 0; 11198 rval = TRAN_BUSY; 11199 } else { 11200 mutex_enter(&ptgt->tgt_mutex); 11201 if (plun->lun_state & FCP_LUN_OFFLINE) { 11202 child_info_t *cip; 11203 11204 mutex_enter(&plun->lun_mutex); 11205 cip = plun->lun_cip; 11206 mutex_exit(&plun->lun_mutex); 11207 11208 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11209 fcp_trace, FCP_BUF_LEVEL_6, 0, 11210 "fcp_transport failed 2 for %x: %x; dip=%p", 11211 plun->lun_tgt->tgt_d_id, rval, cip); 11212 11213 rval = TRAN_FATAL_ERROR; 11214 } else { 11215 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11216 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11217 fcp_trace, FCP_BUF_LEVEL_9, 0, 11218 "fcp_scsi_start: FC_BUSY for pkt %p", 11219 pkt); 11220 rval = TRAN_BUSY; 11221 } else { 11222 rval = TRAN_ACCEPT; 11223 fcp_queue_pkt(pptr, cmd); 11224 } 11225 } 11226 mutex_exit(&ptgt->tgt_mutex); 11227 } 11228 11229 return (rval); 11230 } 11231 11232 /* 11233 * called by the transport to abort a packet 11234 */ 11235 /*ARGSUSED*/ 11236 static int 11237 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11238 { 11239 int tgt_cnt; 11240 struct fcp_port *pptr = ADDR2FCP(ap); 11241 struct fcp_lun *plun = ADDR2LUN(ap); 11242 struct fcp_tgt *ptgt = plun->lun_tgt; 11243 11244 if (pkt == NULL) { 11245 if (ptgt) { 11246 mutex_enter(&ptgt->tgt_mutex); 11247 tgt_cnt = ptgt->tgt_change_cnt; 11248 mutex_exit(&ptgt->tgt_mutex); 11249 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11250 return (TRUE); 11251 } 11252 } 11253 return (FALSE); 11254 } 11255 11256 11257 /* 11258 * Perform reset 11259 */ 11260 int 11261 fcp_scsi_reset(struct scsi_address *ap, int level) 11262 { 11263 int rval = 0; 11264 struct fcp_port *pptr = ADDR2FCP(ap); 11265 struct fcp_lun *plun = ADDR2LUN(ap); 11266 struct fcp_tgt *ptgt = plun->lun_tgt; 11267 11268 if (level == RESET_ALL) { 11269 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11270 rval = 1; 11271 } 11272 } else if (level == RESET_TARGET || level == RESET_LUN) { 11273 /* 11274 * If we are in the middle of discovery, return 11275 * SUCCESS as this target will be rediscovered 11276 * anyway 11277 */ 11278 mutex_enter(&ptgt->tgt_mutex); 11279 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11280 mutex_exit(&ptgt->tgt_mutex); 11281 return (1); 11282 } 11283 mutex_exit(&ptgt->tgt_mutex); 11284 11285 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11286 rval = 1; 11287 } 11288 } 11289 return (rval); 11290 } 11291 11292 11293 /* 11294 * called by the framework to get a SCSI capability 11295 */ 11296 static int 11297 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11298 { 11299 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11300 } 11301 11302 11303 /* 11304 * called by the framework to set a SCSI capability 11305 */ 11306 static int 11307 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11308 { 11309 return (fcp_commoncap(ap, cap, value, whom, 1)); 11310 } 11311 11312 /* 11313 * Function: fcp_pkt_setup 11314 * 11315 * Description: This function sets up the scsi_pkt structure passed by the 11316 * caller. This function assumes fcp_pkt_constructor has been 11317 * called previously for the packet passed by the caller. If 11318 * successful this call will have the following results: 11319 * 11320 * - The resources needed that will be constant through out 11321 * the whole transaction are allocated. 11322 * - The fields that will be constant through out the whole 11323 * transaction are initialized. 11324 * - The scsi packet will be linked to the LUN structure 11325 * addressed by the transaction. 11326 * 11327 * Argument: 11328 * *pkt Pointer to a scsi_pkt structure. 11329 * callback 11330 * arg 11331 * 11332 * Return Value: 0 Success 11333 * !0 Failure 11334 * 11335 * Context: Kernel context or interrupt context 11336 */ 11337 /* ARGSUSED */ 11338 static int 11339 fcp_pkt_setup(struct scsi_pkt *pkt, 11340 int (*callback)(caddr_t arg), 11341 caddr_t arg) 11342 { 11343 struct fcp_pkt *cmd; 11344 struct fcp_port *pptr; 11345 struct fcp_lun *plun; 11346 struct fcp_tgt *ptgt; 11347 int kf; 11348 fc_packet_t *fpkt; 11349 fc_frame_hdr_t *hp; 11350 11351 pptr = ADDR2FCP(&pkt->pkt_address); 11352 plun = ADDR2LUN(&pkt->pkt_address); 11353 ptgt = plun->lun_tgt; 11354 11355 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11356 fpkt = cmd->cmd_fp_pkt; 11357 11358 /* 11359 * this request is for dma allocation only 11360 */ 11361 /* 11362 * First step of fcp_scsi_init_pkt: pkt allocation 11363 * We determine if the caller is willing to wait for the 11364 * resources. 11365 */ 11366 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11367 11368 /* 11369 * Selective zeroing of the pkt. 11370 */ 11371 cmd->cmd_back = NULL; 11372 cmd->cmd_next = NULL; 11373 11374 /* 11375 * Zero out fcp command 11376 */ 11377 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11378 11379 cmd->cmd_state = FCP_PKT_IDLE; 11380 11381 fpkt = cmd->cmd_fp_pkt; 11382 fpkt->pkt_data_acc = NULL; 11383 11384 /* 11385 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11386 * could be destroyed. We need fail pkt_setup. 11387 */ 11388 if (pptr->port_state & FCP_STATE_OFFLINE) { 11389 return (-1); 11390 } 11391 11392 mutex_enter(&ptgt->tgt_mutex); 11393 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11394 11395 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11396 != FC_SUCCESS) { 11397 mutex_exit(&ptgt->tgt_mutex); 11398 return (-1); 11399 } 11400 11401 mutex_exit(&ptgt->tgt_mutex); 11402 11403 /* Fill in the Fabric Channel Header */ 11404 hp = &fpkt->pkt_cmd_fhdr; 11405 hp->r_ctl = R_CTL_COMMAND; 11406 hp->rsvd = 0; 11407 hp->type = FC_TYPE_SCSI_FCP; 11408 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11409 hp->seq_id = 0; 11410 hp->df_ctl = 0; 11411 hp->seq_cnt = 0; 11412 hp->ox_id = 0xffff; 11413 hp->rx_id = 0xffff; 11414 hp->ro = 0; 11415 11416 /* 11417 * A doubly linked list (cmd_forw, cmd_back) is built 11418 * out of every allocated packet on a per-lun basis 11419 * 11420 * The packets are maintained in the list so as to satisfy 11421 * scsi_abort() requests. At present (which is unlikely to 11422 * change in the future) nobody performs a real scsi_abort 11423 * in the SCSI target drivers (as they don't keep the packets 11424 * after doing scsi_transport - so they don't know how to 11425 * abort a packet other than sending a NULL to abort all 11426 * outstanding packets) 11427 */ 11428 mutex_enter(&plun->lun_mutex); 11429 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11430 plun->lun_pkt_head->cmd_back = cmd; 11431 } else { 11432 plun->lun_pkt_tail = cmd; 11433 } 11434 plun->lun_pkt_head = cmd; 11435 mutex_exit(&plun->lun_mutex); 11436 return (0); 11437 } 11438 11439 /* 11440 * Function: fcp_pkt_teardown 11441 * 11442 * Description: This function releases a scsi_pkt structure and all the 11443 * resources attached to it. 11444 * 11445 * Argument: *pkt Pointer to a scsi_pkt structure. 11446 * 11447 * Return Value: None 11448 * 11449 * Context: User, Kernel or Interrupt context. 11450 */ 11451 static void 11452 fcp_pkt_teardown(struct scsi_pkt *pkt) 11453 { 11454 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11455 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11456 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11457 11458 /* 11459 * Remove the packet from the per-lun list 11460 */ 11461 mutex_enter(&plun->lun_mutex); 11462 if (cmd->cmd_back) { 11463 ASSERT(cmd != plun->lun_pkt_head); 11464 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11465 } else { 11466 ASSERT(cmd == plun->lun_pkt_head); 11467 plun->lun_pkt_head = cmd->cmd_forw; 11468 } 11469 11470 if (cmd->cmd_forw) { 11471 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11472 } else { 11473 ASSERT(cmd == plun->lun_pkt_tail); 11474 plun->lun_pkt_tail = cmd->cmd_back; 11475 } 11476 11477 mutex_exit(&plun->lun_mutex); 11478 11479 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11480 } 11481 11482 /* 11483 * Routine for reset notification setup, to register or cancel. 11484 * This function is called by SCSA 11485 */ 11486 /*ARGSUSED*/ 11487 static int 11488 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11489 void (*callback)(caddr_t), caddr_t arg) 11490 { 11491 struct fcp_port *pptr = ADDR2FCP(ap); 11492 11493 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11494 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11495 } 11496 11497 11498 static int 11499 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11500 ddi_eventcookie_t *event_cookiep) 11501 { 11502 struct fcp_port *pptr = fcp_dip2port(dip); 11503 11504 if (pptr == NULL) { 11505 return (DDI_FAILURE); 11506 } 11507 11508 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11509 event_cookiep, NDI_EVENT_NOPASS)); 11510 } 11511 11512 11513 static int 11514 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11515 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11516 ddi_callback_id_t *cb_id) 11517 { 11518 struct fcp_port *pptr = fcp_dip2port(dip); 11519 11520 if (pptr == NULL) { 11521 return (DDI_FAILURE); 11522 } 11523 11524 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11525 eventid, callback, arg, NDI_SLEEP, cb_id)); 11526 } 11527 11528 11529 static int 11530 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11531 { 11532 11533 struct fcp_port *pptr = fcp_dip2port(dip); 11534 11535 if (pptr == NULL) { 11536 return (DDI_FAILURE); 11537 } 11538 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11539 } 11540 11541 11542 /* 11543 * called by the transport to post an event 11544 */ 11545 static int 11546 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11547 ddi_eventcookie_t eventid, void *impldata) 11548 { 11549 struct fcp_port *pptr = fcp_dip2port(dip); 11550 11551 if (pptr == NULL) { 11552 return (DDI_FAILURE); 11553 } 11554 11555 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11556 eventid, impldata)); 11557 } 11558 11559 11560 /* 11561 * A target in in many cases in Fibre Channel has a one to one relation 11562 * with a port identifier (which is also known as D_ID and also as AL_PA 11563 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11564 * will most likely result in resetting all LUNs (which means a reset will 11565 * occur on all the SCSI devices connected at the other end of the bridge) 11566 * That is the latest favorite topic for discussion, for, one can debate as 11567 * hot as one likes and come up with arguably a best solution to one's 11568 * satisfaction 11569 * 11570 * To stay on track and not digress much, here are the problems stated 11571 * briefly: 11572 * 11573 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11574 * target drivers use RESET_TARGET even if their instance is on a 11575 * LUN. Doesn't that sound a bit broken ? 11576 * 11577 * FCP SCSI (the current spec) only defines RESET TARGET in the 11578 * control fields of an FCP_CMND structure. It should have been 11579 * fixed right there, giving flexibility to the initiators to 11580 * minimize havoc that could be caused by resetting a target. 11581 */ 11582 static int 11583 fcp_reset_target(struct scsi_address *ap, int level) 11584 { 11585 int rval = FC_FAILURE; 11586 char lun_id[25]; 11587 struct fcp_port *pptr = ADDR2FCP(ap); 11588 struct fcp_lun *plun = ADDR2LUN(ap); 11589 struct fcp_tgt *ptgt = plun->lun_tgt; 11590 struct scsi_pkt *pkt; 11591 struct fcp_pkt *cmd; 11592 struct fcp_rsp *rsp; 11593 uint32_t tgt_cnt; 11594 struct fcp_rsp_info *rsp_info; 11595 struct fcp_reset_elem *p; 11596 int bval; 11597 11598 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11599 KM_NOSLEEP)) == NULL) { 11600 return (rval); 11601 } 11602 11603 mutex_enter(&ptgt->tgt_mutex); 11604 if (level == RESET_TARGET) { 11605 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11606 mutex_exit(&ptgt->tgt_mutex); 11607 kmem_free(p, sizeof (struct fcp_reset_elem)); 11608 return (rval); 11609 } 11610 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11611 (void) strcpy(lun_id, " "); 11612 } else { 11613 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11614 mutex_exit(&ptgt->tgt_mutex); 11615 kmem_free(p, sizeof (struct fcp_reset_elem)); 11616 return (rval); 11617 } 11618 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11619 11620 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11621 } 11622 tgt_cnt = ptgt->tgt_change_cnt; 11623 11624 mutex_exit(&ptgt->tgt_mutex); 11625 11626 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11627 0, 0, NULL, 0)) == NULL) { 11628 kmem_free(p, sizeof (struct fcp_reset_elem)); 11629 mutex_enter(&ptgt->tgt_mutex); 11630 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11631 mutex_exit(&ptgt->tgt_mutex); 11632 return (rval); 11633 } 11634 pkt->pkt_time = FCP_POLL_TIMEOUT; 11635 11636 /* fill in cmd part of packet */ 11637 cmd = PKT2CMD(pkt); 11638 if (level == RESET_TARGET) { 11639 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11640 } else { 11641 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11642 } 11643 cmd->cmd_fp_pkt->pkt_comp = NULL; 11644 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11645 11646 /* prepare a packet for transport */ 11647 fcp_prepare_pkt(pptr, cmd, plun); 11648 11649 if (cmd->cmd_pkt->pkt_time) { 11650 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11651 } else { 11652 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11653 } 11654 11655 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11656 bval = fcp_dopoll(pptr, cmd); 11657 fc_ulp_idle_port(pptr->port_fp_handle); 11658 11659 /* submit the packet */ 11660 if (bval == TRAN_ACCEPT) { 11661 int error = 3; 11662 11663 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11664 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11665 sizeof (struct fcp_rsp)); 11666 11667 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11668 if (fcp_validate_fcp_response(rsp, pptr) == 11669 FC_SUCCESS) { 11670 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11671 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11672 sizeof (struct fcp_rsp), rsp_info, 11673 cmd->cmd_fp_pkt->pkt_resp_acc, 11674 sizeof (struct fcp_rsp_info)); 11675 } 11676 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11677 rval = FC_SUCCESS; 11678 error = 0; 11679 } else { 11680 error = 1; 11681 } 11682 } else { 11683 error = 2; 11684 } 11685 } 11686 11687 switch (error) { 11688 case 0: 11689 fcp_log(CE_WARN, pptr->port_dip, 11690 "!FCP: WWN 0x%08x%08x %s reset successfully", 11691 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11692 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11693 break; 11694 11695 case 1: 11696 fcp_log(CE_WARN, pptr->port_dip, 11697 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11698 " response code=%x", 11699 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11700 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11701 rsp_info->rsp_code); 11702 break; 11703 11704 case 2: 11705 fcp_log(CE_WARN, pptr->port_dip, 11706 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11707 " Bad FCP response values: rsvd1=%x," 11708 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11709 " rsplen=%x, senselen=%x", 11710 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11711 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11712 rsp->reserved_0, rsp->reserved_1, 11713 rsp->fcp_u.fcp_status.reserved_0, 11714 rsp->fcp_u.fcp_status.reserved_1, 11715 rsp->fcp_response_len, rsp->fcp_sense_len); 11716 break; 11717 11718 default: 11719 fcp_log(CE_WARN, pptr->port_dip, 11720 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11721 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11722 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11723 break; 11724 } 11725 } 11726 scsi_destroy_pkt(pkt); 11727 11728 if (rval == FC_FAILURE) { 11729 mutex_enter(&ptgt->tgt_mutex); 11730 if (level == RESET_TARGET) { 11731 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11732 } else { 11733 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11734 } 11735 mutex_exit(&ptgt->tgt_mutex); 11736 kmem_free(p, sizeof (struct fcp_reset_elem)); 11737 return (rval); 11738 } 11739 11740 mutex_enter(&pptr->port_mutex); 11741 if (level == RESET_TARGET) { 11742 p->tgt = ptgt; 11743 p->lun = NULL; 11744 } else { 11745 p->tgt = NULL; 11746 p->lun = plun; 11747 } 11748 p->tgt = ptgt; 11749 p->tgt_cnt = tgt_cnt; 11750 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11751 p->next = pptr->port_reset_list; 11752 pptr->port_reset_list = p; 11753 11754 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11755 fcp_trace, FCP_BUF_LEVEL_3, 0, 11756 "Notify ssd of the reset to reinstate the reservations"); 11757 11758 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11759 &pptr->port_reset_notify_listf); 11760 11761 mutex_exit(&pptr->port_mutex); 11762 11763 return (rval); 11764 } 11765 11766 11767 /* 11768 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11769 * SCSI capabilities 11770 */ 11771 /* ARGSUSED */ 11772 static int 11773 fcp_commoncap(struct scsi_address *ap, char *cap, 11774 int val, int tgtonly, int doset) 11775 { 11776 struct fcp_port *pptr = ADDR2FCP(ap); 11777 struct fcp_lun *plun = ADDR2LUN(ap); 11778 struct fcp_tgt *ptgt = plun->lun_tgt; 11779 int cidx; 11780 int rval = FALSE; 11781 11782 if (cap == (char *)0) { 11783 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11784 fcp_trace, FCP_BUF_LEVEL_3, 0, 11785 "fcp_commoncap: invalid arg"); 11786 return (rval); 11787 } 11788 11789 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11790 return (UNDEFINED); 11791 } 11792 11793 /* 11794 * Process setcap request. 11795 */ 11796 if (doset) { 11797 /* 11798 * At present, we can only set binary (0/1) values 11799 */ 11800 switch (cidx) { 11801 case SCSI_CAP_ARQ: 11802 if (val == 0) { 11803 rval = FALSE; 11804 } else { 11805 rval = TRUE; 11806 } 11807 break; 11808 11809 case SCSI_CAP_LUN_RESET: 11810 if (val) { 11811 plun->lun_cap |= FCP_LUN_CAP_RESET; 11812 } else { 11813 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11814 } 11815 rval = TRUE; 11816 break; 11817 11818 case SCSI_CAP_SECTOR_SIZE: 11819 rval = TRUE; 11820 break; 11821 default: 11822 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11823 fcp_trace, FCP_BUF_LEVEL_4, 0, 11824 "fcp_setcap: unsupported %d", cidx); 11825 rval = UNDEFINED; 11826 break; 11827 } 11828 11829 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11830 fcp_trace, FCP_BUF_LEVEL_5, 0, 11831 "set cap: cap=%s, val/tgtonly/doset/rval = " 11832 "0x%x/0x%x/0x%x/%d", 11833 cap, val, tgtonly, doset, rval); 11834 11835 } else { 11836 /* 11837 * Process getcap request. 11838 */ 11839 switch (cidx) { 11840 case SCSI_CAP_DMA_MAX: 11841 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11842 11843 /* 11844 * Need to make an adjustment qlc is uint_t 64 11845 * st is int, so we will make the adjustment here 11846 * being as nobody wants to touch this. 11847 * It still leaves the max single block length 11848 * of 2 gig. This should last . 11849 */ 11850 11851 if (rval == -1) { 11852 rval = MAX_INT_DMA; 11853 } 11854 11855 break; 11856 11857 case SCSI_CAP_INITIATOR_ID: 11858 rval = pptr->port_id; 11859 break; 11860 11861 case SCSI_CAP_ARQ: 11862 case SCSI_CAP_RESET_NOTIFICATION: 11863 case SCSI_CAP_TAGGED_QING: 11864 rval = TRUE; 11865 break; 11866 11867 case SCSI_CAP_SCSI_VERSION: 11868 rval = 3; 11869 break; 11870 11871 case SCSI_CAP_INTERCONNECT_TYPE: 11872 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11873 (ptgt->tgt_hard_addr == 0)) { 11874 rval = INTERCONNECT_FABRIC; 11875 } else { 11876 rval = INTERCONNECT_FIBRE; 11877 } 11878 break; 11879 11880 case SCSI_CAP_LUN_RESET: 11881 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11882 TRUE : FALSE; 11883 break; 11884 11885 default: 11886 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11887 fcp_trace, FCP_BUF_LEVEL_4, 0, 11888 "fcp_getcap: unsupported %d", cidx); 11889 rval = UNDEFINED; 11890 break; 11891 } 11892 11893 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11894 fcp_trace, FCP_BUF_LEVEL_8, 0, 11895 "get cap: cap=%s, val/tgtonly/doset/rval = " 11896 "0x%x/0x%x/0x%x/%d", 11897 cap, val, tgtonly, doset, rval); 11898 } 11899 11900 return (rval); 11901 } 11902 11903 /* 11904 * called by the transport to get the port-wwn and lun 11905 * properties of this device, and to create a "name" based on them 11906 * 11907 * these properties don't exist on sun4m 11908 * 11909 * return 1 for success else return 0 11910 */ 11911 /* ARGSUSED */ 11912 static int 11913 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11914 { 11915 int i; 11916 int *lun; 11917 int numChars; 11918 uint_t nlun; 11919 uint_t count; 11920 uint_t nbytes; 11921 uchar_t *bytes; 11922 uint16_t lun_num; 11923 uint32_t tgt_id; 11924 char **conf_wwn; 11925 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11926 uchar_t barray[FC_WWN_SIZE]; 11927 dev_info_t *tgt_dip; 11928 struct fcp_tgt *ptgt; 11929 struct fcp_port *pptr; 11930 struct fcp_lun *plun; 11931 11932 ASSERT(sd != NULL); 11933 ASSERT(name != NULL); 11934 11935 tgt_dip = sd->sd_dev; 11936 pptr = ddi_get_soft_state(fcp_softstate, 11937 ddi_get_instance(ddi_get_parent(tgt_dip))); 11938 if (pptr == NULL) { 11939 return (0); 11940 } 11941 11942 ASSERT(tgt_dip != NULL); 11943 11944 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11945 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11946 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11947 name[0] = '\0'; 11948 return (0); 11949 } 11950 11951 if (nlun == 0) { 11952 ddi_prop_free(lun); 11953 return (0); 11954 } 11955 11956 lun_num = lun[0]; 11957 ddi_prop_free(lun); 11958 11959 /* 11960 * Lookup for .conf WWN property 11961 */ 11962 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11963 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11964 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11965 ASSERT(count >= 1); 11966 11967 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11968 ddi_prop_free(conf_wwn); 11969 mutex_enter(&pptr->port_mutex); 11970 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11971 mutex_exit(&pptr->port_mutex); 11972 return (0); 11973 } 11974 ptgt = plun->lun_tgt; 11975 mutex_exit(&pptr->port_mutex); 11976 11977 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11978 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11979 11980 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11981 ptgt->tgt_hard_addr != 0) { 11982 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11983 ptgt->tgt_hard_addr]; 11984 } else { 11985 tgt_id = ptgt->tgt_d_id; 11986 } 11987 11988 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11989 TARGET_PROP, tgt_id); 11990 } 11991 11992 /* get the our port-wwn property */ 11993 bytes = NULL; 11994 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 11995 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 11996 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 11997 if (bytes != NULL) { 11998 ddi_prop_free(bytes); 11999 } 12000 return (0); 12001 } 12002 12003 for (i = 0; i < FC_WWN_SIZE; i++) { 12004 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12005 } 12006 12007 /* Stick in the address of the form "wWWN,LUN" */ 12008 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12009 12010 ASSERT(numChars < len); 12011 if (numChars >= len) { 12012 fcp_log(CE_WARN, pptr->port_dip, 12013 "!fcp_scsi_get_name: " 12014 "name parameter length too small, it needs to be %d", 12015 numChars+1); 12016 } 12017 12018 ddi_prop_free(bytes); 12019 12020 return (1); 12021 } 12022 12023 12024 /* 12025 * called by the transport to get the SCSI target id value, returning 12026 * it in "name" 12027 * 12028 * this isn't needed/used on sun4m 12029 * 12030 * return 1 for success else return 0 12031 */ 12032 /* ARGSUSED */ 12033 static int 12034 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12035 { 12036 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12037 struct fcp_tgt *ptgt; 12038 int numChars; 12039 12040 if (plun == NULL) { 12041 return (0); 12042 } 12043 12044 if ((ptgt = plun->lun_tgt) == NULL) { 12045 return (0); 12046 } 12047 12048 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12049 12050 ASSERT(numChars < len); 12051 if (numChars >= len) { 12052 fcp_log(CE_WARN, NULL, 12053 "!fcp_scsi_get_bus_addr: " 12054 "name parameter length too small, it needs to be %d", 12055 numChars+1); 12056 } 12057 12058 return (1); 12059 } 12060 12061 12062 /* 12063 * called internally to reset the link where the specified port lives 12064 */ 12065 static int 12066 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12067 { 12068 la_wwn_t wwn; 12069 struct fcp_lun *plun; 12070 struct fcp_tgt *ptgt; 12071 12072 /* disable restart of lip if we're suspended */ 12073 mutex_enter(&pptr->port_mutex); 12074 12075 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12076 FCP_STATE_POWER_DOWN)) { 12077 mutex_exit(&pptr->port_mutex); 12078 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12079 fcp_trace, FCP_BUF_LEVEL_2, 0, 12080 "fcp_linkreset, fcp%d: link reset " 12081 "disabled due to DDI_SUSPEND", 12082 ddi_get_instance(pptr->port_dip)); 12083 return (FC_FAILURE); 12084 } 12085 12086 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12087 mutex_exit(&pptr->port_mutex); 12088 return (FC_SUCCESS); 12089 } 12090 12091 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12092 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12093 12094 /* 12095 * If ap == NULL assume local link reset. 12096 */ 12097 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12098 plun = ADDR2LUN(ap); 12099 ptgt = plun->lun_tgt; 12100 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12101 } else { 12102 bzero((caddr_t)&wwn, sizeof (wwn)); 12103 } 12104 mutex_exit(&pptr->port_mutex); 12105 12106 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12107 } 12108 12109 12110 /* 12111 * called from fcp_port_attach() to resume a port 12112 * return DDI_* success/failure status 12113 * acquires and releases the global mutex 12114 * acquires and releases the port mutex 12115 */ 12116 /*ARGSUSED*/ 12117 12118 static int 12119 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12120 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12121 { 12122 int res = DDI_FAILURE; /* default result */ 12123 struct fcp_port *pptr; /* port state ptr */ 12124 uint32_t alloc_cnt; 12125 uint32_t max_cnt; 12126 fc_portmap_t *tmp_list = NULL; 12127 12128 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12129 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12130 instance); 12131 12132 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12133 cmn_err(CE_WARN, "fcp: bad soft state"); 12134 return (res); 12135 } 12136 12137 mutex_enter(&pptr->port_mutex); 12138 switch (cmd) { 12139 case FC_CMD_RESUME: 12140 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12141 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12142 break; 12143 12144 case FC_CMD_POWER_UP: 12145 /* 12146 * If the port is DDI_SUSPENded, defer rediscovery 12147 * until DDI_RESUME occurs 12148 */ 12149 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12150 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12151 mutex_exit(&pptr->port_mutex); 12152 return (DDI_SUCCESS); 12153 } 12154 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12155 } 12156 pptr->port_id = s_id; 12157 pptr->port_state = FCP_STATE_INIT; 12158 mutex_exit(&pptr->port_mutex); 12159 12160 /* 12161 * Make a copy of ulp_port_info as fctl allocates 12162 * a temp struct. 12163 */ 12164 (void) fcp_cp_pinfo(pptr, pinfo); 12165 12166 mutex_enter(&fcp_global_mutex); 12167 if (fcp_watchdog_init++ == 0) { 12168 fcp_watchdog_tick = fcp_watchdog_timeout * 12169 drv_usectohz(1000000); 12170 fcp_watchdog_id = timeout(fcp_watch, 12171 NULL, fcp_watchdog_tick); 12172 } 12173 mutex_exit(&fcp_global_mutex); 12174 12175 /* 12176 * Handle various topologies and link states. 12177 */ 12178 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12179 case FC_STATE_OFFLINE: 12180 /* 12181 * Wait for ONLINE, at which time a state 12182 * change will cause a statec_callback 12183 */ 12184 res = DDI_SUCCESS; 12185 break; 12186 12187 case FC_STATE_ONLINE: 12188 12189 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12190 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12191 res = DDI_SUCCESS; 12192 break; 12193 } 12194 12195 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12196 !fcp_enable_auto_configuration) { 12197 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12198 if (tmp_list == NULL) { 12199 if (!alloc_cnt) { 12200 res = DDI_SUCCESS; 12201 } 12202 break; 12203 } 12204 max_cnt = alloc_cnt; 12205 } else { 12206 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12207 12208 alloc_cnt = FCP_MAX_DEVICES; 12209 12210 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12211 (sizeof (fc_portmap_t)) * alloc_cnt, 12212 KM_NOSLEEP)) == NULL) { 12213 fcp_log(CE_WARN, pptr->port_dip, 12214 "!fcp%d: failed to allocate portmap", 12215 instance); 12216 break; 12217 } 12218 12219 max_cnt = alloc_cnt; 12220 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12221 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12222 FC_SUCCESS) { 12223 caddr_t msg; 12224 12225 (void) fc_ulp_error(res, &msg); 12226 12227 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12228 fcp_trace, FCP_BUF_LEVEL_2, 0, 12229 "resume failed getportmap: reason=0x%x", 12230 res); 12231 12232 fcp_log(CE_WARN, pptr->port_dip, 12233 "!failed to get port map : %s", msg); 12234 break; 12235 } 12236 if (max_cnt > alloc_cnt) { 12237 alloc_cnt = max_cnt; 12238 } 12239 } 12240 12241 /* 12242 * do the SCSI device discovery and create 12243 * the devinfos 12244 */ 12245 fcp_statec_callback(ulph, pptr->port_fp_handle, 12246 pptr->port_phys_state, pptr->port_topology, tmp_list, 12247 max_cnt, pptr->port_id); 12248 12249 res = DDI_SUCCESS; 12250 break; 12251 12252 default: 12253 fcp_log(CE_WARN, pptr->port_dip, 12254 "!fcp%d: invalid port state at attach=0x%x", 12255 instance, pptr->port_phys_state); 12256 12257 mutex_enter(&pptr->port_mutex); 12258 pptr->port_phys_state = FCP_STATE_OFFLINE; 12259 mutex_exit(&pptr->port_mutex); 12260 res = DDI_SUCCESS; 12261 12262 break; 12263 } 12264 12265 if (tmp_list != NULL) { 12266 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12267 } 12268 12269 return (res); 12270 } 12271 12272 12273 static void 12274 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12275 { 12276 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12277 pptr->port_dip = pinfo->port_dip; 12278 pptr->port_fp_handle = pinfo->port_handle; 12279 if (pinfo->port_acc_attr != NULL) { 12280 /* 12281 * FCA supports DMA 12282 */ 12283 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12284 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12285 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12286 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12287 } 12288 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12289 pptr->port_max_exch = pinfo->port_fca_max_exch; 12290 pptr->port_phys_state = pinfo->port_state; 12291 pptr->port_topology = pinfo->port_flags; 12292 pptr->port_reset_action = pinfo->port_reset_action; 12293 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12294 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12295 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12296 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12297 12298 /* Clear FMA caps to avoid fm-capability ereport */ 12299 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12300 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12301 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12302 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12303 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12304 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12305 } 12306 12307 /* 12308 * If the elements wait field is set to 1 then 12309 * another thread is waiting for the operation to complete. Once 12310 * it is complete, the waiting thread is signaled and the element is 12311 * freed by the waiting thread. If the elements wait field is set to 0 12312 * the element is freed. 12313 */ 12314 static void 12315 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12316 { 12317 ASSERT(elem != NULL); 12318 mutex_enter(&elem->mutex); 12319 elem->result = result; 12320 if (elem->wait) { 12321 elem->wait = 0; 12322 cv_signal(&elem->cv); 12323 mutex_exit(&elem->mutex); 12324 } else { 12325 mutex_exit(&elem->mutex); 12326 cv_destroy(&elem->cv); 12327 mutex_destroy(&elem->mutex); 12328 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12329 } 12330 } 12331 12332 /* 12333 * This function is invoked from the taskq thread to allocate 12334 * devinfo nodes and to online/offline them. 12335 */ 12336 static void 12337 fcp_hp_task(void *arg) 12338 { 12339 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12340 struct fcp_lun *plun = elem->lun; 12341 struct fcp_port *pptr = elem->port; 12342 int result; 12343 12344 ASSERT(elem->what == FCP_ONLINE || 12345 elem->what == FCP_OFFLINE || 12346 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12347 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12348 12349 mutex_enter(&pptr->port_mutex); 12350 mutex_enter(&plun->lun_mutex); 12351 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12352 plun->lun_event_count != elem->event_cnt) || 12353 pptr->port_state & (FCP_STATE_SUSPENDED | 12354 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12355 mutex_exit(&plun->lun_mutex); 12356 mutex_exit(&pptr->port_mutex); 12357 fcp_process_elem(elem, NDI_FAILURE); 12358 return; 12359 } 12360 mutex_exit(&plun->lun_mutex); 12361 mutex_exit(&pptr->port_mutex); 12362 12363 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12364 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12365 fcp_process_elem(elem, result); 12366 } 12367 12368 12369 static child_info_t * 12370 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12371 int tcount) 12372 { 12373 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12374 12375 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12376 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12377 12378 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12379 /* 12380 * Child has not been created yet. Create the child device 12381 * based on the per-Lun flags. 12382 */ 12383 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12384 plun->lun_cip = 12385 CIP(fcp_create_dip(plun, lcount, tcount)); 12386 plun->lun_mpxio = 0; 12387 } else { 12388 plun->lun_cip = 12389 CIP(fcp_create_pip(plun, lcount, tcount)); 12390 plun->lun_mpxio = 1; 12391 } 12392 } else { 12393 plun->lun_cip = cip; 12394 } 12395 12396 return (plun->lun_cip); 12397 } 12398 12399 12400 static int 12401 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12402 { 12403 int rval = FC_FAILURE; 12404 dev_info_t *pdip; 12405 struct dev_info *dip; 12406 int circular; 12407 12408 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12409 12410 pdip = plun->lun_tgt->tgt_port->port_dip; 12411 12412 if (plun->lun_cip == NULL) { 12413 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12414 fcp_trace, FCP_BUF_LEVEL_3, 0, 12415 "fcp_is_dip_present: plun->lun_cip is NULL: " 12416 "plun: %p lun state: %x num: %d target state: %x", 12417 plun, plun->lun_state, plun->lun_num, 12418 plun->lun_tgt->tgt_port->port_state); 12419 return (rval); 12420 } 12421 ndi_devi_enter(pdip, &circular); 12422 dip = DEVI(pdip)->devi_child; 12423 while (dip) { 12424 if (dip == DEVI(cdip)) { 12425 rval = FC_SUCCESS; 12426 break; 12427 } 12428 dip = dip->devi_sibling; 12429 } 12430 ndi_devi_exit(pdip, circular); 12431 return (rval); 12432 } 12433 12434 static int 12435 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12436 { 12437 int rval = FC_FAILURE; 12438 12439 ASSERT(plun != NULL); 12440 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12441 12442 if (plun->lun_mpxio == 0) { 12443 rval = fcp_is_dip_present(plun, DIP(cip)); 12444 } else { 12445 rval = fcp_is_pip_present(plun, PIP(cip)); 12446 } 12447 12448 return (rval); 12449 } 12450 12451 /* 12452 * Function: fcp_create_dip 12453 * 12454 * Description: Creates a dev_info_t structure for the LUN specified by the 12455 * caller. 12456 * 12457 * Argument: plun Lun structure 12458 * link_cnt Link state count. 12459 * tgt_cnt Target state change count. 12460 * 12461 * Return Value: NULL if it failed 12462 * dev_info_t structure address if it succeeded 12463 * 12464 * Context: Kernel context 12465 */ 12466 static dev_info_t * 12467 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12468 { 12469 int failure = 0; 12470 uint32_t tgt_id; 12471 uint64_t sam_lun; 12472 struct fcp_tgt *ptgt = plun->lun_tgt; 12473 struct fcp_port *pptr = ptgt->tgt_port; 12474 dev_info_t *pdip = pptr->port_dip; 12475 dev_info_t *cdip = NULL; 12476 dev_info_t *old_dip = DIP(plun->lun_cip); 12477 char *nname = NULL; 12478 char **compatible = NULL; 12479 int ncompatible; 12480 char *scsi_binding_set; 12481 char t_pwwn[17]; 12482 12483 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12484 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12485 12486 /* get the 'scsi-binding-set' property */ 12487 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12488 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12489 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12490 scsi_binding_set = NULL; 12491 } 12492 12493 /* determine the node name and compatible */ 12494 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12495 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12496 if (scsi_binding_set) { 12497 ddi_prop_free(scsi_binding_set); 12498 } 12499 12500 if (nname == NULL) { 12501 #ifdef DEBUG 12502 cmn_err(CE_WARN, "%s%d: no driver for " 12503 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12504 " compatible: %s", 12505 ddi_driver_name(pdip), ddi_get_instance(pdip), 12506 ptgt->tgt_port_wwn.raw_wwn[0], 12507 ptgt->tgt_port_wwn.raw_wwn[1], 12508 ptgt->tgt_port_wwn.raw_wwn[2], 12509 ptgt->tgt_port_wwn.raw_wwn[3], 12510 ptgt->tgt_port_wwn.raw_wwn[4], 12511 ptgt->tgt_port_wwn.raw_wwn[5], 12512 ptgt->tgt_port_wwn.raw_wwn[6], 12513 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12514 *compatible); 12515 #endif /* DEBUG */ 12516 failure++; 12517 goto end_of_fcp_create_dip; 12518 } 12519 12520 cdip = fcp_find_existing_dip(plun, pdip, nname); 12521 12522 /* 12523 * if the old_dip does not match the cdip, that means there is 12524 * some property change. since we'll be using the cdip, we need 12525 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12526 * then the dtype for the device has been updated. Offline the 12527 * the old device and create a new device with the new device type 12528 * Refer to bug: 4764752 12529 */ 12530 if (old_dip && (cdip != old_dip || 12531 plun->lun_state & FCP_LUN_CHANGED)) { 12532 plun->lun_state &= ~(FCP_LUN_INIT); 12533 mutex_exit(&plun->lun_mutex); 12534 mutex_exit(&pptr->port_mutex); 12535 12536 mutex_enter(&ptgt->tgt_mutex); 12537 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12538 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12539 mutex_exit(&ptgt->tgt_mutex); 12540 12541 #ifdef DEBUG 12542 if (cdip != NULL) { 12543 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12544 fcp_trace, FCP_BUF_LEVEL_2, 0, 12545 "Old dip=%p; New dip=%p don't match", old_dip, 12546 cdip); 12547 } else { 12548 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12549 fcp_trace, FCP_BUF_LEVEL_2, 0, 12550 "Old dip=%p; New dip=NULL don't match", old_dip); 12551 } 12552 #endif 12553 12554 mutex_enter(&pptr->port_mutex); 12555 mutex_enter(&plun->lun_mutex); 12556 } 12557 12558 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12559 plun->lun_state &= ~(FCP_LUN_CHANGED); 12560 if (ndi_devi_alloc(pptr->port_dip, nname, 12561 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12562 failure++; 12563 goto end_of_fcp_create_dip; 12564 } 12565 } 12566 12567 /* 12568 * Previously all the properties for the devinfo were destroyed here 12569 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12570 * the devid property (and other properties established by the target 12571 * driver or framework) which the code does not always recreate, this 12572 * call was removed. 12573 * This opens a theoretical possibility that we may return with a 12574 * stale devid on the node if the scsi entity behind the fibre channel 12575 * lun has changed. 12576 */ 12577 12578 /* decorate the node with compatible */ 12579 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12580 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12581 failure++; 12582 goto end_of_fcp_create_dip; 12583 } 12584 12585 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12586 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12587 failure++; 12588 goto end_of_fcp_create_dip; 12589 } 12590 12591 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12592 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12593 failure++; 12594 goto end_of_fcp_create_dip; 12595 } 12596 12597 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12598 t_pwwn[16] = '\0'; 12599 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12600 != DDI_PROP_SUCCESS) { 12601 failure++; 12602 goto end_of_fcp_create_dip; 12603 } 12604 12605 /* 12606 * If there is no hard address - We might have to deal with 12607 * that by using WWN - Having said that it is important to 12608 * recognize this problem early so ssd can be informed of 12609 * the right interconnect type. 12610 */ 12611 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12612 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12613 } else { 12614 tgt_id = ptgt->tgt_d_id; 12615 } 12616 12617 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12618 tgt_id) != DDI_PROP_SUCCESS) { 12619 failure++; 12620 goto end_of_fcp_create_dip; 12621 } 12622 12623 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12624 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12625 failure++; 12626 goto end_of_fcp_create_dip; 12627 } 12628 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12629 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12630 sam_lun) != DDI_PROP_SUCCESS) { 12631 failure++; 12632 goto end_of_fcp_create_dip; 12633 } 12634 12635 end_of_fcp_create_dip: 12636 scsi_hba_nodename_compatible_free(nname, compatible); 12637 12638 if (cdip != NULL && failure) { 12639 (void) ndi_prop_remove_all(cdip); 12640 (void) ndi_devi_free(cdip); 12641 cdip = NULL; 12642 } 12643 12644 return (cdip); 12645 } 12646 12647 /* 12648 * Function: fcp_create_pip 12649 * 12650 * Description: Creates a Path Id for the LUN specified by the caller. 12651 * 12652 * Argument: plun Lun structure 12653 * link_cnt Link state count. 12654 * tgt_cnt Target state count. 12655 * 12656 * Return Value: NULL if it failed 12657 * mdi_pathinfo_t structure address if it succeeded 12658 * 12659 * Context: Kernel context 12660 */ 12661 static mdi_pathinfo_t * 12662 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12663 { 12664 int i; 12665 char buf[MAXNAMELEN]; 12666 char uaddr[MAXNAMELEN]; 12667 int failure = 0; 12668 uint32_t tgt_id; 12669 uint64_t sam_lun; 12670 struct fcp_tgt *ptgt = plun->lun_tgt; 12671 struct fcp_port *pptr = ptgt->tgt_port; 12672 dev_info_t *pdip = pptr->port_dip; 12673 mdi_pathinfo_t *pip = NULL; 12674 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12675 char *nname = NULL; 12676 char **compatible = NULL; 12677 int ncompatible; 12678 char *scsi_binding_set; 12679 char t_pwwn[17]; 12680 12681 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12682 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12683 12684 scsi_binding_set = "vhci"; 12685 12686 /* determine the node name and compatible */ 12687 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12688 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12689 12690 if (nname == NULL) { 12691 #ifdef DEBUG 12692 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12693 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12694 " compatible: %s", 12695 ddi_driver_name(pdip), ddi_get_instance(pdip), 12696 ptgt->tgt_port_wwn.raw_wwn[0], 12697 ptgt->tgt_port_wwn.raw_wwn[1], 12698 ptgt->tgt_port_wwn.raw_wwn[2], 12699 ptgt->tgt_port_wwn.raw_wwn[3], 12700 ptgt->tgt_port_wwn.raw_wwn[4], 12701 ptgt->tgt_port_wwn.raw_wwn[5], 12702 ptgt->tgt_port_wwn.raw_wwn[6], 12703 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12704 *compatible); 12705 #endif /* DEBUG */ 12706 failure++; 12707 goto end_of_fcp_create_pip; 12708 } 12709 12710 pip = fcp_find_existing_pip(plun, pdip); 12711 12712 /* 12713 * if the old_dip does not match the cdip, that means there is 12714 * some property change. since we'll be using the cdip, we need 12715 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12716 * then the dtype for the device has been updated. Offline the 12717 * the old device and create a new device with the new device type 12718 * Refer to bug: 4764752 12719 */ 12720 if (old_pip && (pip != old_pip || 12721 plun->lun_state & FCP_LUN_CHANGED)) { 12722 plun->lun_state &= ~(FCP_LUN_INIT); 12723 mutex_exit(&plun->lun_mutex); 12724 mutex_exit(&pptr->port_mutex); 12725 12726 mutex_enter(&ptgt->tgt_mutex); 12727 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12728 FCP_OFFLINE, lcount, tcount, 12729 NDI_DEVI_REMOVE, 0); 12730 mutex_exit(&ptgt->tgt_mutex); 12731 12732 if (pip != NULL) { 12733 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12734 fcp_trace, FCP_BUF_LEVEL_2, 0, 12735 "Old pip=%p; New pip=%p don't match", 12736 old_pip, pip); 12737 } else { 12738 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12739 fcp_trace, FCP_BUF_LEVEL_2, 0, 12740 "Old pip=%p; New pip=NULL don't match", 12741 old_pip); 12742 } 12743 12744 mutex_enter(&pptr->port_mutex); 12745 mutex_enter(&plun->lun_mutex); 12746 } 12747 12748 /* 12749 * Since FC_WWN_SIZE is 8 bytes and its not like the 12750 * lun_guid_size which is dependent on the target, I don't 12751 * believe the same trancation happens here UNLESS the standards 12752 * change the FC_WWN_SIZE value to something larger than 12753 * MAXNAMELEN(currently 255 bytes). 12754 */ 12755 12756 for (i = 0; i < FC_WWN_SIZE; i++) { 12757 (void) sprintf(&buf[i << 1], "%02x", 12758 ptgt->tgt_port_wwn.raw_wwn[i]); 12759 } 12760 12761 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12762 buf, plun->lun_num); 12763 12764 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12765 /* 12766 * Release the locks before calling into 12767 * mdi_pi_alloc_compatible() since this can result in a 12768 * callback into fcp which can result in a deadlock 12769 * (see bug # 4870272). 12770 * 12771 * Basically, what we are trying to avoid is the scenario where 12772 * one thread does ndi_devi_enter() and tries to grab 12773 * fcp_mutex and another does it the other way round. 12774 * 12775 * But before we do that, make sure that nobody releases the 12776 * port in the meantime. We can do this by setting a flag. 12777 */ 12778 plun->lun_state &= ~(FCP_LUN_CHANGED); 12779 pptr->port_state |= FCP_STATE_IN_MDI; 12780 mutex_exit(&plun->lun_mutex); 12781 mutex_exit(&pptr->port_mutex); 12782 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12783 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12784 fcp_log(CE_WARN, pptr->port_dip, 12785 "!path alloc failed:0x%x", plun); 12786 mutex_enter(&pptr->port_mutex); 12787 mutex_enter(&plun->lun_mutex); 12788 pptr->port_state &= ~FCP_STATE_IN_MDI; 12789 failure++; 12790 goto end_of_fcp_create_pip; 12791 } 12792 mutex_enter(&pptr->port_mutex); 12793 mutex_enter(&plun->lun_mutex); 12794 pptr->port_state &= ~FCP_STATE_IN_MDI; 12795 } else { 12796 (void) mdi_prop_remove(pip, NULL); 12797 } 12798 12799 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12800 12801 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12802 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12803 != DDI_PROP_SUCCESS) { 12804 failure++; 12805 goto end_of_fcp_create_pip; 12806 } 12807 12808 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12809 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12810 != DDI_PROP_SUCCESS) { 12811 failure++; 12812 goto end_of_fcp_create_pip; 12813 } 12814 12815 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12816 t_pwwn[16] = '\0'; 12817 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12818 != DDI_PROP_SUCCESS) { 12819 failure++; 12820 goto end_of_fcp_create_pip; 12821 } 12822 12823 /* 12824 * If there is no hard address - We might have to deal with 12825 * that by using WWN - Having said that it is important to 12826 * recognize this problem early so ssd can be informed of 12827 * the right interconnect type. 12828 */ 12829 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12830 ptgt->tgt_hard_addr != 0) { 12831 tgt_id = (uint32_t) 12832 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12833 } else { 12834 tgt_id = ptgt->tgt_d_id; 12835 } 12836 12837 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12838 != DDI_PROP_SUCCESS) { 12839 failure++; 12840 goto end_of_fcp_create_pip; 12841 } 12842 12843 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12844 != DDI_PROP_SUCCESS) { 12845 failure++; 12846 goto end_of_fcp_create_pip; 12847 } 12848 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12849 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12850 != DDI_PROP_SUCCESS) { 12851 failure++; 12852 goto end_of_fcp_create_pip; 12853 } 12854 12855 end_of_fcp_create_pip: 12856 scsi_hba_nodename_compatible_free(nname, compatible); 12857 12858 if (pip != NULL && failure) { 12859 (void) mdi_prop_remove(pip, NULL); 12860 mutex_exit(&plun->lun_mutex); 12861 mutex_exit(&pptr->port_mutex); 12862 (void) mdi_pi_free(pip, 0); 12863 mutex_enter(&pptr->port_mutex); 12864 mutex_enter(&plun->lun_mutex); 12865 pip = NULL; 12866 } 12867 12868 return (pip); 12869 } 12870 12871 static dev_info_t * 12872 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12873 { 12874 uint_t nbytes; 12875 uchar_t *bytes; 12876 uint_t nwords; 12877 uint32_t tgt_id; 12878 int *words; 12879 dev_info_t *cdip; 12880 dev_info_t *ndip; 12881 struct fcp_tgt *ptgt = plun->lun_tgt; 12882 struct fcp_port *pptr = ptgt->tgt_port; 12883 int circular; 12884 12885 ndi_devi_enter(pdip, &circular); 12886 12887 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12888 while ((cdip = ndip) != NULL) { 12889 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12890 12891 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12892 continue; 12893 } 12894 12895 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12896 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12897 &nbytes) != DDI_PROP_SUCCESS) { 12898 continue; 12899 } 12900 12901 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12902 if (bytes != NULL) { 12903 ddi_prop_free(bytes); 12904 } 12905 continue; 12906 } 12907 ASSERT(bytes != NULL); 12908 12909 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12910 ddi_prop_free(bytes); 12911 continue; 12912 } 12913 12914 ddi_prop_free(bytes); 12915 12916 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12917 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12918 &nbytes) != DDI_PROP_SUCCESS) { 12919 continue; 12920 } 12921 12922 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12923 if (bytes != NULL) { 12924 ddi_prop_free(bytes); 12925 } 12926 continue; 12927 } 12928 ASSERT(bytes != NULL); 12929 12930 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12931 ddi_prop_free(bytes); 12932 continue; 12933 } 12934 12935 ddi_prop_free(bytes); 12936 12937 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12938 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12939 &nwords) != DDI_PROP_SUCCESS) { 12940 continue; 12941 } 12942 12943 if (nwords != 1 || words == NULL) { 12944 if (words != NULL) { 12945 ddi_prop_free(words); 12946 } 12947 continue; 12948 } 12949 ASSERT(words != NULL); 12950 12951 /* 12952 * If there is no hard address - We might have to deal with 12953 * that by using WWN - Having said that it is important to 12954 * recognize this problem early so ssd can be informed of 12955 * the right interconnect type. 12956 */ 12957 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12958 ptgt->tgt_hard_addr != 0) { 12959 tgt_id = 12960 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12961 } else { 12962 tgt_id = ptgt->tgt_d_id; 12963 } 12964 12965 if (tgt_id != (uint32_t)*words) { 12966 ddi_prop_free(words); 12967 continue; 12968 } 12969 ddi_prop_free(words); 12970 12971 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12972 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12973 &nwords) != DDI_PROP_SUCCESS) { 12974 continue; 12975 } 12976 12977 if (nwords != 1 || words == NULL) { 12978 if (words != NULL) { 12979 ddi_prop_free(words); 12980 } 12981 continue; 12982 } 12983 ASSERT(words != NULL); 12984 12985 if (plun->lun_num == (uint16_t)*words) { 12986 ddi_prop_free(words); 12987 break; 12988 } 12989 ddi_prop_free(words); 12990 } 12991 ndi_devi_exit(pdip, circular); 12992 12993 return (cdip); 12994 } 12995 12996 12997 static int 12998 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 12999 { 13000 dev_info_t *pdip; 13001 char buf[MAXNAMELEN]; 13002 char uaddr[MAXNAMELEN]; 13003 int rval = FC_FAILURE; 13004 13005 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13006 13007 pdip = plun->lun_tgt->tgt_port->port_dip; 13008 13009 /* 13010 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13011 * non-NULL even when the LUN is not there as in the case when a LUN is 13012 * configured and then deleted on the device end (for T3/T4 case). In 13013 * such cases, pip will be NULL. 13014 * 13015 * If the device generates an RSCN, it will end up getting offlined when 13016 * it disappeared and a new LUN will get created when it is rediscovered 13017 * on the device. If we check for lun_cip here, the LUN will not end 13018 * up getting onlined since this function will end up returning a 13019 * FC_SUCCESS. 13020 * 13021 * The behavior is different on other devices. For instance, on a HDS, 13022 * there was no RSCN generated by the device but the next I/O generated 13023 * a check condition and rediscovery got triggered that way. So, in 13024 * such cases, this path will not be exercised 13025 */ 13026 if (pip == NULL) { 13027 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13028 fcp_trace, FCP_BUF_LEVEL_4, 0, 13029 "fcp_is_pip_present: plun->lun_cip is NULL: " 13030 "plun: %p lun state: %x num: %d target state: %x", 13031 plun, plun->lun_state, plun->lun_num, 13032 plun->lun_tgt->tgt_port->port_state); 13033 return (rval); 13034 } 13035 13036 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13037 13038 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13039 13040 if (mdi_pi_find(pdip, NULL, uaddr) == pip) { 13041 rval = FC_SUCCESS; 13042 } 13043 13044 return (rval); 13045 } 13046 13047 static mdi_pathinfo_t * 13048 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13049 { 13050 char buf[MAXNAMELEN]; 13051 char uaddr[MAXNAMELEN]; 13052 mdi_pathinfo_t *pip; 13053 struct fcp_tgt *ptgt = plun->lun_tgt; 13054 struct fcp_port *pptr = ptgt->tgt_port; 13055 13056 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13057 13058 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13059 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13060 13061 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13062 13063 return (pip); 13064 } 13065 13066 13067 static int 13068 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13069 int tcount, int flags, int *circ) 13070 { 13071 int rval; 13072 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13073 struct fcp_tgt *ptgt = plun->lun_tgt; 13074 dev_info_t *cdip = NULL; 13075 13076 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13077 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13078 13079 if (plun->lun_cip == NULL) { 13080 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13081 fcp_trace, FCP_BUF_LEVEL_3, 0, 13082 "fcp_online_child: plun->lun_cip is NULL: " 13083 "plun: %p state: %x num: %d target state: %x", 13084 plun, plun->lun_state, plun->lun_num, 13085 plun->lun_tgt->tgt_port->port_state); 13086 return (NDI_FAILURE); 13087 } 13088 again: 13089 if (plun->lun_mpxio == 0) { 13090 cdip = DIP(cip); 13091 mutex_exit(&plun->lun_mutex); 13092 mutex_exit(&pptr->port_mutex); 13093 13094 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13095 fcp_trace, FCP_BUF_LEVEL_3, 0, 13096 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13097 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13098 13099 /* 13100 * We could check for FCP_LUN_INIT here but chances 13101 * of getting here when it's already in FCP_LUN_INIT 13102 * is rare and a duplicate ndi_devi_online wouldn't 13103 * hurt either (as the node would already have been 13104 * in CF2) 13105 */ 13106 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13107 rval = ndi_devi_bind_driver(cdip, flags); 13108 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13109 fcp_trace, FCP_BUF_LEVEL_3, 0, 13110 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13111 } else { 13112 rval = ndi_devi_online(cdip, flags); 13113 } 13114 13115 /* 13116 * We log the message into trace buffer if the device 13117 * is "ses" and into syslog for any other device 13118 * type. This is to prevent the ndi_devi_online failure 13119 * message that appears for V880/A5K ses devices. 13120 */ 13121 if (rval == NDI_SUCCESS) { 13122 mutex_enter(&ptgt->tgt_mutex); 13123 plun->lun_state |= FCP_LUN_INIT; 13124 mutex_exit(&ptgt->tgt_mutex); 13125 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13126 fcp_log(CE_NOTE, pptr->port_dip, 13127 "!ndi_devi_online:" 13128 " failed for %s: target=%x lun=%x %x", 13129 ddi_get_name(cdip), ptgt->tgt_d_id, 13130 plun->lun_num, rval); 13131 } else { 13132 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13133 fcp_trace, FCP_BUF_LEVEL_3, 0, 13134 " !ndi_devi_online:" 13135 " failed for %s: target=%x lun=%x %x", 13136 ddi_get_name(cdip), ptgt->tgt_d_id, 13137 plun->lun_num, rval); 13138 } 13139 } else { 13140 cdip = mdi_pi_get_client(PIP(cip)); 13141 mutex_exit(&plun->lun_mutex); 13142 mutex_exit(&pptr->port_mutex); 13143 13144 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13145 fcp_trace, FCP_BUF_LEVEL_3, 0, 13146 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13147 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13148 13149 /* 13150 * Hold path and exit phci to avoid deadlock with power 13151 * management code during mdi_pi_online. 13152 */ 13153 mdi_hold_path(PIP(cip)); 13154 mdi_devi_exit_phci(pptr->port_dip, *circ); 13155 13156 rval = mdi_pi_online(PIP(cip), flags); 13157 13158 mdi_devi_enter_phci(pptr->port_dip, circ); 13159 mdi_rele_path(PIP(cip)); 13160 13161 if (rval == MDI_SUCCESS) { 13162 mutex_enter(&ptgt->tgt_mutex); 13163 plun->lun_state |= FCP_LUN_INIT; 13164 mutex_exit(&ptgt->tgt_mutex); 13165 13166 /* 13167 * Clear MPxIO path permanent disable in case 13168 * fcp hotplug dropped the offline event. 13169 */ 13170 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13171 13172 } else if (rval == MDI_NOT_SUPPORTED) { 13173 child_info_t *old_cip = cip; 13174 13175 /* 13176 * MPxIO does not support this device yet. 13177 * Enumerate in legacy mode. 13178 */ 13179 mutex_enter(&pptr->port_mutex); 13180 mutex_enter(&plun->lun_mutex); 13181 plun->lun_mpxio = 0; 13182 plun->lun_cip = NULL; 13183 cdip = fcp_create_dip(plun, lcount, tcount); 13184 plun->lun_cip = cip = CIP(cdip); 13185 if (cip == NULL) { 13186 fcp_log(CE_WARN, pptr->port_dip, 13187 "!fcp_online_child: " 13188 "Create devinfo failed for LU=%p", plun); 13189 mutex_exit(&plun->lun_mutex); 13190 13191 mutex_enter(&ptgt->tgt_mutex); 13192 plun->lun_state |= FCP_LUN_OFFLINE; 13193 mutex_exit(&ptgt->tgt_mutex); 13194 13195 mutex_exit(&pptr->port_mutex); 13196 13197 /* 13198 * free the mdi_pathinfo node 13199 */ 13200 (void) mdi_pi_free(PIP(old_cip), 0); 13201 } else { 13202 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13203 fcp_trace, FCP_BUF_LEVEL_3, 0, 13204 "fcp_online_child: creating devinfo " 13205 "node 0x%p for plun 0x%p", 13206 cip, plun); 13207 mutex_exit(&plun->lun_mutex); 13208 mutex_exit(&pptr->port_mutex); 13209 /* 13210 * free the mdi_pathinfo node 13211 */ 13212 (void) mdi_pi_free(PIP(old_cip), 0); 13213 mutex_enter(&pptr->port_mutex); 13214 mutex_enter(&plun->lun_mutex); 13215 goto again; 13216 } 13217 } else { 13218 if (cdip) { 13219 fcp_log(CE_NOTE, pptr->port_dip, 13220 "!fcp_online_child: mdi_pi_online:" 13221 " failed for %s: target=%x lun=%x %x", 13222 ddi_get_name(cdip), ptgt->tgt_d_id, 13223 plun->lun_num, rval); 13224 } 13225 } 13226 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13227 } 13228 13229 if (rval == NDI_SUCCESS) { 13230 if (cdip) { 13231 (void) ndi_event_retrieve_cookie( 13232 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13233 &fcp_insert_eid, NDI_EVENT_NOPASS); 13234 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13235 cdip, fcp_insert_eid, NULL); 13236 } 13237 } 13238 mutex_enter(&pptr->port_mutex); 13239 mutex_enter(&plun->lun_mutex); 13240 return (rval); 13241 } 13242 13243 /* ARGSUSED */ 13244 static int 13245 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13246 int tcount, int flags, int *circ) 13247 { 13248 int rval; 13249 int lun_mpxio; 13250 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13251 struct fcp_tgt *ptgt = plun->lun_tgt; 13252 dev_info_t *cdip; 13253 13254 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13255 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13256 13257 if (plun->lun_cip == NULL) { 13258 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13259 fcp_trace, FCP_BUF_LEVEL_3, 0, 13260 "fcp_offline_child: plun->lun_cip is NULL: " 13261 "plun: %p lun state: %x num: %d target state: %x", 13262 plun, plun->lun_state, plun->lun_num, 13263 plun->lun_tgt->tgt_port->port_state); 13264 return (NDI_FAILURE); 13265 } 13266 13267 /* 13268 * We will use this value twice. Make a copy to be sure we use 13269 * the same value in both places. 13270 */ 13271 lun_mpxio = plun->lun_mpxio; 13272 13273 if (lun_mpxio == 0) { 13274 cdip = DIP(cip); 13275 mutex_exit(&plun->lun_mutex); 13276 mutex_exit(&pptr->port_mutex); 13277 rval = ndi_devi_offline(DIP(cip), NDI_DEVFS_CLEAN | flags); 13278 if (rval != NDI_SUCCESS) { 13279 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13280 fcp_trace, FCP_BUF_LEVEL_3, 0, 13281 "fcp_offline_child: ndi_devi_offline failed " 13282 "rval=%x cip=%p", rval, cip); 13283 } 13284 } else { 13285 cdip = mdi_pi_get_client(PIP(cip)); 13286 mutex_exit(&plun->lun_mutex); 13287 mutex_exit(&pptr->port_mutex); 13288 13289 /* 13290 * Exit phci to avoid deadlock with power management code 13291 * during mdi_pi_offline 13292 */ 13293 mdi_hold_path(PIP(cip)); 13294 mdi_devi_exit_phci(pptr->port_dip, *circ); 13295 13296 rval = mdi_pi_offline(PIP(cip), flags & ~NDI_DEVI_REMOVE); 13297 13298 mdi_devi_enter_phci(pptr->port_dip, circ); 13299 mdi_rele_path(PIP(cip)); 13300 13301 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13302 } 13303 13304 mutex_enter(&ptgt->tgt_mutex); 13305 plun->lun_state &= ~FCP_LUN_INIT; 13306 mutex_exit(&ptgt->tgt_mutex); 13307 13308 if (rval == NDI_SUCCESS) { 13309 cdip = NULL; 13310 if (flags & NDI_DEVI_REMOVE) { 13311 mutex_enter(&plun->lun_mutex); 13312 /* 13313 * If the guid of the LUN changes, lun_cip will not 13314 * equal to cip, and after offlining the LUN with the 13315 * old guid, we should keep lun_cip since it's the cip 13316 * of the LUN with the new guid. 13317 * Otherwise remove our reference to child node. 13318 * 13319 * This must be done before the child node is freed, 13320 * otherwise other threads could see a stale lun_cip 13321 * pointer. 13322 */ 13323 if (plun->lun_cip == cip) { 13324 plun->lun_cip = NULL; 13325 } 13326 if (plun->lun_old_guid) { 13327 kmem_free(plun->lun_old_guid, 13328 plun->lun_old_guid_size); 13329 plun->lun_old_guid = NULL; 13330 plun->lun_old_guid_size = 0; 13331 } 13332 mutex_exit(&plun->lun_mutex); 13333 } 13334 } 13335 13336 if (lun_mpxio != 0) { 13337 if (rval == NDI_SUCCESS) { 13338 /* 13339 * Clear MPxIO path permanent disable as the path is 13340 * already offlined. 13341 */ 13342 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13343 13344 if (flags & NDI_DEVI_REMOVE) { 13345 (void) mdi_pi_free(PIP(cip), 0); 13346 } 13347 } else { 13348 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13349 fcp_trace, FCP_BUF_LEVEL_3, 0, 13350 "fcp_offline_child: mdi_pi_offline failed " 13351 "rval=%x cip=%p", rval, cip); 13352 } 13353 } 13354 13355 mutex_enter(&pptr->port_mutex); 13356 mutex_enter(&plun->lun_mutex); 13357 13358 if (cdip) { 13359 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13360 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13361 " target=%x lun=%x", "ndi_offline", 13362 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13363 } 13364 13365 return (rval); 13366 } 13367 13368 static void 13369 fcp_remove_child(struct fcp_lun *plun) 13370 { 13371 child_info_t *cip; 13372 int circ; 13373 13374 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13375 13376 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13377 if (plun->lun_mpxio == 0) { 13378 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13379 (void) ndi_devi_free(DIP(plun->lun_cip)); 13380 plun->lun_cip = NULL; 13381 } else { 13382 /* 13383 * Clear reference to the child node in the lun. 13384 * This must be done before freeing it with mdi_pi_free 13385 * and with lun_mutex held so that other threads always 13386 * see either valid lun_cip or NULL when holding 13387 * lun_mutex. We keep a copy in cip. 13388 */ 13389 cip = plun->lun_cip; 13390 plun->lun_cip = NULL; 13391 13392 mutex_exit(&plun->lun_mutex); 13393 mutex_exit(&plun->lun_tgt->tgt_mutex); 13394 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13395 13396 mdi_devi_enter(plun->lun_tgt->tgt_port->port_dip, 13397 &circ); 13398 13399 /* 13400 * Exit phci to avoid deadlock with power management 13401 * code during mdi_pi_offline 13402 */ 13403 mdi_hold_path(PIP(cip)); 13404 mdi_devi_exit_phci(plun->lun_tgt->tgt_port->port_dip, 13405 circ); 13406 (void) mdi_pi_offline(PIP(cip), 0); 13407 mdi_devi_enter_phci(plun->lun_tgt->tgt_port->port_dip, 13408 &circ); 13409 mdi_rele_path(PIP(cip)); 13410 13411 mdi_devi_exit(plun->lun_tgt->tgt_port->port_dip, circ); 13412 13413 FCP_TRACE(fcp_logq, 13414 plun->lun_tgt->tgt_port->port_instbuf, 13415 fcp_trace, FCP_BUF_LEVEL_3, 0, 13416 "lun=%p pip freed %p", plun, cip); 13417 13418 (void) mdi_prop_remove(PIP(cip), NULL); 13419 (void) mdi_pi_free(PIP(cip), 0); 13420 13421 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13422 mutex_enter(&plun->lun_tgt->tgt_mutex); 13423 mutex_enter(&plun->lun_mutex); 13424 } 13425 } else { 13426 plun->lun_cip = NULL; 13427 } 13428 } 13429 13430 /* 13431 * called when a timeout occurs 13432 * 13433 * can be scheduled during an attach or resume (if not already running) 13434 * 13435 * one timeout is set up for all ports 13436 * 13437 * acquires and releases the global mutex 13438 */ 13439 /*ARGSUSED*/ 13440 static void 13441 fcp_watch(void *arg) 13442 { 13443 struct fcp_port *pptr; 13444 struct fcp_ipkt *icmd; 13445 struct fcp_ipkt *nicmd; 13446 struct fcp_pkt *cmd; 13447 struct fcp_pkt *ncmd; 13448 struct fcp_pkt *tail; 13449 struct fcp_pkt *pcmd; 13450 struct fcp_pkt *save_head; 13451 struct fcp_port *save_port; 13452 13453 /* increment global watchdog time */ 13454 fcp_watchdog_time += fcp_watchdog_timeout; 13455 13456 mutex_enter(&fcp_global_mutex); 13457 13458 /* scan each port in our list */ 13459 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13460 save_port = fcp_port_head; 13461 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13462 mutex_exit(&fcp_global_mutex); 13463 13464 mutex_enter(&pptr->port_mutex); 13465 if (pptr->port_ipkt_list == NULL && 13466 (pptr->port_state & (FCP_STATE_SUSPENDED | 13467 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13468 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13469 mutex_exit(&pptr->port_mutex); 13470 mutex_enter(&fcp_global_mutex); 13471 goto end_of_watchdog; 13472 } 13473 13474 /* 13475 * We check if a list of targets need to be offlined. 13476 */ 13477 if (pptr->port_offline_tgts) { 13478 fcp_scan_offline_tgts(pptr); 13479 } 13480 13481 /* 13482 * We check if a list of luns need to be offlined. 13483 */ 13484 if (pptr->port_offline_luns) { 13485 fcp_scan_offline_luns(pptr); 13486 } 13487 13488 /* 13489 * We check if a list of targets or luns need to be reset. 13490 */ 13491 if (pptr->port_reset_list) { 13492 fcp_check_reset_delay(pptr); 13493 } 13494 13495 mutex_exit(&pptr->port_mutex); 13496 13497 /* 13498 * This is where the pending commands (pkt) are checked for 13499 * timeout. 13500 */ 13501 mutex_enter(&pptr->port_pkt_mutex); 13502 tail = pptr->port_pkt_tail; 13503 13504 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13505 cmd != NULL; cmd = ncmd) { 13506 ncmd = cmd->cmd_next; 13507 /* 13508 * If a command is in this queue the bit CFLAG_IN_QUEUE 13509 * must be set. 13510 */ 13511 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13512 /* 13513 * FCP_INVALID_TIMEOUT will be set for those 13514 * command that need to be failed. Mostly those 13515 * cmds that could not be queued down for the 13516 * "timeout" value. cmd->cmd_timeout is used 13517 * to try and requeue the command regularly. 13518 */ 13519 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13520 /* 13521 * This command hasn't timed out yet. Let's 13522 * go to the next one. 13523 */ 13524 pcmd = cmd; 13525 goto end_of_loop; 13526 } 13527 13528 if (cmd == pptr->port_pkt_head) { 13529 ASSERT(pcmd == NULL); 13530 pptr->port_pkt_head = cmd->cmd_next; 13531 } else { 13532 ASSERT(pcmd != NULL); 13533 pcmd->cmd_next = cmd->cmd_next; 13534 } 13535 13536 if (cmd == pptr->port_pkt_tail) { 13537 ASSERT(cmd->cmd_next == NULL); 13538 pptr->port_pkt_tail = pcmd; 13539 if (pcmd) { 13540 pcmd->cmd_next = NULL; 13541 } 13542 } 13543 cmd->cmd_next = NULL; 13544 13545 /* 13546 * save the current head before dropping the 13547 * mutex - If the head doesn't remain the 13548 * same after re acquiring the mutex, just 13549 * bail out and revisit on next tick. 13550 * 13551 * PS: The tail pointer can change as the commands 13552 * get requeued after failure to retransport 13553 */ 13554 save_head = pptr->port_pkt_head; 13555 mutex_exit(&pptr->port_pkt_mutex); 13556 13557 if (cmd->cmd_fp_pkt->pkt_timeout == 13558 FCP_INVALID_TIMEOUT) { 13559 struct scsi_pkt *pkt = cmd->cmd_pkt; 13560 struct fcp_lun *plun; 13561 struct fcp_tgt *ptgt; 13562 13563 plun = ADDR2LUN(&pkt->pkt_address); 13564 ptgt = plun->lun_tgt; 13565 13566 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13567 fcp_trace, FCP_BUF_LEVEL_2, 0, 13568 "SCSI cmd 0x%x to D_ID=%x timed out", 13569 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13570 13571 cmd->cmd_state == FCP_PKT_ABORTING ? 13572 fcp_fail_cmd(cmd, CMD_RESET, 13573 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13574 CMD_TIMEOUT, STAT_ABORTED); 13575 } else { 13576 fcp_retransport_cmd(pptr, cmd); 13577 } 13578 mutex_enter(&pptr->port_pkt_mutex); 13579 if (save_head && save_head != pptr->port_pkt_head) { 13580 /* 13581 * Looks like linked list got changed (mostly 13582 * happens when an an OFFLINE LUN code starts 13583 * returning overflow queue commands in 13584 * parallel. So bail out and revisit during 13585 * next tick 13586 */ 13587 break; 13588 } 13589 end_of_loop: 13590 /* 13591 * Scan only upto the previously known tail pointer 13592 * to avoid excessive processing - lots of new packets 13593 * could have been added to the tail or the old ones 13594 * re-queued. 13595 */ 13596 if (cmd == tail) { 13597 break; 13598 } 13599 } 13600 mutex_exit(&pptr->port_pkt_mutex); 13601 13602 mutex_enter(&pptr->port_mutex); 13603 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13604 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13605 13606 nicmd = icmd->ipkt_next; 13607 if ((icmd->ipkt_restart != 0) && 13608 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13609 /* packet has not timed out */ 13610 continue; 13611 } 13612 13613 /* time for packet re-transport */ 13614 if (icmd == pptr->port_ipkt_list) { 13615 pptr->port_ipkt_list = icmd->ipkt_next; 13616 if (pptr->port_ipkt_list) { 13617 pptr->port_ipkt_list->ipkt_prev = 13618 NULL; 13619 } 13620 } else { 13621 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13622 if (icmd->ipkt_next) { 13623 icmd->ipkt_next->ipkt_prev = 13624 icmd->ipkt_prev; 13625 } 13626 } 13627 icmd->ipkt_next = NULL; 13628 icmd->ipkt_prev = NULL; 13629 mutex_exit(&pptr->port_mutex); 13630 13631 if (fcp_is_retryable(icmd)) { 13632 fc_ulp_rscn_info_t *rscnp = 13633 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13634 pkt_ulp_rscn_infop; 13635 13636 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13637 fcp_trace, FCP_BUF_LEVEL_2, 0, 13638 "%x to D_ID=%x Retrying..", 13639 icmd->ipkt_opcode, 13640 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13641 13642 /* 13643 * Update the RSCN count in the packet 13644 * before resending. 13645 */ 13646 13647 if (rscnp != NULL) { 13648 rscnp->ulp_rscn_count = 13649 fc_ulp_get_rscn_count(pptr-> 13650 port_fp_handle); 13651 } 13652 13653 mutex_enter(&pptr->port_mutex); 13654 mutex_enter(&ptgt->tgt_mutex); 13655 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13656 mutex_exit(&ptgt->tgt_mutex); 13657 mutex_exit(&pptr->port_mutex); 13658 switch (icmd->ipkt_opcode) { 13659 int rval; 13660 case LA_ELS_PLOGI: 13661 if ((rval = fc_ulp_login( 13662 pptr->port_fp_handle, 13663 &icmd->ipkt_fpkt, 1)) == 13664 FC_SUCCESS) { 13665 mutex_enter( 13666 &pptr->port_mutex); 13667 continue; 13668 } 13669 if (fcp_handle_ipkt_errors( 13670 pptr, ptgt, icmd, rval, 13671 "PLOGI") == DDI_SUCCESS) { 13672 mutex_enter( 13673 &pptr->port_mutex); 13674 continue; 13675 } 13676 break; 13677 13678 case LA_ELS_PRLI: 13679 if ((rval = fc_ulp_issue_els( 13680 pptr->port_fp_handle, 13681 icmd->ipkt_fpkt)) == 13682 FC_SUCCESS) { 13683 mutex_enter( 13684 &pptr->port_mutex); 13685 continue; 13686 } 13687 if (fcp_handle_ipkt_errors( 13688 pptr, ptgt, icmd, rval, 13689 "PRLI") == DDI_SUCCESS) { 13690 mutex_enter( 13691 &pptr->port_mutex); 13692 continue; 13693 } 13694 break; 13695 13696 default: 13697 if ((rval = fcp_transport( 13698 pptr->port_fp_handle, 13699 icmd->ipkt_fpkt, 1)) == 13700 FC_SUCCESS) { 13701 mutex_enter( 13702 &pptr->port_mutex); 13703 continue; 13704 } 13705 if (fcp_handle_ipkt_errors( 13706 pptr, ptgt, icmd, rval, 13707 "PRLI") == DDI_SUCCESS) { 13708 mutex_enter( 13709 &pptr->port_mutex); 13710 continue; 13711 } 13712 break; 13713 } 13714 } else { 13715 mutex_exit(&ptgt->tgt_mutex); 13716 mutex_exit(&pptr->port_mutex); 13717 } 13718 } else { 13719 fcp_print_error(icmd->ipkt_fpkt); 13720 } 13721 13722 (void) fcp_call_finish_init(pptr, ptgt, 13723 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13724 icmd->ipkt_cause); 13725 fcp_icmd_free(pptr, icmd); 13726 mutex_enter(&pptr->port_mutex); 13727 } 13728 13729 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13730 mutex_exit(&pptr->port_mutex); 13731 mutex_enter(&fcp_global_mutex); 13732 13733 end_of_watchdog: 13734 /* 13735 * Bail out early before getting into trouble 13736 */ 13737 if (save_port != fcp_port_head) { 13738 break; 13739 } 13740 } 13741 13742 if (fcp_watchdog_init > 0) { 13743 /* reschedule timeout to go again */ 13744 fcp_watchdog_id = 13745 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13746 } 13747 mutex_exit(&fcp_global_mutex); 13748 } 13749 13750 13751 static void 13752 fcp_check_reset_delay(struct fcp_port *pptr) 13753 { 13754 uint32_t tgt_cnt; 13755 int level; 13756 struct fcp_tgt *ptgt; 13757 struct fcp_lun *plun; 13758 struct fcp_reset_elem *cur = NULL; 13759 struct fcp_reset_elem *next = NULL; 13760 struct fcp_reset_elem *prev = NULL; 13761 13762 ASSERT(mutex_owned(&pptr->port_mutex)); 13763 13764 next = pptr->port_reset_list; 13765 while ((cur = next) != NULL) { 13766 next = cur->next; 13767 13768 if (cur->timeout < fcp_watchdog_time) { 13769 prev = cur; 13770 continue; 13771 } 13772 13773 ptgt = cur->tgt; 13774 plun = cur->lun; 13775 tgt_cnt = cur->tgt_cnt; 13776 13777 if (ptgt) { 13778 level = RESET_TARGET; 13779 } else { 13780 ASSERT(plun != NULL); 13781 level = RESET_LUN; 13782 ptgt = plun->lun_tgt; 13783 } 13784 if (prev) { 13785 prev->next = next; 13786 } else { 13787 /* 13788 * Because we drop port mutex while doing aborts for 13789 * packets, we can't rely on reset_list pointing to 13790 * our head 13791 */ 13792 if (cur == pptr->port_reset_list) { 13793 pptr->port_reset_list = next; 13794 } else { 13795 struct fcp_reset_elem *which; 13796 13797 which = pptr->port_reset_list; 13798 while (which && which->next != cur) { 13799 which = which->next; 13800 } 13801 ASSERT(which != NULL); 13802 13803 which->next = next; 13804 prev = which; 13805 } 13806 } 13807 13808 kmem_free(cur, sizeof (*cur)); 13809 13810 if (tgt_cnt == ptgt->tgt_change_cnt) { 13811 mutex_enter(&ptgt->tgt_mutex); 13812 if (level == RESET_TARGET) { 13813 fcp_update_tgt_state(ptgt, 13814 FCP_RESET, FCP_LUN_BUSY); 13815 } else { 13816 fcp_update_lun_state(plun, 13817 FCP_RESET, FCP_LUN_BUSY); 13818 } 13819 mutex_exit(&ptgt->tgt_mutex); 13820 13821 mutex_exit(&pptr->port_mutex); 13822 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13823 mutex_enter(&pptr->port_mutex); 13824 } 13825 } 13826 } 13827 13828 13829 static void 13830 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13831 struct fcp_lun *rlun, int tgt_cnt) 13832 { 13833 int rval; 13834 struct fcp_lun *tlun, *nlun; 13835 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13836 *cmd = NULL, *head = NULL, 13837 *tail = NULL; 13838 13839 mutex_enter(&pptr->port_pkt_mutex); 13840 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13841 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13842 struct fcp_tgt *ptgt = plun->lun_tgt; 13843 13844 ncmd = cmd->cmd_next; 13845 13846 if (ptgt != ttgt && plun != rlun) { 13847 pcmd = cmd; 13848 continue; 13849 } 13850 13851 if (pcmd != NULL) { 13852 ASSERT(pptr->port_pkt_head != cmd); 13853 pcmd->cmd_next = ncmd; 13854 } else { 13855 ASSERT(cmd == pptr->port_pkt_head); 13856 pptr->port_pkt_head = ncmd; 13857 } 13858 if (pptr->port_pkt_tail == cmd) { 13859 ASSERT(cmd->cmd_next == NULL); 13860 pptr->port_pkt_tail = pcmd; 13861 if (pcmd != NULL) { 13862 pcmd->cmd_next = NULL; 13863 } 13864 } 13865 13866 if (head == NULL) { 13867 head = tail = cmd; 13868 } else { 13869 ASSERT(tail != NULL); 13870 tail->cmd_next = cmd; 13871 tail = cmd; 13872 } 13873 cmd->cmd_next = NULL; 13874 } 13875 mutex_exit(&pptr->port_pkt_mutex); 13876 13877 for (cmd = head; cmd != NULL; cmd = ncmd) { 13878 struct scsi_pkt *pkt = cmd->cmd_pkt; 13879 13880 ncmd = cmd->cmd_next; 13881 ASSERT(pkt != NULL); 13882 13883 mutex_enter(&pptr->port_mutex); 13884 if (ttgt->tgt_change_cnt == tgt_cnt) { 13885 mutex_exit(&pptr->port_mutex); 13886 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13887 pkt->pkt_reason = CMD_RESET; 13888 pkt->pkt_statistics |= STAT_DEV_RESET; 13889 cmd->cmd_state = FCP_PKT_IDLE; 13890 fcp_post_callback(cmd); 13891 } else { 13892 mutex_exit(&pptr->port_mutex); 13893 } 13894 } 13895 13896 /* 13897 * If the FCA will return all the commands in its queue then our 13898 * work is easy, just return. 13899 */ 13900 13901 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13902 return; 13903 } 13904 13905 /* 13906 * For RESET_LUN get hold of target pointer 13907 */ 13908 if (ttgt == NULL) { 13909 ASSERT(rlun != NULL); 13910 13911 ttgt = rlun->lun_tgt; 13912 13913 ASSERT(ttgt != NULL); 13914 } 13915 13916 /* 13917 * There are some severe race conditions here. 13918 * While we are trying to abort the pkt, it might be completing 13919 * so mark it aborted and if the abort does not succeed then 13920 * handle it in the watch thread. 13921 */ 13922 mutex_enter(&ttgt->tgt_mutex); 13923 nlun = ttgt->tgt_lun; 13924 mutex_exit(&ttgt->tgt_mutex); 13925 while ((tlun = nlun) != NULL) { 13926 int restart = 0; 13927 if (rlun && rlun != tlun) { 13928 mutex_enter(&ttgt->tgt_mutex); 13929 nlun = tlun->lun_next; 13930 mutex_exit(&ttgt->tgt_mutex); 13931 continue; 13932 } 13933 mutex_enter(&tlun->lun_mutex); 13934 cmd = tlun->lun_pkt_head; 13935 while (cmd != NULL) { 13936 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13937 struct scsi_pkt *pkt; 13938 13939 restart = 1; 13940 cmd->cmd_state = FCP_PKT_ABORTING; 13941 mutex_exit(&tlun->lun_mutex); 13942 rval = fc_ulp_abort(pptr->port_fp_handle, 13943 cmd->cmd_fp_pkt, KM_SLEEP); 13944 if (rval == FC_SUCCESS) { 13945 pkt = cmd->cmd_pkt; 13946 pkt->pkt_reason = CMD_RESET; 13947 pkt->pkt_statistics |= STAT_DEV_RESET; 13948 cmd->cmd_state = FCP_PKT_IDLE; 13949 fcp_post_callback(cmd); 13950 } else { 13951 caddr_t msg; 13952 13953 (void) fc_ulp_error(rval, &msg); 13954 13955 /* 13956 * This part is tricky. The abort 13957 * failed and now the command could 13958 * be completing. The cmd_state == 13959 * FCP_PKT_ABORTING should save 13960 * us in fcp_cmd_callback. If we 13961 * are already aborting ignore the 13962 * command in fcp_cmd_callback. 13963 * Here we leave this packet for 20 13964 * sec to be aborted in the 13965 * fcp_watch thread. 13966 */ 13967 fcp_log(CE_WARN, pptr->port_dip, 13968 "!Abort failed after reset %s", 13969 msg); 13970 13971 cmd->cmd_timeout = 13972 fcp_watchdog_time + 13973 cmd->cmd_pkt->pkt_time + 13974 FCP_FAILED_DELAY; 13975 13976 cmd->cmd_fp_pkt->pkt_timeout = 13977 FCP_INVALID_TIMEOUT; 13978 /* 13979 * This is a hack, cmd is put in the 13980 * overflow queue so that it can be 13981 * timed out finally 13982 */ 13983 cmd->cmd_flags |= CFLAG_IN_QUEUE; 13984 13985 mutex_enter(&pptr->port_pkt_mutex); 13986 if (pptr->port_pkt_head) { 13987 ASSERT(pptr->port_pkt_tail 13988 != NULL); 13989 pptr->port_pkt_tail->cmd_next 13990 = cmd; 13991 pptr->port_pkt_tail = cmd; 13992 } else { 13993 ASSERT(pptr->port_pkt_tail 13994 == NULL); 13995 pptr->port_pkt_head = 13996 pptr->port_pkt_tail 13997 = cmd; 13998 } 13999 cmd->cmd_next = NULL; 14000 mutex_exit(&pptr->port_pkt_mutex); 14001 } 14002 mutex_enter(&tlun->lun_mutex); 14003 cmd = tlun->lun_pkt_head; 14004 } else { 14005 cmd = cmd->cmd_forw; 14006 } 14007 } 14008 mutex_exit(&tlun->lun_mutex); 14009 14010 mutex_enter(&ttgt->tgt_mutex); 14011 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14012 mutex_exit(&ttgt->tgt_mutex); 14013 14014 mutex_enter(&pptr->port_mutex); 14015 if (tgt_cnt != ttgt->tgt_change_cnt) { 14016 mutex_exit(&pptr->port_mutex); 14017 return; 14018 } else { 14019 mutex_exit(&pptr->port_mutex); 14020 } 14021 } 14022 } 14023 14024 14025 /* 14026 * unlink the soft state, returning the soft state found (if any) 14027 * 14028 * acquires and releases the global mutex 14029 */ 14030 struct fcp_port * 14031 fcp_soft_state_unlink(struct fcp_port *pptr) 14032 { 14033 struct fcp_port *hptr; /* ptr index */ 14034 struct fcp_port *tptr; /* prev hptr */ 14035 14036 mutex_enter(&fcp_global_mutex); 14037 for (hptr = fcp_port_head, tptr = NULL; 14038 hptr != NULL; 14039 tptr = hptr, hptr = hptr->port_next) { 14040 if (hptr == pptr) { 14041 /* we found a match -- remove this item */ 14042 if (tptr == NULL) { 14043 /* we're at the head of the list */ 14044 fcp_port_head = hptr->port_next; 14045 } else { 14046 tptr->port_next = hptr->port_next; 14047 } 14048 break; /* success */ 14049 } 14050 } 14051 if (fcp_port_head == NULL) { 14052 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14053 } 14054 mutex_exit(&fcp_global_mutex); 14055 return (hptr); 14056 } 14057 14058 14059 /* 14060 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14061 * WWN and a LUN number 14062 */ 14063 /* ARGSUSED */ 14064 static struct fcp_lun * 14065 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14066 { 14067 int hash; 14068 struct fcp_tgt *ptgt; 14069 struct fcp_lun *plun; 14070 14071 ASSERT(mutex_owned(&pptr->port_mutex)); 14072 14073 hash = FCP_HASH(wwn); 14074 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14075 ptgt = ptgt->tgt_next) { 14076 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14077 sizeof (ptgt->tgt_port_wwn)) == 0) { 14078 mutex_enter(&ptgt->tgt_mutex); 14079 for (plun = ptgt->tgt_lun; 14080 plun != NULL; 14081 plun = plun->lun_next) { 14082 if (plun->lun_num == lun) { 14083 mutex_exit(&ptgt->tgt_mutex); 14084 return (plun); 14085 } 14086 } 14087 mutex_exit(&ptgt->tgt_mutex); 14088 return (NULL); 14089 } 14090 } 14091 return (NULL); 14092 } 14093 14094 /* 14095 * Function: fcp_prepare_pkt 14096 * 14097 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14098 * for fcp_start(). It binds the data or partially maps it. 14099 * Builds the FCP header and starts the initialization of the 14100 * Fibre Channel header. 14101 * 14102 * Argument: *pptr FCP port. 14103 * *cmd FCP packet. 14104 * *plun LUN the command will be sent to. 14105 * 14106 * Context: User, Kernel and Interrupt context. 14107 */ 14108 static void 14109 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14110 struct fcp_lun *plun) 14111 { 14112 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14113 struct fcp_tgt *ptgt = plun->lun_tgt; 14114 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14115 14116 ASSERT(cmd->cmd_pkt->pkt_comp || 14117 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14118 14119 if (cmd->cmd_pkt->pkt_numcookies) { 14120 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14121 fcmd->fcp_cntl.cntl_read_data = 1; 14122 fcmd->fcp_cntl.cntl_write_data = 0; 14123 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14124 } else { 14125 fcmd->fcp_cntl.cntl_read_data = 0; 14126 fcmd->fcp_cntl.cntl_write_data = 1; 14127 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14128 } 14129 14130 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14131 14132 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14133 ASSERT(fpkt->pkt_data_cookie_cnt <= 14134 pptr->port_data_dma_attr.dma_attr_sgllen); 14135 14136 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14137 14138 /* FCA needs pkt_datalen to be set */ 14139 fpkt->pkt_datalen = cmd->cmd_dmacount; 14140 fcmd->fcp_data_len = cmd->cmd_dmacount; 14141 } else { 14142 fcmd->fcp_cntl.cntl_read_data = 0; 14143 fcmd->fcp_cntl.cntl_write_data = 0; 14144 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14145 fpkt->pkt_datalen = 0; 14146 fcmd->fcp_data_len = 0; 14147 } 14148 14149 /* set up the Tagged Queuing type */ 14150 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14151 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14152 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14153 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14154 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14155 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14156 } else { 14157 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14158 } 14159 14160 fcmd->fcp_ent_addr = plun->lun_addr; 14161 14162 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14163 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14164 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14165 } else { 14166 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14167 } 14168 14169 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14170 cmd->cmd_pkt->pkt_state = 0; 14171 cmd->cmd_pkt->pkt_statistics = 0; 14172 cmd->cmd_pkt->pkt_resid = 0; 14173 14174 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14175 14176 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14177 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14178 fpkt->pkt_comp = NULL; 14179 } else { 14180 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14181 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14182 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14183 } 14184 fpkt->pkt_comp = fcp_cmd_callback; 14185 } 14186 14187 mutex_enter(&pptr->port_mutex); 14188 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14189 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14190 } 14191 mutex_exit(&pptr->port_mutex); 14192 14193 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14194 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14195 14196 /* 14197 * Save a few kernel cycles here 14198 */ 14199 #ifndef __lock_lint 14200 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14201 #endif /* __lock_lint */ 14202 } 14203 14204 static void 14205 fcp_post_callback(struct fcp_pkt *cmd) 14206 { 14207 scsi_hba_pkt_comp(cmd->cmd_pkt); 14208 } 14209 14210 14211 /* 14212 * called to do polled I/O by fcp_start() 14213 * 14214 * return a transport status value, i.e. TRAN_ACCECPT for success 14215 */ 14216 static int 14217 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14218 { 14219 int rval; 14220 14221 #ifdef DEBUG 14222 mutex_enter(&pptr->port_pkt_mutex); 14223 pptr->port_npkts++; 14224 mutex_exit(&pptr->port_pkt_mutex); 14225 #endif /* DEBUG */ 14226 14227 if (cmd->cmd_fp_pkt->pkt_timeout) { 14228 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14229 } else { 14230 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14231 } 14232 14233 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14234 14235 cmd->cmd_state = FCP_PKT_ISSUED; 14236 14237 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14238 14239 #ifdef DEBUG 14240 mutex_enter(&pptr->port_pkt_mutex); 14241 pptr->port_npkts--; 14242 mutex_exit(&pptr->port_pkt_mutex); 14243 #endif /* DEBUG */ 14244 14245 cmd->cmd_state = FCP_PKT_IDLE; 14246 14247 switch (rval) { 14248 case FC_SUCCESS: 14249 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14250 fcp_complete_pkt(cmd->cmd_fp_pkt); 14251 rval = TRAN_ACCEPT; 14252 } else { 14253 rval = TRAN_FATAL_ERROR; 14254 } 14255 break; 14256 14257 case FC_TRAN_BUSY: 14258 rval = TRAN_BUSY; 14259 cmd->cmd_pkt->pkt_resid = 0; 14260 break; 14261 14262 case FC_BADPACKET: 14263 rval = TRAN_BADPKT; 14264 break; 14265 14266 default: 14267 rval = TRAN_FATAL_ERROR; 14268 break; 14269 } 14270 14271 return (rval); 14272 } 14273 14274 14275 /* 14276 * called by some of the following transport-called routines to convert 14277 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14278 */ 14279 static struct fcp_port * 14280 fcp_dip2port(dev_info_t *dip) 14281 { 14282 int instance; 14283 14284 instance = ddi_get_instance(dip); 14285 return (ddi_get_soft_state(fcp_softstate, instance)); 14286 } 14287 14288 14289 /* 14290 * called internally to return a LUN given a dip 14291 */ 14292 struct fcp_lun * 14293 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14294 { 14295 struct fcp_tgt *ptgt; 14296 struct fcp_lun *plun; 14297 int i; 14298 14299 14300 ASSERT(mutex_owned(&pptr->port_mutex)); 14301 14302 for (i = 0; i < FCP_NUM_HASH; i++) { 14303 for (ptgt = pptr->port_tgt_hash_table[i]; 14304 ptgt != NULL; 14305 ptgt = ptgt->tgt_next) { 14306 mutex_enter(&ptgt->tgt_mutex); 14307 for (plun = ptgt->tgt_lun; plun != NULL; 14308 plun = plun->lun_next) { 14309 mutex_enter(&plun->lun_mutex); 14310 if (plun->lun_cip == cip) { 14311 mutex_exit(&plun->lun_mutex); 14312 mutex_exit(&ptgt->tgt_mutex); 14313 return (plun); /* match found */ 14314 } 14315 mutex_exit(&plun->lun_mutex); 14316 } 14317 mutex_exit(&ptgt->tgt_mutex); 14318 } 14319 } 14320 return (NULL); /* no LUN found */ 14321 } 14322 14323 /* 14324 * pass an element to the hotplug list, kick the hotplug thread 14325 * and wait for the element to get processed by the hotplug thread. 14326 * on return the element is freed. 14327 * 14328 * return zero success and non-zero on failure 14329 * 14330 * acquires/releases the target mutex 14331 * 14332 */ 14333 static int 14334 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14335 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14336 { 14337 struct fcp_hp_elem *elem; 14338 int rval; 14339 14340 mutex_enter(&plun->lun_tgt->tgt_mutex); 14341 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14342 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14343 mutex_exit(&plun->lun_tgt->tgt_mutex); 14344 fcp_log(CE_CONT, pptr->port_dip, 14345 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14346 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14347 return (NDI_FAILURE); 14348 } 14349 mutex_exit(&plun->lun_tgt->tgt_mutex); 14350 mutex_enter(&elem->mutex); 14351 if (elem->wait) { 14352 while (elem->wait) { 14353 cv_wait(&elem->cv, &elem->mutex); 14354 } 14355 } 14356 rval = (elem->result); 14357 mutex_exit(&elem->mutex); 14358 mutex_destroy(&elem->mutex); 14359 cv_destroy(&elem->cv); 14360 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14361 return (rval); 14362 } 14363 14364 /* 14365 * pass an element to the hotplug list, and then 14366 * kick the hotplug thread 14367 * 14368 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14369 * 14370 * acquires/releases the hotplug mutex 14371 * 14372 * called with the target mutex owned 14373 * 14374 * memory acquired in NOSLEEP mode 14375 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14376 * for the hp daemon to process the request and is responsible for 14377 * freeing the element 14378 */ 14379 static struct fcp_hp_elem * 14380 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14381 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14382 { 14383 struct fcp_hp_elem *elem; 14384 dev_info_t *pdip; 14385 14386 ASSERT(pptr != NULL); 14387 ASSERT(plun != NULL); 14388 ASSERT(plun->lun_tgt != NULL); 14389 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14390 14391 /* create space for a hotplug element */ 14392 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14393 == NULL) { 14394 fcp_log(CE_WARN, NULL, 14395 "!can't allocate memory for hotplug element"); 14396 return (NULL); 14397 } 14398 14399 /* fill in hotplug element */ 14400 elem->port = pptr; 14401 elem->lun = plun; 14402 elem->cip = cip; 14403 elem->old_lun_mpxio = plun->lun_mpxio; 14404 elem->what = what; 14405 elem->flags = flags; 14406 elem->link_cnt = link_cnt; 14407 elem->tgt_cnt = tgt_cnt; 14408 elem->wait = wait; 14409 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14410 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14411 14412 /* schedule the hotplug task */ 14413 pdip = pptr->port_dip; 14414 mutex_enter(&plun->lun_mutex); 14415 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14416 plun->lun_event_count++; 14417 elem->event_cnt = plun->lun_event_count; 14418 } 14419 mutex_exit(&plun->lun_mutex); 14420 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14421 (void *)elem, KM_NOSLEEP) == NULL) { 14422 mutex_enter(&plun->lun_mutex); 14423 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14424 plun->lun_event_count--; 14425 } 14426 mutex_exit(&plun->lun_mutex); 14427 kmem_free(elem, sizeof (*elem)); 14428 return (0); 14429 } 14430 14431 return (elem); 14432 } 14433 14434 14435 static void 14436 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14437 { 14438 int rval; 14439 struct scsi_address *ap; 14440 struct fcp_lun *plun; 14441 struct fcp_tgt *ptgt; 14442 fc_packet_t *fpkt; 14443 14444 ap = &cmd->cmd_pkt->pkt_address; 14445 plun = ADDR2LUN(ap); 14446 ptgt = plun->lun_tgt; 14447 14448 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14449 14450 cmd->cmd_state = FCP_PKT_IDLE; 14451 14452 mutex_enter(&pptr->port_mutex); 14453 mutex_enter(&ptgt->tgt_mutex); 14454 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14455 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14456 fc_ulp_rscn_info_t *rscnp; 14457 14458 cmd->cmd_state = FCP_PKT_ISSUED; 14459 14460 /* 14461 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14462 * originally NULL, hence we try to set it to the pd pointed 14463 * to by the SCSI device we're trying to get to. 14464 */ 14465 14466 fpkt = cmd->cmd_fp_pkt; 14467 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14468 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14469 /* 14470 * We need to notify the transport that we now have a 14471 * reference to the remote port handle. 14472 */ 14473 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14474 } 14475 14476 mutex_exit(&ptgt->tgt_mutex); 14477 mutex_exit(&pptr->port_mutex); 14478 14479 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14480 14481 /* prepare the packet */ 14482 14483 fcp_prepare_pkt(pptr, cmd, plun); 14484 14485 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14486 pkt_ulp_rscn_infop; 14487 14488 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14489 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14490 14491 if (rscnp != NULL) { 14492 rscnp->ulp_rscn_count = 14493 fc_ulp_get_rscn_count(pptr-> 14494 port_fp_handle); 14495 } 14496 14497 rval = fcp_transport(pptr->port_fp_handle, 14498 cmd->cmd_fp_pkt, 0); 14499 14500 if (rval == FC_SUCCESS) { 14501 return; 14502 } 14503 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14504 } else { 14505 mutex_exit(&ptgt->tgt_mutex); 14506 mutex_exit(&pptr->port_mutex); 14507 } 14508 14509 fcp_queue_pkt(pptr, cmd); 14510 } 14511 14512 14513 static void 14514 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14515 { 14516 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14517 14518 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14519 cmd->cmd_state = FCP_PKT_IDLE; 14520 14521 cmd->cmd_pkt->pkt_reason = reason; 14522 cmd->cmd_pkt->pkt_state = 0; 14523 cmd->cmd_pkt->pkt_statistics = statistics; 14524 14525 fcp_post_callback(cmd); 14526 } 14527 14528 /* 14529 * Function: fcp_queue_pkt 14530 * 14531 * Description: This function queues the packet passed by the caller into 14532 * the list of packets of the FCP port. 14533 * 14534 * Argument: *pptr FCP port. 14535 * *cmd FCP packet to queue. 14536 * 14537 * Return Value: None 14538 * 14539 * Context: User, Kernel and Interrupt context. 14540 */ 14541 static void 14542 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14543 { 14544 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14545 14546 mutex_enter(&pptr->port_pkt_mutex); 14547 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14548 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14549 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14550 14551 /* 14552 * zero pkt_time means hang around for ever 14553 */ 14554 if (cmd->cmd_pkt->pkt_time) { 14555 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14556 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14557 } else { 14558 /* 14559 * Indicate the watch thread to fail the 14560 * command by setting it to highest value 14561 */ 14562 cmd->cmd_timeout = fcp_watchdog_time; 14563 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14564 } 14565 } 14566 14567 if (pptr->port_pkt_head) { 14568 ASSERT(pptr->port_pkt_tail != NULL); 14569 14570 pptr->port_pkt_tail->cmd_next = cmd; 14571 pptr->port_pkt_tail = cmd; 14572 } else { 14573 ASSERT(pptr->port_pkt_tail == NULL); 14574 14575 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14576 } 14577 cmd->cmd_next = NULL; 14578 mutex_exit(&pptr->port_pkt_mutex); 14579 } 14580 14581 /* 14582 * Function: fcp_update_targets 14583 * 14584 * Description: This function applies the specified change of state to all 14585 * the targets listed. The operation applied is 'set'. 14586 * 14587 * Argument: *pptr FCP port. 14588 * *dev_list Array of fc_portmap_t structures. 14589 * count Length of dev_list. 14590 * state State bits to update. 14591 * cause Reason for the update. 14592 * 14593 * Return Value: None 14594 * 14595 * Context: User, Kernel and Interrupt context. 14596 * The mutex pptr->port_mutex must be held. 14597 */ 14598 static void 14599 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14600 uint32_t count, uint32_t state, int cause) 14601 { 14602 fc_portmap_t *map_entry; 14603 struct fcp_tgt *ptgt; 14604 14605 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14606 14607 while (count--) { 14608 map_entry = &(dev_list[count]); 14609 ptgt = fcp_lookup_target(pptr, 14610 (uchar_t *)&(map_entry->map_pwwn)); 14611 if (ptgt == NULL) { 14612 continue; 14613 } 14614 14615 mutex_enter(&ptgt->tgt_mutex); 14616 ptgt->tgt_trace = 0; 14617 ptgt->tgt_change_cnt++; 14618 ptgt->tgt_statec_cause = cause; 14619 ptgt->tgt_tmp_cnt = 1; 14620 fcp_update_tgt_state(ptgt, FCP_SET, state); 14621 mutex_exit(&ptgt->tgt_mutex); 14622 } 14623 } 14624 14625 static int 14626 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14627 int lcount, int tcount, int cause) 14628 { 14629 int rval; 14630 14631 mutex_enter(&pptr->port_mutex); 14632 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14633 mutex_exit(&pptr->port_mutex); 14634 14635 return (rval); 14636 } 14637 14638 14639 static int 14640 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14641 int lcount, int tcount, int cause) 14642 { 14643 int finish_init = 0; 14644 int finish_tgt = 0; 14645 int do_finish_init = 0; 14646 int rval = FCP_NO_CHANGE; 14647 14648 if (cause == FCP_CAUSE_LINK_CHANGE || 14649 cause == FCP_CAUSE_LINK_DOWN) { 14650 do_finish_init = 1; 14651 } 14652 14653 if (ptgt != NULL) { 14654 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14655 FCP_BUF_LEVEL_2, 0, 14656 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14657 " cause = %d, d_id = 0x%x, tgt_done = %d", 14658 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14659 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14660 ptgt->tgt_d_id, ptgt->tgt_done); 14661 14662 mutex_enter(&ptgt->tgt_mutex); 14663 14664 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14665 rval = FCP_DEV_CHANGE; 14666 if (do_finish_init && ptgt->tgt_done == 0) { 14667 ptgt->tgt_done++; 14668 finish_init = 1; 14669 } 14670 } else { 14671 if (--ptgt->tgt_tmp_cnt <= 0) { 14672 ptgt->tgt_tmp_cnt = 0; 14673 finish_tgt = 1; 14674 14675 if (do_finish_init) { 14676 finish_init = 1; 14677 } 14678 } 14679 } 14680 mutex_exit(&ptgt->tgt_mutex); 14681 } else { 14682 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14683 FCP_BUF_LEVEL_2, 0, 14684 "Call Finish Init for NO target"); 14685 14686 if (do_finish_init) { 14687 finish_init = 1; 14688 } 14689 } 14690 14691 if (finish_tgt) { 14692 ASSERT(ptgt != NULL); 14693 14694 mutex_enter(&ptgt->tgt_mutex); 14695 #ifdef DEBUG 14696 bzero(ptgt->tgt_tmp_cnt_stack, 14697 sizeof (ptgt->tgt_tmp_cnt_stack)); 14698 14699 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14700 FCP_STACK_DEPTH); 14701 #endif /* DEBUG */ 14702 mutex_exit(&ptgt->tgt_mutex); 14703 14704 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14705 } 14706 14707 if (finish_init && lcount == pptr->port_link_cnt) { 14708 ASSERT(pptr->port_tmp_cnt > 0); 14709 if (--pptr->port_tmp_cnt == 0) { 14710 fcp_finish_init(pptr); 14711 } 14712 } else if (lcount != pptr->port_link_cnt) { 14713 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14714 fcp_trace, FCP_BUF_LEVEL_2, 0, 14715 "fcp_call_finish_init_held,1: state change occured" 14716 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14717 } 14718 14719 return (rval); 14720 } 14721 14722 static void 14723 fcp_reconfigure_luns(void * tgt_handle) 14724 { 14725 uint32_t dev_cnt; 14726 fc_portmap_t *devlist; 14727 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14728 struct fcp_port *pptr = ptgt->tgt_port; 14729 14730 /* 14731 * If the timer that fires this off got canceled too late, the 14732 * target could have been destroyed. 14733 */ 14734 14735 if (ptgt->tgt_tid == NULL) { 14736 return; 14737 } 14738 14739 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14740 if (devlist == NULL) { 14741 fcp_log(CE_WARN, pptr->port_dip, 14742 "!fcp%d: failed to allocate for portmap", 14743 pptr->port_instance); 14744 return; 14745 } 14746 14747 dev_cnt = 1; 14748 devlist->map_pd = ptgt->tgt_pd_handle; 14749 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14750 devlist->map_did.port_id = ptgt->tgt_d_id; 14751 14752 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14753 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14754 14755 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14756 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14757 devlist->map_flags = 0; 14758 14759 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14760 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14761 14762 /* 14763 * Clear the tgt_tid after no more references to 14764 * the fcp_tgt 14765 */ 14766 mutex_enter(&ptgt->tgt_mutex); 14767 ptgt->tgt_tid = NULL; 14768 mutex_exit(&ptgt->tgt_mutex); 14769 14770 kmem_free(devlist, sizeof (*devlist)); 14771 } 14772 14773 14774 static void 14775 fcp_free_targets(struct fcp_port *pptr) 14776 { 14777 int i; 14778 struct fcp_tgt *ptgt; 14779 14780 mutex_enter(&pptr->port_mutex); 14781 for (i = 0; i < FCP_NUM_HASH; i++) { 14782 ptgt = pptr->port_tgt_hash_table[i]; 14783 while (ptgt != NULL) { 14784 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14785 14786 fcp_free_target(ptgt); 14787 ptgt = next_tgt; 14788 } 14789 } 14790 mutex_exit(&pptr->port_mutex); 14791 } 14792 14793 14794 static void 14795 fcp_free_target(struct fcp_tgt *ptgt) 14796 { 14797 struct fcp_lun *plun; 14798 timeout_id_t tid; 14799 14800 mutex_enter(&ptgt->tgt_mutex); 14801 tid = ptgt->tgt_tid; 14802 14803 /* 14804 * Cancel any pending timeouts for this target. 14805 */ 14806 14807 if (tid != NULL) { 14808 /* 14809 * Set tgt_tid to NULL first to avoid a race in the callback. 14810 * If tgt_tid is NULL, the callback will simply return. 14811 */ 14812 ptgt->tgt_tid = NULL; 14813 mutex_exit(&ptgt->tgt_mutex); 14814 (void) untimeout(tid); 14815 mutex_enter(&ptgt->tgt_mutex); 14816 } 14817 14818 plun = ptgt->tgt_lun; 14819 while (plun != NULL) { 14820 struct fcp_lun *next_lun = plun->lun_next; 14821 14822 fcp_dealloc_lun(plun); 14823 plun = next_lun; 14824 } 14825 14826 mutex_exit(&ptgt->tgt_mutex); 14827 fcp_dealloc_tgt(ptgt); 14828 } 14829 14830 /* 14831 * Function: fcp_is_retryable 14832 * 14833 * Description: Indicates if the internal packet is retryable. 14834 * 14835 * Argument: *icmd FCP internal packet. 14836 * 14837 * Return Value: 0 Not retryable 14838 * 1 Retryable 14839 * 14840 * Context: User, Kernel and Interrupt context 14841 */ 14842 static int 14843 fcp_is_retryable(struct fcp_ipkt *icmd) 14844 { 14845 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14846 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14847 return (0); 14848 } 14849 14850 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14851 icmd->ipkt_port->port_deadline) ? 1 : 0); 14852 } 14853 14854 /* 14855 * Function: fcp_create_on_demand 14856 * 14857 * Argument: *pptr FCP port. 14858 * *pwwn Port WWN. 14859 * 14860 * Return Value: 0 Success 14861 * EIO 14862 * ENOMEM 14863 * EBUSY 14864 * EINVAL 14865 * 14866 * Context: User and Kernel context 14867 */ 14868 static int 14869 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14870 { 14871 int wait_ms; 14872 int tcount; 14873 int lcount; 14874 int ret; 14875 int error; 14876 int rval = EIO; 14877 int ntries; 14878 fc_portmap_t *devlist; 14879 opaque_t pd; 14880 struct fcp_lun *plun; 14881 struct fcp_tgt *ptgt; 14882 int old_manual = 0; 14883 14884 /* Allocates the fc_portmap_t structure. */ 14885 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14886 14887 /* 14888 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14889 * in the commented statement below: 14890 * 14891 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14892 * 14893 * Below, the deadline for the discovery process is set. 14894 */ 14895 mutex_enter(&pptr->port_mutex); 14896 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14897 mutex_exit(&pptr->port_mutex); 14898 14899 /* 14900 * We try to find the remote port based on the WWN provided by the 14901 * caller. We actually ask fp/fctl if it has it. 14902 */ 14903 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14904 (la_wwn_t *)pwwn, &error, 1); 14905 14906 if (pd == NULL) { 14907 kmem_free(devlist, sizeof (*devlist)); 14908 return (rval); 14909 } 14910 14911 /* 14912 * The remote port was found. We ask fp/fctl to update our 14913 * fc_portmap_t structure. 14914 */ 14915 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14916 (la_wwn_t *)pwwn, devlist); 14917 if (ret != FC_SUCCESS) { 14918 kmem_free(devlist, sizeof (*devlist)); 14919 return (rval); 14920 } 14921 14922 /* 14923 * The map flag field is set to indicates that the creation is being 14924 * done at the user request (Ioclt probably luxadm or cfgadm). 14925 */ 14926 devlist->map_type = PORT_DEVICE_USER_CREATE; 14927 14928 mutex_enter(&pptr->port_mutex); 14929 14930 /* 14931 * We check to see if fcp already has a target that describes the 14932 * device being created. If not it is created. 14933 */ 14934 ptgt = fcp_lookup_target(pptr, pwwn); 14935 if (ptgt == NULL) { 14936 lcount = pptr->port_link_cnt; 14937 mutex_exit(&pptr->port_mutex); 14938 14939 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14940 if (ptgt == NULL) { 14941 fcp_log(CE_WARN, pptr->port_dip, 14942 "!FC target allocation failed"); 14943 return (ENOMEM); 14944 } 14945 14946 mutex_enter(&pptr->port_mutex); 14947 } 14948 14949 mutex_enter(&ptgt->tgt_mutex); 14950 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14951 ptgt->tgt_tmp_cnt = 1; 14952 ptgt->tgt_device_created = 0; 14953 /* 14954 * If fabric and auto config is set but the target was 14955 * manually unconfigured then reset to the manual_config_only to 14956 * 0 so the device will get configured. 14957 */ 14958 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14959 fcp_enable_auto_configuration && 14960 ptgt->tgt_manual_config_only == 1) { 14961 old_manual = 1; 14962 ptgt->tgt_manual_config_only = 0; 14963 } 14964 mutex_exit(&ptgt->tgt_mutex); 14965 14966 fcp_update_targets(pptr, devlist, 1, 14967 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14968 14969 lcount = pptr->port_link_cnt; 14970 tcount = ptgt->tgt_change_cnt; 14971 14972 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14973 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14974 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14975 fcp_enable_auto_configuration && old_manual) { 14976 mutex_enter(&ptgt->tgt_mutex); 14977 ptgt->tgt_manual_config_only = 1; 14978 mutex_exit(&ptgt->tgt_mutex); 14979 } 14980 14981 if (pptr->port_link_cnt != lcount || 14982 ptgt->tgt_change_cnt != tcount) { 14983 rval = EBUSY; 14984 } 14985 mutex_exit(&pptr->port_mutex); 14986 14987 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14988 FCP_BUF_LEVEL_3, 0, 14989 "fcp_create_on_demand: mapflags ptgt=%x, " 14990 "lcount=%x::port_link_cnt=%x, " 14991 "tcount=%x: tgt_change_cnt=%x, rval=%x", 14992 ptgt, lcount, pptr->port_link_cnt, 14993 tcount, ptgt->tgt_change_cnt, rval); 14994 return (rval); 14995 } 14996 14997 /* 14998 * Due to lack of synchronization mechanisms, we perform 14999 * periodic monitoring of our request; Because requests 15000 * get dropped when another one supercedes (either because 15001 * of a link change or a target change), it is difficult to 15002 * provide a clean synchronization mechanism (such as a 15003 * semaphore or a conditional variable) without exhaustively 15004 * rewriting the mainline discovery code of this driver. 15005 */ 15006 wait_ms = 500; 15007 15008 ntries = fcp_max_target_retries; 15009 15010 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15011 FCP_BUF_LEVEL_3, 0, 15012 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15013 "lcount=%x::port_link_cnt=%x, " 15014 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15015 "tgt_tmp_cnt =%x", 15016 ntries, ptgt, lcount, pptr->port_link_cnt, 15017 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15018 ptgt->tgt_tmp_cnt); 15019 15020 mutex_enter(&ptgt->tgt_mutex); 15021 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15022 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15023 mutex_exit(&ptgt->tgt_mutex); 15024 mutex_exit(&pptr->port_mutex); 15025 15026 delay(drv_usectohz(wait_ms * 1000)); 15027 15028 mutex_enter(&pptr->port_mutex); 15029 mutex_enter(&ptgt->tgt_mutex); 15030 } 15031 15032 15033 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15034 rval = EBUSY; 15035 } else { 15036 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15037 FCP_TGT_NODE_PRESENT) { 15038 rval = 0; 15039 } 15040 } 15041 15042 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15043 FCP_BUF_LEVEL_3, 0, 15044 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15045 "lcount=%x::port_link_cnt=%x, " 15046 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15047 "tgt_tmp_cnt =%x", 15048 ntries, ptgt, lcount, pptr->port_link_cnt, 15049 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15050 ptgt->tgt_tmp_cnt); 15051 15052 if (rval) { 15053 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15054 fcp_enable_auto_configuration && old_manual) { 15055 ptgt->tgt_manual_config_only = 1; 15056 } 15057 mutex_exit(&ptgt->tgt_mutex); 15058 mutex_exit(&pptr->port_mutex); 15059 kmem_free(devlist, sizeof (*devlist)); 15060 15061 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15062 FCP_BUF_LEVEL_3, 0, 15063 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15064 "lcount=%x::port_link_cnt=%x, " 15065 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15066 "tgt_device_created=%x, tgt D_ID=%x", 15067 ntries, ptgt, lcount, pptr->port_link_cnt, 15068 tcount, ptgt->tgt_change_cnt, rval, 15069 ptgt->tgt_device_created, ptgt->tgt_d_id); 15070 return (rval); 15071 } 15072 15073 if ((plun = ptgt->tgt_lun) != NULL) { 15074 tcount = plun->lun_tgt->tgt_change_cnt; 15075 } else { 15076 rval = EINVAL; 15077 } 15078 lcount = pptr->port_link_cnt; 15079 15080 /* 15081 * Configuring the target with no LUNs will fail. We 15082 * should reset the node state so that it is not 15083 * automatically configured when the LUNs are added 15084 * to this target. 15085 */ 15086 if (ptgt->tgt_lun_cnt == 0) { 15087 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15088 } 15089 mutex_exit(&ptgt->tgt_mutex); 15090 mutex_exit(&pptr->port_mutex); 15091 15092 while (plun) { 15093 child_info_t *cip; 15094 15095 mutex_enter(&plun->lun_mutex); 15096 cip = plun->lun_cip; 15097 mutex_exit(&plun->lun_mutex); 15098 15099 mutex_enter(&ptgt->tgt_mutex); 15100 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15101 mutex_exit(&ptgt->tgt_mutex); 15102 15103 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15104 FCP_ONLINE, lcount, tcount, 15105 NDI_ONLINE_ATTACH); 15106 if (rval != NDI_SUCCESS) { 15107 FCP_TRACE(fcp_logq, 15108 pptr->port_instbuf, fcp_trace, 15109 FCP_BUF_LEVEL_3, 0, 15110 "fcp_create_on_demand: " 15111 "pass_to_hp_and_wait failed " 15112 "rval=%x", rval); 15113 rval = EIO; 15114 } else { 15115 mutex_enter(&LUN_TGT->tgt_mutex); 15116 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15117 FCP_LUN_BUSY); 15118 mutex_exit(&LUN_TGT->tgt_mutex); 15119 } 15120 mutex_enter(&ptgt->tgt_mutex); 15121 } 15122 15123 plun = plun->lun_next; 15124 mutex_exit(&ptgt->tgt_mutex); 15125 } 15126 15127 kmem_free(devlist, sizeof (*devlist)); 15128 15129 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15130 fcp_enable_auto_configuration && old_manual) { 15131 mutex_enter(&ptgt->tgt_mutex); 15132 /* if successful then set manual to 0 */ 15133 if (rval == 0) { 15134 ptgt->tgt_manual_config_only = 0; 15135 } else { 15136 /* reset to 1 so the user has to do the config */ 15137 ptgt->tgt_manual_config_only = 1; 15138 } 15139 mutex_exit(&ptgt->tgt_mutex); 15140 } 15141 15142 return (rval); 15143 } 15144 15145 15146 static void 15147 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15148 { 15149 int count; 15150 uchar_t byte; 15151 15152 count = 0; 15153 while (*string) { 15154 byte = FCP_ATOB(*string); string++; 15155 byte = byte << 4 | FCP_ATOB(*string); string++; 15156 bytes[count++] = byte; 15157 15158 if (count >= byte_len) { 15159 break; 15160 } 15161 } 15162 } 15163 15164 static void 15165 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15166 { 15167 int i; 15168 15169 for (i = 0; i < FC_WWN_SIZE; i++) { 15170 (void) sprintf(string + (i * 2), 15171 "%02x", wwn[i]); 15172 } 15173 15174 } 15175 15176 static void 15177 fcp_print_error(fc_packet_t *fpkt) 15178 { 15179 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15180 fpkt->pkt_ulp_private; 15181 struct fcp_port *pptr; 15182 struct fcp_tgt *ptgt; 15183 struct fcp_lun *plun; 15184 caddr_t buf; 15185 int scsi_cmd = 0; 15186 15187 ptgt = icmd->ipkt_tgt; 15188 plun = icmd->ipkt_lun; 15189 pptr = ptgt->tgt_port; 15190 15191 buf = kmem_zalloc(256, KM_NOSLEEP); 15192 if (buf == NULL) { 15193 return; 15194 } 15195 15196 switch (icmd->ipkt_opcode) { 15197 case SCMD_REPORT_LUN: 15198 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15199 " lun=0x%%x failed"); 15200 scsi_cmd++; 15201 break; 15202 15203 case SCMD_INQUIRY_PAGE83: 15204 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15205 " lun=0x%%x failed"); 15206 scsi_cmd++; 15207 break; 15208 15209 case SCMD_INQUIRY: 15210 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15211 " lun=0x%%x failed"); 15212 scsi_cmd++; 15213 break; 15214 15215 case LA_ELS_PLOGI: 15216 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15217 break; 15218 15219 case LA_ELS_PRLI: 15220 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15221 break; 15222 } 15223 15224 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15225 struct fcp_rsp response, *rsp; 15226 uchar_t asc, ascq; 15227 caddr_t sense_key = NULL; 15228 struct fcp_rsp_info fcp_rsp_err, *bep; 15229 15230 if (icmd->ipkt_nodma) { 15231 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15232 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15233 sizeof (struct fcp_rsp)); 15234 } else { 15235 rsp = &response; 15236 bep = &fcp_rsp_err; 15237 15238 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15239 sizeof (struct fcp_rsp)); 15240 15241 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15242 bep, fpkt->pkt_resp_acc, 15243 sizeof (struct fcp_rsp_info)); 15244 } 15245 15246 15247 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15248 (void) sprintf(buf + strlen(buf), 15249 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15250 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15251 " senselen=%%x. Giving up"); 15252 15253 fcp_log(CE_WARN, pptr->port_dip, buf, 15254 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15255 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15256 rsp->fcp_u.fcp_status.reserved_1, 15257 rsp->fcp_response_len, rsp->fcp_sense_len); 15258 15259 kmem_free(buf, 256); 15260 return; 15261 } 15262 15263 if (rsp->fcp_u.fcp_status.rsp_len_set && 15264 bep->rsp_code != FCP_NO_FAILURE) { 15265 (void) sprintf(buf + strlen(buf), 15266 " FCP Response code = 0x%x", bep->rsp_code); 15267 } 15268 15269 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15270 struct scsi_extended_sense sense_info, *sense_ptr; 15271 15272 if (icmd->ipkt_nodma) { 15273 sense_ptr = (struct scsi_extended_sense *) 15274 ((caddr_t)fpkt->pkt_resp + 15275 sizeof (struct fcp_rsp) + 15276 rsp->fcp_response_len); 15277 } else { 15278 sense_ptr = &sense_info; 15279 15280 FCP_CP_IN(fpkt->pkt_resp + 15281 sizeof (struct fcp_rsp) + 15282 rsp->fcp_response_len, &sense_info, 15283 fpkt->pkt_resp_acc, 15284 sizeof (struct scsi_extended_sense)); 15285 } 15286 15287 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15288 NUM_IMPL_SENSE_KEYS) { 15289 sense_key = sense_keys[sense_ptr->es_key]; 15290 } else { 15291 sense_key = "Undefined"; 15292 } 15293 15294 asc = sense_ptr->es_add_code; 15295 ascq = sense_ptr->es_qual_code; 15296 15297 (void) sprintf(buf + strlen(buf), 15298 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15299 " Giving up"); 15300 15301 fcp_log(CE_WARN, pptr->port_dip, buf, 15302 ptgt->tgt_d_id, plun->lun_num, sense_key, 15303 asc, ascq); 15304 } else { 15305 (void) sprintf(buf + strlen(buf), 15306 " : SCSI status=%%x. Giving up"); 15307 15308 fcp_log(CE_WARN, pptr->port_dip, buf, 15309 ptgt->tgt_d_id, plun->lun_num, 15310 rsp->fcp_u.fcp_status.scsi_status); 15311 } 15312 } else { 15313 caddr_t state, reason, action, expln; 15314 15315 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15316 &action, &expln); 15317 15318 (void) sprintf(buf + strlen(buf), ": State:%%s," 15319 " Reason:%%s. Giving up"); 15320 15321 if (scsi_cmd) { 15322 fcp_log(CE_WARN, pptr->port_dip, buf, 15323 ptgt->tgt_d_id, plun->lun_num, state, reason); 15324 } else { 15325 fcp_log(CE_WARN, pptr->port_dip, buf, 15326 ptgt->tgt_d_id, state, reason); 15327 } 15328 } 15329 15330 kmem_free(buf, 256); 15331 } 15332 15333 15334 static int 15335 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15336 struct fcp_ipkt *icmd, int rval, caddr_t op) 15337 { 15338 int ret = DDI_FAILURE; 15339 char *error; 15340 15341 switch (rval) { 15342 case FC_DEVICE_BUSY_NEW_RSCN: 15343 /* 15344 * This means that there was a new RSCN that the transport 15345 * knows about (which the ULP *may* know about too) but the 15346 * pkt that was sent down was related to an older RSCN. So, we 15347 * are just going to reset the retry count and deadline and 15348 * continue to retry. The idea is that transport is currently 15349 * working on the new RSCN and will soon let the ULPs know 15350 * about it and when it does the existing logic will kick in 15351 * where it will change the tcount to indicate that something 15352 * changed on the target. So, rediscovery will start and there 15353 * will not be an infinite retry. 15354 * 15355 * For a full flow of how the RSCN info is transferred back and 15356 * forth, see fp.c 15357 */ 15358 icmd->ipkt_retries = 0; 15359 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15360 FCP_ICMD_DEADLINE; 15361 15362 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15363 FCP_BUF_LEVEL_3, 0, 15364 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15365 rval, ptgt->tgt_d_id); 15366 /* FALLTHROUGH */ 15367 15368 case FC_STATEC_BUSY: 15369 case FC_DEVICE_BUSY: 15370 case FC_PBUSY: 15371 case FC_FBUSY: 15372 case FC_TRAN_BUSY: 15373 case FC_OFFLINE: 15374 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15375 FCP_BUF_LEVEL_3, 0, 15376 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15377 rval, ptgt->tgt_d_id); 15378 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15379 fcp_is_retryable(icmd)) { 15380 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15381 ret = DDI_SUCCESS; 15382 } 15383 break; 15384 15385 case FC_LOGINREQ: 15386 /* 15387 * FC_LOGINREQ used to be handled just like all the cases 15388 * above. It has been changed to handled a PRLI that fails 15389 * with FC_LOGINREQ different than other ipkts that fail 15390 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15391 * a simple matter to turn it into a PLOGI instead, so that's 15392 * exactly what we do here. 15393 */ 15394 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15395 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15396 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15397 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15398 } else { 15399 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15400 FCP_BUF_LEVEL_3, 0, 15401 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15402 rval, ptgt->tgt_d_id); 15403 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15404 fcp_is_retryable(icmd)) { 15405 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15406 ret = DDI_SUCCESS; 15407 } 15408 } 15409 break; 15410 15411 default: 15412 mutex_enter(&pptr->port_mutex); 15413 mutex_enter(&ptgt->tgt_mutex); 15414 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15415 mutex_exit(&ptgt->tgt_mutex); 15416 mutex_exit(&pptr->port_mutex); 15417 15418 (void) fc_ulp_error(rval, &error); 15419 fcp_log(CE_WARN, pptr->port_dip, 15420 "!Failed to send %s to D_ID=%x error=%s", 15421 op, ptgt->tgt_d_id, error); 15422 } else { 15423 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15424 fcp_trace, FCP_BUF_LEVEL_2, 0, 15425 "fcp_handle_ipkt_errors,1: state change occured" 15426 " for D_ID=0x%x", ptgt->tgt_d_id); 15427 mutex_exit(&ptgt->tgt_mutex); 15428 mutex_exit(&pptr->port_mutex); 15429 } 15430 break; 15431 } 15432 15433 return (ret); 15434 } 15435 15436 15437 /* 15438 * Check of outstanding commands on any LUN for this target 15439 */ 15440 static int 15441 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15442 { 15443 struct fcp_lun *plun; 15444 struct fcp_pkt *cmd; 15445 15446 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15447 mutex_enter(&plun->lun_mutex); 15448 for (cmd = plun->lun_pkt_head; cmd != NULL; 15449 cmd = cmd->cmd_forw) { 15450 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15451 mutex_exit(&plun->lun_mutex); 15452 return (FC_SUCCESS); 15453 } 15454 } 15455 mutex_exit(&plun->lun_mutex); 15456 } 15457 15458 return (FC_FAILURE); 15459 } 15460 15461 static fc_portmap_t * 15462 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15463 { 15464 int i; 15465 fc_portmap_t *devlist; 15466 fc_portmap_t *devptr = NULL; 15467 struct fcp_tgt *ptgt; 15468 15469 mutex_enter(&pptr->port_mutex); 15470 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15471 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15472 ptgt = ptgt->tgt_next) { 15473 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15474 ++*dev_cnt; 15475 } 15476 } 15477 } 15478 15479 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15480 KM_NOSLEEP); 15481 if (devlist == NULL) { 15482 mutex_exit(&pptr->port_mutex); 15483 fcp_log(CE_WARN, pptr->port_dip, 15484 "!fcp%d: failed to allocate for portmap for construct map", 15485 pptr->port_instance); 15486 return (devptr); 15487 } 15488 15489 for (i = 0; i < FCP_NUM_HASH; i++) { 15490 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15491 ptgt = ptgt->tgt_next) { 15492 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15493 int ret; 15494 15495 ret = fc_ulp_pwwn_to_portmap( 15496 pptr->port_fp_handle, 15497 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15498 devlist); 15499 15500 if (ret == FC_SUCCESS) { 15501 devlist++; 15502 continue; 15503 } 15504 15505 devlist->map_pd = NULL; 15506 devlist->map_did.port_id = ptgt->tgt_d_id; 15507 devlist->map_hard_addr.hard_addr = 15508 ptgt->tgt_hard_addr; 15509 15510 devlist->map_state = PORT_DEVICE_INVALID; 15511 devlist->map_type = PORT_DEVICE_OLD; 15512 15513 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15514 &devlist->map_nwwn, FC_WWN_SIZE); 15515 15516 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15517 &devlist->map_pwwn, FC_WWN_SIZE); 15518 15519 devlist++; 15520 } 15521 } 15522 } 15523 15524 mutex_exit(&pptr->port_mutex); 15525 15526 return (devptr); 15527 } 15528 /* 15529 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15530 */ 15531 static void 15532 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15533 { 15534 int i; 15535 struct fcp_tgt *ptgt; 15536 struct fcp_lun *plun; 15537 15538 for (i = 0; i < FCP_NUM_HASH; i++) { 15539 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15540 ptgt = ptgt->tgt_next) { 15541 mutex_enter(&ptgt->tgt_mutex); 15542 for (plun = ptgt->tgt_lun; plun != NULL; 15543 plun = plun->lun_next) { 15544 if (plun->lun_mpxio && 15545 plun->lun_state & FCP_LUN_BUSY) { 15546 if (!fcp_pass_to_hp(pptr, plun, 15547 plun->lun_cip, 15548 FCP_MPXIO_PATH_SET_BUSY, 15549 pptr->port_link_cnt, 15550 ptgt->tgt_change_cnt, 0, 0)) { 15551 FCP_TRACE(fcp_logq, 15552 pptr->port_instbuf, 15553 fcp_trace, 15554 FCP_BUF_LEVEL_2, 0, 15555 "path_verifybusy: " 15556 "disable lun %p failed!", 15557 plun); 15558 } 15559 } 15560 } 15561 mutex_exit(&ptgt->tgt_mutex); 15562 } 15563 } 15564 } 15565 15566 static int 15567 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15568 { 15569 dev_info_t *cdip = NULL; 15570 dev_info_t *pdip = NULL; 15571 15572 ASSERT(plun); 15573 15574 mutex_enter(&plun->lun_mutex); 15575 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15576 mutex_exit(&plun->lun_mutex); 15577 return (NDI_FAILURE); 15578 } 15579 mutex_exit(&plun->lun_mutex); 15580 cdip = mdi_pi_get_client(PIP(cip)); 15581 pdip = mdi_pi_get_phci(PIP(cip)); 15582 15583 ASSERT(cdip != NULL); 15584 ASSERT(pdip != NULL); 15585 15586 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15587 /* LUN ready for IO */ 15588 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15589 } else { 15590 /* LUN busy to accept IO */ 15591 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15592 } 15593 return (NDI_SUCCESS); 15594 } 15595 15596 /* 15597 * Caller must free the returned string of MAXPATHLEN len 15598 * If the device is offline (-1 instance number) NULL 15599 * will be returned. 15600 */ 15601 static char * 15602 fcp_get_lun_path(struct fcp_lun *plun) 15603 { 15604 dev_info_t *dip = NULL; 15605 char *path = NULL; 15606 mdi_pathinfo_t *pip = NULL; 15607 15608 if (plun == NULL) { 15609 return (NULL); 15610 } 15611 15612 mutex_enter(&plun->lun_mutex); 15613 if (plun->lun_mpxio == 0) { 15614 dip = DIP(plun->lun_cip); 15615 mutex_exit(&plun->lun_mutex); 15616 } else { 15617 /* 15618 * lun_cip must be accessed with lun_mutex held. Here 15619 * plun->lun_cip either points to a valid node or it is NULL. 15620 * Make a copy so that we can release lun_mutex. 15621 */ 15622 pip = PIP(plun->lun_cip); 15623 15624 /* 15625 * Increase ref count on the path so that we can release 15626 * lun_mutex and still be sure that the pathinfo node (and thus 15627 * also the client) is not deallocated. If pip is NULL, this 15628 * has no effect. 15629 */ 15630 mdi_hold_path(pip); 15631 15632 mutex_exit(&plun->lun_mutex); 15633 15634 /* Get the client. If pip is NULL, we get NULL. */ 15635 dip = mdi_pi_get_client(pip); 15636 } 15637 15638 if (dip == NULL) 15639 goto out; 15640 if (ddi_get_instance(dip) < 0) 15641 goto out; 15642 15643 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15644 if (path == NULL) 15645 goto out; 15646 15647 (void) ddi_pathname(dip, path); 15648 15649 /* Clean up. */ 15650 out: 15651 if (pip != NULL) 15652 mdi_rele_path(pip); 15653 15654 /* 15655 * In reality, the user wants a fully valid path (one they can open) 15656 * but this string is lacking the mount point, and the minor node. 15657 * It would be nice if we could "figure these out" somehow 15658 * and fill them in. Otherwise, the userland code has to understand 15659 * driver specific details of which minor node is the "best" or 15660 * "right" one to expose. (Ex: which slice is the whole disk, or 15661 * which tape doesn't rewind) 15662 */ 15663 return (path); 15664 } 15665 15666 static int 15667 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15668 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15669 { 15670 int64_t reset_delay; 15671 int rval, retry = 0; 15672 struct fcp_port *pptr = fcp_dip2port(parent); 15673 15674 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15675 (ddi_get_lbolt64() - pptr->port_attach_time); 15676 if (reset_delay < 0) { 15677 reset_delay = 0; 15678 } 15679 15680 if (fcp_bus_config_debug) { 15681 flag |= NDI_DEVI_DEBUG; 15682 } 15683 15684 switch (op) { 15685 case BUS_CONFIG_ONE: 15686 /* 15687 * Retry the command since we need to ensure 15688 * the fabric devices are available for root 15689 */ 15690 while (retry++ < fcp_max_bus_config_retries) { 15691 rval = (ndi_busop_bus_config(parent, 15692 flag | NDI_MDI_FALLBACK, op, 15693 arg, childp, (clock_t)reset_delay)); 15694 if (rval == 0) { 15695 return (rval); 15696 } 15697 } 15698 15699 /* 15700 * drain taskq to make sure nodes are created and then 15701 * try again. 15702 */ 15703 taskq_wait(DEVI(parent)->devi_taskq); 15704 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15705 op, arg, childp, 0)); 15706 15707 case BUS_CONFIG_DRIVER: 15708 case BUS_CONFIG_ALL: { 15709 /* 15710 * delay till all devices report in (port_tmp_cnt == 0) 15711 * or FCP_INIT_WAIT_TIMEOUT 15712 */ 15713 mutex_enter(&pptr->port_mutex); 15714 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15715 (void) cv_timedwait(&pptr->port_config_cv, 15716 &pptr->port_mutex, 15717 ddi_get_lbolt() + (clock_t)reset_delay); 15718 reset_delay = 15719 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15720 (ddi_get_lbolt64() - pptr->port_attach_time); 15721 } 15722 mutex_exit(&pptr->port_mutex); 15723 /* drain taskq to make sure nodes are created */ 15724 taskq_wait(DEVI(parent)->devi_taskq); 15725 return (ndi_busop_bus_config(parent, flag, op, 15726 arg, childp, 0)); 15727 } 15728 15729 default: 15730 return (NDI_FAILURE); 15731 } 15732 /*NOTREACHED*/ 15733 } 15734 15735 static int 15736 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15737 ddi_bus_config_op_t op, void *arg) 15738 { 15739 if (fcp_bus_config_debug) { 15740 flag |= NDI_DEVI_DEBUG; 15741 } 15742 15743 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15744 } 15745 15746 15747 /* 15748 * Routine to copy GUID into the lun structure. 15749 * returns 0 if copy was successful and 1 if encountered a 15750 * failure and did not copy the guid. 15751 */ 15752 static int 15753 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15754 { 15755 15756 int retval = 0; 15757 15758 /* add one for the null terminator */ 15759 const unsigned int len = strlen(guidp) + 1; 15760 15761 if ((guidp == NULL) || (plun == NULL)) { 15762 return (1); 15763 } 15764 15765 /* 15766 * if the plun->lun_guid already has been allocated, 15767 * then check the size. if the size is exact, reuse 15768 * it....if not free it an allocate the required size. 15769 * The reallocation should NOT typically happen 15770 * unless the GUIDs reported changes between passes. 15771 * We free up and alloc again even if the 15772 * size was more than required. This is due to the 15773 * fact that the field lun_guid_size - serves 15774 * dual role of indicating the size of the wwn 15775 * size and ALSO the allocation size. 15776 */ 15777 if (plun->lun_guid) { 15778 if (plun->lun_guid_size != len) { 15779 /* 15780 * free the allocated memory and 15781 * initialize the field 15782 * lun_guid_size to 0. 15783 */ 15784 kmem_free(plun->lun_guid, plun->lun_guid_size); 15785 plun->lun_guid = NULL; 15786 plun->lun_guid_size = 0; 15787 } 15788 } 15789 /* 15790 * alloc only if not already done. 15791 */ 15792 if (plun->lun_guid == NULL) { 15793 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15794 if (plun->lun_guid == NULL) { 15795 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15796 "Unable to allocate" 15797 "Memory for GUID!!! size %d", len); 15798 retval = 1; 15799 } else { 15800 plun->lun_guid_size = len; 15801 } 15802 } 15803 if (plun->lun_guid) { 15804 /* 15805 * now copy the GUID 15806 */ 15807 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15808 } 15809 return (retval); 15810 } 15811 15812 /* 15813 * fcp_reconfig_wait 15814 * 15815 * Wait for a rediscovery/reconfiguration to complete before continuing. 15816 */ 15817 15818 static void 15819 fcp_reconfig_wait(struct fcp_port *pptr) 15820 { 15821 clock_t reconfig_start, wait_timeout; 15822 15823 /* 15824 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15825 * reconfiguration in progress. 15826 */ 15827 15828 mutex_enter(&pptr->port_mutex); 15829 if (pptr->port_tmp_cnt == 0) { 15830 mutex_exit(&pptr->port_mutex); 15831 return; 15832 } 15833 mutex_exit(&pptr->port_mutex); 15834 15835 /* 15836 * If we cause a reconfig by raising power, delay until all devices 15837 * report in (port_tmp_cnt returns to 0) 15838 */ 15839 15840 reconfig_start = ddi_get_lbolt(); 15841 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15842 15843 mutex_enter(&pptr->port_mutex); 15844 15845 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15846 pptr->port_tmp_cnt) { 15847 15848 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15849 reconfig_start + wait_timeout); 15850 } 15851 15852 mutex_exit(&pptr->port_mutex); 15853 15854 /* 15855 * Even if fcp_tmp_count isn't 0, continue without error. The port 15856 * we want may still be ok. If not, it will error out later 15857 */ 15858 } 15859 15860 /* 15861 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15862 * We rely on the fcp_global_mutex to provide protection against changes to 15863 * the fcp_lun_blacklist. 15864 * 15865 * You can describe a list of target port WWNs and LUN numbers which will 15866 * not be configured. LUN numbers will be interpreted as decimal. White 15867 * spaces and ',' can be used in the list of LUN numbers. 15868 * 15869 * To prevent LUNs 1 and 2 from being configured for target 15870 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15871 * 15872 * pwwn-lun-blacklist= 15873 * "510000f010fd92a1,1,2", 15874 * "510000e012079df1,1,2"; 15875 */ 15876 static void 15877 fcp_read_blacklist(dev_info_t *dip, 15878 struct fcp_black_list_entry **pplun_blacklist) 15879 { 15880 char **prop_array = NULL; 15881 char *curr_pwwn = NULL; 15882 char *curr_lun = NULL; 15883 uint32_t prop_item = 0; 15884 int idx = 0; 15885 int len = 0; 15886 15887 ASSERT(mutex_owned(&fcp_global_mutex)); 15888 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15889 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15890 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15891 return; 15892 } 15893 15894 for (idx = 0; idx < prop_item; idx++) { 15895 15896 curr_pwwn = prop_array[idx]; 15897 while (*curr_pwwn == ' ') { 15898 curr_pwwn++; 15899 } 15900 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15901 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15902 ", please check.", curr_pwwn); 15903 continue; 15904 } 15905 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15906 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15907 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15908 ", please check.", curr_pwwn); 15909 continue; 15910 } 15911 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15912 if (isxdigit(curr_pwwn[len]) != TRUE) { 15913 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15914 "blacklist, please check.", curr_pwwn); 15915 break; 15916 } 15917 } 15918 if (len != sizeof (la_wwn_t) * 2) { 15919 continue; 15920 } 15921 15922 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15923 *(curr_lun - 1) = '\0'; 15924 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15925 } 15926 15927 ddi_prop_free(prop_array); 15928 } 15929 15930 /* 15931 * Get the masking info about one remote target port designated by wwn. 15932 * Lun ids could be separated by ',' or white spaces. 15933 */ 15934 static void 15935 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15936 struct fcp_black_list_entry **pplun_blacklist) 15937 { 15938 int idx = 0; 15939 uint32_t offset = 0; 15940 unsigned long lun_id = 0; 15941 char lunid_buf[16]; 15942 char *pend = NULL; 15943 int illegal_digit = 0; 15944 15945 while (offset < strlen(curr_lun)) { 15946 while ((curr_lun[offset + idx] != ',') && 15947 (curr_lun[offset + idx] != '\0') && 15948 (curr_lun[offset + idx] != ' ')) { 15949 if (isdigit(curr_lun[offset + idx]) == 0) { 15950 illegal_digit++; 15951 } 15952 idx++; 15953 } 15954 if (illegal_digit > 0) { 15955 offset += (idx+1); /* To the start of next lun */ 15956 idx = 0; 15957 illegal_digit = 0; 15958 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15959 "the blacklist, please check digits.", 15960 curr_lun, curr_pwwn); 15961 continue; 15962 } 15963 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15964 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15965 "the blacklist, please check the length of LUN#.", 15966 curr_lun, curr_pwwn); 15967 break; 15968 } 15969 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15970 offset++; 15971 continue; 15972 } 15973 15974 bcopy(curr_lun + offset, lunid_buf, idx); 15975 lunid_buf[idx] = '\0'; 15976 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15977 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15978 } else { 15979 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15980 "the blacklist, please check %s.", 15981 curr_lun, curr_pwwn, lunid_buf); 15982 } 15983 offset += (idx+1); /* To the start of next lun */ 15984 idx = 0; 15985 } 15986 } 15987 15988 /* 15989 * Add one masking record 15990 */ 15991 static void 15992 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 15993 struct fcp_black_list_entry **pplun_blacklist) 15994 { 15995 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15996 struct fcp_black_list_entry *new_entry = NULL; 15997 la_wwn_t wwn; 15998 15999 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16000 while (tmp_entry) { 16001 if ((bcmp(&tmp_entry->wwn, &wwn, 16002 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16003 return; 16004 } 16005 16006 tmp_entry = tmp_entry->next; 16007 } 16008 16009 /* add to black list */ 16010 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16011 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16012 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16013 new_entry->lun = lun_id; 16014 new_entry->masked = 0; 16015 new_entry->next = *pplun_blacklist; 16016 *pplun_blacklist = new_entry; 16017 } 16018 16019 /* 16020 * Check if we should mask the specified lun of this fcp_tgt 16021 */ 16022 static int 16023 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) 16024 { 16025 struct fcp_black_list_entry *remote_port; 16026 16027 remote_port = fcp_lun_blacklist; 16028 while (remote_port != NULL) { 16029 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16030 if (remote_port->lun == lun_id) { 16031 remote_port->masked++; 16032 if (remote_port->masked == 1) { 16033 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16034 "%02x%02x%02x%02x%02x%02x%02x%02x " 16035 "is masked due to black listing.\n", 16036 lun_id, wwn->raw_wwn[0], 16037 wwn->raw_wwn[1], wwn->raw_wwn[2], 16038 wwn->raw_wwn[3], wwn->raw_wwn[4], 16039 wwn->raw_wwn[5], wwn->raw_wwn[6], 16040 wwn->raw_wwn[7]); 16041 } 16042 return (TRUE); 16043 } 16044 } 16045 remote_port = remote_port->next; 16046 } 16047 return (FALSE); 16048 } 16049 16050 /* 16051 * Release all allocated resources 16052 */ 16053 static void 16054 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) 16055 { 16056 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16057 struct fcp_black_list_entry *current_entry = NULL; 16058 16059 ASSERT(mutex_owned(&fcp_global_mutex)); 16060 /* 16061 * Traverse all luns 16062 */ 16063 while (tmp_entry) { 16064 current_entry = tmp_entry; 16065 tmp_entry = tmp_entry->next; 16066 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16067 } 16068 *pplun_blacklist = NULL; 16069 } 16070 16071 /* 16072 * In fcp module, 16073 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16074 */ 16075 static struct scsi_pkt * 16076 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16077 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16078 int flags, int (*callback)(), caddr_t arg) 16079 { 16080 fcp_port_t *pptr = ADDR2FCP(ap); 16081 fcp_pkt_t *cmd = NULL; 16082 fc_frame_hdr_t *hp; 16083 16084 /* 16085 * First step: get the packet 16086 */ 16087 if (pkt == NULL) { 16088 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16089 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16090 callback, arg); 16091 if (pkt == NULL) { 16092 return (NULL); 16093 } 16094 16095 /* 16096 * All fields in scsi_pkt will be initialized properly or 16097 * set to zero. We need do nothing for scsi_pkt. 16098 */ 16099 /* 16100 * But it's our responsibility to link other related data 16101 * structures. Their initialization will be done, just 16102 * before the scsi_pkt will be sent to FCA. 16103 */ 16104 cmd = PKT2CMD(pkt); 16105 cmd->cmd_pkt = pkt; 16106 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16107 /* 16108 * fc_packet_t 16109 */ 16110 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16111 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16112 sizeof (struct fcp_pkt)); 16113 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16114 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16115 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16116 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16117 /* 16118 * Fill in the Fabric Channel Header 16119 */ 16120 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16121 hp->r_ctl = R_CTL_COMMAND; 16122 hp->rsvd = 0; 16123 hp->type = FC_TYPE_SCSI_FCP; 16124 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16125 hp->seq_id = 0; 16126 hp->df_ctl = 0; 16127 hp->seq_cnt = 0; 16128 hp->ox_id = 0xffff; 16129 hp->rx_id = 0xffff; 16130 hp->ro = 0; 16131 } else { 16132 /* 16133 * We need think if we should reset any elements in 16134 * related data structures. 16135 */ 16136 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16137 fcp_trace, FCP_BUF_LEVEL_6, 0, 16138 "reusing pkt, flags %d", flags); 16139 cmd = PKT2CMD(pkt); 16140 if (cmd->cmd_fp_pkt->pkt_pd) { 16141 cmd->cmd_fp_pkt->pkt_pd = NULL; 16142 } 16143 } 16144 16145 /* 16146 * Second step: dma allocation/move 16147 */ 16148 if (bp && bp->b_bcount != 0) { 16149 /* 16150 * Mark if it's read or write 16151 */ 16152 if (bp->b_flags & B_READ) { 16153 cmd->cmd_flags |= CFLAG_IS_READ; 16154 } else { 16155 cmd->cmd_flags &= ~CFLAG_IS_READ; 16156 } 16157 16158 bp_mapin(bp); 16159 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16160 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16161 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16162 } else { 16163 /* 16164 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16165 * to send zero-length read/write. 16166 */ 16167 cmd->cmd_fp_pkt->pkt_data = NULL; 16168 cmd->cmd_fp_pkt->pkt_datalen = 0; 16169 } 16170 16171 return (pkt); 16172 } 16173 16174 static void 16175 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16176 { 16177 fcp_port_t *pptr = ADDR2FCP(ap); 16178 16179 /* 16180 * First we let FCA to uninitilize private part. 16181 */ 16182 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16183 PKT2CMD(pkt)->cmd_fp_pkt); 16184 16185 /* 16186 * Then we uninitialize fc_packet. 16187 */ 16188 16189 /* 16190 * Thirdly, we uninitializae fcp_pkt. 16191 */ 16192 16193 /* 16194 * In the end, we free scsi_pkt. 16195 */ 16196 scsi_hba_pkt_free(ap, pkt); 16197 } 16198 16199 static int 16200 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16201 { 16202 fcp_port_t *pptr = ADDR2FCP(ap); 16203 fcp_lun_t *plun = ADDR2LUN(ap); 16204 fcp_tgt_t *ptgt = plun->lun_tgt; 16205 fcp_pkt_t *cmd = PKT2CMD(pkt); 16206 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16207 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16208 int rval; 16209 16210 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16211 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16212 16213 /* 16214 * Firstly, we need initialize fcp_pkt_t 16215 * Secondly, we need initialize fcp_cmd_t. 16216 */ 16217 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16218 fcmd->fcp_data_len = fpkt->pkt_datalen; 16219 fcmd->fcp_ent_addr = plun->lun_addr; 16220 if (pkt->pkt_flags & FLAG_HTAG) { 16221 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16222 } else if (pkt->pkt_flags & FLAG_OTAG) { 16223 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16224 } else if (pkt->pkt_flags & FLAG_STAG) { 16225 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16226 } else { 16227 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16228 } 16229 16230 if (cmd->cmd_flags & CFLAG_IS_READ) { 16231 fcmd->fcp_cntl.cntl_read_data = 1; 16232 fcmd->fcp_cntl.cntl_write_data = 0; 16233 } else { 16234 fcmd->fcp_cntl.cntl_read_data = 0; 16235 fcmd->fcp_cntl.cntl_write_data = 1; 16236 } 16237 16238 /* 16239 * Then we need initialize fc_packet_t too. 16240 */ 16241 fpkt->pkt_timeout = pkt->pkt_time + 2; 16242 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16243 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16244 if (cmd->cmd_flags & CFLAG_IS_READ) { 16245 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16246 } else { 16247 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16248 } 16249 16250 if (pkt->pkt_flags & FLAG_NOINTR) { 16251 fpkt->pkt_comp = NULL; 16252 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16253 } else { 16254 fpkt->pkt_comp = fcp_cmd_callback; 16255 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16256 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16257 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16258 } 16259 } 16260 16261 /* 16262 * Lastly, we need initialize scsi_pkt 16263 */ 16264 pkt->pkt_reason = CMD_CMPLT; 16265 pkt->pkt_state = 0; 16266 pkt->pkt_statistics = 0; 16267 pkt->pkt_resid = 0; 16268 16269 /* 16270 * if interrupts aren't allowed (e.g. at dump time) then we'll 16271 * have to do polled I/O 16272 */ 16273 if (pkt->pkt_flags & FLAG_NOINTR) { 16274 return (fcp_dopoll(pptr, cmd)); 16275 } 16276 16277 cmd->cmd_state = FCP_PKT_ISSUED; 16278 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16279 if (rval == FC_SUCCESS) { 16280 return (TRAN_ACCEPT); 16281 } 16282 16283 /* 16284 * Need more consideration 16285 * 16286 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16287 */ 16288 cmd->cmd_state = FCP_PKT_IDLE; 16289 if (rval == FC_TRAN_BUSY) { 16290 return (TRAN_BUSY); 16291 } else { 16292 return (TRAN_FATAL_ERROR); 16293 } 16294 } 16295 16296 /* 16297 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16298 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16299 */ 16300 static void 16301 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16302 { 16303 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16304 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16305 } 16306 16307 /* 16308 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16309 */ 16310 static void 16311 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16312 { 16313 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16314 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16315 }