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 skip; 8218 } else { 8219 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) 8220 goto skip; 8221 ccip = cip; 8222 } 8223 8224 if (online == FCP_ONLINE) { 8225 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8226 &circ); 8227 } else { 8228 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8229 &circ); 8230 } 8231 8232 skip: 8233 mutex_exit(&plun->lun_mutex); 8234 mutex_exit(&pptr->port_mutex); 8235 8236 if (rval == NDI_SUCCESS) { 8237 fc_ulp_log_device_event(pptr->port_fp_handle, 8238 online == FCP_ONLINE ? 8239 FC_ULP_DEVICE_ONLINE : FC_ULP_DEVICE_OFFLINE); 8240 } 8241 8242 if (is_mpxio) { 8243 mdi_devi_exit(pptr->port_dip, circ); 8244 } else { 8245 ndi_devi_exit(pptr->port_dip, circ); 8246 } 8247 8248 fc_ulp_idle_port(pptr->port_fp_handle); 8249 8250 return (rval); 8251 } 8252 8253 8254 /* 8255 * take a target offline by taking all of its LUNs offline 8256 */ 8257 /*ARGSUSED*/ 8258 static int 8259 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8260 int link_cnt, int tgt_cnt, int nowait, int flags) 8261 { 8262 struct fcp_tgt_elem *elem; 8263 8264 ASSERT(mutex_owned(&pptr->port_mutex)); 8265 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8266 8267 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8268 8269 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8270 ptgt->tgt_change_cnt)) { 8271 mutex_exit(&ptgt->tgt_mutex); 8272 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8273 mutex_enter(&ptgt->tgt_mutex); 8274 8275 return (0); 8276 } 8277 8278 ptgt->tgt_pd_handle = NULL; 8279 mutex_exit(&ptgt->tgt_mutex); 8280 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8281 mutex_enter(&ptgt->tgt_mutex); 8282 8283 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8284 8285 if (ptgt->tgt_tcap && 8286 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8287 elem->flags = flags; 8288 elem->time = fcp_watchdog_time; 8289 if (nowait == 0) { 8290 elem->time += fcp_offline_delay; 8291 } 8292 elem->ptgt = ptgt; 8293 elem->link_cnt = link_cnt; 8294 elem->tgt_cnt = tgt_cnt; 8295 elem->next = pptr->port_offline_tgts; 8296 pptr->port_offline_tgts = elem; 8297 } else { 8298 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8299 } 8300 8301 return (1); 8302 } 8303 8304 8305 static void 8306 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8307 int link_cnt, int tgt_cnt, int flags) 8308 { 8309 ASSERT(mutex_owned(&pptr->port_mutex)); 8310 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8311 8312 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8313 ptgt->tgt_state = FCP_TGT_OFFLINE; 8314 ptgt->tgt_pd_handle = NULL; 8315 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8316 } 8317 8318 8319 static void 8320 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8321 int flags) 8322 { 8323 struct fcp_lun *plun; 8324 8325 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8326 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8327 8328 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8329 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8330 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8331 } 8332 } 8333 } 8334 8335 8336 /* 8337 * take a LUN offline 8338 * 8339 * enters and leaves with the target mutex held, releasing it in the process 8340 * 8341 * allocates memory in non-sleep mode 8342 */ 8343 static void 8344 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8345 int nowait, int flags) 8346 { 8347 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8348 struct fcp_lun_elem *elem; 8349 8350 ASSERT(plun != NULL); 8351 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8352 8353 if (nowait) { 8354 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8355 return; 8356 } 8357 8358 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8359 elem->flags = flags; 8360 elem->time = fcp_watchdog_time; 8361 if (nowait == 0) { 8362 elem->time += fcp_offline_delay; 8363 } 8364 elem->plun = plun; 8365 elem->link_cnt = link_cnt; 8366 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8367 elem->next = pptr->port_offline_luns; 8368 pptr->port_offline_luns = elem; 8369 } else { 8370 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8371 } 8372 } 8373 8374 8375 static void 8376 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8377 { 8378 struct fcp_pkt *head = NULL; 8379 8380 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8381 8382 mutex_exit(&LUN_TGT->tgt_mutex); 8383 8384 head = fcp_scan_commands(plun); 8385 if (head != NULL) { 8386 fcp_abort_commands(head, LUN_PORT); 8387 } 8388 8389 mutex_enter(&LUN_TGT->tgt_mutex); 8390 8391 if (plun->lun_cip && plun->lun_mpxio) { 8392 /* 8393 * Intimate MPxIO lun busy is cleared 8394 */ 8395 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8396 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8397 0, 0)) { 8398 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8399 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8400 LUN_TGT->tgt_d_id, plun->lun_num); 8401 } 8402 /* 8403 * Intimate MPxIO that the lun is now marked for offline 8404 */ 8405 mutex_exit(&LUN_TGT->tgt_mutex); 8406 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8407 mutex_enter(&LUN_TGT->tgt_mutex); 8408 } 8409 } 8410 8411 static void 8412 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8413 int flags) 8414 { 8415 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8416 8417 mutex_exit(&LUN_TGT->tgt_mutex); 8418 fcp_update_offline_flags(plun); 8419 mutex_enter(&LUN_TGT->tgt_mutex); 8420 8421 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8422 8423 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8424 fcp_trace, FCP_BUF_LEVEL_4, 0, 8425 "offline_lun: passing OFFLINE elem to HP thread"); 8426 8427 if (plun->lun_cip) { 8428 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8429 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8430 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8431 LUN_TGT->tgt_trace); 8432 8433 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8434 link_cnt, tgt_cnt, flags, 0)) { 8435 fcp_log(CE_CONT, LUN_PORT->port_dip, 8436 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8437 LUN_TGT->tgt_d_id, plun->lun_num); 8438 } 8439 } 8440 } 8441 8442 static void 8443 fcp_scan_offline_luns(struct fcp_port *pptr) 8444 { 8445 struct fcp_lun_elem *elem; 8446 struct fcp_lun_elem *prev; 8447 struct fcp_lun_elem *next; 8448 8449 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8450 8451 prev = NULL; 8452 elem = pptr->port_offline_luns; 8453 while (elem) { 8454 next = elem->next; 8455 if (elem->time <= fcp_watchdog_time) { 8456 int changed = 1; 8457 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8458 8459 mutex_enter(&ptgt->tgt_mutex); 8460 if (pptr->port_link_cnt == elem->link_cnt && 8461 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8462 changed = 0; 8463 } 8464 8465 if (!changed && 8466 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8467 fcp_offline_lun_now(elem->plun, 8468 elem->link_cnt, elem->tgt_cnt, elem->flags); 8469 } 8470 mutex_exit(&ptgt->tgt_mutex); 8471 8472 kmem_free(elem, sizeof (*elem)); 8473 8474 if (prev) { 8475 prev->next = next; 8476 } else { 8477 pptr->port_offline_luns = next; 8478 } 8479 } else { 8480 prev = elem; 8481 } 8482 elem = next; 8483 } 8484 } 8485 8486 8487 static void 8488 fcp_scan_offline_tgts(struct fcp_port *pptr) 8489 { 8490 struct fcp_tgt_elem *elem; 8491 struct fcp_tgt_elem *prev; 8492 struct fcp_tgt_elem *next; 8493 8494 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8495 8496 prev = NULL; 8497 elem = pptr->port_offline_tgts; 8498 while (elem) { 8499 next = elem->next; 8500 if (elem->time <= fcp_watchdog_time) { 8501 int outdated = 1; 8502 struct fcp_tgt *ptgt = elem->ptgt; 8503 8504 mutex_enter(&ptgt->tgt_mutex); 8505 8506 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8507 /* No change on tgt since elem was created. */ 8508 outdated = 0; 8509 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8510 pptr->port_link_cnt == elem->link_cnt + 1 && 8511 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8512 /* 8513 * Exactly one thing happened to the target 8514 * inbetween: the local port went offline. 8515 * For fp the remote port is already gone so 8516 * it will not tell us again to offline the 8517 * target. We must offline it now. 8518 */ 8519 outdated = 0; 8520 } 8521 8522 if (!outdated && !(ptgt->tgt_state & 8523 FCP_TGT_OFFLINE)) { 8524 fcp_offline_target_now(pptr, 8525 ptgt, elem->link_cnt, elem->tgt_cnt, 8526 elem->flags); 8527 } 8528 8529 mutex_exit(&ptgt->tgt_mutex); 8530 8531 kmem_free(elem, sizeof (*elem)); 8532 8533 if (prev) { 8534 prev->next = next; 8535 } else { 8536 pptr->port_offline_tgts = next; 8537 } 8538 } else { 8539 prev = elem; 8540 } 8541 elem = next; 8542 } 8543 } 8544 8545 8546 static void 8547 fcp_update_offline_flags(struct fcp_lun *plun) 8548 { 8549 struct fcp_port *pptr = LUN_PORT; 8550 ASSERT(plun != NULL); 8551 8552 mutex_enter(&LUN_TGT->tgt_mutex); 8553 plun->lun_state |= FCP_LUN_OFFLINE; 8554 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8555 8556 mutex_enter(&plun->lun_mutex); 8557 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8558 dev_info_t *cdip = NULL; 8559 8560 mutex_exit(&LUN_TGT->tgt_mutex); 8561 8562 if (plun->lun_mpxio == 0) { 8563 cdip = DIP(plun->lun_cip); 8564 } else if (plun->lun_cip) { 8565 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8566 } 8567 8568 mutex_exit(&plun->lun_mutex); 8569 if (cdip) { 8570 (void) ndi_event_retrieve_cookie( 8571 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8572 &fcp_remove_eid, NDI_EVENT_NOPASS); 8573 (void) ndi_event_run_callbacks( 8574 pptr->port_ndi_event_hdl, cdip, 8575 fcp_remove_eid, NULL); 8576 } 8577 } else { 8578 mutex_exit(&plun->lun_mutex); 8579 mutex_exit(&LUN_TGT->tgt_mutex); 8580 } 8581 } 8582 8583 8584 /* 8585 * Scan all of the command pkts for this port, moving pkts that 8586 * match our LUN onto our own list (headed by "head") 8587 */ 8588 static struct fcp_pkt * 8589 fcp_scan_commands(struct fcp_lun *plun) 8590 { 8591 struct fcp_port *pptr = LUN_PORT; 8592 8593 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8594 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8595 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8596 8597 struct fcp_pkt *head = NULL; /* head of our list */ 8598 struct fcp_pkt *tail = NULL; /* tail of our list */ 8599 8600 int cmds_found = 0; 8601 8602 mutex_enter(&pptr->port_pkt_mutex); 8603 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8604 struct fcp_lun *tlun = 8605 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8606 8607 ncmd = cmd->cmd_next; /* set next command */ 8608 8609 /* 8610 * if this pkt is for a different LUN or the 8611 * command is sent down, skip it. 8612 */ 8613 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8614 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8615 pcmd = cmd; 8616 continue; 8617 } 8618 cmds_found++; 8619 if (pcmd != NULL) { 8620 ASSERT(pptr->port_pkt_head != cmd); 8621 pcmd->cmd_next = cmd->cmd_next; 8622 } else { 8623 ASSERT(cmd == pptr->port_pkt_head); 8624 pptr->port_pkt_head = cmd->cmd_next; 8625 } 8626 8627 if (cmd == pptr->port_pkt_tail) { 8628 pptr->port_pkt_tail = pcmd; 8629 if (pcmd) { 8630 pcmd->cmd_next = NULL; 8631 } 8632 } 8633 8634 if (head == NULL) { 8635 head = tail = cmd; 8636 } else { 8637 ASSERT(tail != NULL); 8638 8639 tail->cmd_next = cmd; 8640 tail = cmd; 8641 } 8642 cmd->cmd_next = NULL; 8643 } 8644 mutex_exit(&pptr->port_pkt_mutex); 8645 8646 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8647 fcp_trace, FCP_BUF_LEVEL_8, 0, 8648 "scan commands: %d cmd(s) found", cmds_found); 8649 8650 return (head); 8651 } 8652 8653 8654 /* 8655 * Abort all the commands in the command queue 8656 */ 8657 static void 8658 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8659 { 8660 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8661 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8662 8663 ASSERT(mutex_owned(&pptr->port_mutex)); 8664 8665 /* scan through the pkts and invalid them */ 8666 for (cmd = head; cmd != NULL; cmd = ncmd) { 8667 struct scsi_pkt *pkt = cmd->cmd_pkt; 8668 8669 ncmd = cmd->cmd_next; 8670 ASSERT(pkt != NULL); 8671 8672 /* 8673 * The lun is going to be marked offline. Indicate 8674 * the target driver not to requeue or retry this command 8675 * as the device is going to be offlined pretty soon. 8676 */ 8677 pkt->pkt_reason = CMD_DEV_GONE; 8678 pkt->pkt_statistics = 0; 8679 pkt->pkt_state = 0; 8680 8681 /* reset cmd flags/state */ 8682 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8683 cmd->cmd_state = FCP_PKT_IDLE; 8684 8685 /* 8686 * ensure we have a packet completion routine, 8687 * then call it. 8688 */ 8689 ASSERT(pkt->pkt_comp != NULL); 8690 8691 mutex_exit(&pptr->port_mutex); 8692 fcp_post_callback(cmd); 8693 mutex_enter(&pptr->port_mutex); 8694 } 8695 } 8696 8697 8698 /* 8699 * the pkt_comp callback for command packets 8700 */ 8701 static void 8702 fcp_cmd_callback(fc_packet_t *fpkt) 8703 { 8704 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8705 struct scsi_pkt *pkt = cmd->cmd_pkt; 8706 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8707 8708 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8709 8710 if (cmd->cmd_state == FCP_PKT_IDLE) { 8711 cmn_err(CE_PANIC, "Packet already completed %p", 8712 (void *)cmd); 8713 } 8714 8715 /* 8716 * Watch thread should be freeing the packet, ignore the pkt. 8717 */ 8718 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8719 fcp_log(CE_CONT, pptr->port_dip, 8720 "!FCP: Pkt completed while aborting\n"); 8721 return; 8722 } 8723 cmd->cmd_state = FCP_PKT_IDLE; 8724 8725 fcp_complete_pkt(fpkt); 8726 8727 #ifdef DEBUG 8728 mutex_enter(&pptr->port_pkt_mutex); 8729 pptr->port_npkts--; 8730 mutex_exit(&pptr->port_pkt_mutex); 8731 #endif /* DEBUG */ 8732 8733 fcp_post_callback(cmd); 8734 } 8735 8736 8737 static void 8738 fcp_complete_pkt(fc_packet_t *fpkt) 8739 { 8740 int error = 0; 8741 struct fcp_pkt *cmd = (struct fcp_pkt *) 8742 fpkt->pkt_ulp_private; 8743 struct scsi_pkt *pkt = cmd->cmd_pkt; 8744 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8745 struct fcp_lun *plun; 8746 struct fcp_tgt *ptgt; 8747 struct fcp_rsp *rsp; 8748 struct scsi_address save; 8749 8750 #ifdef DEBUG 8751 save = pkt->pkt_address; 8752 #endif /* DEBUG */ 8753 8754 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8755 8756 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8757 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8758 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8759 sizeof (struct fcp_rsp)); 8760 } 8761 8762 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8763 STATE_SENT_CMD | STATE_GOT_STATUS; 8764 8765 pkt->pkt_resid = 0; 8766 8767 if (fpkt->pkt_datalen) { 8768 pkt->pkt_state |= STATE_XFERRED_DATA; 8769 if (fpkt->pkt_data_resid) { 8770 error++; 8771 } 8772 } 8773 8774 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8775 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8776 /* 8777 * The next two checks make sure that if there 8778 * is no sense data or a valid response and 8779 * the command came back with check condition, 8780 * the command should be retried. 8781 */ 8782 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8783 !rsp->fcp_u.fcp_status.sense_len_set) { 8784 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8785 pkt->pkt_resid = cmd->cmd_dmacount; 8786 } 8787 } 8788 8789 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8790 return; 8791 } 8792 8793 plun = ADDR2LUN(&pkt->pkt_address); 8794 ptgt = plun->lun_tgt; 8795 ASSERT(ptgt != NULL); 8796 8797 /* 8798 * Update the transfer resid, if appropriate 8799 */ 8800 if (rsp->fcp_u.fcp_status.resid_over || 8801 rsp->fcp_u.fcp_status.resid_under) { 8802 pkt->pkt_resid = rsp->fcp_resid; 8803 } 8804 8805 /* 8806 * First see if we got a FCP protocol error. 8807 */ 8808 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8809 struct fcp_rsp_info *bep; 8810 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8811 sizeof (struct fcp_rsp)); 8812 8813 if (fcp_validate_fcp_response(rsp, pptr) != 8814 FC_SUCCESS) { 8815 pkt->pkt_reason = CMD_CMPLT; 8816 *(pkt->pkt_scbp) = STATUS_CHECK; 8817 8818 fcp_log(CE_WARN, pptr->port_dip, 8819 "!SCSI command to d_id=0x%x lun=0x%x" 8820 " failed, Bad FCP response values:" 8821 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8822 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8823 ptgt->tgt_d_id, plun->lun_num, 8824 rsp->reserved_0, rsp->reserved_1, 8825 rsp->fcp_u.fcp_status.reserved_0, 8826 rsp->fcp_u.fcp_status.reserved_1, 8827 rsp->fcp_response_len, rsp->fcp_sense_len); 8828 8829 return; 8830 } 8831 8832 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8833 FCP_CP_IN(fpkt->pkt_resp + 8834 sizeof (struct fcp_rsp), bep, 8835 fpkt->pkt_resp_acc, 8836 sizeof (struct fcp_rsp_info)); 8837 } 8838 8839 if (bep->rsp_code != FCP_NO_FAILURE) { 8840 child_info_t *cip; 8841 8842 pkt->pkt_reason = CMD_TRAN_ERR; 8843 8844 mutex_enter(&plun->lun_mutex); 8845 cip = plun->lun_cip; 8846 mutex_exit(&plun->lun_mutex); 8847 8848 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8849 fcp_trace, FCP_BUF_LEVEL_2, 0, 8850 "FCP response error on cmd=%p" 8851 " target=0x%x, cip=%p", cmd, 8852 ptgt->tgt_d_id, cip); 8853 } 8854 } 8855 8856 /* 8857 * See if we got a SCSI error with sense data 8858 */ 8859 if (rsp->fcp_u.fcp_status.sense_len_set) { 8860 uchar_t rqlen; 8861 caddr_t sense_from; 8862 child_info_t *cip; 8863 timeout_id_t tid; 8864 struct scsi_arq_status *arq; 8865 struct scsi_extended_sense *sense_to; 8866 8867 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8868 sense_to = &arq->sts_sensedata; 8869 8870 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8871 sizeof (struct scsi_extended_sense)); 8872 8873 sense_from = (caddr_t)fpkt->pkt_resp + 8874 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8875 8876 if (fcp_validate_fcp_response(rsp, pptr) != 8877 FC_SUCCESS) { 8878 pkt->pkt_reason = CMD_CMPLT; 8879 *(pkt->pkt_scbp) = STATUS_CHECK; 8880 8881 fcp_log(CE_WARN, pptr->port_dip, 8882 "!SCSI command to d_id=0x%x lun=0x%x" 8883 " failed, Bad FCP response values:" 8884 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8885 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8886 ptgt->tgt_d_id, plun->lun_num, 8887 rsp->reserved_0, rsp->reserved_1, 8888 rsp->fcp_u.fcp_status.reserved_0, 8889 rsp->fcp_u.fcp_status.reserved_1, 8890 rsp->fcp_response_len, rsp->fcp_sense_len); 8891 8892 return; 8893 } 8894 8895 /* 8896 * copy in sense information 8897 */ 8898 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8899 FCP_CP_IN(sense_from, sense_to, 8900 fpkt->pkt_resp_acc, rqlen); 8901 } else { 8902 bcopy(sense_from, sense_to, rqlen); 8903 } 8904 8905 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8906 (FCP_SENSE_NO_LUN(sense_to))) { 8907 mutex_enter(&ptgt->tgt_mutex); 8908 if (ptgt->tgt_tid == NULL) { 8909 /* 8910 * Kick off rediscovery 8911 */ 8912 tid = timeout(fcp_reconfigure_luns, 8913 (caddr_t)ptgt, drv_usectohz(1)); 8914 8915 ptgt->tgt_tid = tid; 8916 ptgt->tgt_state |= FCP_TGT_BUSY; 8917 } 8918 mutex_exit(&ptgt->tgt_mutex); 8919 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8920 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8921 fcp_trace, FCP_BUF_LEVEL_3, 0, 8922 "!FCP: Report Lun Has Changed" 8923 " target=%x", ptgt->tgt_d_id); 8924 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8925 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8926 fcp_trace, FCP_BUF_LEVEL_3, 0, 8927 "!FCP: LU Not Supported" 8928 " target=%x", ptgt->tgt_d_id); 8929 } 8930 } 8931 ASSERT(pkt->pkt_scbp != NULL); 8932 8933 pkt->pkt_state |= STATE_ARQ_DONE; 8934 8935 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8936 8937 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8938 arq->sts_rqpkt_reason = 0; 8939 arq->sts_rqpkt_statistics = 0; 8940 8941 arq->sts_rqpkt_state = STATE_GOT_BUS | 8942 STATE_GOT_TARGET | STATE_SENT_CMD | 8943 STATE_GOT_STATUS | STATE_ARQ_DONE | 8944 STATE_XFERRED_DATA; 8945 8946 mutex_enter(&plun->lun_mutex); 8947 cip = plun->lun_cip; 8948 mutex_exit(&plun->lun_mutex); 8949 8950 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8951 fcp_trace, FCP_BUF_LEVEL_8, 0, 8952 "SCSI Check condition on cmd=%p target=0x%x" 8953 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8954 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8955 cmd->cmd_fcp_cmd.fcp_cdb[0], 8956 rsp->fcp_u.fcp_status.scsi_status, 8957 sense_to->es_key, sense_to->es_add_code, 8958 sense_to->es_qual_code); 8959 } 8960 } else { 8961 plun = ADDR2LUN(&pkt->pkt_address); 8962 ptgt = plun->lun_tgt; 8963 ASSERT(ptgt != NULL); 8964 8965 /* 8966 * Work harder to translate errors into target driver 8967 * understandable ones. Note with despair that the target 8968 * drivers don't decode pkt_state and pkt_reason exhaustively 8969 * They resort to using the big hammer most often, which 8970 * may not get fixed in the life time of this driver. 8971 */ 8972 pkt->pkt_state = 0; 8973 pkt->pkt_statistics = 0; 8974 8975 switch (fpkt->pkt_state) { 8976 case FC_PKT_TRAN_ERROR: 8977 switch (fpkt->pkt_reason) { 8978 case FC_REASON_OVERRUN: 8979 pkt->pkt_reason = CMD_CMD_OVR; 8980 pkt->pkt_statistics |= STAT_ABORTED; 8981 break; 8982 8983 case FC_REASON_XCHG_BSY: { 8984 caddr_t ptr; 8985 8986 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8987 8988 ptr = (caddr_t)pkt->pkt_scbp; 8989 if (ptr) { 8990 *ptr = STATUS_BUSY; 8991 } 8992 break; 8993 } 8994 8995 case FC_REASON_ABORTED: 8996 pkt->pkt_reason = CMD_TRAN_ERR; 8997 pkt->pkt_statistics |= STAT_ABORTED; 8998 break; 8999 9000 case FC_REASON_ABORT_FAILED: 9001 pkt->pkt_reason = CMD_ABORT_FAIL; 9002 break; 9003 9004 case FC_REASON_NO_SEQ_INIT: 9005 case FC_REASON_CRC_ERROR: 9006 pkt->pkt_reason = CMD_TRAN_ERR; 9007 pkt->pkt_statistics |= STAT_ABORTED; 9008 break; 9009 default: 9010 pkt->pkt_reason = CMD_TRAN_ERR; 9011 break; 9012 } 9013 break; 9014 9015 case FC_PKT_PORT_OFFLINE: { 9016 dev_info_t *cdip = NULL; 9017 caddr_t ptr; 9018 9019 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9020 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9021 fcp_trace, FCP_BUF_LEVEL_8, 0, 9022 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9023 ptgt->tgt_d_id); 9024 } 9025 9026 mutex_enter(&plun->lun_mutex); 9027 if (plun->lun_mpxio == 0) { 9028 cdip = DIP(plun->lun_cip); 9029 } else if (plun->lun_cip) { 9030 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9031 } 9032 9033 mutex_exit(&plun->lun_mutex); 9034 9035 if (cdip) { 9036 (void) ndi_event_retrieve_cookie( 9037 pptr->port_ndi_event_hdl, cdip, 9038 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9039 NDI_EVENT_NOPASS); 9040 (void) ndi_event_run_callbacks( 9041 pptr->port_ndi_event_hdl, cdip, 9042 fcp_remove_eid, NULL); 9043 } 9044 9045 /* 9046 * If the link goes off-line for a lip, 9047 * this will cause a error to the ST SG 9048 * SGEN drivers. By setting BUSY we will 9049 * give the drivers the chance to retry 9050 * before it blows of the job. ST will 9051 * remember how many times it has retried. 9052 */ 9053 9054 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9055 (plun->lun_type == DTYPE_CHANGER)) { 9056 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9057 ptr = (caddr_t)pkt->pkt_scbp; 9058 if (ptr) { 9059 *ptr = STATUS_BUSY; 9060 } 9061 } else { 9062 pkt->pkt_reason = CMD_TRAN_ERR; 9063 pkt->pkt_statistics |= STAT_BUS_RESET; 9064 } 9065 break; 9066 } 9067 9068 case FC_PKT_TRAN_BSY: 9069 /* 9070 * Use the ssd Qfull handling here. 9071 */ 9072 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9073 pkt->pkt_state = STATE_GOT_BUS; 9074 break; 9075 9076 case FC_PKT_TIMEOUT: 9077 pkt->pkt_reason = CMD_TIMEOUT; 9078 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9079 pkt->pkt_statistics |= STAT_TIMEOUT; 9080 } else { 9081 pkt->pkt_statistics |= STAT_ABORTED; 9082 } 9083 break; 9084 9085 case FC_PKT_LOCAL_RJT: 9086 switch (fpkt->pkt_reason) { 9087 case FC_REASON_OFFLINE: { 9088 dev_info_t *cdip = NULL; 9089 9090 mutex_enter(&plun->lun_mutex); 9091 if (plun->lun_mpxio == 0) { 9092 cdip = DIP(plun->lun_cip); 9093 } else if (plun->lun_cip) { 9094 cdip = mdi_pi_get_client( 9095 PIP(plun->lun_cip)); 9096 } 9097 mutex_exit(&plun->lun_mutex); 9098 9099 if (cdip) { 9100 (void) ndi_event_retrieve_cookie( 9101 pptr->port_ndi_event_hdl, cdip, 9102 FCAL_REMOVE_EVENT, 9103 &fcp_remove_eid, 9104 NDI_EVENT_NOPASS); 9105 (void) ndi_event_run_callbacks( 9106 pptr->port_ndi_event_hdl, 9107 cdip, fcp_remove_eid, NULL); 9108 } 9109 9110 pkt->pkt_reason = CMD_TRAN_ERR; 9111 pkt->pkt_statistics |= STAT_BUS_RESET; 9112 9113 break; 9114 } 9115 9116 case FC_REASON_NOMEM: 9117 case FC_REASON_QFULL: { 9118 caddr_t ptr; 9119 9120 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9121 ptr = (caddr_t)pkt->pkt_scbp; 9122 if (ptr) { 9123 *ptr = STATUS_BUSY; 9124 } 9125 break; 9126 } 9127 9128 case FC_REASON_DMA_ERROR: 9129 pkt->pkt_reason = CMD_DMA_DERR; 9130 pkt->pkt_statistics |= STAT_ABORTED; 9131 break; 9132 9133 case FC_REASON_CRC_ERROR: 9134 case FC_REASON_UNDERRUN: { 9135 uchar_t status; 9136 /* 9137 * Work around for Bugid: 4240945. 9138 * IB on A5k doesn't set the Underrun bit 9139 * in the fcp status, when it is transferring 9140 * less than requested amount of data. Work 9141 * around the ses problem to keep luxadm 9142 * happy till ibfirmware is fixed. 9143 */ 9144 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9145 FCP_CP_IN(fpkt->pkt_resp, rsp, 9146 fpkt->pkt_resp_acc, 9147 sizeof (struct fcp_rsp)); 9148 } 9149 status = rsp->fcp_u.fcp_status.scsi_status; 9150 if (((plun->lun_type & DTYPE_MASK) == 9151 DTYPE_ESI) && (status == STATUS_GOOD)) { 9152 pkt->pkt_reason = CMD_CMPLT; 9153 *pkt->pkt_scbp = status; 9154 pkt->pkt_resid = 0; 9155 } else { 9156 pkt->pkt_reason = CMD_TRAN_ERR; 9157 pkt->pkt_statistics |= STAT_ABORTED; 9158 } 9159 break; 9160 } 9161 9162 case FC_REASON_NO_CONNECTION: 9163 case FC_REASON_UNSUPPORTED: 9164 case FC_REASON_ILLEGAL_REQ: 9165 case FC_REASON_BAD_SID: 9166 case FC_REASON_DIAG_BUSY: 9167 case FC_REASON_FCAL_OPN_FAIL: 9168 case FC_REASON_BAD_XID: 9169 default: 9170 pkt->pkt_reason = CMD_TRAN_ERR; 9171 pkt->pkt_statistics |= STAT_ABORTED; 9172 break; 9173 9174 } 9175 break; 9176 9177 case FC_PKT_NPORT_RJT: 9178 case FC_PKT_FABRIC_RJT: 9179 case FC_PKT_NPORT_BSY: 9180 case FC_PKT_FABRIC_BSY: 9181 default: 9182 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9183 fcp_trace, FCP_BUF_LEVEL_8, 0, 9184 "FC Status 0x%x, reason 0x%x", 9185 fpkt->pkt_state, fpkt->pkt_reason); 9186 pkt->pkt_reason = CMD_TRAN_ERR; 9187 pkt->pkt_statistics |= STAT_ABORTED; 9188 break; 9189 } 9190 9191 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9192 fcp_trace, FCP_BUF_LEVEL_9, 0, 9193 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9194 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9195 fpkt->pkt_reason); 9196 } 9197 9198 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9199 } 9200 9201 9202 static int 9203 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9204 { 9205 if (rsp->reserved_0 || rsp->reserved_1 || 9206 rsp->fcp_u.fcp_status.reserved_0 || 9207 rsp->fcp_u.fcp_status.reserved_1) { 9208 /* 9209 * These reserved fields should ideally be zero. FCP-2 does say 9210 * that the recipient need not check for reserved fields to be 9211 * zero. If they are not zero, we will not make a fuss about it 9212 * - just log it (in debug to both trace buffer and messages 9213 * file and to trace buffer only in non-debug) and move on. 9214 * 9215 * Non-zero reserved fields were seen with minnows. 9216 * 9217 * qlc takes care of some of this but we cannot assume that all 9218 * FCAs will do so. 9219 */ 9220 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9221 FCP_BUF_LEVEL_5, 0, 9222 "Got fcp response packet with non-zero reserved fields " 9223 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9224 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9225 rsp->reserved_0, rsp->reserved_1, 9226 rsp->fcp_u.fcp_status.reserved_0, 9227 rsp->fcp_u.fcp_status.reserved_1); 9228 } 9229 9230 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9231 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9232 return (FC_FAILURE); 9233 } 9234 9235 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9236 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9237 sizeof (struct fcp_rsp))) { 9238 return (FC_FAILURE); 9239 } 9240 9241 return (FC_SUCCESS); 9242 } 9243 9244 9245 /* 9246 * This is called when there is a change the in device state. The case we're 9247 * handling here is, if the d_id s does not match, offline this tgt and online 9248 * a new tgt with the new d_id. called from fcp_handle_devices with 9249 * port_mutex held. 9250 */ 9251 static int 9252 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9253 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9254 { 9255 ASSERT(mutex_owned(&pptr->port_mutex)); 9256 9257 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9258 fcp_trace, FCP_BUF_LEVEL_3, 0, 9259 "Starting fcp_device_changed..."); 9260 9261 /* 9262 * The two cases where the port_device_changed is called is 9263 * either it changes it's d_id or it's hard address. 9264 */ 9265 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9266 (FC_TOP_EXTERNAL(pptr->port_topology) && 9267 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9268 9269 /* offline this target */ 9270 mutex_enter(&ptgt->tgt_mutex); 9271 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9272 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9273 0, 1, NDI_DEVI_REMOVE); 9274 } 9275 mutex_exit(&ptgt->tgt_mutex); 9276 9277 fcp_log(CE_NOTE, pptr->port_dip, 9278 "Change in target properties: Old D_ID=%x New D_ID=%x" 9279 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9280 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9281 map_entry->map_hard_addr.hard_addr); 9282 } 9283 9284 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9285 link_cnt, tgt_cnt, cause)); 9286 } 9287 9288 /* 9289 * Function: fcp_alloc_lun 9290 * 9291 * Description: Creates a new lun structure and adds it to the list 9292 * of luns of the target. 9293 * 9294 * Argument: ptgt Target the lun will belong to. 9295 * 9296 * Return Value: NULL Failed 9297 * Not NULL Succeeded 9298 * 9299 * Context: Kernel context 9300 */ 9301 static struct fcp_lun * 9302 fcp_alloc_lun(struct fcp_tgt *ptgt) 9303 { 9304 struct fcp_lun *plun; 9305 9306 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9307 if (plun != NULL) { 9308 /* 9309 * Initialize the mutex before putting in the target list 9310 * especially before releasing the target mutex. 9311 */ 9312 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9313 plun->lun_tgt = ptgt; 9314 9315 mutex_enter(&ptgt->tgt_mutex); 9316 plun->lun_next = ptgt->tgt_lun; 9317 ptgt->tgt_lun = plun; 9318 plun->lun_old_guid = NULL; 9319 plun->lun_old_guid_size = 0; 9320 mutex_exit(&ptgt->tgt_mutex); 9321 } 9322 9323 return (plun); 9324 } 9325 9326 /* 9327 * Function: fcp_dealloc_lun 9328 * 9329 * Description: Frees the LUN structure passed by the caller. 9330 * 9331 * Argument: plun LUN structure to free. 9332 * 9333 * Return Value: None 9334 * 9335 * Context: Kernel context. 9336 */ 9337 static void 9338 fcp_dealloc_lun(struct fcp_lun *plun) 9339 { 9340 mutex_enter(&plun->lun_mutex); 9341 if (plun->lun_cip) { 9342 fcp_remove_child(plun); 9343 } 9344 mutex_exit(&plun->lun_mutex); 9345 9346 mutex_destroy(&plun->lun_mutex); 9347 if (plun->lun_guid) { 9348 kmem_free(plun->lun_guid, plun->lun_guid_size); 9349 } 9350 if (plun->lun_old_guid) { 9351 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9352 } 9353 kmem_free(plun, sizeof (*plun)); 9354 } 9355 9356 /* 9357 * Function: fcp_alloc_tgt 9358 * 9359 * Description: Creates a new target structure and adds it to the port 9360 * hash list. 9361 * 9362 * Argument: pptr fcp port structure 9363 * *map_entry entry describing the target to create 9364 * link_cnt Link state change counter 9365 * 9366 * Return Value: NULL Failed 9367 * Not NULL Succeeded 9368 * 9369 * Context: Kernel context. 9370 */ 9371 static struct fcp_tgt * 9372 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9373 { 9374 int hash; 9375 uchar_t *wwn; 9376 struct fcp_tgt *ptgt; 9377 9378 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9379 if (ptgt != NULL) { 9380 mutex_enter(&pptr->port_mutex); 9381 if (link_cnt != pptr->port_link_cnt) { 9382 /* 9383 * oh oh -- another link reset 9384 * in progress -- give up 9385 */ 9386 mutex_exit(&pptr->port_mutex); 9387 kmem_free(ptgt, sizeof (*ptgt)); 9388 ptgt = NULL; 9389 } else { 9390 /* 9391 * initialize the mutex before putting in the port 9392 * wwn list, especially before releasing the port 9393 * mutex. 9394 */ 9395 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9396 9397 /* add new target entry to the port's hash list */ 9398 wwn = (uchar_t *)&map_entry->map_pwwn; 9399 hash = FCP_HASH(wwn); 9400 9401 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9402 pptr->port_tgt_hash_table[hash] = ptgt; 9403 9404 /* save cross-ptr */ 9405 ptgt->tgt_port = pptr; 9406 9407 ptgt->tgt_change_cnt = 1; 9408 9409 /* initialize the target manual_config_only flag */ 9410 if (fcp_enable_auto_configuration) { 9411 ptgt->tgt_manual_config_only = 0; 9412 } else { 9413 ptgt->tgt_manual_config_only = 1; 9414 } 9415 9416 mutex_exit(&pptr->port_mutex); 9417 } 9418 } 9419 9420 return (ptgt); 9421 } 9422 9423 /* 9424 * Function: fcp_dealloc_tgt 9425 * 9426 * Description: Frees the target structure passed by the caller. 9427 * 9428 * Argument: ptgt Target structure to free. 9429 * 9430 * Return Value: None 9431 * 9432 * Context: Kernel context. 9433 */ 9434 static void 9435 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9436 { 9437 mutex_destroy(&ptgt->tgt_mutex); 9438 kmem_free(ptgt, sizeof (*ptgt)); 9439 } 9440 9441 9442 /* 9443 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9444 * 9445 * Device discovery commands will not be retried for-ever as 9446 * this will have repercussions on other devices that need to 9447 * be submitted to the hotplug thread. After a quick glance 9448 * at the SCSI-3 spec, it was found that the spec doesn't 9449 * mandate a forever retry, rather recommends a delayed retry. 9450 * 9451 * Since Photon IB is single threaded, STATUS_BUSY is common 9452 * in a 4+initiator environment. Make sure the total time 9453 * spent on retries (including command timeout) does not 9454 * 60 seconds 9455 */ 9456 static void 9457 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9458 { 9459 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9460 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9461 9462 mutex_enter(&pptr->port_mutex); 9463 mutex_enter(&ptgt->tgt_mutex); 9464 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9465 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9466 fcp_trace, FCP_BUF_LEVEL_2, 0, 9467 "fcp_queue_ipkt,1:state change occured" 9468 " for D_ID=0x%x", ptgt->tgt_d_id); 9469 mutex_exit(&ptgt->tgt_mutex); 9470 mutex_exit(&pptr->port_mutex); 9471 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9472 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9473 fcp_icmd_free(pptr, icmd); 9474 return; 9475 } 9476 mutex_exit(&ptgt->tgt_mutex); 9477 9478 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9479 9480 if (pptr->port_ipkt_list != NULL) { 9481 /* add pkt to front of doubly-linked list */ 9482 pptr->port_ipkt_list->ipkt_prev = icmd; 9483 icmd->ipkt_next = pptr->port_ipkt_list; 9484 pptr->port_ipkt_list = icmd; 9485 icmd->ipkt_prev = NULL; 9486 } else { 9487 /* this is the first/only pkt on the list */ 9488 pptr->port_ipkt_list = icmd; 9489 icmd->ipkt_next = NULL; 9490 icmd->ipkt_prev = NULL; 9491 } 9492 mutex_exit(&pptr->port_mutex); 9493 } 9494 9495 /* 9496 * Function: fcp_transport 9497 * 9498 * Description: This function submits the Fibre Channel packet to the transort 9499 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9500 * fails the submission, the treatment depends on the value of 9501 * the variable internal. 9502 * 9503 * Argument: port_handle fp/fctl port handle. 9504 * *fpkt Packet to submit to the transport layer. 9505 * internal Not zero when it's an internal packet. 9506 * 9507 * Return Value: FC_TRAN_BUSY 9508 * FC_STATEC_BUSY 9509 * FC_OFFLINE 9510 * FC_LOGINREQ 9511 * FC_DEVICE_BUSY 9512 * FC_SUCCESS 9513 */ 9514 static int 9515 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9516 { 9517 int rval; 9518 9519 rval = fc_ulp_transport(port_handle, fpkt); 9520 if (rval == FC_SUCCESS) { 9521 return (rval); 9522 } 9523 9524 /* 9525 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9526 * a command, if the underlying modules see that there is a state 9527 * change, or if a port is OFFLINE, that means, that state change 9528 * hasn't reached FCP yet, so re-queue the command for deferred 9529 * submission. 9530 */ 9531 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9532 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9533 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9534 /* 9535 * Defer packet re-submission. Life hang is possible on 9536 * internal commands if the port driver sends FC_STATEC_BUSY 9537 * for ever, but that shouldn't happen in a good environment. 9538 * Limiting re-transport for internal commands is probably a 9539 * good idea.. 9540 * A race condition can happen when a port sees barrage of 9541 * link transitions offline to online. If the FCTL has 9542 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9543 * internal commands should be queued to do the discovery. 9544 * The race condition is when an online comes and FCP starts 9545 * its internal discovery and the link goes offline. It is 9546 * possible that the statec_callback has not reached FCP 9547 * and FCP is carrying on with its internal discovery. 9548 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9549 * that the link has gone offline. At this point FCP should 9550 * drop all the internal commands and wait for the 9551 * statec_callback. It will be facilitated by incrementing 9552 * port_link_cnt. 9553 * 9554 * For external commands, the (FC)pkt_timeout is decremented 9555 * by the QUEUE Delay added by our driver, Care is taken to 9556 * ensure that it doesn't become zero (zero means no timeout) 9557 * If the time expires right inside driver queue itself, 9558 * the watch thread will return it to the original caller 9559 * indicating that the command has timed-out. 9560 */ 9561 if (internal) { 9562 char *op; 9563 struct fcp_ipkt *icmd; 9564 9565 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9566 switch (icmd->ipkt_opcode) { 9567 case SCMD_REPORT_LUN: 9568 op = "REPORT LUN"; 9569 break; 9570 9571 case SCMD_INQUIRY: 9572 op = "INQUIRY"; 9573 break; 9574 9575 case SCMD_INQUIRY_PAGE83: 9576 op = "INQUIRY-83"; 9577 break; 9578 9579 default: 9580 op = "Internal SCSI COMMAND"; 9581 break; 9582 } 9583 9584 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9585 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9586 rval = FC_SUCCESS; 9587 } 9588 } else { 9589 struct fcp_pkt *cmd; 9590 struct fcp_port *pptr; 9591 9592 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9593 cmd->cmd_state = FCP_PKT_IDLE; 9594 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9595 9596 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9597 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9598 fcp_trace, FCP_BUF_LEVEL_9, 0, 9599 "fcp_transport: xport busy for pkt %p", 9600 cmd->cmd_pkt); 9601 rval = FC_TRAN_BUSY; 9602 } else { 9603 fcp_queue_pkt(pptr, cmd); 9604 rval = FC_SUCCESS; 9605 } 9606 } 9607 } 9608 9609 return (rval); 9610 } 9611 9612 /*VARARGS3*/ 9613 static void 9614 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9615 { 9616 char buf[256]; 9617 va_list ap; 9618 9619 if (dip == NULL) { 9620 dip = fcp_global_dip; 9621 } 9622 9623 va_start(ap, fmt); 9624 (void) vsprintf(buf, fmt, ap); 9625 va_end(ap); 9626 9627 scsi_log(dip, "fcp", level, buf); 9628 } 9629 9630 /* 9631 * This function retries NS registry of FC4 type. 9632 * It assumes that fcp_mutex is held. 9633 * The function does nothing if topology is not fabric 9634 * So, the topology has to be set before this function can be called 9635 */ 9636 static void 9637 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9638 { 9639 int rval; 9640 9641 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9642 9643 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9644 ((pptr->port_topology != FC_TOP_FABRIC) && 9645 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9646 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9647 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9648 } 9649 return; 9650 } 9651 mutex_exit(&pptr->port_mutex); 9652 rval = fcp_do_ns_registry(pptr, s_id); 9653 mutex_enter(&pptr->port_mutex); 9654 9655 if (rval == 0) { 9656 /* Registry successful. Reset flag */ 9657 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9658 } 9659 } 9660 9661 /* 9662 * This function registers the ULP with the switch by calling transport i/f 9663 */ 9664 static int 9665 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9666 { 9667 fc_ns_cmd_t ns_cmd; 9668 ns_rfc_type_t rfc; 9669 uint32_t types[8]; 9670 9671 /* 9672 * Prepare the Name server structure to 9673 * register with the transport in case of 9674 * Fabric configuration. 9675 */ 9676 bzero(&rfc, sizeof (rfc)); 9677 bzero(types, sizeof (types)); 9678 9679 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9680 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9681 9682 rfc.rfc_port_id.port_id = s_id; 9683 bcopy(types, rfc.rfc_types, sizeof (types)); 9684 9685 ns_cmd.ns_flags = 0; 9686 ns_cmd.ns_cmd = NS_RFT_ID; 9687 ns_cmd.ns_req_len = sizeof (rfc); 9688 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9689 ns_cmd.ns_resp_len = 0; 9690 ns_cmd.ns_resp_payload = NULL; 9691 9692 /* 9693 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9694 */ 9695 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9696 fcp_log(CE_WARN, pptr->port_dip, 9697 "!ns_registry: failed name server registration"); 9698 return (1); 9699 } 9700 9701 return (0); 9702 } 9703 9704 /* 9705 * Function: fcp_handle_port_attach 9706 * 9707 * Description: This function is called from fcp_port_attach() to attach a 9708 * new port. This routine does the following: 9709 * 9710 * 1) Allocates an fcp_port structure and initializes it. 9711 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9712 * server. 9713 * 3) Kicks off the enumeration of the targets/luns visible 9714 * through this new port. That is done by calling 9715 * fcp_statec_callback() if the port is online. 9716 * 9717 * Argument: ulph fp/fctl port handle. 9718 * *pinfo Port information. 9719 * s_id Port ID. 9720 * instance Device instance number for the local port 9721 * (returned by ddi_get_instance()). 9722 * 9723 * Return Value: DDI_SUCCESS 9724 * DDI_FAILURE 9725 * 9726 * Context: User and Kernel context. 9727 */ 9728 /*ARGSUSED*/ 9729 int 9730 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9731 uint32_t s_id, int instance) 9732 { 9733 int res = DDI_FAILURE; 9734 scsi_hba_tran_t *tran; 9735 int mutex_initted = FALSE; 9736 int hba_attached = FALSE; 9737 int soft_state_linked = FALSE; 9738 int event_bind = FALSE; 9739 struct fcp_port *pptr; 9740 fc_portmap_t *tmp_list = NULL; 9741 uint32_t max_cnt, alloc_cnt; 9742 uchar_t *boot_wwn = NULL; 9743 uint_t nbytes; 9744 int manual_cfg; 9745 9746 /* 9747 * this port instance attaching for the first time (or after 9748 * being detached before) 9749 */ 9750 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9751 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9752 9753 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9754 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9755 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9756 instance); 9757 return (res); 9758 } 9759 9760 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9761 /* this shouldn't happen */ 9762 ddi_soft_state_free(fcp_softstate, instance); 9763 cmn_err(CE_WARN, "fcp: bad soft state"); 9764 return (res); 9765 } 9766 9767 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9768 9769 /* 9770 * Make a copy of ulp_port_info as fctl allocates 9771 * a temp struct. 9772 */ 9773 (void) fcp_cp_pinfo(pptr, pinfo); 9774 9775 /* 9776 * Check for manual_configuration_only property. 9777 * Enable manual configurtion if the property is 9778 * set to 1, otherwise disable manual configuration. 9779 */ 9780 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9781 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9782 MANUAL_CFG_ONLY, 9783 -1)) != -1) { 9784 if (manual_cfg == 1) { 9785 char *pathname; 9786 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9787 (void) ddi_pathname(pptr->port_dip, pathname); 9788 cmn_err(CE_NOTE, 9789 "%s (%s%d) %s is enabled via %s.conf.", 9790 pathname, 9791 ddi_driver_name(pptr->port_dip), 9792 ddi_get_instance(pptr->port_dip), 9793 MANUAL_CFG_ONLY, 9794 ddi_driver_name(pptr->port_dip)); 9795 fcp_enable_auto_configuration = 0; 9796 kmem_free(pathname, MAXPATHLEN); 9797 } 9798 } 9799 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9800 pptr->port_link_cnt = 1; 9801 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9802 pptr->port_id = s_id; 9803 pptr->port_instance = instance; 9804 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9805 pptr->port_state = FCP_STATE_INIT; 9806 if (pinfo->port_acc_attr == NULL) { 9807 /* 9808 * The corresponding FCA doesn't support DMA at all 9809 */ 9810 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9811 } 9812 9813 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9814 9815 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9816 /* 9817 * If FCA supports DMA in SCSI data phase, we need preallocate 9818 * dma cookie, so stash the cookie size 9819 */ 9820 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9821 pptr->port_data_dma_attr.dma_attr_sgllen; 9822 } 9823 9824 /* 9825 * The two mutexes of fcp_port are initialized. The variable 9826 * mutex_initted is incremented to remember that fact. That variable 9827 * is checked when the routine fails and the mutexes have to be 9828 * destroyed. 9829 */ 9830 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9831 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9832 mutex_initted++; 9833 9834 /* 9835 * The SCSI tran structure is allocate and initialized now. 9836 */ 9837 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9838 fcp_log(CE_WARN, pptr->port_dip, 9839 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9840 goto fail; 9841 } 9842 9843 /* link in the transport structure then fill it in */ 9844 pptr->port_tran = tran; 9845 tran->tran_hba_private = pptr; 9846 tran->tran_tgt_init = fcp_scsi_tgt_init; 9847 tran->tran_tgt_probe = NULL; 9848 tran->tran_tgt_free = fcp_scsi_tgt_free; 9849 tran->tran_start = fcp_scsi_start; 9850 tran->tran_reset = fcp_scsi_reset; 9851 tran->tran_abort = fcp_scsi_abort; 9852 tran->tran_getcap = fcp_scsi_getcap; 9853 tran->tran_setcap = fcp_scsi_setcap; 9854 tran->tran_init_pkt = NULL; 9855 tran->tran_destroy_pkt = NULL; 9856 tran->tran_dmafree = NULL; 9857 tran->tran_sync_pkt = NULL; 9858 tran->tran_reset_notify = fcp_scsi_reset_notify; 9859 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9860 tran->tran_get_name = fcp_scsi_get_name; 9861 tran->tran_clear_aca = NULL; 9862 tran->tran_clear_task_set = NULL; 9863 tran->tran_terminate_task = NULL; 9864 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9865 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9866 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9867 tran->tran_post_event = fcp_scsi_bus_post_event; 9868 tran->tran_quiesce = NULL; 9869 tran->tran_unquiesce = NULL; 9870 tran->tran_bus_reset = NULL; 9871 tran->tran_bus_config = fcp_scsi_bus_config; 9872 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9873 tran->tran_bus_power = NULL; 9874 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9875 9876 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9877 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9878 tran->tran_setup_pkt = fcp_pkt_setup; 9879 tran->tran_teardown_pkt = fcp_pkt_teardown; 9880 tran->tran_hba_len = pptr->port_priv_pkt_len + 9881 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9882 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9883 /* 9884 * If FCA don't support DMA, then we use different vectors to 9885 * minimize the effects on DMA code flow path 9886 */ 9887 tran->tran_start = fcp_pseudo_start; 9888 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9889 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9890 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9891 tran->tran_dmafree = fcp_pseudo_dmafree; 9892 tran->tran_setup_pkt = NULL; 9893 tran->tran_teardown_pkt = NULL; 9894 tran->tran_pkt_constructor = NULL; 9895 tran->tran_pkt_destructor = NULL; 9896 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9897 } 9898 9899 /* 9900 * Allocate an ndi event handle 9901 */ 9902 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9903 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9904 9905 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9906 sizeof (fcp_ndi_event_defs)); 9907 9908 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9909 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9910 9911 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9912 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9913 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9914 9915 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9916 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9917 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9918 goto fail; 9919 } 9920 event_bind++; /* Checked in fail case */ 9921 9922 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9923 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9924 != DDI_SUCCESS) { 9925 fcp_log(CE_WARN, pptr->port_dip, 9926 "!fcp%d: scsi_hba_attach_setup failed", instance); 9927 goto fail; 9928 } 9929 hba_attached++; /* Checked in fail case */ 9930 9931 pptr->port_mpxio = 0; 9932 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9933 MDI_SUCCESS) { 9934 pptr->port_mpxio++; 9935 } 9936 9937 /* 9938 * The following code is putting the new port structure in the global 9939 * list of ports and, if it is the first port to attach, it start the 9940 * fcp_watchdog_tick. 9941 * 9942 * Why put this new port in the global before we are done attaching it? 9943 * We are actually making the structure globally known before we are 9944 * done attaching it. The reason for that is: because of the code that 9945 * follows. At this point the resources to handle the port are 9946 * allocated. This function is now going to do the following: 9947 * 9948 * 1) It is going to try to register with the name server advertizing 9949 * the new FCP capability of the port. 9950 * 2) It is going to play the role of the fp/fctl layer by building 9951 * a list of worlwide names reachable through this port and call 9952 * itself on fcp_statec_callback(). That requires the port to 9953 * be part of the global list. 9954 */ 9955 mutex_enter(&fcp_global_mutex); 9956 if (fcp_port_head == NULL) { 9957 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9958 } 9959 pptr->port_next = fcp_port_head; 9960 fcp_port_head = pptr; 9961 soft_state_linked++; 9962 9963 if (fcp_watchdog_init++ == 0) { 9964 fcp_watchdog_tick = fcp_watchdog_timeout * 9965 drv_usectohz(1000000); 9966 fcp_watchdog_id = timeout(fcp_watch, NULL, 9967 fcp_watchdog_tick); 9968 } 9969 mutex_exit(&fcp_global_mutex); 9970 9971 /* 9972 * Here an attempt is made to register with the name server, the new 9973 * FCP capability. That is done using an RTF_ID to the name server. 9974 * It is done synchronously. The function fcp_do_ns_registry() 9975 * doesn't return till the name server responded. 9976 * On failures, just ignore it for now and it will get retried during 9977 * state change callbacks. We'll set a flag to show this failure 9978 */ 9979 if (fcp_do_ns_registry(pptr, s_id)) { 9980 mutex_enter(&pptr->port_mutex); 9981 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 9982 mutex_exit(&pptr->port_mutex); 9983 } else { 9984 mutex_enter(&pptr->port_mutex); 9985 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9986 mutex_exit(&pptr->port_mutex); 9987 } 9988 9989 /* 9990 * Lookup for boot WWN property 9991 */ 9992 if (modrootloaded != 1) { 9993 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 9994 ddi_get_parent(pinfo->port_dip), 9995 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 9996 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 9997 (nbytes == FC_WWN_SIZE)) { 9998 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 9999 } 10000 if (boot_wwn) { 10001 ddi_prop_free(boot_wwn); 10002 } 10003 } 10004 10005 /* 10006 * Handle various topologies and link states. 10007 */ 10008 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10009 case FC_STATE_OFFLINE: 10010 10011 /* 10012 * we're attaching a port where the link is offline 10013 * 10014 * Wait for ONLINE, at which time a state 10015 * change will cause a statec_callback 10016 * 10017 * in the mean time, do not do anything 10018 */ 10019 res = DDI_SUCCESS; 10020 pptr->port_state |= FCP_STATE_OFFLINE; 10021 break; 10022 10023 case FC_STATE_ONLINE: { 10024 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10025 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10026 res = DDI_SUCCESS; 10027 break; 10028 } 10029 /* 10030 * discover devices and create nodes (a private 10031 * loop or point-to-point) 10032 */ 10033 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10034 10035 /* 10036 * At this point we are going to build a list of all the ports 10037 * that can be reached through this local port. It looks like 10038 * we cannot handle more than FCP_MAX_DEVICES per local port 10039 * (128). 10040 */ 10041 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10042 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10043 KM_NOSLEEP)) == NULL) { 10044 fcp_log(CE_WARN, pptr->port_dip, 10045 "!fcp%d: failed to allocate portmap", 10046 instance); 10047 goto fail; 10048 } 10049 10050 /* 10051 * fc_ulp_getportmap() is going to provide us with the list of 10052 * remote ports in the buffer we just allocated. The way the 10053 * list is going to be retrieved depends on the topology. 10054 * However, if we are connected to a Fabric, a name server 10055 * request may be sent to get the list of FCP capable ports. 10056 * It should be noted that is the case the request is 10057 * synchronous. This means we are stuck here till the name 10058 * server replies. A lot of things can change during that time 10059 * and including, may be, being called on 10060 * fcp_statec_callback() for different reasons. I'm not sure 10061 * the code can handle that. 10062 */ 10063 max_cnt = FCP_MAX_DEVICES; 10064 alloc_cnt = FCP_MAX_DEVICES; 10065 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10066 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10067 FC_SUCCESS) { 10068 caddr_t msg; 10069 10070 (void) fc_ulp_error(res, &msg); 10071 10072 /* 10073 * this just means the transport is 10074 * busy perhaps building a portmap so, 10075 * for now, succeed this port attach 10076 * when the transport has a new map, 10077 * it'll send us a state change then 10078 */ 10079 fcp_log(CE_WARN, pptr->port_dip, 10080 "!failed to get port map : %s", msg); 10081 10082 res = DDI_SUCCESS; 10083 break; /* go return result */ 10084 } 10085 if (max_cnt > alloc_cnt) { 10086 alloc_cnt = max_cnt; 10087 } 10088 10089 /* 10090 * We are now going to call fcp_statec_callback() ourselves. 10091 * By issuing this call we are trying to kick off the enumera- 10092 * tion process. 10093 */ 10094 /* 10095 * let the state change callback do the SCSI device 10096 * discovery and create the devinfos 10097 */ 10098 fcp_statec_callback(ulph, pptr->port_fp_handle, 10099 pptr->port_phys_state, pptr->port_topology, tmp_list, 10100 max_cnt, pptr->port_id); 10101 10102 res = DDI_SUCCESS; 10103 break; 10104 } 10105 10106 default: 10107 /* unknown port state */ 10108 fcp_log(CE_WARN, pptr->port_dip, 10109 "!fcp%d: invalid port state at attach=0x%x", 10110 instance, pptr->port_phys_state); 10111 10112 mutex_enter(&pptr->port_mutex); 10113 pptr->port_phys_state = FCP_STATE_OFFLINE; 10114 mutex_exit(&pptr->port_mutex); 10115 10116 res = DDI_SUCCESS; 10117 break; 10118 } 10119 10120 /* free temp list if used */ 10121 if (tmp_list != NULL) { 10122 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10123 } 10124 10125 /* note the attach time */ 10126 pptr->port_attach_time = ddi_get_lbolt64(); 10127 10128 /* all done */ 10129 return (res); 10130 10131 /* a failure we have to clean up after */ 10132 fail: 10133 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10134 10135 if (soft_state_linked) { 10136 /* remove this fcp_port from the linked list */ 10137 (void) fcp_soft_state_unlink(pptr); 10138 } 10139 10140 /* unbind and free event set */ 10141 if (pptr->port_ndi_event_hdl) { 10142 if (event_bind) { 10143 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10144 &pptr->port_ndi_events, NDI_SLEEP); 10145 } 10146 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10147 } 10148 10149 if (pptr->port_ndi_event_defs) { 10150 (void) kmem_free(pptr->port_ndi_event_defs, 10151 sizeof (fcp_ndi_event_defs)); 10152 } 10153 10154 /* 10155 * Clean up mpxio stuff 10156 */ 10157 if (pptr->port_mpxio) { 10158 (void) mdi_phci_unregister(pptr->port_dip, 0); 10159 pptr->port_mpxio--; 10160 } 10161 10162 /* undo SCSI HBA setup */ 10163 if (hba_attached) { 10164 (void) scsi_hba_detach(pptr->port_dip); 10165 } 10166 if (pptr->port_tran != NULL) { 10167 scsi_hba_tran_free(pptr->port_tran); 10168 } 10169 10170 mutex_enter(&fcp_global_mutex); 10171 10172 /* 10173 * We check soft_state_linked, because it is incremented right before 10174 * we call increment fcp_watchdog_init. Therefore, we know if 10175 * soft_state_linked is still FALSE, we do not want to decrement 10176 * fcp_watchdog_init or possibly call untimeout. 10177 */ 10178 10179 if (soft_state_linked) { 10180 if (--fcp_watchdog_init == 0) { 10181 timeout_id_t tid = fcp_watchdog_id; 10182 10183 mutex_exit(&fcp_global_mutex); 10184 (void) untimeout(tid); 10185 } else { 10186 mutex_exit(&fcp_global_mutex); 10187 } 10188 } else { 10189 mutex_exit(&fcp_global_mutex); 10190 } 10191 10192 if (mutex_initted) { 10193 mutex_destroy(&pptr->port_mutex); 10194 mutex_destroy(&pptr->port_pkt_mutex); 10195 } 10196 10197 if (tmp_list != NULL) { 10198 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10199 } 10200 10201 /* this makes pptr invalid */ 10202 ddi_soft_state_free(fcp_softstate, instance); 10203 10204 return (DDI_FAILURE); 10205 } 10206 10207 10208 static int 10209 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10210 { 10211 int count = 0; 10212 10213 mutex_enter(&pptr->port_mutex); 10214 10215 /* 10216 * if the port is powered down or suspended, nothing else 10217 * to do; just return. 10218 */ 10219 if (flag != FCP_STATE_DETACHING) { 10220 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10221 FCP_STATE_SUSPENDED)) { 10222 pptr->port_state |= flag; 10223 mutex_exit(&pptr->port_mutex); 10224 return (FC_SUCCESS); 10225 } 10226 } 10227 10228 if (pptr->port_state & FCP_STATE_IN_MDI) { 10229 mutex_exit(&pptr->port_mutex); 10230 return (FC_FAILURE); 10231 } 10232 10233 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10234 fcp_trace, FCP_BUF_LEVEL_2, 0, 10235 "fcp_handle_port_detach: port is detaching"); 10236 10237 pptr->port_state |= flag; 10238 10239 /* 10240 * Wait for any ongoing reconfig/ipkt to complete, that 10241 * ensures the freeing to targets/luns is safe. 10242 * No more ref to this port should happen from statec/ioctl 10243 * after that as it was removed from the global port list. 10244 */ 10245 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10246 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10247 /* 10248 * Let's give sufficient time for reconfig/ipkt 10249 * to complete. 10250 */ 10251 if (count++ >= FCP_ICMD_DEADLINE) { 10252 break; 10253 } 10254 mutex_exit(&pptr->port_mutex); 10255 delay(drv_usectohz(1000000)); 10256 mutex_enter(&pptr->port_mutex); 10257 } 10258 10259 /* 10260 * if the driver is still busy then fail to 10261 * suspend/power down. 10262 */ 10263 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10264 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10265 pptr->port_state &= ~flag; 10266 mutex_exit(&pptr->port_mutex); 10267 return (FC_FAILURE); 10268 } 10269 10270 if (flag == FCP_STATE_DETACHING) { 10271 pptr = fcp_soft_state_unlink(pptr); 10272 ASSERT(pptr != NULL); 10273 } 10274 10275 pptr->port_link_cnt++; 10276 pptr->port_state |= FCP_STATE_OFFLINE; 10277 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10278 10279 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10280 FCP_CAUSE_LINK_DOWN); 10281 mutex_exit(&pptr->port_mutex); 10282 10283 /* kill watch dog timer if we're the last */ 10284 mutex_enter(&fcp_global_mutex); 10285 if (--fcp_watchdog_init == 0) { 10286 timeout_id_t tid = fcp_watchdog_id; 10287 mutex_exit(&fcp_global_mutex); 10288 (void) untimeout(tid); 10289 } else { 10290 mutex_exit(&fcp_global_mutex); 10291 } 10292 10293 /* clean up the port structures */ 10294 if (flag == FCP_STATE_DETACHING) { 10295 fcp_cleanup_port(pptr, instance); 10296 } 10297 10298 return (FC_SUCCESS); 10299 } 10300 10301 10302 static void 10303 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10304 { 10305 ASSERT(pptr != NULL); 10306 10307 /* unbind and free event set */ 10308 if (pptr->port_ndi_event_hdl) { 10309 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10310 &pptr->port_ndi_events, NDI_SLEEP); 10311 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10312 } 10313 10314 if (pptr->port_ndi_event_defs) { 10315 (void) kmem_free(pptr->port_ndi_event_defs, 10316 sizeof (fcp_ndi_event_defs)); 10317 } 10318 10319 /* free the lun/target structures and devinfos */ 10320 fcp_free_targets(pptr); 10321 10322 /* 10323 * Clean up mpxio stuff 10324 */ 10325 if (pptr->port_mpxio) { 10326 (void) mdi_phci_unregister(pptr->port_dip, 0); 10327 pptr->port_mpxio--; 10328 } 10329 10330 /* clean up SCSA stuff */ 10331 (void) scsi_hba_detach(pptr->port_dip); 10332 if (pptr->port_tran != NULL) { 10333 scsi_hba_tran_free(pptr->port_tran); 10334 } 10335 10336 #ifdef KSTATS_CODE 10337 /* clean up kstats */ 10338 if (pptr->fcp_ksp != NULL) { 10339 kstat_delete(pptr->fcp_ksp); 10340 } 10341 #endif 10342 10343 /* clean up soft state mutexes/condition variables */ 10344 mutex_destroy(&pptr->port_mutex); 10345 mutex_destroy(&pptr->port_pkt_mutex); 10346 10347 /* all done with soft state */ 10348 ddi_soft_state_free(fcp_softstate, instance); 10349 } 10350 10351 /* 10352 * Function: fcp_kmem_cache_constructor 10353 * 10354 * Description: This function allocates and initializes the resources required 10355 * to build a scsi_pkt structure the target driver. The result 10356 * of the allocation and initialization will be cached in the 10357 * memory cache. As DMA resources may be allocated here, that 10358 * means DMA resources will be tied up in the cache manager. 10359 * This is a tradeoff that has been made for performance reasons. 10360 * 10361 * Argument: *buf Memory to preinitialize. 10362 * *arg FCP port structure (fcp_port). 10363 * kmflags Value passed to kmem_cache_alloc() and 10364 * propagated to the constructor. 10365 * 10366 * Return Value: 0 Allocation/Initialization was successful. 10367 * -1 Allocation or Initialization failed. 10368 * 10369 * 10370 * If the returned value is 0, the buffer is initialized like this: 10371 * 10372 * +================================+ 10373 * +----> | struct scsi_pkt | 10374 * | | | 10375 * | +--- | pkt_ha_private | 10376 * | | | | 10377 * | | +================================+ 10378 * | | 10379 * | | +================================+ 10380 * | +--> | struct fcp_pkt | <---------+ 10381 * | | | | 10382 * +----- | cmd_pkt | | 10383 * | cmd_fp_pkt | ---+ | 10384 * +-------->| cmd_fcp_rsp[] | | | 10385 * | +--->| cmd_fcp_cmd[] | | | 10386 * | | |--------------------------------| | | 10387 * | | | struct fc_packet | <--+ | 10388 * | | | | | 10389 * | | | pkt_ulp_private | ----------+ 10390 * | | | pkt_fca_private | -----+ 10391 * | | | pkt_data_cookie | ---+ | 10392 * | | | pkt_cmdlen | | | 10393 * | |(a) | pkt_rsplen | | | 10394 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10395 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10396 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10397 * | pkt_resp_cookie | ---|-|--+ | | | 10398 * | pkt_cmd_dma | | | | | | | 10399 * | pkt_cmd_acc | | | | | | | 10400 * +================================+ | | | | | | 10401 * | dma_cookies | <--+ | | | | | 10402 * | | | | | | | 10403 * +================================+ | | | | | 10404 * | fca_private | <----+ | | | | 10405 * | | | | | | 10406 * +================================+ | | | | 10407 * | | | | 10408 * | | | | 10409 * +================================+ (d) | | | | 10410 * | fcp_resp cookies | <-------+ | | | 10411 * | | | | | 10412 * +================================+ | | | 10413 * | | | 10414 * +================================+ (d) | | | 10415 * | fcp_resp | <-----------+ | | 10416 * | (DMA resources associated) | | | 10417 * +================================+ | | 10418 * | | 10419 * | | 10420 * | | 10421 * +================================+ (c) | | 10422 * | fcp_cmd cookies | <---------------+ | 10423 * | | | 10424 * +================================+ | 10425 * | 10426 * +================================+ (c) | 10427 * | fcp_cmd | <--------------------+ 10428 * | (DMA resources associated) | 10429 * +================================+ 10430 * 10431 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10432 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10433 * (c) Only if DMA is used for the FCP_CMD buffer. 10434 * (d) Only if DMA is used for the FCP_RESP buffer 10435 */ 10436 static int 10437 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10438 int kmflags) 10439 { 10440 struct fcp_pkt *cmd; 10441 struct fcp_port *pptr; 10442 fc_packet_t *fpkt; 10443 10444 pptr = (struct fcp_port *)tran->tran_hba_private; 10445 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10446 bzero(cmd, tran->tran_hba_len); 10447 10448 cmd->cmd_pkt = pkt; 10449 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10450 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10451 cmd->cmd_fp_pkt = fpkt; 10452 10453 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10454 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10455 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10456 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10457 10458 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10459 sizeof (struct fcp_pkt)); 10460 10461 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10462 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10463 10464 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10465 /* 10466 * The underlying HBA doesn't want to DMA the fcp_cmd or 10467 * fcp_resp. The transfer of information will be done by 10468 * bcopy. 10469 * The naming of the flags (that is actually a value) is 10470 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10471 * DMA" but instead "NO DMA". 10472 */ 10473 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10474 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10475 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10476 } else { 10477 /* 10478 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10479 * buffer. A buffer is allocated for each one the ddi_dma_* 10480 * interfaces. 10481 */ 10482 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10483 return (-1); 10484 } 10485 } 10486 10487 return (0); 10488 } 10489 10490 /* 10491 * Function: fcp_kmem_cache_destructor 10492 * 10493 * Description: Called by the destructor of the cache managed by SCSA. 10494 * All the resources pre-allocated in fcp_pkt_constructor 10495 * and the data also pre-initialized in fcp_pkt_constructor 10496 * are freed and uninitialized here. 10497 * 10498 * Argument: *buf Memory to uninitialize. 10499 * *arg FCP port structure (fcp_port). 10500 * 10501 * Return Value: None 10502 * 10503 * Context: kernel 10504 */ 10505 static void 10506 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10507 { 10508 struct fcp_pkt *cmd; 10509 struct fcp_port *pptr; 10510 10511 pptr = (struct fcp_port *)(tran->tran_hba_private); 10512 cmd = pkt->pkt_ha_private; 10513 10514 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10515 /* 10516 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10517 * buffer and DMA resources allocated to do so are released. 10518 */ 10519 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10520 } 10521 } 10522 10523 /* 10524 * Function: fcp_alloc_cmd_resp 10525 * 10526 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10527 * will be DMAed by the HBA. The buffer is allocated applying 10528 * the DMA requirements for the HBA. The buffers allocated will 10529 * also be bound. DMA resources are allocated in the process. 10530 * They will be released by fcp_free_cmd_resp(). 10531 * 10532 * Argument: *pptr FCP port. 10533 * *fpkt fc packet for which the cmd and resp packet should be 10534 * allocated. 10535 * flags Allocation flags. 10536 * 10537 * Return Value: FC_FAILURE 10538 * FC_SUCCESS 10539 * 10540 * Context: User or Kernel context only if flags == KM_SLEEP. 10541 * Interrupt context if the KM_SLEEP is not specified. 10542 */ 10543 static int 10544 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10545 { 10546 int rval; 10547 int cmd_len; 10548 int resp_len; 10549 ulong_t real_len; 10550 int (*cb) (caddr_t); 10551 ddi_dma_cookie_t pkt_cookie; 10552 ddi_dma_cookie_t *cp; 10553 uint32_t cnt; 10554 10555 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10556 10557 cmd_len = fpkt->pkt_cmdlen; 10558 resp_len = fpkt->pkt_rsplen; 10559 10560 ASSERT(fpkt->pkt_cmd_dma == NULL); 10561 10562 /* Allocation of a DMA handle used in subsequent calls. */ 10563 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10564 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10565 return (FC_FAILURE); 10566 } 10567 10568 /* A buffer is allocated that satisfies the DMA requirements. */ 10569 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10570 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10571 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10572 10573 if (rval != DDI_SUCCESS) { 10574 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10575 return (FC_FAILURE); 10576 } 10577 10578 if (real_len < cmd_len) { 10579 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10580 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10581 return (FC_FAILURE); 10582 } 10583 10584 /* The buffer allocated is DMA bound. */ 10585 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10586 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10587 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10588 10589 if (rval != DDI_DMA_MAPPED) { 10590 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10591 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10592 return (FC_FAILURE); 10593 } 10594 10595 if (fpkt->pkt_cmd_cookie_cnt > 10596 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10597 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10598 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10599 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10600 return (FC_FAILURE); 10601 } 10602 10603 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10604 10605 /* 10606 * The buffer where the scatter/gather list is going to be built is 10607 * allocated. 10608 */ 10609 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10610 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10611 KM_NOSLEEP); 10612 10613 if (cp == NULL) { 10614 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10615 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10616 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10617 return (FC_FAILURE); 10618 } 10619 10620 /* 10621 * The scatter/gather list for the buffer we just allocated is built 10622 * here. 10623 */ 10624 *cp = pkt_cookie; 10625 cp++; 10626 10627 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10628 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10629 &pkt_cookie); 10630 *cp = pkt_cookie; 10631 } 10632 10633 ASSERT(fpkt->pkt_resp_dma == NULL); 10634 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10635 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10636 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10637 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10638 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10639 return (FC_FAILURE); 10640 } 10641 10642 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10643 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10644 (caddr_t *)&fpkt->pkt_resp, &real_len, 10645 &fpkt->pkt_resp_acc); 10646 10647 if (rval != DDI_SUCCESS) { 10648 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10649 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10650 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10651 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10652 kmem_free(fpkt->pkt_cmd_cookie, 10653 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10654 return (FC_FAILURE); 10655 } 10656 10657 if (real_len < resp_len) { 10658 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10659 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10660 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10661 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10662 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10663 kmem_free(fpkt->pkt_cmd_cookie, 10664 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10665 return (FC_FAILURE); 10666 } 10667 10668 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10669 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10670 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10671 10672 if (rval != DDI_DMA_MAPPED) { 10673 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10674 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10675 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10676 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10677 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10678 kmem_free(fpkt->pkt_cmd_cookie, 10679 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10680 return (FC_FAILURE); 10681 } 10682 10683 if (fpkt->pkt_resp_cookie_cnt > 10684 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10685 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10686 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10687 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10688 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10689 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10690 kmem_free(fpkt->pkt_cmd_cookie, 10691 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10692 return (FC_FAILURE); 10693 } 10694 10695 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10696 10697 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10698 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10699 KM_NOSLEEP); 10700 10701 if (cp == NULL) { 10702 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10703 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10704 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10705 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10706 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10707 kmem_free(fpkt->pkt_cmd_cookie, 10708 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10709 return (FC_FAILURE); 10710 } 10711 10712 *cp = pkt_cookie; 10713 cp++; 10714 10715 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10716 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10717 &pkt_cookie); 10718 *cp = pkt_cookie; 10719 } 10720 10721 return (FC_SUCCESS); 10722 } 10723 10724 /* 10725 * Function: fcp_free_cmd_resp 10726 * 10727 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10728 * allocated by fcp_alloc_cmd_resp() and all the resources 10729 * associated with them. That includes the DMA resources and the 10730 * buffer allocated for the cookies of each one of them. 10731 * 10732 * Argument: *pptr FCP port context. 10733 * *fpkt fc packet containing the cmd and resp packet 10734 * to be released. 10735 * 10736 * Return Value: None 10737 * 10738 * Context: Interrupt, User and Kernel context. 10739 */ 10740 /* ARGSUSED */ 10741 static void 10742 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10743 { 10744 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10745 10746 if (fpkt->pkt_resp_dma) { 10747 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10748 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10749 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10750 } 10751 10752 if (fpkt->pkt_resp_cookie) { 10753 kmem_free(fpkt->pkt_resp_cookie, 10754 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10755 fpkt->pkt_resp_cookie = NULL; 10756 } 10757 10758 if (fpkt->pkt_cmd_dma) { 10759 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10760 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10761 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10762 } 10763 10764 if (fpkt->pkt_cmd_cookie) { 10765 kmem_free(fpkt->pkt_cmd_cookie, 10766 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10767 fpkt->pkt_cmd_cookie = NULL; 10768 } 10769 } 10770 10771 10772 /* 10773 * called by the transport to do our own target initialization 10774 * 10775 * can acquire and release the global mutex 10776 */ 10777 /* ARGSUSED */ 10778 static int 10779 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10780 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10781 { 10782 uchar_t *bytes; 10783 uint_t nbytes; 10784 uint16_t lun_num; 10785 struct fcp_tgt *ptgt; 10786 struct fcp_lun *plun; 10787 struct fcp_port *pptr = (struct fcp_port *) 10788 hba_tran->tran_hba_private; 10789 10790 ASSERT(pptr != NULL); 10791 10792 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10793 FCP_BUF_LEVEL_8, 0, 10794 "fcp_phys_tgt_init: called for %s (instance %d)", 10795 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10796 10797 /* get our port WWN property */ 10798 bytes = NULL; 10799 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10800 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10801 (nbytes != FC_WWN_SIZE)) { 10802 /* no port WWN property */ 10803 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10804 FCP_BUF_LEVEL_8, 0, 10805 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10806 " for %s (instance %d): bytes=%p nbytes=%x", 10807 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10808 nbytes); 10809 10810 if (bytes != NULL) { 10811 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10812 } 10813 10814 return (DDI_NOT_WELL_FORMED); 10815 } 10816 ASSERT(bytes != NULL); 10817 10818 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10819 LUN_PROP, 0xFFFF); 10820 if (lun_num == 0xFFFF) { 10821 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10822 FCP_BUF_LEVEL_8, 0, 10823 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10824 " for %s (instance %d)", ddi_get_name(tgt_dip), 10825 ddi_get_instance(tgt_dip)); 10826 10827 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10828 return (DDI_NOT_WELL_FORMED); 10829 } 10830 10831 mutex_enter(&pptr->port_mutex); 10832 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10833 mutex_exit(&pptr->port_mutex); 10834 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10835 FCP_BUF_LEVEL_8, 0, 10836 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10837 " for %s (instance %d)", ddi_get_name(tgt_dip), 10838 ddi_get_instance(tgt_dip)); 10839 10840 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10841 return (DDI_FAILURE); 10842 } 10843 10844 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10845 FC_WWN_SIZE) == 0); 10846 ASSERT(plun->lun_num == lun_num); 10847 10848 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10849 10850 ptgt = plun->lun_tgt; 10851 10852 mutex_enter(&ptgt->tgt_mutex); 10853 plun->lun_tgt_count++; 10854 scsi_device_hba_private_set(sd, plun); 10855 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10856 plun->lun_sd = sd; 10857 mutex_exit(&ptgt->tgt_mutex); 10858 mutex_exit(&pptr->port_mutex); 10859 10860 return (DDI_SUCCESS); 10861 } 10862 10863 /*ARGSUSED*/ 10864 static int 10865 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10866 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10867 { 10868 uchar_t *bytes; 10869 uint_t nbytes; 10870 uint16_t lun_num; 10871 struct fcp_tgt *ptgt; 10872 struct fcp_lun *plun; 10873 struct fcp_port *pptr = (struct fcp_port *) 10874 hba_tran->tran_hba_private; 10875 child_info_t *cip; 10876 10877 ASSERT(pptr != NULL); 10878 10879 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10880 fcp_trace, FCP_BUF_LEVEL_8, 0, 10881 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10882 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10883 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10884 10885 cip = (child_info_t *)sd->sd_pathinfo; 10886 if (cip == NULL) { 10887 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10888 fcp_trace, FCP_BUF_LEVEL_8, 0, 10889 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10890 " for %s (instance %d)", ddi_get_name(tgt_dip), 10891 ddi_get_instance(tgt_dip)); 10892 10893 return (DDI_NOT_WELL_FORMED); 10894 } 10895 10896 /* get our port WWN property */ 10897 bytes = NULL; 10898 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10899 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10900 (nbytes != FC_WWN_SIZE)) { 10901 if (bytes) { 10902 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10903 } 10904 return (DDI_NOT_WELL_FORMED); 10905 } 10906 10907 ASSERT(bytes != NULL); 10908 10909 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10910 LUN_PROP, 0xFFFF); 10911 if (lun_num == 0xFFFF) { 10912 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10913 fcp_trace, FCP_BUF_LEVEL_8, 0, 10914 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10915 " for %s (instance %d)", ddi_get_name(tgt_dip), 10916 ddi_get_instance(tgt_dip)); 10917 10918 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10919 return (DDI_NOT_WELL_FORMED); 10920 } 10921 10922 mutex_enter(&pptr->port_mutex); 10923 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10924 mutex_exit(&pptr->port_mutex); 10925 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10926 fcp_trace, FCP_BUF_LEVEL_8, 0, 10927 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10928 " for %s (instance %d)", ddi_get_name(tgt_dip), 10929 ddi_get_instance(tgt_dip)); 10930 10931 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10932 return (DDI_FAILURE); 10933 } 10934 10935 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10936 FC_WWN_SIZE) == 0); 10937 ASSERT(plun->lun_num == lun_num); 10938 10939 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10940 10941 ptgt = plun->lun_tgt; 10942 10943 mutex_enter(&ptgt->tgt_mutex); 10944 plun->lun_tgt_count++; 10945 scsi_device_hba_private_set(sd, plun); 10946 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10947 plun->lun_sd = sd; 10948 mutex_exit(&ptgt->tgt_mutex); 10949 mutex_exit(&pptr->port_mutex); 10950 10951 return (DDI_SUCCESS); 10952 } 10953 10954 10955 /* 10956 * called by the transport to do our own target initialization 10957 * 10958 * can acquire and release the global mutex 10959 */ 10960 /* ARGSUSED */ 10961 static int 10962 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10963 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10964 { 10965 struct fcp_port *pptr = (struct fcp_port *) 10966 hba_tran->tran_hba_private; 10967 int rval; 10968 10969 ASSERT(pptr != NULL); 10970 10971 /* 10972 * Child node is getting initialized. Look at the mpxio component 10973 * type on the child device to see if this device is mpxio managed 10974 * or not. 10975 */ 10976 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 10977 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10978 } else { 10979 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10980 } 10981 10982 return (rval); 10983 } 10984 10985 10986 /* ARGSUSED */ 10987 static void 10988 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10989 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10990 { 10991 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 10992 struct fcp_tgt *ptgt; 10993 10994 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 10995 fcp_trace, FCP_BUF_LEVEL_8, 0, 10996 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 10997 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 10998 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10999 11000 if (plun == NULL) { 11001 return; 11002 } 11003 ptgt = plun->lun_tgt; 11004 11005 ASSERT(ptgt != NULL); 11006 11007 mutex_enter(&ptgt->tgt_mutex); 11008 ASSERT(plun->lun_tgt_count > 0); 11009 11010 if (--plun->lun_tgt_count == 0) { 11011 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11012 } 11013 plun->lun_sd = NULL; 11014 mutex_exit(&ptgt->tgt_mutex); 11015 } 11016 11017 /* 11018 * Function: fcp_scsi_start 11019 * 11020 * Description: This function is called by the target driver to request a 11021 * command to be sent. 11022 * 11023 * Argument: *ap SCSI address of the device. 11024 * *pkt SCSI packet containing the cmd to send. 11025 * 11026 * Return Value: TRAN_ACCEPT 11027 * TRAN_BUSY 11028 * TRAN_BADPKT 11029 * TRAN_FATAL_ERROR 11030 */ 11031 static int 11032 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11033 { 11034 struct fcp_port *pptr = ADDR2FCP(ap); 11035 struct fcp_lun *plun = ADDR2LUN(ap); 11036 struct fcp_pkt *cmd = PKT2CMD(pkt); 11037 struct fcp_tgt *ptgt = plun->lun_tgt; 11038 int rval; 11039 11040 /* ensure command isn't already issued */ 11041 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11042 11043 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11044 fcp_trace, FCP_BUF_LEVEL_9, 0, 11045 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11046 11047 /* 11048 * If the device is offline and is not in the process of coming 11049 * online, fail the request. 11050 */ 11051 mutex_enter(&plun->lun_mutex); 11052 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11053 !(plun->lun_state & FCP_LUN_ONLINING)) { 11054 mutex_exit(&plun->lun_mutex); 11055 if (cmd->cmd_fp_pkt->pkt_pd == NULL) 11056 pkt->pkt_reason = CMD_DEV_GONE; 11057 return (TRAN_FATAL_ERROR); 11058 } 11059 mutex_exit(&plun->lun_mutex); 11060 11061 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11062 11063 /* 11064 * If we are suspended, kernel is trying to dump, so don't 11065 * block, fail or defer requests - send them down right away. 11066 * NOTE: If we are in panic (i.e. trying to dump), we can't 11067 * assume we have been suspended. There is hardware such as 11068 * the v880 that doesn't do PM. Thus, the check for 11069 * ddi_in_panic. 11070 * 11071 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11072 * of changing. So, if we can queue the packet, do it. Eventually, 11073 * either the device will have gone away or changed and we can fail 11074 * the request, or we can proceed if the device didn't change. 11075 * 11076 * If the pd in the target or the packet is NULL it's probably 11077 * because the device has gone away, we allow the request to be 11078 * put on the internal queue here in case the device comes back within 11079 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11080 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11081 * could be NULL because the device was disappearing during or since 11082 * packet initialization. 11083 */ 11084 11085 mutex_enter(&pptr->port_mutex); 11086 mutex_enter(&ptgt->tgt_mutex); 11087 11088 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11089 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11090 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11091 (ptgt->tgt_pd_handle == NULL) || 11092 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11093 /* 11094 * If ((LUN is busy AND 11095 * LUN not suspended AND 11096 * The system is not in panic state) OR 11097 * (The port is coming up)) 11098 * 11099 * We check to see if the any of the flags FLAG_NOINTR or 11100 * FLAG_NOQUEUE is set. If one of them is set the value 11101 * returned will be TRAN_BUSY. If not, the request is queued. 11102 */ 11103 mutex_exit(&ptgt->tgt_mutex); 11104 mutex_exit(&pptr->port_mutex); 11105 11106 /* see if using interrupts is allowed (so queueing'll work) */ 11107 if (pkt->pkt_flags & FLAG_NOINTR) { 11108 pkt->pkt_resid = 0; 11109 return (TRAN_BUSY); 11110 } 11111 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11112 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11113 fcp_trace, FCP_BUF_LEVEL_9, 0, 11114 "fcp_scsi_start: lun busy for pkt %p", pkt); 11115 return (TRAN_BUSY); 11116 } 11117 #ifdef DEBUG 11118 mutex_enter(&pptr->port_pkt_mutex); 11119 pptr->port_npkts++; 11120 mutex_exit(&pptr->port_pkt_mutex); 11121 #endif /* DEBUG */ 11122 11123 /* got queue up the pkt for later */ 11124 fcp_queue_pkt(pptr, cmd); 11125 return (TRAN_ACCEPT); 11126 } 11127 cmd->cmd_state = FCP_PKT_ISSUED; 11128 11129 mutex_exit(&ptgt->tgt_mutex); 11130 mutex_exit(&pptr->port_mutex); 11131 11132 /* 11133 * Now that we released the mutexes, what was protected by them can 11134 * change. 11135 */ 11136 11137 /* 11138 * If there is a reconfiguration in progress, wait for it to complete. 11139 */ 11140 fcp_reconfig_wait(pptr); 11141 11142 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11143 pkt->pkt_time : 0; 11144 11145 /* prepare the packet */ 11146 11147 fcp_prepare_pkt(pptr, cmd, plun); 11148 11149 if (cmd->cmd_pkt->pkt_time) { 11150 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11151 } else { 11152 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11153 } 11154 11155 /* 11156 * if interrupts aren't allowed (e.g. at dump time) then we'll 11157 * have to do polled I/O 11158 */ 11159 if (pkt->pkt_flags & FLAG_NOINTR) { 11160 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11161 return (fcp_dopoll(pptr, cmd)); 11162 } 11163 11164 #ifdef DEBUG 11165 mutex_enter(&pptr->port_pkt_mutex); 11166 pptr->port_npkts++; 11167 mutex_exit(&pptr->port_pkt_mutex); 11168 #endif /* DEBUG */ 11169 11170 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11171 if (rval == FC_SUCCESS) { 11172 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11173 fcp_trace, FCP_BUF_LEVEL_9, 0, 11174 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11175 return (TRAN_ACCEPT); 11176 } 11177 11178 cmd->cmd_state = FCP_PKT_IDLE; 11179 11180 #ifdef DEBUG 11181 mutex_enter(&pptr->port_pkt_mutex); 11182 pptr->port_npkts--; 11183 mutex_exit(&pptr->port_pkt_mutex); 11184 #endif /* DEBUG */ 11185 11186 /* 11187 * For lack of clearer definitions, choose 11188 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11189 */ 11190 11191 if (rval == FC_TRAN_BUSY) { 11192 pkt->pkt_resid = 0; 11193 rval = TRAN_BUSY; 11194 } else { 11195 mutex_enter(&ptgt->tgt_mutex); 11196 if (plun->lun_state & FCP_LUN_OFFLINE) { 11197 child_info_t *cip; 11198 11199 mutex_enter(&plun->lun_mutex); 11200 cip = plun->lun_cip; 11201 mutex_exit(&plun->lun_mutex); 11202 11203 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11204 fcp_trace, FCP_BUF_LEVEL_6, 0, 11205 "fcp_transport failed 2 for %x: %x; dip=%p", 11206 plun->lun_tgt->tgt_d_id, rval, cip); 11207 11208 rval = TRAN_FATAL_ERROR; 11209 } else { 11210 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11211 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11212 fcp_trace, FCP_BUF_LEVEL_9, 0, 11213 "fcp_scsi_start: FC_BUSY for pkt %p", 11214 pkt); 11215 rval = TRAN_BUSY; 11216 } else { 11217 rval = TRAN_ACCEPT; 11218 fcp_queue_pkt(pptr, cmd); 11219 } 11220 } 11221 mutex_exit(&ptgt->tgt_mutex); 11222 } 11223 11224 return (rval); 11225 } 11226 11227 /* 11228 * called by the transport to abort a packet 11229 */ 11230 /*ARGSUSED*/ 11231 static int 11232 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11233 { 11234 int tgt_cnt; 11235 struct fcp_port *pptr = ADDR2FCP(ap); 11236 struct fcp_lun *plun = ADDR2LUN(ap); 11237 struct fcp_tgt *ptgt = plun->lun_tgt; 11238 11239 if (pkt == NULL) { 11240 if (ptgt) { 11241 mutex_enter(&ptgt->tgt_mutex); 11242 tgt_cnt = ptgt->tgt_change_cnt; 11243 mutex_exit(&ptgt->tgt_mutex); 11244 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11245 return (TRUE); 11246 } 11247 } 11248 return (FALSE); 11249 } 11250 11251 11252 /* 11253 * Perform reset 11254 */ 11255 int 11256 fcp_scsi_reset(struct scsi_address *ap, int level) 11257 { 11258 int rval = 0; 11259 struct fcp_port *pptr = ADDR2FCP(ap); 11260 struct fcp_lun *plun = ADDR2LUN(ap); 11261 struct fcp_tgt *ptgt = plun->lun_tgt; 11262 11263 if (level == RESET_ALL) { 11264 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11265 rval = 1; 11266 } 11267 } else if (level == RESET_TARGET || level == RESET_LUN) { 11268 /* 11269 * If we are in the middle of discovery, return 11270 * SUCCESS as this target will be rediscovered 11271 * anyway 11272 */ 11273 mutex_enter(&ptgt->tgt_mutex); 11274 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11275 mutex_exit(&ptgt->tgt_mutex); 11276 return (1); 11277 } 11278 mutex_exit(&ptgt->tgt_mutex); 11279 11280 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11281 rval = 1; 11282 } 11283 } 11284 return (rval); 11285 } 11286 11287 11288 /* 11289 * called by the framework to get a SCSI capability 11290 */ 11291 static int 11292 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11293 { 11294 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11295 } 11296 11297 11298 /* 11299 * called by the framework to set a SCSI capability 11300 */ 11301 static int 11302 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11303 { 11304 return (fcp_commoncap(ap, cap, value, whom, 1)); 11305 } 11306 11307 /* 11308 * Function: fcp_pkt_setup 11309 * 11310 * Description: This function sets up the scsi_pkt structure passed by the 11311 * caller. This function assumes fcp_pkt_constructor has been 11312 * called previously for the packet passed by the caller. If 11313 * successful this call will have the following results: 11314 * 11315 * - The resources needed that will be constant through out 11316 * the whole transaction are allocated. 11317 * - The fields that will be constant through out the whole 11318 * transaction are initialized. 11319 * - The scsi packet will be linked to the LUN structure 11320 * addressed by the transaction. 11321 * 11322 * Argument: 11323 * *pkt Pointer to a scsi_pkt structure. 11324 * callback 11325 * arg 11326 * 11327 * Return Value: 0 Success 11328 * !0 Failure 11329 * 11330 * Context: Kernel context or interrupt context 11331 */ 11332 /* ARGSUSED */ 11333 static int 11334 fcp_pkt_setup(struct scsi_pkt *pkt, 11335 int (*callback)(caddr_t arg), 11336 caddr_t arg) 11337 { 11338 struct fcp_pkt *cmd; 11339 struct fcp_port *pptr; 11340 struct fcp_lun *plun; 11341 struct fcp_tgt *ptgt; 11342 int kf; 11343 fc_packet_t *fpkt; 11344 fc_frame_hdr_t *hp; 11345 11346 pptr = ADDR2FCP(&pkt->pkt_address); 11347 plun = ADDR2LUN(&pkt->pkt_address); 11348 ptgt = plun->lun_tgt; 11349 11350 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11351 fpkt = cmd->cmd_fp_pkt; 11352 11353 /* 11354 * this request is for dma allocation only 11355 */ 11356 /* 11357 * First step of fcp_scsi_init_pkt: pkt allocation 11358 * We determine if the caller is willing to wait for the 11359 * resources. 11360 */ 11361 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11362 11363 /* 11364 * Selective zeroing of the pkt. 11365 */ 11366 cmd->cmd_back = NULL; 11367 cmd->cmd_next = NULL; 11368 11369 /* 11370 * Zero out fcp command 11371 */ 11372 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11373 11374 cmd->cmd_state = FCP_PKT_IDLE; 11375 11376 fpkt = cmd->cmd_fp_pkt; 11377 fpkt->pkt_data_acc = NULL; 11378 11379 /* 11380 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11381 * could be destroyed. We need fail pkt_setup. 11382 */ 11383 if (pptr->port_state & FCP_STATE_OFFLINE) { 11384 return (-1); 11385 } 11386 11387 mutex_enter(&ptgt->tgt_mutex); 11388 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11389 11390 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11391 != FC_SUCCESS) { 11392 mutex_exit(&ptgt->tgt_mutex); 11393 return (-1); 11394 } 11395 11396 mutex_exit(&ptgt->tgt_mutex); 11397 11398 /* Fill in the Fabric Channel Header */ 11399 hp = &fpkt->pkt_cmd_fhdr; 11400 hp->r_ctl = R_CTL_COMMAND; 11401 hp->rsvd = 0; 11402 hp->type = FC_TYPE_SCSI_FCP; 11403 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11404 hp->seq_id = 0; 11405 hp->df_ctl = 0; 11406 hp->seq_cnt = 0; 11407 hp->ox_id = 0xffff; 11408 hp->rx_id = 0xffff; 11409 hp->ro = 0; 11410 11411 /* 11412 * A doubly linked list (cmd_forw, cmd_back) is built 11413 * out of every allocated packet on a per-lun basis 11414 * 11415 * The packets are maintained in the list so as to satisfy 11416 * scsi_abort() requests. At present (which is unlikely to 11417 * change in the future) nobody performs a real scsi_abort 11418 * in the SCSI target drivers (as they don't keep the packets 11419 * after doing scsi_transport - so they don't know how to 11420 * abort a packet other than sending a NULL to abort all 11421 * outstanding packets) 11422 */ 11423 mutex_enter(&plun->lun_mutex); 11424 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11425 plun->lun_pkt_head->cmd_back = cmd; 11426 } else { 11427 plun->lun_pkt_tail = cmd; 11428 } 11429 plun->lun_pkt_head = cmd; 11430 mutex_exit(&plun->lun_mutex); 11431 return (0); 11432 } 11433 11434 /* 11435 * Function: fcp_pkt_teardown 11436 * 11437 * Description: This function releases a scsi_pkt structure and all the 11438 * resources attached to it. 11439 * 11440 * Argument: *pkt Pointer to a scsi_pkt structure. 11441 * 11442 * Return Value: None 11443 * 11444 * Context: User, Kernel or Interrupt context. 11445 */ 11446 static void 11447 fcp_pkt_teardown(struct scsi_pkt *pkt) 11448 { 11449 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11450 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11451 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11452 11453 /* 11454 * Remove the packet from the per-lun list 11455 */ 11456 mutex_enter(&plun->lun_mutex); 11457 if (cmd->cmd_back) { 11458 ASSERT(cmd != plun->lun_pkt_head); 11459 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11460 } else { 11461 ASSERT(cmd == plun->lun_pkt_head); 11462 plun->lun_pkt_head = cmd->cmd_forw; 11463 } 11464 11465 if (cmd->cmd_forw) { 11466 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11467 } else { 11468 ASSERT(cmd == plun->lun_pkt_tail); 11469 plun->lun_pkt_tail = cmd->cmd_back; 11470 } 11471 11472 mutex_exit(&plun->lun_mutex); 11473 11474 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11475 } 11476 11477 /* 11478 * Routine for reset notification setup, to register or cancel. 11479 * This function is called by SCSA 11480 */ 11481 /*ARGSUSED*/ 11482 static int 11483 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11484 void (*callback)(caddr_t), caddr_t arg) 11485 { 11486 struct fcp_port *pptr = ADDR2FCP(ap); 11487 11488 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11489 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11490 } 11491 11492 11493 static int 11494 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11495 ddi_eventcookie_t *event_cookiep) 11496 { 11497 struct fcp_port *pptr = fcp_dip2port(dip); 11498 11499 if (pptr == NULL) { 11500 return (DDI_FAILURE); 11501 } 11502 11503 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11504 event_cookiep, NDI_EVENT_NOPASS)); 11505 } 11506 11507 11508 static int 11509 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11510 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11511 ddi_callback_id_t *cb_id) 11512 { 11513 struct fcp_port *pptr = fcp_dip2port(dip); 11514 11515 if (pptr == NULL) { 11516 return (DDI_FAILURE); 11517 } 11518 11519 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11520 eventid, callback, arg, NDI_SLEEP, cb_id)); 11521 } 11522 11523 11524 static int 11525 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11526 { 11527 11528 struct fcp_port *pptr = fcp_dip2port(dip); 11529 11530 if (pptr == NULL) { 11531 return (DDI_FAILURE); 11532 } 11533 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11534 } 11535 11536 11537 /* 11538 * called by the transport to post an event 11539 */ 11540 static int 11541 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11542 ddi_eventcookie_t eventid, void *impldata) 11543 { 11544 struct fcp_port *pptr = fcp_dip2port(dip); 11545 11546 if (pptr == NULL) { 11547 return (DDI_FAILURE); 11548 } 11549 11550 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11551 eventid, impldata)); 11552 } 11553 11554 11555 /* 11556 * A target in in many cases in Fibre Channel has a one to one relation 11557 * with a port identifier (which is also known as D_ID and also as AL_PA 11558 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11559 * will most likely result in resetting all LUNs (which means a reset will 11560 * occur on all the SCSI devices connected at the other end of the bridge) 11561 * That is the latest favorite topic for discussion, for, one can debate as 11562 * hot as one likes and come up with arguably a best solution to one's 11563 * satisfaction 11564 * 11565 * To stay on track and not digress much, here are the problems stated 11566 * briefly: 11567 * 11568 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11569 * target drivers use RESET_TARGET even if their instance is on a 11570 * LUN. Doesn't that sound a bit broken ? 11571 * 11572 * FCP SCSI (the current spec) only defines RESET TARGET in the 11573 * control fields of an FCP_CMND structure. It should have been 11574 * fixed right there, giving flexibility to the initiators to 11575 * minimize havoc that could be caused by resetting a target. 11576 */ 11577 static int 11578 fcp_reset_target(struct scsi_address *ap, int level) 11579 { 11580 int rval = FC_FAILURE; 11581 char lun_id[25]; 11582 struct fcp_port *pptr = ADDR2FCP(ap); 11583 struct fcp_lun *plun = ADDR2LUN(ap); 11584 struct fcp_tgt *ptgt = plun->lun_tgt; 11585 struct scsi_pkt *pkt; 11586 struct fcp_pkt *cmd; 11587 struct fcp_rsp *rsp; 11588 uint32_t tgt_cnt; 11589 struct fcp_rsp_info *rsp_info; 11590 struct fcp_reset_elem *p; 11591 int bval; 11592 11593 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11594 KM_NOSLEEP)) == NULL) { 11595 return (rval); 11596 } 11597 11598 mutex_enter(&ptgt->tgt_mutex); 11599 if (level == RESET_TARGET) { 11600 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11601 mutex_exit(&ptgt->tgt_mutex); 11602 kmem_free(p, sizeof (struct fcp_reset_elem)); 11603 return (rval); 11604 } 11605 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11606 (void) strcpy(lun_id, " "); 11607 } else { 11608 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11609 mutex_exit(&ptgt->tgt_mutex); 11610 kmem_free(p, sizeof (struct fcp_reset_elem)); 11611 return (rval); 11612 } 11613 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11614 11615 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11616 } 11617 tgt_cnt = ptgt->tgt_change_cnt; 11618 11619 mutex_exit(&ptgt->tgt_mutex); 11620 11621 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11622 0, 0, NULL, 0)) == NULL) { 11623 kmem_free(p, sizeof (struct fcp_reset_elem)); 11624 mutex_enter(&ptgt->tgt_mutex); 11625 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11626 mutex_exit(&ptgt->tgt_mutex); 11627 return (rval); 11628 } 11629 pkt->pkt_time = FCP_POLL_TIMEOUT; 11630 11631 /* fill in cmd part of packet */ 11632 cmd = PKT2CMD(pkt); 11633 if (level == RESET_TARGET) { 11634 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11635 } else { 11636 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11637 } 11638 cmd->cmd_fp_pkt->pkt_comp = NULL; 11639 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11640 11641 /* prepare a packet for transport */ 11642 fcp_prepare_pkt(pptr, cmd, plun); 11643 11644 if (cmd->cmd_pkt->pkt_time) { 11645 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11646 } else { 11647 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11648 } 11649 11650 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11651 bval = fcp_dopoll(pptr, cmd); 11652 fc_ulp_idle_port(pptr->port_fp_handle); 11653 11654 /* submit the packet */ 11655 if (bval == TRAN_ACCEPT) { 11656 int error = 3; 11657 11658 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11659 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11660 sizeof (struct fcp_rsp)); 11661 11662 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11663 if (fcp_validate_fcp_response(rsp, pptr) == 11664 FC_SUCCESS) { 11665 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11666 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11667 sizeof (struct fcp_rsp), rsp_info, 11668 cmd->cmd_fp_pkt->pkt_resp_acc, 11669 sizeof (struct fcp_rsp_info)); 11670 } 11671 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11672 rval = FC_SUCCESS; 11673 error = 0; 11674 } else { 11675 error = 1; 11676 } 11677 } else { 11678 error = 2; 11679 } 11680 } 11681 11682 switch (error) { 11683 case 0: 11684 fcp_log(CE_WARN, pptr->port_dip, 11685 "!FCP: WWN 0x%08x%08x %s reset successfully", 11686 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11687 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11688 break; 11689 11690 case 1: 11691 fcp_log(CE_WARN, pptr->port_dip, 11692 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11693 " response code=%x", 11694 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11695 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11696 rsp_info->rsp_code); 11697 break; 11698 11699 case 2: 11700 fcp_log(CE_WARN, pptr->port_dip, 11701 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11702 " Bad FCP response values: rsvd1=%x," 11703 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11704 " rsplen=%x, senselen=%x", 11705 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11706 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11707 rsp->reserved_0, rsp->reserved_1, 11708 rsp->fcp_u.fcp_status.reserved_0, 11709 rsp->fcp_u.fcp_status.reserved_1, 11710 rsp->fcp_response_len, rsp->fcp_sense_len); 11711 break; 11712 11713 default: 11714 fcp_log(CE_WARN, pptr->port_dip, 11715 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11716 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11717 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11718 break; 11719 } 11720 } 11721 scsi_destroy_pkt(pkt); 11722 11723 if (rval == FC_FAILURE) { 11724 mutex_enter(&ptgt->tgt_mutex); 11725 if (level == RESET_TARGET) { 11726 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11727 } else { 11728 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11729 } 11730 mutex_exit(&ptgt->tgt_mutex); 11731 kmem_free(p, sizeof (struct fcp_reset_elem)); 11732 return (rval); 11733 } 11734 11735 mutex_enter(&pptr->port_mutex); 11736 if (level == RESET_TARGET) { 11737 p->tgt = ptgt; 11738 p->lun = NULL; 11739 } else { 11740 p->tgt = NULL; 11741 p->lun = plun; 11742 } 11743 p->tgt = ptgt; 11744 p->tgt_cnt = tgt_cnt; 11745 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11746 p->next = pptr->port_reset_list; 11747 pptr->port_reset_list = p; 11748 11749 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11750 fcp_trace, FCP_BUF_LEVEL_3, 0, 11751 "Notify ssd of the reset to reinstate the reservations"); 11752 11753 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11754 &pptr->port_reset_notify_listf); 11755 11756 mutex_exit(&pptr->port_mutex); 11757 11758 return (rval); 11759 } 11760 11761 11762 /* 11763 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11764 * SCSI capabilities 11765 */ 11766 /* ARGSUSED */ 11767 static int 11768 fcp_commoncap(struct scsi_address *ap, char *cap, 11769 int val, int tgtonly, int doset) 11770 { 11771 struct fcp_port *pptr = ADDR2FCP(ap); 11772 struct fcp_lun *plun = ADDR2LUN(ap); 11773 struct fcp_tgt *ptgt = plun->lun_tgt; 11774 int cidx; 11775 int rval = FALSE; 11776 11777 if (cap == (char *)0) { 11778 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11779 fcp_trace, FCP_BUF_LEVEL_3, 0, 11780 "fcp_commoncap: invalid arg"); 11781 return (rval); 11782 } 11783 11784 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11785 return (UNDEFINED); 11786 } 11787 11788 /* 11789 * Process setcap request. 11790 */ 11791 if (doset) { 11792 /* 11793 * At present, we can only set binary (0/1) values 11794 */ 11795 switch (cidx) { 11796 case SCSI_CAP_ARQ: 11797 if (val == 0) { 11798 rval = FALSE; 11799 } else { 11800 rval = TRUE; 11801 } 11802 break; 11803 11804 case SCSI_CAP_LUN_RESET: 11805 if (val) { 11806 plun->lun_cap |= FCP_LUN_CAP_RESET; 11807 } else { 11808 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11809 } 11810 rval = TRUE; 11811 break; 11812 11813 case SCSI_CAP_SECTOR_SIZE: 11814 rval = TRUE; 11815 break; 11816 default: 11817 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11818 fcp_trace, FCP_BUF_LEVEL_4, 0, 11819 "fcp_setcap: unsupported %d", cidx); 11820 rval = UNDEFINED; 11821 break; 11822 } 11823 11824 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11825 fcp_trace, FCP_BUF_LEVEL_5, 0, 11826 "set cap: cap=%s, val/tgtonly/doset/rval = " 11827 "0x%x/0x%x/0x%x/%d", 11828 cap, val, tgtonly, doset, rval); 11829 11830 } else { 11831 /* 11832 * Process getcap request. 11833 */ 11834 switch (cidx) { 11835 case SCSI_CAP_DMA_MAX: 11836 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11837 11838 /* 11839 * Need to make an adjustment qlc is uint_t 64 11840 * st is int, so we will make the adjustment here 11841 * being as nobody wants to touch this. 11842 * It still leaves the max single block length 11843 * of 2 gig. This should last . 11844 */ 11845 11846 if (rval == -1) { 11847 rval = MAX_INT_DMA; 11848 } 11849 11850 break; 11851 11852 case SCSI_CAP_INITIATOR_ID: 11853 rval = pptr->port_id; 11854 break; 11855 11856 case SCSI_CAP_ARQ: 11857 case SCSI_CAP_RESET_NOTIFICATION: 11858 case SCSI_CAP_TAGGED_QING: 11859 rval = TRUE; 11860 break; 11861 11862 case SCSI_CAP_SCSI_VERSION: 11863 rval = 3; 11864 break; 11865 11866 case SCSI_CAP_INTERCONNECT_TYPE: 11867 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11868 (ptgt->tgt_hard_addr == 0)) { 11869 rval = INTERCONNECT_FABRIC; 11870 } else { 11871 rval = INTERCONNECT_FIBRE; 11872 } 11873 break; 11874 11875 case SCSI_CAP_LUN_RESET: 11876 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11877 TRUE : FALSE; 11878 break; 11879 11880 default: 11881 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11882 fcp_trace, FCP_BUF_LEVEL_4, 0, 11883 "fcp_getcap: unsupported %d", cidx); 11884 rval = UNDEFINED; 11885 break; 11886 } 11887 11888 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11889 fcp_trace, FCP_BUF_LEVEL_8, 0, 11890 "get cap: cap=%s, val/tgtonly/doset/rval = " 11891 "0x%x/0x%x/0x%x/%d", 11892 cap, val, tgtonly, doset, rval); 11893 } 11894 11895 return (rval); 11896 } 11897 11898 /* 11899 * called by the transport to get the port-wwn and lun 11900 * properties of this device, and to create a "name" based on them 11901 * 11902 * these properties don't exist on sun4m 11903 * 11904 * return 1 for success else return 0 11905 */ 11906 /* ARGSUSED */ 11907 static int 11908 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11909 { 11910 int i; 11911 int *lun; 11912 int numChars; 11913 uint_t nlun; 11914 uint_t count; 11915 uint_t nbytes; 11916 uchar_t *bytes; 11917 uint16_t lun_num; 11918 uint32_t tgt_id; 11919 char **conf_wwn; 11920 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11921 uchar_t barray[FC_WWN_SIZE]; 11922 dev_info_t *tgt_dip; 11923 struct fcp_tgt *ptgt; 11924 struct fcp_port *pptr; 11925 struct fcp_lun *plun; 11926 11927 ASSERT(sd != NULL); 11928 ASSERT(name != NULL); 11929 11930 tgt_dip = sd->sd_dev; 11931 pptr = ddi_get_soft_state(fcp_softstate, 11932 ddi_get_instance(ddi_get_parent(tgt_dip))); 11933 if (pptr == NULL) { 11934 return (0); 11935 } 11936 11937 ASSERT(tgt_dip != NULL); 11938 11939 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11940 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11941 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11942 name[0] = '\0'; 11943 return (0); 11944 } 11945 11946 if (nlun == 0) { 11947 ddi_prop_free(lun); 11948 return (0); 11949 } 11950 11951 lun_num = lun[0]; 11952 ddi_prop_free(lun); 11953 11954 /* 11955 * Lookup for .conf WWN property 11956 */ 11957 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11958 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11959 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11960 ASSERT(count >= 1); 11961 11962 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11963 ddi_prop_free(conf_wwn); 11964 mutex_enter(&pptr->port_mutex); 11965 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11966 mutex_exit(&pptr->port_mutex); 11967 return (0); 11968 } 11969 ptgt = plun->lun_tgt; 11970 mutex_exit(&pptr->port_mutex); 11971 11972 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11973 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11974 11975 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11976 ptgt->tgt_hard_addr != 0) { 11977 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11978 ptgt->tgt_hard_addr]; 11979 } else { 11980 tgt_id = ptgt->tgt_d_id; 11981 } 11982 11983 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11984 TARGET_PROP, tgt_id); 11985 } 11986 11987 /* get the our port-wwn property */ 11988 bytes = NULL; 11989 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 11990 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 11991 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 11992 if (bytes != NULL) { 11993 ddi_prop_free(bytes); 11994 } 11995 return (0); 11996 } 11997 11998 for (i = 0; i < FC_WWN_SIZE; i++) { 11999 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12000 } 12001 12002 /* Stick in the address of the form "wWWN,LUN" */ 12003 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12004 12005 ASSERT(numChars < len); 12006 if (numChars >= len) { 12007 fcp_log(CE_WARN, pptr->port_dip, 12008 "!fcp_scsi_get_name: " 12009 "name parameter length too small, it needs to be %d", 12010 numChars+1); 12011 } 12012 12013 ddi_prop_free(bytes); 12014 12015 return (1); 12016 } 12017 12018 12019 /* 12020 * called by the transport to get the SCSI target id value, returning 12021 * it in "name" 12022 * 12023 * this isn't needed/used on sun4m 12024 * 12025 * return 1 for success else return 0 12026 */ 12027 /* ARGSUSED */ 12028 static int 12029 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12030 { 12031 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12032 struct fcp_tgt *ptgt; 12033 int numChars; 12034 12035 if (plun == NULL) { 12036 return (0); 12037 } 12038 12039 if ((ptgt = plun->lun_tgt) == NULL) { 12040 return (0); 12041 } 12042 12043 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12044 12045 ASSERT(numChars < len); 12046 if (numChars >= len) { 12047 fcp_log(CE_WARN, NULL, 12048 "!fcp_scsi_get_bus_addr: " 12049 "name parameter length too small, it needs to be %d", 12050 numChars+1); 12051 } 12052 12053 return (1); 12054 } 12055 12056 12057 /* 12058 * called internally to reset the link where the specified port lives 12059 */ 12060 static int 12061 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12062 { 12063 la_wwn_t wwn; 12064 struct fcp_lun *plun; 12065 struct fcp_tgt *ptgt; 12066 12067 /* disable restart of lip if we're suspended */ 12068 mutex_enter(&pptr->port_mutex); 12069 12070 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12071 FCP_STATE_POWER_DOWN)) { 12072 mutex_exit(&pptr->port_mutex); 12073 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12074 fcp_trace, FCP_BUF_LEVEL_2, 0, 12075 "fcp_linkreset, fcp%d: link reset " 12076 "disabled due to DDI_SUSPEND", 12077 ddi_get_instance(pptr->port_dip)); 12078 return (FC_FAILURE); 12079 } 12080 12081 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12082 mutex_exit(&pptr->port_mutex); 12083 return (FC_SUCCESS); 12084 } 12085 12086 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12087 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12088 12089 /* 12090 * If ap == NULL assume local link reset. 12091 */ 12092 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12093 plun = ADDR2LUN(ap); 12094 ptgt = plun->lun_tgt; 12095 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12096 } else { 12097 bzero((caddr_t)&wwn, sizeof (wwn)); 12098 } 12099 mutex_exit(&pptr->port_mutex); 12100 12101 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12102 } 12103 12104 12105 /* 12106 * called from fcp_port_attach() to resume a port 12107 * return DDI_* success/failure status 12108 * acquires and releases the global mutex 12109 * acquires and releases the port mutex 12110 */ 12111 /*ARGSUSED*/ 12112 12113 static int 12114 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12115 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12116 { 12117 int res = DDI_FAILURE; /* default result */ 12118 struct fcp_port *pptr; /* port state ptr */ 12119 uint32_t alloc_cnt; 12120 uint32_t max_cnt; 12121 fc_portmap_t *tmp_list = NULL; 12122 12123 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12124 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12125 instance); 12126 12127 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12128 cmn_err(CE_WARN, "fcp: bad soft state"); 12129 return (res); 12130 } 12131 12132 mutex_enter(&pptr->port_mutex); 12133 switch (cmd) { 12134 case FC_CMD_RESUME: 12135 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12136 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12137 break; 12138 12139 case FC_CMD_POWER_UP: 12140 /* 12141 * If the port is DDI_SUSPENded, defer rediscovery 12142 * until DDI_RESUME occurs 12143 */ 12144 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12145 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12146 mutex_exit(&pptr->port_mutex); 12147 return (DDI_SUCCESS); 12148 } 12149 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12150 } 12151 pptr->port_id = s_id; 12152 pptr->port_state = FCP_STATE_INIT; 12153 mutex_exit(&pptr->port_mutex); 12154 12155 /* 12156 * Make a copy of ulp_port_info as fctl allocates 12157 * a temp struct. 12158 */ 12159 (void) fcp_cp_pinfo(pptr, pinfo); 12160 12161 mutex_enter(&fcp_global_mutex); 12162 if (fcp_watchdog_init++ == 0) { 12163 fcp_watchdog_tick = fcp_watchdog_timeout * 12164 drv_usectohz(1000000); 12165 fcp_watchdog_id = timeout(fcp_watch, 12166 NULL, fcp_watchdog_tick); 12167 } 12168 mutex_exit(&fcp_global_mutex); 12169 12170 /* 12171 * Handle various topologies and link states. 12172 */ 12173 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12174 case FC_STATE_OFFLINE: 12175 /* 12176 * Wait for ONLINE, at which time a state 12177 * change will cause a statec_callback 12178 */ 12179 res = DDI_SUCCESS; 12180 break; 12181 12182 case FC_STATE_ONLINE: 12183 12184 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12185 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12186 res = DDI_SUCCESS; 12187 break; 12188 } 12189 12190 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12191 !fcp_enable_auto_configuration) { 12192 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12193 if (tmp_list == NULL) { 12194 if (!alloc_cnt) { 12195 res = DDI_SUCCESS; 12196 } 12197 break; 12198 } 12199 max_cnt = alloc_cnt; 12200 } else { 12201 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12202 12203 alloc_cnt = FCP_MAX_DEVICES; 12204 12205 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12206 (sizeof (fc_portmap_t)) * alloc_cnt, 12207 KM_NOSLEEP)) == NULL) { 12208 fcp_log(CE_WARN, pptr->port_dip, 12209 "!fcp%d: failed to allocate portmap", 12210 instance); 12211 break; 12212 } 12213 12214 max_cnt = alloc_cnt; 12215 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12216 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12217 FC_SUCCESS) { 12218 caddr_t msg; 12219 12220 (void) fc_ulp_error(res, &msg); 12221 12222 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12223 fcp_trace, FCP_BUF_LEVEL_2, 0, 12224 "resume failed getportmap: reason=0x%x", 12225 res); 12226 12227 fcp_log(CE_WARN, pptr->port_dip, 12228 "!failed to get port map : %s", msg); 12229 break; 12230 } 12231 if (max_cnt > alloc_cnt) { 12232 alloc_cnt = max_cnt; 12233 } 12234 } 12235 12236 /* 12237 * do the SCSI device discovery and create 12238 * the devinfos 12239 */ 12240 fcp_statec_callback(ulph, pptr->port_fp_handle, 12241 pptr->port_phys_state, pptr->port_topology, tmp_list, 12242 max_cnt, pptr->port_id); 12243 12244 res = DDI_SUCCESS; 12245 break; 12246 12247 default: 12248 fcp_log(CE_WARN, pptr->port_dip, 12249 "!fcp%d: invalid port state at attach=0x%x", 12250 instance, pptr->port_phys_state); 12251 12252 mutex_enter(&pptr->port_mutex); 12253 pptr->port_phys_state = FCP_STATE_OFFLINE; 12254 mutex_exit(&pptr->port_mutex); 12255 res = DDI_SUCCESS; 12256 12257 break; 12258 } 12259 12260 if (tmp_list != NULL) { 12261 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12262 } 12263 12264 return (res); 12265 } 12266 12267 12268 static void 12269 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12270 { 12271 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12272 pptr->port_dip = pinfo->port_dip; 12273 pptr->port_fp_handle = pinfo->port_handle; 12274 if (pinfo->port_acc_attr != NULL) { 12275 /* 12276 * FCA supports DMA 12277 */ 12278 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12279 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12280 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12281 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12282 } 12283 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12284 pptr->port_max_exch = pinfo->port_fca_max_exch; 12285 pptr->port_phys_state = pinfo->port_state; 12286 pptr->port_topology = pinfo->port_flags; 12287 pptr->port_reset_action = pinfo->port_reset_action; 12288 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12289 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12290 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12291 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12292 12293 /* Clear FMA caps to avoid fm-capability ereport */ 12294 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12295 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12296 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12297 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12298 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12299 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12300 } 12301 12302 /* 12303 * If the elements wait field is set to 1 then 12304 * another thread is waiting for the operation to complete. Once 12305 * it is complete, the waiting thread is signaled and the element is 12306 * freed by the waiting thread. If the elements wait field is set to 0 12307 * the element is freed. 12308 */ 12309 static void 12310 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12311 { 12312 ASSERT(elem != NULL); 12313 mutex_enter(&elem->mutex); 12314 elem->result = result; 12315 if (elem->wait) { 12316 elem->wait = 0; 12317 cv_signal(&elem->cv); 12318 mutex_exit(&elem->mutex); 12319 } else { 12320 mutex_exit(&elem->mutex); 12321 cv_destroy(&elem->cv); 12322 mutex_destroy(&elem->mutex); 12323 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12324 } 12325 } 12326 12327 /* 12328 * This function is invoked from the taskq thread to allocate 12329 * devinfo nodes and to online/offline them. 12330 */ 12331 static void 12332 fcp_hp_task(void *arg) 12333 { 12334 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12335 struct fcp_lun *plun = elem->lun; 12336 struct fcp_port *pptr = elem->port; 12337 int result; 12338 12339 ASSERT(elem->what == FCP_ONLINE || 12340 elem->what == FCP_OFFLINE || 12341 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12342 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12343 12344 mutex_enter(&pptr->port_mutex); 12345 mutex_enter(&plun->lun_mutex); 12346 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12347 plun->lun_event_count != elem->event_cnt) || 12348 pptr->port_state & (FCP_STATE_SUSPENDED | 12349 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12350 mutex_exit(&plun->lun_mutex); 12351 mutex_exit(&pptr->port_mutex); 12352 fcp_process_elem(elem, NDI_FAILURE); 12353 return; 12354 } 12355 mutex_exit(&plun->lun_mutex); 12356 mutex_exit(&pptr->port_mutex); 12357 12358 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12359 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12360 fcp_process_elem(elem, result); 12361 } 12362 12363 12364 static child_info_t * 12365 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12366 int tcount) 12367 { 12368 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12369 12370 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12371 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12372 12373 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12374 /* 12375 * Child has not been created yet. Create the child device 12376 * based on the per-Lun flags. 12377 */ 12378 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12379 plun->lun_cip = 12380 CIP(fcp_create_dip(plun, lcount, tcount)); 12381 plun->lun_mpxio = 0; 12382 } else { 12383 plun->lun_cip = 12384 CIP(fcp_create_pip(plun, lcount, tcount)); 12385 plun->lun_mpxio = 1; 12386 } 12387 } else { 12388 plun->lun_cip = cip; 12389 } 12390 12391 return (plun->lun_cip); 12392 } 12393 12394 12395 static int 12396 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12397 { 12398 int rval = FC_FAILURE; 12399 dev_info_t *pdip; 12400 struct dev_info *dip; 12401 int circular; 12402 12403 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12404 12405 pdip = plun->lun_tgt->tgt_port->port_dip; 12406 12407 if (plun->lun_cip == NULL) { 12408 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12409 fcp_trace, FCP_BUF_LEVEL_3, 0, 12410 "fcp_is_dip_present: plun->lun_cip is NULL: " 12411 "plun: %p lun state: %x num: %d target state: %x", 12412 plun, plun->lun_state, plun->lun_num, 12413 plun->lun_tgt->tgt_port->port_state); 12414 return (rval); 12415 } 12416 ndi_devi_enter(pdip, &circular); 12417 dip = DEVI(pdip)->devi_child; 12418 while (dip) { 12419 if (dip == DEVI(cdip)) { 12420 rval = FC_SUCCESS; 12421 break; 12422 } 12423 dip = dip->devi_sibling; 12424 } 12425 ndi_devi_exit(pdip, circular); 12426 return (rval); 12427 } 12428 12429 static int 12430 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12431 { 12432 int rval = FC_FAILURE; 12433 12434 ASSERT(plun != NULL); 12435 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12436 12437 if (plun->lun_mpxio == 0) { 12438 rval = fcp_is_dip_present(plun, DIP(cip)); 12439 } else { 12440 rval = fcp_is_pip_present(plun, PIP(cip)); 12441 } 12442 12443 return (rval); 12444 } 12445 12446 /* 12447 * Function: fcp_create_dip 12448 * 12449 * Description: Creates a dev_info_t structure for the LUN specified by the 12450 * caller. 12451 * 12452 * Argument: plun Lun structure 12453 * link_cnt Link state count. 12454 * tgt_cnt Target state change count. 12455 * 12456 * Return Value: NULL if it failed 12457 * dev_info_t structure address if it succeeded 12458 * 12459 * Context: Kernel context 12460 */ 12461 static dev_info_t * 12462 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12463 { 12464 int failure = 0; 12465 uint32_t tgt_id; 12466 uint64_t sam_lun; 12467 struct fcp_tgt *ptgt = plun->lun_tgt; 12468 struct fcp_port *pptr = ptgt->tgt_port; 12469 dev_info_t *pdip = pptr->port_dip; 12470 dev_info_t *cdip = NULL; 12471 dev_info_t *old_dip = DIP(plun->lun_cip); 12472 char *nname = NULL; 12473 char **compatible = NULL; 12474 int ncompatible; 12475 char *scsi_binding_set; 12476 char t_pwwn[17]; 12477 12478 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12479 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12480 12481 /* get the 'scsi-binding-set' property */ 12482 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12483 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12484 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12485 scsi_binding_set = NULL; 12486 } 12487 12488 /* determine the node name and compatible */ 12489 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12490 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12491 if (scsi_binding_set) { 12492 ddi_prop_free(scsi_binding_set); 12493 } 12494 12495 if (nname == NULL) { 12496 #ifdef DEBUG 12497 cmn_err(CE_WARN, "%s%d: no driver for " 12498 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12499 " compatible: %s", 12500 ddi_driver_name(pdip), ddi_get_instance(pdip), 12501 ptgt->tgt_port_wwn.raw_wwn[0], 12502 ptgt->tgt_port_wwn.raw_wwn[1], 12503 ptgt->tgt_port_wwn.raw_wwn[2], 12504 ptgt->tgt_port_wwn.raw_wwn[3], 12505 ptgt->tgt_port_wwn.raw_wwn[4], 12506 ptgt->tgt_port_wwn.raw_wwn[5], 12507 ptgt->tgt_port_wwn.raw_wwn[6], 12508 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12509 *compatible); 12510 #endif /* DEBUG */ 12511 failure++; 12512 goto end_of_fcp_create_dip; 12513 } 12514 12515 cdip = fcp_find_existing_dip(plun, pdip, nname); 12516 12517 /* 12518 * if the old_dip does not match the cdip, that means there is 12519 * some property change. since we'll be using the cdip, we need 12520 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12521 * then the dtype for the device has been updated. Offline the 12522 * the old device and create a new device with the new device type 12523 * Refer to bug: 4764752 12524 */ 12525 if (old_dip && (cdip != old_dip || 12526 plun->lun_state & FCP_LUN_CHANGED)) { 12527 plun->lun_state &= ~(FCP_LUN_INIT); 12528 mutex_exit(&plun->lun_mutex); 12529 mutex_exit(&pptr->port_mutex); 12530 12531 mutex_enter(&ptgt->tgt_mutex); 12532 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12533 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12534 mutex_exit(&ptgt->tgt_mutex); 12535 12536 #ifdef DEBUG 12537 if (cdip != NULL) { 12538 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12539 fcp_trace, FCP_BUF_LEVEL_2, 0, 12540 "Old dip=%p; New dip=%p don't match", old_dip, 12541 cdip); 12542 } else { 12543 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12544 fcp_trace, FCP_BUF_LEVEL_2, 0, 12545 "Old dip=%p; New dip=NULL don't match", old_dip); 12546 } 12547 #endif 12548 12549 mutex_enter(&pptr->port_mutex); 12550 mutex_enter(&plun->lun_mutex); 12551 } 12552 12553 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12554 plun->lun_state &= ~(FCP_LUN_CHANGED); 12555 if (ndi_devi_alloc(pptr->port_dip, nname, 12556 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12557 failure++; 12558 goto end_of_fcp_create_dip; 12559 } 12560 } 12561 12562 /* 12563 * Previously all the properties for the devinfo were destroyed here 12564 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12565 * the devid property (and other properties established by the target 12566 * driver or framework) which the code does not always recreate, this 12567 * call was removed. 12568 * This opens a theoretical possibility that we may return with a 12569 * stale devid on the node if the scsi entity behind the fibre channel 12570 * lun has changed. 12571 */ 12572 12573 /* decorate the node with compatible */ 12574 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12575 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12576 failure++; 12577 goto end_of_fcp_create_dip; 12578 } 12579 12580 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12581 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12582 failure++; 12583 goto end_of_fcp_create_dip; 12584 } 12585 12586 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12587 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12588 failure++; 12589 goto end_of_fcp_create_dip; 12590 } 12591 12592 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12593 t_pwwn[16] = '\0'; 12594 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12595 != DDI_PROP_SUCCESS) { 12596 failure++; 12597 goto end_of_fcp_create_dip; 12598 } 12599 12600 /* 12601 * If there is no hard address - We might have to deal with 12602 * that by using WWN - Having said that it is important to 12603 * recognize this problem early so ssd can be informed of 12604 * the right interconnect type. 12605 */ 12606 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12607 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12608 } else { 12609 tgt_id = ptgt->tgt_d_id; 12610 } 12611 12612 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12613 tgt_id) != DDI_PROP_SUCCESS) { 12614 failure++; 12615 goto end_of_fcp_create_dip; 12616 } 12617 12618 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12619 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12620 failure++; 12621 goto end_of_fcp_create_dip; 12622 } 12623 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12624 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12625 sam_lun) != DDI_PROP_SUCCESS) { 12626 failure++; 12627 goto end_of_fcp_create_dip; 12628 } 12629 12630 end_of_fcp_create_dip: 12631 scsi_hba_nodename_compatible_free(nname, compatible); 12632 12633 if (cdip != NULL && failure) { 12634 (void) ndi_prop_remove_all(cdip); 12635 (void) ndi_devi_free(cdip); 12636 cdip = NULL; 12637 } 12638 12639 return (cdip); 12640 } 12641 12642 /* 12643 * Function: fcp_create_pip 12644 * 12645 * Description: Creates a Path Id for the LUN specified by the caller. 12646 * 12647 * Argument: plun Lun structure 12648 * link_cnt Link state count. 12649 * tgt_cnt Target state count. 12650 * 12651 * Return Value: NULL if it failed 12652 * mdi_pathinfo_t structure address if it succeeded 12653 * 12654 * Context: Kernel context 12655 */ 12656 static mdi_pathinfo_t * 12657 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12658 { 12659 int i; 12660 char buf[MAXNAMELEN]; 12661 char uaddr[MAXNAMELEN]; 12662 int failure = 0; 12663 uint32_t tgt_id; 12664 uint64_t sam_lun; 12665 struct fcp_tgt *ptgt = plun->lun_tgt; 12666 struct fcp_port *pptr = ptgt->tgt_port; 12667 dev_info_t *pdip = pptr->port_dip; 12668 mdi_pathinfo_t *pip = NULL; 12669 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12670 char *nname = NULL; 12671 char **compatible = NULL; 12672 int ncompatible; 12673 char *scsi_binding_set; 12674 char t_pwwn[17]; 12675 12676 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12677 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12678 12679 scsi_binding_set = "vhci"; 12680 12681 /* determine the node name and compatible */ 12682 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12683 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12684 12685 if (nname == NULL) { 12686 #ifdef DEBUG 12687 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12688 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12689 " compatible: %s", 12690 ddi_driver_name(pdip), ddi_get_instance(pdip), 12691 ptgt->tgt_port_wwn.raw_wwn[0], 12692 ptgt->tgt_port_wwn.raw_wwn[1], 12693 ptgt->tgt_port_wwn.raw_wwn[2], 12694 ptgt->tgt_port_wwn.raw_wwn[3], 12695 ptgt->tgt_port_wwn.raw_wwn[4], 12696 ptgt->tgt_port_wwn.raw_wwn[5], 12697 ptgt->tgt_port_wwn.raw_wwn[6], 12698 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12699 *compatible); 12700 #endif /* DEBUG */ 12701 failure++; 12702 goto end_of_fcp_create_pip; 12703 } 12704 12705 pip = fcp_find_existing_pip(plun, pdip); 12706 12707 /* 12708 * if the old_dip does not match the cdip, that means there is 12709 * some property change. since we'll be using the cdip, we need 12710 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12711 * then the dtype for the device has been updated. Offline the 12712 * the old device and create a new device with the new device type 12713 * Refer to bug: 4764752 12714 */ 12715 if (old_pip && (pip != old_pip || 12716 plun->lun_state & FCP_LUN_CHANGED)) { 12717 plun->lun_state &= ~(FCP_LUN_INIT); 12718 mutex_exit(&plun->lun_mutex); 12719 mutex_exit(&pptr->port_mutex); 12720 12721 mutex_enter(&ptgt->tgt_mutex); 12722 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12723 FCP_OFFLINE, lcount, tcount, 12724 NDI_DEVI_REMOVE, 0); 12725 mutex_exit(&ptgt->tgt_mutex); 12726 12727 if (pip != NULL) { 12728 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12729 fcp_trace, FCP_BUF_LEVEL_2, 0, 12730 "Old pip=%p; New pip=%p don't match", 12731 old_pip, pip); 12732 } else { 12733 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12734 fcp_trace, FCP_BUF_LEVEL_2, 0, 12735 "Old pip=%p; New pip=NULL don't match", 12736 old_pip); 12737 } 12738 12739 mutex_enter(&pptr->port_mutex); 12740 mutex_enter(&plun->lun_mutex); 12741 } 12742 12743 /* 12744 * Since FC_WWN_SIZE is 8 bytes and its not like the 12745 * lun_guid_size which is dependent on the target, I don't 12746 * believe the same trancation happens here UNLESS the standards 12747 * change the FC_WWN_SIZE value to something larger than 12748 * MAXNAMELEN(currently 255 bytes). 12749 */ 12750 12751 for (i = 0; i < FC_WWN_SIZE; i++) { 12752 (void) sprintf(&buf[i << 1], "%02x", 12753 ptgt->tgt_port_wwn.raw_wwn[i]); 12754 } 12755 12756 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12757 buf, plun->lun_num); 12758 12759 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12760 /* 12761 * Release the locks before calling into 12762 * mdi_pi_alloc_compatible() since this can result in a 12763 * callback into fcp which can result in a deadlock 12764 * (see bug # 4870272). 12765 * 12766 * Basically, what we are trying to avoid is the scenario where 12767 * one thread does ndi_devi_enter() and tries to grab 12768 * fcp_mutex and another does it the other way round. 12769 * 12770 * But before we do that, make sure that nobody releases the 12771 * port in the meantime. We can do this by setting a flag. 12772 */ 12773 plun->lun_state &= ~(FCP_LUN_CHANGED); 12774 pptr->port_state |= FCP_STATE_IN_MDI; 12775 mutex_exit(&plun->lun_mutex); 12776 mutex_exit(&pptr->port_mutex); 12777 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12778 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12779 fcp_log(CE_WARN, pptr->port_dip, 12780 "!path alloc failed:0x%x", plun); 12781 mutex_enter(&pptr->port_mutex); 12782 mutex_enter(&plun->lun_mutex); 12783 pptr->port_state &= ~FCP_STATE_IN_MDI; 12784 failure++; 12785 goto end_of_fcp_create_pip; 12786 } 12787 mutex_enter(&pptr->port_mutex); 12788 mutex_enter(&plun->lun_mutex); 12789 pptr->port_state &= ~FCP_STATE_IN_MDI; 12790 } else { 12791 (void) mdi_prop_remove(pip, NULL); 12792 } 12793 12794 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12795 12796 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12797 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12798 != DDI_PROP_SUCCESS) { 12799 failure++; 12800 goto end_of_fcp_create_pip; 12801 } 12802 12803 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12804 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12805 != DDI_PROP_SUCCESS) { 12806 failure++; 12807 goto end_of_fcp_create_pip; 12808 } 12809 12810 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12811 t_pwwn[16] = '\0'; 12812 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12813 != DDI_PROP_SUCCESS) { 12814 failure++; 12815 goto end_of_fcp_create_pip; 12816 } 12817 12818 /* 12819 * If there is no hard address - We might have to deal with 12820 * that by using WWN - Having said that it is important to 12821 * recognize this problem early so ssd can be informed of 12822 * the right interconnect type. 12823 */ 12824 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12825 ptgt->tgt_hard_addr != 0) { 12826 tgt_id = (uint32_t) 12827 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12828 } else { 12829 tgt_id = ptgt->tgt_d_id; 12830 } 12831 12832 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12833 != DDI_PROP_SUCCESS) { 12834 failure++; 12835 goto end_of_fcp_create_pip; 12836 } 12837 12838 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12839 != DDI_PROP_SUCCESS) { 12840 failure++; 12841 goto end_of_fcp_create_pip; 12842 } 12843 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12844 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12845 != DDI_PROP_SUCCESS) { 12846 failure++; 12847 goto end_of_fcp_create_pip; 12848 } 12849 12850 end_of_fcp_create_pip: 12851 scsi_hba_nodename_compatible_free(nname, compatible); 12852 12853 if (pip != NULL && failure) { 12854 (void) mdi_prop_remove(pip, NULL); 12855 mutex_exit(&plun->lun_mutex); 12856 mutex_exit(&pptr->port_mutex); 12857 (void) mdi_pi_free(pip, 0); 12858 mutex_enter(&pptr->port_mutex); 12859 mutex_enter(&plun->lun_mutex); 12860 pip = NULL; 12861 } 12862 12863 return (pip); 12864 } 12865 12866 static dev_info_t * 12867 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12868 { 12869 uint_t nbytes; 12870 uchar_t *bytes; 12871 uint_t nwords; 12872 uint32_t tgt_id; 12873 int *words; 12874 dev_info_t *cdip; 12875 dev_info_t *ndip; 12876 struct fcp_tgt *ptgt = plun->lun_tgt; 12877 struct fcp_port *pptr = ptgt->tgt_port; 12878 int circular; 12879 12880 ndi_devi_enter(pdip, &circular); 12881 12882 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12883 while ((cdip = ndip) != NULL) { 12884 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12885 12886 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12887 continue; 12888 } 12889 12890 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12891 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12892 &nbytes) != DDI_PROP_SUCCESS) { 12893 continue; 12894 } 12895 12896 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12897 if (bytes != NULL) { 12898 ddi_prop_free(bytes); 12899 } 12900 continue; 12901 } 12902 ASSERT(bytes != NULL); 12903 12904 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12905 ddi_prop_free(bytes); 12906 continue; 12907 } 12908 12909 ddi_prop_free(bytes); 12910 12911 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12912 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12913 &nbytes) != DDI_PROP_SUCCESS) { 12914 continue; 12915 } 12916 12917 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12918 if (bytes != NULL) { 12919 ddi_prop_free(bytes); 12920 } 12921 continue; 12922 } 12923 ASSERT(bytes != NULL); 12924 12925 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12926 ddi_prop_free(bytes); 12927 continue; 12928 } 12929 12930 ddi_prop_free(bytes); 12931 12932 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12933 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12934 &nwords) != DDI_PROP_SUCCESS) { 12935 continue; 12936 } 12937 12938 if (nwords != 1 || words == NULL) { 12939 if (words != NULL) { 12940 ddi_prop_free(words); 12941 } 12942 continue; 12943 } 12944 ASSERT(words != NULL); 12945 12946 /* 12947 * If there is no hard address - We might have to deal with 12948 * that by using WWN - Having said that it is important to 12949 * recognize this problem early so ssd can be informed of 12950 * the right interconnect type. 12951 */ 12952 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12953 ptgt->tgt_hard_addr != 0) { 12954 tgt_id = 12955 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12956 } else { 12957 tgt_id = ptgt->tgt_d_id; 12958 } 12959 12960 if (tgt_id != (uint32_t)*words) { 12961 ddi_prop_free(words); 12962 continue; 12963 } 12964 ddi_prop_free(words); 12965 12966 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12967 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12968 &nwords) != DDI_PROP_SUCCESS) { 12969 continue; 12970 } 12971 12972 if (nwords != 1 || words == NULL) { 12973 if (words != NULL) { 12974 ddi_prop_free(words); 12975 } 12976 continue; 12977 } 12978 ASSERT(words != NULL); 12979 12980 if (plun->lun_num == (uint16_t)*words) { 12981 ddi_prop_free(words); 12982 break; 12983 } 12984 ddi_prop_free(words); 12985 } 12986 ndi_devi_exit(pdip, circular); 12987 12988 return (cdip); 12989 } 12990 12991 12992 static int 12993 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 12994 { 12995 dev_info_t *pdip; 12996 char buf[MAXNAMELEN]; 12997 char uaddr[MAXNAMELEN]; 12998 int rval = FC_FAILURE; 12999 13000 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13001 13002 pdip = plun->lun_tgt->tgt_port->port_dip; 13003 13004 /* 13005 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13006 * non-NULL even when the LUN is not there as in the case when a LUN is 13007 * configured and then deleted on the device end (for T3/T4 case). In 13008 * such cases, pip will be NULL. 13009 * 13010 * If the device generates an RSCN, it will end up getting offlined when 13011 * it disappeared and a new LUN will get created when it is rediscovered 13012 * on the device. If we check for lun_cip here, the LUN will not end 13013 * up getting onlined since this function will end up returning a 13014 * FC_SUCCESS. 13015 * 13016 * The behavior is different on other devices. For instance, on a HDS, 13017 * there was no RSCN generated by the device but the next I/O generated 13018 * a check condition and rediscovery got triggered that way. So, in 13019 * such cases, this path will not be exercised 13020 */ 13021 if (pip == NULL) { 13022 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13023 fcp_trace, FCP_BUF_LEVEL_4, 0, 13024 "fcp_is_pip_present: plun->lun_cip is NULL: " 13025 "plun: %p lun state: %x num: %d target state: %x", 13026 plun, plun->lun_state, plun->lun_num, 13027 plun->lun_tgt->tgt_port->port_state); 13028 return (rval); 13029 } 13030 13031 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13032 13033 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13034 13035 if (mdi_pi_find(pdip, NULL, uaddr) == pip) { 13036 rval = FC_SUCCESS; 13037 } 13038 13039 return (rval); 13040 } 13041 13042 static mdi_pathinfo_t * 13043 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13044 { 13045 char buf[MAXNAMELEN]; 13046 char uaddr[MAXNAMELEN]; 13047 mdi_pathinfo_t *pip; 13048 struct fcp_tgt *ptgt = plun->lun_tgt; 13049 struct fcp_port *pptr = ptgt->tgt_port; 13050 13051 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13052 13053 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13054 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13055 13056 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13057 13058 return (pip); 13059 } 13060 13061 13062 static int 13063 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13064 int tcount, int flags, int *circ) 13065 { 13066 int rval; 13067 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13068 struct fcp_tgt *ptgt = plun->lun_tgt; 13069 dev_info_t *cdip = NULL; 13070 13071 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13072 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13073 13074 if (plun->lun_cip == NULL) { 13075 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13076 fcp_trace, FCP_BUF_LEVEL_3, 0, 13077 "fcp_online_child: plun->lun_cip is NULL: " 13078 "plun: %p state: %x num: %d target state: %x", 13079 plun, plun->lun_state, plun->lun_num, 13080 plun->lun_tgt->tgt_port->port_state); 13081 return (NDI_FAILURE); 13082 } 13083 again: 13084 if (plun->lun_mpxio == 0) { 13085 cdip = DIP(cip); 13086 mutex_exit(&plun->lun_mutex); 13087 mutex_exit(&pptr->port_mutex); 13088 13089 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13090 fcp_trace, FCP_BUF_LEVEL_3, 0, 13091 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13092 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13093 13094 /* 13095 * We could check for FCP_LUN_INIT here but chances 13096 * of getting here when it's already in FCP_LUN_INIT 13097 * is rare and a duplicate ndi_devi_online wouldn't 13098 * hurt either (as the node would already have been 13099 * in CF2) 13100 */ 13101 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13102 rval = ndi_devi_bind_driver(cdip, flags); 13103 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13104 fcp_trace, FCP_BUF_LEVEL_3, 0, 13105 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13106 } else { 13107 rval = ndi_devi_online(cdip, flags); 13108 } 13109 13110 /* 13111 * We log the message into trace buffer if the device 13112 * is "ses" and into syslog for any other device 13113 * type. This is to prevent the ndi_devi_online failure 13114 * message that appears for V880/A5K ses devices. 13115 */ 13116 if (rval == NDI_SUCCESS) { 13117 mutex_enter(&ptgt->tgt_mutex); 13118 plun->lun_state |= FCP_LUN_INIT; 13119 mutex_exit(&ptgt->tgt_mutex); 13120 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13121 fcp_log(CE_NOTE, pptr->port_dip, 13122 "!ndi_devi_online:" 13123 " failed for %s: target=%x lun=%x %x", 13124 ddi_get_name(cdip), ptgt->tgt_d_id, 13125 plun->lun_num, rval); 13126 } else { 13127 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13128 fcp_trace, FCP_BUF_LEVEL_3, 0, 13129 " !ndi_devi_online:" 13130 " failed for %s: target=%x lun=%x %x", 13131 ddi_get_name(cdip), ptgt->tgt_d_id, 13132 plun->lun_num, rval); 13133 } 13134 } else { 13135 cdip = mdi_pi_get_client(PIP(cip)); 13136 mutex_exit(&plun->lun_mutex); 13137 mutex_exit(&pptr->port_mutex); 13138 13139 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13140 fcp_trace, FCP_BUF_LEVEL_3, 0, 13141 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13142 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13143 13144 /* 13145 * Hold path and exit phci to avoid deadlock with power 13146 * management code during mdi_pi_online. 13147 */ 13148 mdi_hold_path(PIP(cip)); 13149 mdi_devi_exit_phci(pptr->port_dip, *circ); 13150 13151 rval = mdi_pi_online(PIP(cip), flags); 13152 13153 mdi_devi_enter_phci(pptr->port_dip, circ); 13154 mdi_rele_path(PIP(cip)); 13155 13156 if (rval == MDI_SUCCESS) { 13157 mutex_enter(&ptgt->tgt_mutex); 13158 plun->lun_state |= FCP_LUN_INIT; 13159 mutex_exit(&ptgt->tgt_mutex); 13160 13161 /* 13162 * Clear MPxIO path permanent disable in case 13163 * fcp hotplug dropped the offline event. 13164 */ 13165 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13166 13167 } else if (rval == MDI_NOT_SUPPORTED) { 13168 child_info_t *old_cip = cip; 13169 13170 /* 13171 * MPxIO does not support this device yet. 13172 * Enumerate in legacy mode. 13173 */ 13174 mutex_enter(&pptr->port_mutex); 13175 mutex_enter(&plun->lun_mutex); 13176 plun->lun_mpxio = 0; 13177 plun->lun_cip = NULL; 13178 cdip = fcp_create_dip(plun, lcount, tcount); 13179 plun->lun_cip = cip = CIP(cdip); 13180 if (cip == NULL) { 13181 fcp_log(CE_WARN, pptr->port_dip, 13182 "!fcp_online_child: " 13183 "Create devinfo failed for LU=%p", plun); 13184 mutex_exit(&plun->lun_mutex); 13185 13186 mutex_enter(&ptgt->tgt_mutex); 13187 plun->lun_state |= FCP_LUN_OFFLINE; 13188 mutex_exit(&ptgt->tgt_mutex); 13189 13190 mutex_exit(&pptr->port_mutex); 13191 13192 /* 13193 * free the mdi_pathinfo node 13194 */ 13195 (void) mdi_pi_free(PIP(old_cip), 0); 13196 } else { 13197 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13198 fcp_trace, FCP_BUF_LEVEL_3, 0, 13199 "fcp_online_child: creating devinfo " 13200 "node 0x%p for plun 0x%p", 13201 cip, plun); 13202 mutex_exit(&plun->lun_mutex); 13203 mutex_exit(&pptr->port_mutex); 13204 /* 13205 * free the mdi_pathinfo node 13206 */ 13207 (void) mdi_pi_free(PIP(old_cip), 0); 13208 mutex_enter(&pptr->port_mutex); 13209 mutex_enter(&plun->lun_mutex); 13210 goto again; 13211 } 13212 } else { 13213 if (cdip) { 13214 fcp_log(CE_NOTE, pptr->port_dip, 13215 "!fcp_online_child: mdi_pi_online:" 13216 " failed for %s: target=%x lun=%x %x", 13217 ddi_get_name(cdip), ptgt->tgt_d_id, 13218 plun->lun_num, rval); 13219 } 13220 } 13221 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13222 } 13223 13224 if (rval == NDI_SUCCESS) { 13225 if (cdip) { 13226 (void) ndi_event_retrieve_cookie( 13227 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13228 &fcp_insert_eid, NDI_EVENT_NOPASS); 13229 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13230 cdip, fcp_insert_eid, NULL); 13231 } 13232 } 13233 mutex_enter(&pptr->port_mutex); 13234 mutex_enter(&plun->lun_mutex); 13235 return (rval); 13236 } 13237 13238 /* ARGSUSED */ 13239 static int 13240 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13241 int tcount, int flags, int *circ) 13242 { 13243 int rval; 13244 int lun_mpxio; 13245 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13246 struct fcp_tgt *ptgt = plun->lun_tgt; 13247 dev_info_t *cdip; 13248 13249 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13250 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13251 13252 if (plun->lun_cip == NULL) { 13253 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13254 fcp_trace, FCP_BUF_LEVEL_3, 0, 13255 "fcp_offline_child: plun->lun_cip is NULL: " 13256 "plun: %p lun state: %x num: %d target state: %x", 13257 plun, plun->lun_state, plun->lun_num, 13258 plun->lun_tgt->tgt_port->port_state); 13259 return (NDI_FAILURE); 13260 } 13261 13262 /* 13263 * We will use this value twice. Make a copy to be sure we use 13264 * the same value in both places. 13265 */ 13266 lun_mpxio = plun->lun_mpxio; 13267 13268 if (lun_mpxio == 0) { 13269 cdip = DIP(cip); 13270 mutex_exit(&plun->lun_mutex); 13271 mutex_exit(&pptr->port_mutex); 13272 rval = ndi_devi_offline(DIP(cip), NDI_DEVFS_CLEAN | flags); 13273 if (rval != NDI_SUCCESS) { 13274 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13275 fcp_trace, FCP_BUF_LEVEL_3, 0, 13276 "fcp_offline_child: ndi_devi_offline failed " 13277 "rval=%x cip=%p", rval, cip); 13278 } 13279 } else { 13280 cdip = mdi_pi_get_client(PIP(cip)); 13281 mutex_exit(&plun->lun_mutex); 13282 mutex_exit(&pptr->port_mutex); 13283 13284 /* 13285 * Exit phci to avoid deadlock with power management code 13286 * during mdi_pi_offline 13287 */ 13288 mdi_hold_path(PIP(cip)); 13289 mdi_devi_exit_phci(pptr->port_dip, *circ); 13290 13291 rval = mdi_pi_offline(PIP(cip), flags & ~NDI_DEVI_REMOVE); 13292 13293 mdi_devi_enter_phci(pptr->port_dip, circ); 13294 mdi_rele_path(PIP(cip)); 13295 13296 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13297 } 13298 13299 mutex_enter(&ptgt->tgt_mutex); 13300 plun->lun_state &= ~FCP_LUN_INIT; 13301 mutex_exit(&ptgt->tgt_mutex); 13302 13303 if (rval == NDI_SUCCESS) { 13304 cdip = NULL; 13305 if (flags & NDI_DEVI_REMOVE) { 13306 mutex_enter(&plun->lun_mutex); 13307 /* 13308 * If the guid of the LUN changes, lun_cip will not 13309 * equal to cip, and after offlining the LUN with the 13310 * old guid, we should keep lun_cip since it's the cip 13311 * of the LUN with the new guid. 13312 * Otherwise remove our reference to child node. 13313 * 13314 * This must be done before the child node is freed, 13315 * otherwise other threads could see a stale lun_cip 13316 * pointer. 13317 */ 13318 if (plun->lun_cip == cip) { 13319 plun->lun_cip = NULL; 13320 } 13321 if (plun->lun_old_guid) { 13322 kmem_free(plun->lun_old_guid, 13323 plun->lun_old_guid_size); 13324 plun->lun_old_guid = NULL; 13325 plun->lun_old_guid_size = 0; 13326 } 13327 mutex_exit(&plun->lun_mutex); 13328 } 13329 } 13330 13331 if (lun_mpxio != 0) { 13332 if (rval == NDI_SUCCESS) { 13333 /* 13334 * Clear MPxIO path permanent disable as the path is 13335 * already offlined. 13336 */ 13337 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13338 13339 if (flags & NDI_DEVI_REMOVE) { 13340 (void) mdi_pi_free(PIP(cip), 0); 13341 } 13342 } else { 13343 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13344 fcp_trace, FCP_BUF_LEVEL_3, 0, 13345 "fcp_offline_child: mdi_pi_offline failed " 13346 "rval=%x cip=%p", rval, cip); 13347 } 13348 } 13349 13350 mutex_enter(&pptr->port_mutex); 13351 mutex_enter(&plun->lun_mutex); 13352 13353 if (cdip) { 13354 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13355 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13356 " target=%x lun=%x", "ndi_offline", 13357 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13358 } 13359 13360 return (rval); 13361 } 13362 13363 static void 13364 fcp_remove_child(struct fcp_lun *plun) 13365 { 13366 child_info_t *cip; 13367 int circ; 13368 13369 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13370 13371 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13372 if (plun->lun_mpxio == 0) { 13373 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13374 (void) ndi_devi_free(DIP(plun->lun_cip)); 13375 plun->lun_cip = NULL; 13376 } else { 13377 /* 13378 * Clear reference to the child node in the lun. 13379 * This must be done before freeing it with mdi_pi_free 13380 * and with lun_mutex held so that other threads always 13381 * see either valid lun_cip or NULL when holding 13382 * lun_mutex. We keep a copy in cip. 13383 */ 13384 cip = plun->lun_cip; 13385 plun->lun_cip = NULL; 13386 13387 mutex_exit(&plun->lun_mutex); 13388 mutex_exit(&plun->lun_tgt->tgt_mutex); 13389 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13390 13391 mdi_devi_enter(plun->lun_tgt->tgt_port->port_dip, 13392 &circ); 13393 13394 /* 13395 * Exit phci to avoid deadlock with power management 13396 * code during mdi_pi_offline 13397 */ 13398 mdi_hold_path(PIP(cip)); 13399 mdi_devi_exit_phci(plun->lun_tgt->tgt_port->port_dip, 13400 circ); 13401 (void) mdi_pi_offline(PIP(cip), 0); 13402 mdi_devi_enter_phci(plun->lun_tgt->tgt_port->port_dip, 13403 &circ); 13404 mdi_rele_path(PIP(cip)); 13405 13406 mdi_devi_exit(plun->lun_tgt->tgt_port->port_dip, circ); 13407 13408 FCP_TRACE(fcp_logq, 13409 plun->lun_tgt->tgt_port->port_instbuf, 13410 fcp_trace, FCP_BUF_LEVEL_3, 0, 13411 "lun=%p pip freed %p", plun, cip); 13412 13413 (void) mdi_prop_remove(PIP(cip), NULL); 13414 (void) mdi_pi_free(PIP(cip), 0); 13415 13416 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13417 mutex_enter(&plun->lun_tgt->tgt_mutex); 13418 mutex_enter(&plun->lun_mutex); 13419 } 13420 } else { 13421 plun->lun_cip = NULL; 13422 } 13423 } 13424 13425 /* 13426 * called when a timeout occurs 13427 * 13428 * can be scheduled during an attach or resume (if not already running) 13429 * 13430 * one timeout is set up for all ports 13431 * 13432 * acquires and releases the global mutex 13433 */ 13434 /*ARGSUSED*/ 13435 static void 13436 fcp_watch(void *arg) 13437 { 13438 struct fcp_port *pptr; 13439 struct fcp_ipkt *icmd; 13440 struct fcp_ipkt *nicmd; 13441 struct fcp_pkt *cmd; 13442 struct fcp_pkt *ncmd; 13443 struct fcp_pkt *tail; 13444 struct fcp_pkt *pcmd; 13445 struct fcp_pkt *save_head; 13446 struct fcp_port *save_port; 13447 13448 /* increment global watchdog time */ 13449 fcp_watchdog_time += fcp_watchdog_timeout; 13450 13451 mutex_enter(&fcp_global_mutex); 13452 13453 /* scan each port in our list */ 13454 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13455 save_port = fcp_port_head; 13456 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13457 mutex_exit(&fcp_global_mutex); 13458 13459 mutex_enter(&pptr->port_mutex); 13460 if (pptr->port_ipkt_list == NULL && 13461 (pptr->port_state & (FCP_STATE_SUSPENDED | 13462 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13463 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13464 mutex_exit(&pptr->port_mutex); 13465 mutex_enter(&fcp_global_mutex); 13466 goto end_of_watchdog; 13467 } 13468 13469 /* 13470 * We check if a list of targets need to be offlined. 13471 */ 13472 if (pptr->port_offline_tgts) { 13473 fcp_scan_offline_tgts(pptr); 13474 } 13475 13476 /* 13477 * We check if a list of luns need to be offlined. 13478 */ 13479 if (pptr->port_offline_luns) { 13480 fcp_scan_offline_luns(pptr); 13481 } 13482 13483 /* 13484 * We check if a list of targets or luns need to be reset. 13485 */ 13486 if (pptr->port_reset_list) { 13487 fcp_check_reset_delay(pptr); 13488 } 13489 13490 mutex_exit(&pptr->port_mutex); 13491 13492 /* 13493 * This is where the pending commands (pkt) are checked for 13494 * timeout. 13495 */ 13496 mutex_enter(&pptr->port_pkt_mutex); 13497 tail = pptr->port_pkt_tail; 13498 13499 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13500 cmd != NULL; cmd = ncmd) { 13501 ncmd = cmd->cmd_next; 13502 /* 13503 * If a command is in this queue the bit CFLAG_IN_QUEUE 13504 * must be set. 13505 */ 13506 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13507 /* 13508 * FCP_INVALID_TIMEOUT will be set for those 13509 * command that need to be failed. Mostly those 13510 * cmds that could not be queued down for the 13511 * "timeout" value. cmd->cmd_timeout is used 13512 * to try and requeue the command regularly. 13513 */ 13514 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13515 /* 13516 * This command hasn't timed out yet. Let's 13517 * go to the next one. 13518 */ 13519 pcmd = cmd; 13520 goto end_of_loop; 13521 } 13522 13523 if (cmd == pptr->port_pkt_head) { 13524 ASSERT(pcmd == NULL); 13525 pptr->port_pkt_head = cmd->cmd_next; 13526 } else { 13527 ASSERT(pcmd != NULL); 13528 pcmd->cmd_next = cmd->cmd_next; 13529 } 13530 13531 if (cmd == pptr->port_pkt_tail) { 13532 ASSERT(cmd->cmd_next == NULL); 13533 pptr->port_pkt_tail = pcmd; 13534 if (pcmd) { 13535 pcmd->cmd_next = NULL; 13536 } 13537 } 13538 cmd->cmd_next = NULL; 13539 13540 /* 13541 * save the current head before dropping the 13542 * mutex - If the head doesn't remain the 13543 * same after re acquiring the mutex, just 13544 * bail out and revisit on next tick. 13545 * 13546 * PS: The tail pointer can change as the commands 13547 * get requeued after failure to retransport 13548 */ 13549 save_head = pptr->port_pkt_head; 13550 mutex_exit(&pptr->port_pkt_mutex); 13551 13552 if (cmd->cmd_fp_pkt->pkt_timeout == 13553 FCP_INVALID_TIMEOUT) { 13554 struct scsi_pkt *pkt = cmd->cmd_pkt; 13555 struct fcp_lun *plun; 13556 struct fcp_tgt *ptgt; 13557 13558 plun = ADDR2LUN(&pkt->pkt_address); 13559 ptgt = plun->lun_tgt; 13560 13561 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13562 fcp_trace, FCP_BUF_LEVEL_2, 0, 13563 "SCSI cmd 0x%x to D_ID=%x timed out", 13564 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13565 13566 cmd->cmd_state == FCP_PKT_ABORTING ? 13567 fcp_fail_cmd(cmd, CMD_RESET, 13568 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13569 CMD_TIMEOUT, STAT_ABORTED); 13570 } else { 13571 fcp_retransport_cmd(pptr, cmd); 13572 } 13573 mutex_enter(&pptr->port_pkt_mutex); 13574 if (save_head && save_head != pptr->port_pkt_head) { 13575 /* 13576 * Looks like linked list got changed (mostly 13577 * happens when an an OFFLINE LUN code starts 13578 * returning overflow queue commands in 13579 * parallel. So bail out and revisit during 13580 * next tick 13581 */ 13582 break; 13583 } 13584 end_of_loop: 13585 /* 13586 * Scan only upto the previously known tail pointer 13587 * to avoid excessive processing - lots of new packets 13588 * could have been added to the tail or the old ones 13589 * re-queued. 13590 */ 13591 if (cmd == tail) { 13592 break; 13593 } 13594 } 13595 mutex_exit(&pptr->port_pkt_mutex); 13596 13597 mutex_enter(&pptr->port_mutex); 13598 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13599 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13600 13601 nicmd = icmd->ipkt_next; 13602 if ((icmd->ipkt_restart != 0) && 13603 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13604 /* packet has not timed out */ 13605 continue; 13606 } 13607 13608 /* time for packet re-transport */ 13609 if (icmd == pptr->port_ipkt_list) { 13610 pptr->port_ipkt_list = icmd->ipkt_next; 13611 if (pptr->port_ipkt_list) { 13612 pptr->port_ipkt_list->ipkt_prev = 13613 NULL; 13614 } 13615 } else { 13616 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13617 if (icmd->ipkt_next) { 13618 icmd->ipkt_next->ipkt_prev = 13619 icmd->ipkt_prev; 13620 } 13621 } 13622 icmd->ipkt_next = NULL; 13623 icmd->ipkt_prev = NULL; 13624 mutex_exit(&pptr->port_mutex); 13625 13626 if (fcp_is_retryable(icmd)) { 13627 fc_ulp_rscn_info_t *rscnp = 13628 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13629 pkt_ulp_rscn_infop; 13630 13631 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13632 fcp_trace, FCP_BUF_LEVEL_2, 0, 13633 "%x to D_ID=%x Retrying..", 13634 icmd->ipkt_opcode, 13635 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13636 13637 /* 13638 * Update the RSCN count in the packet 13639 * before resending. 13640 */ 13641 13642 if (rscnp != NULL) { 13643 rscnp->ulp_rscn_count = 13644 fc_ulp_get_rscn_count(pptr-> 13645 port_fp_handle); 13646 } 13647 13648 mutex_enter(&pptr->port_mutex); 13649 mutex_enter(&ptgt->tgt_mutex); 13650 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13651 mutex_exit(&ptgt->tgt_mutex); 13652 mutex_exit(&pptr->port_mutex); 13653 switch (icmd->ipkt_opcode) { 13654 int rval; 13655 case LA_ELS_PLOGI: 13656 if ((rval = fc_ulp_login( 13657 pptr->port_fp_handle, 13658 &icmd->ipkt_fpkt, 1)) == 13659 FC_SUCCESS) { 13660 mutex_enter( 13661 &pptr->port_mutex); 13662 continue; 13663 } 13664 if (fcp_handle_ipkt_errors( 13665 pptr, ptgt, icmd, rval, 13666 "PLOGI") == DDI_SUCCESS) { 13667 mutex_enter( 13668 &pptr->port_mutex); 13669 continue; 13670 } 13671 break; 13672 13673 case LA_ELS_PRLI: 13674 if ((rval = fc_ulp_issue_els( 13675 pptr->port_fp_handle, 13676 icmd->ipkt_fpkt)) == 13677 FC_SUCCESS) { 13678 mutex_enter( 13679 &pptr->port_mutex); 13680 continue; 13681 } 13682 if (fcp_handle_ipkt_errors( 13683 pptr, ptgt, icmd, rval, 13684 "PRLI") == DDI_SUCCESS) { 13685 mutex_enter( 13686 &pptr->port_mutex); 13687 continue; 13688 } 13689 break; 13690 13691 default: 13692 if ((rval = fcp_transport( 13693 pptr->port_fp_handle, 13694 icmd->ipkt_fpkt, 1)) == 13695 FC_SUCCESS) { 13696 mutex_enter( 13697 &pptr->port_mutex); 13698 continue; 13699 } 13700 if (fcp_handle_ipkt_errors( 13701 pptr, ptgt, icmd, rval, 13702 "PRLI") == DDI_SUCCESS) { 13703 mutex_enter( 13704 &pptr->port_mutex); 13705 continue; 13706 } 13707 break; 13708 } 13709 } else { 13710 mutex_exit(&ptgt->tgt_mutex); 13711 mutex_exit(&pptr->port_mutex); 13712 } 13713 } else { 13714 fcp_print_error(icmd->ipkt_fpkt); 13715 } 13716 13717 (void) fcp_call_finish_init(pptr, ptgt, 13718 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13719 icmd->ipkt_cause); 13720 fcp_icmd_free(pptr, icmd); 13721 mutex_enter(&pptr->port_mutex); 13722 } 13723 13724 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13725 mutex_exit(&pptr->port_mutex); 13726 mutex_enter(&fcp_global_mutex); 13727 13728 end_of_watchdog: 13729 /* 13730 * Bail out early before getting into trouble 13731 */ 13732 if (save_port != fcp_port_head) { 13733 break; 13734 } 13735 } 13736 13737 if (fcp_watchdog_init > 0) { 13738 /* reschedule timeout to go again */ 13739 fcp_watchdog_id = 13740 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13741 } 13742 mutex_exit(&fcp_global_mutex); 13743 } 13744 13745 13746 static void 13747 fcp_check_reset_delay(struct fcp_port *pptr) 13748 { 13749 uint32_t tgt_cnt; 13750 int level; 13751 struct fcp_tgt *ptgt; 13752 struct fcp_lun *plun; 13753 struct fcp_reset_elem *cur = NULL; 13754 struct fcp_reset_elem *next = NULL; 13755 struct fcp_reset_elem *prev = NULL; 13756 13757 ASSERT(mutex_owned(&pptr->port_mutex)); 13758 13759 next = pptr->port_reset_list; 13760 while ((cur = next) != NULL) { 13761 next = cur->next; 13762 13763 if (cur->timeout < fcp_watchdog_time) { 13764 prev = cur; 13765 continue; 13766 } 13767 13768 ptgt = cur->tgt; 13769 plun = cur->lun; 13770 tgt_cnt = cur->tgt_cnt; 13771 13772 if (ptgt) { 13773 level = RESET_TARGET; 13774 } else { 13775 ASSERT(plun != NULL); 13776 level = RESET_LUN; 13777 ptgt = plun->lun_tgt; 13778 } 13779 if (prev) { 13780 prev->next = next; 13781 } else { 13782 /* 13783 * Because we drop port mutex while doing aborts for 13784 * packets, we can't rely on reset_list pointing to 13785 * our head 13786 */ 13787 if (cur == pptr->port_reset_list) { 13788 pptr->port_reset_list = next; 13789 } else { 13790 struct fcp_reset_elem *which; 13791 13792 which = pptr->port_reset_list; 13793 while (which && which->next != cur) { 13794 which = which->next; 13795 } 13796 ASSERT(which != NULL); 13797 13798 which->next = next; 13799 prev = which; 13800 } 13801 } 13802 13803 kmem_free(cur, sizeof (*cur)); 13804 13805 if (tgt_cnt == ptgt->tgt_change_cnt) { 13806 mutex_enter(&ptgt->tgt_mutex); 13807 if (level == RESET_TARGET) { 13808 fcp_update_tgt_state(ptgt, 13809 FCP_RESET, FCP_LUN_BUSY); 13810 } else { 13811 fcp_update_lun_state(plun, 13812 FCP_RESET, FCP_LUN_BUSY); 13813 } 13814 mutex_exit(&ptgt->tgt_mutex); 13815 13816 mutex_exit(&pptr->port_mutex); 13817 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13818 mutex_enter(&pptr->port_mutex); 13819 } 13820 } 13821 } 13822 13823 13824 static void 13825 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13826 struct fcp_lun *rlun, int tgt_cnt) 13827 { 13828 int rval; 13829 struct fcp_lun *tlun, *nlun; 13830 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13831 *cmd = NULL, *head = NULL, 13832 *tail = NULL; 13833 13834 mutex_enter(&pptr->port_pkt_mutex); 13835 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13836 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13837 struct fcp_tgt *ptgt = plun->lun_tgt; 13838 13839 ncmd = cmd->cmd_next; 13840 13841 if (ptgt != ttgt && plun != rlun) { 13842 pcmd = cmd; 13843 continue; 13844 } 13845 13846 if (pcmd != NULL) { 13847 ASSERT(pptr->port_pkt_head != cmd); 13848 pcmd->cmd_next = ncmd; 13849 } else { 13850 ASSERT(cmd == pptr->port_pkt_head); 13851 pptr->port_pkt_head = ncmd; 13852 } 13853 if (pptr->port_pkt_tail == cmd) { 13854 ASSERT(cmd->cmd_next == NULL); 13855 pptr->port_pkt_tail = pcmd; 13856 if (pcmd != NULL) { 13857 pcmd->cmd_next = NULL; 13858 } 13859 } 13860 13861 if (head == NULL) { 13862 head = tail = cmd; 13863 } else { 13864 ASSERT(tail != NULL); 13865 tail->cmd_next = cmd; 13866 tail = cmd; 13867 } 13868 cmd->cmd_next = NULL; 13869 } 13870 mutex_exit(&pptr->port_pkt_mutex); 13871 13872 for (cmd = head; cmd != NULL; cmd = ncmd) { 13873 struct scsi_pkt *pkt = cmd->cmd_pkt; 13874 13875 ncmd = cmd->cmd_next; 13876 ASSERT(pkt != NULL); 13877 13878 mutex_enter(&pptr->port_mutex); 13879 if (ttgt->tgt_change_cnt == tgt_cnt) { 13880 mutex_exit(&pptr->port_mutex); 13881 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13882 pkt->pkt_reason = CMD_RESET; 13883 pkt->pkt_statistics |= STAT_DEV_RESET; 13884 cmd->cmd_state = FCP_PKT_IDLE; 13885 fcp_post_callback(cmd); 13886 } else { 13887 mutex_exit(&pptr->port_mutex); 13888 } 13889 } 13890 13891 /* 13892 * If the FCA will return all the commands in its queue then our 13893 * work is easy, just return. 13894 */ 13895 13896 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13897 return; 13898 } 13899 13900 /* 13901 * For RESET_LUN get hold of target pointer 13902 */ 13903 if (ttgt == NULL) { 13904 ASSERT(rlun != NULL); 13905 13906 ttgt = rlun->lun_tgt; 13907 13908 ASSERT(ttgt != NULL); 13909 } 13910 13911 /* 13912 * There are some severe race conditions here. 13913 * While we are trying to abort the pkt, it might be completing 13914 * so mark it aborted and if the abort does not succeed then 13915 * handle it in the watch thread. 13916 */ 13917 mutex_enter(&ttgt->tgt_mutex); 13918 nlun = ttgt->tgt_lun; 13919 mutex_exit(&ttgt->tgt_mutex); 13920 while ((tlun = nlun) != NULL) { 13921 int restart = 0; 13922 if (rlun && rlun != tlun) { 13923 mutex_enter(&ttgt->tgt_mutex); 13924 nlun = tlun->lun_next; 13925 mutex_exit(&ttgt->tgt_mutex); 13926 continue; 13927 } 13928 mutex_enter(&tlun->lun_mutex); 13929 cmd = tlun->lun_pkt_head; 13930 while (cmd != NULL) { 13931 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13932 struct scsi_pkt *pkt; 13933 13934 restart = 1; 13935 cmd->cmd_state = FCP_PKT_ABORTING; 13936 mutex_exit(&tlun->lun_mutex); 13937 rval = fc_ulp_abort(pptr->port_fp_handle, 13938 cmd->cmd_fp_pkt, KM_SLEEP); 13939 if (rval == FC_SUCCESS) { 13940 pkt = cmd->cmd_pkt; 13941 pkt->pkt_reason = CMD_RESET; 13942 pkt->pkt_statistics |= STAT_DEV_RESET; 13943 cmd->cmd_state = FCP_PKT_IDLE; 13944 fcp_post_callback(cmd); 13945 } else { 13946 caddr_t msg; 13947 13948 (void) fc_ulp_error(rval, &msg); 13949 13950 /* 13951 * This part is tricky. The abort 13952 * failed and now the command could 13953 * be completing. The cmd_state == 13954 * FCP_PKT_ABORTING should save 13955 * us in fcp_cmd_callback. If we 13956 * are already aborting ignore the 13957 * command in fcp_cmd_callback. 13958 * Here we leave this packet for 20 13959 * sec to be aborted in the 13960 * fcp_watch thread. 13961 */ 13962 fcp_log(CE_WARN, pptr->port_dip, 13963 "!Abort failed after reset %s", 13964 msg); 13965 13966 cmd->cmd_timeout = 13967 fcp_watchdog_time + 13968 cmd->cmd_pkt->pkt_time + 13969 FCP_FAILED_DELAY; 13970 13971 cmd->cmd_fp_pkt->pkt_timeout = 13972 FCP_INVALID_TIMEOUT; 13973 /* 13974 * This is a hack, cmd is put in the 13975 * overflow queue so that it can be 13976 * timed out finally 13977 */ 13978 cmd->cmd_flags |= CFLAG_IN_QUEUE; 13979 13980 mutex_enter(&pptr->port_pkt_mutex); 13981 if (pptr->port_pkt_head) { 13982 ASSERT(pptr->port_pkt_tail 13983 != NULL); 13984 pptr->port_pkt_tail->cmd_next 13985 = cmd; 13986 pptr->port_pkt_tail = cmd; 13987 } else { 13988 ASSERT(pptr->port_pkt_tail 13989 == NULL); 13990 pptr->port_pkt_head = 13991 pptr->port_pkt_tail 13992 = cmd; 13993 } 13994 cmd->cmd_next = NULL; 13995 mutex_exit(&pptr->port_pkt_mutex); 13996 } 13997 mutex_enter(&tlun->lun_mutex); 13998 cmd = tlun->lun_pkt_head; 13999 } else { 14000 cmd = cmd->cmd_forw; 14001 } 14002 } 14003 mutex_exit(&tlun->lun_mutex); 14004 14005 mutex_enter(&ttgt->tgt_mutex); 14006 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14007 mutex_exit(&ttgt->tgt_mutex); 14008 14009 mutex_enter(&pptr->port_mutex); 14010 if (tgt_cnt != ttgt->tgt_change_cnt) { 14011 mutex_exit(&pptr->port_mutex); 14012 return; 14013 } else { 14014 mutex_exit(&pptr->port_mutex); 14015 } 14016 } 14017 } 14018 14019 14020 /* 14021 * unlink the soft state, returning the soft state found (if any) 14022 * 14023 * acquires and releases the global mutex 14024 */ 14025 struct fcp_port * 14026 fcp_soft_state_unlink(struct fcp_port *pptr) 14027 { 14028 struct fcp_port *hptr; /* ptr index */ 14029 struct fcp_port *tptr; /* prev hptr */ 14030 14031 mutex_enter(&fcp_global_mutex); 14032 for (hptr = fcp_port_head, tptr = NULL; 14033 hptr != NULL; 14034 tptr = hptr, hptr = hptr->port_next) { 14035 if (hptr == pptr) { 14036 /* we found a match -- remove this item */ 14037 if (tptr == NULL) { 14038 /* we're at the head of the list */ 14039 fcp_port_head = hptr->port_next; 14040 } else { 14041 tptr->port_next = hptr->port_next; 14042 } 14043 break; /* success */ 14044 } 14045 } 14046 if (fcp_port_head == NULL) { 14047 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14048 } 14049 mutex_exit(&fcp_global_mutex); 14050 return (hptr); 14051 } 14052 14053 14054 /* 14055 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14056 * WWN and a LUN number 14057 */ 14058 /* ARGSUSED */ 14059 static struct fcp_lun * 14060 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14061 { 14062 int hash; 14063 struct fcp_tgt *ptgt; 14064 struct fcp_lun *plun; 14065 14066 ASSERT(mutex_owned(&pptr->port_mutex)); 14067 14068 hash = FCP_HASH(wwn); 14069 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14070 ptgt = ptgt->tgt_next) { 14071 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14072 sizeof (ptgt->tgt_port_wwn)) == 0) { 14073 mutex_enter(&ptgt->tgt_mutex); 14074 for (plun = ptgt->tgt_lun; 14075 plun != NULL; 14076 plun = plun->lun_next) { 14077 if (plun->lun_num == lun) { 14078 mutex_exit(&ptgt->tgt_mutex); 14079 return (plun); 14080 } 14081 } 14082 mutex_exit(&ptgt->tgt_mutex); 14083 return (NULL); 14084 } 14085 } 14086 return (NULL); 14087 } 14088 14089 /* 14090 * Function: fcp_prepare_pkt 14091 * 14092 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14093 * for fcp_start(). It binds the data or partially maps it. 14094 * Builds the FCP header and starts the initialization of the 14095 * Fibre Channel header. 14096 * 14097 * Argument: *pptr FCP port. 14098 * *cmd FCP packet. 14099 * *plun LUN the command will be sent to. 14100 * 14101 * Context: User, Kernel and Interrupt context. 14102 */ 14103 static void 14104 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14105 struct fcp_lun *plun) 14106 { 14107 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14108 struct fcp_tgt *ptgt = plun->lun_tgt; 14109 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14110 14111 ASSERT(cmd->cmd_pkt->pkt_comp || 14112 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14113 14114 if (cmd->cmd_pkt->pkt_numcookies) { 14115 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14116 fcmd->fcp_cntl.cntl_read_data = 1; 14117 fcmd->fcp_cntl.cntl_write_data = 0; 14118 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14119 } else { 14120 fcmd->fcp_cntl.cntl_read_data = 0; 14121 fcmd->fcp_cntl.cntl_write_data = 1; 14122 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14123 } 14124 14125 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14126 14127 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14128 ASSERT(fpkt->pkt_data_cookie_cnt <= 14129 pptr->port_data_dma_attr.dma_attr_sgllen); 14130 14131 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14132 14133 /* FCA needs pkt_datalen to be set */ 14134 fpkt->pkt_datalen = cmd->cmd_dmacount; 14135 fcmd->fcp_data_len = cmd->cmd_dmacount; 14136 } else { 14137 fcmd->fcp_cntl.cntl_read_data = 0; 14138 fcmd->fcp_cntl.cntl_write_data = 0; 14139 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14140 fpkt->pkt_datalen = 0; 14141 fcmd->fcp_data_len = 0; 14142 } 14143 14144 /* set up the Tagged Queuing type */ 14145 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14146 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14147 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14148 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14149 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14150 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14151 } else { 14152 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14153 } 14154 14155 fcmd->fcp_ent_addr = plun->lun_addr; 14156 14157 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14158 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14159 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14160 } else { 14161 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14162 } 14163 14164 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14165 cmd->cmd_pkt->pkt_state = 0; 14166 cmd->cmd_pkt->pkt_statistics = 0; 14167 cmd->cmd_pkt->pkt_resid = 0; 14168 14169 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14170 14171 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14172 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14173 fpkt->pkt_comp = NULL; 14174 } else { 14175 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14176 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14177 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14178 } 14179 fpkt->pkt_comp = fcp_cmd_callback; 14180 } 14181 14182 mutex_enter(&pptr->port_mutex); 14183 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14184 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14185 } 14186 mutex_exit(&pptr->port_mutex); 14187 14188 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14189 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14190 14191 /* 14192 * Save a few kernel cycles here 14193 */ 14194 #ifndef __lock_lint 14195 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14196 #endif /* __lock_lint */ 14197 } 14198 14199 static void 14200 fcp_post_callback(struct fcp_pkt *cmd) 14201 { 14202 scsi_hba_pkt_comp(cmd->cmd_pkt); 14203 } 14204 14205 14206 /* 14207 * called to do polled I/O by fcp_start() 14208 * 14209 * return a transport status value, i.e. TRAN_ACCECPT for success 14210 */ 14211 static int 14212 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14213 { 14214 int rval; 14215 14216 #ifdef DEBUG 14217 mutex_enter(&pptr->port_pkt_mutex); 14218 pptr->port_npkts++; 14219 mutex_exit(&pptr->port_pkt_mutex); 14220 #endif /* DEBUG */ 14221 14222 if (cmd->cmd_fp_pkt->pkt_timeout) { 14223 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14224 } else { 14225 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14226 } 14227 14228 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14229 14230 cmd->cmd_state = FCP_PKT_ISSUED; 14231 14232 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14233 14234 #ifdef DEBUG 14235 mutex_enter(&pptr->port_pkt_mutex); 14236 pptr->port_npkts--; 14237 mutex_exit(&pptr->port_pkt_mutex); 14238 #endif /* DEBUG */ 14239 14240 cmd->cmd_state = FCP_PKT_IDLE; 14241 14242 switch (rval) { 14243 case FC_SUCCESS: 14244 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14245 fcp_complete_pkt(cmd->cmd_fp_pkt); 14246 rval = TRAN_ACCEPT; 14247 } else { 14248 rval = TRAN_FATAL_ERROR; 14249 } 14250 break; 14251 14252 case FC_TRAN_BUSY: 14253 rval = TRAN_BUSY; 14254 cmd->cmd_pkt->pkt_resid = 0; 14255 break; 14256 14257 case FC_BADPACKET: 14258 rval = TRAN_BADPKT; 14259 break; 14260 14261 default: 14262 rval = TRAN_FATAL_ERROR; 14263 break; 14264 } 14265 14266 return (rval); 14267 } 14268 14269 14270 /* 14271 * called by some of the following transport-called routines to convert 14272 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14273 */ 14274 static struct fcp_port * 14275 fcp_dip2port(dev_info_t *dip) 14276 { 14277 int instance; 14278 14279 instance = ddi_get_instance(dip); 14280 return (ddi_get_soft_state(fcp_softstate, instance)); 14281 } 14282 14283 14284 /* 14285 * called internally to return a LUN given a dip 14286 */ 14287 struct fcp_lun * 14288 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14289 { 14290 struct fcp_tgt *ptgt; 14291 struct fcp_lun *plun; 14292 int i; 14293 14294 14295 ASSERT(mutex_owned(&pptr->port_mutex)); 14296 14297 for (i = 0; i < FCP_NUM_HASH; i++) { 14298 for (ptgt = pptr->port_tgt_hash_table[i]; 14299 ptgt != NULL; 14300 ptgt = ptgt->tgt_next) { 14301 mutex_enter(&ptgt->tgt_mutex); 14302 for (plun = ptgt->tgt_lun; plun != NULL; 14303 plun = plun->lun_next) { 14304 mutex_enter(&plun->lun_mutex); 14305 if (plun->lun_cip == cip) { 14306 mutex_exit(&plun->lun_mutex); 14307 mutex_exit(&ptgt->tgt_mutex); 14308 return (plun); /* match found */ 14309 } 14310 mutex_exit(&plun->lun_mutex); 14311 } 14312 mutex_exit(&ptgt->tgt_mutex); 14313 } 14314 } 14315 return (NULL); /* no LUN found */ 14316 } 14317 14318 /* 14319 * pass an element to the hotplug list, kick the hotplug thread 14320 * and wait for the element to get processed by the hotplug thread. 14321 * on return the element is freed. 14322 * 14323 * return zero success and non-zero on failure 14324 * 14325 * acquires/releases the target mutex 14326 * 14327 */ 14328 static int 14329 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14330 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14331 { 14332 struct fcp_hp_elem *elem; 14333 int rval; 14334 14335 mutex_enter(&plun->lun_tgt->tgt_mutex); 14336 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14337 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14338 mutex_exit(&plun->lun_tgt->tgt_mutex); 14339 fcp_log(CE_CONT, pptr->port_dip, 14340 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14341 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14342 return (NDI_FAILURE); 14343 } 14344 mutex_exit(&plun->lun_tgt->tgt_mutex); 14345 mutex_enter(&elem->mutex); 14346 if (elem->wait) { 14347 while (elem->wait) { 14348 cv_wait(&elem->cv, &elem->mutex); 14349 } 14350 } 14351 rval = (elem->result); 14352 mutex_exit(&elem->mutex); 14353 mutex_destroy(&elem->mutex); 14354 cv_destroy(&elem->cv); 14355 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14356 return (rval); 14357 } 14358 14359 /* 14360 * pass an element to the hotplug list, and then 14361 * kick the hotplug thread 14362 * 14363 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14364 * 14365 * acquires/releases the hotplug mutex 14366 * 14367 * called with the target mutex owned 14368 * 14369 * memory acquired in NOSLEEP mode 14370 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14371 * for the hp daemon to process the request and is responsible for 14372 * freeing the element 14373 */ 14374 static struct fcp_hp_elem * 14375 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14376 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14377 { 14378 struct fcp_hp_elem *elem; 14379 dev_info_t *pdip; 14380 14381 ASSERT(pptr != NULL); 14382 ASSERT(plun != NULL); 14383 ASSERT(plun->lun_tgt != NULL); 14384 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14385 14386 /* create space for a hotplug element */ 14387 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14388 == NULL) { 14389 fcp_log(CE_WARN, NULL, 14390 "!can't allocate memory for hotplug element"); 14391 return (NULL); 14392 } 14393 14394 /* fill in hotplug element */ 14395 elem->port = pptr; 14396 elem->lun = plun; 14397 elem->cip = cip; 14398 elem->old_lun_mpxio = plun->lun_mpxio; 14399 elem->what = what; 14400 elem->flags = flags; 14401 elem->link_cnt = link_cnt; 14402 elem->tgt_cnt = tgt_cnt; 14403 elem->wait = wait; 14404 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14405 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14406 14407 /* schedule the hotplug task */ 14408 pdip = pptr->port_dip; 14409 mutex_enter(&plun->lun_mutex); 14410 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14411 plun->lun_event_count++; 14412 elem->event_cnt = plun->lun_event_count; 14413 } 14414 mutex_exit(&plun->lun_mutex); 14415 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14416 (void *)elem, KM_NOSLEEP) == NULL) { 14417 mutex_enter(&plun->lun_mutex); 14418 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14419 plun->lun_event_count--; 14420 } 14421 mutex_exit(&plun->lun_mutex); 14422 kmem_free(elem, sizeof (*elem)); 14423 return (0); 14424 } 14425 14426 return (elem); 14427 } 14428 14429 14430 static void 14431 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14432 { 14433 int rval; 14434 struct scsi_address *ap; 14435 struct fcp_lun *plun; 14436 struct fcp_tgt *ptgt; 14437 fc_packet_t *fpkt; 14438 14439 ap = &cmd->cmd_pkt->pkt_address; 14440 plun = ADDR2LUN(ap); 14441 ptgt = plun->lun_tgt; 14442 14443 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14444 14445 cmd->cmd_state = FCP_PKT_IDLE; 14446 14447 mutex_enter(&pptr->port_mutex); 14448 mutex_enter(&ptgt->tgt_mutex); 14449 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14450 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14451 fc_ulp_rscn_info_t *rscnp; 14452 14453 cmd->cmd_state = FCP_PKT_ISSUED; 14454 14455 /* 14456 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14457 * originally NULL, hence we try to set it to the pd pointed 14458 * to by the SCSI device we're trying to get to. 14459 */ 14460 14461 fpkt = cmd->cmd_fp_pkt; 14462 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14463 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14464 /* 14465 * We need to notify the transport that we now have a 14466 * reference to the remote port handle. 14467 */ 14468 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14469 } 14470 14471 mutex_exit(&ptgt->tgt_mutex); 14472 mutex_exit(&pptr->port_mutex); 14473 14474 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14475 14476 /* prepare the packet */ 14477 14478 fcp_prepare_pkt(pptr, cmd, plun); 14479 14480 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14481 pkt_ulp_rscn_infop; 14482 14483 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14484 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14485 14486 if (rscnp != NULL) { 14487 rscnp->ulp_rscn_count = 14488 fc_ulp_get_rscn_count(pptr-> 14489 port_fp_handle); 14490 } 14491 14492 rval = fcp_transport(pptr->port_fp_handle, 14493 cmd->cmd_fp_pkt, 0); 14494 14495 if (rval == FC_SUCCESS) { 14496 return; 14497 } 14498 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14499 } else { 14500 mutex_exit(&ptgt->tgt_mutex); 14501 mutex_exit(&pptr->port_mutex); 14502 } 14503 14504 fcp_queue_pkt(pptr, cmd); 14505 } 14506 14507 14508 static void 14509 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14510 { 14511 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14512 14513 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14514 cmd->cmd_state = FCP_PKT_IDLE; 14515 14516 cmd->cmd_pkt->pkt_reason = reason; 14517 cmd->cmd_pkt->pkt_state = 0; 14518 cmd->cmd_pkt->pkt_statistics = statistics; 14519 14520 fcp_post_callback(cmd); 14521 } 14522 14523 /* 14524 * Function: fcp_queue_pkt 14525 * 14526 * Description: This function queues the packet passed by the caller into 14527 * the list of packets of the FCP port. 14528 * 14529 * Argument: *pptr FCP port. 14530 * *cmd FCP packet to queue. 14531 * 14532 * Return Value: None 14533 * 14534 * Context: User, Kernel and Interrupt context. 14535 */ 14536 static void 14537 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14538 { 14539 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14540 14541 mutex_enter(&pptr->port_pkt_mutex); 14542 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14543 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14544 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14545 14546 /* 14547 * zero pkt_time means hang around for ever 14548 */ 14549 if (cmd->cmd_pkt->pkt_time) { 14550 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14551 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14552 } else { 14553 /* 14554 * Indicate the watch thread to fail the 14555 * command by setting it to highest value 14556 */ 14557 cmd->cmd_timeout = fcp_watchdog_time; 14558 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14559 } 14560 } 14561 14562 if (pptr->port_pkt_head) { 14563 ASSERT(pptr->port_pkt_tail != NULL); 14564 14565 pptr->port_pkt_tail->cmd_next = cmd; 14566 pptr->port_pkt_tail = cmd; 14567 } else { 14568 ASSERT(pptr->port_pkt_tail == NULL); 14569 14570 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14571 } 14572 cmd->cmd_next = NULL; 14573 mutex_exit(&pptr->port_pkt_mutex); 14574 } 14575 14576 /* 14577 * Function: fcp_update_targets 14578 * 14579 * Description: This function applies the specified change of state to all 14580 * the targets listed. The operation applied is 'set'. 14581 * 14582 * Argument: *pptr FCP port. 14583 * *dev_list Array of fc_portmap_t structures. 14584 * count Length of dev_list. 14585 * state State bits to update. 14586 * cause Reason for the update. 14587 * 14588 * Return Value: None 14589 * 14590 * Context: User, Kernel and Interrupt context. 14591 * The mutex pptr->port_mutex must be held. 14592 */ 14593 static void 14594 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14595 uint32_t count, uint32_t state, int cause) 14596 { 14597 fc_portmap_t *map_entry; 14598 struct fcp_tgt *ptgt; 14599 14600 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14601 14602 while (count--) { 14603 map_entry = &(dev_list[count]); 14604 ptgt = fcp_lookup_target(pptr, 14605 (uchar_t *)&(map_entry->map_pwwn)); 14606 if (ptgt == NULL) { 14607 continue; 14608 } 14609 14610 mutex_enter(&ptgt->tgt_mutex); 14611 ptgt->tgt_trace = 0; 14612 ptgt->tgt_change_cnt++; 14613 ptgt->tgt_statec_cause = cause; 14614 ptgt->tgt_tmp_cnt = 1; 14615 fcp_update_tgt_state(ptgt, FCP_SET, state); 14616 mutex_exit(&ptgt->tgt_mutex); 14617 } 14618 } 14619 14620 static int 14621 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14622 int lcount, int tcount, int cause) 14623 { 14624 int rval; 14625 14626 mutex_enter(&pptr->port_mutex); 14627 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14628 mutex_exit(&pptr->port_mutex); 14629 14630 return (rval); 14631 } 14632 14633 14634 static int 14635 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14636 int lcount, int tcount, int cause) 14637 { 14638 int finish_init = 0; 14639 int finish_tgt = 0; 14640 int do_finish_init = 0; 14641 int rval = FCP_NO_CHANGE; 14642 14643 if (cause == FCP_CAUSE_LINK_CHANGE || 14644 cause == FCP_CAUSE_LINK_DOWN) { 14645 do_finish_init = 1; 14646 } 14647 14648 if (ptgt != NULL) { 14649 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14650 FCP_BUF_LEVEL_2, 0, 14651 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14652 " cause = %d, d_id = 0x%x, tgt_done = %d", 14653 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14654 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14655 ptgt->tgt_d_id, ptgt->tgt_done); 14656 14657 mutex_enter(&ptgt->tgt_mutex); 14658 14659 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14660 rval = FCP_DEV_CHANGE; 14661 if (do_finish_init && ptgt->tgt_done == 0) { 14662 ptgt->tgt_done++; 14663 finish_init = 1; 14664 } 14665 } else { 14666 if (--ptgt->tgt_tmp_cnt <= 0) { 14667 ptgt->tgt_tmp_cnt = 0; 14668 finish_tgt = 1; 14669 14670 if (do_finish_init) { 14671 finish_init = 1; 14672 } 14673 } 14674 } 14675 mutex_exit(&ptgt->tgt_mutex); 14676 } else { 14677 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14678 FCP_BUF_LEVEL_2, 0, 14679 "Call Finish Init for NO target"); 14680 14681 if (do_finish_init) { 14682 finish_init = 1; 14683 } 14684 } 14685 14686 if (finish_tgt) { 14687 ASSERT(ptgt != NULL); 14688 14689 mutex_enter(&ptgt->tgt_mutex); 14690 #ifdef DEBUG 14691 bzero(ptgt->tgt_tmp_cnt_stack, 14692 sizeof (ptgt->tgt_tmp_cnt_stack)); 14693 14694 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14695 FCP_STACK_DEPTH); 14696 #endif /* DEBUG */ 14697 mutex_exit(&ptgt->tgt_mutex); 14698 14699 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14700 } 14701 14702 if (finish_init && lcount == pptr->port_link_cnt) { 14703 ASSERT(pptr->port_tmp_cnt > 0); 14704 if (--pptr->port_tmp_cnt == 0) { 14705 fcp_finish_init(pptr); 14706 } 14707 } else if (lcount != pptr->port_link_cnt) { 14708 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14709 fcp_trace, FCP_BUF_LEVEL_2, 0, 14710 "fcp_call_finish_init_held,1: state change occured" 14711 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14712 } 14713 14714 return (rval); 14715 } 14716 14717 static void 14718 fcp_reconfigure_luns(void * tgt_handle) 14719 { 14720 uint32_t dev_cnt; 14721 fc_portmap_t *devlist; 14722 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14723 struct fcp_port *pptr = ptgt->tgt_port; 14724 14725 /* 14726 * If the timer that fires this off got canceled too late, the 14727 * target could have been destroyed. 14728 */ 14729 14730 if (ptgt->tgt_tid == NULL) { 14731 return; 14732 } 14733 14734 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14735 if (devlist == NULL) { 14736 fcp_log(CE_WARN, pptr->port_dip, 14737 "!fcp%d: failed to allocate for portmap", 14738 pptr->port_instance); 14739 return; 14740 } 14741 14742 dev_cnt = 1; 14743 devlist->map_pd = ptgt->tgt_pd_handle; 14744 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14745 devlist->map_did.port_id = ptgt->tgt_d_id; 14746 14747 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14748 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14749 14750 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14751 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14752 devlist->map_flags = 0; 14753 14754 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14755 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14756 14757 /* 14758 * Clear the tgt_tid after no more references to 14759 * the fcp_tgt 14760 */ 14761 mutex_enter(&ptgt->tgt_mutex); 14762 ptgt->tgt_tid = NULL; 14763 mutex_exit(&ptgt->tgt_mutex); 14764 14765 kmem_free(devlist, sizeof (*devlist)); 14766 } 14767 14768 14769 static void 14770 fcp_free_targets(struct fcp_port *pptr) 14771 { 14772 int i; 14773 struct fcp_tgt *ptgt; 14774 14775 mutex_enter(&pptr->port_mutex); 14776 for (i = 0; i < FCP_NUM_HASH; i++) { 14777 ptgt = pptr->port_tgt_hash_table[i]; 14778 while (ptgt != NULL) { 14779 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14780 14781 fcp_free_target(ptgt); 14782 ptgt = next_tgt; 14783 } 14784 } 14785 mutex_exit(&pptr->port_mutex); 14786 } 14787 14788 14789 static void 14790 fcp_free_target(struct fcp_tgt *ptgt) 14791 { 14792 struct fcp_lun *plun; 14793 timeout_id_t tid; 14794 14795 mutex_enter(&ptgt->tgt_mutex); 14796 tid = ptgt->tgt_tid; 14797 14798 /* 14799 * Cancel any pending timeouts for this target. 14800 */ 14801 14802 if (tid != NULL) { 14803 /* 14804 * Set tgt_tid to NULL first to avoid a race in the callback. 14805 * If tgt_tid is NULL, the callback will simply return. 14806 */ 14807 ptgt->tgt_tid = NULL; 14808 mutex_exit(&ptgt->tgt_mutex); 14809 (void) untimeout(tid); 14810 mutex_enter(&ptgt->tgt_mutex); 14811 } 14812 14813 plun = ptgt->tgt_lun; 14814 while (plun != NULL) { 14815 struct fcp_lun *next_lun = plun->lun_next; 14816 14817 fcp_dealloc_lun(plun); 14818 plun = next_lun; 14819 } 14820 14821 mutex_exit(&ptgt->tgt_mutex); 14822 fcp_dealloc_tgt(ptgt); 14823 } 14824 14825 /* 14826 * Function: fcp_is_retryable 14827 * 14828 * Description: Indicates if the internal packet is retryable. 14829 * 14830 * Argument: *icmd FCP internal packet. 14831 * 14832 * Return Value: 0 Not retryable 14833 * 1 Retryable 14834 * 14835 * Context: User, Kernel and Interrupt context 14836 */ 14837 static int 14838 fcp_is_retryable(struct fcp_ipkt *icmd) 14839 { 14840 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14841 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14842 return (0); 14843 } 14844 14845 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14846 icmd->ipkt_port->port_deadline) ? 1 : 0); 14847 } 14848 14849 /* 14850 * Function: fcp_create_on_demand 14851 * 14852 * Argument: *pptr FCP port. 14853 * *pwwn Port WWN. 14854 * 14855 * Return Value: 0 Success 14856 * EIO 14857 * ENOMEM 14858 * EBUSY 14859 * EINVAL 14860 * 14861 * Context: User and Kernel context 14862 */ 14863 static int 14864 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14865 { 14866 int wait_ms; 14867 int tcount; 14868 int lcount; 14869 int ret; 14870 int error; 14871 int rval = EIO; 14872 int ntries; 14873 fc_portmap_t *devlist; 14874 opaque_t pd; 14875 struct fcp_lun *plun; 14876 struct fcp_tgt *ptgt; 14877 int old_manual = 0; 14878 14879 /* Allocates the fc_portmap_t structure. */ 14880 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14881 14882 /* 14883 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14884 * in the commented statement below: 14885 * 14886 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14887 * 14888 * Below, the deadline for the discovery process is set. 14889 */ 14890 mutex_enter(&pptr->port_mutex); 14891 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14892 mutex_exit(&pptr->port_mutex); 14893 14894 /* 14895 * We try to find the remote port based on the WWN provided by the 14896 * caller. We actually ask fp/fctl if it has it. 14897 */ 14898 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14899 (la_wwn_t *)pwwn, &error, 1); 14900 14901 if (pd == NULL) { 14902 kmem_free(devlist, sizeof (*devlist)); 14903 return (rval); 14904 } 14905 14906 /* 14907 * The remote port was found. We ask fp/fctl to update our 14908 * fc_portmap_t structure. 14909 */ 14910 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14911 (la_wwn_t *)pwwn, devlist); 14912 if (ret != FC_SUCCESS) { 14913 kmem_free(devlist, sizeof (*devlist)); 14914 return (rval); 14915 } 14916 14917 /* 14918 * The map flag field is set to indicates that the creation is being 14919 * done at the user request (Ioclt probably luxadm or cfgadm). 14920 */ 14921 devlist->map_type = PORT_DEVICE_USER_CREATE; 14922 14923 mutex_enter(&pptr->port_mutex); 14924 14925 /* 14926 * We check to see if fcp already has a target that describes the 14927 * device being created. If not it is created. 14928 */ 14929 ptgt = fcp_lookup_target(pptr, pwwn); 14930 if (ptgt == NULL) { 14931 lcount = pptr->port_link_cnt; 14932 mutex_exit(&pptr->port_mutex); 14933 14934 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14935 if (ptgt == NULL) { 14936 fcp_log(CE_WARN, pptr->port_dip, 14937 "!FC target allocation failed"); 14938 return (ENOMEM); 14939 } 14940 14941 mutex_enter(&pptr->port_mutex); 14942 } 14943 14944 mutex_enter(&ptgt->tgt_mutex); 14945 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14946 ptgt->tgt_tmp_cnt = 1; 14947 ptgt->tgt_device_created = 0; 14948 /* 14949 * If fabric and auto config is set but the target was 14950 * manually unconfigured then reset to the manual_config_only to 14951 * 0 so the device will get configured. 14952 */ 14953 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14954 fcp_enable_auto_configuration && 14955 ptgt->tgt_manual_config_only == 1) { 14956 old_manual = 1; 14957 ptgt->tgt_manual_config_only = 0; 14958 } 14959 mutex_exit(&ptgt->tgt_mutex); 14960 14961 fcp_update_targets(pptr, devlist, 1, 14962 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14963 14964 lcount = pptr->port_link_cnt; 14965 tcount = ptgt->tgt_change_cnt; 14966 14967 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14968 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14969 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14970 fcp_enable_auto_configuration && old_manual) { 14971 mutex_enter(&ptgt->tgt_mutex); 14972 ptgt->tgt_manual_config_only = 1; 14973 mutex_exit(&ptgt->tgt_mutex); 14974 } 14975 14976 if (pptr->port_link_cnt != lcount || 14977 ptgt->tgt_change_cnt != tcount) { 14978 rval = EBUSY; 14979 } 14980 mutex_exit(&pptr->port_mutex); 14981 14982 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14983 FCP_BUF_LEVEL_3, 0, 14984 "fcp_create_on_demand: mapflags ptgt=%x, " 14985 "lcount=%x::port_link_cnt=%x, " 14986 "tcount=%x: tgt_change_cnt=%x, rval=%x", 14987 ptgt, lcount, pptr->port_link_cnt, 14988 tcount, ptgt->tgt_change_cnt, rval); 14989 return (rval); 14990 } 14991 14992 /* 14993 * Due to lack of synchronization mechanisms, we perform 14994 * periodic monitoring of our request; Because requests 14995 * get dropped when another one supercedes (either because 14996 * of a link change or a target change), it is difficult to 14997 * provide a clean synchronization mechanism (such as a 14998 * semaphore or a conditional variable) without exhaustively 14999 * rewriting the mainline discovery code of this driver. 15000 */ 15001 wait_ms = 500; 15002 15003 ntries = fcp_max_target_retries; 15004 15005 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15006 FCP_BUF_LEVEL_3, 0, 15007 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15008 "lcount=%x::port_link_cnt=%x, " 15009 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15010 "tgt_tmp_cnt =%x", 15011 ntries, ptgt, lcount, pptr->port_link_cnt, 15012 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15013 ptgt->tgt_tmp_cnt); 15014 15015 mutex_enter(&ptgt->tgt_mutex); 15016 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15017 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15018 mutex_exit(&ptgt->tgt_mutex); 15019 mutex_exit(&pptr->port_mutex); 15020 15021 delay(drv_usectohz(wait_ms * 1000)); 15022 15023 mutex_enter(&pptr->port_mutex); 15024 mutex_enter(&ptgt->tgt_mutex); 15025 } 15026 15027 15028 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15029 rval = EBUSY; 15030 } else { 15031 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15032 FCP_TGT_NODE_PRESENT) { 15033 rval = 0; 15034 } 15035 } 15036 15037 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15038 FCP_BUF_LEVEL_3, 0, 15039 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15040 "lcount=%x::port_link_cnt=%x, " 15041 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15042 "tgt_tmp_cnt =%x", 15043 ntries, ptgt, lcount, pptr->port_link_cnt, 15044 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15045 ptgt->tgt_tmp_cnt); 15046 15047 if (rval) { 15048 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15049 fcp_enable_auto_configuration && old_manual) { 15050 ptgt->tgt_manual_config_only = 1; 15051 } 15052 mutex_exit(&ptgt->tgt_mutex); 15053 mutex_exit(&pptr->port_mutex); 15054 kmem_free(devlist, sizeof (*devlist)); 15055 15056 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15057 FCP_BUF_LEVEL_3, 0, 15058 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15059 "lcount=%x::port_link_cnt=%x, " 15060 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15061 "tgt_device_created=%x, tgt D_ID=%x", 15062 ntries, ptgt, lcount, pptr->port_link_cnt, 15063 tcount, ptgt->tgt_change_cnt, rval, 15064 ptgt->tgt_device_created, ptgt->tgt_d_id); 15065 return (rval); 15066 } 15067 15068 if ((plun = ptgt->tgt_lun) != NULL) { 15069 tcount = plun->lun_tgt->tgt_change_cnt; 15070 } else { 15071 rval = EINVAL; 15072 } 15073 lcount = pptr->port_link_cnt; 15074 15075 /* 15076 * Configuring the target with no LUNs will fail. We 15077 * should reset the node state so that it is not 15078 * automatically configured when the LUNs are added 15079 * to this target. 15080 */ 15081 if (ptgt->tgt_lun_cnt == 0) { 15082 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15083 } 15084 mutex_exit(&ptgt->tgt_mutex); 15085 mutex_exit(&pptr->port_mutex); 15086 15087 while (plun) { 15088 child_info_t *cip; 15089 15090 mutex_enter(&plun->lun_mutex); 15091 cip = plun->lun_cip; 15092 mutex_exit(&plun->lun_mutex); 15093 15094 mutex_enter(&ptgt->tgt_mutex); 15095 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15096 mutex_exit(&ptgt->tgt_mutex); 15097 15098 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15099 FCP_ONLINE, lcount, tcount, 15100 NDI_ONLINE_ATTACH); 15101 if (rval != NDI_SUCCESS) { 15102 FCP_TRACE(fcp_logq, 15103 pptr->port_instbuf, fcp_trace, 15104 FCP_BUF_LEVEL_3, 0, 15105 "fcp_create_on_demand: " 15106 "pass_to_hp_and_wait failed " 15107 "rval=%x", rval); 15108 rval = EIO; 15109 } else { 15110 mutex_enter(&LUN_TGT->tgt_mutex); 15111 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15112 FCP_LUN_BUSY); 15113 mutex_exit(&LUN_TGT->tgt_mutex); 15114 } 15115 mutex_enter(&ptgt->tgt_mutex); 15116 } 15117 15118 plun = plun->lun_next; 15119 mutex_exit(&ptgt->tgt_mutex); 15120 } 15121 15122 kmem_free(devlist, sizeof (*devlist)); 15123 15124 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15125 fcp_enable_auto_configuration && old_manual) { 15126 mutex_enter(&ptgt->tgt_mutex); 15127 /* if successful then set manual to 0 */ 15128 if (rval == 0) { 15129 ptgt->tgt_manual_config_only = 0; 15130 } else { 15131 /* reset to 1 so the user has to do the config */ 15132 ptgt->tgt_manual_config_only = 1; 15133 } 15134 mutex_exit(&ptgt->tgt_mutex); 15135 } 15136 15137 return (rval); 15138 } 15139 15140 15141 static void 15142 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15143 { 15144 int count; 15145 uchar_t byte; 15146 15147 count = 0; 15148 while (*string) { 15149 byte = FCP_ATOB(*string); string++; 15150 byte = byte << 4 | FCP_ATOB(*string); string++; 15151 bytes[count++] = byte; 15152 15153 if (count >= byte_len) { 15154 break; 15155 } 15156 } 15157 } 15158 15159 static void 15160 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15161 { 15162 int i; 15163 15164 for (i = 0; i < FC_WWN_SIZE; i++) { 15165 (void) sprintf(string + (i * 2), 15166 "%02x", wwn[i]); 15167 } 15168 15169 } 15170 15171 static void 15172 fcp_print_error(fc_packet_t *fpkt) 15173 { 15174 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15175 fpkt->pkt_ulp_private; 15176 struct fcp_port *pptr; 15177 struct fcp_tgt *ptgt; 15178 struct fcp_lun *plun; 15179 caddr_t buf; 15180 int scsi_cmd = 0; 15181 15182 ptgt = icmd->ipkt_tgt; 15183 plun = icmd->ipkt_lun; 15184 pptr = ptgt->tgt_port; 15185 15186 buf = kmem_zalloc(256, KM_NOSLEEP); 15187 if (buf == NULL) { 15188 return; 15189 } 15190 15191 switch (icmd->ipkt_opcode) { 15192 case SCMD_REPORT_LUN: 15193 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15194 " lun=0x%%x failed"); 15195 scsi_cmd++; 15196 break; 15197 15198 case SCMD_INQUIRY_PAGE83: 15199 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15200 " lun=0x%%x failed"); 15201 scsi_cmd++; 15202 break; 15203 15204 case SCMD_INQUIRY: 15205 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15206 " lun=0x%%x failed"); 15207 scsi_cmd++; 15208 break; 15209 15210 case LA_ELS_PLOGI: 15211 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15212 break; 15213 15214 case LA_ELS_PRLI: 15215 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15216 break; 15217 } 15218 15219 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15220 struct fcp_rsp response, *rsp; 15221 uchar_t asc, ascq; 15222 caddr_t sense_key = NULL; 15223 struct fcp_rsp_info fcp_rsp_err, *bep; 15224 15225 if (icmd->ipkt_nodma) { 15226 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15227 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15228 sizeof (struct fcp_rsp)); 15229 } else { 15230 rsp = &response; 15231 bep = &fcp_rsp_err; 15232 15233 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15234 sizeof (struct fcp_rsp)); 15235 15236 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15237 bep, fpkt->pkt_resp_acc, 15238 sizeof (struct fcp_rsp_info)); 15239 } 15240 15241 15242 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15243 (void) sprintf(buf + strlen(buf), 15244 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15245 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15246 " senselen=%%x. Giving up"); 15247 15248 fcp_log(CE_WARN, pptr->port_dip, buf, 15249 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15250 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15251 rsp->fcp_u.fcp_status.reserved_1, 15252 rsp->fcp_response_len, rsp->fcp_sense_len); 15253 15254 kmem_free(buf, 256); 15255 return; 15256 } 15257 15258 if (rsp->fcp_u.fcp_status.rsp_len_set && 15259 bep->rsp_code != FCP_NO_FAILURE) { 15260 (void) sprintf(buf + strlen(buf), 15261 " FCP Response code = 0x%x", bep->rsp_code); 15262 } 15263 15264 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15265 struct scsi_extended_sense sense_info, *sense_ptr; 15266 15267 if (icmd->ipkt_nodma) { 15268 sense_ptr = (struct scsi_extended_sense *) 15269 ((caddr_t)fpkt->pkt_resp + 15270 sizeof (struct fcp_rsp) + 15271 rsp->fcp_response_len); 15272 } else { 15273 sense_ptr = &sense_info; 15274 15275 FCP_CP_IN(fpkt->pkt_resp + 15276 sizeof (struct fcp_rsp) + 15277 rsp->fcp_response_len, &sense_info, 15278 fpkt->pkt_resp_acc, 15279 sizeof (struct scsi_extended_sense)); 15280 } 15281 15282 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15283 NUM_IMPL_SENSE_KEYS) { 15284 sense_key = sense_keys[sense_ptr->es_key]; 15285 } else { 15286 sense_key = "Undefined"; 15287 } 15288 15289 asc = sense_ptr->es_add_code; 15290 ascq = sense_ptr->es_qual_code; 15291 15292 (void) sprintf(buf + strlen(buf), 15293 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15294 " Giving up"); 15295 15296 fcp_log(CE_WARN, pptr->port_dip, buf, 15297 ptgt->tgt_d_id, plun->lun_num, sense_key, 15298 asc, ascq); 15299 } else { 15300 (void) sprintf(buf + strlen(buf), 15301 " : SCSI status=%%x. Giving up"); 15302 15303 fcp_log(CE_WARN, pptr->port_dip, buf, 15304 ptgt->tgt_d_id, plun->lun_num, 15305 rsp->fcp_u.fcp_status.scsi_status); 15306 } 15307 } else { 15308 caddr_t state, reason, action, expln; 15309 15310 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15311 &action, &expln); 15312 15313 (void) sprintf(buf + strlen(buf), ": State:%%s," 15314 " Reason:%%s. Giving up"); 15315 15316 if (scsi_cmd) { 15317 fcp_log(CE_WARN, pptr->port_dip, buf, 15318 ptgt->tgt_d_id, plun->lun_num, state, reason); 15319 } else { 15320 fcp_log(CE_WARN, pptr->port_dip, buf, 15321 ptgt->tgt_d_id, state, reason); 15322 } 15323 } 15324 15325 kmem_free(buf, 256); 15326 } 15327 15328 15329 static int 15330 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15331 struct fcp_ipkt *icmd, int rval, caddr_t op) 15332 { 15333 int ret = DDI_FAILURE; 15334 char *error; 15335 15336 switch (rval) { 15337 case FC_DEVICE_BUSY_NEW_RSCN: 15338 /* 15339 * This means that there was a new RSCN that the transport 15340 * knows about (which the ULP *may* know about too) but the 15341 * pkt that was sent down was related to an older RSCN. So, we 15342 * are just going to reset the retry count and deadline and 15343 * continue to retry. The idea is that transport is currently 15344 * working on the new RSCN and will soon let the ULPs know 15345 * about it and when it does the existing logic will kick in 15346 * where it will change the tcount to indicate that something 15347 * changed on the target. So, rediscovery will start and there 15348 * will not be an infinite retry. 15349 * 15350 * For a full flow of how the RSCN info is transferred back and 15351 * forth, see fp.c 15352 */ 15353 icmd->ipkt_retries = 0; 15354 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15355 FCP_ICMD_DEADLINE; 15356 15357 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15358 FCP_BUF_LEVEL_3, 0, 15359 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15360 rval, ptgt->tgt_d_id); 15361 /* FALLTHROUGH */ 15362 15363 case FC_STATEC_BUSY: 15364 case FC_DEVICE_BUSY: 15365 case FC_PBUSY: 15366 case FC_FBUSY: 15367 case FC_TRAN_BUSY: 15368 case FC_OFFLINE: 15369 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15370 FCP_BUF_LEVEL_3, 0, 15371 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15372 rval, ptgt->tgt_d_id); 15373 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15374 fcp_is_retryable(icmd)) { 15375 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15376 ret = DDI_SUCCESS; 15377 } 15378 break; 15379 15380 case FC_LOGINREQ: 15381 /* 15382 * FC_LOGINREQ used to be handled just like all the cases 15383 * above. It has been changed to handled a PRLI that fails 15384 * with FC_LOGINREQ different than other ipkts that fail 15385 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15386 * a simple matter to turn it into a PLOGI instead, so that's 15387 * exactly what we do here. 15388 */ 15389 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15390 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15391 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15392 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15393 } else { 15394 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15395 FCP_BUF_LEVEL_3, 0, 15396 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15397 rval, ptgt->tgt_d_id); 15398 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15399 fcp_is_retryable(icmd)) { 15400 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15401 ret = DDI_SUCCESS; 15402 } 15403 } 15404 break; 15405 15406 default: 15407 mutex_enter(&pptr->port_mutex); 15408 mutex_enter(&ptgt->tgt_mutex); 15409 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15410 mutex_exit(&ptgt->tgt_mutex); 15411 mutex_exit(&pptr->port_mutex); 15412 15413 (void) fc_ulp_error(rval, &error); 15414 fcp_log(CE_WARN, pptr->port_dip, 15415 "!Failed to send %s to D_ID=%x error=%s", 15416 op, ptgt->tgt_d_id, error); 15417 } else { 15418 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15419 fcp_trace, FCP_BUF_LEVEL_2, 0, 15420 "fcp_handle_ipkt_errors,1: state change occured" 15421 " for D_ID=0x%x", ptgt->tgt_d_id); 15422 mutex_exit(&ptgt->tgt_mutex); 15423 mutex_exit(&pptr->port_mutex); 15424 } 15425 break; 15426 } 15427 15428 return (ret); 15429 } 15430 15431 15432 /* 15433 * Check of outstanding commands on any LUN for this target 15434 */ 15435 static int 15436 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15437 { 15438 struct fcp_lun *plun; 15439 struct fcp_pkt *cmd; 15440 15441 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15442 mutex_enter(&plun->lun_mutex); 15443 for (cmd = plun->lun_pkt_head; cmd != NULL; 15444 cmd = cmd->cmd_forw) { 15445 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15446 mutex_exit(&plun->lun_mutex); 15447 return (FC_SUCCESS); 15448 } 15449 } 15450 mutex_exit(&plun->lun_mutex); 15451 } 15452 15453 return (FC_FAILURE); 15454 } 15455 15456 static fc_portmap_t * 15457 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15458 { 15459 int i; 15460 fc_portmap_t *devlist; 15461 fc_portmap_t *devptr = NULL; 15462 struct fcp_tgt *ptgt; 15463 15464 mutex_enter(&pptr->port_mutex); 15465 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15466 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15467 ptgt = ptgt->tgt_next) { 15468 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15469 ++*dev_cnt; 15470 } 15471 } 15472 } 15473 15474 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15475 KM_NOSLEEP); 15476 if (devlist == NULL) { 15477 mutex_exit(&pptr->port_mutex); 15478 fcp_log(CE_WARN, pptr->port_dip, 15479 "!fcp%d: failed to allocate for portmap for construct map", 15480 pptr->port_instance); 15481 return (devptr); 15482 } 15483 15484 for (i = 0; i < FCP_NUM_HASH; i++) { 15485 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15486 ptgt = ptgt->tgt_next) { 15487 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15488 int ret; 15489 15490 ret = fc_ulp_pwwn_to_portmap( 15491 pptr->port_fp_handle, 15492 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15493 devlist); 15494 15495 if (ret == FC_SUCCESS) { 15496 devlist++; 15497 continue; 15498 } 15499 15500 devlist->map_pd = NULL; 15501 devlist->map_did.port_id = ptgt->tgt_d_id; 15502 devlist->map_hard_addr.hard_addr = 15503 ptgt->tgt_hard_addr; 15504 15505 devlist->map_state = PORT_DEVICE_INVALID; 15506 devlist->map_type = PORT_DEVICE_OLD; 15507 15508 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15509 &devlist->map_nwwn, FC_WWN_SIZE); 15510 15511 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15512 &devlist->map_pwwn, FC_WWN_SIZE); 15513 15514 devlist++; 15515 } 15516 } 15517 } 15518 15519 mutex_exit(&pptr->port_mutex); 15520 15521 return (devptr); 15522 } 15523 /* 15524 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15525 */ 15526 static void 15527 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15528 { 15529 int i; 15530 struct fcp_tgt *ptgt; 15531 struct fcp_lun *plun; 15532 15533 for (i = 0; i < FCP_NUM_HASH; i++) { 15534 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15535 ptgt = ptgt->tgt_next) { 15536 mutex_enter(&ptgt->tgt_mutex); 15537 for (plun = ptgt->tgt_lun; plun != NULL; 15538 plun = plun->lun_next) { 15539 if (plun->lun_mpxio && 15540 plun->lun_state & FCP_LUN_BUSY) { 15541 if (!fcp_pass_to_hp(pptr, plun, 15542 plun->lun_cip, 15543 FCP_MPXIO_PATH_SET_BUSY, 15544 pptr->port_link_cnt, 15545 ptgt->tgt_change_cnt, 0, 0)) { 15546 FCP_TRACE(fcp_logq, 15547 pptr->port_instbuf, 15548 fcp_trace, 15549 FCP_BUF_LEVEL_2, 0, 15550 "path_verifybusy: " 15551 "disable lun %p failed!", 15552 plun); 15553 } 15554 } 15555 } 15556 mutex_exit(&ptgt->tgt_mutex); 15557 } 15558 } 15559 } 15560 15561 static int 15562 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15563 { 15564 dev_info_t *cdip = NULL; 15565 dev_info_t *pdip = NULL; 15566 15567 ASSERT(plun); 15568 15569 mutex_enter(&plun->lun_mutex); 15570 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15571 mutex_exit(&plun->lun_mutex); 15572 return (NDI_FAILURE); 15573 } 15574 mutex_exit(&plun->lun_mutex); 15575 cdip = mdi_pi_get_client(PIP(cip)); 15576 pdip = mdi_pi_get_phci(PIP(cip)); 15577 15578 ASSERT(cdip != NULL); 15579 ASSERT(pdip != NULL); 15580 15581 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15582 /* LUN ready for IO */ 15583 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15584 } else { 15585 /* LUN busy to accept IO */ 15586 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15587 } 15588 return (NDI_SUCCESS); 15589 } 15590 15591 /* 15592 * Caller must free the returned string of MAXPATHLEN len 15593 * If the device is offline (-1 instance number) NULL 15594 * will be returned. 15595 */ 15596 static char * 15597 fcp_get_lun_path(struct fcp_lun *plun) 15598 { 15599 dev_info_t *dip = NULL; 15600 char *path = NULL; 15601 mdi_pathinfo_t *pip = NULL; 15602 15603 if (plun == NULL) { 15604 return (NULL); 15605 } 15606 15607 mutex_enter(&plun->lun_mutex); 15608 if (plun->lun_mpxio == 0) { 15609 dip = DIP(plun->lun_cip); 15610 mutex_exit(&plun->lun_mutex); 15611 } else { 15612 /* 15613 * lun_cip must be accessed with lun_mutex held. Here 15614 * plun->lun_cip either points to a valid node or it is NULL. 15615 * Make a copy so that we can release lun_mutex. 15616 */ 15617 pip = PIP(plun->lun_cip); 15618 15619 /* 15620 * Increase ref count on the path so that we can release 15621 * lun_mutex and still be sure that the pathinfo node (and thus 15622 * also the client) is not deallocated. If pip is NULL, this 15623 * has no effect. 15624 */ 15625 mdi_hold_path(pip); 15626 15627 mutex_exit(&plun->lun_mutex); 15628 15629 /* Get the client. If pip is NULL, we get NULL. */ 15630 dip = mdi_pi_get_client(pip); 15631 } 15632 15633 if (dip == NULL) 15634 goto out; 15635 if (ddi_get_instance(dip) < 0) 15636 goto out; 15637 15638 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15639 if (path == NULL) 15640 goto out; 15641 15642 (void) ddi_pathname(dip, path); 15643 15644 /* Clean up. */ 15645 out: 15646 if (pip != NULL) 15647 mdi_rele_path(pip); 15648 15649 /* 15650 * In reality, the user wants a fully valid path (one they can open) 15651 * but this string is lacking the mount point, and the minor node. 15652 * It would be nice if we could "figure these out" somehow 15653 * and fill them in. Otherwise, the userland code has to understand 15654 * driver specific details of which minor node is the "best" or 15655 * "right" one to expose. (Ex: which slice is the whole disk, or 15656 * which tape doesn't rewind) 15657 */ 15658 return (path); 15659 } 15660 15661 static int 15662 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15663 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15664 { 15665 int64_t reset_delay; 15666 int rval, retry = 0; 15667 struct fcp_port *pptr = fcp_dip2port(parent); 15668 15669 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15670 (ddi_get_lbolt64() - pptr->port_attach_time); 15671 if (reset_delay < 0) { 15672 reset_delay = 0; 15673 } 15674 15675 if (fcp_bus_config_debug) { 15676 flag |= NDI_DEVI_DEBUG; 15677 } 15678 15679 switch (op) { 15680 case BUS_CONFIG_ONE: 15681 /* 15682 * Retry the command since we need to ensure 15683 * the fabric devices are available for root 15684 */ 15685 while (retry++ < fcp_max_bus_config_retries) { 15686 rval = (ndi_busop_bus_config(parent, 15687 flag | NDI_MDI_FALLBACK, op, 15688 arg, childp, (clock_t)reset_delay)); 15689 if (rval == 0) { 15690 return (rval); 15691 } 15692 } 15693 15694 /* 15695 * drain taskq to make sure nodes are created and then 15696 * try again. 15697 */ 15698 taskq_wait(DEVI(parent)->devi_taskq); 15699 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15700 op, arg, childp, 0)); 15701 15702 case BUS_CONFIG_DRIVER: 15703 case BUS_CONFIG_ALL: { 15704 /* 15705 * delay till all devices report in (port_tmp_cnt == 0) 15706 * or FCP_INIT_WAIT_TIMEOUT 15707 */ 15708 mutex_enter(&pptr->port_mutex); 15709 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15710 (void) cv_timedwait(&pptr->port_config_cv, 15711 &pptr->port_mutex, 15712 ddi_get_lbolt() + (clock_t)reset_delay); 15713 reset_delay = 15714 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15715 (ddi_get_lbolt64() - pptr->port_attach_time); 15716 } 15717 mutex_exit(&pptr->port_mutex); 15718 /* drain taskq to make sure nodes are created */ 15719 taskq_wait(DEVI(parent)->devi_taskq); 15720 return (ndi_busop_bus_config(parent, flag, op, 15721 arg, childp, 0)); 15722 } 15723 15724 default: 15725 return (NDI_FAILURE); 15726 } 15727 /*NOTREACHED*/ 15728 } 15729 15730 static int 15731 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15732 ddi_bus_config_op_t op, void *arg) 15733 { 15734 if (fcp_bus_config_debug) { 15735 flag |= NDI_DEVI_DEBUG; 15736 } 15737 15738 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15739 } 15740 15741 15742 /* 15743 * Routine to copy GUID into the lun structure. 15744 * returns 0 if copy was successful and 1 if encountered a 15745 * failure and did not copy the guid. 15746 */ 15747 static int 15748 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15749 { 15750 15751 int retval = 0; 15752 15753 /* add one for the null terminator */ 15754 const unsigned int len = strlen(guidp) + 1; 15755 15756 if ((guidp == NULL) || (plun == NULL)) { 15757 return (1); 15758 } 15759 15760 /* 15761 * if the plun->lun_guid already has been allocated, 15762 * then check the size. if the size is exact, reuse 15763 * it....if not free it an allocate the required size. 15764 * The reallocation should NOT typically happen 15765 * unless the GUIDs reported changes between passes. 15766 * We free up and alloc again even if the 15767 * size was more than required. This is due to the 15768 * fact that the field lun_guid_size - serves 15769 * dual role of indicating the size of the wwn 15770 * size and ALSO the allocation size. 15771 */ 15772 if (plun->lun_guid) { 15773 if (plun->lun_guid_size != len) { 15774 /* 15775 * free the allocated memory and 15776 * initialize the field 15777 * lun_guid_size to 0. 15778 */ 15779 kmem_free(plun->lun_guid, plun->lun_guid_size); 15780 plun->lun_guid = NULL; 15781 plun->lun_guid_size = 0; 15782 } 15783 } 15784 /* 15785 * alloc only if not already done. 15786 */ 15787 if (plun->lun_guid == NULL) { 15788 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15789 if (plun->lun_guid == NULL) { 15790 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15791 "Unable to allocate" 15792 "Memory for GUID!!! size %d", len); 15793 retval = 1; 15794 } else { 15795 plun->lun_guid_size = len; 15796 } 15797 } 15798 if (plun->lun_guid) { 15799 /* 15800 * now copy the GUID 15801 */ 15802 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15803 } 15804 return (retval); 15805 } 15806 15807 /* 15808 * fcp_reconfig_wait 15809 * 15810 * Wait for a rediscovery/reconfiguration to complete before continuing. 15811 */ 15812 15813 static void 15814 fcp_reconfig_wait(struct fcp_port *pptr) 15815 { 15816 clock_t reconfig_start, wait_timeout; 15817 15818 /* 15819 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15820 * reconfiguration in progress. 15821 */ 15822 15823 mutex_enter(&pptr->port_mutex); 15824 if (pptr->port_tmp_cnt == 0) { 15825 mutex_exit(&pptr->port_mutex); 15826 return; 15827 } 15828 mutex_exit(&pptr->port_mutex); 15829 15830 /* 15831 * If we cause a reconfig by raising power, delay until all devices 15832 * report in (port_tmp_cnt returns to 0) 15833 */ 15834 15835 reconfig_start = ddi_get_lbolt(); 15836 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15837 15838 mutex_enter(&pptr->port_mutex); 15839 15840 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15841 pptr->port_tmp_cnt) { 15842 15843 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15844 reconfig_start + wait_timeout); 15845 } 15846 15847 mutex_exit(&pptr->port_mutex); 15848 15849 /* 15850 * Even if fcp_tmp_count isn't 0, continue without error. The port 15851 * we want may still be ok. If not, it will error out later 15852 */ 15853 } 15854 15855 /* 15856 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15857 * We rely on the fcp_global_mutex to provide protection against changes to 15858 * the fcp_lun_blacklist. 15859 * 15860 * You can describe a list of target port WWNs and LUN numbers which will 15861 * not be configured. LUN numbers will be interpreted as decimal. White 15862 * spaces and ',' can be used in the list of LUN numbers. 15863 * 15864 * To prevent LUNs 1 and 2 from being configured for target 15865 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15866 * 15867 * pwwn-lun-blacklist= 15868 * "510000f010fd92a1,1,2", 15869 * "510000e012079df1,1,2"; 15870 */ 15871 static void 15872 fcp_read_blacklist(dev_info_t *dip, 15873 struct fcp_black_list_entry **pplun_blacklist) 15874 { 15875 char **prop_array = NULL; 15876 char *curr_pwwn = NULL; 15877 char *curr_lun = NULL; 15878 uint32_t prop_item = 0; 15879 int idx = 0; 15880 int len = 0; 15881 15882 ASSERT(mutex_owned(&fcp_global_mutex)); 15883 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15884 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15885 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15886 return; 15887 } 15888 15889 for (idx = 0; idx < prop_item; idx++) { 15890 15891 curr_pwwn = prop_array[idx]; 15892 while (*curr_pwwn == ' ') { 15893 curr_pwwn++; 15894 } 15895 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15896 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15897 ", please check.", curr_pwwn); 15898 continue; 15899 } 15900 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15901 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15902 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15903 ", please check.", curr_pwwn); 15904 continue; 15905 } 15906 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15907 if (isxdigit(curr_pwwn[len]) != TRUE) { 15908 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15909 "blacklist, please check.", curr_pwwn); 15910 break; 15911 } 15912 } 15913 if (len != sizeof (la_wwn_t) * 2) { 15914 continue; 15915 } 15916 15917 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15918 *(curr_lun - 1) = '\0'; 15919 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15920 } 15921 15922 ddi_prop_free(prop_array); 15923 } 15924 15925 /* 15926 * Get the masking info about one remote target port designated by wwn. 15927 * Lun ids could be separated by ',' or white spaces. 15928 */ 15929 static void 15930 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15931 struct fcp_black_list_entry **pplun_blacklist) 15932 { 15933 int idx = 0; 15934 uint32_t offset = 0; 15935 unsigned long lun_id = 0; 15936 char lunid_buf[16]; 15937 char *pend = NULL; 15938 int illegal_digit = 0; 15939 15940 while (offset < strlen(curr_lun)) { 15941 while ((curr_lun[offset + idx] != ',') && 15942 (curr_lun[offset + idx] != '\0') && 15943 (curr_lun[offset + idx] != ' ')) { 15944 if (isdigit(curr_lun[offset + idx]) == 0) { 15945 illegal_digit++; 15946 } 15947 idx++; 15948 } 15949 if (illegal_digit > 0) { 15950 offset += (idx+1); /* To the start of next lun */ 15951 idx = 0; 15952 illegal_digit = 0; 15953 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15954 "the blacklist, please check digits.", 15955 curr_lun, curr_pwwn); 15956 continue; 15957 } 15958 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15959 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15960 "the blacklist, please check the length of LUN#.", 15961 curr_lun, curr_pwwn); 15962 break; 15963 } 15964 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15965 offset++; 15966 continue; 15967 } 15968 15969 bcopy(curr_lun + offset, lunid_buf, idx); 15970 lunid_buf[idx] = '\0'; 15971 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15972 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15973 } else { 15974 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15975 "the blacklist, please check %s.", 15976 curr_lun, curr_pwwn, lunid_buf); 15977 } 15978 offset += (idx+1); /* To the start of next lun */ 15979 idx = 0; 15980 } 15981 } 15982 15983 /* 15984 * Add one masking record 15985 */ 15986 static void 15987 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 15988 struct fcp_black_list_entry **pplun_blacklist) 15989 { 15990 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15991 struct fcp_black_list_entry *new_entry = NULL; 15992 la_wwn_t wwn; 15993 15994 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 15995 while (tmp_entry) { 15996 if ((bcmp(&tmp_entry->wwn, &wwn, 15997 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 15998 return; 15999 } 16000 16001 tmp_entry = tmp_entry->next; 16002 } 16003 16004 /* add to black list */ 16005 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16006 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16007 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16008 new_entry->lun = lun_id; 16009 new_entry->masked = 0; 16010 new_entry->next = *pplun_blacklist; 16011 *pplun_blacklist = new_entry; 16012 } 16013 16014 /* 16015 * Check if we should mask the specified lun of this fcp_tgt 16016 */ 16017 static int 16018 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) 16019 { 16020 struct fcp_black_list_entry *remote_port; 16021 16022 remote_port = fcp_lun_blacklist; 16023 while (remote_port != NULL) { 16024 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16025 if (remote_port->lun == lun_id) { 16026 remote_port->masked++; 16027 if (remote_port->masked == 1) { 16028 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16029 "%02x%02x%02x%02x%02x%02x%02x%02x " 16030 "is masked due to black listing.\n", 16031 lun_id, wwn->raw_wwn[0], 16032 wwn->raw_wwn[1], wwn->raw_wwn[2], 16033 wwn->raw_wwn[3], wwn->raw_wwn[4], 16034 wwn->raw_wwn[5], wwn->raw_wwn[6], 16035 wwn->raw_wwn[7]); 16036 } 16037 return (TRUE); 16038 } 16039 } 16040 remote_port = remote_port->next; 16041 } 16042 return (FALSE); 16043 } 16044 16045 /* 16046 * Release all allocated resources 16047 */ 16048 static void 16049 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) 16050 { 16051 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16052 struct fcp_black_list_entry *current_entry = NULL; 16053 16054 ASSERT(mutex_owned(&fcp_global_mutex)); 16055 /* 16056 * Traverse all luns 16057 */ 16058 while (tmp_entry) { 16059 current_entry = tmp_entry; 16060 tmp_entry = tmp_entry->next; 16061 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16062 } 16063 *pplun_blacklist = NULL; 16064 } 16065 16066 /* 16067 * In fcp module, 16068 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16069 */ 16070 static struct scsi_pkt * 16071 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16072 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16073 int flags, int (*callback)(), caddr_t arg) 16074 { 16075 fcp_port_t *pptr = ADDR2FCP(ap); 16076 fcp_pkt_t *cmd = NULL; 16077 fc_frame_hdr_t *hp; 16078 16079 /* 16080 * First step: get the packet 16081 */ 16082 if (pkt == NULL) { 16083 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16084 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16085 callback, arg); 16086 if (pkt == NULL) { 16087 return (NULL); 16088 } 16089 16090 /* 16091 * All fields in scsi_pkt will be initialized properly or 16092 * set to zero. We need do nothing for scsi_pkt. 16093 */ 16094 /* 16095 * But it's our responsibility to link other related data 16096 * structures. Their initialization will be done, just 16097 * before the scsi_pkt will be sent to FCA. 16098 */ 16099 cmd = PKT2CMD(pkt); 16100 cmd->cmd_pkt = pkt; 16101 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16102 /* 16103 * fc_packet_t 16104 */ 16105 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16106 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16107 sizeof (struct fcp_pkt)); 16108 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16109 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16110 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16111 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16112 /* 16113 * Fill in the Fabric Channel Header 16114 */ 16115 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16116 hp->r_ctl = R_CTL_COMMAND; 16117 hp->rsvd = 0; 16118 hp->type = FC_TYPE_SCSI_FCP; 16119 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16120 hp->seq_id = 0; 16121 hp->df_ctl = 0; 16122 hp->seq_cnt = 0; 16123 hp->ox_id = 0xffff; 16124 hp->rx_id = 0xffff; 16125 hp->ro = 0; 16126 } else { 16127 /* 16128 * We need think if we should reset any elements in 16129 * related data structures. 16130 */ 16131 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16132 fcp_trace, FCP_BUF_LEVEL_6, 0, 16133 "reusing pkt, flags %d", flags); 16134 cmd = PKT2CMD(pkt); 16135 if (cmd->cmd_fp_pkt->pkt_pd) { 16136 cmd->cmd_fp_pkt->pkt_pd = NULL; 16137 } 16138 } 16139 16140 /* 16141 * Second step: dma allocation/move 16142 */ 16143 if (bp && bp->b_bcount != 0) { 16144 /* 16145 * Mark if it's read or write 16146 */ 16147 if (bp->b_flags & B_READ) { 16148 cmd->cmd_flags |= CFLAG_IS_READ; 16149 } else { 16150 cmd->cmd_flags &= ~CFLAG_IS_READ; 16151 } 16152 16153 bp_mapin(bp); 16154 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16155 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16156 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16157 } else { 16158 /* 16159 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16160 * to send zero-length read/write. 16161 */ 16162 cmd->cmd_fp_pkt->pkt_data = NULL; 16163 cmd->cmd_fp_pkt->pkt_datalen = 0; 16164 } 16165 16166 return (pkt); 16167 } 16168 16169 static void 16170 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16171 { 16172 fcp_port_t *pptr = ADDR2FCP(ap); 16173 16174 /* 16175 * First we let FCA to uninitilize private part. 16176 */ 16177 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16178 PKT2CMD(pkt)->cmd_fp_pkt); 16179 16180 /* 16181 * Then we uninitialize fc_packet. 16182 */ 16183 16184 /* 16185 * Thirdly, we uninitializae fcp_pkt. 16186 */ 16187 16188 /* 16189 * In the end, we free scsi_pkt. 16190 */ 16191 scsi_hba_pkt_free(ap, pkt); 16192 } 16193 16194 static int 16195 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16196 { 16197 fcp_port_t *pptr = ADDR2FCP(ap); 16198 fcp_lun_t *plun = ADDR2LUN(ap); 16199 fcp_tgt_t *ptgt = plun->lun_tgt; 16200 fcp_pkt_t *cmd = PKT2CMD(pkt); 16201 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16202 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16203 int rval; 16204 16205 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16206 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16207 16208 /* 16209 * Firstly, we need initialize fcp_pkt_t 16210 * Secondly, we need initialize fcp_cmd_t. 16211 */ 16212 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16213 fcmd->fcp_data_len = fpkt->pkt_datalen; 16214 fcmd->fcp_ent_addr = plun->lun_addr; 16215 if (pkt->pkt_flags & FLAG_HTAG) { 16216 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16217 } else if (pkt->pkt_flags & FLAG_OTAG) { 16218 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16219 } else if (pkt->pkt_flags & FLAG_STAG) { 16220 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16221 } else { 16222 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16223 } 16224 16225 if (cmd->cmd_flags & CFLAG_IS_READ) { 16226 fcmd->fcp_cntl.cntl_read_data = 1; 16227 fcmd->fcp_cntl.cntl_write_data = 0; 16228 } else { 16229 fcmd->fcp_cntl.cntl_read_data = 0; 16230 fcmd->fcp_cntl.cntl_write_data = 1; 16231 } 16232 16233 /* 16234 * Then we need initialize fc_packet_t too. 16235 */ 16236 fpkt->pkt_timeout = pkt->pkt_time + 2; 16237 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16238 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16239 if (cmd->cmd_flags & CFLAG_IS_READ) { 16240 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16241 } else { 16242 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16243 } 16244 16245 if (pkt->pkt_flags & FLAG_NOINTR) { 16246 fpkt->pkt_comp = NULL; 16247 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16248 } else { 16249 fpkt->pkt_comp = fcp_cmd_callback; 16250 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16251 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16252 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16253 } 16254 } 16255 16256 /* 16257 * Lastly, we need initialize scsi_pkt 16258 */ 16259 pkt->pkt_reason = CMD_CMPLT; 16260 pkt->pkt_state = 0; 16261 pkt->pkt_statistics = 0; 16262 pkt->pkt_resid = 0; 16263 16264 /* 16265 * if interrupts aren't allowed (e.g. at dump time) then we'll 16266 * have to do polled I/O 16267 */ 16268 if (pkt->pkt_flags & FLAG_NOINTR) { 16269 return (fcp_dopoll(pptr, cmd)); 16270 } 16271 16272 cmd->cmd_state = FCP_PKT_ISSUED; 16273 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16274 if (rval == FC_SUCCESS) { 16275 return (TRAN_ACCEPT); 16276 } 16277 16278 /* 16279 * Need more consideration 16280 * 16281 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16282 */ 16283 cmd->cmd_state = FCP_PKT_IDLE; 16284 if (rval == FC_TRAN_BUSY) { 16285 return (TRAN_BUSY); 16286 } else { 16287 return (TRAN_FATAL_ERROR); 16288 } 16289 } 16290 16291 /* 16292 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16293 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16294 */ 16295 static void 16296 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16297 { 16298 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16299 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16300 } 16301 16302 /* 16303 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16304 */ 16305 static void 16306 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16307 { 16308 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16309 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16310 }