1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 24 * Fibre Channel SCSI ULP Mapping driver 25 */ 26 27 #include <sys/scsi/scsi.h> 28 #include <sys/types.h> 29 #include <sys/varargs.h> 30 #include <sys/devctl.h> 31 #include <sys/thread.h> 32 #include <sys/thread.h> 33 #include <sys/open.h> 34 #include <sys/file.h> 35 #include <sys/sunndi.h> 36 #include <sys/console.h> 37 #include <sys/proc.h> 38 #include <sys/time.h> 39 #include <sys/utsname.h> 40 #include <sys/scsi/impl/scsi_reset_notify.h> 41 #include <sys/ndi_impldefs.h> 42 #include <sys/byteorder.h> 43 #include <sys/fs/dv_node.h> 44 #include <sys/ctype.h> 45 #include <sys/sunmdi.h> 46 47 #include <sys/fibre-channel/fc.h> 48 #include <sys/fibre-channel/impl/fc_ulpif.h> 49 #include <sys/fibre-channel/ulp/fcpvar.h> 50 51 /* 52 * Discovery Process 53 * ================= 54 * 55 * The discovery process is a major function of FCP. In order to help 56 * understand that function a flow diagram is given here. This diagram 57 * doesn't claim to cover all the cases and the events that can occur during 58 * the discovery process nor the subtleties of the code. The code paths shown 59 * are simplified. Its purpose is to help the reader (and potentially bug 60 * fixer) have an overall view of the logic of the code. For that reason the 61 * diagram covers the simple case of the line coming up cleanly or of a new 62 * port attaching to FCP the link being up. The reader must keep in mind 63 * that: 64 * 65 * - There are special cases where bringing devices online and offline 66 * is driven by Ioctl. 67 * 68 * - The behavior of the discovery process can be modified through the 69 * .conf file. 70 * 71 * - The line can go down and come back up at any time during the 72 * discovery process which explains some of the complexity of the code. 73 * 74 * ............................................................................ 75 * 76 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 77 * 78 * 79 * +-------------------------+ 80 * fp/fctl module --->| fcp_port_attach | 81 * +-------------------------+ 82 * | | 83 * | | 84 * | v 85 * | +-------------------------+ 86 * | | fcp_handle_port_attach | 87 * | +-------------------------+ 88 * | | 89 * | | 90 * +--------------------+ | 91 * | | 92 * v v 93 * +-------------------------+ 94 * | fcp_statec_callback | 95 * +-------------------------+ 96 * | 97 * | 98 * v 99 * +-------------------------+ 100 * | fcp_handle_devices | 101 * +-------------------------+ 102 * | 103 * | 104 * v 105 * +-------------------------+ 106 * | fcp_handle_mapflags | 107 * +-------------------------+ 108 * | 109 * | 110 * v 111 * +-------------------------+ 112 * | fcp_send_els | 113 * | | 114 * | PLOGI or PRLI To all the| 115 * | reachable devices. | 116 * +-------------------------+ 117 * 118 * 119 * ............................................................................ 120 * 121 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 122 * STEP 1 are called (it is actually the same function). 123 * 124 * 125 * +-------------------------+ 126 * | fcp_icmd_callback | 127 * fp/fctl module --->| | 128 * | callback for PLOGI and | 129 * | PRLI. | 130 * +-------------------------+ 131 * | 132 * | 133 * Received PLOGI Accept /-\ Received PRLI Accept 134 * _ _ _ _ _ _ / \_ _ _ _ _ _ 135 * | \ / | 136 * | \-/ | 137 * | | 138 * v v 139 * +-------------------------+ +-------------------------+ 140 * | fcp_send_els | | fcp_send_scsi | 141 * | | | | 142 * | PRLI | | REPORT_LUN | 143 * +-------------------------+ +-------------------------+ 144 * 145 * ............................................................................ 146 * 147 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 148 * (It is actually the same function). 149 * 150 * 151 * +-------------------------+ 152 * fp/fctl module ------->| fcp_scsi_callback | 153 * +-------------------------+ 154 * | 155 * | 156 * | 157 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 158 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 159 * | \ / | 160 * | \-/ | 161 * | | | 162 * | Receive INQUIRY reply| | 163 * | | | 164 * v v v 165 * +------------------------+ +----------------------+ +----------------------+ 166 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 167 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 168 * +------------------------+ +----------------------+ +----------------------+ 169 * | | | 170 * | | | 171 * | | | 172 * v v | 173 * +-----------------+ +-----------------+ | 174 * | fcp_send_scsi | | fcp_send_scsi | | 175 * | | | | | 176 * | INQUIRY | | INQUIRY PAGE83 | | 177 * | (To each LUN) | +-----------------+ | 178 * +-----------------+ | 179 * | 180 * v 181 * +------------------------+ 182 * | fcp_call_finish_init | 183 * +------------------------+ 184 * | 185 * v 186 * +-----------------------------+ 187 * | fcp_call_finish_init_held | 188 * +-----------------------------+ 189 * | 190 * | 191 * All LUNs scanned /-\ 192 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 193 * | \ / 194 * | \-/ 195 * v | 196 * +------------------+ | 197 * | fcp_finish_tgt | | 198 * +------------------+ | 199 * | Target Not Offline and | 200 * Target Not Offline and | not marked and tgt_node_state | 201 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 202 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 203 * | \ / | | 204 * | \-/ | | 205 * v v | 206 * +----------------------------+ +-------------------+ | 207 * | fcp_offline_target | | fcp_create_luns | | 208 * | | +-------------------+ | 209 * | A structure fcp_tgt_elem | | | 210 * | is created and queued in | v | 211 * | the FCP port list | +-------------------+ | 212 * | port_offline_tgts. It | | fcp_pass_to_hp | | 213 * | will be unqueued by the | | | | 214 * | watchdog timer. | | Called for each | | 215 * +----------------------------+ | LUN. Dispatches | | 216 * | | fcp_hp_task | | 217 * | +-------------------+ | 218 * | | | 219 * | | | 220 * | | | 221 * | +---------------->| 222 * | | 223 * +---------------------------------------------->| 224 * | 225 * | 226 * All the targets (devices) have been scanned /-\ 227 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 228 * | \ / 229 * | \-/ 230 * +-------------------------------------+ | 231 * | fcp_finish_init | | 232 * | | | 233 * | Signal broadcasts the condition | | 234 * | variable port_config_cv of the FCP | | 235 * | port. One potential code sequence | | 236 * | waiting on the condition variable | | 237 * | the code sequence handling | | 238 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 239 * | The other is in the function | | 240 * | fcp_reconfig_wait which is called | | 241 * | in the transmit path preventing IOs | | 242 * | from going through till the disco- | | 243 * | very process is over. | | 244 * +-------------------------------------+ | 245 * | | 246 * | | 247 * +--------------------------------->| 248 * | 249 * v 250 * Return 251 * 252 * ............................................................................ 253 * 254 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 255 * 256 * 257 * +-------------------------+ 258 * | fcp_hp_task | 259 * +-------------------------+ 260 * | 261 * | 262 * v 263 * +-------------------------+ 264 * | fcp_trigger_lun | 265 * +-------------------------+ 266 * | 267 * | 268 * v 269 * Bring offline /-\ Bring online 270 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 271 * | \ / | 272 * | \-/ | 273 * v v 274 * +---------------------+ +-----------------------+ 275 * | fcp_offline_child | | fcp_get_cip | 276 * +---------------------+ | | 277 * | Creates a dev_info_t | 278 * | or a mdi_pathinfo_t | 279 * | depending on whether | 280 * | mpxio is on or off. | 281 * +-----------------------+ 282 * | 283 * | 284 * v 285 * +-----------------------+ 286 * | fcp_online_child | 287 * | | 288 * | Set device online | 289 * | using NDI or MDI. | 290 * +-----------------------+ 291 * 292 * ............................................................................ 293 * 294 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 295 * what is described here. We only show the target offline path. 296 * 297 * 298 * +--------------------------+ 299 * | fcp_watch | 300 * +--------------------------+ 301 * | 302 * | 303 * v 304 * +--------------------------+ 305 * | fcp_scan_offline_tgts | 306 * +--------------------------+ 307 * | 308 * | 309 * v 310 * +--------------------------+ 311 * | fcp_offline_target_now | 312 * +--------------------------+ 313 * | 314 * | 315 * v 316 * +--------------------------+ 317 * | fcp_offline_tgt_luns | 318 * +--------------------------+ 319 * | 320 * | 321 * v 322 * +--------------------------+ 323 * | fcp_offline_lun | 324 * +--------------------------+ 325 * | 326 * | 327 * v 328 * +----------------------------------+ 329 * | fcp_offline_lun_now | 330 * | | 331 * | A request (or two if mpxio) is | 332 * | sent to the hot plug task using | 333 * | a fcp_hp_elem structure. | 334 * +----------------------------------+ 335 */ 336 337 /* 338 * Functions registered with DDI framework 339 */ 340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 345 cred_t *credp, int *rval); 346 347 /* 348 * Functions registered with FC Transport framework 349 */ 350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 351 fc_attach_cmd_t cmd, uint32_t s_id); 352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 353 fc_detach_cmd_t cmd); 354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 355 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 356 uint32_t claimed); 357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 358 fc_unsol_buf_t *buf, uint32_t claimed); 359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 360 fc_unsol_buf_t *buf, uint32_t claimed); 361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 362 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 363 uint32_t dev_cnt, uint32_t port_sid); 364 365 /* 366 * Functions registered with SCSA framework 367 */ 368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 369 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 371 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 373 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 376 static int fcp_scsi_reset(struct scsi_address *ap, int level); 377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 379 int whom); 380 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 382 void (*callback)(caddr_t), caddr_t arg); 383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 384 char *name, ddi_eventcookie_t *event_cookiep); 385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 386 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 387 ddi_callback_id_t *cb_id); 388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 389 ddi_callback_id_t cb_id); 390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 391 ddi_eventcookie_t eventid, void *impldata); 392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 393 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 395 ddi_bus_config_op_t op, void *arg); 396 397 /* 398 * Internal functions 399 */ 400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 401 int mode, int *rval); 402 403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 404 int mode, int *rval); 405 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 406 struct fcp_scsi_cmd *fscsi, int mode); 407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 408 caddr_t base_addr, int mode); 409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 410 411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 412 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 413 int *fc_pkt_reason, int *fc_pkt_action); 414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 415 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 416 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 417 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 422 423 static void fcp_handle_devices(struct fcp_port *pptr, 424 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 425 fcp_map_tag_t *map_tag, int cause); 426 static int fcp_handle_mapflags(struct fcp_port *pptr, 427 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 428 int tgt_cnt, int cause); 429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause); 430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 431 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 433 int cause); 434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 435 uint32_t state); 436 static struct fcp_port *fcp_get_port(opaque_t port_handle); 437 static void fcp_unsol_callback(fc_packet_t *fpkt); 438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 439 uchar_t r_ctl, uchar_t type); 440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 442 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 443 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 446 int nodma, int flags); 447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 449 uchar_t *wwn); 450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 451 uint32_t d_id); 452 static void fcp_icmd_callback(fc_packet_t *fpkt); 453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 454 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 456 static void fcp_scsi_callback(fc_packet_t *fpkt); 457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 461 uint16_t lun_num); 462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 463 int link_cnt, int tgt_cnt, int cause); 464 static void fcp_finish_init(struct fcp_port *pptr); 465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 466 int tgt_cnt, int cause); 467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 468 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 470 int link_cnt, int tgt_cnt, int nowait, int flags); 471 static void fcp_offline_target_now(struct fcp_port *pptr, 472 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 474 int tgt_cnt, int flags); 475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 476 int nowait, int flags); 477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 478 int tgt_cnt); 479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 480 int tgt_cnt, int flags); 481 static void fcp_scan_offline_luns(struct fcp_port *pptr); 482 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 483 static void fcp_update_offline_flags(struct fcp_lun *plun); 484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 485 static void fcp_abort_commands(struct fcp_pkt *head, struct 486 fcp_port *pptr); 487 static void fcp_cmd_callback(fc_packet_t *fpkt); 488 static void fcp_complete_pkt(fc_packet_t *fpkt); 489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 490 struct fcp_port *pptr); 491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 492 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 494 static void fcp_dealloc_lun(struct fcp_lun *plun); 495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 496 fc_portmap_t *map_entry, int link_cnt); 497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 500 int internal); 501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 503 uint32_t s_id, int instance); 504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 505 int instance); 506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 508 int); 509 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 512 int flags); 513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 514 static int fcp_reset_target(struct scsi_address *ap, int level); 515 static int fcp_commoncap(struct scsi_address *ap, char *cap, 516 int val, int tgtonly, int doset); 517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 520 int sleep); 521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 522 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 526 int lcount, int tcount); 527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 530 int tgt_cnt); 531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 532 dev_info_t *pdip, caddr_t name); 533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 534 int lcount, int tcount, int flags, int *circ); 535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 536 int lcount, int tcount, int flags, int *circ); 537 static void fcp_remove_child(struct fcp_lun *plun); 538 static void fcp_watch(void *arg); 539 static void fcp_check_reset_delay(struct fcp_port *pptr); 540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 541 struct fcp_lun *rlun, int tgt_cnt); 542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 544 uchar_t *wwn, uint16_t lun); 545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 546 struct fcp_lun *plun); 547 static void fcp_post_callback(struct fcp_pkt *cmd); 548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 549 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 551 child_info_t *cip); 552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 553 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 554 int tgt_cnt, int flags); 555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 556 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 557 int tgt_cnt, int flags, int wait); 558 static void fcp_retransport_cmd(struct fcp_port *pptr, 559 struct fcp_pkt *cmd); 560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 561 uint_t statistics); 562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 563 static void fcp_update_targets(struct fcp_port *pptr, 564 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 565 static int fcp_call_finish_init(struct fcp_port *pptr, 566 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 567 static int fcp_call_finish_init_held(struct fcp_port *pptr, 568 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 569 static void fcp_reconfigure_luns(void * tgt_handle); 570 static void fcp_free_targets(struct fcp_port *pptr); 571 static void fcp_free_target(struct fcp_tgt *ptgt); 572 static int fcp_is_retryable(struct fcp_ipkt *icmd); 573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 576 static void fcp_print_error(fc_packet_t *fpkt); 577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 578 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 581 uint32_t *dev_cnt); 582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 585 struct fcp_ioctl *, struct fcp_port **); 586 static char *fcp_get_lun_path(struct fcp_lun *plun); 587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 588 int *rval); 589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 591 static char *fcp_get_lun_path(struct fcp_lun *plun); 592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 593 int *rval); 594 static void fcp_reconfig_wait(struct fcp_port *pptr); 595 596 /* 597 * New functions added for mpxio support 598 */ 599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 600 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 602 int tcount); 603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 604 dev_info_t *pdip); 605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 610 int what); 611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 612 fc_packet_t *fpkt); 613 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 614 615 /* 616 * New functions added for lun masking support 617 */ 618 static void fcp_read_blacklist(dev_info_t *dip, 619 struct fcp_black_list_entry **pplun_blacklist); 620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 621 struct fcp_black_list_entry **pplun_blacklist); 622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 623 struct fcp_black_list_entry **pplun_blacklist); 624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 626 627 /* 628 * New functions to support software FCA (like fcoei) 629 */ 630 static struct scsi_pkt *fcp_pseudo_init_pkt( 631 struct scsi_address *ap, struct scsi_pkt *pkt, 632 struct buf *bp, int cmdlen, int statuslen, 633 int tgtlen, int flags, int (*callback)(), caddr_t arg); 634 static void fcp_pseudo_destroy_pkt( 635 struct scsi_address *ap, struct scsi_pkt *pkt); 636 static void fcp_pseudo_sync_pkt( 637 struct scsi_address *ap, struct scsi_pkt *pkt); 638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt); 639 static void fcp_pseudo_dmafree( 640 struct scsi_address *ap, struct scsi_pkt *pkt); 641 642 extern struct mod_ops mod_driverops; 643 /* 644 * This variable is defined in modctl.c and set to '1' after the root driver 645 * and fs are loaded. It serves as an indication that the root filesystem can 646 * be used. 647 */ 648 extern int modrootloaded; 649 /* 650 * This table contains strings associated with the SCSI sense key codes. It 651 * is used by FCP to print a clear explanation of the code returned in the 652 * sense information by a device. 653 */ 654 extern char *sense_keys[]; 655 /* 656 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 657 * under this device that the paths to a physical device are created when 658 * MPxIO is used. 659 */ 660 extern dev_info_t *scsi_vhci_dip; 661 662 /* 663 * Report lun processing 664 */ 665 #define FCP_LUN_ADDRESSING 0x80 666 #define FCP_PD_ADDRESSING 0x00 667 #define FCP_VOLUME_ADDRESSING 0x40 668 669 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 670 #define MAX_INT_DMA 0x7fffffff 671 /* 672 * Property definitions 673 */ 674 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 675 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 676 #define TARGET_PROP (char *)fcp_target_prop 677 #define LUN_PROP (char *)fcp_lun_prop 678 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 679 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 680 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 681 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 682 #define INIT_PORT_PROP (char *)fcp_init_port_prop 683 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 684 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 685 /* 686 * Short hand macros. 687 */ 688 #define LUN_PORT (plun->lun_tgt->tgt_port) 689 #define LUN_TGT (plun->lun_tgt) 690 691 /* 692 * Driver private macros 693 */ 694 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 695 ((x) >= 'a' && (x) <= 'f') ? \ 696 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 697 698 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 699 700 #define FCP_N_NDI_EVENTS \ 701 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 702 703 #define FCP_LINK_STATE_CHANGED(p, c) \ 704 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 705 706 #define FCP_TGT_STATE_CHANGED(t, c) \ 707 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 708 709 #define FCP_STATE_CHANGED(p, t, c) \ 710 (FCP_TGT_STATE_CHANGED(t, c)) 711 712 #define FCP_MUST_RETRY(fpkt) \ 713 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 714 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 715 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 716 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 717 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 718 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 719 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 720 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 721 722 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 723 ((es)->es_key == KEY_UNIT_ATTENTION && \ 724 (es)->es_add_code == 0x3f && \ 725 (es)->es_qual_code == 0x0e) 726 727 #define FCP_SENSE_NO_LUN(es) \ 728 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 729 (es)->es_add_code == 0x25 && \ 730 (es)->es_qual_code == 0x0) 731 732 #define FCP_VERSION "20091208-1.192" 733 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 734 735 #define FCP_NUM_ELEMENTS(array) \ 736 (sizeof (array) / sizeof ((array)[0])) 737 738 /* 739 * Debugging, Error reporting, and tracing 740 */ 741 #define FCP_LOG_SIZE 1024 * 1024 742 743 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 744 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 745 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 746 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 747 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 748 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 749 #define FCP_LEVEL_7 0x00040 750 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 751 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 752 753 754 755 /* 756 * Log contents to system messages file 757 */ 758 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 759 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 760 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 761 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 762 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 763 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 764 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 765 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 766 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 767 768 769 /* 770 * Log contents to trace buffer 771 */ 772 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 773 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 774 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 775 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 776 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 777 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 778 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 779 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 780 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 781 782 783 /* 784 * Log contents to both system messages file and trace buffer 785 */ 786 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 787 FC_TRACE_LOG_MSG) 788 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 789 FC_TRACE_LOG_MSG) 790 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 791 FC_TRACE_LOG_MSG) 792 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 793 FC_TRACE_LOG_MSG) 794 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 795 FC_TRACE_LOG_MSG) 796 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 797 FC_TRACE_LOG_MSG) 798 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 799 FC_TRACE_LOG_MSG) 800 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 801 FC_TRACE_LOG_MSG) 802 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 803 FC_TRACE_LOG_MSG) 804 #ifdef DEBUG 805 #define FCP_DTRACE fc_trace_debug 806 #else 807 #define FCP_DTRACE 808 #endif 809 810 #define FCP_TRACE fc_trace_debug 811 812 static struct cb_ops fcp_cb_ops = { 813 fcp_open, /* open */ 814 fcp_close, /* close */ 815 nodev, /* strategy */ 816 nodev, /* print */ 817 nodev, /* dump */ 818 nodev, /* read */ 819 nodev, /* write */ 820 fcp_ioctl, /* ioctl */ 821 nodev, /* devmap */ 822 nodev, /* mmap */ 823 nodev, /* segmap */ 824 nochpoll, /* chpoll */ 825 ddi_prop_op, /* cb_prop_op */ 826 0, /* streamtab */ 827 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 828 CB_REV, /* rev */ 829 nodev, /* aread */ 830 nodev /* awrite */ 831 }; 832 833 834 static struct dev_ops fcp_ops = { 835 DEVO_REV, 836 0, 837 ddi_getinfo_1to1, 838 nulldev, /* identify */ 839 nulldev, /* probe */ 840 fcp_attach, /* attach and detach are mandatory */ 841 fcp_detach, 842 nodev, /* reset */ 843 &fcp_cb_ops, /* cb_ops */ 844 NULL, /* bus_ops */ 845 NULL, /* power */ 846 }; 847 848 849 char *fcp_version = FCP_NAME_VERSION; 850 851 static struct modldrv modldrv = { 852 &mod_driverops, 853 FCP_NAME_VERSION, 854 &fcp_ops 855 }; 856 857 858 static struct modlinkage modlinkage = { 859 MODREV_1, 860 &modldrv, 861 NULL 862 }; 863 864 865 static fc_ulp_modinfo_t fcp_modinfo = { 866 &fcp_modinfo, /* ulp_handle */ 867 FCTL_ULP_MODREV_4, /* ulp_rev */ 868 FC4_SCSI_FCP, /* ulp_type */ 869 "fcp", /* ulp_name */ 870 FCP_STATEC_MASK, /* ulp_statec_mask */ 871 fcp_port_attach, /* ulp_port_attach */ 872 fcp_port_detach, /* ulp_port_detach */ 873 fcp_port_ioctl, /* ulp_port_ioctl */ 874 fcp_els_callback, /* ulp_els_callback */ 875 fcp_data_callback, /* ulp_data_callback */ 876 fcp_statec_callback /* ulp_statec_callback */ 877 }; 878 879 #ifdef DEBUG 880 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 881 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 882 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 883 FCP_LEVEL_6 | FCP_LEVEL_7) 884 #else 885 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 886 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 887 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 888 FCP_LEVEL_6 | FCP_LEVEL_7) 889 #endif 890 891 /* FCP global variables */ 892 int fcp_bus_config_debug = 0; 893 static int fcp_log_size = FCP_LOG_SIZE; 894 static int fcp_trace = FCP_TRACE_DEFAULT; 895 static fc_trace_logq_t *fcp_logq = NULL; 896 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 897 /* 898 * The auto-configuration is set by default. The only way of disabling it is 899 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 900 */ 901 static int fcp_enable_auto_configuration = 1; 902 static int fcp_max_bus_config_retries = 4; 903 static int fcp_lun_ready_retry = 300; 904 /* 905 * The value assigned to the following variable has changed several times due 906 * to a problem with the data underruns reporting of some firmware(s). The 907 * current value of 50 gives a timeout value of 25 seconds for a max number 908 * of 256 LUNs. 909 */ 910 static int fcp_max_target_retries = 50; 911 /* 912 * Watchdog variables 913 * ------------------ 914 * 915 * fcp_watchdog_init 916 * 917 * Indicates if the watchdog timer is running or not. This is actually 918 * a counter of the number of Fibre Channel ports that attached. When 919 * the first port attaches the watchdog is started. When the last port 920 * detaches the watchdog timer is stopped. 921 * 922 * fcp_watchdog_time 923 * 924 * This is the watchdog clock counter. It is incremented by 925 * fcp_watchdog_time each time the watchdog timer expires. 926 * 927 * fcp_watchdog_timeout 928 * 929 * Increment value of the variable fcp_watchdog_time as well as the 930 * the timeout value of the watchdog timer. The unit is 1 second. It 931 * is strange that this is not a #define but a variable since the code 932 * never changes this value. The reason why it can be said that the 933 * unit is 1 second is because the number of ticks for the watchdog 934 * timer is determined like this: 935 * 936 * fcp_watchdog_tick = fcp_watchdog_timeout * 937 * drv_usectohz(1000000); 938 * 939 * The value 1000000 is hard coded in the code. 940 * 941 * fcp_watchdog_tick 942 * 943 * Watchdog timer value in ticks. 944 */ 945 static int fcp_watchdog_init = 0; 946 static int fcp_watchdog_time = 0; 947 static int fcp_watchdog_timeout = 1; 948 static int fcp_watchdog_tick; 949 950 /* 951 * fcp_offline_delay is a global variable to enable customisation of 952 * the timeout on link offlines or RSCNs. The default value is set 953 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 954 * specified in FCP4 Chapter 11 (see www.t10.org). 955 * 956 * The variable fcp_offline_delay is specified in SECONDS. 957 * 958 * If we made this a static var then the user would not be able to 959 * change it. This variable is set in fcp_attach(). 960 */ 961 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 962 963 static void *fcp_softstate = NULL; /* for soft state */ 964 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 965 static kmutex_t fcp_global_mutex; 966 static kmutex_t fcp_ioctl_mutex; 967 static dev_info_t *fcp_global_dip = NULL; 968 static timeout_id_t fcp_watchdog_id; 969 const char *fcp_lun_prop = "lun"; 970 const char *fcp_sam_lun_prop = "sam-lun"; 971 const char *fcp_target_prop = "target"; 972 /* 973 * NOTE: consumers of "node-wwn" property include stmsboot in ON 974 * consolidation. 975 */ 976 const char *fcp_node_wwn_prop = "node-wwn"; 977 const char *fcp_port_wwn_prop = "port-wwn"; 978 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 979 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 980 const char *fcp_manual_config_only = "manual_configuration_only"; 981 const char *fcp_init_port_prop = "initiator-port"; 982 const char *fcp_tgt_port_prop = "target-port"; 983 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 984 985 static struct fcp_port *fcp_port_head = NULL; 986 static ddi_eventcookie_t fcp_insert_eid; 987 static ddi_eventcookie_t fcp_remove_eid; 988 989 static ndi_event_definition_t fcp_ndi_event_defs[] = { 990 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 991 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 992 }; 993 994 /* 995 * List of valid commands for the scsi_ioctl call 996 */ 997 static uint8_t scsi_ioctl_list[] = { 998 SCMD_INQUIRY, 999 SCMD_REPORT_LUN, 1000 SCMD_READ_CAPACITY 1001 }; 1002 1003 /* 1004 * this is used to dummy up a report lun response for cases 1005 * where the target doesn't support it 1006 */ 1007 static uchar_t fcp_dummy_lun[] = { 1008 0x00, /* MSB length (length = no of luns * 8) */ 1009 0x00, 1010 0x00, 1011 0x08, /* LSB length */ 1012 0x00, /* MSB reserved */ 1013 0x00, 1014 0x00, 1015 0x00, /* LSB reserved */ 1016 FCP_PD_ADDRESSING, 1017 0x00, /* LUN is ZERO at the first level */ 1018 0x00, 1019 0x00, /* second level is zero */ 1020 0x00, 1021 0x00, /* third level is zero */ 1022 0x00, 1023 0x00 /* fourth level is zero */ 1024 }; 1025 1026 static uchar_t fcp_alpa_to_switch[] = { 1027 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1029 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1030 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1031 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1032 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1033 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1034 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1035 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1036 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1037 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1038 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1039 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1040 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1041 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1042 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1043 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1044 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1045 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1047 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1048 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1049 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1050 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1051 }; 1052 1053 static caddr_t pid = "SESS01 "; 1054 1055 /* 1056 * This table is used to determine whether or not it's safe to copy in 1057 * the target node name for a lun. Since all luns behind the same target 1058 * have the same wwnn, only tagets that do not support multiple luns are 1059 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1060 */ 1061 1062 char *fcp_symmetric_disk_table[] = { 1063 "SEAGATE ST", 1064 "IBM DDYFT", 1065 "SUNW SUNWGS", /* Daktari enclosure */ 1066 "SUN SENA", /* SES device */ 1067 "SUN SESS01" /* VICOM SVE box */ 1068 }; 1069 1070 int fcp_symmetric_disk_table_size = 1071 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1072 1073 /* 1074 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1075 * will panic if you don't pass this in to the routine, this information. 1076 * Need to determine what the actual impact to the system is by providing 1077 * this information if any. Since dma allocation is done in pkt_init it may 1078 * not have any impact. These values are straight from the Writing Device 1079 * Driver manual. 1080 */ 1081 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1082 DMA_ATTR_V0, /* ddi_dma_attr version */ 1083 0, /* low address */ 1084 0xffffffff, /* high address */ 1085 0x00ffffff, /* counter upper bound */ 1086 1, /* alignment requirements */ 1087 0x3f, /* burst sizes */ 1088 1, /* minimum DMA access */ 1089 0xffffffff, /* maximum DMA access */ 1090 (1 << 24) - 1, /* segment boundary restrictions */ 1091 1, /* scater/gather list length */ 1092 512, /* device granularity */ 1093 0 /* DMA flags */ 1094 }; 1095 1096 /* 1097 * The _init(9e) return value should be that of mod_install(9f). Under 1098 * some circumstances, a failure may not be related mod_install(9f) and 1099 * one would then require a return value to indicate the failure. Looking 1100 * at mod_install(9f), it is expected to return 0 for success and non-zero 1101 * for failure. mod_install(9f) for device drivers, further goes down the 1102 * calling chain and ends up in ddi_installdrv(), whose return values are 1103 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1104 * calling chain of mod_install(9f) which return values like EINVAL and 1105 * in some even return -1. 1106 * 1107 * To work around the vagaries of the mod_install() calling chain, return 1108 * either 0 or ENODEV depending on the success or failure of mod_install() 1109 */ 1110 int 1111 _init(void) 1112 { 1113 int rval; 1114 1115 /* 1116 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1117 * before registering with the transport first. 1118 */ 1119 if (ddi_soft_state_init(&fcp_softstate, 1120 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1121 return (EINVAL); 1122 } 1123 1124 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1125 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1126 1127 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1128 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1129 mutex_destroy(&fcp_global_mutex); 1130 mutex_destroy(&fcp_ioctl_mutex); 1131 ddi_soft_state_fini(&fcp_softstate); 1132 return (ENODEV); 1133 } 1134 1135 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1136 1137 if ((rval = mod_install(&modlinkage)) != 0) { 1138 fc_trace_free_logq(fcp_logq); 1139 (void) fc_ulp_remove(&fcp_modinfo); 1140 mutex_destroy(&fcp_global_mutex); 1141 mutex_destroy(&fcp_ioctl_mutex); 1142 ddi_soft_state_fini(&fcp_softstate); 1143 rval = ENODEV; 1144 } 1145 1146 return (rval); 1147 } 1148 1149 1150 /* 1151 * the system is done with us as a driver, so clean up 1152 */ 1153 int 1154 _fini(void) 1155 { 1156 int rval; 1157 1158 /* 1159 * don't start cleaning up until we know that the module remove 1160 * has worked -- if this works, then we know that each instance 1161 * has successfully been DDI_DETACHed 1162 */ 1163 if ((rval = mod_remove(&modlinkage)) != 0) { 1164 return (rval); 1165 } 1166 1167 (void) fc_ulp_remove(&fcp_modinfo); 1168 1169 ddi_soft_state_fini(&fcp_softstate); 1170 mutex_destroy(&fcp_global_mutex); 1171 mutex_destroy(&fcp_ioctl_mutex); 1172 fc_trace_free_logq(fcp_logq); 1173 1174 return (rval); 1175 } 1176 1177 1178 int 1179 _info(struct modinfo *modinfop) 1180 { 1181 return (mod_info(&modlinkage, modinfop)); 1182 } 1183 1184 1185 /* 1186 * attach the module 1187 */ 1188 static int 1189 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1190 { 1191 int rval = DDI_SUCCESS; 1192 1193 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1194 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1195 1196 if (cmd == DDI_ATTACH) { 1197 /* The FCP pseudo device is created here. */ 1198 mutex_enter(&fcp_global_mutex); 1199 fcp_global_dip = devi; 1200 mutex_exit(&fcp_global_mutex); 1201 1202 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1203 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1204 ddi_report_dev(fcp_global_dip); 1205 } else { 1206 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1207 mutex_enter(&fcp_global_mutex); 1208 fcp_global_dip = NULL; 1209 mutex_exit(&fcp_global_mutex); 1210 1211 rval = DDI_FAILURE; 1212 } 1213 /* 1214 * We check the fcp_offline_delay property at this 1215 * point. This variable is global for the driver, 1216 * not specific to an instance. 1217 * 1218 * We do not recommend setting the value to less 1219 * than 10 seconds (RA_TOV_els), or greater than 1220 * 60 seconds. 1221 */ 1222 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1223 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1224 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1225 if ((fcp_offline_delay < 10) || 1226 (fcp_offline_delay > 60)) { 1227 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1228 "to %d second(s). This is outside the " 1229 "recommended range of 10..60 seconds.", 1230 fcp_offline_delay); 1231 } 1232 } 1233 1234 return (rval); 1235 } 1236 1237 1238 /*ARGSUSED*/ 1239 static int 1240 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1241 { 1242 int res = DDI_SUCCESS; 1243 1244 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1245 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1246 1247 if (cmd == DDI_DETACH) { 1248 /* 1249 * Check if there are active ports/threads. If there 1250 * are any, we will fail, else we will succeed (there 1251 * should not be much to clean up) 1252 */ 1253 mutex_enter(&fcp_global_mutex); 1254 FCP_DTRACE(fcp_logq, "fcp", 1255 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1256 (void *) fcp_port_head); 1257 1258 if (fcp_port_head == NULL) { 1259 ddi_remove_minor_node(fcp_global_dip, NULL); 1260 fcp_global_dip = NULL; 1261 mutex_exit(&fcp_global_mutex); 1262 } else { 1263 mutex_exit(&fcp_global_mutex); 1264 res = DDI_FAILURE; 1265 } 1266 } 1267 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1268 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1269 1270 return (res); 1271 } 1272 1273 1274 /* ARGSUSED */ 1275 static int 1276 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1277 { 1278 if (otype != OTYP_CHR) { 1279 return (EINVAL); 1280 } 1281 1282 /* 1283 * Allow only root to talk; 1284 */ 1285 if (drv_priv(credp)) { 1286 return (EPERM); 1287 } 1288 1289 mutex_enter(&fcp_global_mutex); 1290 if (fcp_oflag & FCP_EXCL) { 1291 mutex_exit(&fcp_global_mutex); 1292 return (EBUSY); 1293 } 1294 1295 if (flag & FEXCL) { 1296 if (fcp_oflag & FCP_OPEN) { 1297 mutex_exit(&fcp_global_mutex); 1298 return (EBUSY); 1299 } 1300 fcp_oflag |= FCP_EXCL; 1301 } 1302 fcp_oflag |= FCP_OPEN; 1303 mutex_exit(&fcp_global_mutex); 1304 1305 return (0); 1306 } 1307 1308 1309 /* ARGSUSED */ 1310 static int 1311 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1312 { 1313 if (otype != OTYP_CHR) { 1314 return (EINVAL); 1315 } 1316 1317 mutex_enter(&fcp_global_mutex); 1318 if (!(fcp_oflag & FCP_OPEN)) { 1319 mutex_exit(&fcp_global_mutex); 1320 return (ENODEV); 1321 } 1322 fcp_oflag = FCP_IDLE; 1323 mutex_exit(&fcp_global_mutex); 1324 1325 return (0); 1326 } 1327 1328 1329 /* 1330 * fcp_ioctl 1331 * Entry point for the FCP ioctls 1332 * 1333 * Input: 1334 * See ioctl(9E) 1335 * 1336 * Output: 1337 * See ioctl(9E) 1338 * 1339 * Returns: 1340 * See ioctl(9E) 1341 * 1342 * Context: 1343 * Kernel context. 1344 */ 1345 /* ARGSUSED */ 1346 static int 1347 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1348 int *rval) 1349 { 1350 int ret = 0; 1351 1352 mutex_enter(&fcp_global_mutex); 1353 if (!(fcp_oflag & FCP_OPEN)) { 1354 mutex_exit(&fcp_global_mutex); 1355 return (ENXIO); 1356 } 1357 mutex_exit(&fcp_global_mutex); 1358 1359 switch (cmd) { 1360 case FCP_TGT_INQUIRY: 1361 case FCP_TGT_CREATE: 1362 case FCP_TGT_DELETE: 1363 ret = fcp_setup_device_data_ioctl(cmd, 1364 (struct fcp_ioctl *)data, mode, rval); 1365 break; 1366 1367 case FCP_TGT_SEND_SCSI: 1368 mutex_enter(&fcp_ioctl_mutex); 1369 ret = fcp_setup_scsi_ioctl( 1370 (struct fcp_scsi_cmd *)data, mode, rval); 1371 mutex_exit(&fcp_ioctl_mutex); 1372 break; 1373 1374 case FCP_STATE_COUNT: 1375 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1376 mode, rval); 1377 break; 1378 case FCP_GET_TARGET_MAPPINGS: 1379 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1380 mode, rval); 1381 break; 1382 default: 1383 fcp_log(CE_WARN, NULL, 1384 "!Invalid ioctl opcode = 0x%x", cmd); 1385 ret = EINVAL; 1386 } 1387 1388 return (ret); 1389 } 1390 1391 1392 /* 1393 * fcp_setup_device_data_ioctl 1394 * Setup handler for the "device data" style of 1395 * ioctl for FCP. See "fcp_util.h" for data structure 1396 * definition. 1397 * 1398 * Input: 1399 * cmd = FCP ioctl command 1400 * data = ioctl data 1401 * mode = See ioctl(9E) 1402 * 1403 * Output: 1404 * data = ioctl data 1405 * rval = return value - see ioctl(9E) 1406 * 1407 * Returns: 1408 * See ioctl(9E) 1409 * 1410 * Context: 1411 * Kernel context. 1412 */ 1413 /* ARGSUSED */ 1414 static int 1415 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1416 int *rval) 1417 { 1418 struct fcp_port *pptr; 1419 struct device_data *dev_data; 1420 uint32_t link_cnt; 1421 la_wwn_t *wwn_ptr = NULL; 1422 struct fcp_tgt *ptgt = NULL; 1423 struct fcp_lun *plun = NULL; 1424 int i, error; 1425 struct fcp_ioctl fioctl; 1426 1427 #ifdef _MULTI_DATAMODEL 1428 switch (ddi_model_convert_from(mode & FMODELS)) { 1429 case DDI_MODEL_ILP32: { 1430 struct fcp32_ioctl f32_ioctl; 1431 1432 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1433 sizeof (struct fcp32_ioctl), mode)) { 1434 return (EFAULT); 1435 } 1436 fioctl.fp_minor = f32_ioctl.fp_minor; 1437 fioctl.listlen = f32_ioctl.listlen; 1438 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1439 break; 1440 } 1441 case DDI_MODEL_NONE: 1442 if (ddi_copyin((void *)data, (void *)&fioctl, 1443 sizeof (struct fcp_ioctl), mode)) { 1444 return (EFAULT); 1445 } 1446 break; 1447 } 1448 1449 #else /* _MULTI_DATAMODEL */ 1450 if (ddi_copyin((void *)data, (void *)&fioctl, 1451 sizeof (struct fcp_ioctl), mode)) { 1452 return (EFAULT); 1453 } 1454 #endif /* _MULTI_DATAMODEL */ 1455 1456 /* 1457 * Right now we can assume that the minor number matches with 1458 * this instance of fp. If this changes we will need to 1459 * revisit this logic. 1460 */ 1461 mutex_enter(&fcp_global_mutex); 1462 pptr = fcp_port_head; 1463 while (pptr) { 1464 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1465 break; 1466 } else { 1467 pptr = pptr->port_next; 1468 } 1469 } 1470 mutex_exit(&fcp_global_mutex); 1471 if (pptr == NULL) { 1472 return (ENXIO); 1473 } 1474 mutex_enter(&pptr->port_mutex); 1475 1476 1477 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1478 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1479 mutex_exit(&pptr->port_mutex); 1480 return (ENOMEM); 1481 } 1482 1483 if (ddi_copyin(fioctl.list, dev_data, 1484 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1485 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1486 mutex_exit(&pptr->port_mutex); 1487 return (EFAULT); 1488 } 1489 link_cnt = pptr->port_link_cnt; 1490 1491 if (cmd == FCP_TGT_INQUIRY) { 1492 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1493 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1494 sizeof (wwn_ptr->raw_wwn)) == 0) { 1495 /* This ioctl is requesting INQ info of local HBA */ 1496 mutex_exit(&pptr->port_mutex); 1497 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1498 dev_data[0].dev_status = 0; 1499 if (ddi_copyout(dev_data, fioctl.list, 1500 (sizeof (struct device_data)) * fioctl.listlen, 1501 mode)) { 1502 kmem_free(dev_data, 1503 sizeof (*dev_data) * fioctl.listlen); 1504 return (EFAULT); 1505 } 1506 kmem_free(dev_data, 1507 sizeof (*dev_data) * fioctl.listlen); 1508 #ifdef _MULTI_DATAMODEL 1509 switch (ddi_model_convert_from(mode & FMODELS)) { 1510 case DDI_MODEL_ILP32: { 1511 struct fcp32_ioctl f32_ioctl; 1512 f32_ioctl.fp_minor = fioctl.fp_minor; 1513 f32_ioctl.listlen = fioctl.listlen; 1514 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1515 if (ddi_copyout((void *)&f32_ioctl, 1516 (void *)data, 1517 sizeof (struct fcp32_ioctl), mode)) { 1518 return (EFAULT); 1519 } 1520 break; 1521 } 1522 case DDI_MODEL_NONE: 1523 if (ddi_copyout((void *)&fioctl, (void *)data, 1524 sizeof (struct fcp_ioctl), mode)) { 1525 return (EFAULT); 1526 } 1527 break; 1528 } 1529 #else /* _MULTI_DATAMODEL */ 1530 if (ddi_copyout((void *)&fioctl, (void *)data, 1531 sizeof (struct fcp_ioctl), mode)) { 1532 return (EFAULT); 1533 } 1534 #endif /* _MULTI_DATAMODEL */ 1535 return (0); 1536 } 1537 } 1538 1539 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1540 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1541 mutex_exit(&pptr->port_mutex); 1542 return (ENXIO); 1543 } 1544 1545 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1546 i++) { 1547 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1548 1549 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1550 1551 1552 dev_data[i].dev_status = ENXIO; 1553 1554 if ((ptgt = fcp_lookup_target(pptr, 1555 (uchar_t *)wwn_ptr)) == NULL) { 1556 mutex_exit(&pptr->port_mutex); 1557 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1558 wwn_ptr, &error, 0) == NULL) { 1559 dev_data[i].dev_status = ENODEV; 1560 mutex_enter(&pptr->port_mutex); 1561 continue; 1562 } else { 1563 1564 dev_data[i].dev_status = EAGAIN; 1565 1566 mutex_enter(&pptr->port_mutex); 1567 continue; 1568 } 1569 } else { 1570 mutex_enter(&ptgt->tgt_mutex); 1571 if (ptgt->tgt_state & (FCP_TGT_MARK | 1572 FCP_TGT_BUSY)) { 1573 dev_data[i].dev_status = EAGAIN; 1574 mutex_exit(&ptgt->tgt_mutex); 1575 continue; 1576 } 1577 1578 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1579 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1580 dev_data[i].dev_status = ENOTSUP; 1581 } else { 1582 dev_data[i].dev_status = ENXIO; 1583 } 1584 mutex_exit(&ptgt->tgt_mutex); 1585 continue; 1586 } 1587 1588 switch (cmd) { 1589 case FCP_TGT_INQUIRY: 1590 /* 1591 * The reason we give device type of 1592 * lun 0 only even though in some 1593 * cases(like maxstrat) lun 0 device 1594 * type may be 0x3f(invalid) is that 1595 * for bridge boxes target will appear 1596 * as luns and the first lun could be 1597 * a device that utility may not care 1598 * about (like a tape device). 1599 */ 1600 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1601 dev_data[i].dev_status = 0; 1602 mutex_exit(&ptgt->tgt_mutex); 1603 1604 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1605 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1606 } else { 1607 dev_data[i].dev0_type = plun->lun_type; 1608 } 1609 mutex_enter(&ptgt->tgt_mutex); 1610 break; 1611 1612 case FCP_TGT_CREATE: 1613 mutex_exit(&ptgt->tgt_mutex); 1614 mutex_exit(&pptr->port_mutex); 1615 1616 /* 1617 * serialize state change call backs. 1618 * only one call back will be handled 1619 * at a time. 1620 */ 1621 mutex_enter(&fcp_global_mutex); 1622 if (fcp_oflag & FCP_BUSY) { 1623 mutex_exit(&fcp_global_mutex); 1624 if (dev_data) { 1625 kmem_free(dev_data, 1626 sizeof (*dev_data) * 1627 fioctl.listlen); 1628 } 1629 return (EBUSY); 1630 } 1631 fcp_oflag |= FCP_BUSY; 1632 mutex_exit(&fcp_global_mutex); 1633 1634 dev_data[i].dev_status = 1635 fcp_create_on_demand(pptr, 1636 wwn_ptr->raw_wwn); 1637 1638 if (dev_data[i].dev_status != 0) { 1639 char buf[25]; 1640 1641 for (i = 0; i < FC_WWN_SIZE; i++) { 1642 (void) sprintf(&buf[i << 1], 1643 "%02x", 1644 wwn_ptr->raw_wwn[i]); 1645 } 1646 1647 fcp_log(CE_WARN, pptr->port_dip, 1648 "!Failed to create nodes for" 1649 " pwwn=%s; error=%x", buf, 1650 dev_data[i].dev_status); 1651 } 1652 1653 /* allow state change call backs again */ 1654 mutex_enter(&fcp_global_mutex); 1655 fcp_oflag &= ~FCP_BUSY; 1656 mutex_exit(&fcp_global_mutex); 1657 1658 mutex_enter(&pptr->port_mutex); 1659 mutex_enter(&ptgt->tgt_mutex); 1660 1661 break; 1662 1663 case FCP_TGT_DELETE: 1664 break; 1665 1666 default: 1667 fcp_log(CE_WARN, pptr->port_dip, 1668 "!Invalid device data ioctl " 1669 "opcode = 0x%x", cmd); 1670 } 1671 mutex_exit(&ptgt->tgt_mutex); 1672 } 1673 } 1674 mutex_exit(&pptr->port_mutex); 1675 1676 if (ddi_copyout(dev_data, fioctl.list, 1677 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1678 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1679 return (EFAULT); 1680 } 1681 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1682 1683 #ifdef _MULTI_DATAMODEL 1684 switch (ddi_model_convert_from(mode & FMODELS)) { 1685 case DDI_MODEL_ILP32: { 1686 struct fcp32_ioctl f32_ioctl; 1687 1688 f32_ioctl.fp_minor = fioctl.fp_minor; 1689 f32_ioctl.listlen = fioctl.listlen; 1690 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1691 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1692 sizeof (struct fcp32_ioctl), mode)) { 1693 return (EFAULT); 1694 } 1695 break; 1696 } 1697 case DDI_MODEL_NONE: 1698 if (ddi_copyout((void *)&fioctl, (void *)data, 1699 sizeof (struct fcp_ioctl), mode)) { 1700 return (EFAULT); 1701 } 1702 break; 1703 } 1704 #else /* _MULTI_DATAMODEL */ 1705 1706 if (ddi_copyout((void *)&fioctl, (void *)data, 1707 sizeof (struct fcp_ioctl), mode)) { 1708 return (EFAULT); 1709 } 1710 #endif /* _MULTI_DATAMODEL */ 1711 1712 return (0); 1713 } 1714 1715 /* 1716 * Fetch the target mappings (path, etc.) for all LUNs 1717 * on this port. 1718 */ 1719 /* ARGSUSED */ 1720 static int 1721 fcp_get_target_mappings(struct fcp_ioctl *data, 1722 int mode, int *rval) 1723 { 1724 struct fcp_port *pptr; 1725 fc_hba_target_mappings_t *mappings; 1726 fc_hba_mapping_entry_t *map; 1727 struct fcp_tgt *ptgt = NULL; 1728 struct fcp_lun *plun = NULL; 1729 int i, mapIndex, mappingSize; 1730 int listlen; 1731 struct fcp_ioctl fioctl; 1732 char *path; 1733 fcp_ent_addr_t sam_lun_addr; 1734 1735 #ifdef _MULTI_DATAMODEL 1736 switch (ddi_model_convert_from(mode & FMODELS)) { 1737 case DDI_MODEL_ILP32: { 1738 struct fcp32_ioctl f32_ioctl; 1739 1740 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1741 sizeof (struct fcp32_ioctl), mode)) { 1742 return (EFAULT); 1743 } 1744 fioctl.fp_minor = f32_ioctl.fp_minor; 1745 fioctl.listlen = f32_ioctl.listlen; 1746 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1747 break; 1748 } 1749 case DDI_MODEL_NONE: 1750 if (ddi_copyin((void *)data, (void *)&fioctl, 1751 sizeof (struct fcp_ioctl), mode)) { 1752 return (EFAULT); 1753 } 1754 break; 1755 } 1756 1757 #else /* _MULTI_DATAMODEL */ 1758 if (ddi_copyin((void *)data, (void *)&fioctl, 1759 sizeof (struct fcp_ioctl), mode)) { 1760 return (EFAULT); 1761 } 1762 #endif /* _MULTI_DATAMODEL */ 1763 1764 /* 1765 * Right now we can assume that the minor number matches with 1766 * this instance of fp. If this changes we will need to 1767 * revisit this logic. 1768 */ 1769 mutex_enter(&fcp_global_mutex); 1770 pptr = fcp_port_head; 1771 while (pptr) { 1772 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1773 break; 1774 } else { 1775 pptr = pptr->port_next; 1776 } 1777 } 1778 mutex_exit(&fcp_global_mutex); 1779 if (pptr == NULL) { 1780 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1781 fioctl.fp_minor); 1782 return (ENXIO); 1783 } 1784 1785 1786 /* We use listlen to show the total buffer size */ 1787 mappingSize = fioctl.listlen; 1788 1789 /* Now calculate how many mapping entries will fit */ 1790 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1791 - sizeof (fc_hba_target_mappings_t); 1792 if (listlen <= 0) { 1793 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1794 return (ENXIO); 1795 } 1796 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1797 1798 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1799 return (ENOMEM); 1800 } 1801 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1802 1803 /* Now get to work */ 1804 mapIndex = 0; 1805 1806 mutex_enter(&pptr->port_mutex); 1807 /* Loop through all targets on this port */ 1808 for (i = 0; i < FCP_NUM_HASH; i++) { 1809 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1810 ptgt = ptgt->tgt_next) { 1811 1812 mutex_enter(&ptgt->tgt_mutex); 1813 1814 /* Loop through all LUNs on this target */ 1815 for (plun = ptgt->tgt_lun; plun != NULL; 1816 plun = plun->lun_next) { 1817 if (plun->lun_state & FCP_LUN_OFFLINE) { 1818 continue; 1819 } 1820 1821 path = fcp_get_lun_path(plun); 1822 if (path == NULL) { 1823 continue; 1824 } 1825 1826 if (mapIndex >= listlen) { 1827 mapIndex ++; 1828 kmem_free(path, MAXPATHLEN); 1829 continue; 1830 } 1831 map = &mappings->entries[mapIndex++]; 1832 bcopy(path, map->targetDriver, 1833 sizeof (map->targetDriver)); 1834 map->d_id = ptgt->tgt_d_id; 1835 map->busNumber = 0; 1836 map->targetNumber = ptgt->tgt_d_id; 1837 map->osLUN = plun->lun_num; 1838 1839 /* 1840 * We had swapped lun when we stored it in 1841 * lun_addr. We need to swap it back before 1842 * returning it to user land 1843 */ 1844 1845 sam_lun_addr.ent_addr_0 = 1846 BE_16(plun->lun_addr.ent_addr_0); 1847 sam_lun_addr.ent_addr_1 = 1848 BE_16(plun->lun_addr.ent_addr_1); 1849 sam_lun_addr.ent_addr_2 = 1850 BE_16(plun->lun_addr.ent_addr_2); 1851 sam_lun_addr.ent_addr_3 = 1852 BE_16(plun->lun_addr.ent_addr_3); 1853 1854 bcopy(&sam_lun_addr, &map->samLUN, 1855 FCP_LUN_SIZE); 1856 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1857 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1858 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1859 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1860 1861 if (plun->lun_guid) { 1862 1863 /* convert ascii wwn to bytes */ 1864 fcp_ascii_to_wwn(plun->lun_guid, 1865 map->guid, sizeof (map->guid)); 1866 1867 if ((sizeof (map->guid)) < 1868 plun->lun_guid_size / 2) { 1869 cmn_err(CE_WARN, 1870 "fcp_get_target_mappings:" 1871 "guid copy space " 1872 "insufficient." 1873 "Copy Truncation - " 1874 "available %d; need %d", 1875 (int)sizeof (map->guid), 1876 (int) 1877 plun->lun_guid_size / 2); 1878 } 1879 } 1880 kmem_free(path, MAXPATHLEN); 1881 } 1882 mutex_exit(&ptgt->tgt_mutex); 1883 } 1884 } 1885 mutex_exit(&pptr->port_mutex); 1886 mappings->numLuns = mapIndex; 1887 1888 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1889 kmem_free(mappings, mappingSize); 1890 return (EFAULT); 1891 } 1892 kmem_free(mappings, mappingSize); 1893 1894 #ifdef _MULTI_DATAMODEL 1895 switch (ddi_model_convert_from(mode & FMODELS)) { 1896 case DDI_MODEL_ILP32: { 1897 struct fcp32_ioctl f32_ioctl; 1898 1899 f32_ioctl.fp_minor = fioctl.fp_minor; 1900 f32_ioctl.listlen = fioctl.listlen; 1901 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1902 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1903 sizeof (struct fcp32_ioctl), mode)) { 1904 return (EFAULT); 1905 } 1906 break; 1907 } 1908 case DDI_MODEL_NONE: 1909 if (ddi_copyout((void *)&fioctl, (void *)data, 1910 sizeof (struct fcp_ioctl), mode)) { 1911 return (EFAULT); 1912 } 1913 break; 1914 } 1915 #else /* _MULTI_DATAMODEL */ 1916 1917 if (ddi_copyout((void *)&fioctl, (void *)data, 1918 sizeof (struct fcp_ioctl), mode)) { 1919 return (EFAULT); 1920 } 1921 #endif /* _MULTI_DATAMODEL */ 1922 1923 return (0); 1924 } 1925 1926 /* 1927 * fcp_setup_scsi_ioctl 1928 * Setup handler for the "scsi passthru" style of 1929 * ioctl for FCP. See "fcp_util.h" for data structure 1930 * definition. 1931 * 1932 * Input: 1933 * u_fscsi = ioctl data (user address space) 1934 * mode = See ioctl(9E) 1935 * 1936 * Output: 1937 * u_fscsi = ioctl data (user address space) 1938 * rval = return value - see ioctl(9E) 1939 * 1940 * Returns: 1941 * 0 = OK 1942 * EAGAIN = See errno.h 1943 * EBUSY = See errno.h 1944 * EFAULT = See errno.h 1945 * EINTR = See errno.h 1946 * EINVAL = See errno.h 1947 * EIO = See errno.h 1948 * ENOMEM = See errno.h 1949 * ENXIO = See errno.h 1950 * 1951 * Context: 1952 * Kernel context. 1953 */ 1954 /* ARGSUSED */ 1955 static int 1956 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1957 int mode, int *rval) 1958 { 1959 int ret = 0; 1960 int temp_ret; 1961 caddr_t k_cdbbufaddr = NULL; 1962 caddr_t k_bufaddr = NULL; 1963 caddr_t k_rqbufaddr = NULL; 1964 caddr_t u_cdbbufaddr; 1965 caddr_t u_bufaddr; 1966 caddr_t u_rqbufaddr; 1967 struct fcp_scsi_cmd k_fscsi; 1968 1969 /* 1970 * Get fcp_scsi_cmd array element from user address space 1971 */ 1972 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1973 != 0) { 1974 return (ret); 1975 } 1976 1977 1978 /* 1979 * Even though kmem_alloc() checks the validity of the 1980 * buffer length, this check is needed when the 1981 * kmem_flags set and the zero buffer length is passed. 1982 */ 1983 if ((k_fscsi.scsi_cdblen <= 0) || 1984 (k_fscsi.scsi_buflen <= 0) || 1985 (k_fscsi.scsi_rqlen <= 0)) { 1986 return (EINVAL); 1987 } 1988 1989 /* 1990 * Allocate data for fcp_scsi_cmd pointer fields 1991 */ 1992 if (ret == 0) { 1993 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 1994 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 1995 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 1996 1997 if (k_cdbbufaddr == NULL || 1998 k_bufaddr == NULL || 1999 k_rqbufaddr == NULL) { 2000 ret = ENOMEM; 2001 } 2002 } 2003 2004 /* 2005 * Get fcp_scsi_cmd pointer fields from user 2006 * address space 2007 */ 2008 if (ret == 0) { 2009 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2010 u_bufaddr = k_fscsi.scsi_bufaddr; 2011 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2012 2013 if (ddi_copyin(u_cdbbufaddr, 2014 k_cdbbufaddr, 2015 k_fscsi.scsi_cdblen, 2016 mode)) { 2017 ret = EFAULT; 2018 } else if (ddi_copyin(u_bufaddr, 2019 k_bufaddr, 2020 k_fscsi.scsi_buflen, 2021 mode)) { 2022 ret = EFAULT; 2023 } else if (ddi_copyin(u_rqbufaddr, 2024 k_rqbufaddr, 2025 k_fscsi.scsi_rqlen, 2026 mode)) { 2027 ret = EFAULT; 2028 } 2029 } 2030 2031 /* 2032 * Send scsi command (blocking) 2033 */ 2034 if (ret == 0) { 2035 /* 2036 * Prior to sending the scsi command, the 2037 * fcp_scsi_cmd data structure must contain kernel, 2038 * not user, addresses. 2039 */ 2040 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2041 k_fscsi.scsi_bufaddr = k_bufaddr; 2042 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2043 2044 ret = fcp_send_scsi_ioctl(&k_fscsi); 2045 2046 /* 2047 * After sending the scsi command, the 2048 * fcp_scsi_cmd data structure must contain user, 2049 * not kernel, addresses. 2050 */ 2051 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2052 k_fscsi.scsi_bufaddr = u_bufaddr; 2053 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2054 } 2055 2056 /* 2057 * Put fcp_scsi_cmd pointer fields to user address space 2058 */ 2059 if (ret == 0) { 2060 if (ddi_copyout(k_cdbbufaddr, 2061 u_cdbbufaddr, 2062 k_fscsi.scsi_cdblen, 2063 mode)) { 2064 ret = EFAULT; 2065 } else if (ddi_copyout(k_bufaddr, 2066 u_bufaddr, 2067 k_fscsi.scsi_buflen, 2068 mode)) { 2069 ret = EFAULT; 2070 } else if (ddi_copyout(k_rqbufaddr, 2071 u_rqbufaddr, 2072 k_fscsi.scsi_rqlen, 2073 mode)) { 2074 ret = EFAULT; 2075 } 2076 } 2077 2078 /* 2079 * Free data for fcp_scsi_cmd pointer fields 2080 */ 2081 if (k_cdbbufaddr != NULL) { 2082 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2083 } 2084 if (k_bufaddr != NULL) { 2085 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2086 } 2087 if (k_rqbufaddr != NULL) { 2088 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2089 } 2090 2091 /* 2092 * Put fcp_scsi_cmd array element to user address space 2093 */ 2094 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2095 if (temp_ret != 0) { 2096 ret = temp_ret; 2097 } 2098 2099 /* 2100 * Return status 2101 */ 2102 return (ret); 2103 } 2104 2105 2106 /* 2107 * fcp_copyin_scsi_cmd 2108 * Copy in fcp_scsi_cmd data structure from user address space. 2109 * The data may be in 32 bit or 64 bit modes. 2110 * 2111 * Input: 2112 * base_addr = from address (user address space) 2113 * mode = See ioctl(9E) and ddi_copyin(9F) 2114 * 2115 * Output: 2116 * fscsi = to address (kernel address space) 2117 * 2118 * Returns: 2119 * 0 = OK 2120 * EFAULT = Error 2121 * 2122 * Context: 2123 * Kernel context. 2124 */ 2125 static int 2126 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2127 { 2128 #ifdef _MULTI_DATAMODEL 2129 struct fcp32_scsi_cmd f32scsi; 2130 2131 switch (ddi_model_convert_from(mode & FMODELS)) { 2132 case DDI_MODEL_ILP32: 2133 /* 2134 * Copy data from user address space 2135 */ 2136 if (ddi_copyin((void *)base_addr, 2137 &f32scsi, 2138 sizeof (struct fcp32_scsi_cmd), 2139 mode)) { 2140 return (EFAULT); 2141 } 2142 /* 2143 * Convert from 32 bit to 64 bit 2144 */ 2145 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2146 break; 2147 case DDI_MODEL_NONE: 2148 /* 2149 * Copy data from user address space 2150 */ 2151 if (ddi_copyin((void *)base_addr, 2152 fscsi, 2153 sizeof (struct fcp_scsi_cmd), 2154 mode)) { 2155 return (EFAULT); 2156 } 2157 break; 2158 } 2159 #else /* _MULTI_DATAMODEL */ 2160 /* 2161 * Copy data from user address space 2162 */ 2163 if (ddi_copyin((void *)base_addr, 2164 fscsi, 2165 sizeof (struct fcp_scsi_cmd), 2166 mode)) { 2167 return (EFAULT); 2168 } 2169 #endif /* _MULTI_DATAMODEL */ 2170 2171 return (0); 2172 } 2173 2174 2175 /* 2176 * fcp_copyout_scsi_cmd 2177 * Copy out fcp_scsi_cmd data structure to user address space. 2178 * The data may be in 32 bit or 64 bit modes. 2179 * 2180 * Input: 2181 * fscsi = to address (kernel address space) 2182 * mode = See ioctl(9E) and ddi_copyin(9F) 2183 * 2184 * Output: 2185 * base_addr = from address (user address space) 2186 * 2187 * Returns: 2188 * 0 = OK 2189 * EFAULT = Error 2190 * 2191 * Context: 2192 * Kernel context. 2193 */ 2194 static int 2195 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2196 { 2197 #ifdef _MULTI_DATAMODEL 2198 struct fcp32_scsi_cmd f32scsi; 2199 2200 switch (ddi_model_convert_from(mode & FMODELS)) { 2201 case DDI_MODEL_ILP32: 2202 /* 2203 * Convert from 64 bit to 32 bit 2204 */ 2205 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2206 /* 2207 * Copy data to user address space 2208 */ 2209 if (ddi_copyout(&f32scsi, 2210 (void *)base_addr, 2211 sizeof (struct fcp32_scsi_cmd), 2212 mode)) { 2213 return (EFAULT); 2214 } 2215 break; 2216 case DDI_MODEL_NONE: 2217 /* 2218 * Copy data to user address space 2219 */ 2220 if (ddi_copyout(fscsi, 2221 (void *)base_addr, 2222 sizeof (struct fcp_scsi_cmd), 2223 mode)) { 2224 return (EFAULT); 2225 } 2226 break; 2227 } 2228 #else /* _MULTI_DATAMODEL */ 2229 /* 2230 * Copy data to user address space 2231 */ 2232 if (ddi_copyout(fscsi, 2233 (void *)base_addr, 2234 sizeof (struct fcp_scsi_cmd), 2235 mode)) { 2236 return (EFAULT); 2237 } 2238 #endif /* _MULTI_DATAMODEL */ 2239 2240 return (0); 2241 } 2242 2243 2244 /* 2245 * fcp_send_scsi_ioctl 2246 * Sends the SCSI command in blocking mode. 2247 * 2248 * Input: 2249 * fscsi = SCSI command data structure 2250 * 2251 * Output: 2252 * fscsi = SCSI command data structure 2253 * 2254 * Returns: 2255 * 0 = OK 2256 * EAGAIN = See errno.h 2257 * EBUSY = See errno.h 2258 * EINTR = See errno.h 2259 * EINVAL = See errno.h 2260 * EIO = See errno.h 2261 * ENOMEM = See errno.h 2262 * ENXIO = See errno.h 2263 * 2264 * Context: 2265 * Kernel context. 2266 */ 2267 static int 2268 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2269 { 2270 struct fcp_lun *plun = NULL; 2271 struct fcp_port *pptr = NULL; 2272 struct fcp_tgt *ptgt = NULL; 2273 fc_packet_t *fpkt = NULL; 2274 struct fcp_ipkt *icmd = NULL; 2275 int target_created = FALSE; 2276 fc_frame_hdr_t *hp; 2277 struct fcp_cmd fcp_cmd; 2278 struct fcp_cmd *fcmd; 2279 union scsi_cdb *scsi_cdb; 2280 la_wwn_t *wwn_ptr; 2281 int nodma; 2282 struct fcp_rsp *rsp; 2283 struct fcp_rsp_info *rsp_info; 2284 caddr_t rsp_sense; 2285 int buf_len; 2286 int info_len; 2287 int sense_len; 2288 struct scsi_extended_sense *sense_to = NULL; 2289 timeout_id_t tid; 2290 uint8_t reconfig_lun = FALSE; 2291 uint8_t reconfig_pending = FALSE; 2292 uint8_t scsi_cmd; 2293 int rsp_len; 2294 int cmd_index; 2295 int fc_status; 2296 int pkt_state; 2297 int pkt_action; 2298 int pkt_reason; 2299 int ret, xport_retval = ~FC_SUCCESS; 2300 int lcount; 2301 int tcount; 2302 int reconfig_status; 2303 int port_busy = FALSE; 2304 uchar_t *lun_string; 2305 2306 /* 2307 * Check valid SCSI command 2308 */ 2309 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2310 ret = EINVAL; 2311 for (cmd_index = 0; 2312 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2313 ret != 0; 2314 cmd_index++) { 2315 /* 2316 * First byte of CDB is the SCSI command 2317 */ 2318 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2319 ret = 0; 2320 } 2321 } 2322 2323 /* 2324 * Check inputs 2325 */ 2326 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2327 ret = EINVAL; 2328 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2329 /* no larger than */ 2330 ret = EINVAL; 2331 } 2332 2333 2334 /* 2335 * Find FC port 2336 */ 2337 if (ret == 0) { 2338 /* 2339 * Acquire global mutex 2340 */ 2341 mutex_enter(&fcp_global_mutex); 2342 2343 pptr = fcp_port_head; 2344 while (pptr) { 2345 if (pptr->port_instance == 2346 (uint32_t)fscsi->scsi_fc_port_num) { 2347 break; 2348 } else { 2349 pptr = pptr->port_next; 2350 } 2351 } 2352 2353 if (pptr == NULL) { 2354 ret = ENXIO; 2355 } else { 2356 /* 2357 * fc_ulp_busy_port can raise power 2358 * so, we must not hold any mutexes involved in PM 2359 */ 2360 mutex_exit(&fcp_global_mutex); 2361 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2362 } 2363 2364 if (ret == 0) { 2365 2366 /* remember port is busy, so we will release later */ 2367 port_busy = TRUE; 2368 2369 /* 2370 * If there is a reconfiguration in progress, wait 2371 * for it to complete. 2372 */ 2373 2374 fcp_reconfig_wait(pptr); 2375 2376 /* reacquire mutexes in order */ 2377 mutex_enter(&fcp_global_mutex); 2378 mutex_enter(&pptr->port_mutex); 2379 2380 /* 2381 * Will port accept DMA? 2382 */ 2383 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2384 ? 1 : 0; 2385 2386 /* 2387 * If init or offline, device not known 2388 * 2389 * If we are discovering (onlining), we can 2390 * NOT obviously provide reliable data about 2391 * devices until it is complete 2392 */ 2393 if (pptr->port_state & (FCP_STATE_INIT | 2394 FCP_STATE_OFFLINE)) { 2395 ret = ENXIO; 2396 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2397 ret = EBUSY; 2398 } else { 2399 /* 2400 * Find target from pwwn 2401 * 2402 * The wwn must be put into a local 2403 * variable to ensure alignment. 2404 */ 2405 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2406 ptgt = fcp_lookup_target(pptr, 2407 (uchar_t *)wwn_ptr); 2408 2409 /* 2410 * If target not found, 2411 */ 2412 if (ptgt == NULL) { 2413 /* 2414 * Note: Still have global & 2415 * port mutexes 2416 */ 2417 mutex_exit(&pptr->port_mutex); 2418 ptgt = fcp_port_create_tgt(pptr, 2419 wwn_ptr, &ret, &fc_status, 2420 &pkt_state, &pkt_action, 2421 &pkt_reason); 2422 mutex_enter(&pptr->port_mutex); 2423 2424 fscsi->scsi_fc_status = fc_status; 2425 fscsi->scsi_pkt_state = 2426 (uchar_t)pkt_state; 2427 fscsi->scsi_pkt_reason = pkt_reason; 2428 fscsi->scsi_pkt_action = 2429 (uchar_t)pkt_action; 2430 2431 if (ptgt != NULL) { 2432 target_created = TRUE; 2433 } else if (ret == 0) { 2434 ret = ENOMEM; 2435 } 2436 } 2437 2438 if (ret == 0) { 2439 /* 2440 * Acquire target 2441 */ 2442 mutex_enter(&ptgt->tgt_mutex); 2443 2444 /* 2445 * If target is mark or busy, 2446 * then target can not be used 2447 */ 2448 if (ptgt->tgt_state & 2449 (FCP_TGT_MARK | 2450 FCP_TGT_BUSY)) { 2451 ret = EBUSY; 2452 } else { 2453 /* 2454 * Mark target as busy 2455 */ 2456 ptgt->tgt_state |= 2457 FCP_TGT_BUSY; 2458 } 2459 2460 /* 2461 * Release target 2462 */ 2463 lcount = pptr->port_link_cnt; 2464 tcount = ptgt->tgt_change_cnt; 2465 mutex_exit(&ptgt->tgt_mutex); 2466 } 2467 } 2468 2469 /* 2470 * Release port 2471 */ 2472 mutex_exit(&pptr->port_mutex); 2473 } 2474 2475 /* 2476 * Release global mutex 2477 */ 2478 mutex_exit(&fcp_global_mutex); 2479 } 2480 2481 if (ret == 0) { 2482 uint64_t belun = BE_64(fscsi->scsi_lun); 2483 2484 /* 2485 * If it's a target device, find lun from pwwn 2486 * The wwn must be put into a local 2487 * variable to ensure alignment. 2488 */ 2489 mutex_enter(&pptr->port_mutex); 2490 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2491 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2492 /* this is not a target */ 2493 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2494 ret = ENXIO; 2495 } else if ((belun << 16) != 0) { 2496 /* 2497 * Since fcp only support PD and LU addressing method 2498 * so far, the last 6 bytes of a valid LUN are expected 2499 * to be filled with 00h. 2500 */ 2501 fscsi->scsi_fc_status = FC_INVALID_LUN; 2502 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2503 " method 0x%02x with LUN number 0x%016" PRIx64, 2504 (uint8_t)(belun >> 62), belun); 2505 ret = ENXIO; 2506 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2507 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2508 /* 2509 * This is a SCSI target, but no LUN at this 2510 * address. 2511 * 2512 * In the future, we may want to send this to 2513 * the target, and let it respond 2514 * appropriately 2515 */ 2516 ret = ENXIO; 2517 } 2518 mutex_exit(&pptr->port_mutex); 2519 } 2520 2521 /* 2522 * Finished grabbing external resources 2523 * Allocate internal packet (icmd) 2524 */ 2525 if (ret == 0) { 2526 /* 2527 * Calc rsp len assuming rsp info included 2528 */ 2529 rsp_len = sizeof (struct fcp_rsp) + 2530 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2531 2532 icmd = fcp_icmd_alloc(pptr, ptgt, 2533 sizeof (struct fcp_cmd), 2534 rsp_len, 2535 fscsi->scsi_buflen, 2536 nodma, 2537 lcount, /* ipkt_link_cnt */ 2538 tcount, /* ipkt_change_cnt */ 2539 0, /* cause */ 2540 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2541 2542 if (icmd == NULL) { 2543 ret = ENOMEM; 2544 } else { 2545 /* 2546 * Setup internal packet as sema sync 2547 */ 2548 fcp_ipkt_sema_init(icmd); 2549 } 2550 } 2551 2552 if (ret == 0) { 2553 /* 2554 * Init fpkt pointer for use. 2555 */ 2556 2557 fpkt = icmd->ipkt_fpkt; 2558 2559 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2560 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2561 fpkt->pkt_timeout = fscsi->scsi_timeout; 2562 2563 /* 2564 * Init fcmd pointer for use by SCSI command 2565 */ 2566 2567 if (nodma) { 2568 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2569 } else { 2570 fcmd = &fcp_cmd; 2571 } 2572 bzero(fcmd, sizeof (struct fcp_cmd)); 2573 ptgt = plun->lun_tgt; 2574 2575 lun_string = (uchar_t *)&fscsi->scsi_lun; 2576 2577 fcmd->fcp_ent_addr.ent_addr_0 = 2578 BE_16(*(uint16_t *)&(lun_string[0])); 2579 fcmd->fcp_ent_addr.ent_addr_1 = 2580 BE_16(*(uint16_t *)&(lun_string[2])); 2581 fcmd->fcp_ent_addr.ent_addr_2 = 2582 BE_16(*(uint16_t *)&(lun_string[4])); 2583 fcmd->fcp_ent_addr.ent_addr_3 = 2584 BE_16(*(uint16_t *)&(lun_string[6])); 2585 2586 /* 2587 * Setup internal packet(icmd) 2588 */ 2589 icmd->ipkt_lun = plun; 2590 icmd->ipkt_restart = 0; 2591 icmd->ipkt_retries = 0; 2592 icmd->ipkt_opcode = 0; 2593 2594 /* 2595 * Init the frame HEADER Pointer for use 2596 */ 2597 hp = &fpkt->pkt_cmd_fhdr; 2598 2599 hp->s_id = pptr->port_id; 2600 hp->d_id = ptgt->tgt_d_id; 2601 hp->r_ctl = R_CTL_COMMAND; 2602 hp->type = FC_TYPE_SCSI_FCP; 2603 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2604 hp->rsvd = 0; 2605 hp->seq_id = 0; 2606 hp->seq_cnt = 0; 2607 hp->ox_id = 0xffff; 2608 hp->rx_id = 0xffff; 2609 hp->ro = 0; 2610 2611 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2612 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2613 fcmd->fcp_cntl.cntl_write_data = 0; 2614 fcmd->fcp_data_len = fscsi->scsi_buflen; 2615 2616 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2617 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2618 fscsi->scsi_cdblen); 2619 2620 if (!nodma) { 2621 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2622 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2623 } 2624 2625 /* 2626 * Send SCSI command to FC transport 2627 */ 2628 2629 if (ret == 0) { 2630 mutex_enter(&ptgt->tgt_mutex); 2631 2632 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2633 mutex_exit(&ptgt->tgt_mutex); 2634 fscsi->scsi_fc_status = xport_retval = 2635 fc_ulp_transport(pptr->port_fp_handle, 2636 fpkt); 2637 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2638 ret = EIO; 2639 } 2640 } else { 2641 mutex_exit(&ptgt->tgt_mutex); 2642 ret = EBUSY; 2643 } 2644 } 2645 } 2646 2647 /* 2648 * Wait for completion only if fc_ulp_transport was called and it 2649 * returned a success. This is the only time callback will happen. 2650 * Otherwise, there is no point in waiting 2651 */ 2652 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2653 ret = fcp_ipkt_sema_wait(icmd); 2654 } 2655 2656 /* 2657 * Copy data to IOCTL data structures 2658 */ 2659 rsp = NULL; 2660 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2661 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2662 2663 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2664 fcp_log(CE_WARN, pptr->port_dip, 2665 "!SCSI command to d_id=0x%x lun=0x%x" 2666 " failed, Bad FCP response values:" 2667 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2668 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2669 ptgt->tgt_d_id, plun->lun_num, 2670 rsp->reserved_0, rsp->reserved_1, 2671 rsp->fcp_u.fcp_status.reserved_0, 2672 rsp->fcp_u.fcp_status.reserved_1, 2673 rsp->fcp_response_len, rsp->fcp_sense_len); 2674 2675 ret = EIO; 2676 } 2677 } 2678 2679 if ((ret == 0) && (rsp != NULL)) { 2680 /* 2681 * Calc response lengths 2682 */ 2683 sense_len = 0; 2684 info_len = 0; 2685 2686 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2687 info_len = rsp->fcp_response_len; 2688 } 2689 2690 rsp_info = (struct fcp_rsp_info *) 2691 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2692 2693 /* 2694 * Get SCSI status 2695 */ 2696 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2697 /* 2698 * If a lun was just added or removed and the next command 2699 * comes through this interface, we need to capture the check 2700 * condition so we can discover the new topology. 2701 */ 2702 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2703 rsp->fcp_u.fcp_status.sense_len_set) { 2704 sense_len = rsp->fcp_sense_len; 2705 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2706 sense_to = (struct scsi_extended_sense *)rsp_sense; 2707 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2708 (FCP_SENSE_NO_LUN(sense_to))) { 2709 reconfig_lun = TRUE; 2710 } 2711 } 2712 2713 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2714 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2715 if (reconfig_lun == FALSE) { 2716 reconfig_status = 2717 fcp_is_reconfig_needed(ptgt, fpkt); 2718 } 2719 2720 if ((reconfig_lun == TRUE) || 2721 (reconfig_status == TRUE)) { 2722 mutex_enter(&ptgt->tgt_mutex); 2723 if (ptgt->tgt_tid == NULL) { 2724 /* 2725 * Either we've been notified the 2726 * REPORT_LUN data has changed, or 2727 * we've determined on our own that 2728 * we're out of date. Kick off 2729 * rediscovery. 2730 */ 2731 tid = timeout(fcp_reconfigure_luns, 2732 (caddr_t)ptgt, drv_usectohz(1)); 2733 2734 ptgt->tgt_tid = tid; 2735 ptgt->tgt_state |= FCP_TGT_BUSY; 2736 ret = EBUSY; 2737 reconfig_pending = TRUE; 2738 } 2739 mutex_exit(&ptgt->tgt_mutex); 2740 } 2741 } 2742 2743 /* 2744 * Calc residuals and buffer lengths 2745 */ 2746 2747 if (ret == 0) { 2748 buf_len = fscsi->scsi_buflen; 2749 fscsi->scsi_bufresid = 0; 2750 if (rsp->fcp_u.fcp_status.resid_under) { 2751 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2752 fscsi->scsi_bufresid = rsp->fcp_resid; 2753 } else { 2754 cmn_err(CE_WARN, "fcp: bad residue %x " 2755 "for txfer len %x", rsp->fcp_resid, 2756 fscsi->scsi_buflen); 2757 fscsi->scsi_bufresid = 2758 fscsi->scsi_buflen; 2759 } 2760 buf_len -= fscsi->scsi_bufresid; 2761 } 2762 if (rsp->fcp_u.fcp_status.resid_over) { 2763 fscsi->scsi_bufresid = -rsp->fcp_resid; 2764 } 2765 2766 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2767 if (fscsi->scsi_rqlen < sense_len) { 2768 sense_len = fscsi->scsi_rqlen; 2769 } 2770 2771 fscsi->scsi_fc_rspcode = 0; 2772 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2773 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2774 } 2775 fscsi->scsi_pkt_state = fpkt->pkt_state; 2776 fscsi->scsi_pkt_action = fpkt->pkt_action; 2777 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2778 2779 /* 2780 * Copy data and request sense 2781 * 2782 * Data must be copied by using the FCP_CP_IN macro. 2783 * This will ensure the proper byte order since the data 2784 * is being copied directly from the memory mapped 2785 * device register. 2786 * 2787 * The response (and request sense) will be in the 2788 * correct byte order. No special copy is necessary. 2789 */ 2790 2791 if (buf_len) { 2792 FCP_CP_IN(fpkt->pkt_data, 2793 fscsi->scsi_bufaddr, 2794 fpkt->pkt_data_acc, 2795 buf_len); 2796 } 2797 bcopy((void *)rsp_sense, 2798 (void *)fscsi->scsi_rqbufaddr, 2799 sense_len); 2800 } 2801 } 2802 2803 /* 2804 * Cleanup transport data structures if icmd was alloc-ed 2805 * So, cleanup happens in the same thread that icmd was alloc-ed 2806 */ 2807 if (icmd != NULL) { 2808 fcp_ipkt_sema_cleanup(icmd); 2809 } 2810 2811 /* restore pm busy/idle status */ 2812 if (port_busy) { 2813 fc_ulp_idle_port(pptr->port_fp_handle); 2814 } 2815 2816 /* 2817 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2818 * flag, it'll be cleared when the reconfig is complete. 2819 */ 2820 if ((ptgt != NULL) && !reconfig_pending) { 2821 /* 2822 * If target was created, 2823 */ 2824 if (target_created) { 2825 mutex_enter(&ptgt->tgt_mutex); 2826 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2827 mutex_exit(&ptgt->tgt_mutex); 2828 } else { 2829 /* 2830 * De-mark target as busy 2831 */ 2832 mutex_enter(&ptgt->tgt_mutex); 2833 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2834 mutex_exit(&ptgt->tgt_mutex); 2835 } 2836 } 2837 return (ret); 2838 } 2839 2840 2841 static int 2842 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2843 fc_packet_t *fpkt) 2844 { 2845 uchar_t *lun_string; 2846 uint16_t lun_num, i; 2847 int num_luns; 2848 int actual_luns; 2849 int num_masked_luns; 2850 int lun_buflen; 2851 struct fcp_lun *plun = NULL; 2852 struct fcp_reportlun_resp *report_lun; 2853 uint8_t reconfig_needed = FALSE; 2854 uint8_t lun_exists = FALSE; 2855 fcp_port_t *pptr = ptgt->tgt_port; 2856 2857 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2858 2859 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2860 fpkt->pkt_datalen); 2861 2862 /* get number of luns (which is supplied as LUNS * 8) */ 2863 num_luns = BE_32(report_lun->num_lun) >> 3; 2864 2865 /* 2866 * Figure out exactly how many lun strings our response buffer 2867 * can hold. 2868 */ 2869 lun_buflen = (fpkt->pkt_datalen - 2870 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2871 2872 /* 2873 * Is our response buffer full or not? We don't want to 2874 * potentially walk beyond the number of luns we have. 2875 */ 2876 if (num_luns <= lun_buflen) { 2877 actual_luns = num_luns; 2878 } else { 2879 actual_luns = lun_buflen; 2880 } 2881 2882 mutex_enter(&ptgt->tgt_mutex); 2883 2884 /* Scan each lun to see if we have masked it. */ 2885 num_masked_luns = 0; 2886 if (fcp_lun_blacklist != NULL) { 2887 for (i = 0; i < actual_luns; i++) { 2888 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2889 switch (lun_string[0] & 0xC0) { 2890 case FCP_LUN_ADDRESSING: 2891 case FCP_PD_ADDRESSING: 2892 case FCP_VOLUME_ADDRESSING: 2893 lun_num = ((lun_string[0] & 0x3F) << 8) 2894 | lun_string[1]; 2895 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2896 lun_num) == TRUE) { 2897 num_masked_luns++; 2898 } 2899 break; 2900 default: 2901 break; 2902 } 2903 } 2904 } 2905 2906 /* 2907 * The quick and easy check. If the number of LUNs reported 2908 * doesn't match the number we currently know about, we need 2909 * to reconfigure. 2910 */ 2911 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2912 mutex_exit(&ptgt->tgt_mutex); 2913 kmem_free(report_lun, fpkt->pkt_datalen); 2914 return (TRUE); 2915 } 2916 2917 /* 2918 * If the quick and easy check doesn't turn up anything, we walk 2919 * the list of luns from the REPORT_LUN response and look for 2920 * any luns we don't know about. If we find one, we know we need 2921 * to reconfigure. We will skip LUNs that are masked because of the 2922 * blacklist. 2923 */ 2924 for (i = 0; i < actual_luns; i++) { 2925 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2926 lun_exists = FALSE; 2927 switch (lun_string[0] & 0xC0) { 2928 case FCP_LUN_ADDRESSING: 2929 case FCP_PD_ADDRESSING: 2930 case FCP_VOLUME_ADDRESSING: 2931 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2932 2933 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2934 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2935 lun_exists = TRUE; 2936 break; 2937 } 2938 2939 for (plun = ptgt->tgt_lun; plun; 2940 plun = plun->lun_next) { 2941 if (plun->lun_num == lun_num) { 2942 lun_exists = TRUE; 2943 break; 2944 } 2945 } 2946 break; 2947 default: 2948 break; 2949 } 2950 2951 if (lun_exists == FALSE) { 2952 reconfig_needed = TRUE; 2953 break; 2954 } 2955 } 2956 2957 mutex_exit(&ptgt->tgt_mutex); 2958 kmem_free(report_lun, fpkt->pkt_datalen); 2959 2960 return (reconfig_needed); 2961 } 2962 2963 /* 2964 * This function is called by fcp_handle_page83 and uses inquiry response data 2965 * stored in plun->lun_inq to determine whether or not a device is a member of 2966 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2967 * otherwise 1. 2968 */ 2969 static int 2970 fcp_symmetric_device_probe(struct fcp_lun *plun) 2971 { 2972 struct scsi_inquiry *stdinq = &plun->lun_inq; 2973 char *devidptr; 2974 int i, len; 2975 2976 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2977 devidptr = fcp_symmetric_disk_table[i]; 2978 len = (int)strlen(devidptr); 2979 2980 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 2981 return (0); 2982 } 2983 } 2984 return (1); 2985 } 2986 2987 2988 /* 2989 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 2990 * It basically returns the current count of # of state change callbacks 2991 * i.e the value of tgt_change_cnt. 2992 * 2993 * INPUT: 2994 * fcp_ioctl.fp_minor -> The minor # of the fp port 2995 * fcp_ioctl.listlen -> 1 2996 * fcp_ioctl.list -> Pointer to a 32 bit integer 2997 */ 2998 /*ARGSUSED2*/ 2999 static int 3000 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3001 { 3002 int ret; 3003 uint32_t link_cnt; 3004 struct fcp_ioctl fioctl; 3005 struct fcp_port *pptr = NULL; 3006 3007 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3008 &pptr)) != 0) { 3009 return (ret); 3010 } 3011 3012 ASSERT(pptr != NULL); 3013 3014 if (fioctl.listlen != 1) { 3015 return (EINVAL); 3016 } 3017 3018 mutex_enter(&pptr->port_mutex); 3019 if (pptr->port_state & FCP_STATE_OFFLINE) { 3020 mutex_exit(&pptr->port_mutex); 3021 return (ENXIO); 3022 } 3023 3024 /* 3025 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3026 * When the fcp initially attaches to the port and there are nothing 3027 * hanging out of the port or if there was a repeat offline state change 3028 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3029 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3030 * will differentiate the 2 cases. 3031 */ 3032 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3033 mutex_exit(&pptr->port_mutex); 3034 return (ENXIO); 3035 } 3036 3037 link_cnt = pptr->port_link_cnt; 3038 mutex_exit(&pptr->port_mutex); 3039 3040 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3041 return (EFAULT); 3042 } 3043 3044 #ifdef _MULTI_DATAMODEL 3045 switch (ddi_model_convert_from(mode & FMODELS)) { 3046 case DDI_MODEL_ILP32: { 3047 struct fcp32_ioctl f32_ioctl; 3048 3049 f32_ioctl.fp_minor = fioctl.fp_minor; 3050 f32_ioctl.listlen = fioctl.listlen; 3051 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3052 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3053 sizeof (struct fcp32_ioctl), mode)) { 3054 return (EFAULT); 3055 } 3056 break; 3057 } 3058 case DDI_MODEL_NONE: 3059 if (ddi_copyout((void *)&fioctl, (void *)data, 3060 sizeof (struct fcp_ioctl), mode)) { 3061 return (EFAULT); 3062 } 3063 break; 3064 } 3065 #else /* _MULTI_DATAMODEL */ 3066 3067 if (ddi_copyout((void *)&fioctl, (void *)data, 3068 sizeof (struct fcp_ioctl), mode)) { 3069 return (EFAULT); 3070 } 3071 #endif /* _MULTI_DATAMODEL */ 3072 3073 return (0); 3074 } 3075 3076 /* 3077 * This function copies the fcp_ioctl structure passed in from user land 3078 * into kernel land. Handles 32 bit applications. 3079 */ 3080 /*ARGSUSED*/ 3081 static int 3082 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3083 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3084 { 3085 struct fcp_port *t_pptr; 3086 3087 #ifdef _MULTI_DATAMODEL 3088 switch (ddi_model_convert_from(mode & FMODELS)) { 3089 case DDI_MODEL_ILP32: { 3090 struct fcp32_ioctl f32_ioctl; 3091 3092 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3093 sizeof (struct fcp32_ioctl), mode)) { 3094 return (EFAULT); 3095 } 3096 fioctl->fp_minor = f32_ioctl.fp_minor; 3097 fioctl->listlen = f32_ioctl.listlen; 3098 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3099 break; 3100 } 3101 case DDI_MODEL_NONE: 3102 if (ddi_copyin((void *)data, (void *)fioctl, 3103 sizeof (struct fcp_ioctl), mode)) { 3104 return (EFAULT); 3105 } 3106 break; 3107 } 3108 3109 #else /* _MULTI_DATAMODEL */ 3110 if (ddi_copyin((void *)data, (void *)fioctl, 3111 sizeof (struct fcp_ioctl), mode)) { 3112 return (EFAULT); 3113 } 3114 #endif /* _MULTI_DATAMODEL */ 3115 3116 /* 3117 * Right now we can assume that the minor number matches with 3118 * this instance of fp. If this changes we will need to 3119 * revisit this logic. 3120 */ 3121 mutex_enter(&fcp_global_mutex); 3122 t_pptr = fcp_port_head; 3123 while (t_pptr) { 3124 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3125 break; 3126 } else { 3127 t_pptr = t_pptr->port_next; 3128 } 3129 } 3130 *pptr = t_pptr; 3131 mutex_exit(&fcp_global_mutex); 3132 if (t_pptr == NULL) { 3133 return (ENXIO); 3134 } 3135 3136 return (0); 3137 } 3138 3139 /* 3140 * Function: fcp_port_create_tgt 3141 * 3142 * Description: As the name suggest this function creates the target context 3143 * specified by the the WWN provided by the caller. If the 3144 * creation goes well and the target is known by fp/fctl a PLOGI 3145 * followed by a PRLI are issued. 3146 * 3147 * Argument: pptr fcp port structure 3148 * pwwn WWN of the target 3149 * ret_val Address of the return code. It could be: 3150 * EIO, ENOMEM or 0. 3151 * fc_status PLOGI or PRLI status completion 3152 * fc_pkt_state PLOGI or PRLI state completion 3153 * fc_pkt_reason PLOGI or PRLI reason completion 3154 * fc_pkt_action PLOGI or PRLI action completion 3155 * 3156 * Return Value: NULL if it failed 3157 * Target structure address if it succeeds 3158 */ 3159 static struct fcp_tgt * 3160 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3161 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3162 { 3163 struct fcp_tgt *ptgt = NULL; 3164 fc_portmap_t devlist; 3165 int lcount; 3166 int error; 3167 3168 *ret_val = 0; 3169 3170 /* 3171 * Check FC port device & get port map 3172 */ 3173 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3174 &error, 1) == NULL) { 3175 *ret_val = EIO; 3176 } else { 3177 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3178 &devlist) != FC_SUCCESS) { 3179 *ret_val = EIO; 3180 } 3181 } 3182 3183 /* Set port map flags */ 3184 devlist.map_type = PORT_DEVICE_USER_CREATE; 3185 3186 /* Allocate target */ 3187 if (*ret_val == 0) { 3188 lcount = pptr->port_link_cnt; 3189 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3190 if (ptgt == NULL) { 3191 fcp_log(CE_WARN, pptr->port_dip, 3192 "!FC target allocation failed"); 3193 *ret_val = ENOMEM; 3194 } else { 3195 /* Setup target */ 3196 mutex_enter(&ptgt->tgt_mutex); 3197 3198 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3199 ptgt->tgt_tmp_cnt = 1; 3200 ptgt->tgt_d_id = devlist.map_did.port_id; 3201 ptgt->tgt_hard_addr = 3202 devlist.map_hard_addr.hard_addr; 3203 ptgt->tgt_pd_handle = devlist.map_pd; 3204 ptgt->tgt_fca_dev = NULL; 3205 3206 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3207 FC_WWN_SIZE); 3208 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3209 FC_WWN_SIZE); 3210 3211 mutex_exit(&ptgt->tgt_mutex); 3212 } 3213 } 3214 3215 /* Release global mutex for PLOGI and PRLI */ 3216 mutex_exit(&fcp_global_mutex); 3217 3218 /* Send PLOGI (If necessary) */ 3219 if (*ret_val == 0) { 3220 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3221 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3222 } 3223 3224 /* Send PRLI (If necessary) */ 3225 if (*ret_val == 0) { 3226 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3227 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3228 } 3229 3230 mutex_enter(&fcp_global_mutex); 3231 3232 return (ptgt); 3233 } 3234 3235 /* 3236 * Function: fcp_tgt_send_plogi 3237 * 3238 * Description: This function sends a PLOGI to the target specified by the 3239 * caller and waits till it completes. 3240 * 3241 * Argument: ptgt Target to send the plogi to. 3242 * fc_status Status returned by fp/fctl in the PLOGI request. 3243 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3244 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3245 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3246 * 3247 * Return Value: 0 3248 * ENOMEM 3249 * EIO 3250 * 3251 * Context: User context. 3252 */ 3253 static int 3254 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3255 int *fc_pkt_reason, int *fc_pkt_action) 3256 { 3257 struct fcp_port *pptr; 3258 struct fcp_ipkt *icmd; 3259 struct fc_packet *fpkt; 3260 fc_frame_hdr_t *hp; 3261 struct la_els_logi logi; 3262 int tcount; 3263 int lcount; 3264 int ret, login_retval = ~FC_SUCCESS; 3265 3266 ret = 0; 3267 3268 pptr = ptgt->tgt_port; 3269 3270 lcount = pptr->port_link_cnt; 3271 tcount = ptgt->tgt_change_cnt; 3272 3273 /* Alloc internal packet */ 3274 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3275 sizeof (la_els_logi_t), 0, 3276 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3277 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3278 3279 if (icmd == NULL) { 3280 ret = ENOMEM; 3281 } else { 3282 /* 3283 * Setup internal packet as sema sync 3284 */ 3285 fcp_ipkt_sema_init(icmd); 3286 3287 /* 3288 * Setup internal packet (icmd) 3289 */ 3290 icmd->ipkt_lun = NULL; 3291 icmd->ipkt_restart = 0; 3292 icmd->ipkt_retries = 0; 3293 icmd->ipkt_opcode = LA_ELS_PLOGI; 3294 3295 /* 3296 * Setup fc_packet 3297 */ 3298 fpkt = icmd->ipkt_fpkt; 3299 3300 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3301 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3302 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3303 3304 /* 3305 * Setup FC frame header 3306 */ 3307 hp = &fpkt->pkt_cmd_fhdr; 3308 3309 hp->s_id = pptr->port_id; /* source ID */ 3310 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3311 hp->r_ctl = R_CTL_ELS_REQ; 3312 hp->type = FC_TYPE_EXTENDED_LS; 3313 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3314 hp->seq_id = 0; 3315 hp->rsvd = 0; 3316 hp->df_ctl = 0; 3317 hp->seq_cnt = 0; 3318 hp->ox_id = 0xffff; /* i.e. none */ 3319 hp->rx_id = 0xffff; /* i.e. none */ 3320 hp->ro = 0; 3321 3322 /* 3323 * Setup PLOGI 3324 */ 3325 bzero(&logi, sizeof (struct la_els_logi)); 3326 logi.ls_code.ls_code = LA_ELS_PLOGI; 3327 3328 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3329 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3330 3331 /* 3332 * Send PLOGI 3333 */ 3334 *fc_status = login_retval = 3335 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3336 if (*fc_status != FC_SUCCESS) { 3337 ret = EIO; 3338 } 3339 } 3340 3341 /* 3342 * Wait for completion 3343 */ 3344 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3345 ret = fcp_ipkt_sema_wait(icmd); 3346 3347 *fc_pkt_state = fpkt->pkt_state; 3348 *fc_pkt_reason = fpkt->pkt_reason; 3349 *fc_pkt_action = fpkt->pkt_action; 3350 } 3351 3352 /* 3353 * Cleanup transport data structures if icmd was alloc-ed AND if there 3354 * is going to be no callback (i.e if fc_ulp_login() failed). 3355 * Otherwise, cleanup happens in callback routine. 3356 */ 3357 if (icmd != NULL) { 3358 fcp_ipkt_sema_cleanup(icmd); 3359 } 3360 3361 return (ret); 3362 } 3363 3364 /* 3365 * Function: fcp_tgt_send_prli 3366 * 3367 * Description: Does nothing as of today. 3368 * 3369 * Argument: ptgt Target to send the prli to. 3370 * fc_status Status returned by fp/fctl in the PRLI request. 3371 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3372 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3373 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3374 * 3375 * Return Value: 0 3376 */ 3377 /*ARGSUSED*/ 3378 static int 3379 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3380 int *fc_pkt_reason, int *fc_pkt_action) 3381 { 3382 return (0); 3383 } 3384 3385 /* 3386 * Function: fcp_ipkt_sema_init 3387 * 3388 * Description: Initializes the semaphore contained in the internal packet. 3389 * 3390 * Argument: icmd Internal packet the semaphore of which must be 3391 * initialized. 3392 * 3393 * Return Value: None 3394 * 3395 * Context: User context only. 3396 */ 3397 static void 3398 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3399 { 3400 struct fc_packet *fpkt; 3401 3402 fpkt = icmd->ipkt_fpkt; 3403 3404 /* Create semaphore for sync */ 3405 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3406 3407 /* Setup the completion callback */ 3408 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3409 } 3410 3411 /* 3412 * Function: fcp_ipkt_sema_wait 3413 * 3414 * Description: Wait on the semaphore embedded in the internal packet. The 3415 * semaphore is released in the callback. 3416 * 3417 * Argument: icmd Internal packet to wait on for completion. 3418 * 3419 * Return Value: 0 3420 * EIO 3421 * EBUSY 3422 * EAGAIN 3423 * 3424 * Context: User context only. 3425 * 3426 * This function does a conversion between the field pkt_state of the fc_packet 3427 * embedded in the internal packet (icmd) and the code it returns. 3428 */ 3429 static int 3430 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3431 { 3432 struct fc_packet *fpkt; 3433 int ret; 3434 3435 ret = EIO; 3436 fpkt = icmd->ipkt_fpkt; 3437 3438 /* 3439 * Wait on semaphore 3440 */ 3441 sema_p(&(icmd->ipkt_sema)); 3442 3443 /* 3444 * Check the status of the FC packet 3445 */ 3446 switch (fpkt->pkt_state) { 3447 case FC_PKT_SUCCESS: 3448 ret = 0; 3449 break; 3450 case FC_PKT_LOCAL_RJT: 3451 switch (fpkt->pkt_reason) { 3452 case FC_REASON_SEQ_TIMEOUT: 3453 case FC_REASON_RX_BUF_TIMEOUT: 3454 ret = EAGAIN; 3455 break; 3456 case FC_REASON_PKT_BUSY: 3457 ret = EBUSY; 3458 break; 3459 } 3460 break; 3461 case FC_PKT_TIMEOUT: 3462 ret = EAGAIN; 3463 break; 3464 case FC_PKT_LOCAL_BSY: 3465 case FC_PKT_TRAN_BSY: 3466 case FC_PKT_NPORT_BSY: 3467 case FC_PKT_FABRIC_BSY: 3468 ret = EBUSY; 3469 break; 3470 case FC_PKT_LS_RJT: 3471 case FC_PKT_BA_RJT: 3472 switch (fpkt->pkt_reason) { 3473 case FC_REASON_LOGICAL_BSY: 3474 ret = EBUSY; 3475 break; 3476 } 3477 break; 3478 case FC_PKT_FS_RJT: 3479 switch (fpkt->pkt_reason) { 3480 case FC_REASON_FS_LOGICAL_BUSY: 3481 ret = EBUSY; 3482 break; 3483 } 3484 break; 3485 } 3486 3487 return (ret); 3488 } 3489 3490 /* 3491 * Function: fcp_ipkt_sema_callback 3492 * 3493 * Description: Registered as the completion callback function for the FC 3494 * transport when the ipkt semaphore is used for sync. This will 3495 * cleanup the used data structures, if necessary and wake up 3496 * the user thread to complete the transaction. 3497 * 3498 * Argument: fpkt FC packet (points to the icmd) 3499 * 3500 * Return Value: None 3501 * 3502 * Context: User context only 3503 */ 3504 static void 3505 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3506 { 3507 struct fcp_ipkt *icmd; 3508 3509 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3510 3511 /* 3512 * Wake up user thread 3513 */ 3514 sema_v(&(icmd->ipkt_sema)); 3515 } 3516 3517 /* 3518 * Function: fcp_ipkt_sema_cleanup 3519 * 3520 * Description: Called to cleanup (if necessary) the data structures used 3521 * when ipkt sema is used for sync. This function will detect 3522 * whether the caller is the last thread (via counter) and 3523 * cleanup only if necessary. 3524 * 3525 * Argument: icmd Internal command packet 3526 * 3527 * Return Value: None 3528 * 3529 * Context: User context only 3530 */ 3531 static void 3532 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3533 { 3534 struct fcp_tgt *ptgt; 3535 struct fcp_port *pptr; 3536 3537 ptgt = icmd->ipkt_tgt; 3538 pptr = icmd->ipkt_port; 3539 3540 /* 3541 * Acquire data structure 3542 */ 3543 mutex_enter(&ptgt->tgt_mutex); 3544 3545 /* 3546 * Destroy semaphore 3547 */ 3548 sema_destroy(&(icmd->ipkt_sema)); 3549 3550 /* 3551 * Cleanup internal packet 3552 */ 3553 mutex_exit(&ptgt->tgt_mutex); 3554 fcp_icmd_free(pptr, icmd); 3555 } 3556 3557 /* 3558 * Function: fcp_port_attach 3559 * 3560 * Description: Called by the transport framework to resume, suspend or 3561 * attach a new port. 3562 * 3563 * Argument: ulph Port handle 3564 * *pinfo Port information 3565 * cmd Command 3566 * s_id Port ID 3567 * 3568 * Return Value: FC_FAILURE or FC_SUCCESS 3569 */ 3570 /*ARGSUSED*/ 3571 static int 3572 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3573 fc_attach_cmd_t cmd, uint32_t s_id) 3574 { 3575 int instance; 3576 int res = FC_FAILURE; /* default result */ 3577 3578 ASSERT(pinfo != NULL); 3579 3580 instance = ddi_get_instance(pinfo->port_dip); 3581 3582 switch (cmd) { 3583 case FC_CMD_ATTACH: 3584 /* 3585 * this port instance attaching for the first time (or after 3586 * being detached before) 3587 */ 3588 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3589 instance) == DDI_SUCCESS) { 3590 res = FC_SUCCESS; 3591 } else { 3592 ASSERT(ddi_get_soft_state(fcp_softstate, 3593 instance) == NULL); 3594 } 3595 break; 3596 3597 case FC_CMD_RESUME: 3598 case FC_CMD_POWER_UP: 3599 /* 3600 * this port instance was attached and the suspended and 3601 * will now be resumed 3602 */ 3603 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3604 instance) == DDI_SUCCESS) { 3605 res = FC_SUCCESS; 3606 } 3607 break; 3608 3609 default: 3610 /* shouldn't happen */ 3611 FCP_TRACE(fcp_logq, "fcp", 3612 fcp_trace, FCP_BUF_LEVEL_2, 0, 3613 "port_attach: unknown cmdcommand: %d", cmd); 3614 break; 3615 } 3616 3617 /* return result */ 3618 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3619 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3620 3621 return (res); 3622 } 3623 3624 3625 /* 3626 * detach or suspend this port instance 3627 * 3628 * acquires and releases the global mutex 3629 * 3630 * acquires and releases the mutex for this port 3631 * 3632 * acquires and releases the hotplug mutex for this port 3633 */ 3634 /*ARGSUSED*/ 3635 static int 3636 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3637 fc_detach_cmd_t cmd) 3638 { 3639 int flag; 3640 int instance; 3641 struct fcp_port *pptr; 3642 3643 instance = ddi_get_instance(info->port_dip); 3644 pptr = ddi_get_soft_state(fcp_softstate, instance); 3645 3646 switch (cmd) { 3647 case FC_CMD_SUSPEND: 3648 FCP_DTRACE(fcp_logq, "fcp", 3649 fcp_trace, FCP_BUF_LEVEL_8, 0, 3650 "port suspend called for port %d", instance); 3651 flag = FCP_STATE_SUSPENDED; 3652 break; 3653 3654 case FC_CMD_POWER_DOWN: 3655 FCP_DTRACE(fcp_logq, "fcp", 3656 fcp_trace, FCP_BUF_LEVEL_8, 0, 3657 "port power down called for port %d", instance); 3658 flag = FCP_STATE_POWER_DOWN; 3659 break; 3660 3661 case FC_CMD_DETACH: 3662 FCP_DTRACE(fcp_logq, "fcp", 3663 fcp_trace, FCP_BUF_LEVEL_8, 0, 3664 "port detach called for port %d", instance); 3665 flag = FCP_STATE_DETACHING; 3666 break; 3667 3668 default: 3669 /* shouldn't happen */ 3670 return (FC_FAILURE); 3671 } 3672 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3673 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3674 3675 return (fcp_handle_port_detach(pptr, flag, instance)); 3676 } 3677 3678 3679 /* 3680 * called for ioctls on the transport's devctl interface, and the transport 3681 * has passed it to us 3682 * 3683 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3684 * 3685 * return FC_SUCCESS if we decide to claim the ioctl, 3686 * else return FC_UNCLAIMED 3687 * 3688 * *rval is set iff we decide to claim the ioctl 3689 */ 3690 /*ARGSUSED*/ 3691 static int 3692 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3693 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3694 { 3695 int retval = FC_UNCLAIMED; /* return value */ 3696 struct fcp_port *pptr = NULL; /* our soft state */ 3697 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3698 dev_info_t *cdip; 3699 mdi_pathinfo_t *pip = NULL; 3700 char *ndi_nm; /* NDI name */ 3701 char *ndi_addr; /* NDI addr */ 3702 int is_mpxio, circ; 3703 int devi_entered = 0; 3704 clock_t end_time; 3705 3706 ASSERT(rval != NULL); 3707 3708 FCP_DTRACE(fcp_logq, "fcp", 3709 fcp_trace, FCP_BUF_LEVEL_8, 0, 3710 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3711 3712 /* if already claimed then forget it */ 3713 if (claimed) { 3714 /* 3715 * for now, if this ioctl has already been claimed, then 3716 * we just ignore it 3717 */ 3718 return (retval); 3719 } 3720 3721 /* get our port info */ 3722 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3723 fcp_log(CE_WARN, NULL, 3724 "!fcp:Invalid port handle handle in ioctl"); 3725 *rval = ENXIO; 3726 return (retval); 3727 } 3728 is_mpxio = pptr->port_mpxio; 3729 3730 switch (cmd) { 3731 case DEVCTL_BUS_GETSTATE: 3732 case DEVCTL_BUS_QUIESCE: 3733 case DEVCTL_BUS_UNQUIESCE: 3734 case DEVCTL_BUS_RESET: 3735 case DEVCTL_BUS_RESETALL: 3736 3737 case DEVCTL_BUS_DEV_CREATE: 3738 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3739 return (retval); 3740 } 3741 break; 3742 3743 case DEVCTL_DEVICE_GETSTATE: 3744 case DEVCTL_DEVICE_OFFLINE: 3745 case DEVCTL_DEVICE_ONLINE: 3746 case DEVCTL_DEVICE_REMOVE: 3747 case DEVCTL_DEVICE_RESET: 3748 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3749 return (retval); 3750 } 3751 3752 ASSERT(dcp != NULL); 3753 3754 /* ensure we have a name and address */ 3755 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3756 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3757 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3758 fcp_trace, FCP_BUF_LEVEL_2, 0, 3759 "ioctl: can't get name (%s) or addr (%s)", 3760 ndi_nm ? ndi_nm : "<null ptr>", 3761 ndi_addr ? ndi_addr : "<null ptr>"); 3762 ndi_dc_freehdl(dcp); 3763 return (retval); 3764 } 3765 3766 3767 /* get our child's DIP */ 3768 ASSERT(pptr != NULL); 3769 if (is_mpxio) { 3770 mdi_devi_enter(pptr->port_dip, &circ); 3771 } else { 3772 ndi_devi_enter(pptr->port_dip, &circ); 3773 } 3774 devi_entered = 1; 3775 3776 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3777 ndi_addr)) == NULL) { 3778 /* Look for virtually enumerated devices. */ 3779 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3780 if (pip == NULL || 3781 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3782 *rval = ENXIO; 3783 goto out; 3784 } 3785 } 3786 break; 3787 3788 default: 3789 *rval = ENOTTY; 3790 return (retval); 3791 } 3792 3793 /* this ioctl is ours -- process it */ 3794 3795 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3796 3797 /* we assume it will be a success; else we'll set error value */ 3798 *rval = 0; 3799 3800 3801 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3802 fcp_trace, FCP_BUF_LEVEL_8, 0, 3803 "ioctl: claiming this one"); 3804 3805 /* handle ioctls now */ 3806 switch (cmd) { 3807 case DEVCTL_DEVICE_GETSTATE: 3808 ASSERT(cdip != NULL); 3809 ASSERT(dcp != NULL); 3810 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3811 *rval = EFAULT; 3812 } 3813 break; 3814 3815 case DEVCTL_DEVICE_REMOVE: 3816 case DEVCTL_DEVICE_OFFLINE: { 3817 int flag = 0; 3818 int lcount; 3819 int tcount; 3820 struct fcp_pkt *head = NULL; 3821 struct fcp_lun *plun; 3822 child_info_t *cip = CIP(cdip); 3823 int all = 1; 3824 struct fcp_lun *tplun; 3825 struct fcp_tgt *ptgt; 3826 3827 ASSERT(pptr != NULL); 3828 ASSERT(cdip != NULL); 3829 3830 mutex_enter(&pptr->port_mutex); 3831 if (pip != NULL) { 3832 cip = CIP(pip); 3833 } 3834 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3835 mutex_exit(&pptr->port_mutex); 3836 *rval = ENXIO; 3837 break; 3838 } 3839 3840 head = fcp_scan_commands(plun); 3841 if (head != NULL) { 3842 fcp_abort_commands(head, LUN_PORT); 3843 } 3844 lcount = pptr->port_link_cnt; 3845 tcount = plun->lun_tgt->tgt_change_cnt; 3846 mutex_exit(&pptr->port_mutex); 3847 3848 if (cmd == DEVCTL_DEVICE_REMOVE) { 3849 flag = NDI_DEVI_REMOVE; 3850 } 3851 3852 if (is_mpxio) { 3853 mdi_devi_exit(pptr->port_dip, circ); 3854 } else { 3855 ndi_devi_exit(pptr->port_dip, circ); 3856 } 3857 devi_entered = 0; 3858 3859 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3860 FCP_OFFLINE, lcount, tcount, flag); 3861 3862 if (*rval != NDI_SUCCESS) { 3863 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3864 break; 3865 } 3866 3867 fcp_update_offline_flags(plun); 3868 3869 ptgt = plun->lun_tgt; 3870 mutex_enter(&ptgt->tgt_mutex); 3871 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3872 tplun->lun_next) { 3873 mutex_enter(&tplun->lun_mutex); 3874 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3875 all = 0; 3876 } 3877 mutex_exit(&tplun->lun_mutex); 3878 } 3879 3880 if (all) { 3881 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3882 /* 3883 * The user is unconfiguring/offlining the device. 3884 * If fabric and the auto configuration is set 3885 * then make sure the user is the only one who 3886 * can reconfigure the device. 3887 */ 3888 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3889 fcp_enable_auto_configuration) { 3890 ptgt->tgt_manual_config_only = 1; 3891 } 3892 } 3893 mutex_exit(&ptgt->tgt_mutex); 3894 break; 3895 } 3896 3897 case DEVCTL_DEVICE_ONLINE: { 3898 int lcount; 3899 int tcount; 3900 struct fcp_lun *plun; 3901 child_info_t *cip = CIP(cdip); 3902 3903 ASSERT(cdip != NULL); 3904 ASSERT(pptr != NULL); 3905 3906 mutex_enter(&pptr->port_mutex); 3907 if (pip != NULL) { 3908 cip = CIP(pip); 3909 } 3910 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3911 mutex_exit(&pptr->port_mutex); 3912 *rval = ENXIO; 3913 break; 3914 } 3915 lcount = pptr->port_link_cnt; 3916 tcount = plun->lun_tgt->tgt_change_cnt; 3917 mutex_exit(&pptr->port_mutex); 3918 3919 /* 3920 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3921 * to allow the device attach to occur when the device is 3922 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3923 * from the scsi_probe()). 3924 */ 3925 mutex_enter(&LUN_TGT->tgt_mutex); 3926 plun->lun_state |= FCP_LUN_ONLINING; 3927 mutex_exit(&LUN_TGT->tgt_mutex); 3928 3929 if (is_mpxio) { 3930 mdi_devi_exit(pptr->port_dip, circ); 3931 } else { 3932 ndi_devi_exit(pptr->port_dip, circ); 3933 } 3934 devi_entered = 0; 3935 3936 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3937 FCP_ONLINE, lcount, tcount, 0); 3938 3939 if (*rval != NDI_SUCCESS) { 3940 /* Reset the FCP_LUN_ONLINING bit */ 3941 mutex_enter(&LUN_TGT->tgt_mutex); 3942 plun->lun_state &= ~FCP_LUN_ONLINING; 3943 mutex_exit(&LUN_TGT->tgt_mutex); 3944 *rval = EIO; 3945 break; 3946 } 3947 mutex_enter(&LUN_TGT->tgt_mutex); 3948 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3949 FCP_LUN_ONLINING); 3950 mutex_exit(&LUN_TGT->tgt_mutex); 3951 break; 3952 } 3953 3954 case DEVCTL_BUS_DEV_CREATE: { 3955 uchar_t *bytes = NULL; 3956 uint_t nbytes; 3957 struct fcp_tgt *ptgt = NULL; 3958 struct fcp_lun *plun = NULL; 3959 dev_info_t *useless_dip = NULL; 3960 3961 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3962 DEVCTL_CONSTRUCT, &useless_dip); 3963 if (*rval != 0 || useless_dip == NULL) { 3964 break; 3965 } 3966 3967 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3968 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3969 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3970 *rval = EINVAL; 3971 (void) ndi_devi_free(useless_dip); 3972 if (bytes != NULL) { 3973 ddi_prop_free(bytes); 3974 } 3975 break; 3976 } 3977 3978 *rval = fcp_create_on_demand(pptr, bytes); 3979 if (*rval == 0) { 3980 mutex_enter(&pptr->port_mutex); 3981 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 3982 if (ptgt) { 3983 /* 3984 * We now have a pointer to the target that 3985 * was created. Lets point to the first LUN on 3986 * this new target. 3987 */ 3988 mutex_enter(&ptgt->tgt_mutex); 3989 3990 plun = ptgt->tgt_lun; 3991 /* 3992 * There may be stale/offline LUN entries on 3993 * this list (this is by design) and so we have 3994 * to make sure we point to the first online 3995 * LUN 3996 */ 3997 while (plun && 3998 plun->lun_state & FCP_LUN_OFFLINE) { 3999 plun = plun->lun_next; 4000 } 4001 4002 mutex_exit(&ptgt->tgt_mutex); 4003 } 4004 mutex_exit(&pptr->port_mutex); 4005 } 4006 4007 if (*rval == 0 && ptgt && plun) { 4008 mutex_enter(&plun->lun_mutex); 4009 /* 4010 * Allow up to fcp_lun_ready_retry seconds to 4011 * configure all the luns behind the target. 4012 * 4013 * The intent here is to allow targets with long 4014 * reboot/reset-recovery times to become available 4015 * while limiting the maximum wait time for an 4016 * unresponsive target. 4017 */ 4018 end_time = ddi_get_lbolt() + 4019 SEC_TO_TICK(fcp_lun_ready_retry); 4020 4021 while (ddi_get_lbolt() < end_time) { 4022 retval = FC_SUCCESS; 4023 4024 /* 4025 * The new ndi interfaces for on-demand creation 4026 * are inflexible, Do some more work to pass on 4027 * a path name of some LUN (design is broken !) 4028 */ 4029 if (plun->lun_cip) { 4030 if (plun->lun_mpxio == 0) { 4031 cdip = DIP(plun->lun_cip); 4032 } else { 4033 cdip = mdi_pi_get_client( 4034 PIP(plun->lun_cip)); 4035 } 4036 if (cdip == NULL) { 4037 *rval = ENXIO; 4038 break; 4039 } 4040 4041 if (!i_ddi_devi_attached(cdip)) { 4042 mutex_exit(&plun->lun_mutex); 4043 delay(drv_usectohz(1000000)); 4044 mutex_enter(&plun->lun_mutex); 4045 } else { 4046 /* 4047 * This Lun is ready, lets 4048 * check the next one. 4049 */ 4050 mutex_exit(&plun->lun_mutex); 4051 plun = plun->lun_next; 4052 while (plun && (plun->lun_state 4053 & FCP_LUN_OFFLINE)) { 4054 plun = plun->lun_next; 4055 } 4056 if (!plun) { 4057 break; 4058 } 4059 mutex_enter(&plun->lun_mutex); 4060 } 4061 } else { 4062 /* 4063 * lun_cip field for a valid lun 4064 * should never be NULL. Fail the 4065 * command. 4066 */ 4067 *rval = ENXIO; 4068 break; 4069 } 4070 } 4071 if (plun) { 4072 mutex_exit(&plun->lun_mutex); 4073 } else { 4074 char devnm[MAXNAMELEN]; 4075 int nmlen; 4076 4077 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4078 ddi_node_name(cdip), 4079 ddi_get_name_addr(cdip)); 4080 4081 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4082 0) { 4083 *rval = EFAULT; 4084 } 4085 } 4086 } else { 4087 int i; 4088 char buf[25]; 4089 4090 for (i = 0; i < FC_WWN_SIZE; i++) { 4091 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4092 } 4093 4094 fcp_log(CE_WARN, pptr->port_dip, 4095 "!Failed to create nodes for pwwn=%s; error=%x", 4096 buf, *rval); 4097 } 4098 4099 (void) ndi_devi_free(useless_dip); 4100 ddi_prop_free(bytes); 4101 break; 4102 } 4103 4104 case DEVCTL_DEVICE_RESET: { 4105 struct fcp_lun *plun; 4106 child_info_t *cip = CIP(cdip); 4107 4108 ASSERT(cdip != NULL); 4109 ASSERT(pptr != NULL); 4110 mutex_enter(&pptr->port_mutex); 4111 if (pip != NULL) { 4112 cip = CIP(pip); 4113 } 4114 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4115 mutex_exit(&pptr->port_mutex); 4116 *rval = ENXIO; 4117 break; 4118 } 4119 mutex_exit(&pptr->port_mutex); 4120 4121 mutex_enter(&plun->lun_tgt->tgt_mutex); 4122 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4123 mutex_exit(&plun->lun_tgt->tgt_mutex); 4124 4125 *rval = ENXIO; 4126 break; 4127 } 4128 4129 if (plun->lun_sd == NULL) { 4130 mutex_exit(&plun->lun_tgt->tgt_mutex); 4131 4132 *rval = ENXIO; 4133 break; 4134 } 4135 mutex_exit(&plun->lun_tgt->tgt_mutex); 4136 4137 /* 4138 * set up ap so that fcp_reset can figure out 4139 * which target to reset 4140 */ 4141 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4142 RESET_TARGET) == FALSE) { 4143 *rval = EIO; 4144 } 4145 break; 4146 } 4147 4148 case DEVCTL_BUS_GETSTATE: 4149 ASSERT(dcp != NULL); 4150 ASSERT(pptr != NULL); 4151 ASSERT(pptr->port_dip != NULL); 4152 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4153 NDI_SUCCESS) { 4154 *rval = EFAULT; 4155 } 4156 break; 4157 4158 case DEVCTL_BUS_QUIESCE: 4159 case DEVCTL_BUS_UNQUIESCE: 4160 *rval = ENOTSUP; 4161 break; 4162 4163 case DEVCTL_BUS_RESET: 4164 case DEVCTL_BUS_RESETALL: 4165 ASSERT(pptr != NULL); 4166 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4167 break; 4168 4169 default: 4170 ASSERT(dcp != NULL); 4171 *rval = ENOTTY; 4172 break; 4173 } 4174 4175 /* all done -- clean up and return */ 4176 out: if (devi_entered) { 4177 if (is_mpxio) { 4178 mdi_devi_exit(pptr->port_dip, circ); 4179 } else { 4180 ndi_devi_exit(pptr->port_dip, circ); 4181 } 4182 } 4183 4184 if (dcp != NULL) { 4185 ndi_dc_freehdl(dcp); 4186 } 4187 4188 return (retval); 4189 } 4190 4191 4192 /*ARGSUSED*/ 4193 static int 4194 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4195 uint32_t claimed) 4196 { 4197 uchar_t r_ctl; 4198 uchar_t ls_code; 4199 struct fcp_port *pptr; 4200 4201 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4202 return (FC_UNCLAIMED); 4203 } 4204 4205 mutex_enter(&pptr->port_mutex); 4206 if (pptr->port_state & (FCP_STATE_DETACHING | 4207 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4208 mutex_exit(&pptr->port_mutex); 4209 return (FC_UNCLAIMED); 4210 } 4211 mutex_exit(&pptr->port_mutex); 4212 4213 r_ctl = buf->ub_frame.r_ctl; 4214 4215 switch (r_ctl & R_CTL_ROUTING) { 4216 case R_CTL_EXTENDED_SVC: 4217 if (r_ctl == R_CTL_ELS_REQ) { 4218 ls_code = buf->ub_buffer[0]; 4219 4220 switch (ls_code) { 4221 case LA_ELS_PRLI: 4222 /* 4223 * We really don't care if something fails. 4224 * If the PRLI was not sent out, then the 4225 * other end will time it out. 4226 */ 4227 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4228 return (FC_SUCCESS); 4229 } 4230 return (FC_UNCLAIMED); 4231 /* NOTREACHED */ 4232 4233 default: 4234 break; 4235 } 4236 } 4237 /* FALLTHROUGH */ 4238 4239 default: 4240 return (FC_UNCLAIMED); 4241 } 4242 } 4243 4244 4245 /*ARGSUSED*/ 4246 static int 4247 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4248 uint32_t claimed) 4249 { 4250 return (FC_UNCLAIMED); 4251 } 4252 4253 /* 4254 * Function: fcp_statec_callback 4255 * 4256 * Description: The purpose of this function is to handle a port state change. 4257 * It is called from fp/fctl and, in a few instances, internally. 4258 * 4259 * Argument: ulph fp/fctl port handle 4260 * port_handle fcp_port structure 4261 * port_state Physical state of the port 4262 * port_top Topology 4263 * *devlist Pointer to the first entry of a table 4264 * containing the remote ports that can be 4265 * reached. 4266 * dev_cnt Number of entries pointed by devlist. 4267 * port_sid Port ID of the local port. 4268 * 4269 * Return Value: None 4270 */ 4271 /*ARGSUSED*/ 4272 static void 4273 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4274 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4275 uint32_t dev_cnt, uint32_t port_sid) 4276 { 4277 uint32_t link_count; 4278 int map_len = 0; 4279 struct fcp_port *pptr; 4280 fcp_map_tag_t *map_tag = NULL; 4281 4282 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4283 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4284 return; /* nothing to work with! */ 4285 } 4286 4287 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4288 fcp_trace, FCP_BUF_LEVEL_2, 0, 4289 "fcp_statec_callback: port state/dev_cnt/top =" 4290 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4291 dev_cnt, port_top); 4292 4293 mutex_enter(&pptr->port_mutex); 4294 4295 /* 4296 * If a thread is in detach, don't do anything. 4297 */ 4298 if (pptr->port_state & (FCP_STATE_DETACHING | 4299 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4300 mutex_exit(&pptr->port_mutex); 4301 return; 4302 } 4303 4304 /* 4305 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4306 * init_pkt is called, it knows whether or not the target's status 4307 * (or pd) might be changing. 4308 */ 4309 4310 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4311 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4312 } 4313 4314 /* 4315 * the transport doesn't allocate or probe unless being 4316 * asked to by either the applications or ULPs 4317 * 4318 * in cases where the port is OFFLINE at the time of port 4319 * attach callback and the link comes ONLINE later, for 4320 * easier automatic node creation (i.e. without you having to 4321 * go out and run the utility to perform LOGINs) the 4322 * following conditional is helpful 4323 */ 4324 pptr->port_phys_state = port_state; 4325 4326 if (dev_cnt) { 4327 mutex_exit(&pptr->port_mutex); 4328 4329 map_len = sizeof (*map_tag) * dev_cnt; 4330 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4331 if (map_tag == NULL) { 4332 fcp_log(CE_WARN, pptr->port_dip, 4333 "!fcp%d: failed to allocate for map tags; " 4334 " state change will not be processed", 4335 pptr->port_instance); 4336 4337 mutex_enter(&pptr->port_mutex); 4338 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4339 mutex_exit(&pptr->port_mutex); 4340 4341 return; 4342 } 4343 4344 mutex_enter(&pptr->port_mutex); 4345 } 4346 4347 if (pptr->port_id != port_sid) { 4348 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4349 fcp_trace, FCP_BUF_LEVEL_3, 0, 4350 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4351 port_sid); 4352 /* 4353 * The local port changed ID. It is the first time a port ID 4354 * is assigned or something drastic happened. We might have 4355 * been unplugged and replugged on another loop or fabric port 4356 * or somebody grabbed the AL_PA we had or somebody rezoned 4357 * the fabric we were plugged into. 4358 */ 4359 pptr->port_id = port_sid; 4360 } 4361 4362 switch (FC_PORT_STATE_MASK(port_state)) { 4363 case FC_STATE_OFFLINE: 4364 case FC_STATE_RESET_REQUESTED: 4365 /* 4366 * link has gone from online to offline -- just update the 4367 * state of this port to BUSY and MARKed to go offline 4368 */ 4369 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4370 fcp_trace, FCP_BUF_LEVEL_3, 0, 4371 "link went offline"); 4372 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4373 /* 4374 * We were offline a while ago and this one 4375 * seems to indicate that the loop has gone 4376 * dead forever. 4377 */ 4378 pptr->port_tmp_cnt += dev_cnt; 4379 pptr->port_state &= ~FCP_STATE_OFFLINE; 4380 pptr->port_state |= FCP_STATE_INIT; 4381 link_count = pptr->port_link_cnt; 4382 fcp_handle_devices(pptr, devlist, dev_cnt, 4383 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4384 } else { 4385 pptr->port_link_cnt++; 4386 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4387 fcp_update_state(pptr, (FCP_LUN_BUSY | 4388 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4389 if (pptr->port_mpxio) { 4390 fcp_update_mpxio_path_verifybusy(pptr); 4391 } 4392 pptr->port_state |= FCP_STATE_OFFLINE; 4393 pptr->port_state &= 4394 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4395 pptr->port_tmp_cnt = 0; 4396 } 4397 mutex_exit(&pptr->port_mutex); 4398 break; 4399 4400 case FC_STATE_ONLINE: 4401 case FC_STATE_LIP: 4402 case FC_STATE_LIP_LBIT_SET: 4403 /* 4404 * link has gone from offline to online 4405 */ 4406 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4407 fcp_trace, FCP_BUF_LEVEL_3, 0, 4408 "link went online"); 4409 4410 pptr->port_link_cnt++; 4411 4412 while (pptr->port_ipkt_cnt) { 4413 mutex_exit(&pptr->port_mutex); 4414 delay(drv_usectohz(1000000)); 4415 mutex_enter(&pptr->port_mutex); 4416 } 4417 4418 pptr->port_topology = port_top; 4419 4420 /* 4421 * The state of the targets and luns accessible through this 4422 * port is updated. 4423 */ 4424 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4425 FCP_CAUSE_LINK_CHANGE); 4426 4427 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4428 pptr->port_state |= FCP_STATE_ONLINING; 4429 pptr->port_tmp_cnt = dev_cnt; 4430 link_count = pptr->port_link_cnt; 4431 4432 pptr->port_deadline = fcp_watchdog_time + 4433 FCP_ICMD_DEADLINE; 4434 4435 if (!dev_cnt) { 4436 /* 4437 * We go directly to the online state if no remote 4438 * ports were discovered. 4439 */ 4440 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4441 fcp_trace, FCP_BUF_LEVEL_3, 0, 4442 "No remote ports discovered"); 4443 4444 pptr->port_state &= ~FCP_STATE_ONLINING; 4445 pptr->port_state |= FCP_STATE_ONLINE; 4446 } 4447 4448 switch (port_top) { 4449 case FC_TOP_FABRIC: 4450 case FC_TOP_PUBLIC_LOOP: 4451 case FC_TOP_PRIVATE_LOOP: 4452 case FC_TOP_PT_PT: 4453 4454 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4455 fcp_retry_ns_registry(pptr, port_sid); 4456 } 4457 4458 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4459 map_tag, FCP_CAUSE_LINK_CHANGE); 4460 break; 4461 4462 default: 4463 /* 4464 * We got here because we were provided with an unknown 4465 * topology. 4466 */ 4467 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4468 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4469 } 4470 4471 pptr->port_tmp_cnt -= dev_cnt; 4472 fcp_log(CE_WARN, pptr->port_dip, 4473 "!unknown/unsupported topology (0x%x)", port_top); 4474 break; 4475 } 4476 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4477 fcp_trace, FCP_BUF_LEVEL_3, 0, 4478 "Notify ssd of the reset to reinstate the reservations"); 4479 4480 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4481 &pptr->port_reset_notify_listf); 4482 4483 mutex_exit(&pptr->port_mutex); 4484 4485 break; 4486 4487 case FC_STATE_RESET: 4488 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4489 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4490 fcp_trace, FCP_BUF_LEVEL_3, 0, 4491 "RESET state, waiting for Offline/Online state_cb"); 4492 mutex_exit(&pptr->port_mutex); 4493 break; 4494 4495 case FC_STATE_DEVICE_CHANGE: 4496 /* 4497 * We come here when an application has requested 4498 * Dynamic node creation/deletion in Fabric connectivity. 4499 */ 4500 if (pptr->port_state & (FCP_STATE_OFFLINE | 4501 FCP_STATE_INIT)) { 4502 /* 4503 * This case can happen when the FCTL is in the 4504 * process of giving us on online and the host on 4505 * the other side issues a PLOGI/PLOGO. Ideally 4506 * the state changes should be serialized unless 4507 * they are opposite (online-offline). 4508 * The transport will give us a final state change 4509 * so we can ignore this for the time being. 4510 */ 4511 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4512 mutex_exit(&pptr->port_mutex); 4513 break; 4514 } 4515 4516 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4517 fcp_retry_ns_registry(pptr, port_sid); 4518 } 4519 4520 /* 4521 * Extend the deadline under steady state conditions 4522 * to provide more time for the device-change-commands 4523 */ 4524 if (!pptr->port_ipkt_cnt) { 4525 pptr->port_deadline = fcp_watchdog_time + 4526 FCP_ICMD_DEADLINE; 4527 } 4528 4529 /* 4530 * There is another race condition here, where if we were 4531 * in ONLINEING state and a devices in the map logs out, 4532 * fp will give another state change as DEVICE_CHANGE 4533 * and OLD. This will result in that target being offlined. 4534 * The pd_handle is freed. If from the first statec callback 4535 * we were going to fire a PLOGI/PRLI, the system will 4536 * panic in fc_ulp_transport with invalid pd_handle. 4537 * The fix is to check for the link_cnt before issuing 4538 * any command down. 4539 */ 4540 fcp_update_targets(pptr, devlist, dev_cnt, 4541 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4542 4543 link_count = pptr->port_link_cnt; 4544 4545 fcp_handle_devices(pptr, devlist, dev_cnt, 4546 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4547 4548 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4549 4550 mutex_exit(&pptr->port_mutex); 4551 break; 4552 4553 case FC_STATE_TARGET_PORT_RESET: 4554 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4555 fcp_retry_ns_registry(pptr, port_sid); 4556 } 4557 4558 /* Do nothing else */ 4559 mutex_exit(&pptr->port_mutex); 4560 break; 4561 4562 default: 4563 fcp_log(CE_WARN, pptr->port_dip, 4564 "!Invalid state change=0x%x", port_state); 4565 mutex_exit(&pptr->port_mutex); 4566 break; 4567 } 4568 4569 if (map_tag) { 4570 kmem_free(map_tag, map_len); 4571 } 4572 } 4573 4574 /* 4575 * Function: fcp_handle_devices 4576 * 4577 * Description: This function updates the devices currently known by 4578 * walking the list provided by the caller. The list passed 4579 * by the caller is supposed to be the list of reachable 4580 * devices. 4581 * 4582 * Argument: *pptr Fcp port structure. 4583 * *devlist Pointer to the first entry of a table 4584 * containing the remote ports that can be 4585 * reached. 4586 * dev_cnt Number of entries pointed by devlist. 4587 * link_cnt Link state count. 4588 * *map_tag Array of fcp_map_tag_t structures. 4589 * cause What caused this function to be called. 4590 * 4591 * Return Value: None 4592 * 4593 * Notes: The pptr->port_mutex must be held. 4594 */ 4595 static void 4596 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4597 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4598 { 4599 int i; 4600 int check_finish_init = 0; 4601 fc_portmap_t *map_entry; 4602 struct fcp_tgt *ptgt = NULL; 4603 4604 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4605 fcp_trace, FCP_BUF_LEVEL_3, 0, 4606 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4607 4608 if (dev_cnt) { 4609 ASSERT(map_tag != NULL); 4610 } 4611 4612 /* 4613 * The following code goes through the list of remote ports that are 4614 * accessible through this (pptr) local port (The list walked is the 4615 * one provided by the caller which is the list of the remote ports 4616 * currently reachable). It checks if any of them was already 4617 * known by looking for the corresponding target structure based on 4618 * the world wide name. If a target is part of the list it is tagged 4619 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4620 * 4621 * Old comment 4622 * ----------- 4623 * Before we drop port mutex; we MUST get the tags updated; This 4624 * two step process is somewhat slow, but more reliable. 4625 */ 4626 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4627 map_entry = &(devlist[i]); 4628 4629 /* 4630 * get ptr to this map entry in our port's 4631 * list (if any) 4632 */ 4633 ptgt = fcp_lookup_target(pptr, 4634 (uchar_t *)&(map_entry->map_pwwn)); 4635 4636 if (ptgt) { 4637 map_tag[i] = ptgt->tgt_change_cnt; 4638 if (cause == FCP_CAUSE_LINK_CHANGE) { 4639 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4640 } 4641 } 4642 } 4643 4644 /* 4645 * At this point we know which devices of the new list were already 4646 * known (The field tgt_aux_state of the target structure has been 4647 * set to FCP_TGT_TAGGED). 4648 * 4649 * The following code goes through the list of targets currently known 4650 * by the local port (the list is actually a hashing table). If a 4651 * target is found and is not tagged, it means the target cannot 4652 * be reached anymore through the local port (pptr). It is offlined. 4653 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4654 */ 4655 for (i = 0; i < FCP_NUM_HASH; i++) { 4656 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4657 ptgt = ptgt->tgt_next) { 4658 mutex_enter(&ptgt->tgt_mutex); 4659 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4660 (cause == FCP_CAUSE_LINK_CHANGE) && 4661 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4662 fcp_offline_target_now(pptr, ptgt, 4663 link_cnt, ptgt->tgt_change_cnt, 0); 4664 } 4665 mutex_exit(&ptgt->tgt_mutex); 4666 } 4667 } 4668 4669 /* 4670 * At this point, the devices that were known but cannot be reached 4671 * anymore, have most likely been offlined. 4672 * 4673 * The following section of code seems to go through the list of 4674 * remote ports that can now be reached. For every single one it 4675 * checks if it is already known or if it is a new port. 4676 */ 4677 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4678 4679 if (check_finish_init) { 4680 ASSERT(i > 0); 4681 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4682 map_tag[i - 1], cause); 4683 check_finish_init = 0; 4684 } 4685 4686 /* get a pointer to this map entry */ 4687 map_entry = &(devlist[i]); 4688 4689 /* 4690 * Check for the duplicate map entry flag. If we have marked 4691 * this entry as a duplicate we skip it since the correct 4692 * (perhaps even same) state change will be encountered 4693 * later in the list. 4694 */ 4695 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4696 continue; 4697 } 4698 4699 /* get ptr to this map entry in our port's list (if any) */ 4700 ptgt = fcp_lookup_target(pptr, 4701 (uchar_t *)&(map_entry->map_pwwn)); 4702 4703 if (ptgt) { 4704 /* 4705 * This device was already known. The field 4706 * tgt_aux_state is reset (was probably set to 4707 * FCP_TGT_TAGGED previously in this routine). 4708 */ 4709 ptgt->tgt_aux_state = 0; 4710 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4711 fcp_trace, FCP_BUF_LEVEL_3, 0, 4712 "handle_devices: map did/state/type/flags = " 4713 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4714 "tgt_state=%d", 4715 map_entry->map_did.port_id, map_entry->map_state, 4716 map_entry->map_type, map_entry->map_flags, 4717 ptgt->tgt_d_id, ptgt->tgt_state); 4718 } 4719 4720 if (map_entry->map_type == PORT_DEVICE_OLD || 4721 map_entry->map_type == PORT_DEVICE_NEW || 4722 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4723 map_entry->map_type == PORT_DEVICE_CHANGED) { 4724 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4725 fcp_trace, FCP_BUF_LEVEL_2, 0, 4726 "map_type=%x, did = %x", 4727 map_entry->map_type, 4728 map_entry->map_did.port_id); 4729 } 4730 4731 switch (map_entry->map_type) { 4732 case PORT_DEVICE_NOCHANGE: 4733 case PORT_DEVICE_USER_CREATE: 4734 case PORT_DEVICE_USER_LOGIN: 4735 case PORT_DEVICE_NEW: 4736 case PORT_DEVICE_REPORTLUN_CHANGED: 4737 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4738 4739 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4740 link_cnt, (ptgt) ? map_tag[i] : 0, 4741 cause) == TRUE) { 4742 4743 FCP_TGT_TRACE(ptgt, map_tag[i], 4744 FCP_TGT_TRACE_2); 4745 check_finish_init++; 4746 } 4747 break; 4748 4749 case PORT_DEVICE_OLD: 4750 if (ptgt != NULL) { 4751 FCP_TGT_TRACE(ptgt, map_tag[i], 4752 FCP_TGT_TRACE_3); 4753 4754 mutex_enter(&ptgt->tgt_mutex); 4755 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4756 /* 4757 * Must do an in-line wait for I/Os 4758 * to get drained 4759 */ 4760 mutex_exit(&ptgt->tgt_mutex); 4761 mutex_exit(&pptr->port_mutex); 4762 4763 mutex_enter(&ptgt->tgt_mutex); 4764 while (ptgt->tgt_ipkt_cnt || 4765 fcp_outstanding_lun_cmds(ptgt) 4766 == FC_SUCCESS) { 4767 mutex_exit(&ptgt->tgt_mutex); 4768 delay(drv_usectohz(1000000)); 4769 mutex_enter(&ptgt->tgt_mutex); 4770 } 4771 mutex_exit(&ptgt->tgt_mutex); 4772 4773 mutex_enter(&pptr->port_mutex); 4774 mutex_enter(&ptgt->tgt_mutex); 4775 4776 (void) fcp_offline_target(pptr, ptgt, 4777 link_cnt, map_tag[i], 0, 0); 4778 } 4779 mutex_exit(&ptgt->tgt_mutex); 4780 } 4781 check_finish_init++; 4782 break; 4783 4784 case PORT_DEVICE_USER_DELETE: 4785 case PORT_DEVICE_USER_LOGOUT: 4786 if (ptgt != NULL) { 4787 FCP_TGT_TRACE(ptgt, map_tag[i], 4788 FCP_TGT_TRACE_4); 4789 4790 mutex_enter(&ptgt->tgt_mutex); 4791 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4792 (void) fcp_offline_target(pptr, ptgt, 4793 link_cnt, map_tag[i], 1, 0); 4794 } 4795 mutex_exit(&ptgt->tgt_mutex); 4796 } 4797 check_finish_init++; 4798 break; 4799 4800 case PORT_DEVICE_CHANGED: 4801 if (ptgt != NULL) { 4802 FCP_TGT_TRACE(ptgt, map_tag[i], 4803 FCP_TGT_TRACE_5); 4804 4805 if (fcp_device_changed(pptr, ptgt, 4806 map_entry, link_cnt, map_tag[i], 4807 cause) == TRUE) { 4808 check_finish_init++; 4809 } 4810 } else { 4811 if (fcp_handle_mapflags(pptr, ptgt, 4812 map_entry, link_cnt, 0, cause) == TRUE) { 4813 check_finish_init++; 4814 } 4815 } 4816 break; 4817 4818 default: 4819 fcp_log(CE_WARN, pptr->port_dip, 4820 "!Invalid map_type=0x%x", map_entry->map_type); 4821 check_finish_init++; 4822 break; 4823 } 4824 } 4825 4826 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4827 ASSERT(i > 0); 4828 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4829 map_tag[i-1], cause); 4830 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4831 fcp_offline_all(pptr, link_cnt, cause); 4832 } 4833 } 4834 4835 static int 4836 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4837 { 4838 struct fcp_lun *plun; 4839 struct fcp_port *pptr; 4840 int rscn_count; 4841 int lun0_newalloc; 4842 int ret = TRUE; 4843 4844 ASSERT(ptgt); 4845 pptr = ptgt->tgt_port; 4846 lun0_newalloc = 0; 4847 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4848 /* 4849 * no LUN struct for LUN 0 yet exists, 4850 * so create one 4851 */ 4852 plun = fcp_alloc_lun(ptgt); 4853 if (plun == NULL) { 4854 fcp_log(CE_WARN, pptr->port_dip, 4855 "!Failed to allocate lun 0 for" 4856 " D_ID=%x", ptgt->tgt_d_id); 4857 return (ret); 4858 } 4859 lun0_newalloc = 1; 4860 } 4861 4862 mutex_enter(&ptgt->tgt_mutex); 4863 /* 4864 * consider lun 0 as device not connected if it is 4865 * offlined or newly allocated 4866 */ 4867 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4868 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4869 } 4870 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4871 plun->lun_state &= ~FCP_LUN_OFFLINE; 4872 ptgt->tgt_lun_cnt = 1; 4873 ptgt->tgt_report_lun_cnt = 0; 4874 mutex_exit(&ptgt->tgt_mutex); 4875 4876 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4877 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4878 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4879 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4880 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4881 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4882 "to D_ID=%x", ptgt->tgt_d_id); 4883 } else { 4884 ret = FALSE; 4885 } 4886 4887 return (ret); 4888 } 4889 4890 /* 4891 * Function: fcp_handle_mapflags 4892 * 4893 * Description: This function creates a target structure if the ptgt passed 4894 * is NULL. It also kicks off the PLOGI if we are not logged 4895 * into the target yet or the PRLI if we are logged into the 4896 * target already. The rest of the treatment is done in the 4897 * callbacks of the PLOGI or PRLI. 4898 * 4899 * Argument: *pptr FCP Port structure. 4900 * *ptgt Target structure. 4901 * *map_entry Array of fc_portmap_t structures. 4902 * link_cnt Link state count. 4903 * tgt_cnt Target state count. 4904 * cause What caused this function to be called. 4905 * 4906 * Return Value: TRUE Failed 4907 * FALSE Succeeded 4908 * 4909 * Notes: pptr->port_mutex must be owned. 4910 */ 4911 static int 4912 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4913 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4914 { 4915 int lcount; 4916 int tcount; 4917 int ret = TRUE; 4918 int alloc; 4919 struct fcp_ipkt *icmd; 4920 struct fcp_lun *pseq_lun = NULL; 4921 uchar_t opcode; 4922 int valid_ptgt_was_passed = FALSE; 4923 4924 ASSERT(mutex_owned(&pptr->port_mutex)); 4925 4926 /* 4927 * This case is possible where the FCTL has come up and done discovery 4928 * before FCP was loaded and attached. FCTL would have discovered the 4929 * devices and later the ULP came online. In this case ULP's would get 4930 * PORT_DEVICE_NOCHANGE but target would be NULL. 4931 */ 4932 if (ptgt == NULL) { 4933 /* don't already have a target */ 4934 mutex_exit(&pptr->port_mutex); 4935 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4936 mutex_enter(&pptr->port_mutex); 4937 4938 if (ptgt == NULL) { 4939 fcp_log(CE_WARN, pptr->port_dip, 4940 "!FC target allocation failed"); 4941 return (ret); 4942 } 4943 mutex_enter(&ptgt->tgt_mutex); 4944 ptgt->tgt_statec_cause = cause; 4945 ptgt->tgt_tmp_cnt = 1; 4946 mutex_exit(&ptgt->tgt_mutex); 4947 } else { 4948 valid_ptgt_was_passed = TRUE; 4949 } 4950 4951 /* 4952 * Copy in the target parameters 4953 */ 4954 mutex_enter(&ptgt->tgt_mutex); 4955 ptgt->tgt_d_id = map_entry->map_did.port_id; 4956 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4957 ptgt->tgt_pd_handle = map_entry->map_pd; 4958 ptgt->tgt_fca_dev = NULL; 4959 4960 /* Copy port and node WWNs */ 4961 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4962 FC_WWN_SIZE); 4963 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4964 FC_WWN_SIZE); 4965 4966 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4967 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4968 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4969 valid_ptgt_was_passed) { 4970 /* 4971 * determine if there are any tape LUNs on this target 4972 */ 4973 for (pseq_lun = ptgt->tgt_lun; 4974 pseq_lun != NULL; 4975 pseq_lun = pseq_lun->lun_next) { 4976 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4977 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4978 fcp_update_tgt_state(ptgt, FCP_RESET, 4979 FCP_LUN_MARK); 4980 mutex_exit(&ptgt->tgt_mutex); 4981 return (ret); 4982 } 4983 } 4984 } 4985 4986 /* 4987 * if UA'REPORT_LUN_CHANGED received, 4988 * send out REPORT LUN promptly, skip PLOGI/PRLI process 4989 */ 4990 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 4991 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 4992 mutex_exit(&ptgt->tgt_mutex); 4993 mutex_exit(&pptr->port_mutex); 4994 4995 ret = fcp_handle_reportlun_changed(ptgt, cause); 4996 4997 mutex_enter(&pptr->port_mutex); 4998 return (ret); 4999 } 5000 5001 /* 5002 * If ptgt was NULL when this function was entered, then tgt_node_state 5003 * was never specifically initialized but zeroed out which means 5004 * FCP_TGT_NODE_NONE. 5005 */ 5006 switch (ptgt->tgt_node_state) { 5007 case FCP_TGT_NODE_NONE: 5008 case FCP_TGT_NODE_ON_DEMAND: 5009 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5010 !fcp_enable_auto_configuration && 5011 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5012 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5013 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5014 fcp_enable_auto_configuration && 5015 (ptgt->tgt_manual_config_only == 1) && 5016 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5017 /* 5018 * If auto configuration is set and 5019 * the tgt_manual_config_only flag is set then 5020 * we only want the user to be able to change 5021 * the state through create_on_demand. 5022 */ 5023 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5024 } else { 5025 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5026 } 5027 break; 5028 5029 case FCP_TGT_NODE_PRESENT: 5030 break; 5031 } 5032 /* 5033 * If we are booting from a fabric device, make sure we 5034 * mark the node state appropriately for this target to be 5035 * enumerated 5036 */ 5037 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5038 if (bcmp((caddr_t)pptr->port_boot_wwn, 5039 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5040 sizeof (ptgt->tgt_port_wwn)) == 0) { 5041 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5042 } 5043 } 5044 mutex_exit(&ptgt->tgt_mutex); 5045 5046 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5047 fcp_trace, FCP_BUF_LEVEL_3, 0, 5048 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5049 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5050 map_entry->map_rscn_info.ulp_rscn_count); 5051 5052 mutex_enter(&ptgt->tgt_mutex); 5053 5054 /* 5055 * Reset target OFFLINE state and mark the target BUSY 5056 */ 5057 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5058 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5059 5060 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5061 lcount = link_cnt; 5062 5063 mutex_exit(&ptgt->tgt_mutex); 5064 mutex_exit(&pptr->port_mutex); 5065 5066 /* 5067 * if we are already logged in, then we do a PRLI, else 5068 * we do a PLOGI first (to get logged in) 5069 * 5070 * We will not check if we are the PLOGI initiator 5071 */ 5072 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5073 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5074 5075 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5076 5077 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5078 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5079 cause, map_entry->map_rscn_info.ulp_rscn_count); 5080 5081 if (icmd == NULL) { 5082 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5083 /* 5084 * We've exited port_mutex before calling fcp_icmd_alloc, 5085 * we need to make sure we reacquire it before returning. 5086 */ 5087 mutex_enter(&pptr->port_mutex); 5088 return (FALSE); 5089 } 5090 5091 /* TRUE is only returned while target is intended skipped */ 5092 ret = FALSE; 5093 /* discover info about this target */ 5094 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5095 lcount, tcount, cause)) == DDI_SUCCESS) { 5096 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5097 } else { 5098 fcp_icmd_free(pptr, icmd); 5099 ret = TRUE; 5100 } 5101 mutex_enter(&pptr->port_mutex); 5102 5103 return (ret); 5104 } 5105 5106 /* 5107 * Function: fcp_send_els 5108 * 5109 * Description: Sends an ELS to the target specified by the caller. Supports 5110 * PLOGI and PRLI. 5111 * 5112 * Argument: *pptr Fcp port. 5113 * *ptgt Target to send the ELS to. 5114 * *icmd Internal packet 5115 * opcode ELS opcode 5116 * lcount Link state change counter 5117 * tcount Target state change counter 5118 * cause What caused the call 5119 * 5120 * Return Value: DDI_SUCCESS 5121 * Others 5122 */ 5123 static int 5124 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5125 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5126 { 5127 fc_packet_t *fpkt; 5128 fc_frame_hdr_t *hp; 5129 int internal = 0; 5130 int alloc; 5131 int cmd_len; 5132 int resp_len; 5133 int res = DDI_FAILURE; /* default result */ 5134 int rval = DDI_FAILURE; 5135 5136 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5137 ASSERT(ptgt->tgt_port == pptr); 5138 5139 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5140 fcp_trace, FCP_BUF_LEVEL_5, 0, 5141 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5142 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5143 5144 if (opcode == LA_ELS_PLOGI) { 5145 cmd_len = sizeof (la_els_logi_t); 5146 resp_len = sizeof (la_els_logi_t); 5147 } else { 5148 ASSERT(opcode == LA_ELS_PRLI); 5149 cmd_len = sizeof (la_els_prli_t); 5150 resp_len = sizeof (la_els_prli_t); 5151 } 5152 5153 if (icmd == NULL) { 5154 alloc = FCP_MAX(sizeof (la_els_logi_t), 5155 sizeof (la_els_prli_t)); 5156 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5157 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5158 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5159 if (icmd == NULL) { 5160 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5161 return (res); 5162 } 5163 internal++; 5164 } 5165 fpkt = icmd->ipkt_fpkt; 5166 5167 fpkt->pkt_cmdlen = cmd_len; 5168 fpkt->pkt_rsplen = resp_len; 5169 fpkt->pkt_datalen = 0; 5170 icmd->ipkt_retries = 0; 5171 5172 /* fill in fpkt info */ 5173 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5174 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5175 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5176 5177 /* get ptr to frame hdr in fpkt */ 5178 hp = &fpkt->pkt_cmd_fhdr; 5179 5180 /* 5181 * fill in frame hdr 5182 */ 5183 hp->r_ctl = R_CTL_ELS_REQ; 5184 hp->s_id = pptr->port_id; /* source ID */ 5185 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5186 hp->type = FC_TYPE_EXTENDED_LS; 5187 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5188 hp->seq_id = 0; 5189 hp->rsvd = 0; 5190 hp->df_ctl = 0; 5191 hp->seq_cnt = 0; 5192 hp->ox_id = 0xffff; /* i.e. none */ 5193 hp->rx_id = 0xffff; /* i.e. none */ 5194 hp->ro = 0; 5195 5196 /* 5197 * at this point we have a filled in cmd pkt 5198 * 5199 * fill in the respective info, then use the transport to send 5200 * the packet 5201 * 5202 * for a PLOGI call fc_ulp_login(), and 5203 * for a PRLI call fc_ulp_issue_els() 5204 */ 5205 switch (opcode) { 5206 case LA_ELS_PLOGI: { 5207 struct la_els_logi logi; 5208 5209 bzero(&logi, sizeof (struct la_els_logi)); 5210 5211 hp = &fpkt->pkt_cmd_fhdr; 5212 hp->r_ctl = R_CTL_ELS_REQ; 5213 logi.ls_code.ls_code = LA_ELS_PLOGI; 5214 logi.ls_code.mbz = 0; 5215 5216 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5217 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5218 5219 icmd->ipkt_opcode = LA_ELS_PLOGI; 5220 5221 mutex_enter(&pptr->port_mutex); 5222 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5223 5224 mutex_exit(&pptr->port_mutex); 5225 5226 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5227 if (rval == FC_SUCCESS) { 5228 res = DDI_SUCCESS; 5229 break; 5230 } 5231 5232 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5233 5234 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5235 rval, "PLOGI"); 5236 } else { 5237 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5238 fcp_trace, FCP_BUF_LEVEL_5, 0, 5239 "fcp_send_els1: state change occured" 5240 " for D_ID=0x%x", ptgt->tgt_d_id); 5241 mutex_exit(&pptr->port_mutex); 5242 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5243 } 5244 break; 5245 } 5246 5247 case LA_ELS_PRLI: { 5248 struct la_els_prli prli; 5249 struct fcp_prli *fprli; 5250 5251 bzero(&prli, sizeof (struct la_els_prli)); 5252 5253 hp = &fpkt->pkt_cmd_fhdr; 5254 hp->r_ctl = R_CTL_ELS_REQ; 5255 5256 /* fill in PRLI cmd ELS fields */ 5257 prli.ls_code = LA_ELS_PRLI; 5258 prli.page_length = 0x10; /* huh? */ 5259 prli.payload_length = sizeof (struct la_els_prli); 5260 5261 icmd->ipkt_opcode = LA_ELS_PRLI; 5262 5263 /* get ptr to PRLI service params */ 5264 fprli = (struct fcp_prli *)prli.service_params; 5265 5266 /* fill in service params */ 5267 fprli->type = 0x08; 5268 fprli->resvd1 = 0; 5269 fprli->orig_process_assoc_valid = 0; 5270 fprli->resp_process_assoc_valid = 0; 5271 fprli->establish_image_pair = 1; 5272 fprli->resvd2 = 0; 5273 fprli->resvd3 = 0; 5274 fprli->obsolete_1 = 0; 5275 fprli->obsolete_2 = 0; 5276 fprli->data_overlay_allowed = 0; 5277 fprli->initiator_fn = 1; 5278 fprli->confirmed_compl_allowed = 1; 5279 5280 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5281 fprli->target_fn = 1; 5282 } else { 5283 fprli->target_fn = 0; 5284 } 5285 5286 fprli->retry = 1; 5287 fprli->read_xfer_rdy_disabled = 1; 5288 fprli->write_xfer_rdy_disabled = 0; 5289 5290 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5291 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5292 5293 /* issue the PRLI request */ 5294 5295 mutex_enter(&pptr->port_mutex); 5296 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5297 5298 mutex_exit(&pptr->port_mutex); 5299 5300 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5301 if (rval == FC_SUCCESS) { 5302 res = DDI_SUCCESS; 5303 break; 5304 } 5305 5306 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5307 5308 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5309 rval, "PRLI"); 5310 } else { 5311 mutex_exit(&pptr->port_mutex); 5312 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5313 } 5314 break; 5315 } 5316 5317 default: 5318 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5319 break; 5320 } 5321 5322 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5323 fcp_trace, FCP_BUF_LEVEL_5, 0, 5324 "fcp_send_els: returning %d", res); 5325 5326 if (res != DDI_SUCCESS) { 5327 if (internal) { 5328 fcp_icmd_free(pptr, icmd); 5329 } 5330 } 5331 5332 return (res); 5333 } 5334 5335 5336 /* 5337 * called internally update the state of all of the tgts and each LUN 5338 * for this port (i.e. each target known to be attached to this port) 5339 * if they are not already offline 5340 * 5341 * must be called with the port mutex owned 5342 * 5343 * acquires and releases the target mutexes for each target attached 5344 * to this port 5345 */ 5346 void 5347 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5348 { 5349 int i; 5350 struct fcp_tgt *ptgt; 5351 5352 ASSERT(mutex_owned(&pptr->port_mutex)); 5353 5354 for (i = 0; i < FCP_NUM_HASH; i++) { 5355 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5356 ptgt = ptgt->tgt_next) { 5357 mutex_enter(&ptgt->tgt_mutex); 5358 fcp_update_tgt_state(ptgt, FCP_SET, state); 5359 ptgt->tgt_change_cnt++; 5360 ptgt->tgt_statec_cause = cause; 5361 ptgt->tgt_tmp_cnt = 1; 5362 ptgt->tgt_done = 0; 5363 mutex_exit(&ptgt->tgt_mutex); 5364 } 5365 } 5366 } 5367 5368 5369 static void 5370 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5371 { 5372 int i; 5373 int ndevs; 5374 struct fcp_tgt *ptgt; 5375 5376 ASSERT(mutex_owned(&pptr->port_mutex)); 5377 5378 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5379 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5380 ptgt = ptgt->tgt_next) { 5381 ndevs++; 5382 } 5383 } 5384 5385 if (ndevs == 0) { 5386 return; 5387 } 5388 pptr->port_tmp_cnt = ndevs; 5389 5390 for (i = 0; i < FCP_NUM_HASH; i++) { 5391 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5392 ptgt = ptgt->tgt_next) { 5393 (void) fcp_call_finish_init_held(pptr, ptgt, 5394 lcount, ptgt->tgt_change_cnt, cause); 5395 } 5396 } 5397 } 5398 5399 /* 5400 * Function: fcp_update_tgt_state 5401 * 5402 * Description: This function updates the field tgt_state of a target. That 5403 * field is a bitmap and which bit can be set or reset 5404 * individually. The action applied to the target state is also 5405 * applied to all the LUNs belonging to the target (provided the 5406 * LUN is not offline). A side effect of applying the state 5407 * modification to the target and the LUNs is the field tgt_trace 5408 * of the target and lun_trace of the LUNs is set to zero. 5409 * 5410 * 5411 * Argument: *ptgt Target structure. 5412 * flag Flag indication what action to apply (set/reset). 5413 * state State bits to update. 5414 * 5415 * Return Value: None 5416 * 5417 * Context: Interrupt, Kernel or User context. 5418 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5419 * calling this function. 5420 */ 5421 void 5422 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5423 { 5424 struct fcp_lun *plun; 5425 5426 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5427 5428 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5429 /* The target is not offline. */ 5430 if (flag == FCP_SET) { 5431 ptgt->tgt_state |= state; 5432 ptgt->tgt_trace = 0; 5433 } else { 5434 ptgt->tgt_state &= ~state; 5435 } 5436 5437 for (plun = ptgt->tgt_lun; plun != NULL; 5438 plun = plun->lun_next) { 5439 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5440 /* The LUN is not offline. */ 5441 if (flag == FCP_SET) { 5442 plun->lun_state |= state; 5443 plun->lun_trace = 0; 5444 } else { 5445 plun->lun_state &= ~state; 5446 } 5447 } 5448 } 5449 } 5450 } 5451 5452 /* 5453 * Function: fcp_update_tgt_state 5454 * 5455 * Description: This function updates the field lun_state of a LUN. That 5456 * field is a bitmap and which bit can be set or reset 5457 * individually. 5458 * 5459 * Argument: *plun LUN structure. 5460 * flag Flag indication what action to apply (set/reset). 5461 * state State bits to update. 5462 * 5463 * Return Value: None 5464 * 5465 * Context: Interrupt, Kernel or User context. 5466 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5467 * calling this function. 5468 */ 5469 void 5470 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5471 { 5472 struct fcp_tgt *ptgt = plun->lun_tgt; 5473 5474 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5475 5476 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5477 if (flag == FCP_SET) { 5478 plun->lun_state |= state; 5479 } else { 5480 plun->lun_state &= ~state; 5481 } 5482 } 5483 } 5484 5485 /* 5486 * Function: fcp_get_port 5487 * 5488 * Description: This function returns the fcp_port structure from the opaque 5489 * handle passed by the caller. That opaque handle is the handle 5490 * used by fp/fctl to identify a particular local port. That 5491 * handle has been stored in the corresponding fcp_port 5492 * structure. This function is going to walk the global list of 5493 * fcp_port structures till one has a port_fp_handle that matches 5494 * the handle passed by the caller. This function enters the 5495 * mutex fcp_global_mutex while walking the global list and then 5496 * releases it. 5497 * 5498 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5499 * particular port. 5500 * 5501 * Return Value: NULL Not found. 5502 * Not NULL Pointer to the fcp_port structure. 5503 * 5504 * Context: Interrupt, Kernel or User context. 5505 */ 5506 static struct fcp_port * 5507 fcp_get_port(opaque_t port_handle) 5508 { 5509 struct fcp_port *pptr; 5510 5511 ASSERT(port_handle != NULL); 5512 5513 mutex_enter(&fcp_global_mutex); 5514 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5515 if (pptr->port_fp_handle == port_handle) { 5516 break; 5517 } 5518 } 5519 mutex_exit(&fcp_global_mutex); 5520 5521 return (pptr); 5522 } 5523 5524 5525 static void 5526 fcp_unsol_callback(fc_packet_t *fpkt) 5527 { 5528 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5529 struct fcp_port *pptr = icmd->ipkt_port; 5530 5531 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5532 caddr_t state, reason, action, expln; 5533 5534 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5535 &action, &expln); 5536 5537 fcp_log(CE_WARN, pptr->port_dip, 5538 "!couldn't post response to unsolicited request: " 5539 " state=%s reason=%s rx_id=%x ox_id=%x", 5540 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5541 fpkt->pkt_cmd_fhdr.rx_id); 5542 } 5543 fcp_icmd_free(pptr, icmd); 5544 } 5545 5546 5547 /* 5548 * Perform general purpose preparation of a response to an unsolicited request 5549 */ 5550 static void 5551 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5552 uchar_t r_ctl, uchar_t type) 5553 { 5554 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5555 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5556 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5557 pkt->pkt_cmd_fhdr.type = type; 5558 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5559 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5560 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5561 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5562 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5563 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5564 pkt->pkt_cmd_fhdr.ro = 0; 5565 pkt->pkt_cmd_fhdr.rsvd = 0; 5566 pkt->pkt_comp = fcp_unsol_callback; 5567 pkt->pkt_pd = NULL; 5568 pkt->pkt_ub_resp_token = (opaque_t)buf; 5569 } 5570 5571 5572 /*ARGSUSED*/ 5573 static int 5574 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5575 { 5576 fc_packet_t *fpkt; 5577 struct la_els_prli prli; 5578 struct fcp_prli *fprli; 5579 struct fcp_ipkt *icmd; 5580 struct la_els_prli *from; 5581 struct fcp_prli *orig; 5582 struct fcp_tgt *ptgt; 5583 int tcount = 0; 5584 int lcount; 5585 5586 from = (struct la_els_prli *)buf->ub_buffer; 5587 orig = (struct fcp_prli *)from->service_params; 5588 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5589 NULL) { 5590 mutex_enter(&ptgt->tgt_mutex); 5591 tcount = ptgt->tgt_change_cnt; 5592 mutex_exit(&ptgt->tgt_mutex); 5593 } 5594 5595 mutex_enter(&pptr->port_mutex); 5596 lcount = pptr->port_link_cnt; 5597 mutex_exit(&pptr->port_mutex); 5598 5599 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5600 sizeof (la_els_prli_t), 0, 5601 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5602 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5603 return (FC_FAILURE); 5604 } 5605 5606 fpkt = icmd->ipkt_fpkt; 5607 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5608 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5609 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5610 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5611 fpkt->pkt_rsplen = 0; 5612 fpkt->pkt_datalen = 0; 5613 5614 icmd->ipkt_opcode = LA_ELS_PRLI; 5615 5616 bzero(&prli, sizeof (struct la_els_prli)); 5617 fprli = (struct fcp_prli *)prli.service_params; 5618 prli.ls_code = LA_ELS_ACC; 5619 prli.page_length = 0x10; 5620 prli.payload_length = sizeof (struct la_els_prli); 5621 5622 /* fill in service params */ 5623 fprli->type = 0x08; 5624 fprli->resvd1 = 0; 5625 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5626 fprli->orig_process_associator = orig->orig_process_associator; 5627 fprli->resp_process_assoc_valid = 0; 5628 fprli->establish_image_pair = 1; 5629 fprli->resvd2 = 0; 5630 fprli->resvd3 = 0; 5631 fprli->obsolete_1 = 0; 5632 fprli->obsolete_2 = 0; 5633 fprli->data_overlay_allowed = 0; 5634 fprli->initiator_fn = 1; 5635 fprli->confirmed_compl_allowed = 1; 5636 5637 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5638 fprli->target_fn = 1; 5639 } else { 5640 fprli->target_fn = 0; 5641 } 5642 5643 fprli->retry = 1; 5644 fprli->read_xfer_rdy_disabled = 1; 5645 fprli->write_xfer_rdy_disabled = 0; 5646 5647 /* save the unsol prli payload first */ 5648 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5649 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5650 5651 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5652 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5653 5654 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5655 5656 mutex_enter(&pptr->port_mutex); 5657 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5658 int rval; 5659 mutex_exit(&pptr->port_mutex); 5660 5661 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5662 FC_SUCCESS) { 5663 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5664 ptgt != NULL) { 5665 fcp_queue_ipkt(pptr, fpkt); 5666 return (FC_SUCCESS); 5667 } 5668 /* Let it timeout */ 5669 fcp_icmd_free(pptr, icmd); 5670 return (FC_FAILURE); 5671 } 5672 } else { 5673 mutex_exit(&pptr->port_mutex); 5674 fcp_icmd_free(pptr, icmd); 5675 return (FC_FAILURE); 5676 } 5677 5678 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5679 5680 return (FC_SUCCESS); 5681 } 5682 5683 /* 5684 * Function: fcp_icmd_alloc 5685 * 5686 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5687 * field is initialized to fcp_icmd_callback. Sometimes it is 5688 * modified by the caller (such as fcp_send_scsi). The 5689 * structure is also tied to the state of the line and of the 5690 * target at a particular time. That link is established by 5691 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5692 * and tcount which came respectively from pptr->link_cnt and 5693 * ptgt->tgt_change_cnt. 5694 * 5695 * Argument: *pptr Fcp port. 5696 * *ptgt Target (destination of the command). 5697 * cmd_len Length of the command. 5698 * resp_len Length of the expected response. 5699 * data_len Length of the data. 5700 * nodma Indicates weither the command and response. 5701 * will be transfer through DMA or not. 5702 * lcount Link state change counter. 5703 * tcount Target state change counter. 5704 * cause Reason that lead to this call. 5705 * 5706 * Return Value: NULL Failed. 5707 * Not NULL Internal packet address. 5708 */ 5709 static struct fcp_ipkt * 5710 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5711 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5712 uint32_t rscn_count) 5713 { 5714 int dma_setup = 0; 5715 fc_packet_t *fpkt; 5716 struct fcp_ipkt *icmd = NULL; 5717 5718 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5719 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5720 KM_NOSLEEP); 5721 if (icmd == NULL) { 5722 fcp_log(CE_WARN, pptr->port_dip, 5723 "!internal packet allocation failed"); 5724 return (NULL); 5725 } 5726 5727 /* 5728 * initialize the allocated packet 5729 */ 5730 icmd->ipkt_nodma = nodma; 5731 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5732 icmd->ipkt_lun = NULL; 5733 5734 icmd->ipkt_link_cnt = lcount; 5735 icmd->ipkt_change_cnt = tcount; 5736 icmd->ipkt_cause = cause; 5737 5738 mutex_enter(&pptr->port_mutex); 5739 icmd->ipkt_port = pptr; 5740 mutex_exit(&pptr->port_mutex); 5741 5742 /* keep track of amt of data to be sent in pkt */ 5743 icmd->ipkt_cmdlen = cmd_len; 5744 icmd->ipkt_resplen = resp_len; 5745 icmd->ipkt_datalen = data_len; 5746 5747 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5748 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5749 5750 /* set pkt's private ptr to point to cmd pkt */ 5751 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5752 5753 /* set FCA private ptr to memory just beyond */ 5754 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5755 ((char *)icmd + sizeof (struct fcp_ipkt) + 5756 pptr->port_dmacookie_sz); 5757 5758 /* get ptr to fpkt substruct and fill it in */ 5759 fpkt = icmd->ipkt_fpkt; 5760 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5761 sizeof (struct fcp_ipkt)); 5762 5763 if (ptgt != NULL) { 5764 icmd->ipkt_tgt = ptgt; 5765 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5766 } 5767 5768 fpkt->pkt_comp = fcp_icmd_callback; 5769 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5770 fpkt->pkt_cmdlen = cmd_len; 5771 fpkt->pkt_rsplen = resp_len; 5772 fpkt->pkt_datalen = data_len; 5773 5774 /* 5775 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5776 * rscn_count as fcp knows down to the transport. If a valid count was 5777 * passed into this function, we allocate memory to actually pass down 5778 * this info. 5779 * 5780 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5781 * basically mean that fcp will not be able to help transport 5782 * distinguish if a new RSCN has come after fcp was last informed about 5783 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5784 * 5068068 where the device might end up going offline in case of RSCN 5785 * storms. 5786 */ 5787 fpkt->pkt_ulp_rscn_infop = NULL; 5788 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5789 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5790 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5791 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5792 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5793 fcp_trace, FCP_BUF_LEVEL_6, 0, 5794 "Failed to alloc memory to pass rscn info"); 5795 } 5796 } 5797 5798 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5799 fc_ulp_rscn_info_t *rscnp; 5800 5801 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5802 rscnp->ulp_rscn_count = rscn_count; 5803 } 5804 5805 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5806 goto fail; 5807 } 5808 dma_setup++; 5809 5810 /* 5811 * Must hold target mutex across setting of pkt_pd and call to 5812 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5813 * away while we're not looking. 5814 */ 5815 if (ptgt != NULL) { 5816 mutex_enter(&ptgt->tgt_mutex); 5817 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5818 5819 /* ask transport to do its initialization on this pkt */ 5820 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5821 != FC_SUCCESS) { 5822 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5823 fcp_trace, FCP_BUF_LEVEL_6, 0, 5824 "fc_ulp_init_packet failed"); 5825 mutex_exit(&ptgt->tgt_mutex); 5826 goto fail; 5827 } 5828 mutex_exit(&ptgt->tgt_mutex); 5829 } else { 5830 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5831 != FC_SUCCESS) { 5832 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5833 fcp_trace, FCP_BUF_LEVEL_6, 0, 5834 "fc_ulp_init_packet failed"); 5835 goto fail; 5836 } 5837 } 5838 5839 mutex_enter(&pptr->port_mutex); 5840 if (pptr->port_state & (FCP_STATE_DETACHING | 5841 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5842 int rval; 5843 5844 mutex_exit(&pptr->port_mutex); 5845 5846 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5847 ASSERT(rval == FC_SUCCESS); 5848 5849 goto fail; 5850 } 5851 5852 if (ptgt != NULL) { 5853 mutex_enter(&ptgt->tgt_mutex); 5854 ptgt->tgt_ipkt_cnt++; 5855 mutex_exit(&ptgt->tgt_mutex); 5856 } 5857 5858 pptr->port_ipkt_cnt++; 5859 5860 mutex_exit(&pptr->port_mutex); 5861 5862 return (icmd); 5863 5864 fail: 5865 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5866 kmem_free(fpkt->pkt_ulp_rscn_infop, 5867 sizeof (fc_ulp_rscn_info_t)); 5868 fpkt->pkt_ulp_rscn_infop = NULL; 5869 } 5870 5871 if (dma_setup) { 5872 fcp_free_dma(pptr, icmd); 5873 } 5874 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5875 (size_t)pptr->port_dmacookie_sz); 5876 5877 return (NULL); 5878 } 5879 5880 /* 5881 * Function: fcp_icmd_free 5882 * 5883 * Description: Frees the internal command passed by the caller. 5884 * 5885 * Argument: *pptr Fcp port. 5886 * *icmd Internal packet to free. 5887 * 5888 * Return Value: None 5889 */ 5890 static void 5891 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5892 { 5893 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5894 5895 /* Let the underlying layers do their cleanup. */ 5896 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5897 icmd->ipkt_fpkt); 5898 5899 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5900 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5901 sizeof (fc_ulp_rscn_info_t)); 5902 } 5903 5904 fcp_free_dma(pptr, icmd); 5905 5906 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5907 (size_t)pptr->port_dmacookie_sz); 5908 5909 mutex_enter(&pptr->port_mutex); 5910 5911 if (ptgt) { 5912 mutex_enter(&ptgt->tgt_mutex); 5913 ptgt->tgt_ipkt_cnt--; 5914 mutex_exit(&ptgt->tgt_mutex); 5915 } 5916 5917 pptr->port_ipkt_cnt--; 5918 mutex_exit(&pptr->port_mutex); 5919 } 5920 5921 /* 5922 * Function: fcp_alloc_dma 5923 * 5924 * Description: Allocated the DMA resources required for the internal 5925 * packet. 5926 * 5927 * Argument: *pptr FCP port. 5928 * *icmd Internal FCP packet. 5929 * nodma Indicates if the Cmd and Resp will be DMAed. 5930 * flags Allocation flags (Sleep or NoSleep). 5931 * 5932 * Return Value: FC_SUCCESS 5933 * FC_NOMEM 5934 */ 5935 static int 5936 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5937 int nodma, int flags) 5938 { 5939 int rval; 5940 size_t real_size; 5941 uint_t ccount; 5942 int bound = 0; 5943 int cmd_resp = 0; 5944 fc_packet_t *fpkt; 5945 ddi_dma_cookie_t pkt_data_cookie; 5946 ddi_dma_cookie_t *cp; 5947 uint32_t cnt; 5948 5949 fpkt = &icmd->ipkt_fc_packet; 5950 5951 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5952 fpkt->pkt_resp_dma == NULL); 5953 5954 icmd->ipkt_nodma = nodma; 5955 5956 if (nodma) { 5957 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5958 if (fpkt->pkt_cmd == NULL) { 5959 goto fail; 5960 } 5961 5962 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5963 if (fpkt->pkt_resp == NULL) { 5964 goto fail; 5965 } 5966 } else { 5967 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5968 5969 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5970 if (rval == FC_FAILURE) { 5971 ASSERT(fpkt->pkt_cmd_dma == NULL && 5972 fpkt->pkt_resp_dma == NULL); 5973 goto fail; 5974 } 5975 cmd_resp++; 5976 } 5977 5978 if ((fpkt->pkt_datalen != 0) && 5979 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 5980 /* 5981 * set up DMA handle and memory for the data in this packet 5982 */ 5983 if (ddi_dma_alloc_handle(pptr->port_dip, 5984 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 5985 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 5986 goto fail; 5987 } 5988 5989 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 5990 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 5991 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 5992 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 5993 goto fail; 5994 } 5995 5996 /* was DMA mem size gotten < size asked for/needed ?? */ 5997 if (real_size < fpkt->pkt_datalen) { 5998 goto fail; 5999 } 6000 6001 /* bind DMA address and handle together */ 6002 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6003 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6004 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6005 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6006 goto fail; 6007 } 6008 bound++; 6009 6010 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6011 goto fail; 6012 } 6013 6014 fpkt->pkt_data_cookie_cnt = ccount; 6015 6016 cp = fpkt->pkt_data_cookie; 6017 *cp = pkt_data_cookie; 6018 cp++; 6019 6020 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6021 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6022 &pkt_data_cookie); 6023 *cp = pkt_data_cookie; 6024 } 6025 6026 } else if (fpkt->pkt_datalen != 0) { 6027 /* 6028 * If it's a pseudo FCA, then it can't support DMA even in 6029 * SCSI data phase. 6030 */ 6031 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6032 if (fpkt->pkt_data == NULL) { 6033 goto fail; 6034 } 6035 6036 } 6037 6038 return (FC_SUCCESS); 6039 6040 fail: 6041 if (bound) { 6042 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6043 } 6044 6045 if (fpkt->pkt_data_dma) { 6046 if (fpkt->pkt_data) { 6047 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6048 } 6049 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6050 } else { 6051 if (fpkt->pkt_data) { 6052 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6053 } 6054 } 6055 6056 if (nodma) { 6057 if (fpkt->pkt_cmd) { 6058 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6059 } 6060 if (fpkt->pkt_resp) { 6061 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6062 } 6063 } else { 6064 if (cmd_resp) { 6065 fcp_free_cmd_resp(pptr, fpkt); 6066 } 6067 } 6068 6069 return (FC_NOMEM); 6070 } 6071 6072 6073 static void 6074 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6075 { 6076 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6077 6078 if (fpkt->pkt_data_dma) { 6079 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6080 if (fpkt->pkt_data) { 6081 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6082 } 6083 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6084 } else { 6085 if (fpkt->pkt_data) { 6086 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6087 } 6088 /* 6089 * Need we reset pkt_* to zero??? 6090 */ 6091 } 6092 6093 if (icmd->ipkt_nodma) { 6094 if (fpkt->pkt_cmd) { 6095 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6096 } 6097 if (fpkt->pkt_resp) { 6098 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6099 } 6100 } else { 6101 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6102 6103 fcp_free_cmd_resp(pptr, fpkt); 6104 } 6105 } 6106 6107 /* 6108 * Function: fcp_lookup_target 6109 * 6110 * Description: Finds a target given a WWN. 6111 * 6112 * Argument: *pptr FCP port. 6113 * *wwn World Wide Name of the device to look for. 6114 * 6115 * Return Value: NULL No target found 6116 * Not NULL Target structure 6117 * 6118 * Context: Interrupt context. 6119 * The mutex pptr->port_mutex must be owned. 6120 */ 6121 /* ARGSUSED */ 6122 static struct fcp_tgt * 6123 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6124 { 6125 int hash; 6126 struct fcp_tgt *ptgt; 6127 6128 ASSERT(mutex_owned(&pptr->port_mutex)); 6129 6130 hash = FCP_HASH(wwn); 6131 6132 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6133 ptgt = ptgt->tgt_next) { 6134 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6135 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6136 sizeof (ptgt->tgt_port_wwn)) == 0) { 6137 break; 6138 } 6139 } 6140 6141 return (ptgt); 6142 } 6143 6144 6145 /* 6146 * Find target structure given a port identifier 6147 */ 6148 static struct fcp_tgt * 6149 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6150 { 6151 fc_portid_t port_id; 6152 la_wwn_t pwwn; 6153 struct fcp_tgt *ptgt = NULL; 6154 6155 port_id.priv_lilp_posit = 0; 6156 port_id.port_id = d_id; 6157 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6158 &pwwn) == FC_SUCCESS) { 6159 mutex_enter(&pptr->port_mutex); 6160 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6161 mutex_exit(&pptr->port_mutex); 6162 } 6163 6164 return (ptgt); 6165 } 6166 6167 6168 /* 6169 * the packet completion callback routine for info cmd pkts 6170 * 6171 * this means fpkt pts to a response to either a PLOGI or a PRLI 6172 * 6173 * if there is an error an attempt is made to call a routine to resend 6174 * the command that failed 6175 */ 6176 static void 6177 fcp_icmd_callback(fc_packet_t *fpkt) 6178 { 6179 struct fcp_ipkt *icmd; 6180 struct fcp_port *pptr; 6181 struct fcp_tgt *ptgt; 6182 struct la_els_prli *prli; 6183 struct la_els_prli prli_s; 6184 struct fcp_prli *fprli; 6185 struct fcp_lun *plun; 6186 int free_pkt = 1; 6187 int rval; 6188 ls_code_t resp; 6189 uchar_t prli_acc = 0; 6190 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6191 int lun0_newalloc; 6192 6193 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6194 6195 /* get ptrs to the port and target structs for the cmd */ 6196 pptr = icmd->ipkt_port; 6197 ptgt = icmd->ipkt_tgt; 6198 6199 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6200 6201 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6202 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6203 sizeof (prli_s)); 6204 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6205 } 6206 6207 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6208 fcp_trace, FCP_BUF_LEVEL_2, 0, 6209 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6210 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6211 ptgt->tgt_d_id); 6212 6213 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6214 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6215 6216 mutex_enter(&ptgt->tgt_mutex); 6217 if (ptgt->tgt_pd_handle == NULL) { 6218 /* 6219 * in a fabric environment the port device handles 6220 * get created only after successful LOGIN into the 6221 * transport, so the transport makes this port 6222 * device (pd) handle available in this packet, so 6223 * save it now 6224 */ 6225 ASSERT(fpkt->pkt_pd != NULL); 6226 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6227 } 6228 mutex_exit(&ptgt->tgt_mutex); 6229 6230 /* which ELS cmd is this response for ?? */ 6231 switch (icmd->ipkt_opcode) { 6232 case LA_ELS_PLOGI: 6233 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6234 fcp_trace, FCP_BUF_LEVEL_5, 0, 6235 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6236 ptgt->tgt_d_id, 6237 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6238 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6239 6240 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6241 FCP_TGT_TRACE_15); 6242 6243 /* Note that we are not allocating a new icmd */ 6244 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6245 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6246 icmd->ipkt_cause) != DDI_SUCCESS) { 6247 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6248 FCP_TGT_TRACE_16); 6249 goto fail; 6250 } 6251 break; 6252 6253 case LA_ELS_PRLI: 6254 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6255 fcp_trace, FCP_BUF_LEVEL_5, 0, 6256 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6257 6258 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6259 FCP_TGT_TRACE_17); 6260 6261 prli = &prli_s; 6262 6263 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6264 sizeof (prli_s)); 6265 6266 fprli = (struct fcp_prli *)prli->service_params; 6267 6268 mutex_enter(&ptgt->tgt_mutex); 6269 ptgt->tgt_icap = fprli->initiator_fn; 6270 ptgt->tgt_tcap = fprli->target_fn; 6271 mutex_exit(&ptgt->tgt_mutex); 6272 6273 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6274 /* 6275 * this FCP device does not support target mode 6276 */ 6277 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6278 FCP_TGT_TRACE_18); 6279 goto fail; 6280 } 6281 if (fprli->retry == 1) { 6282 fc_ulp_disable_relogin(pptr->port_fp_handle, 6283 &ptgt->tgt_port_wwn); 6284 } 6285 6286 /* target is no longer offline */ 6287 mutex_enter(&pptr->port_mutex); 6288 mutex_enter(&ptgt->tgt_mutex); 6289 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6290 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6291 FCP_TGT_MARK); 6292 } else { 6293 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6294 fcp_trace, FCP_BUF_LEVEL_2, 0, 6295 "fcp_icmd_callback,1: state change " 6296 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6297 mutex_exit(&ptgt->tgt_mutex); 6298 mutex_exit(&pptr->port_mutex); 6299 goto fail; 6300 } 6301 mutex_exit(&ptgt->tgt_mutex); 6302 mutex_exit(&pptr->port_mutex); 6303 6304 /* 6305 * lun 0 should always respond to inquiry, so 6306 * get the LUN struct for LUN 0 6307 * 6308 * Currently we deal with first level of addressing. 6309 * If / when we start supporting 0x device types 6310 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6311 * this logic will need revisiting. 6312 */ 6313 lun0_newalloc = 0; 6314 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6315 /* 6316 * no LUN struct for LUN 0 yet exists, 6317 * so create one 6318 */ 6319 plun = fcp_alloc_lun(ptgt); 6320 if (plun == NULL) { 6321 fcp_log(CE_WARN, pptr->port_dip, 6322 "!Failed to allocate lun 0 for" 6323 " D_ID=%x", ptgt->tgt_d_id); 6324 goto fail; 6325 } 6326 lun0_newalloc = 1; 6327 } 6328 6329 /* fill in LUN info */ 6330 mutex_enter(&ptgt->tgt_mutex); 6331 /* 6332 * consider lun 0 as device not connected if it is 6333 * offlined or newly allocated 6334 */ 6335 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6336 lun0_newalloc) { 6337 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6338 } 6339 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6340 plun->lun_state &= ~FCP_LUN_OFFLINE; 6341 ptgt->tgt_lun_cnt = 1; 6342 ptgt->tgt_report_lun_cnt = 0; 6343 mutex_exit(&ptgt->tgt_mutex); 6344 6345 /* Retrieve the rscn count (if a valid one exists) */ 6346 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6347 rscn_count = ((fc_ulp_rscn_info_t *) 6348 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6349 ->ulp_rscn_count; 6350 } else { 6351 rscn_count = FC_INVALID_RSCN_COUNT; 6352 } 6353 6354 /* send Report Lun request to target */ 6355 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6356 sizeof (struct fcp_reportlun_resp), 6357 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6358 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6359 mutex_enter(&pptr->port_mutex); 6360 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6361 fcp_log(CE_WARN, pptr->port_dip, 6362 "!Failed to send REPORT LUN to" 6363 " D_ID=%x", ptgt->tgt_d_id); 6364 } else { 6365 FCP_TRACE(fcp_logq, 6366 pptr->port_instbuf, fcp_trace, 6367 FCP_BUF_LEVEL_5, 0, 6368 "fcp_icmd_callback,2:state change" 6369 " occured for D_ID=0x%x", 6370 ptgt->tgt_d_id); 6371 } 6372 mutex_exit(&pptr->port_mutex); 6373 6374 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6375 FCP_TGT_TRACE_19); 6376 6377 goto fail; 6378 } else { 6379 free_pkt = 0; 6380 fcp_icmd_free(pptr, icmd); 6381 } 6382 break; 6383 6384 default: 6385 fcp_log(CE_WARN, pptr->port_dip, 6386 "!fcp_icmd_callback Invalid opcode"); 6387 goto fail; 6388 } 6389 6390 return; 6391 } 6392 6393 6394 /* 6395 * Other PLOGI failures are not retried as the 6396 * transport does it already 6397 */ 6398 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6399 if (fcp_is_retryable(icmd) && 6400 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6401 6402 if (FCP_MUST_RETRY(fpkt)) { 6403 fcp_queue_ipkt(pptr, fpkt); 6404 return; 6405 } 6406 6407 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6408 fcp_trace, FCP_BUF_LEVEL_2, 0, 6409 "ELS PRLI is retried for d_id=0x%x, state=%x," 6410 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6411 fpkt->pkt_reason); 6412 6413 /* 6414 * Retry by recalling the routine that 6415 * originally queued this packet 6416 */ 6417 mutex_enter(&pptr->port_mutex); 6418 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6419 caddr_t msg; 6420 6421 mutex_exit(&pptr->port_mutex); 6422 6423 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6424 6425 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6426 fpkt->pkt_timeout += 6427 FCP_TIMEOUT_DELTA; 6428 } 6429 6430 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6431 fpkt); 6432 if (rval == FC_SUCCESS) { 6433 return; 6434 } 6435 6436 if (rval == FC_STATEC_BUSY || 6437 rval == FC_OFFLINE) { 6438 fcp_queue_ipkt(pptr, fpkt); 6439 return; 6440 } 6441 (void) fc_ulp_error(rval, &msg); 6442 6443 fcp_log(CE_NOTE, pptr->port_dip, 6444 "!ELS 0x%x failed to d_id=0x%x;" 6445 " %s", icmd->ipkt_opcode, 6446 ptgt->tgt_d_id, msg); 6447 } else { 6448 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6449 fcp_trace, FCP_BUF_LEVEL_2, 0, 6450 "fcp_icmd_callback,3: state change " 6451 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6452 mutex_exit(&pptr->port_mutex); 6453 } 6454 } 6455 } else { 6456 if (fcp_is_retryable(icmd) && 6457 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6458 if (FCP_MUST_RETRY(fpkt)) { 6459 fcp_queue_ipkt(pptr, fpkt); 6460 return; 6461 } 6462 } 6463 mutex_enter(&pptr->port_mutex); 6464 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6465 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6466 mutex_exit(&pptr->port_mutex); 6467 fcp_print_error(fpkt); 6468 } else { 6469 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6470 fcp_trace, FCP_BUF_LEVEL_2, 0, 6471 "fcp_icmd_callback,4: state change occured" 6472 " for D_ID=0x%x", ptgt->tgt_d_id); 6473 mutex_exit(&pptr->port_mutex); 6474 } 6475 } 6476 6477 fail: 6478 if (free_pkt) { 6479 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6480 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6481 fcp_icmd_free(pptr, icmd); 6482 } 6483 } 6484 6485 6486 /* 6487 * called internally to send an info cmd using the transport 6488 * 6489 * sends either an INQ or a REPORT_LUN 6490 * 6491 * when the packet is completed fcp_scsi_callback is called 6492 */ 6493 static int 6494 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6495 int lcount, int tcount, int cause, uint32_t rscn_count) 6496 { 6497 int nodma; 6498 struct fcp_ipkt *icmd; 6499 struct fcp_tgt *ptgt; 6500 struct fcp_port *pptr; 6501 fc_frame_hdr_t *hp; 6502 fc_packet_t *fpkt; 6503 struct fcp_cmd fcp_cmd; 6504 struct fcp_cmd *fcmd; 6505 union scsi_cdb *scsi_cdb; 6506 6507 ASSERT(plun != NULL); 6508 6509 ptgt = plun->lun_tgt; 6510 ASSERT(ptgt != NULL); 6511 6512 pptr = ptgt->tgt_port; 6513 ASSERT(pptr != NULL); 6514 6515 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6516 fcp_trace, FCP_BUF_LEVEL_5, 0, 6517 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6518 6519 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6520 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6521 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6522 rscn_count); 6523 6524 if (icmd == NULL) { 6525 return (DDI_FAILURE); 6526 } 6527 6528 fpkt = icmd->ipkt_fpkt; 6529 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6530 icmd->ipkt_retries = 0; 6531 icmd->ipkt_opcode = opcode; 6532 icmd->ipkt_lun = plun; 6533 6534 if (nodma) { 6535 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6536 } else { 6537 fcmd = &fcp_cmd; 6538 } 6539 bzero(fcmd, sizeof (struct fcp_cmd)); 6540 6541 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6542 6543 hp = &fpkt->pkt_cmd_fhdr; 6544 6545 hp->s_id = pptr->port_id; 6546 hp->d_id = ptgt->tgt_d_id; 6547 hp->r_ctl = R_CTL_COMMAND; 6548 hp->type = FC_TYPE_SCSI_FCP; 6549 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6550 hp->rsvd = 0; 6551 hp->seq_id = 0; 6552 hp->seq_cnt = 0; 6553 hp->ox_id = 0xffff; 6554 hp->rx_id = 0xffff; 6555 hp->ro = 0; 6556 6557 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6558 6559 /* 6560 * Request SCSI target for expedited processing 6561 */ 6562 6563 /* 6564 * Set up for untagged queuing because we do not 6565 * know if the fibre device supports queuing. 6566 */ 6567 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6568 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6569 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6570 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6571 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6572 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6573 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6574 6575 switch (opcode) { 6576 case SCMD_INQUIRY_PAGE83: 6577 /* 6578 * Prepare to get the Inquiry VPD page 83 information 6579 */ 6580 fcmd->fcp_cntl.cntl_read_data = 1; 6581 fcmd->fcp_cntl.cntl_write_data = 0; 6582 fcmd->fcp_data_len = alloc_len; 6583 6584 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6585 fpkt->pkt_comp = fcp_scsi_callback; 6586 6587 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6588 scsi_cdb->g0_addr2 = 0x01; 6589 scsi_cdb->g0_addr1 = 0x83; 6590 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6591 break; 6592 6593 case SCMD_INQUIRY: 6594 fcmd->fcp_cntl.cntl_read_data = 1; 6595 fcmd->fcp_cntl.cntl_write_data = 0; 6596 fcmd->fcp_data_len = alloc_len; 6597 6598 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6599 fpkt->pkt_comp = fcp_scsi_callback; 6600 6601 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6602 scsi_cdb->g0_count0 = SUN_INQSIZE; 6603 break; 6604 6605 case SCMD_REPORT_LUN: { 6606 fc_portid_t d_id; 6607 opaque_t fca_dev; 6608 6609 ASSERT(alloc_len >= 16); 6610 6611 d_id.priv_lilp_posit = 0; 6612 d_id.port_id = ptgt->tgt_d_id; 6613 6614 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6615 6616 mutex_enter(&ptgt->tgt_mutex); 6617 ptgt->tgt_fca_dev = fca_dev; 6618 mutex_exit(&ptgt->tgt_mutex); 6619 6620 fcmd->fcp_cntl.cntl_read_data = 1; 6621 fcmd->fcp_cntl.cntl_write_data = 0; 6622 fcmd->fcp_data_len = alloc_len; 6623 6624 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6625 fpkt->pkt_comp = fcp_scsi_callback; 6626 6627 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6628 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6629 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6630 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6631 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6632 break; 6633 } 6634 6635 default: 6636 fcp_log(CE_WARN, pptr->port_dip, 6637 "!fcp_send_scsi Invalid opcode"); 6638 break; 6639 } 6640 6641 if (!nodma) { 6642 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6643 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6644 } 6645 6646 mutex_enter(&pptr->port_mutex); 6647 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6648 6649 mutex_exit(&pptr->port_mutex); 6650 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6651 FC_SUCCESS) { 6652 fcp_icmd_free(pptr, icmd); 6653 return (DDI_FAILURE); 6654 } 6655 return (DDI_SUCCESS); 6656 } else { 6657 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6658 fcp_trace, FCP_BUF_LEVEL_2, 0, 6659 "fcp_send_scsi,1: state change occured" 6660 " for D_ID=0x%x", ptgt->tgt_d_id); 6661 mutex_exit(&pptr->port_mutex); 6662 fcp_icmd_free(pptr, icmd); 6663 return (DDI_FAILURE); 6664 } 6665 } 6666 6667 6668 /* 6669 * called by fcp_scsi_callback to check to handle the case where 6670 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6671 */ 6672 static int 6673 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6674 { 6675 uchar_t rqlen; 6676 int rval = DDI_FAILURE; 6677 struct scsi_extended_sense sense_info, *sense; 6678 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6679 fpkt->pkt_ulp_private; 6680 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6681 struct fcp_port *pptr = ptgt->tgt_port; 6682 6683 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6684 6685 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6686 /* 6687 * SCSI-II Reserve Release support. Some older FC drives return 6688 * Reservation conflict for Report Luns command. 6689 */ 6690 if (icmd->ipkt_nodma) { 6691 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6692 rsp->fcp_u.fcp_status.sense_len_set = 0; 6693 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6694 } else { 6695 fcp_rsp_t new_resp; 6696 6697 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6698 fpkt->pkt_resp_acc, sizeof (new_resp)); 6699 6700 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6701 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6702 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6703 6704 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6705 fpkt->pkt_resp_acc, sizeof (new_resp)); 6706 } 6707 6708 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6709 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6710 6711 return (DDI_SUCCESS); 6712 } 6713 6714 sense = &sense_info; 6715 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6716 /* no need to continue if sense length is not set */ 6717 return (rval); 6718 } 6719 6720 /* casting 64-bit integer to 8-bit */ 6721 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6722 sizeof (struct scsi_extended_sense)); 6723 6724 if (rqlen < 14) { 6725 /* no need to continue if request length isn't long enough */ 6726 return (rval); 6727 } 6728 6729 if (icmd->ipkt_nodma) { 6730 /* 6731 * We can safely use fcp_response_len here since the 6732 * only path that calls fcp_check_reportlun, 6733 * fcp_scsi_callback, has already called 6734 * fcp_validate_fcp_response. 6735 */ 6736 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6737 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6738 } else { 6739 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6740 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6741 sizeof (struct scsi_extended_sense)); 6742 } 6743 6744 if (!FCP_SENSE_NO_LUN(sense)) { 6745 mutex_enter(&ptgt->tgt_mutex); 6746 /* clear the flag if any */ 6747 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6748 mutex_exit(&ptgt->tgt_mutex); 6749 } 6750 6751 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6752 (sense->es_add_code == 0x20)) { 6753 if (icmd->ipkt_nodma) { 6754 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6755 rsp->fcp_u.fcp_status.sense_len_set = 0; 6756 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6757 } else { 6758 fcp_rsp_t new_resp; 6759 6760 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6761 fpkt->pkt_resp_acc, sizeof (new_resp)); 6762 6763 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6764 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6765 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6766 6767 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6768 fpkt->pkt_resp_acc, sizeof (new_resp)); 6769 } 6770 6771 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6772 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6773 6774 return (DDI_SUCCESS); 6775 } 6776 6777 /* 6778 * This is for the STK library which returns a check condition, 6779 * to indicate device is not ready, manual assistance needed. 6780 * This is to a report lun command when the door is open. 6781 */ 6782 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6783 if (icmd->ipkt_nodma) { 6784 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6785 rsp->fcp_u.fcp_status.sense_len_set = 0; 6786 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6787 } else { 6788 fcp_rsp_t new_resp; 6789 6790 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6791 fpkt->pkt_resp_acc, sizeof (new_resp)); 6792 6793 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6794 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6795 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6796 6797 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6798 fpkt->pkt_resp_acc, sizeof (new_resp)); 6799 } 6800 6801 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6802 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6803 6804 return (DDI_SUCCESS); 6805 } 6806 6807 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6808 (FCP_SENSE_NO_LUN(sense))) { 6809 mutex_enter(&ptgt->tgt_mutex); 6810 if ((FCP_SENSE_NO_LUN(sense)) && 6811 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6812 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6813 mutex_exit(&ptgt->tgt_mutex); 6814 /* 6815 * reconfig was triggred by ILLEGAL REQUEST but 6816 * got ILLEGAL REQUEST again 6817 */ 6818 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6819 fcp_trace, FCP_BUF_LEVEL_3, 0, 6820 "!FCP: Unable to obtain Report Lun data" 6821 " target=%x", ptgt->tgt_d_id); 6822 } else { 6823 if (ptgt->tgt_tid == NULL) { 6824 timeout_id_t tid; 6825 /* 6826 * REPORT LUN data has changed. Kick off 6827 * rediscovery 6828 */ 6829 tid = timeout(fcp_reconfigure_luns, 6830 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6831 6832 ptgt->tgt_tid = tid; 6833 ptgt->tgt_state |= FCP_TGT_BUSY; 6834 } 6835 if (FCP_SENSE_NO_LUN(sense)) { 6836 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6837 } 6838 mutex_exit(&ptgt->tgt_mutex); 6839 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6840 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6841 fcp_trace, FCP_BUF_LEVEL_3, 0, 6842 "!FCP:Report Lun Has Changed" 6843 " target=%x", ptgt->tgt_d_id); 6844 } else if (FCP_SENSE_NO_LUN(sense)) { 6845 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6846 fcp_trace, FCP_BUF_LEVEL_3, 0, 6847 "!FCP:LU Not Supported" 6848 " target=%x", ptgt->tgt_d_id); 6849 } 6850 } 6851 rval = DDI_SUCCESS; 6852 } 6853 6854 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6855 fcp_trace, FCP_BUF_LEVEL_5, 0, 6856 "D_ID=%x, sense=%x, status=%x", 6857 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6858 rsp->fcp_u.fcp_status.scsi_status); 6859 6860 return (rval); 6861 } 6862 6863 /* 6864 * Function: fcp_scsi_callback 6865 * 6866 * Description: This is the callback routine set by fcp_send_scsi() after 6867 * it calls fcp_icmd_alloc(). The SCSI command completed here 6868 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6869 * INQUIRY_PAGE83. 6870 * 6871 * Argument: *fpkt FC packet used to convey the command 6872 * 6873 * Return Value: None 6874 */ 6875 static void 6876 fcp_scsi_callback(fc_packet_t *fpkt) 6877 { 6878 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6879 fpkt->pkt_ulp_private; 6880 struct fcp_rsp_info fcp_rsp_err, *bep; 6881 struct fcp_port *pptr; 6882 struct fcp_tgt *ptgt; 6883 struct fcp_lun *plun; 6884 struct fcp_rsp response, *rsp; 6885 6886 ptgt = icmd->ipkt_tgt; 6887 pptr = ptgt->tgt_port; 6888 plun = icmd->ipkt_lun; 6889 6890 if (icmd->ipkt_nodma) { 6891 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6892 } else { 6893 rsp = &response; 6894 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6895 sizeof (struct fcp_rsp)); 6896 } 6897 6898 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6899 fcp_trace, FCP_BUF_LEVEL_2, 0, 6900 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6901 "status=%x, lun num=%x", 6902 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6903 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6904 6905 /* 6906 * Pre-init LUN GUID with NWWN if it is not a device that 6907 * supports multiple luns and we know it's not page83 6908 * compliant. Although using a NWWN is not lun unique, 6909 * we will be fine since there is only one lun behind the taget 6910 * in this case. 6911 */ 6912 if ((plun->lun_guid_size == 0) && 6913 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6914 (fcp_symmetric_device_probe(plun) == 0)) { 6915 6916 char ascii_wwn[FC_WWN_SIZE*2+1]; 6917 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6918 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6919 } 6920 6921 /* 6922 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6923 * when thay have more data than what is asked in CDB. An overrun 6924 * is really when FCP_DL is smaller than the data length in CDB. 6925 * In the case here we know that REPORT LUN command we formed within 6926 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6927 * behavior. In reality this is FC_SUCCESS. 6928 */ 6929 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6930 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6931 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6932 fpkt->pkt_state = FC_PKT_SUCCESS; 6933 } 6934 6935 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6936 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6937 fcp_trace, FCP_BUF_LEVEL_2, 0, 6938 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6939 ptgt->tgt_d_id); 6940 6941 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6942 /* 6943 * Inquiry VPD page command on A5K SES devices would 6944 * result in data CRC errors. 6945 */ 6946 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6947 (void) fcp_handle_page83(fpkt, icmd, 1); 6948 return; 6949 } 6950 } 6951 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6952 FCP_MUST_RETRY(fpkt)) { 6953 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6954 fcp_retry_scsi_cmd(fpkt); 6955 return; 6956 } 6957 6958 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6959 FCP_TGT_TRACE_20); 6960 6961 mutex_enter(&pptr->port_mutex); 6962 mutex_enter(&ptgt->tgt_mutex); 6963 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6964 mutex_exit(&ptgt->tgt_mutex); 6965 mutex_exit(&pptr->port_mutex); 6966 fcp_print_error(fpkt); 6967 } else { 6968 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6969 fcp_trace, FCP_BUF_LEVEL_2, 0, 6970 "fcp_scsi_callback,1: state change occured" 6971 " for D_ID=0x%x", ptgt->tgt_d_id); 6972 mutex_exit(&ptgt->tgt_mutex); 6973 mutex_exit(&pptr->port_mutex); 6974 } 6975 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6976 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6977 fcp_icmd_free(pptr, icmd); 6978 return; 6979 } 6980 6981 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 6982 6983 mutex_enter(&pptr->port_mutex); 6984 mutex_enter(&ptgt->tgt_mutex); 6985 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6986 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6987 fcp_trace, FCP_BUF_LEVEL_2, 0, 6988 "fcp_scsi_callback,2: state change occured" 6989 " for D_ID=0x%x", ptgt->tgt_d_id); 6990 mutex_exit(&ptgt->tgt_mutex); 6991 mutex_exit(&pptr->port_mutex); 6992 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6993 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6994 fcp_icmd_free(pptr, icmd); 6995 return; 6996 } 6997 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 6998 6999 mutex_exit(&ptgt->tgt_mutex); 7000 mutex_exit(&pptr->port_mutex); 7001 7002 if (icmd->ipkt_nodma) { 7003 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7004 sizeof (struct fcp_rsp)); 7005 } else { 7006 bep = &fcp_rsp_err; 7007 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7008 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7009 } 7010 7011 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7012 fcp_retry_scsi_cmd(fpkt); 7013 return; 7014 } 7015 7016 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7017 FCP_NO_FAILURE) { 7018 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7019 fcp_trace, FCP_BUF_LEVEL_2, 0, 7020 "rsp_code=0x%x, rsp_len_set=0x%x", 7021 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7022 fcp_retry_scsi_cmd(fpkt); 7023 return; 7024 } 7025 7026 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7027 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7028 fcp_queue_ipkt(pptr, fpkt); 7029 return; 7030 } 7031 7032 /* 7033 * Devices that do not support INQUIRY_PAGE83, return check condition 7034 * with illegal request as per SCSI spec. 7035 * Crossbridge is one such device and Daktari's SES node is another. 7036 * We want to ideally enumerate these devices as a non-mpxio devices. 7037 * SES nodes (Daktari only currently) are an exception to this. 7038 */ 7039 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7040 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7041 7042 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7043 fcp_trace, FCP_BUF_LEVEL_3, 0, 7044 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7045 "check condition. May enumerate as non-mpxio device", 7046 ptgt->tgt_d_id, plun->lun_type); 7047 7048 /* 7049 * If we let Daktari's SES be enumerated as a non-mpxio 7050 * device, there will be a discrepency in that the other 7051 * internal FC disks will get enumerated as mpxio devices. 7052 * Applications like luxadm expect this to be consistent. 7053 * 7054 * So, we put in a hack here to check if this is an SES device 7055 * and handle it here. 7056 */ 7057 if (plun->lun_type == DTYPE_ESI) { 7058 /* 7059 * Since, pkt_state is actually FC_PKT_SUCCESS 7060 * at this stage, we fake a failure here so that 7061 * fcp_handle_page83 will create a device path using 7062 * the WWN instead of the GUID which is not there anyway 7063 */ 7064 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7065 (void) fcp_handle_page83(fpkt, icmd, 1); 7066 return; 7067 } 7068 7069 mutex_enter(&ptgt->tgt_mutex); 7070 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7071 FCP_LUN_MARK | FCP_LUN_BUSY); 7072 mutex_exit(&ptgt->tgt_mutex); 7073 7074 (void) fcp_call_finish_init(pptr, ptgt, 7075 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7076 icmd->ipkt_cause); 7077 fcp_icmd_free(pptr, icmd); 7078 return; 7079 } 7080 7081 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7082 int rval = DDI_FAILURE; 7083 7084 /* 7085 * handle cases where report lun isn't supported 7086 * by faking up our own REPORT_LUN response or 7087 * UNIT ATTENTION 7088 */ 7089 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7090 rval = fcp_check_reportlun(rsp, fpkt); 7091 7092 /* 7093 * fcp_check_reportlun might have modified the 7094 * FCP response. Copy it in again to get an updated 7095 * FCP response 7096 */ 7097 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7098 rsp = &response; 7099 7100 FCP_CP_IN(fpkt->pkt_resp, rsp, 7101 fpkt->pkt_resp_acc, 7102 sizeof (struct fcp_rsp)); 7103 } 7104 } 7105 7106 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7107 if (rval == DDI_SUCCESS) { 7108 (void) fcp_call_finish_init(pptr, ptgt, 7109 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7110 icmd->ipkt_cause); 7111 fcp_icmd_free(pptr, icmd); 7112 } else { 7113 fcp_retry_scsi_cmd(fpkt); 7114 } 7115 7116 return; 7117 } 7118 } else { 7119 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7120 mutex_enter(&ptgt->tgt_mutex); 7121 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7122 mutex_exit(&ptgt->tgt_mutex); 7123 } 7124 } 7125 7126 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7127 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7128 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7129 DDI_DMA_SYNC_FORCPU); 7130 } 7131 7132 switch (icmd->ipkt_opcode) { 7133 case SCMD_INQUIRY: 7134 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7135 fcp_handle_inquiry(fpkt, icmd); 7136 break; 7137 7138 case SCMD_REPORT_LUN: 7139 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7140 FCP_TGT_TRACE_22); 7141 fcp_handle_reportlun(fpkt, icmd); 7142 break; 7143 7144 case SCMD_INQUIRY_PAGE83: 7145 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7146 (void) fcp_handle_page83(fpkt, icmd, 0); 7147 break; 7148 7149 default: 7150 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7151 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7152 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7153 fcp_icmd_free(pptr, icmd); 7154 break; 7155 } 7156 } 7157 7158 7159 static void 7160 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7161 { 7162 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7163 fpkt->pkt_ulp_private; 7164 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7165 struct fcp_port *pptr = ptgt->tgt_port; 7166 7167 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7168 fcp_is_retryable(icmd)) { 7169 mutex_enter(&pptr->port_mutex); 7170 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7171 mutex_exit(&pptr->port_mutex); 7172 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7173 fcp_trace, FCP_BUF_LEVEL_3, 0, 7174 "Retrying %s to %x; state=%x, reason=%x", 7175 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7176 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7177 fpkt->pkt_state, fpkt->pkt_reason); 7178 7179 fcp_queue_ipkt(pptr, fpkt); 7180 } else { 7181 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7182 fcp_trace, FCP_BUF_LEVEL_3, 0, 7183 "fcp_retry_scsi_cmd,1: state change occured" 7184 " for D_ID=0x%x", ptgt->tgt_d_id); 7185 mutex_exit(&pptr->port_mutex); 7186 (void) fcp_call_finish_init(pptr, ptgt, 7187 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7188 icmd->ipkt_cause); 7189 fcp_icmd_free(pptr, icmd); 7190 } 7191 } else { 7192 fcp_print_error(fpkt); 7193 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7194 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7195 fcp_icmd_free(pptr, icmd); 7196 } 7197 } 7198 7199 /* 7200 * Function: fcp_handle_page83 7201 * 7202 * Description: Treats the response to INQUIRY_PAGE83. 7203 * 7204 * Argument: *fpkt FC packet used to convey the command. 7205 * *icmd Original fcp_ipkt structure. 7206 * ignore_page83_data 7207 * if it's 1, that means it's a special devices's 7208 * page83 response, it should be enumerated under mpxio 7209 * 7210 * Return Value: None 7211 */ 7212 static void 7213 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7214 int ignore_page83_data) 7215 { 7216 struct fcp_port *pptr; 7217 struct fcp_lun *plun; 7218 struct fcp_tgt *ptgt; 7219 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7220 int fail = 0; 7221 ddi_devid_t devid; 7222 char *guid = NULL; 7223 int ret; 7224 7225 ASSERT(icmd != NULL && fpkt != NULL); 7226 7227 pptr = icmd->ipkt_port; 7228 ptgt = icmd->ipkt_tgt; 7229 plun = icmd->ipkt_lun; 7230 7231 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7232 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7233 7234 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7235 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7236 7237 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7238 fcp_trace, FCP_BUF_LEVEL_5, 0, 7239 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7240 "dtype=0x%x, lun num=%x", 7241 pptr->port_instance, ptgt->tgt_d_id, 7242 dev_id_page[0], plun->lun_num); 7243 7244 ret = ddi_devid_scsi_encode( 7245 DEVID_SCSI_ENCODE_VERSION_LATEST, 7246 NULL, /* driver name */ 7247 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7248 sizeof (plun->lun_inq), /* size of standard inquiry */ 7249 NULL, /* page 80 data */ 7250 0, /* page 80 len */ 7251 dev_id_page, /* page 83 data */ 7252 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7253 &devid); 7254 7255 if (ret == DDI_SUCCESS) { 7256 7257 guid = ddi_devid_to_guid(devid); 7258 7259 if (guid) { 7260 /* 7261 * Check our current guid. If it's non null 7262 * and it has changed, we need to copy it into 7263 * lun_old_guid since we might still need it. 7264 */ 7265 if (plun->lun_guid && 7266 strcmp(guid, plun->lun_guid)) { 7267 unsigned int len; 7268 7269 /* 7270 * If the guid of the LUN changes, 7271 * reconfiguration should be triggered 7272 * to reflect the changes. 7273 * i.e. we should offline the LUN with 7274 * the old guid, and online the LUN with 7275 * the new guid. 7276 */ 7277 plun->lun_state |= FCP_LUN_CHANGED; 7278 7279 if (plun->lun_old_guid) { 7280 kmem_free(plun->lun_old_guid, 7281 plun->lun_old_guid_size); 7282 } 7283 7284 len = plun->lun_guid_size; 7285 plun->lun_old_guid_size = len; 7286 7287 plun->lun_old_guid = kmem_zalloc(len, 7288 KM_NOSLEEP); 7289 7290 if (plun->lun_old_guid) { 7291 /* 7292 * The alloc was successful then 7293 * let's do the copy. 7294 */ 7295 bcopy(plun->lun_guid, 7296 plun->lun_old_guid, len); 7297 } else { 7298 fail = 1; 7299 plun->lun_old_guid_size = 0; 7300 } 7301 } 7302 if (!fail) { 7303 if (fcp_copy_guid_2_lun_block( 7304 plun, guid)) { 7305 fail = 1; 7306 } 7307 } 7308 ddi_devid_free_guid(guid); 7309 7310 } else { 7311 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7312 fcp_trace, FCP_BUF_LEVEL_2, 0, 7313 "fcp_handle_page83: unable to create " 7314 "GUID"); 7315 7316 /* couldn't create good guid from devid */ 7317 fail = 1; 7318 } 7319 ddi_devid_free(devid); 7320 7321 } else if (ret == DDI_NOT_WELL_FORMED) { 7322 /* NULL filled data for page 83 */ 7323 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7324 fcp_trace, FCP_BUF_LEVEL_2, 0, 7325 "fcp_handle_page83: retry GUID"); 7326 7327 icmd->ipkt_retries = 0; 7328 fcp_retry_scsi_cmd(fpkt); 7329 return; 7330 } else { 7331 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7332 fcp_trace, FCP_BUF_LEVEL_2, 0, 7333 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7334 ret); 7335 /* 7336 * Since the page83 validation 7337 * introduced late, we are being 7338 * tolerant to the existing devices 7339 * that already found to be working 7340 * under mpxio, like A5200's SES device, 7341 * its page83 response will not be standard-compliant, 7342 * but we still want it to be enumerated under mpxio. 7343 */ 7344 if (fcp_symmetric_device_probe(plun) != 0) { 7345 fail = 1; 7346 } 7347 } 7348 7349 } else { 7350 /* bad packet state */ 7351 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7352 7353 /* 7354 * For some special devices (A5K SES and Daktari's SES devices), 7355 * they should be enumerated under mpxio 7356 * or "luxadm dis" will fail 7357 */ 7358 if (ignore_page83_data) { 7359 fail = 0; 7360 } else { 7361 fail = 1; 7362 } 7363 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7364 fcp_trace, FCP_BUF_LEVEL_2, 0, 7365 "!Devid page cmd failed. " 7366 "fpkt_state: %x fpkt_reason: %x", 7367 "ignore_page83: %d", 7368 fpkt->pkt_state, fpkt->pkt_reason, 7369 ignore_page83_data); 7370 } 7371 7372 mutex_enter(&pptr->port_mutex); 7373 mutex_enter(&plun->lun_mutex); 7374 /* 7375 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7376 * mismatch between lun_cip and lun_mpxio. 7377 */ 7378 if (plun->lun_cip == NULL) { 7379 /* 7380 * If we don't have a guid for this lun it's because we were 7381 * unable to glean one from the page 83 response. Set the 7382 * control flag to 0 here to make sure that we don't attempt to 7383 * enumerate it under mpxio. 7384 */ 7385 if (fail || pptr->port_mpxio == 0) { 7386 plun->lun_mpxio = 0; 7387 } else { 7388 plun->lun_mpxio = 1; 7389 } 7390 } 7391 mutex_exit(&plun->lun_mutex); 7392 mutex_exit(&pptr->port_mutex); 7393 7394 mutex_enter(&ptgt->tgt_mutex); 7395 plun->lun_state &= 7396 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7397 mutex_exit(&ptgt->tgt_mutex); 7398 7399 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7400 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7401 7402 fcp_icmd_free(pptr, icmd); 7403 } 7404 7405 /* 7406 * Function: fcp_handle_inquiry 7407 * 7408 * Description: Called by fcp_scsi_callback to handle the response to an 7409 * INQUIRY request. 7410 * 7411 * Argument: *fpkt FC packet used to convey the command. 7412 * *icmd Original fcp_ipkt structure. 7413 * 7414 * Return Value: None 7415 */ 7416 static void 7417 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7418 { 7419 struct fcp_port *pptr; 7420 struct fcp_lun *plun; 7421 struct fcp_tgt *ptgt; 7422 uchar_t dtype; 7423 uchar_t pqual; 7424 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7425 7426 ASSERT(icmd != NULL && fpkt != NULL); 7427 7428 pptr = icmd->ipkt_port; 7429 ptgt = icmd->ipkt_tgt; 7430 plun = icmd->ipkt_lun; 7431 7432 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7433 sizeof (struct scsi_inquiry)); 7434 7435 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7436 pqual = plun->lun_inq.inq_dtype >> 5; 7437 7438 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7439 fcp_trace, FCP_BUF_LEVEL_5, 0, 7440 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7441 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7442 plun->lun_num, dtype, pqual); 7443 7444 if (pqual != 0) { 7445 /* 7446 * Non-zero peripheral qualifier 7447 */ 7448 fcp_log(CE_CONT, pptr->port_dip, 7449 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7450 "Device type=0x%x Peripheral qual=0x%x\n", 7451 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7452 7453 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7454 fcp_trace, FCP_BUF_LEVEL_5, 0, 7455 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7456 "Device type=0x%x Peripheral qual=0x%x\n", 7457 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7458 7459 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7460 7461 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7462 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7463 fcp_icmd_free(pptr, icmd); 7464 return; 7465 } 7466 7467 /* 7468 * If the device is already initialized, check the dtype 7469 * for a change. If it has changed then update the flags 7470 * so the create_luns will offline the old device and 7471 * create the new device. Refer to bug: 4764752 7472 */ 7473 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7474 plun->lun_state |= FCP_LUN_CHANGED; 7475 } 7476 plun->lun_type = plun->lun_inq.inq_dtype; 7477 7478 /* 7479 * This code is setting/initializing the throttling in the FCA 7480 * driver. 7481 */ 7482 mutex_enter(&pptr->port_mutex); 7483 if (!pptr->port_notify) { 7484 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7485 uint32_t cmd = 0; 7486 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7487 ((cmd & 0xFFFFFF00 >> 8) | 7488 FCP_SVE_THROTTLE << 8)); 7489 pptr->port_notify = 1; 7490 mutex_exit(&pptr->port_mutex); 7491 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7492 mutex_enter(&pptr->port_mutex); 7493 } 7494 } 7495 7496 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7497 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7498 fcp_trace, FCP_BUF_LEVEL_2, 0, 7499 "fcp_handle_inquiry,1:state change occured" 7500 " for D_ID=0x%x", ptgt->tgt_d_id); 7501 mutex_exit(&pptr->port_mutex); 7502 7503 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7504 (void) fcp_call_finish_init(pptr, ptgt, 7505 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7506 icmd->ipkt_cause); 7507 fcp_icmd_free(pptr, icmd); 7508 return; 7509 } 7510 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7511 mutex_exit(&pptr->port_mutex); 7512 7513 /* Retrieve the rscn count (if a valid one exists) */ 7514 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7515 rscn_count = ((fc_ulp_rscn_info_t *) 7516 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7517 } else { 7518 rscn_count = FC_INVALID_RSCN_COUNT; 7519 } 7520 7521 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7522 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7523 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7524 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7525 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7526 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7527 (void) fcp_call_finish_init(pptr, ptgt, 7528 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7529 icmd->ipkt_cause); 7530 } 7531 7532 /* 7533 * Read Inquiry VPD Page 0x83 to uniquely 7534 * identify this logical unit. 7535 */ 7536 fcp_icmd_free(pptr, icmd); 7537 } 7538 7539 /* 7540 * Function: fcp_handle_reportlun 7541 * 7542 * Description: Called by fcp_scsi_callback to handle the response to a 7543 * REPORT_LUN request. 7544 * 7545 * Argument: *fpkt FC packet used to convey the command. 7546 * *icmd Original fcp_ipkt structure. 7547 * 7548 * Return Value: None 7549 */ 7550 static void 7551 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7552 { 7553 int i; 7554 int nluns_claimed; 7555 int nluns_bufmax; 7556 int len; 7557 uint16_t lun_num; 7558 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7559 struct fcp_port *pptr; 7560 struct fcp_tgt *ptgt; 7561 struct fcp_lun *plun; 7562 struct fcp_reportlun_resp *report_lun; 7563 7564 pptr = icmd->ipkt_port; 7565 ptgt = icmd->ipkt_tgt; 7566 len = fpkt->pkt_datalen; 7567 7568 if ((len < FCP_LUN_HEADER) || 7569 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7570 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7571 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7572 fcp_icmd_free(pptr, icmd); 7573 return; 7574 } 7575 7576 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7577 fpkt->pkt_datalen); 7578 7579 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7580 fcp_trace, FCP_BUF_LEVEL_5, 0, 7581 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7582 pptr->port_instance, ptgt->tgt_d_id); 7583 7584 /* 7585 * Get the number of luns (which is supplied as LUNS * 8) the 7586 * device claims it has. 7587 */ 7588 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7589 7590 /* 7591 * Get the maximum number of luns the buffer submitted can hold. 7592 */ 7593 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7594 7595 /* 7596 * Due to limitations of certain hardware, we support only 16 bit LUNs 7597 */ 7598 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7599 kmem_free(report_lun, len); 7600 7601 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7602 " 0x%x number of LUNs for target=%x", nluns_claimed, 7603 ptgt->tgt_d_id); 7604 7605 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7606 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7607 fcp_icmd_free(pptr, icmd); 7608 return; 7609 } 7610 7611 /* 7612 * If there are more LUNs than we have allocated memory for, 7613 * allocate more space and send down yet another report lun if 7614 * the maximum number of attempts hasn't been reached. 7615 */ 7616 mutex_enter(&ptgt->tgt_mutex); 7617 7618 if ((nluns_claimed > nluns_bufmax) && 7619 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7620 7621 struct fcp_lun *plun; 7622 7623 ptgt->tgt_report_lun_cnt++; 7624 plun = ptgt->tgt_lun; 7625 ASSERT(plun != NULL); 7626 mutex_exit(&ptgt->tgt_mutex); 7627 7628 kmem_free(report_lun, len); 7629 7630 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7631 fcp_trace, FCP_BUF_LEVEL_5, 0, 7632 "!Dynamically discovered %d LUNs for D_ID=%x", 7633 nluns_claimed, ptgt->tgt_d_id); 7634 7635 /* Retrieve the rscn count (if a valid one exists) */ 7636 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7637 rscn_count = ((fc_ulp_rscn_info_t *) 7638 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7639 ulp_rscn_count; 7640 } else { 7641 rscn_count = FC_INVALID_RSCN_COUNT; 7642 } 7643 7644 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7645 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7646 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7647 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7648 (void) fcp_call_finish_init(pptr, ptgt, 7649 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7650 icmd->ipkt_cause); 7651 } 7652 7653 fcp_icmd_free(pptr, icmd); 7654 return; 7655 } 7656 7657 if (nluns_claimed > nluns_bufmax) { 7658 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7659 fcp_trace, FCP_BUF_LEVEL_5, 0, 7660 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7661 " Number of LUNs lost=%x", 7662 ptgt->tgt_port_wwn.raw_wwn[0], 7663 ptgt->tgt_port_wwn.raw_wwn[1], 7664 ptgt->tgt_port_wwn.raw_wwn[2], 7665 ptgt->tgt_port_wwn.raw_wwn[3], 7666 ptgt->tgt_port_wwn.raw_wwn[4], 7667 ptgt->tgt_port_wwn.raw_wwn[5], 7668 ptgt->tgt_port_wwn.raw_wwn[6], 7669 ptgt->tgt_port_wwn.raw_wwn[7], 7670 nluns_claimed - nluns_bufmax); 7671 7672 nluns_claimed = nluns_bufmax; 7673 } 7674 ptgt->tgt_lun_cnt = nluns_claimed; 7675 7676 /* 7677 * Identify missing LUNs and print warning messages 7678 */ 7679 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7680 int offline; 7681 int exists = 0; 7682 7683 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7684 7685 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7686 uchar_t *lun_string; 7687 7688 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7689 7690 switch (lun_string[0] & 0xC0) { 7691 case FCP_LUN_ADDRESSING: 7692 case FCP_PD_ADDRESSING: 7693 case FCP_VOLUME_ADDRESSING: 7694 lun_num = ((lun_string[0] & 0x3F) << 8) | 7695 lun_string[1]; 7696 if (plun->lun_num == lun_num) { 7697 exists++; 7698 break; 7699 } 7700 break; 7701 7702 default: 7703 break; 7704 } 7705 } 7706 7707 if (!exists && !offline) { 7708 mutex_exit(&ptgt->tgt_mutex); 7709 7710 mutex_enter(&pptr->port_mutex); 7711 mutex_enter(&ptgt->tgt_mutex); 7712 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7713 /* 7714 * set disappear flag when device was connected 7715 */ 7716 if (!(plun->lun_state & 7717 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7718 plun->lun_state |= FCP_LUN_DISAPPEARED; 7719 } 7720 mutex_exit(&ptgt->tgt_mutex); 7721 mutex_exit(&pptr->port_mutex); 7722 if (!(plun->lun_state & 7723 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7724 fcp_log(CE_NOTE, pptr->port_dip, 7725 "!Lun=%x for target=%x disappeared", 7726 plun->lun_num, ptgt->tgt_d_id); 7727 } 7728 mutex_enter(&ptgt->tgt_mutex); 7729 } else { 7730 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7731 fcp_trace, FCP_BUF_LEVEL_5, 0, 7732 "fcp_handle_reportlun,1: state change" 7733 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7734 mutex_exit(&ptgt->tgt_mutex); 7735 mutex_exit(&pptr->port_mutex); 7736 kmem_free(report_lun, len); 7737 (void) fcp_call_finish_init(pptr, ptgt, 7738 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7739 icmd->ipkt_cause); 7740 fcp_icmd_free(pptr, icmd); 7741 return; 7742 } 7743 } else if (exists) { 7744 /* 7745 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7746 * actually exists in REPORT_LUN response 7747 */ 7748 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7749 plun->lun_state &= 7750 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7751 } 7752 if (offline || plun->lun_num == 0) { 7753 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7754 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7755 mutex_exit(&ptgt->tgt_mutex); 7756 fcp_log(CE_NOTE, pptr->port_dip, 7757 "!Lun=%x for target=%x reappeared", 7758 plun->lun_num, ptgt->tgt_d_id); 7759 mutex_enter(&ptgt->tgt_mutex); 7760 } 7761 } 7762 } 7763 } 7764 7765 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7766 mutex_exit(&ptgt->tgt_mutex); 7767 7768 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7769 fcp_trace, FCP_BUF_LEVEL_5, 0, 7770 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7771 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7772 7773 /* scan each lun */ 7774 for (i = 0; i < nluns_claimed; i++) { 7775 uchar_t *lun_string; 7776 7777 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7778 7779 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7780 fcp_trace, FCP_BUF_LEVEL_5, 0, 7781 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7782 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7783 lun_string[0]); 7784 7785 switch (lun_string[0] & 0xC0) { 7786 case FCP_LUN_ADDRESSING: 7787 case FCP_PD_ADDRESSING: 7788 case FCP_VOLUME_ADDRESSING: 7789 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7790 7791 /* We will skip masked LUNs because of the blacklist. */ 7792 if (fcp_lun_blacklist != NULL) { 7793 mutex_enter(&ptgt->tgt_mutex); 7794 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7795 lun_num) == TRUE) { 7796 ptgt->tgt_lun_cnt--; 7797 mutex_exit(&ptgt->tgt_mutex); 7798 break; 7799 } 7800 mutex_exit(&ptgt->tgt_mutex); 7801 } 7802 7803 /* see if this LUN is already allocated */ 7804 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7805 plun = fcp_alloc_lun(ptgt); 7806 if (plun == NULL) { 7807 fcp_log(CE_NOTE, pptr->port_dip, 7808 "!Lun allocation failed" 7809 " target=%x lun=%x", 7810 ptgt->tgt_d_id, lun_num); 7811 break; 7812 } 7813 } 7814 7815 mutex_enter(&plun->lun_tgt->tgt_mutex); 7816 /* convert to LUN */ 7817 plun->lun_addr.ent_addr_0 = 7818 BE_16(*(uint16_t *)&(lun_string[0])); 7819 plun->lun_addr.ent_addr_1 = 7820 BE_16(*(uint16_t *)&(lun_string[2])); 7821 plun->lun_addr.ent_addr_2 = 7822 BE_16(*(uint16_t *)&(lun_string[4])); 7823 plun->lun_addr.ent_addr_3 = 7824 BE_16(*(uint16_t *)&(lun_string[6])); 7825 7826 plun->lun_num = lun_num; 7827 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7828 plun->lun_state &= ~FCP_LUN_OFFLINE; 7829 mutex_exit(&plun->lun_tgt->tgt_mutex); 7830 7831 /* Retrieve the rscn count (if a valid one exists) */ 7832 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7833 rscn_count = ((fc_ulp_rscn_info_t *) 7834 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7835 ulp_rscn_count; 7836 } else { 7837 rscn_count = FC_INVALID_RSCN_COUNT; 7838 } 7839 7840 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7841 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7842 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7843 mutex_enter(&pptr->port_mutex); 7844 mutex_enter(&plun->lun_tgt->tgt_mutex); 7845 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7846 fcp_log(CE_NOTE, pptr->port_dip, 7847 "!failed to send INQUIRY" 7848 " target=%x lun=%x", 7849 ptgt->tgt_d_id, plun->lun_num); 7850 } else { 7851 FCP_TRACE(fcp_logq, 7852 pptr->port_instbuf, fcp_trace, 7853 FCP_BUF_LEVEL_5, 0, 7854 "fcp_handle_reportlun,2: state" 7855 " change occured for D_ID=0x%x", 7856 ptgt->tgt_d_id); 7857 } 7858 mutex_exit(&plun->lun_tgt->tgt_mutex); 7859 mutex_exit(&pptr->port_mutex); 7860 } else { 7861 continue; 7862 } 7863 break; 7864 7865 default: 7866 fcp_log(CE_WARN, NULL, 7867 "!Unsupported LUN Addressing method %x " 7868 "in response to REPORT_LUN", lun_string[0]); 7869 break; 7870 } 7871 7872 /* 7873 * each time through this loop we should decrement 7874 * the tmp_cnt by one -- since we go through this loop 7875 * one time for each LUN, the tmp_cnt should never be <=0 7876 */ 7877 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7878 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7879 } 7880 7881 if (i == 0) { 7882 fcp_log(CE_WARN, pptr->port_dip, 7883 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7884 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7885 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7886 } 7887 7888 kmem_free(report_lun, len); 7889 fcp_icmd_free(pptr, icmd); 7890 } 7891 7892 7893 /* 7894 * called internally to return a LUN given a target and a LUN number 7895 */ 7896 static struct fcp_lun * 7897 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7898 { 7899 struct fcp_lun *plun; 7900 7901 mutex_enter(&ptgt->tgt_mutex); 7902 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7903 if (plun->lun_num == lun_num) { 7904 mutex_exit(&ptgt->tgt_mutex); 7905 return (plun); 7906 } 7907 } 7908 mutex_exit(&ptgt->tgt_mutex); 7909 7910 return (NULL); 7911 } 7912 7913 7914 /* 7915 * handle finishing one target for fcp_finish_init 7916 * 7917 * return true (non-zero) if we want finish_init to continue with the 7918 * next target 7919 * 7920 * called with the port mutex held 7921 */ 7922 /*ARGSUSED*/ 7923 static int 7924 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7925 int link_cnt, int tgt_cnt, int cause) 7926 { 7927 int rval = 1; 7928 ASSERT(pptr != NULL); 7929 ASSERT(ptgt != NULL); 7930 7931 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7932 fcp_trace, FCP_BUF_LEVEL_5, 0, 7933 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7934 ptgt->tgt_state); 7935 7936 ASSERT(mutex_owned(&pptr->port_mutex)); 7937 7938 if ((pptr->port_link_cnt != link_cnt) || 7939 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7940 /* 7941 * oh oh -- another link reset or target change 7942 * must have occurred while we are in here 7943 */ 7944 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7945 7946 return (0); 7947 } else { 7948 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7949 } 7950 7951 mutex_enter(&ptgt->tgt_mutex); 7952 7953 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7954 /* 7955 * tgt is not offline -- is it marked (i.e. needs 7956 * to be offlined) ?? 7957 */ 7958 if (ptgt->tgt_state & FCP_TGT_MARK) { 7959 /* 7960 * this target not offline *and* 7961 * marked 7962 */ 7963 ptgt->tgt_state &= ~FCP_TGT_MARK; 7964 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7965 tgt_cnt, 0, 0); 7966 } else { 7967 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7968 7969 /* create the LUNs */ 7970 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7971 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7972 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7973 cause); 7974 ptgt->tgt_device_created = 1; 7975 } else { 7976 fcp_update_tgt_state(ptgt, FCP_RESET, 7977 FCP_LUN_BUSY); 7978 } 7979 } 7980 } 7981 7982 mutex_exit(&ptgt->tgt_mutex); 7983 7984 return (rval); 7985 } 7986 7987 7988 /* 7989 * this routine is called to finish port initialization 7990 * 7991 * Each port has a "temp" counter -- when a state change happens (e.g. 7992 * port online), the temp count is set to the number of devices in the map. 7993 * Then, as each device gets "discovered", the temp counter is decremented 7994 * by one. When this count reaches zero we know that all of the devices 7995 * in the map have been discovered (or an error has occurred), so we can 7996 * then finish initialization -- which is done by this routine (well, this 7997 * and fcp-finish_tgt()) 7998 * 7999 * acquires and releases the global mutex 8000 * 8001 * called with the port mutex owned 8002 */ 8003 static void 8004 fcp_finish_init(struct fcp_port *pptr) 8005 { 8006 #ifdef DEBUG 8007 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8008 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8009 FCP_STACK_DEPTH); 8010 #endif /* DEBUG */ 8011 8012 ASSERT(mutex_owned(&pptr->port_mutex)); 8013 8014 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8015 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8016 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8017 8018 if ((pptr->port_state & FCP_STATE_ONLINING) && 8019 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8020 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8021 pptr->port_state &= ~FCP_STATE_ONLINING; 8022 pptr->port_state |= FCP_STATE_ONLINE; 8023 } 8024 8025 /* Wake up threads waiting on config done */ 8026 cv_broadcast(&pptr->port_config_cv); 8027 } 8028 8029 8030 /* 8031 * called from fcp_finish_init to create the LUNs for a target 8032 * 8033 * called with the port mutex owned 8034 */ 8035 static void 8036 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8037 { 8038 struct fcp_lun *plun; 8039 struct fcp_port *pptr; 8040 child_info_t *cip = NULL; 8041 8042 ASSERT(ptgt != NULL); 8043 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8044 8045 pptr = ptgt->tgt_port; 8046 8047 ASSERT(pptr != NULL); 8048 8049 /* scan all LUNs for this target */ 8050 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8051 if (plun->lun_state & FCP_LUN_OFFLINE) { 8052 continue; 8053 } 8054 8055 if (plun->lun_state & FCP_LUN_MARK) { 8056 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8057 fcp_trace, FCP_BUF_LEVEL_2, 0, 8058 "fcp_create_luns: offlining marked LUN!"); 8059 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8060 continue; 8061 } 8062 8063 plun->lun_state &= ~FCP_LUN_BUSY; 8064 8065 /* 8066 * There are conditions in which FCP_LUN_INIT flag is cleared 8067 * but we have a valid plun->lun_cip. To cover this case also 8068 * CLEAR_BUSY whenever we have a valid lun_cip. 8069 */ 8070 if (plun->lun_mpxio && plun->lun_cip && 8071 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8072 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8073 0, 0))) { 8074 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8075 fcp_trace, FCP_BUF_LEVEL_2, 0, 8076 "fcp_create_luns: enable lun %p failed!", 8077 plun); 8078 } 8079 8080 if (plun->lun_state & FCP_LUN_INIT && 8081 !(plun->lun_state & FCP_LUN_CHANGED)) { 8082 continue; 8083 } 8084 8085 if (cause == FCP_CAUSE_USER_CREATE) { 8086 continue; 8087 } 8088 8089 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8090 fcp_trace, FCP_BUF_LEVEL_6, 0, 8091 "create_luns: passing ONLINE elem to HP thread"); 8092 8093 /* 8094 * If lun has changed, prepare for offlining the old path. 8095 * Do not offline the old path right now, since it may be 8096 * still opened. 8097 */ 8098 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8099 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8100 } 8101 8102 /* pass an ONLINE element to the hotplug thread */ 8103 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8104 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8105 8106 /* 8107 * We can not synchronous attach (i.e pass 8108 * NDI_ONLINE_ATTACH) here as we might be 8109 * coming from an interrupt or callback 8110 * thread. 8111 */ 8112 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8113 link_cnt, tgt_cnt, 0, 0)) { 8114 fcp_log(CE_CONT, pptr->port_dip, 8115 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8116 plun->lun_tgt->tgt_d_id, plun->lun_num); 8117 } 8118 } 8119 } 8120 } 8121 8122 8123 /* 8124 * function to online/offline devices 8125 */ 8126 static int 8127 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8128 int online, int lcount, int tcount, int flags) 8129 { 8130 int rval = NDI_FAILURE; 8131 int circ; 8132 child_info_t *ccip; 8133 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8134 int is_mpxio = pptr->port_mpxio; 8135 dev_info_t *cdip, *pdip; 8136 char *devname; 8137 8138 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8139 /* 8140 * When this event gets serviced, lun_cip and lun_mpxio 8141 * has changed, so it should be invalidated now. 8142 */ 8143 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8144 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8145 "plun: %p, cip: %p, what:%d", plun, cip, online); 8146 return (rval); 8147 } 8148 8149 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8150 fcp_trace, FCP_BUF_LEVEL_2, 0, 8151 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8152 "flags=%x mpxio=%x\n", 8153 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8154 plun->lun_mpxio); 8155 8156 /* 8157 * lun_mpxio needs checking here because we can end up in a race 8158 * condition where this task has been dispatched while lun_mpxio is 8159 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8160 * enable MPXIO for the LUN, but was unable to, and hence cleared 8161 * the flag. We rely on the serialization of the tasks here. We return 8162 * NDI_SUCCESS so any callers continue without reporting spurious 8163 * errors, and the still think we're an MPXIO LUN. 8164 */ 8165 8166 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8167 online == FCP_MPXIO_PATH_SET_BUSY) { 8168 if (plun->lun_mpxio) { 8169 rval = fcp_update_mpxio_path(plun, cip, online); 8170 } else { 8171 rval = NDI_SUCCESS; 8172 } 8173 return (rval); 8174 } 8175 8176 /* 8177 * Explicit devfs_clean() due to ndi_devi_offline() not 8178 * executing devfs_clean() if parent lock is held. 8179 */ 8180 ASSERT(!servicing_interrupt()); 8181 if (online == FCP_OFFLINE) { 8182 if (plun->lun_mpxio == 0) { 8183 if (plun->lun_cip == cip) { 8184 cdip = DIP(plun->lun_cip); 8185 } else { 8186 cdip = DIP(cip); 8187 } 8188 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8189 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8190 } else if ((plun->lun_cip != cip) && cip) { 8191 /* 8192 * This means a DTYPE/GUID change, we shall get the 8193 * dip of the old cip instead of the current lun_cip. 8194 */ 8195 cdip = mdi_pi_get_client(PIP(cip)); 8196 } 8197 if (cdip) { 8198 if (i_ddi_devi_attached(cdip)) { 8199 pdip = ddi_get_parent(cdip); 8200 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8201 ndi_devi_enter(pdip, &circ); 8202 (void) ddi_deviname(cdip, devname); 8203 /* 8204 * Release parent lock before calling 8205 * devfs_clean(). 8206 */ 8207 ndi_devi_exit(pdip, circ); 8208 (void) devfs_clean(pdip, devname + 1, 8209 DV_CLEAN_FORCE); 8210 kmem_free(devname, MAXNAMELEN + 1); 8211 } 8212 } 8213 } 8214 8215 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8216 return (NDI_FAILURE); 8217 } 8218 8219 if (is_mpxio) { 8220 mdi_devi_enter(pptr->port_dip, &circ); 8221 } else { 8222 ndi_devi_enter(pptr->port_dip, &circ); 8223 } 8224 8225 mutex_enter(&pptr->port_mutex); 8226 mutex_enter(&plun->lun_mutex); 8227 8228 if (online == FCP_ONLINE) { 8229 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8230 if (ccip == NULL) { 8231 goto fail; 8232 } 8233 } else { 8234 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8235 goto fail; 8236 } 8237 ccip = cip; 8238 } 8239 8240 if (online == FCP_ONLINE) { 8241 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8242 &circ); 8243 fc_ulp_log_device_event(pptr->port_fp_handle, 8244 FC_ULP_DEVICE_ONLINE); 8245 } else { 8246 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8247 &circ); 8248 fc_ulp_log_device_event(pptr->port_fp_handle, 8249 FC_ULP_DEVICE_OFFLINE); 8250 } 8251 8252 fail: mutex_exit(&plun->lun_mutex); 8253 mutex_exit(&pptr->port_mutex); 8254 8255 if (is_mpxio) { 8256 mdi_devi_exit(pptr->port_dip, circ); 8257 } else { 8258 ndi_devi_exit(pptr->port_dip, circ); 8259 } 8260 8261 fc_ulp_idle_port(pptr->port_fp_handle); 8262 8263 return (rval); 8264 } 8265 8266 8267 /* 8268 * take a target offline by taking all of its LUNs offline 8269 */ 8270 /*ARGSUSED*/ 8271 static int 8272 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8273 int link_cnt, int tgt_cnt, int nowait, int flags) 8274 { 8275 struct fcp_tgt_elem *elem; 8276 8277 ASSERT(mutex_owned(&pptr->port_mutex)); 8278 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8279 8280 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8281 8282 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8283 ptgt->tgt_change_cnt)) { 8284 mutex_exit(&ptgt->tgt_mutex); 8285 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8286 mutex_enter(&ptgt->tgt_mutex); 8287 8288 return (0); 8289 } 8290 8291 ptgt->tgt_pd_handle = NULL; 8292 mutex_exit(&ptgt->tgt_mutex); 8293 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8294 mutex_enter(&ptgt->tgt_mutex); 8295 8296 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8297 8298 if (ptgt->tgt_tcap && 8299 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8300 elem->flags = flags; 8301 elem->time = fcp_watchdog_time; 8302 if (nowait == 0) { 8303 elem->time += fcp_offline_delay; 8304 } 8305 elem->ptgt = ptgt; 8306 elem->link_cnt = link_cnt; 8307 elem->tgt_cnt = tgt_cnt; 8308 elem->next = pptr->port_offline_tgts; 8309 pptr->port_offline_tgts = elem; 8310 } else { 8311 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8312 } 8313 8314 return (1); 8315 } 8316 8317 8318 static void 8319 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8320 int link_cnt, int tgt_cnt, int flags) 8321 { 8322 ASSERT(mutex_owned(&pptr->port_mutex)); 8323 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8324 8325 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8326 ptgt->tgt_state = FCP_TGT_OFFLINE; 8327 ptgt->tgt_pd_handle = NULL; 8328 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8329 } 8330 8331 8332 static void 8333 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8334 int flags) 8335 { 8336 struct fcp_lun *plun; 8337 8338 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8339 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8340 8341 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8342 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8343 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8344 } 8345 } 8346 } 8347 8348 8349 /* 8350 * take a LUN offline 8351 * 8352 * enters and leaves with the target mutex held, releasing it in the process 8353 * 8354 * allocates memory in non-sleep mode 8355 */ 8356 static void 8357 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8358 int nowait, int flags) 8359 { 8360 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8361 struct fcp_lun_elem *elem; 8362 8363 ASSERT(plun != NULL); 8364 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8365 8366 if (nowait) { 8367 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8368 return; 8369 } 8370 8371 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8372 elem->flags = flags; 8373 elem->time = fcp_watchdog_time; 8374 if (nowait == 0) { 8375 elem->time += fcp_offline_delay; 8376 } 8377 elem->plun = plun; 8378 elem->link_cnt = link_cnt; 8379 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8380 elem->next = pptr->port_offline_luns; 8381 pptr->port_offline_luns = elem; 8382 } else { 8383 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8384 } 8385 } 8386 8387 8388 static void 8389 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8390 { 8391 struct fcp_pkt *head = NULL; 8392 8393 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8394 8395 mutex_exit(&LUN_TGT->tgt_mutex); 8396 8397 head = fcp_scan_commands(plun); 8398 if (head != NULL) { 8399 fcp_abort_commands(head, LUN_PORT); 8400 } 8401 8402 mutex_enter(&LUN_TGT->tgt_mutex); 8403 8404 if (plun->lun_cip && plun->lun_mpxio) { 8405 /* 8406 * Intimate MPxIO lun busy is cleared 8407 */ 8408 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8409 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8410 0, 0)) { 8411 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8412 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8413 LUN_TGT->tgt_d_id, plun->lun_num); 8414 } 8415 /* 8416 * Intimate MPxIO that the lun is now marked for offline 8417 */ 8418 mutex_exit(&LUN_TGT->tgt_mutex); 8419 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8420 mutex_enter(&LUN_TGT->tgt_mutex); 8421 } 8422 } 8423 8424 static void 8425 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8426 int flags) 8427 { 8428 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8429 8430 mutex_exit(&LUN_TGT->tgt_mutex); 8431 fcp_update_offline_flags(plun); 8432 mutex_enter(&LUN_TGT->tgt_mutex); 8433 8434 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8435 8436 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8437 fcp_trace, FCP_BUF_LEVEL_4, 0, 8438 "offline_lun: passing OFFLINE elem to HP thread"); 8439 8440 if (plun->lun_cip) { 8441 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8442 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8443 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8444 LUN_TGT->tgt_trace); 8445 8446 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8447 link_cnt, tgt_cnt, flags, 0)) { 8448 fcp_log(CE_CONT, LUN_PORT->port_dip, 8449 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8450 LUN_TGT->tgt_d_id, plun->lun_num); 8451 } 8452 } 8453 } 8454 8455 static void 8456 fcp_scan_offline_luns(struct fcp_port *pptr) 8457 { 8458 struct fcp_lun_elem *elem; 8459 struct fcp_lun_elem *prev; 8460 struct fcp_lun_elem *next; 8461 8462 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8463 8464 prev = NULL; 8465 elem = pptr->port_offline_luns; 8466 while (elem) { 8467 next = elem->next; 8468 if (elem->time <= fcp_watchdog_time) { 8469 int changed = 1; 8470 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8471 8472 mutex_enter(&ptgt->tgt_mutex); 8473 if (pptr->port_link_cnt == elem->link_cnt && 8474 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8475 changed = 0; 8476 } 8477 8478 if (!changed && 8479 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8480 fcp_offline_lun_now(elem->plun, 8481 elem->link_cnt, elem->tgt_cnt, elem->flags); 8482 } 8483 mutex_exit(&ptgt->tgt_mutex); 8484 8485 kmem_free(elem, sizeof (*elem)); 8486 8487 if (prev) { 8488 prev->next = next; 8489 } else { 8490 pptr->port_offline_luns = next; 8491 } 8492 } else { 8493 prev = elem; 8494 } 8495 elem = next; 8496 } 8497 } 8498 8499 8500 static void 8501 fcp_scan_offline_tgts(struct fcp_port *pptr) 8502 { 8503 struct fcp_tgt_elem *elem; 8504 struct fcp_tgt_elem *prev; 8505 struct fcp_tgt_elem *next; 8506 8507 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8508 8509 prev = NULL; 8510 elem = pptr->port_offline_tgts; 8511 while (elem) { 8512 next = elem->next; 8513 if (elem->time <= fcp_watchdog_time) { 8514 int outdated = 1; 8515 struct fcp_tgt *ptgt = elem->ptgt; 8516 8517 mutex_enter(&ptgt->tgt_mutex); 8518 8519 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8520 /* No change on tgt since elem was created. */ 8521 outdated = 0; 8522 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8523 pptr->port_link_cnt == elem->link_cnt + 1 && 8524 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8525 /* 8526 * Exactly one thing happened to the target 8527 * inbetween: the local port went offline. 8528 * For fp the remote port is already gone so 8529 * it will not tell us again to offline the 8530 * target. We must offline it now. 8531 */ 8532 outdated = 0; 8533 } 8534 8535 if (!outdated && !(ptgt->tgt_state & 8536 FCP_TGT_OFFLINE)) { 8537 fcp_offline_target_now(pptr, 8538 ptgt, elem->link_cnt, elem->tgt_cnt, 8539 elem->flags); 8540 } 8541 8542 mutex_exit(&ptgt->tgt_mutex); 8543 8544 kmem_free(elem, sizeof (*elem)); 8545 8546 if (prev) { 8547 prev->next = next; 8548 } else { 8549 pptr->port_offline_tgts = next; 8550 } 8551 } else { 8552 prev = elem; 8553 } 8554 elem = next; 8555 } 8556 } 8557 8558 8559 static void 8560 fcp_update_offline_flags(struct fcp_lun *plun) 8561 { 8562 struct fcp_port *pptr = LUN_PORT; 8563 ASSERT(plun != NULL); 8564 8565 mutex_enter(&LUN_TGT->tgt_mutex); 8566 plun->lun_state |= FCP_LUN_OFFLINE; 8567 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8568 8569 mutex_enter(&plun->lun_mutex); 8570 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8571 dev_info_t *cdip = NULL; 8572 8573 mutex_exit(&LUN_TGT->tgt_mutex); 8574 8575 if (plun->lun_mpxio == 0) { 8576 cdip = DIP(plun->lun_cip); 8577 } else if (plun->lun_cip) { 8578 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8579 } 8580 8581 mutex_exit(&plun->lun_mutex); 8582 if (cdip) { 8583 (void) ndi_event_retrieve_cookie( 8584 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8585 &fcp_remove_eid, NDI_EVENT_NOPASS); 8586 (void) ndi_event_run_callbacks( 8587 pptr->port_ndi_event_hdl, cdip, 8588 fcp_remove_eid, NULL); 8589 } 8590 } else { 8591 mutex_exit(&plun->lun_mutex); 8592 mutex_exit(&LUN_TGT->tgt_mutex); 8593 } 8594 } 8595 8596 8597 /* 8598 * Scan all of the command pkts for this port, moving pkts that 8599 * match our LUN onto our own list (headed by "head") 8600 */ 8601 static struct fcp_pkt * 8602 fcp_scan_commands(struct fcp_lun *plun) 8603 { 8604 struct fcp_port *pptr = LUN_PORT; 8605 8606 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8607 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8608 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8609 8610 struct fcp_pkt *head = NULL; /* head of our list */ 8611 struct fcp_pkt *tail = NULL; /* tail of our list */ 8612 8613 int cmds_found = 0; 8614 8615 mutex_enter(&pptr->port_pkt_mutex); 8616 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8617 struct fcp_lun *tlun = 8618 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8619 8620 ncmd = cmd->cmd_next; /* set next command */ 8621 8622 /* 8623 * if this pkt is for a different LUN or the 8624 * command is sent down, skip it. 8625 */ 8626 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8627 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8628 pcmd = cmd; 8629 continue; 8630 } 8631 cmds_found++; 8632 if (pcmd != NULL) { 8633 ASSERT(pptr->port_pkt_head != cmd); 8634 pcmd->cmd_next = cmd->cmd_next; 8635 } else { 8636 ASSERT(cmd == pptr->port_pkt_head); 8637 pptr->port_pkt_head = cmd->cmd_next; 8638 } 8639 8640 if (cmd == pptr->port_pkt_tail) { 8641 pptr->port_pkt_tail = pcmd; 8642 if (pcmd) { 8643 pcmd->cmd_next = NULL; 8644 } 8645 } 8646 8647 if (head == NULL) { 8648 head = tail = cmd; 8649 } else { 8650 ASSERT(tail != NULL); 8651 8652 tail->cmd_next = cmd; 8653 tail = cmd; 8654 } 8655 cmd->cmd_next = NULL; 8656 } 8657 mutex_exit(&pptr->port_pkt_mutex); 8658 8659 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8660 fcp_trace, FCP_BUF_LEVEL_8, 0, 8661 "scan commands: %d cmd(s) found", cmds_found); 8662 8663 return (head); 8664 } 8665 8666 8667 /* 8668 * Abort all the commands in the command queue 8669 */ 8670 static void 8671 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8672 { 8673 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8674 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8675 8676 ASSERT(mutex_owned(&pptr->port_mutex)); 8677 8678 /* scan through the pkts and invalid them */ 8679 for (cmd = head; cmd != NULL; cmd = ncmd) { 8680 struct scsi_pkt *pkt = cmd->cmd_pkt; 8681 8682 ncmd = cmd->cmd_next; 8683 ASSERT(pkt != NULL); 8684 8685 /* 8686 * The lun is going to be marked offline. Indicate 8687 * the target driver not to requeue or retry this command 8688 * as the device is going to be offlined pretty soon. 8689 */ 8690 pkt->pkt_reason = CMD_DEV_GONE; 8691 pkt->pkt_statistics = 0; 8692 pkt->pkt_state = 0; 8693 8694 /* reset cmd flags/state */ 8695 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8696 cmd->cmd_state = FCP_PKT_IDLE; 8697 8698 /* 8699 * ensure we have a packet completion routine, 8700 * then call it. 8701 */ 8702 ASSERT(pkt->pkt_comp != NULL); 8703 8704 mutex_exit(&pptr->port_mutex); 8705 fcp_post_callback(cmd); 8706 mutex_enter(&pptr->port_mutex); 8707 } 8708 } 8709 8710 8711 /* 8712 * the pkt_comp callback for command packets 8713 */ 8714 static void 8715 fcp_cmd_callback(fc_packet_t *fpkt) 8716 { 8717 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8718 struct scsi_pkt *pkt = cmd->cmd_pkt; 8719 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8720 8721 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8722 8723 if (cmd->cmd_state == FCP_PKT_IDLE) { 8724 cmn_err(CE_PANIC, "Packet already completed %p", 8725 (void *)cmd); 8726 } 8727 8728 /* 8729 * Watch thread should be freeing the packet, ignore the pkt. 8730 */ 8731 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8732 fcp_log(CE_CONT, pptr->port_dip, 8733 "!FCP: Pkt completed while aborting\n"); 8734 return; 8735 } 8736 cmd->cmd_state = FCP_PKT_IDLE; 8737 8738 fcp_complete_pkt(fpkt); 8739 8740 #ifdef DEBUG 8741 mutex_enter(&pptr->port_pkt_mutex); 8742 pptr->port_npkts--; 8743 mutex_exit(&pptr->port_pkt_mutex); 8744 #endif /* DEBUG */ 8745 8746 fcp_post_callback(cmd); 8747 } 8748 8749 8750 static void 8751 fcp_complete_pkt(fc_packet_t *fpkt) 8752 { 8753 int error = 0; 8754 struct fcp_pkt *cmd = (struct fcp_pkt *) 8755 fpkt->pkt_ulp_private; 8756 struct scsi_pkt *pkt = cmd->cmd_pkt; 8757 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8758 struct fcp_lun *plun; 8759 struct fcp_tgt *ptgt; 8760 struct fcp_rsp *rsp; 8761 struct scsi_address save; 8762 8763 #ifdef DEBUG 8764 save = pkt->pkt_address; 8765 #endif /* DEBUG */ 8766 8767 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8768 8769 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8770 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8771 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8772 sizeof (struct fcp_rsp)); 8773 } 8774 8775 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8776 STATE_SENT_CMD | STATE_GOT_STATUS; 8777 8778 pkt->pkt_resid = 0; 8779 8780 if (fpkt->pkt_datalen) { 8781 pkt->pkt_state |= STATE_XFERRED_DATA; 8782 if (fpkt->pkt_data_resid) { 8783 error++; 8784 } 8785 } 8786 8787 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8788 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8789 /* 8790 * The next two checks make sure that if there 8791 * is no sense data or a valid response and 8792 * the command came back with check condition, 8793 * the command should be retried. 8794 */ 8795 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8796 !rsp->fcp_u.fcp_status.sense_len_set) { 8797 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8798 pkt->pkt_resid = cmd->cmd_dmacount; 8799 } 8800 } 8801 8802 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8803 return; 8804 } 8805 8806 plun = ADDR2LUN(&pkt->pkt_address); 8807 ptgt = plun->lun_tgt; 8808 ASSERT(ptgt != NULL); 8809 8810 /* 8811 * Update the transfer resid, if appropriate 8812 */ 8813 if (rsp->fcp_u.fcp_status.resid_over || 8814 rsp->fcp_u.fcp_status.resid_under) { 8815 pkt->pkt_resid = rsp->fcp_resid; 8816 } 8817 8818 /* 8819 * First see if we got a FCP protocol error. 8820 */ 8821 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8822 struct fcp_rsp_info *bep; 8823 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8824 sizeof (struct fcp_rsp)); 8825 8826 if (fcp_validate_fcp_response(rsp, pptr) != 8827 FC_SUCCESS) { 8828 pkt->pkt_reason = CMD_CMPLT; 8829 *(pkt->pkt_scbp) = STATUS_CHECK; 8830 8831 fcp_log(CE_WARN, pptr->port_dip, 8832 "!SCSI command to d_id=0x%x lun=0x%x" 8833 " failed, Bad FCP response values:" 8834 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8835 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8836 ptgt->tgt_d_id, plun->lun_num, 8837 rsp->reserved_0, rsp->reserved_1, 8838 rsp->fcp_u.fcp_status.reserved_0, 8839 rsp->fcp_u.fcp_status.reserved_1, 8840 rsp->fcp_response_len, rsp->fcp_sense_len); 8841 8842 return; 8843 } 8844 8845 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8846 FCP_CP_IN(fpkt->pkt_resp + 8847 sizeof (struct fcp_rsp), bep, 8848 fpkt->pkt_resp_acc, 8849 sizeof (struct fcp_rsp_info)); 8850 } 8851 8852 if (bep->rsp_code != FCP_NO_FAILURE) { 8853 child_info_t *cip; 8854 8855 pkt->pkt_reason = CMD_TRAN_ERR; 8856 8857 mutex_enter(&plun->lun_mutex); 8858 cip = plun->lun_cip; 8859 mutex_exit(&plun->lun_mutex); 8860 8861 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8862 fcp_trace, FCP_BUF_LEVEL_2, 0, 8863 "FCP response error on cmd=%p" 8864 " target=0x%x, cip=%p", cmd, 8865 ptgt->tgt_d_id, cip); 8866 } 8867 } 8868 8869 /* 8870 * See if we got a SCSI error with sense data 8871 */ 8872 if (rsp->fcp_u.fcp_status.sense_len_set) { 8873 uchar_t rqlen; 8874 caddr_t sense_from; 8875 child_info_t *cip; 8876 timeout_id_t tid; 8877 struct scsi_arq_status *arq; 8878 struct scsi_extended_sense *sense_to; 8879 8880 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8881 sense_to = &arq->sts_sensedata; 8882 8883 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8884 sizeof (struct scsi_extended_sense)); 8885 8886 sense_from = (caddr_t)fpkt->pkt_resp + 8887 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8888 8889 if (fcp_validate_fcp_response(rsp, pptr) != 8890 FC_SUCCESS) { 8891 pkt->pkt_reason = CMD_CMPLT; 8892 *(pkt->pkt_scbp) = STATUS_CHECK; 8893 8894 fcp_log(CE_WARN, pptr->port_dip, 8895 "!SCSI command to d_id=0x%x lun=0x%x" 8896 " failed, Bad FCP response values:" 8897 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8898 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8899 ptgt->tgt_d_id, plun->lun_num, 8900 rsp->reserved_0, rsp->reserved_1, 8901 rsp->fcp_u.fcp_status.reserved_0, 8902 rsp->fcp_u.fcp_status.reserved_1, 8903 rsp->fcp_response_len, rsp->fcp_sense_len); 8904 8905 return; 8906 } 8907 8908 /* 8909 * copy in sense information 8910 */ 8911 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8912 FCP_CP_IN(sense_from, sense_to, 8913 fpkt->pkt_resp_acc, rqlen); 8914 } else { 8915 bcopy(sense_from, sense_to, rqlen); 8916 } 8917 8918 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8919 (FCP_SENSE_NO_LUN(sense_to))) { 8920 mutex_enter(&ptgt->tgt_mutex); 8921 if (ptgt->tgt_tid == NULL) { 8922 /* 8923 * Kick off rediscovery 8924 */ 8925 tid = timeout(fcp_reconfigure_luns, 8926 (caddr_t)ptgt, drv_usectohz(1)); 8927 8928 ptgt->tgt_tid = tid; 8929 ptgt->tgt_state |= FCP_TGT_BUSY; 8930 } 8931 mutex_exit(&ptgt->tgt_mutex); 8932 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8933 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8934 fcp_trace, FCP_BUF_LEVEL_3, 0, 8935 "!FCP: Report Lun Has Changed" 8936 " target=%x", ptgt->tgt_d_id); 8937 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8938 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8939 fcp_trace, FCP_BUF_LEVEL_3, 0, 8940 "!FCP: LU Not Supported" 8941 " target=%x", ptgt->tgt_d_id); 8942 } 8943 } 8944 ASSERT(pkt->pkt_scbp != NULL); 8945 8946 pkt->pkt_state |= STATE_ARQ_DONE; 8947 8948 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8949 8950 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8951 arq->sts_rqpkt_reason = 0; 8952 arq->sts_rqpkt_statistics = 0; 8953 8954 arq->sts_rqpkt_state = STATE_GOT_BUS | 8955 STATE_GOT_TARGET | STATE_SENT_CMD | 8956 STATE_GOT_STATUS | STATE_ARQ_DONE | 8957 STATE_XFERRED_DATA; 8958 8959 mutex_enter(&plun->lun_mutex); 8960 cip = plun->lun_cip; 8961 mutex_exit(&plun->lun_mutex); 8962 8963 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8964 fcp_trace, FCP_BUF_LEVEL_8, 0, 8965 "SCSI Check condition on cmd=%p target=0x%x" 8966 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8967 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8968 cmd->cmd_fcp_cmd.fcp_cdb[0], 8969 rsp->fcp_u.fcp_status.scsi_status, 8970 sense_to->es_key, sense_to->es_add_code, 8971 sense_to->es_qual_code); 8972 } 8973 } else { 8974 plun = ADDR2LUN(&pkt->pkt_address); 8975 ptgt = plun->lun_tgt; 8976 ASSERT(ptgt != NULL); 8977 8978 /* 8979 * Work harder to translate errors into target driver 8980 * understandable ones. Note with despair that the target 8981 * drivers don't decode pkt_state and pkt_reason exhaustively 8982 * They resort to using the big hammer most often, which 8983 * may not get fixed in the life time of this driver. 8984 */ 8985 pkt->pkt_state = 0; 8986 pkt->pkt_statistics = 0; 8987 8988 switch (fpkt->pkt_state) { 8989 case FC_PKT_TRAN_ERROR: 8990 switch (fpkt->pkt_reason) { 8991 case FC_REASON_OVERRUN: 8992 pkt->pkt_reason = CMD_CMD_OVR; 8993 pkt->pkt_statistics |= STAT_ABORTED; 8994 break; 8995 8996 case FC_REASON_XCHG_BSY: { 8997 caddr_t ptr; 8998 8999 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9000 9001 ptr = (caddr_t)pkt->pkt_scbp; 9002 if (ptr) { 9003 *ptr = STATUS_BUSY; 9004 } 9005 break; 9006 } 9007 9008 case FC_REASON_ABORTED: 9009 pkt->pkt_reason = CMD_TRAN_ERR; 9010 pkt->pkt_statistics |= STAT_ABORTED; 9011 break; 9012 9013 case FC_REASON_ABORT_FAILED: 9014 pkt->pkt_reason = CMD_ABORT_FAIL; 9015 break; 9016 9017 case FC_REASON_NO_SEQ_INIT: 9018 case FC_REASON_CRC_ERROR: 9019 pkt->pkt_reason = CMD_TRAN_ERR; 9020 pkt->pkt_statistics |= STAT_ABORTED; 9021 break; 9022 default: 9023 pkt->pkt_reason = CMD_TRAN_ERR; 9024 break; 9025 } 9026 break; 9027 9028 case FC_PKT_PORT_OFFLINE: { 9029 dev_info_t *cdip = NULL; 9030 caddr_t ptr; 9031 9032 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9033 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9034 fcp_trace, FCP_BUF_LEVEL_8, 0, 9035 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9036 ptgt->tgt_d_id); 9037 } 9038 9039 mutex_enter(&plun->lun_mutex); 9040 if (plun->lun_mpxio == 0) { 9041 cdip = DIP(plun->lun_cip); 9042 } else if (plun->lun_cip) { 9043 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9044 } 9045 9046 mutex_exit(&plun->lun_mutex); 9047 9048 if (cdip) { 9049 (void) ndi_event_retrieve_cookie( 9050 pptr->port_ndi_event_hdl, cdip, 9051 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9052 NDI_EVENT_NOPASS); 9053 (void) ndi_event_run_callbacks( 9054 pptr->port_ndi_event_hdl, cdip, 9055 fcp_remove_eid, NULL); 9056 } 9057 9058 /* 9059 * If the link goes off-line for a lip, 9060 * this will cause a error to the ST SG 9061 * SGEN drivers. By setting BUSY we will 9062 * give the drivers the chance to retry 9063 * before it blows of the job. ST will 9064 * remember how many times it has retried. 9065 */ 9066 9067 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9068 (plun->lun_type == DTYPE_CHANGER)) { 9069 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9070 ptr = (caddr_t)pkt->pkt_scbp; 9071 if (ptr) { 9072 *ptr = STATUS_BUSY; 9073 } 9074 } else { 9075 pkt->pkt_reason = CMD_TRAN_ERR; 9076 pkt->pkt_statistics |= STAT_BUS_RESET; 9077 } 9078 break; 9079 } 9080 9081 case FC_PKT_TRAN_BSY: 9082 /* 9083 * Use the ssd Qfull handling here. 9084 */ 9085 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9086 pkt->pkt_state = STATE_GOT_BUS; 9087 break; 9088 9089 case FC_PKT_TIMEOUT: 9090 pkt->pkt_reason = CMD_TIMEOUT; 9091 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9092 pkt->pkt_statistics |= STAT_TIMEOUT; 9093 } else { 9094 pkt->pkt_statistics |= STAT_ABORTED; 9095 } 9096 break; 9097 9098 case FC_PKT_LOCAL_RJT: 9099 switch (fpkt->pkt_reason) { 9100 case FC_REASON_OFFLINE: { 9101 dev_info_t *cdip = NULL; 9102 9103 mutex_enter(&plun->lun_mutex); 9104 if (plun->lun_mpxio == 0) { 9105 cdip = DIP(plun->lun_cip); 9106 } else if (plun->lun_cip) { 9107 cdip = mdi_pi_get_client( 9108 PIP(plun->lun_cip)); 9109 } 9110 mutex_exit(&plun->lun_mutex); 9111 9112 if (cdip) { 9113 (void) ndi_event_retrieve_cookie( 9114 pptr->port_ndi_event_hdl, cdip, 9115 FCAL_REMOVE_EVENT, 9116 &fcp_remove_eid, 9117 NDI_EVENT_NOPASS); 9118 (void) ndi_event_run_callbacks( 9119 pptr->port_ndi_event_hdl, 9120 cdip, fcp_remove_eid, NULL); 9121 } 9122 9123 pkt->pkt_reason = CMD_TRAN_ERR; 9124 pkt->pkt_statistics |= STAT_BUS_RESET; 9125 9126 break; 9127 } 9128 9129 case FC_REASON_NOMEM: 9130 case FC_REASON_QFULL: { 9131 caddr_t ptr; 9132 9133 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9134 ptr = (caddr_t)pkt->pkt_scbp; 9135 if (ptr) { 9136 *ptr = STATUS_BUSY; 9137 } 9138 break; 9139 } 9140 9141 case FC_REASON_DMA_ERROR: 9142 pkt->pkt_reason = CMD_DMA_DERR; 9143 pkt->pkt_statistics |= STAT_ABORTED; 9144 break; 9145 9146 case FC_REASON_CRC_ERROR: 9147 case FC_REASON_UNDERRUN: { 9148 uchar_t status; 9149 /* 9150 * Work around for Bugid: 4240945. 9151 * IB on A5k doesn't set the Underrun bit 9152 * in the fcp status, when it is transferring 9153 * less than requested amount of data. Work 9154 * around the ses problem to keep luxadm 9155 * happy till ibfirmware is fixed. 9156 */ 9157 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9158 FCP_CP_IN(fpkt->pkt_resp, rsp, 9159 fpkt->pkt_resp_acc, 9160 sizeof (struct fcp_rsp)); 9161 } 9162 status = rsp->fcp_u.fcp_status.scsi_status; 9163 if (((plun->lun_type & DTYPE_MASK) == 9164 DTYPE_ESI) && (status == STATUS_GOOD)) { 9165 pkt->pkt_reason = CMD_CMPLT; 9166 *pkt->pkt_scbp = status; 9167 pkt->pkt_resid = 0; 9168 } else { 9169 pkt->pkt_reason = CMD_TRAN_ERR; 9170 pkt->pkt_statistics |= STAT_ABORTED; 9171 } 9172 break; 9173 } 9174 9175 case FC_REASON_NO_CONNECTION: 9176 case FC_REASON_UNSUPPORTED: 9177 case FC_REASON_ILLEGAL_REQ: 9178 case FC_REASON_BAD_SID: 9179 case FC_REASON_DIAG_BUSY: 9180 case FC_REASON_FCAL_OPN_FAIL: 9181 case FC_REASON_BAD_XID: 9182 default: 9183 pkt->pkt_reason = CMD_TRAN_ERR; 9184 pkt->pkt_statistics |= STAT_ABORTED; 9185 break; 9186 9187 } 9188 break; 9189 9190 case FC_PKT_NPORT_RJT: 9191 case FC_PKT_FABRIC_RJT: 9192 case FC_PKT_NPORT_BSY: 9193 case FC_PKT_FABRIC_BSY: 9194 default: 9195 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9196 fcp_trace, FCP_BUF_LEVEL_8, 0, 9197 "FC Status 0x%x, reason 0x%x", 9198 fpkt->pkt_state, fpkt->pkt_reason); 9199 pkt->pkt_reason = CMD_TRAN_ERR; 9200 pkt->pkt_statistics |= STAT_ABORTED; 9201 break; 9202 } 9203 9204 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9205 fcp_trace, FCP_BUF_LEVEL_9, 0, 9206 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9207 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9208 fpkt->pkt_reason); 9209 } 9210 9211 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9212 } 9213 9214 9215 static int 9216 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9217 { 9218 if (rsp->reserved_0 || rsp->reserved_1 || 9219 rsp->fcp_u.fcp_status.reserved_0 || 9220 rsp->fcp_u.fcp_status.reserved_1) { 9221 /* 9222 * These reserved fields should ideally be zero. FCP-2 does say 9223 * that the recipient need not check for reserved fields to be 9224 * zero. If they are not zero, we will not make a fuss about it 9225 * - just log it (in debug to both trace buffer and messages 9226 * file and to trace buffer only in non-debug) and move on. 9227 * 9228 * Non-zero reserved fields were seen with minnows. 9229 * 9230 * qlc takes care of some of this but we cannot assume that all 9231 * FCAs will do so. 9232 */ 9233 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9234 FCP_BUF_LEVEL_5, 0, 9235 "Got fcp response packet with non-zero reserved fields " 9236 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9237 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9238 rsp->reserved_0, rsp->reserved_1, 9239 rsp->fcp_u.fcp_status.reserved_0, 9240 rsp->fcp_u.fcp_status.reserved_1); 9241 } 9242 9243 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9244 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9245 return (FC_FAILURE); 9246 } 9247 9248 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9249 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9250 sizeof (struct fcp_rsp))) { 9251 return (FC_FAILURE); 9252 } 9253 9254 return (FC_SUCCESS); 9255 } 9256 9257 9258 /* 9259 * This is called when there is a change the in device state. The case we're 9260 * handling here is, if the d_id s does not match, offline this tgt and online 9261 * a new tgt with the new d_id. called from fcp_handle_devices with 9262 * port_mutex held. 9263 */ 9264 static int 9265 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9266 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9267 { 9268 ASSERT(mutex_owned(&pptr->port_mutex)); 9269 9270 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9271 fcp_trace, FCP_BUF_LEVEL_3, 0, 9272 "Starting fcp_device_changed..."); 9273 9274 /* 9275 * The two cases where the port_device_changed is called is 9276 * either it changes it's d_id or it's hard address. 9277 */ 9278 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9279 (FC_TOP_EXTERNAL(pptr->port_topology) && 9280 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9281 9282 /* offline this target */ 9283 mutex_enter(&ptgt->tgt_mutex); 9284 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9285 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9286 0, 1, NDI_DEVI_REMOVE); 9287 } 9288 mutex_exit(&ptgt->tgt_mutex); 9289 9290 fcp_log(CE_NOTE, pptr->port_dip, 9291 "Change in target properties: Old D_ID=%x New D_ID=%x" 9292 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9293 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9294 map_entry->map_hard_addr.hard_addr); 9295 } 9296 9297 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9298 link_cnt, tgt_cnt, cause)); 9299 } 9300 9301 /* 9302 * Function: fcp_alloc_lun 9303 * 9304 * Description: Creates a new lun structure and adds it to the list 9305 * of luns of the target. 9306 * 9307 * Argument: ptgt Target the lun will belong to. 9308 * 9309 * Return Value: NULL Failed 9310 * Not NULL Succeeded 9311 * 9312 * Context: Kernel context 9313 */ 9314 static struct fcp_lun * 9315 fcp_alloc_lun(struct fcp_tgt *ptgt) 9316 { 9317 struct fcp_lun *plun; 9318 9319 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9320 if (plun != NULL) { 9321 /* 9322 * Initialize the mutex before putting in the target list 9323 * especially before releasing the target mutex. 9324 */ 9325 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9326 plun->lun_tgt = ptgt; 9327 9328 mutex_enter(&ptgt->tgt_mutex); 9329 plun->lun_next = ptgt->tgt_lun; 9330 ptgt->tgt_lun = plun; 9331 plun->lun_old_guid = NULL; 9332 plun->lun_old_guid_size = 0; 9333 mutex_exit(&ptgt->tgt_mutex); 9334 } 9335 9336 return (plun); 9337 } 9338 9339 /* 9340 * Function: fcp_dealloc_lun 9341 * 9342 * Description: Frees the LUN structure passed by the caller. 9343 * 9344 * Argument: plun LUN structure to free. 9345 * 9346 * Return Value: None 9347 * 9348 * Context: Kernel context. 9349 */ 9350 static void 9351 fcp_dealloc_lun(struct fcp_lun *plun) 9352 { 9353 mutex_enter(&plun->lun_mutex); 9354 if (plun->lun_cip) { 9355 fcp_remove_child(plun); 9356 } 9357 mutex_exit(&plun->lun_mutex); 9358 9359 mutex_destroy(&plun->lun_mutex); 9360 if (plun->lun_guid) { 9361 kmem_free(plun->lun_guid, plun->lun_guid_size); 9362 } 9363 if (plun->lun_old_guid) { 9364 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9365 } 9366 kmem_free(plun, sizeof (*plun)); 9367 } 9368 9369 /* 9370 * Function: fcp_alloc_tgt 9371 * 9372 * Description: Creates a new target structure and adds it to the port 9373 * hash list. 9374 * 9375 * Argument: pptr fcp port structure 9376 * *map_entry entry describing the target to create 9377 * link_cnt Link state change counter 9378 * 9379 * Return Value: NULL Failed 9380 * Not NULL Succeeded 9381 * 9382 * Context: Kernel context. 9383 */ 9384 static struct fcp_tgt * 9385 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9386 { 9387 int hash; 9388 uchar_t *wwn; 9389 struct fcp_tgt *ptgt; 9390 9391 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9392 if (ptgt != NULL) { 9393 mutex_enter(&pptr->port_mutex); 9394 if (link_cnt != pptr->port_link_cnt) { 9395 /* 9396 * oh oh -- another link reset 9397 * in progress -- give up 9398 */ 9399 mutex_exit(&pptr->port_mutex); 9400 kmem_free(ptgt, sizeof (*ptgt)); 9401 ptgt = NULL; 9402 } else { 9403 /* 9404 * initialize the mutex before putting in the port 9405 * wwn list, especially before releasing the port 9406 * mutex. 9407 */ 9408 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9409 9410 /* add new target entry to the port's hash list */ 9411 wwn = (uchar_t *)&map_entry->map_pwwn; 9412 hash = FCP_HASH(wwn); 9413 9414 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9415 pptr->port_tgt_hash_table[hash] = ptgt; 9416 9417 /* save cross-ptr */ 9418 ptgt->tgt_port = pptr; 9419 9420 ptgt->tgt_change_cnt = 1; 9421 9422 /* initialize the target manual_config_only flag */ 9423 if (fcp_enable_auto_configuration) { 9424 ptgt->tgt_manual_config_only = 0; 9425 } else { 9426 ptgt->tgt_manual_config_only = 1; 9427 } 9428 9429 mutex_exit(&pptr->port_mutex); 9430 } 9431 } 9432 9433 return (ptgt); 9434 } 9435 9436 /* 9437 * Function: fcp_dealloc_tgt 9438 * 9439 * Description: Frees the target structure passed by the caller. 9440 * 9441 * Argument: ptgt Target structure to free. 9442 * 9443 * Return Value: None 9444 * 9445 * Context: Kernel context. 9446 */ 9447 static void 9448 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9449 { 9450 mutex_destroy(&ptgt->tgt_mutex); 9451 kmem_free(ptgt, sizeof (*ptgt)); 9452 } 9453 9454 9455 /* 9456 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9457 * 9458 * Device discovery commands will not be retried for-ever as 9459 * this will have repercussions on other devices that need to 9460 * be submitted to the hotplug thread. After a quick glance 9461 * at the SCSI-3 spec, it was found that the spec doesn't 9462 * mandate a forever retry, rather recommends a delayed retry. 9463 * 9464 * Since Photon IB is single threaded, STATUS_BUSY is common 9465 * in a 4+initiator environment. Make sure the total time 9466 * spent on retries (including command timeout) does not 9467 * 60 seconds 9468 */ 9469 static void 9470 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9471 { 9472 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9473 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9474 9475 mutex_enter(&pptr->port_mutex); 9476 mutex_enter(&ptgt->tgt_mutex); 9477 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9478 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9479 fcp_trace, FCP_BUF_LEVEL_2, 0, 9480 "fcp_queue_ipkt,1:state change occured" 9481 " for D_ID=0x%x", ptgt->tgt_d_id); 9482 mutex_exit(&ptgt->tgt_mutex); 9483 mutex_exit(&pptr->port_mutex); 9484 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9485 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9486 fcp_icmd_free(pptr, icmd); 9487 return; 9488 } 9489 mutex_exit(&ptgt->tgt_mutex); 9490 9491 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9492 9493 if (pptr->port_ipkt_list != NULL) { 9494 /* add pkt to front of doubly-linked list */ 9495 pptr->port_ipkt_list->ipkt_prev = icmd; 9496 icmd->ipkt_next = pptr->port_ipkt_list; 9497 pptr->port_ipkt_list = icmd; 9498 icmd->ipkt_prev = NULL; 9499 } else { 9500 /* this is the first/only pkt on the list */ 9501 pptr->port_ipkt_list = icmd; 9502 icmd->ipkt_next = NULL; 9503 icmd->ipkt_prev = NULL; 9504 } 9505 mutex_exit(&pptr->port_mutex); 9506 } 9507 9508 /* 9509 * Function: fcp_transport 9510 * 9511 * Description: This function submits the Fibre Channel packet to the transort 9512 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9513 * fails the submission, the treatment depends on the value of 9514 * the variable internal. 9515 * 9516 * Argument: port_handle fp/fctl port handle. 9517 * *fpkt Packet to submit to the transport layer. 9518 * internal Not zero when it's an internal packet. 9519 * 9520 * Return Value: FC_TRAN_BUSY 9521 * FC_STATEC_BUSY 9522 * FC_OFFLINE 9523 * FC_LOGINREQ 9524 * FC_DEVICE_BUSY 9525 * FC_SUCCESS 9526 */ 9527 static int 9528 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9529 { 9530 int rval; 9531 9532 rval = fc_ulp_transport(port_handle, fpkt); 9533 if (rval == FC_SUCCESS) { 9534 return (rval); 9535 } 9536 9537 /* 9538 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9539 * a command, if the underlying modules see that there is a state 9540 * change, or if a port is OFFLINE, that means, that state change 9541 * hasn't reached FCP yet, so re-queue the command for deferred 9542 * submission. 9543 */ 9544 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9545 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9546 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9547 /* 9548 * Defer packet re-submission. Life hang is possible on 9549 * internal commands if the port driver sends FC_STATEC_BUSY 9550 * for ever, but that shouldn't happen in a good environment. 9551 * Limiting re-transport for internal commands is probably a 9552 * good idea.. 9553 * A race condition can happen when a port sees barrage of 9554 * link transitions offline to online. If the FCTL has 9555 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9556 * internal commands should be queued to do the discovery. 9557 * The race condition is when an online comes and FCP starts 9558 * its internal discovery and the link goes offline. It is 9559 * possible that the statec_callback has not reached FCP 9560 * and FCP is carrying on with its internal discovery. 9561 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9562 * that the link has gone offline. At this point FCP should 9563 * drop all the internal commands and wait for the 9564 * statec_callback. It will be facilitated by incrementing 9565 * port_link_cnt. 9566 * 9567 * For external commands, the (FC)pkt_timeout is decremented 9568 * by the QUEUE Delay added by our driver, Care is taken to 9569 * ensure that it doesn't become zero (zero means no timeout) 9570 * If the time expires right inside driver queue itself, 9571 * the watch thread will return it to the original caller 9572 * indicating that the command has timed-out. 9573 */ 9574 if (internal) { 9575 char *op; 9576 struct fcp_ipkt *icmd; 9577 9578 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9579 switch (icmd->ipkt_opcode) { 9580 case SCMD_REPORT_LUN: 9581 op = "REPORT LUN"; 9582 break; 9583 9584 case SCMD_INQUIRY: 9585 op = "INQUIRY"; 9586 break; 9587 9588 case SCMD_INQUIRY_PAGE83: 9589 op = "INQUIRY-83"; 9590 break; 9591 9592 default: 9593 op = "Internal SCSI COMMAND"; 9594 break; 9595 } 9596 9597 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9598 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9599 rval = FC_SUCCESS; 9600 } 9601 } else { 9602 struct fcp_pkt *cmd; 9603 struct fcp_port *pptr; 9604 9605 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9606 cmd->cmd_state = FCP_PKT_IDLE; 9607 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9608 9609 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9610 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9611 fcp_trace, FCP_BUF_LEVEL_9, 0, 9612 "fcp_transport: xport busy for pkt %p", 9613 cmd->cmd_pkt); 9614 rval = FC_TRAN_BUSY; 9615 } else { 9616 fcp_queue_pkt(pptr, cmd); 9617 rval = FC_SUCCESS; 9618 } 9619 } 9620 } 9621 9622 return (rval); 9623 } 9624 9625 /*VARARGS3*/ 9626 static void 9627 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9628 { 9629 char buf[256]; 9630 va_list ap; 9631 9632 if (dip == NULL) { 9633 dip = fcp_global_dip; 9634 } 9635 9636 va_start(ap, fmt); 9637 (void) vsprintf(buf, fmt, ap); 9638 va_end(ap); 9639 9640 scsi_log(dip, "fcp", level, buf); 9641 } 9642 9643 /* 9644 * This function retries NS registry of FC4 type. 9645 * It assumes that fcp_mutex is held. 9646 * The function does nothing if topology is not fabric 9647 * So, the topology has to be set before this function can be called 9648 */ 9649 static void 9650 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9651 { 9652 int rval; 9653 9654 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9655 9656 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9657 ((pptr->port_topology != FC_TOP_FABRIC) && 9658 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9659 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9660 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9661 } 9662 return; 9663 } 9664 mutex_exit(&pptr->port_mutex); 9665 rval = fcp_do_ns_registry(pptr, s_id); 9666 mutex_enter(&pptr->port_mutex); 9667 9668 if (rval == 0) { 9669 /* Registry successful. Reset flag */ 9670 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9671 } 9672 } 9673 9674 /* 9675 * This function registers the ULP with the switch by calling transport i/f 9676 */ 9677 static int 9678 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9679 { 9680 fc_ns_cmd_t ns_cmd; 9681 ns_rfc_type_t rfc; 9682 uint32_t types[8]; 9683 9684 /* 9685 * Prepare the Name server structure to 9686 * register with the transport in case of 9687 * Fabric configuration. 9688 */ 9689 bzero(&rfc, sizeof (rfc)); 9690 bzero(types, sizeof (types)); 9691 9692 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9693 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9694 9695 rfc.rfc_port_id.port_id = s_id; 9696 bcopy(types, rfc.rfc_types, sizeof (types)); 9697 9698 ns_cmd.ns_flags = 0; 9699 ns_cmd.ns_cmd = NS_RFT_ID; 9700 ns_cmd.ns_req_len = sizeof (rfc); 9701 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9702 ns_cmd.ns_resp_len = 0; 9703 ns_cmd.ns_resp_payload = NULL; 9704 9705 /* 9706 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9707 */ 9708 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9709 fcp_log(CE_WARN, pptr->port_dip, 9710 "!ns_registry: failed name server registration"); 9711 return (1); 9712 } 9713 9714 return (0); 9715 } 9716 9717 /* 9718 * Function: fcp_handle_port_attach 9719 * 9720 * Description: This function is called from fcp_port_attach() to attach a 9721 * new port. This routine does the following: 9722 * 9723 * 1) Allocates an fcp_port structure and initializes it. 9724 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9725 * server. 9726 * 3) Kicks off the enumeration of the targets/luns visible 9727 * through this new port. That is done by calling 9728 * fcp_statec_callback() if the port is online. 9729 * 9730 * Argument: ulph fp/fctl port handle. 9731 * *pinfo Port information. 9732 * s_id Port ID. 9733 * instance Device instance number for the local port 9734 * (returned by ddi_get_instance()). 9735 * 9736 * Return Value: DDI_SUCCESS 9737 * DDI_FAILURE 9738 * 9739 * Context: User and Kernel context. 9740 */ 9741 /*ARGSUSED*/ 9742 int 9743 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9744 uint32_t s_id, int instance) 9745 { 9746 int res = DDI_FAILURE; 9747 scsi_hba_tran_t *tran; 9748 int mutex_initted = FALSE; 9749 int hba_attached = FALSE; 9750 int soft_state_linked = FALSE; 9751 int event_bind = FALSE; 9752 struct fcp_port *pptr; 9753 fc_portmap_t *tmp_list = NULL; 9754 uint32_t max_cnt, alloc_cnt; 9755 uchar_t *boot_wwn = NULL; 9756 uint_t nbytes; 9757 int manual_cfg; 9758 9759 /* 9760 * this port instance attaching for the first time (or after 9761 * being detached before) 9762 */ 9763 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9764 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9765 9766 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9767 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9768 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9769 instance); 9770 return (res); 9771 } 9772 9773 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9774 /* this shouldn't happen */ 9775 ddi_soft_state_free(fcp_softstate, instance); 9776 cmn_err(CE_WARN, "fcp: bad soft state"); 9777 return (res); 9778 } 9779 9780 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9781 9782 /* 9783 * Make a copy of ulp_port_info as fctl allocates 9784 * a temp struct. 9785 */ 9786 (void) fcp_cp_pinfo(pptr, pinfo); 9787 9788 /* 9789 * Check for manual_configuration_only property. 9790 * Enable manual configurtion if the property is 9791 * set to 1, otherwise disable manual configuration. 9792 */ 9793 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9794 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9795 MANUAL_CFG_ONLY, 9796 -1)) != -1) { 9797 if (manual_cfg == 1) { 9798 char *pathname; 9799 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9800 (void) ddi_pathname(pptr->port_dip, pathname); 9801 cmn_err(CE_NOTE, 9802 "%s (%s%d) %s is enabled via %s.conf.", 9803 pathname, 9804 ddi_driver_name(pptr->port_dip), 9805 ddi_get_instance(pptr->port_dip), 9806 MANUAL_CFG_ONLY, 9807 ddi_driver_name(pptr->port_dip)); 9808 fcp_enable_auto_configuration = 0; 9809 kmem_free(pathname, MAXPATHLEN); 9810 } 9811 } 9812 pptr->port_link_cnt = 1; 9813 pptr->port_id = s_id; 9814 pptr->port_instance = instance; 9815 pptr->port_state = FCP_STATE_INIT; 9816 if (pinfo->port_acc_attr == NULL) { 9817 /* 9818 * The corresponding FCA doesn't support DMA at all 9819 */ 9820 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9821 } 9822 9823 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9824 /* 9825 * If FCA supports DMA in SCSI data phase, we need preallocate 9826 * dma cookie, so stash the cookie size 9827 */ 9828 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9829 pptr->port_data_dma_attr.dma_attr_sgllen; 9830 } 9831 9832 /* 9833 * The two mutexes of fcp_port are initialized. The variable 9834 * mutex_initted is incremented to remember that fact. That variable 9835 * is checked when the routine fails and the mutexes have to be 9836 * destroyed. 9837 */ 9838 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9839 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9840 mutex_initted++; 9841 9842 /* 9843 * The SCSI tran structure is allocate and initialized now. 9844 */ 9845 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9846 fcp_log(CE_WARN, pptr->port_dip, 9847 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9848 goto fail; 9849 } 9850 9851 /* link in the transport structure then fill it in */ 9852 pptr->port_tran = tran; 9853 tran->tran_hba_private = pptr; 9854 tran->tran_tgt_init = fcp_scsi_tgt_init; 9855 tran->tran_tgt_probe = NULL; 9856 tran->tran_tgt_free = fcp_scsi_tgt_free; 9857 tran->tran_start = fcp_scsi_start; 9858 tran->tran_reset = fcp_scsi_reset; 9859 tran->tran_abort = fcp_scsi_abort; 9860 tran->tran_getcap = fcp_scsi_getcap; 9861 tran->tran_setcap = fcp_scsi_setcap; 9862 tran->tran_init_pkt = NULL; 9863 tran->tran_destroy_pkt = NULL; 9864 tran->tran_dmafree = NULL; 9865 tran->tran_sync_pkt = NULL; 9866 tran->tran_reset_notify = fcp_scsi_reset_notify; 9867 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9868 tran->tran_get_name = fcp_scsi_get_name; 9869 tran->tran_clear_aca = NULL; 9870 tran->tran_clear_task_set = NULL; 9871 tran->tran_terminate_task = NULL; 9872 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9873 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9874 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9875 tran->tran_post_event = fcp_scsi_bus_post_event; 9876 tran->tran_quiesce = NULL; 9877 tran->tran_unquiesce = NULL; 9878 tran->tran_bus_reset = NULL; 9879 tran->tran_bus_config = fcp_scsi_bus_config; 9880 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9881 tran->tran_bus_power = NULL; 9882 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9883 9884 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9885 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9886 tran->tran_setup_pkt = fcp_pkt_setup; 9887 tran->tran_teardown_pkt = fcp_pkt_teardown; 9888 tran->tran_hba_len = pptr->port_priv_pkt_len + 9889 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9890 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9891 /* 9892 * If FCA don't support DMA, then we use different vectors to 9893 * minimize the effects on DMA code flow path 9894 */ 9895 tran->tran_start = fcp_pseudo_start; 9896 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9897 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9898 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9899 tran->tran_dmafree = fcp_pseudo_dmafree; 9900 tran->tran_setup_pkt = NULL; 9901 tran->tran_teardown_pkt = NULL; 9902 tran->tran_pkt_constructor = NULL; 9903 tran->tran_pkt_destructor = NULL; 9904 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9905 } 9906 9907 /* 9908 * Allocate an ndi event handle 9909 */ 9910 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9911 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9912 9913 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9914 sizeof (fcp_ndi_event_defs)); 9915 9916 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9917 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9918 9919 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9920 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9921 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9922 9923 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9924 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9925 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9926 goto fail; 9927 } 9928 event_bind++; /* Checked in fail case */ 9929 9930 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9931 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9932 != DDI_SUCCESS) { 9933 fcp_log(CE_WARN, pptr->port_dip, 9934 "!fcp%d: scsi_hba_attach_setup failed", instance); 9935 goto fail; 9936 } 9937 hba_attached++; /* Checked in fail case */ 9938 9939 pptr->port_mpxio = 0; 9940 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9941 MDI_SUCCESS) { 9942 pptr->port_mpxio++; 9943 } 9944 9945 /* 9946 * The following code is putting the new port structure in the global 9947 * list of ports and, if it is the first port to attach, it start the 9948 * fcp_watchdog_tick. 9949 * 9950 * Why put this new port in the global before we are done attaching it? 9951 * We are actually making the structure globally known before we are 9952 * done attaching it. The reason for that is: because of the code that 9953 * follows. At this point the resources to handle the port are 9954 * allocated. This function is now going to do the following: 9955 * 9956 * 1) It is going to try to register with the name server advertizing 9957 * the new FCP capability of the port. 9958 * 2) It is going to play the role of the fp/fctl layer by building 9959 * a list of worlwide names reachable through this port and call 9960 * itself on fcp_statec_callback(). That requires the port to 9961 * be part of the global list. 9962 */ 9963 mutex_enter(&fcp_global_mutex); 9964 if (fcp_port_head == NULL) { 9965 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9966 } 9967 pptr->port_next = fcp_port_head; 9968 fcp_port_head = pptr; 9969 soft_state_linked++; 9970 9971 if (fcp_watchdog_init++ == 0) { 9972 fcp_watchdog_tick = fcp_watchdog_timeout * 9973 drv_usectohz(1000000); 9974 fcp_watchdog_id = timeout(fcp_watch, NULL, 9975 fcp_watchdog_tick); 9976 } 9977 mutex_exit(&fcp_global_mutex); 9978 9979 /* 9980 * Here an attempt is made to register with the name server, the new 9981 * FCP capability. That is done using an RTF_ID to the name server. 9982 * It is done synchronously. The function fcp_do_ns_registry() 9983 * doesn't return till the name server responded. 9984 * On failures, just ignore it for now and it will get retried during 9985 * state change callbacks. We'll set a flag to show this failure 9986 */ 9987 if (fcp_do_ns_registry(pptr, s_id)) { 9988 mutex_enter(&pptr->port_mutex); 9989 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 9990 mutex_exit(&pptr->port_mutex); 9991 } else { 9992 mutex_enter(&pptr->port_mutex); 9993 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9994 mutex_exit(&pptr->port_mutex); 9995 } 9996 9997 /* 9998 * Lookup for boot WWN property 9999 */ 10000 if (modrootloaded != 1) { 10001 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 10002 ddi_get_parent(pinfo->port_dip), 10003 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 10004 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 10005 (nbytes == FC_WWN_SIZE)) { 10006 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 10007 } 10008 if (boot_wwn) { 10009 ddi_prop_free(boot_wwn); 10010 } 10011 } 10012 10013 /* 10014 * Handle various topologies and link states. 10015 */ 10016 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10017 case FC_STATE_OFFLINE: 10018 10019 /* 10020 * we're attaching a port where the link is offline 10021 * 10022 * Wait for ONLINE, at which time a state 10023 * change will cause a statec_callback 10024 * 10025 * in the mean time, do not do anything 10026 */ 10027 res = DDI_SUCCESS; 10028 pptr->port_state |= FCP_STATE_OFFLINE; 10029 break; 10030 10031 case FC_STATE_ONLINE: { 10032 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10033 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10034 res = DDI_SUCCESS; 10035 break; 10036 } 10037 /* 10038 * discover devices and create nodes (a private 10039 * loop or point-to-point) 10040 */ 10041 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10042 10043 /* 10044 * At this point we are going to build a list of all the ports 10045 * that can be reached through this local port. It looks like 10046 * we cannot handle more than FCP_MAX_DEVICES per local port 10047 * (128). 10048 */ 10049 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10050 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10051 KM_NOSLEEP)) == NULL) { 10052 fcp_log(CE_WARN, pptr->port_dip, 10053 "!fcp%d: failed to allocate portmap", 10054 instance); 10055 goto fail; 10056 } 10057 10058 /* 10059 * fc_ulp_getportmap() is going to provide us with the list of 10060 * remote ports in the buffer we just allocated. The way the 10061 * list is going to be retrieved depends on the topology. 10062 * However, if we are connected to a Fabric, a name server 10063 * request may be sent to get the list of FCP capable ports. 10064 * It should be noted that is the case the request is 10065 * synchronous. This means we are stuck here till the name 10066 * server replies. A lot of things can change during that time 10067 * and including, may be, being called on 10068 * fcp_statec_callback() for different reasons. I'm not sure 10069 * the code can handle that. 10070 */ 10071 max_cnt = FCP_MAX_DEVICES; 10072 alloc_cnt = FCP_MAX_DEVICES; 10073 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10074 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10075 FC_SUCCESS) { 10076 caddr_t msg; 10077 10078 (void) fc_ulp_error(res, &msg); 10079 10080 /* 10081 * this just means the transport is 10082 * busy perhaps building a portmap so, 10083 * for now, succeed this port attach 10084 * when the transport has a new map, 10085 * it'll send us a state change then 10086 */ 10087 fcp_log(CE_WARN, pptr->port_dip, 10088 "!failed to get port map : %s", msg); 10089 10090 res = DDI_SUCCESS; 10091 break; /* go return result */ 10092 } 10093 if (max_cnt > alloc_cnt) { 10094 alloc_cnt = max_cnt; 10095 } 10096 10097 /* 10098 * We are now going to call fcp_statec_callback() ourselves. 10099 * By issuing this call we are trying to kick off the enumera- 10100 * tion process. 10101 */ 10102 /* 10103 * let the state change callback do the SCSI device 10104 * discovery and create the devinfos 10105 */ 10106 fcp_statec_callback(ulph, pptr->port_fp_handle, 10107 pptr->port_phys_state, pptr->port_topology, tmp_list, 10108 max_cnt, pptr->port_id); 10109 10110 res = DDI_SUCCESS; 10111 break; 10112 } 10113 10114 default: 10115 /* unknown port state */ 10116 fcp_log(CE_WARN, pptr->port_dip, 10117 "!fcp%d: invalid port state at attach=0x%x", 10118 instance, pptr->port_phys_state); 10119 10120 mutex_enter(&pptr->port_mutex); 10121 pptr->port_phys_state = FCP_STATE_OFFLINE; 10122 mutex_exit(&pptr->port_mutex); 10123 10124 res = DDI_SUCCESS; 10125 break; 10126 } 10127 10128 /* free temp list if used */ 10129 if (tmp_list != NULL) { 10130 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10131 } 10132 10133 /* note the attach time */ 10134 pptr->port_attach_time = ddi_get_lbolt64(); 10135 10136 /* all done */ 10137 return (res); 10138 10139 /* a failure we have to clean up after */ 10140 fail: 10141 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10142 10143 if (soft_state_linked) { 10144 /* remove this fcp_port from the linked list */ 10145 (void) fcp_soft_state_unlink(pptr); 10146 } 10147 10148 /* unbind and free event set */ 10149 if (pptr->port_ndi_event_hdl) { 10150 if (event_bind) { 10151 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10152 &pptr->port_ndi_events, NDI_SLEEP); 10153 } 10154 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10155 } 10156 10157 if (pptr->port_ndi_event_defs) { 10158 (void) kmem_free(pptr->port_ndi_event_defs, 10159 sizeof (fcp_ndi_event_defs)); 10160 } 10161 10162 /* 10163 * Clean up mpxio stuff 10164 */ 10165 if (pptr->port_mpxio) { 10166 (void) mdi_phci_unregister(pptr->port_dip, 0); 10167 pptr->port_mpxio--; 10168 } 10169 10170 /* undo SCSI HBA setup */ 10171 if (hba_attached) { 10172 (void) scsi_hba_detach(pptr->port_dip); 10173 } 10174 if (pptr->port_tran != NULL) { 10175 scsi_hba_tran_free(pptr->port_tran); 10176 } 10177 10178 mutex_enter(&fcp_global_mutex); 10179 10180 /* 10181 * We check soft_state_linked, because it is incremented right before 10182 * we call increment fcp_watchdog_init. Therefore, we know if 10183 * soft_state_linked is still FALSE, we do not want to decrement 10184 * fcp_watchdog_init or possibly call untimeout. 10185 */ 10186 10187 if (soft_state_linked) { 10188 if (--fcp_watchdog_init == 0) { 10189 timeout_id_t tid = fcp_watchdog_id; 10190 10191 mutex_exit(&fcp_global_mutex); 10192 (void) untimeout(tid); 10193 } else { 10194 mutex_exit(&fcp_global_mutex); 10195 } 10196 } else { 10197 mutex_exit(&fcp_global_mutex); 10198 } 10199 10200 if (mutex_initted) { 10201 mutex_destroy(&pptr->port_mutex); 10202 mutex_destroy(&pptr->port_pkt_mutex); 10203 } 10204 10205 if (tmp_list != NULL) { 10206 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10207 } 10208 10209 /* this makes pptr invalid */ 10210 ddi_soft_state_free(fcp_softstate, instance); 10211 10212 return (DDI_FAILURE); 10213 } 10214 10215 10216 static int 10217 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10218 { 10219 int count = 0; 10220 10221 mutex_enter(&pptr->port_mutex); 10222 10223 /* 10224 * if the port is powered down or suspended, nothing else 10225 * to do; just return. 10226 */ 10227 if (flag != FCP_STATE_DETACHING) { 10228 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10229 FCP_STATE_SUSPENDED)) { 10230 pptr->port_state |= flag; 10231 mutex_exit(&pptr->port_mutex); 10232 return (FC_SUCCESS); 10233 } 10234 } 10235 10236 if (pptr->port_state & FCP_STATE_IN_MDI) { 10237 mutex_exit(&pptr->port_mutex); 10238 return (FC_FAILURE); 10239 } 10240 10241 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10242 fcp_trace, FCP_BUF_LEVEL_2, 0, 10243 "fcp_handle_port_detach: port is detaching"); 10244 10245 pptr->port_state |= flag; 10246 10247 /* 10248 * Wait for any ongoing reconfig/ipkt to complete, that 10249 * ensures the freeing to targets/luns is safe. 10250 * No more ref to this port should happen from statec/ioctl 10251 * after that as it was removed from the global port list. 10252 */ 10253 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10254 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10255 /* 10256 * Let's give sufficient time for reconfig/ipkt 10257 * to complete. 10258 */ 10259 if (count++ >= FCP_ICMD_DEADLINE) { 10260 break; 10261 } 10262 mutex_exit(&pptr->port_mutex); 10263 delay(drv_usectohz(1000000)); 10264 mutex_enter(&pptr->port_mutex); 10265 } 10266 10267 /* 10268 * if the driver is still busy then fail to 10269 * suspend/power down. 10270 */ 10271 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10272 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10273 pptr->port_state &= ~flag; 10274 mutex_exit(&pptr->port_mutex); 10275 return (FC_FAILURE); 10276 } 10277 10278 if (flag == FCP_STATE_DETACHING) { 10279 pptr = fcp_soft_state_unlink(pptr); 10280 ASSERT(pptr != NULL); 10281 } 10282 10283 pptr->port_link_cnt++; 10284 pptr->port_state |= FCP_STATE_OFFLINE; 10285 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10286 10287 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10288 FCP_CAUSE_LINK_DOWN); 10289 mutex_exit(&pptr->port_mutex); 10290 10291 /* kill watch dog timer if we're the last */ 10292 mutex_enter(&fcp_global_mutex); 10293 if (--fcp_watchdog_init == 0) { 10294 timeout_id_t tid = fcp_watchdog_id; 10295 mutex_exit(&fcp_global_mutex); 10296 (void) untimeout(tid); 10297 } else { 10298 mutex_exit(&fcp_global_mutex); 10299 } 10300 10301 /* clean up the port structures */ 10302 if (flag == FCP_STATE_DETACHING) { 10303 fcp_cleanup_port(pptr, instance); 10304 } 10305 10306 return (FC_SUCCESS); 10307 } 10308 10309 10310 static void 10311 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10312 { 10313 ASSERT(pptr != NULL); 10314 10315 /* unbind and free event set */ 10316 if (pptr->port_ndi_event_hdl) { 10317 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10318 &pptr->port_ndi_events, NDI_SLEEP); 10319 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10320 } 10321 10322 if (pptr->port_ndi_event_defs) { 10323 (void) kmem_free(pptr->port_ndi_event_defs, 10324 sizeof (fcp_ndi_event_defs)); 10325 } 10326 10327 /* free the lun/target structures and devinfos */ 10328 fcp_free_targets(pptr); 10329 10330 /* 10331 * Clean up mpxio stuff 10332 */ 10333 if (pptr->port_mpxio) { 10334 (void) mdi_phci_unregister(pptr->port_dip, 0); 10335 pptr->port_mpxio--; 10336 } 10337 10338 /* clean up SCSA stuff */ 10339 (void) scsi_hba_detach(pptr->port_dip); 10340 if (pptr->port_tran != NULL) { 10341 scsi_hba_tran_free(pptr->port_tran); 10342 } 10343 10344 #ifdef KSTATS_CODE 10345 /* clean up kstats */ 10346 if (pptr->fcp_ksp != NULL) { 10347 kstat_delete(pptr->fcp_ksp); 10348 } 10349 #endif 10350 10351 /* clean up soft state mutexes/condition variables */ 10352 mutex_destroy(&pptr->port_mutex); 10353 mutex_destroy(&pptr->port_pkt_mutex); 10354 10355 /* all done with soft state */ 10356 ddi_soft_state_free(fcp_softstate, instance); 10357 } 10358 10359 /* 10360 * Function: fcp_kmem_cache_constructor 10361 * 10362 * Description: This function allocates and initializes the resources required 10363 * to build a scsi_pkt structure the target driver. The result 10364 * of the allocation and initialization will be cached in the 10365 * memory cache. As DMA resources may be allocated here, that 10366 * means DMA resources will be tied up in the cache manager. 10367 * This is a tradeoff that has been made for performance reasons. 10368 * 10369 * Argument: *buf Memory to preinitialize. 10370 * *arg FCP port structure (fcp_port). 10371 * kmflags Value passed to kmem_cache_alloc() and 10372 * propagated to the constructor. 10373 * 10374 * Return Value: 0 Allocation/Initialization was successful. 10375 * -1 Allocation or Initialization failed. 10376 * 10377 * 10378 * If the returned value is 0, the buffer is initialized like this: 10379 * 10380 * +================================+ 10381 * +----> | struct scsi_pkt | 10382 * | | | 10383 * | +--- | pkt_ha_private | 10384 * | | | | 10385 * | | +================================+ 10386 * | | 10387 * | | +================================+ 10388 * | +--> | struct fcp_pkt | <---------+ 10389 * | | | | 10390 * +----- | cmd_pkt | | 10391 * | cmd_fp_pkt | ---+ | 10392 * +-------->| cmd_fcp_rsp[] | | | 10393 * | +--->| cmd_fcp_cmd[] | | | 10394 * | | |--------------------------------| | | 10395 * | | | struct fc_packet | <--+ | 10396 * | | | | | 10397 * | | | pkt_ulp_private | ----------+ 10398 * | | | pkt_fca_private | -----+ 10399 * | | | pkt_data_cookie | ---+ | 10400 * | | | pkt_cmdlen | | | 10401 * | |(a) | pkt_rsplen | | | 10402 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10403 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10404 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10405 * | pkt_resp_cookie | ---|-|--+ | | | 10406 * | pkt_cmd_dma | | | | | | | 10407 * | pkt_cmd_acc | | | | | | | 10408 * +================================+ | | | | | | 10409 * | dma_cookies | <--+ | | | | | 10410 * | | | | | | | 10411 * +================================+ | | | | | 10412 * | fca_private | <----+ | | | | 10413 * | | | | | | 10414 * +================================+ | | | | 10415 * | | | | 10416 * | | | | 10417 * +================================+ (d) | | | | 10418 * | fcp_resp cookies | <-------+ | | | 10419 * | | | | | 10420 * +================================+ | | | 10421 * | | | 10422 * +================================+ (d) | | | 10423 * | fcp_resp | <-----------+ | | 10424 * | (DMA resources associated) | | | 10425 * +================================+ | | 10426 * | | 10427 * | | 10428 * | | 10429 * +================================+ (c) | | 10430 * | fcp_cmd cookies | <---------------+ | 10431 * | | | 10432 * +================================+ | 10433 * | 10434 * +================================+ (c) | 10435 * | fcp_cmd | <--------------------+ 10436 * | (DMA resources associated) | 10437 * +================================+ 10438 * 10439 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10440 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10441 * (c) Only if DMA is used for the FCP_CMD buffer. 10442 * (d) Only if DMA is used for the FCP_RESP buffer 10443 */ 10444 static int 10445 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10446 int kmflags) 10447 { 10448 struct fcp_pkt *cmd; 10449 struct fcp_port *pptr; 10450 fc_packet_t *fpkt; 10451 10452 pptr = (struct fcp_port *)tran->tran_hba_private; 10453 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10454 bzero(cmd, tran->tran_hba_len); 10455 10456 cmd->cmd_pkt = pkt; 10457 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10458 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10459 cmd->cmd_fp_pkt = fpkt; 10460 10461 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10462 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10463 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10464 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10465 10466 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10467 sizeof (struct fcp_pkt)); 10468 10469 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10470 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10471 10472 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10473 /* 10474 * The underlying HBA doesn't want to DMA the fcp_cmd or 10475 * fcp_resp. The transfer of information will be done by 10476 * bcopy. 10477 * The naming of the flags (that is actually a value) is 10478 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10479 * DMA" but instead "NO DMA". 10480 */ 10481 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10482 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10483 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10484 } else { 10485 /* 10486 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10487 * buffer. A buffer is allocated for each one the ddi_dma_* 10488 * interfaces. 10489 */ 10490 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10491 return (-1); 10492 } 10493 } 10494 10495 return (0); 10496 } 10497 10498 /* 10499 * Function: fcp_kmem_cache_destructor 10500 * 10501 * Description: Called by the destructor of the cache managed by SCSA. 10502 * All the resources pre-allocated in fcp_pkt_constructor 10503 * and the data also pre-initialized in fcp_pkt_constructor 10504 * are freed and uninitialized here. 10505 * 10506 * Argument: *buf Memory to uninitialize. 10507 * *arg FCP port structure (fcp_port). 10508 * 10509 * Return Value: None 10510 * 10511 * Context: kernel 10512 */ 10513 static void 10514 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10515 { 10516 struct fcp_pkt *cmd; 10517 struct fcp_port *pptr; 10518 10519 pptr = (struct fcp_port *)(tran->tran_hba_private); 10520 cmd = pkt->pkt_ha_private; 10521 10522 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10523 /* 10524 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10525 * buffer and DMA resources allocated to do so are released. 10526 */ 10527 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10528 } 10529 } 10530 10531 /* 10532 * Function: fcp_alloc_cmd_resp 10533 * 10534 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10535 * will be DMAed by the HBA. The buffer is allocated applying 10536 * the DMA requirements for the HBA. The buffers allocated will 10537 * also be bound. DMA resources are allocated in the process. 10538 * They will be released by fcp_free_cmd_resp(). 10539 * 10540 * Argument: *pptr FCP port. 10541 * *fpkt fc packet for which the cmd and resp packet should be 10542 * allocated. 10543 * flags Allocation flags. 10544 * 10545 * Return Value: FC_FAILURE 10546 * FC_SUCCESS 10547 * 10548 * Context: User or Kernel context only if flags == KM_SLEEP. 10549 * Interrupt context if the KM_SLEEP is not specified. 10550 */ 10551 static int 10552 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10553 { 10554 int rval; 10555 int cmd_len; 10556 int resp_len; 10557 ulong_t real_len; 10558 int (*cb) (caddr_t); 10559 ddi_dma_cookie_t pkt_cookie; 10560 ddi_dma_cookie_t *cp; 10561 uint32_t cnt; 10562 10563 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10564 10565 cmd_len = fpkt->pkt_cmdlen; 10566 resp_len = fpkt->pkt_rsplen; 10567 10568 ASSERT(fpkt->pkt_cmd_dma == NULL); 10569 10570 /* Allocation of a DMA handle used in subsequent calls. */ 10571 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10572 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10573 return (FC_FAILURE); 10574 } 10575 10576 /* A buffer is allocated that satisfies the DMA requirements. */ 10577 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10578 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10579 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10580 10581 if (rval != DDI_SUCCESS) { 10582 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10583 return (FC_FAILURE); 10584 } 10585 10586 if (real_len < cmd_len) { 10587 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10588 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10589 return (FC_FAILURE); 10590 } 10591 10592 /* The buffer allocated is DMA bound. */ 10593 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10594 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10595 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10596 10597 if (rval != DDI_DMA_MAPPED) { 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 if (fpkt->pkt_cmd_cookie_cnt > 10604 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10605 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10606 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10607 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10608 return (FC_FAILURE); 10609 } 10610 10611 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10612 10613 /* 10614 * The buffer where the scatter/gather list is going to be built is 10615 * allocated. 10616 */ 10617 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10618 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10619 KM_NOSLEEP); 10620 10621 if (cp == NULL) { 10622 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10623 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10624 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10625 return (FC_FAILURE); 10626 } 10627 10628 /* 10629 * The scatter/gather list for the buffer we just allocated is built 10630 * here. 10631 */ 10632 *cp = pkt_cookie; 10633 cp++; 10634 10635 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10636 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10637 &pkt_cookie); 10638 *cp = pkt_cookie; 10639 } 10640 10641 ASSERT(fpkt->pkt_resp_dma == NULL); 10642 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10643 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10644 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10645 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10646 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10647 return (FC_FAILURE); 10648 } 10649 10650 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10651 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10652 (caddr_t *)&fpkt->pkt_resp, &real_len, 10653 &fpkt->pkt_resp_acc); 10654 10655 if (rval != DDI_SUCCESS) { 10656 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10657 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10658 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10659 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10660 kmem_free(fpkt->pkt_cmd_cookie, 10661 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10662 return (FC_FAILURE); 10663 } 10664 10665 if (real_len < resp_len) { 10666 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10667 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10668 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10669 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10670 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10671 kmem_free(fpkt->pkt_cmd_cookie, 10672 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10673 return (FC_FAILURE); 10674 } 10675 10676 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10677 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10678 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10679 10680 if (rval != DDI_DMA_MAPPED) { 10681 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10682 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10683 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10684 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10685 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10686 kmem_free(fpkt->pkt_cmd_cookie, 10687 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10688 return (FC_FAILURE); 10689 } 10690 10691 if (fpkt->pkt_resp_cookie_cnt > 10692 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10693 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10694 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10695 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10696 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10697 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10698 kmem_free(fpkt->pkt_cmd_cookie, 10699 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10700 return (FC_FAILURE); 10701 } 10702 10703 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10704 10705 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10706 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10707 KM_NOSLEEP); 10708 10709 if (cp == NULL) { 10710 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10711 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10712 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10713 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10714 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10715 kmem_free(fpkt->pkt_cmd_cookie, 10716 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10717 return (FC_FAILURE); 10718 } 10719 10720 *cp = pkt_cookie; 10721 cp++; 10722 10723 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10724 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10725 &pkt_cookie); 10726 *cp = pkt_cookie; 10727 } 10728 10729 return (FC_SUCCESS); 10730 } 10731 10732 /* 10733 * Function: fcp_free_cmd_resp 10734 * 10735 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10736 * allocated by fcp_alloc_cmd_resp() and all the resources 10737 * associated with them. That includes the DMA resources and the 10738 * buffer allocated for the cookies of each one of them. 10739 * 10740 * Argument: *pptr FCP port context. 10741 * *fpkt fc packet containing the cmd and resp packet 10742 * to be released. 10743 * 10744 * Return Value: None 10745 * 10746 * Context: Interrupt, User and Kernel context. 10747 */ 10748 /* ARGSUSED */ 10749 static void 10750 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10751 { 10752 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10753 10754 if (fpkt->pkt_resp_dma) { 10755 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10756 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10757 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10758 } 10759 10760 if (fpkt->pkt_resp_cookie) { 10761 kmem_free(fpkt->pkt_resp_cookie, 10762 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10763 fpkt->pkt_resp_cookie = NULL; 10764 } 10765 10766 if (fpkt->pkt_cmd_dma) { 10767 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10768 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10769 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10770 } 10771 10772 if (fpkt->pkt_cmd_cookie) { 10773 kmem_free(fpkt->pkt_cmd_cookie, 10774 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10775 fpkt->pkt_cmd_cookie = NULL; 10776 } 10777 } 10778 10779 10780 /* 10781 * called by the transport to do our own target initialization 10782 * 10783 * can acquire and release the global mutex 10784 */ 10785 /* ARGSUSED */ 10786 static int 10787 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10788 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10789 { 10790 uchar_t *bytes; 10791 uint_t nbytes; 10792 uint16_t lun_num; 10793 struct fcp_tgt *ptgt; 10794 struct fcp_lun *plun; 10795 struct fcp_port *pptr = (struct fcp_port *) 10796 hba_tran->tran_hba_private; 10797 10798 ASSERT(pptr != NULL); 10799 10800 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10801 FCP_BUF_LEVEL_8, 0, 10802 "fcp_phys_tgt_init: called for %s (instance %d)", 10803 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10804 10805 /* get our port WWN property */ 10806 bytes = NULL; 10807 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10808 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10809 (nbytes != FC_WWN_SIZE)) { 10810 /* no port WWN property */ 10811 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10812 FCP_BUF_LEVEL_8, 0, 10813 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10814 " for %s (instance %d): bytes=%p nbytes=%x", 10815 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10816 nbytes); 10817 10818 if (bytes != NULL) { 10819 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10820 } 10821 10822 return (DDI_NOT_WELL_FORMED); 10823 } 10824 ASSERT(bytes != NULL); 10825 10826 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10827 LUN_PROP, 0xFFFF); 10828 if (lun_num == 0xFFFF) { 10829 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10830 FCP_BUF_LEVEL_8, 0, 10831 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10832 " for %s (instance %d)", ddi_get_name(tgt_dip), 10833 ddi_get_instance(tgt_dip)); 10834 10835 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10836 return (DDI_NOT_WELL_FORMED); 10837 } 10838 10839 mutex_enter(&pptr->port_mutex); 10840 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10841 mutex_exit(&pptr->port_mutex); 10842 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10843 FCP_BUF_LEVEL_8, 0, 10844 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10845 " for %s (instance %d)", ddi_get_name(tgt_dip), 10846 ddi_get_instance(tgt_dip)); 10847 10848 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10849 return (DDI_FAILURE); 10850 } 10851 10852 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10853 FC_WWN_SIZE) == 0); 10854 ASSERT(plun->lun_num == lun_num); 10855 10856 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10857 10858 ptgt = plun->lun_tgt; 10859 10860 mutex_enter(&ptgt->tgt_mutex); 10861 plun->lun_tgt_count++; 10862 scsi_device_hba_private_set(sd, plun); 10863 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10864 plun->lun_sd = sd; 10865 mutex_exit(&ptgt->tgt_mutex); 10866 mutex_exit(&pptr->port_mutex); 10867 10868 return (DDI_SUCCESS); 10869 } 10870 10871 /*ARGSUSED*/ 10872 static int 10873 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10874 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10875 { 10876 uchar_t *bytes; 10877 uint_t nbytes; 10878 uint16_t lun_num; 10879 struct fcp_tgt *ptgt; 10880 struct fcp_lun *plun; 10881 struct fcp_port *pptr = (struct fcp_port *) 10882 hba_tran->tran_hba_private; 10883 child_info_t *cip; 10884 10885 ASSERT(pptr != NULL); 10886 10887 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10888 fcp_trace, FCP_BUF_LEVEL_8, 0, 10889 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10890 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10891 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10892 10893 cip = (child_info_t *)sd->sd_pathinfo; 10894 if (cip == NULL) { 10895 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10896 fcp_trace, FCP_BUF_LEVEL_8, 0, 10897 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10898 " for %s (instance %d)", ddi_get_name(tgt_dip), 10899 ddi_get_instance(tgt_dip)); 10900 10901 return (DDI_NOT_WELL_FORMED); 10902 } 10903 10904 /* get our port WWN property */ 10905 bytes = NULL; 10906 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10907 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10908 (nbytes != FC_WWN_SIZE)) { 10909 if (bytes) { 10910 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10911 } 10912 return (DDI_NOT_WELL_FORMED); 10913 } 10914 10915 ASSERT(bytes != NULL); 10916 10917 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10918 LUN_PROP, 0xFFFF); 10919 if (lun_num == 0xFFFF) { 10920 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10921 fcp_trace, FCP_BUF_LEVEL_8, 0, 10922 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10923 " for %s (instance %d)", ddi_get_name(tgt_dip), 10924 ddi_get_instance(tgt_dip)); 10925 10926 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10927 return (DDI_NOT_WELL_FORMED); 10928 } 10929 10930 mutex_enter(&pptr->port_mutex); 10931 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10932 mutex_exit(&pptr->port_mutex); 10933 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10934 fcp_trace, FCP_BUF_LEVEL_8, 0, 10935 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10936 " for %s (instance %d)", ddi_get_name(tgt_dip), 10937 ddi_get_instance(tgt_dip)); 10938 10939 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10940 return (DDI_FAILURE); 10941 } 10942 10943 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10944 FC_WWN_SIZE) == 0); 10945 ASSERT(plun->lun_num == lun_num); 10946 10947 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10948 10949 ptgt = plun->lun_tgt; 10950 10951 mutex_enter(&ptgt->tgt_mutex); 10952 plun->lun_tgt_count++; 10953 scsi_device_hba_private_set(sd, plun); 10954 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10955 plun->lun_sd = sd; 10956 mutex_exit(&ptgt->tgt_mutex); 10957 mutex_exit(&pptr->port_mutex); 10958 10959 return (DDI_SUCCESS); 10960 } 10961 10962 10963 /* 10964 * called by the transport to do our own target initialization 10965 * 10966 * can acquire and release the global mutex 10967 */ 10968 /* ARGSUSED */ 10969 static int 10970 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10971 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10972 { 10973 struct fcp_port *pptr = (struct fcp_port *) 10974 hba_tran->tran_hba_private; 10975 int rval; 10976 10977 ASSERT(pptr != NULL); 10978 10979 /* 10980 * Child node is getting initialized. Look at the mpxio component 10981 * type on the child device to see if this device is mpxio managed 10982 * or not. 10983 */ 10984 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 10985 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10986 } else { 10987 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10988 } 10989 10990 return (rval); 10991 } 10992 10993 10994 /* ARGSUSED */ 10995 static void 10996 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10997 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10998 { 10999 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 11000 struct fcp_tgt *ptgt; 11001 11002 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 11003 fcp_trace, FCP_BUF_LEVEL_8, 0, 11004 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 11005 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 11006 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 11007 11008 if (plun == NULL) { 11009 return; 11010 } 11011 ptgt = plun->lun_tgt; 11012 11013 ASSERT(ptgt != NULL); 11014 11015 mutex_enter(&ptgt->tgt_mutex); 11016 ASSERT(plun->lun_tgt_count > 0); 11017 11018 if (--plun->lun_tgt_count == 0) { 11019 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11020 } 11021 plun->lun_sd = NULL; 11022 mutex_exit(&ptgt->tgt_mutex); 11023 } 11024 11025 /* 11026 * Function: fcp_scsi_start 11027 * 11028 * Description: This function is called by the target driver to request a 11029 * command to be sent. 11030 * 11031 * Argument: *ap SCSI address of the device. 11032 * *pkt SCSI packet containing the cmd to send. 11033 * 11034 * Return Value: TRAN_ACCEPT 11035 * TRAN_BUSY 11036 * TRAN_BADPKT 11037 * TRAN_FATAL_ERROR 11038 */ 11039 static int 11040 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11041 { 11042 struct fcp_port *pptr = ADDR2FCP(ap); 11043 struct fcp_lun *plun = ADDR2LUN(ap); 11044 struct fcp_pkt *cmd = PKT2CMD(pkt); 11045 struct fcp_tgt *ptgt = plun->lun_tgt; 11046 int rval; 11047 11048 /* ensure command isn't already issued */ 11049 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11050 11051 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11052 fcp_trace, FCP_BUF_LEVEL_9, 0, 11053 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11054 11055 /* 11056 * It is strange that we enter the fcp_port mutex and the target 11057 * mutex to check the lun state (which has a mutex of its own). 11058 */ 11059 mutex_enter(&pptr->port_mutex); 11060 mutex_enter(&ptgt->tgt_mutex); 11061 11062 /* 11063 * If the device is offline and is not in the process of coming 11064 * online, fail the request. 11065 */ 11066 11067 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11068 !(plun->lun_state & FCP_LUN_ONLINING)) { 11069 mutex_exit(&ptgt->tgt_mutex); 11070 mutex_exit(&pptr->port_mutex); 11071 11072 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11073 pkt->pkt_reason = CMD_DEV_GONE; 11074 } 11075 11076 return (TRAN_FATAL_ERROR); 11077 } 11078 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11079 11080 /* 11081 * If we are suspended, kernel is trying to dump, so don't 11082 * block, fail or defer requests - send them down right away. 11083 * NOTE: If we are in panic (i.e. trying to dump), we can't 11084 * assume we have been suspended. There is hardware such as 11085 * the v880 that doesn't do PM. Thus, the check for 11086 * ddi_in_panic. 11087 * 11088 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11089 * of changing. So, if we can queue the packet, do it. Eventually, 11090 * either the device will have gone away or changed and we can fail 11091 * the request, or we can proceed if the device didn't change. 11092 * 11093 * If the pd in the target or the packet is NULL it's probably 11094 * because the device has gone away, we allow the request to be 11095 * put on the internal queue here in case the device comes back within 11096 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11097 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11098 * could be NULL because the device was disappearing during or since 11099 * packet initialization. 11100 */ 11101 11102 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11103 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11104 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11105 (ptgt->tgt_pd_handle == NULL) || 11106 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11107 /* 11108 * If ((LUN is busy AND 11109 * LUN not suspended AND 11110 * The system is not in panic state) OR 11111 * (The port is coming up)) 11112 * 11113 * We check to see if the any of the flags FLAG_NOINTR or 11114 * FLAG_NOQUEUE is set. If one of them is set the value 11115 * returned will be TRAN_BUSY. If not, the request is queued. 11116 */ 11117 mutex_exit(&ptgt->tgt_mutex); 11118 mutex_exit(&pptr->port_mutex); 11119 11120 /* see if using interrupts is allowed (so queueing'll work) */ 11121 if (pkt->pkt_flags & FLAG_NOINTR) { 11122 pkt->pkt_resid = 0; 11123 return (TRAN_BUSY); 11124 } 11125 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11126 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11127 fcp_trace, FCP_BUF_LEVEL_9, 0, 11128 "fcp_scsi_start: lun busy for pkt %p", pkt); 11129 return (TRAN_BUSY); 11130 } 11131 #ifdef DEBUG 11132 mutex_enter(&pptr->port_pkt_mutex); 11133 pptr->port_npkts++; 11134 mutex_exit(&pptr->port_pkt_mutex); 11135 #endif /* DEBUG */ 11136 11137 /* got queue up the pkt for later */ 11138 fcp_queue_pkt(pptr, cmd); 11139 return (TRAN_ACCEPT); 11140 } 11141 cmd->cmd_state = FCP_PKT_ISSUED; 11142 11143 mutex_exit(&ptgt->tgt_mutex); 11144 mutex_exit(&pptr->port_mutex); 11145 11146 /* 11147 * Now that we released the mutexes, what was protected by them can 11148 * change. 11149 */ 11150 11151 /* 11152 * If there is a reconfiguration in progress, wait for it to complete. 11153 */ 11154 fcp_reconfig_wait(pptr); 11155 11156 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11157 pkt->pkt_time : 0; 11158 11159 /* prepare the packet */ 11160 11161 fcp_prepare_pkt(pptr, cmd, plun); 11162 11163 if (cmd->cmd_pkt->pkt_time) { 11164 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11165 } else { 11166 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11167 } 11168 11169 /* 11170 * if interrupts aren't allowed (e.g. at dump time) then we'll 11171 * have to do polled I/O 11172 */ 11173 if (pkt->pkt_flags & FLAG_NOINTR) { 11174 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11175 return (fcp_dopoll(pptr, cmd)); 11176 } 11177 11178 #ifdef DEBUG 11179 mutex_enter(&pptr->port_pkt_mutex); 11180 pptr->port_npkts++; 11181 mutex_exit(&pptr->port_pkt_mutex); 11182 #endif /* DEBUG */ 11183 11184 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11185 if (rval == FC_SUCCESS) { 11186 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11187 fcp_trace, FCP_BUF_LEVEL_9, 0, 11188 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11189 return (TRAN_ACCEPT); 11190 } 11191 11192 cmd->cmd_state = FCP_PKT_IDLE; 11193 11194 #ifdef DEBUG 11195 mutex_enter(&pptr->port_pkt_mutex); 11196 pptr->port_npkts--; 11197 mutex_exit(&pptr->port_pkt_mutex); 11198 #endif /* DEBUG */ 11199 11200 /* 11201 * For lack of clearer definitions, choose 11202 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11203 */ 11204 11205 if (rval == FC_TRAN_BUSY) { 11206 pkt->pkt_resid = 0; 11207 rval = TRAN_BUSY; 11208 } else { 11209 mutex_enter(&ptgt->tgt_mutex); 11210 if (plun->lun_state & FCP_LUN_OFFLINE) { 11211 child_info_t *cip; 11212 11213 mutex_enter(&plun->lun_mutex); 11214 cip = plun->lun_cip; 11215 mutex_exit(&plun->lun_mutex); 11216 11217 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11218 fcp_trace, FCP_BUF_LEVEL_6, 0, 11219 "fcp_transport failed 2 for %x: %x; dip=%p", 11220 plun->lun_tgt->tgt_d_id, rval, cip); 11221 11222 rval = TRAN_FATAL_ERROR; 11223 } else { 11224 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11225 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11226 fcp_trace, FCP_BUF_LEVEL_9, 0, 11227 "fcp_scsi_start: FC_BUSY for pkt %p", 11228 pkt); 11229 rval = TRAN_BUSY; 11230 } else { 11231 rval = TRAN_ACCEPT; 11232 fcp_queue_pkt(pptr, cmd); 11233 } 11234 } 11235 mutex_exit(&ptgt->tgt_mutex); 11236 } 11237 11238 return (rval); 11239 } 11240 11241 /* 11242 * called by the transport to abort a packet 11243 */ 11244 /*ARGSUSED*/ 11245 static int 11246 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11247 { 11248 int tgt_cnt; 11249 struct fcp_port *pptr = ADDR2FCP(ap); 11250 struct fcp_lun *plun = ADDR2LUN(ap); 11251 struct fcp_tgt *ptgt = plun->lun_tgt; 11252 11253 if (pkt == NULL) { 11254 if (ptgt) { 11255 mutex_enter(&ptgt->tgt_mutex); 11256 tgt_cnt = ptgt->tgt_change_cnt; 11257 mutex_exit(&ptgt->tgt_mutex); 11258 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11259 return (TRUE); 11260 } 11261 } 11262 return (FALSE); 11263 } 11264 11265 11266 /* 11267 * Perform reset 11268 */ 11269 int 11270 fcp_scsi_reset(struct scsi_address *ap, int level) 11271 { 11272 int rval = 0; 11273 struct fcp_port *pptr = ADDR2FCP(ap); 11274 struct fcp_lun *plun = ADDR2LUN(ap); 11275 struct fcp_tgt *ptgt = plun->lun_tgt; 11276 11277 if (level == RESET_ALL) { 11278 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11279 rval = 1; 11280 } 11281 } else if (level == RESET_TARGET || level == RESET_LUN) { 11282 /* 11283 * If we are in the middle of discovery, return 11284 * SUCCESS as this target will be rediscovered 11285 * anyway 11286 */ 11287 mutex_enter(&ptgt->tgt_mutex); 11288 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11289 mutex_exit(&ptgt->tgt_mutex); 11290 return (1); 11291 } 11292 mutex_exit(&ptgt->tgt_mutex); 11293 11294 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11295 rval = 1; 11296 } 11297 } 11298 return (rval); 11299 } 11300 11301 11302 /* 11303 * called by the framework to get a SCSI capability 11304 */ 11305 static int 11306 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11307 { 11308 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11309 } 11310 11311 11312 /* 11313 * called by the framework to set a SCSI capability 11314 */ 11315 static int 11316 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11317 { 11318 return (fcp_commoncap(ap, cap, value, whom, 1)); 11319 } 11320 11321 /* 11322 * Function: fcp_pkt_setup 11323 * 11324 * Description: This function sets up the scsi_pkt structure passed by the 11325 * caller. This function assumes fcp_pkt_constructor has been 11326 * called previously for the packet passed by the caller. If 11327 * successful this call will have the following results: 11328 * 11329 * - The resources needed that will be constant through out 11330 * the whole transaction are allocated. 11331 * - The fields that will be constant through out the whole 11332 * transaction are initialized. 11333 * - The scsi packet will be linked to the LUN structure 11334 * addressed by the transaction. 11335 * 11336 * Argument: 11337 * *pkt Pointer to a scsi_pkt structure. 11338 * callback 11339 * arg 11340 * 11341 * Return Value: 0 Success 11342 * !0 Failure 11343 * 11344 * Context: Kernel context or interrupt context 11345 */ 11346 /* ARGSUSED */ 11347 static int 11348 fcp_pkt_setup(struct scsi_pkt *pkt, 11349 int (*callback)(caddr_t arg), 11350 caddr_t arg) 11351 { 11352 struct fcp_pkt *cmd; 11353 struct fcp_port *pptr; 11354 struct fcp_lun *plun; 11355 struct fcp_tgt *ptgt; 11356 int kf; 11357 fc_packet_t *fpkt; 11358 fc_frame_hdr_t *hp; 11359 11360 pptr = ADDR2FCP(&pkt->pkt_address); 11361 plun = ADDR2LUN(&pkt->pkt_address); 11362 ptgt = plun->lun_tgt; 11363 11364 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11365 fpkt = cmd->cmd_fp_pkt; 11366 11367 /* 11368 * this request is for dma allocation only 11369 */ 11370 /* 11371 * First step of fcp_scsi_init_pkt: pkt allocation 11372 * We determine if the caller is willing to wait for the 11373 * resources. 11374 */ 11375 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11376 11377 /* 11378 * Selective zeroing of the pkt. 11379 */ 11380 cmd->cmd_back = NULL; 11381 cmd->cmd_next = NULL; 11382 11383 /* 11384 * Zero out fcp command 11385 */ 11386 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11387 11388 cmd->cmd_state = FCP_PKT_IDLE; 11389 11390 fpkt = cmd->cmd_fp_pkt; 11391 fpkt->pkt_data_acc = NULL; 11392 11393 /* 11394 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11395 * could be destroyed. We need fail pkt_setup. 11396 */ 11397 if (pptr->port_state & FCP_STATE_OFFLINE) { 11398 return (-1); 11399 } 11400 11401 mutex_enter(&ptgt->tgt_mutex); 11402 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11403 11404 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11405 != FC_SUCCESS) { 11406 mutex_exit(&ptgt->tgt_mutex); 11407 return (-1); 11408 } 11409 11410 mutex_exit(&ptgt->tgt_mutex); 11411 11412 /* Fill in the Fabric Channel Header */ 11413 hp = &fpkt->pkt_cmd_fhdr; 11414 hp->r_ctl = R_CTL_COMMAND; 11415 hp->rsvd = 0; 11416 hp->type = FC_TYPE_SCSI_FCP; 11417 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11418 hp->seq_id = 0; 11419 hp->df_ctl = 0; 11420 hp->seq_cnt = 0; 11421 hp->ox_id = 0xffff; 11422 hp->rx_id = 0xffff; 11423 hp->ro = 0; 11424 11425 /* 11426 * A doubly linked list (cmd_forw, cmd_back) is built 11427 * out of every allocated packet on a per-lun basis 11428 * 11429 * The packets are maintained in the list so as to satisfy 11430 * scsi_abort() requests. At present (which is unlikely to 11431 * change in the future) nobody performs a real scsi_abort 11432 * in the SCSI target drivers (as they don't keep the packets 11433 * after doing scsi_transport - so they don't know how to 11434 * abort a packet other than sending a NULL to abort all 11435 * outstanding packets) 11436 */ 11437 mutex_enter(&plun->lun_mutex); 11438 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11439 plun->lun_pkt_head->cmd_back = cmd; 11440 } else { 11441 plun->lun_pkt_tail = cmd; 11442 } 11443 plun->lun_pkt_head = cmd; 11444 mutex_exit(&plun->lun_mutex); 11445 return (0); 11446 } 11447 11448 /* 11449 * Function: fcp_pkt_teardown 11450 * 11451 * Description: This function releases a scsi_pkt structure and all the 11452 * resources attached to it. 11453 * 11454 * Argument: *pkt Pointer to a scsi_pkt structure. 11455 * 11456 * Return Value: None 11457 * 11458 * Context: User, Kernel or Interrupt context. 11459 */ 11460 static void 11461 fcp_pkt_teardown(struct scsi_pkt *pkt) 11462 { 11463 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11464 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11465 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11466 11467 /* 11468 * Remove the packet from the per-lun list 11469 */ 11470 mutex_enter(&plun->lun_mutex); 11471 if (cmd->cmd_back) { 11472 ASSERT(cmd != plun->lun_pkt_head); 11473 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11474 } else { 11475 ASSERT(cmd == plun->lun_pkt_head); 11476 plun->lun_pkt_head = cmd->cmd_forw; 11477 } 11478 11479 if (cmd->cmd_forw) { 11480 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11481 } else { 11482 ASSERT(cmd == plun->lun_pkt_tail); 11483 plun->lun_pkt_tail = cmd->cmd_back; 11484 } 11485 11486 mutex_exit(&plun->lun_mutex); 11487 11488 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11489 } 11490 11491 /* 11492 * Routine for reset notification setup, to register or cancel. 11493 * This function is called by SCSA 11494 */ 11495 /*ARGSUSED*/ 11496 static int 11497 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11498 void (*callback)(caddr_t), caddr_t arg) 11499 { 11500 struct fcp_port *pptr = ADDR2FCP(ap); 11501 11502 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11503 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11504 } 11505 11506 11507 static int 11508 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11509 ddi_eventcookie_t *event_cookiep) 11510 { 11511 struct fcp_port *pptr = fcp_dip2port(dip); 11512 11513 if (pptr == NULL) { 11514 return (DDI_FAILURE); 11515 } 11516 11517 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11518 event_cookiep, NDI_EVENT_NOPASS)); 11519 } 11520 11521 11522 static int 11523 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11524 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11525 ddi_callback_id_t *cb_id) 11526 { 11527 struct fcp_port *pptr = fcp_dip2port(dip); 11528 11529 if (pptr == NULL) { 11530 return (DDI_FAILURE); 11531 } 11532 11533 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11534 eventid, callback, arg, NDI_SLEEP, cb_id)); 11535 } 11536 11537 11538 static int 11539 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11540 { 11541 11542 struct fcp_port *pptr = fcp_dip2port(dip); 11543 11544 if (pptr == NULL) { 11545 return (DDI_FAILURE); 11546 } 11547 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11548 } 11549 11550 11551 /* 11552 * called by the transport to post an event 11553 */ 11554 static int 11555 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11556 ddi_eventcookie_t eventid, void *impldata) 11557 { 11558 struct fcp_port *pptr = fcp_dip2port(dip); 11559 11560 if (pptr == NULL) { 11561 return (DDI_FAILURE); 11562 } 11563 11564 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11565 eventid, impldata)); 11566 } 11567 11568 11569 /* 11570 * A target in in many cases in Fibre Channel has a one to one relation 11571 * with a port identifier (which is also known as D_ID and also as AL_PA 11572 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11573 * will most likely result in resetting all LUNs (which means a reset will 11574 * occur on all the SCSI devices connected at the other end of the bridge) 11575 * That is the latest favorite topic for discussion, for, one can debate as 11576 * hot as one likes and come up with arguably a best solution to one's 11577 * satisfaction 11578 * 11579 * To stay on track and not digress much, here are the problems stated 11580 * briefly: 11581 * 11582 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11583 * target drivers use RESET_TARGET even if their instance is on a 11584 * LUN. Doesn't that sound a bit broken ? 11585 * 11586 * FCP SCSI (the current spec) only defines RESET TARGET in the 11587 * control fields of an FCP_CMND structure. It should have been 11588 * fixed right there, giving flexibility to the initiators to 11589 * minimize havoc that could be caused by resetting a target. 11590 */ 11591 static int 11592 fcp_reset_target(struct scsi_address *ap, int level) 11593 { 11594 int rval = FC_FAILURE; 11595 char lun_id[25]; 11596 struct fcp_port *pptr = ADDR2FCP(ap); 11597 struct fcp_lun *plun = ADDR2LUN(ap); 11598 struct fcp_tgt *ptgt = plun->lun_tgt; 11599 struct scsi_pkt *pkt; 11600 struct fcp_pkt *cmd; 11601 struct fcp_rsp *rsp; 11602 uint32_t tgt_cnt; 11603 struct fcp_rsp_info *rsp_info; 11604 struct fcp_reset_elem *p; 11605 int bval; 11606 11607 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11608 KM_NOSLEEP)) == NULL) { 11609 return (rval); 11610 } 11611 11612 mutex_enter(&ptgt->tgt_mutex); 11613 if (level == RESET_TARGET) { 11614 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11615 mutex_exit(&ptgt->tgt_mutex); 11616 kmem_free(p, sizeof (struct fcp_reset_elem)); 11617 return (rval); 11618 } 11619 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11620 (void) strcpy(lun_id, " "); 11621 } else { 11622 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11623 mutex_exit(&ptgt->tgt_mutex); 11624 kmem_free(p, sizeof (struct fcp_reset_elem)); 11625 return (rval); 11626 } 11627 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11628 11629 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11630 } 11631 tgt_cnt = ptgt->tgt_change_cnt; 11632 11633 mutex_exit(&ptgt->tgt_mutex); 11634 11635 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11636 0, 0, NULL, 0)) == NULL) { 11637 kmem_free(p, sizeof (struct fcp_reset_elem)); 11638 mutex_enter(&ptgt->tgt_mutex); 11639 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11640 mutex_exit(&ptgt->tgt_mutex); 11641 return (rval); 11642 } 11643 pkt->pkt_time = FCP_POLL_TIMEOUT; 11644 11645 /* fill in cmd part of packet */ 11646 cmd = PKT2CMD(pkt); 11647 if (level == RESET_TARGET) { 11648 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11649 } else { 11650 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11651 } 11652 cmd->cmd_fp_pkt->pkt_comp = NULL; 11653 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11654 11655 /* prepare a packet for transport */ 11656 fcp_prepare_pkt(pptr, cmd, plun); 11657 11658 if (cmd->cmd_pkt->pkt_time) { 11659 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11660 } else { 11661 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11662 } 11663 11664 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11665 bval = fcp_dopoll(pptr, cmd); 11666 fc_ulp_idle_port(pptr->port_fp_handle); 11667 11668 /* submit the packet */ 11669 if (bval == TRAN_ACCEPT) { 11670 int error = 3; 11671 11672 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11673 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11674 sizeof (struct fcp_rsp)); 11675 11676 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11677 if (fcp_validate_fcp_response(rsp, pptr) == 11678 FC_SUCCESS) { 11679 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11680 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11681 sizeof (struct fcp_rsp), rsp_info, 11682 cmd->cmd_fp_pkt->pkt_resp_acc, 11683 sizeof (struct fcp_rsp_info)); 11684 } 11685 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11686 rval = FC_SUCCESS; 11687 error = 0; 11688 } else { 11689 error = 1; 11690 } 11691 } else { 11692 error = 2; 11693 } 11694 } 11695 11696 switch (error) { 11697 case 0: 11698 fcp_log(CE_WARN, pptr->port_dip, 11699 "!FCP: WWN 0x%08x%08x %s reset successfully", 11700 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11701 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11702 break; 11703 11704 case 1: 11705 fcp_log(CE_WARN, pptr->port_dip, 11706 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11707 " response code=%x", 11708 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11709 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11710 rsp_info->rsp_code); 11711 break; 11712 11713 case 2: 11714 fcp_log(CE_WARN, pptr->port_dip, 11715 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11716 " Bad FCP response values: rsvd1=%x," 11717 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11718 " rsplen=%x, senselen=%x", 11719 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11720 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11721 rsp->reserved_0, rsp->reserved_1, 11722 rsp->fcp_u.fcp_status.reserved_0, 11723 rsp->fcp_u.fcp_status.reserved_1, 11724 rsp->fcp_response_len, rsp->fcp_sense_len); 11725 break; 11726 11727 default: 11728 fcp_log(CE_WARN, pptr->port_dip, 11729 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11730 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11731 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11732 break; 11733 } 11734 } 11735 scsi_destroy_pkt(pkt); 11736 11737 if (rval == FC_FAILURE) { 11738 mutex_enter(&ptgt->tgt_mutex); 11739 if (level == RESET_TARGET) { 11740 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11741 } else { 11742 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11743 } 11744 mutex_exit(&ptgt->tgt_mutex); 11745 kmem_free(p, sizeof (struct fcp_reset_elem)); 11746 return (rval); 11747 } 11748 11749 mutex_enter(&pptr->port_mutex); 11750 if (level == RESET_TARGET) { 11751 p->tgt = ptgt; 11752 p->lun = NULL; 11753 } else { 11754 p->tgt = NULL; 11755 p->lun = plun; 11756 } 11757 p->tgt = ptgt; 11758 p->tgt_cnt = tgt_cnt; 11759 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11760 p->next = pptr->port_reset_list; 11761 pptr->port_reset_list = p; 11762 11763 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11764 fcp_trace, FCP_BUF_LEVEL_3, 0, 11765 "Notify ssd of the reset to reinstate the reservations"); 11766 11767 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11768 &pptr->port_reset_notify_listf); 11769 11770 mutex_exit(&pptr->port_mutex); 11771 11772 return (rval); 11773 } 11774 11775 11776 /* 11777 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11778 * SCSI capabilities 11779 */ 11780 /* ARGSUSED */ 11781 static int 11782 fcp_commoncap(struct scsi_address *ap, char *cap, 11783 int val, int tgtonly, int doset) 11784 { 11785 struct fcp_port *pptr = ADDR2FCP(ap); 11786 struct fcp_lun *plun = ADDR2LUN(ap); 11787 struct fcp_tgt *ptgt = plun->lun_tgt; 11788 int cidx; 11789 int rval = FALSE; 11790 11791 if (cap == (char *)0) { 11792 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11793 fcp_trace, FCP_BUF_LEVEL_3, 0, 11794 "fcp_commoncap: invalid arg"); 11795 return (rval); 11796 } 11797 11798 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11799 return (UNDEFINED); 11800 } 11801 11802 /* 11803 * Process setcap request. 11804 */ 11805 if (doset) { 11806 /* 11807 * At present, we can only set binary (0/1) values 11808 */ 11809 switch (cidx) { 11810 case SCSI_CAP_ARQ: 11811 if (val == 0) { 11812 rval = FALSE; 11813 } else { 11814 rval = TRUE; 11815 } 11816 break; 11817 11818 case SCSI_CAP_LUN_RESET: 11819 if (val) { 11820 plun->lun_cap |= FCP_LUN_CAP_RESET; 11821 } else { 11822 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11823 } 11824 rval = TRUE; 11825 break; 11826 11827 case SCSI_CAP_SECTOR_SIZE: 11828 rval = TRUE; 11829 break; 11830 default: 11831 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11832 fcp_trace, FCP_BUF_LEVEL_4, 0, 11833 "fcp_setcap: unsupported %d", cidx); 11834 rval = UNDEFINED; 11835 break; 11836 } 11837 11838 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11839 fcp_trace, FCP_BUF_LEVEL_5, 0, 11840 "set cap: cap=%s, val/tgtonly/doset/rval = " 11841 "0x%x/0x%x/0x%x/%d", 11842 cap, val, tgtonly, doset, rval); 11843 11844 } else { 11845 /* 11846 * Process getcap request. 11847 */ 11848 switch (cidx) { 11849 case SCSI_CAP_DMA_MAX: 11850 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11851 11852 /* 11853 * Need to make an adjustment qlc is uint_t 64 11854 * st is int, so we will make the adjustment here 11855 * being as nobody wants to touch this. 11856 * It still leaves the max single block length 11857 * of 2 gig. This should last . 11858 */ 11859 11860 if (rval == -1) { 11861 rval = MAX_INT_DMA; 11862 } 11863 11864 break; 11865 11866 case SCSI_CAP_INITIATOR_ID: 11867 rval = pptr->port_id; 11868 break; 11869 11870 case SCSI_CAP_ARQ: 11871 case SCSI_CAP_RESET_NOTIFICATION: 11872 case SCSI_CAP_TAGGED_QING: 11873 rval = TRUE; 11874 break; 11875 11876 case SCSI_CAP_SCSI_VERSION: 11877 rval = 3; 11878 break; 11879 11880 case SCSI_CAP_INTERCONNECT_TYPE: 11881 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11882 (ptgt->tgt_hard_addr == 0)) { 11883 rval = INTERCONNECT_FABRIC; 11884 } else { 11885 rval = INTERCONNECT_FIBRE; 11886 } 11887 break; 11888 11889 case SCSI_CAP_LUN_RESET: 11890 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11891 TRUE : FALSE; 11892 break; 11893 11894 default: 11895 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11896 fcp_trace, FCP_BUF_LEVEL_4, 0, 11897 "fcp_getcap: unsupported %d", cidx); 11898 rval = UNDEFINED; 11899 break; 11900 } 11901 11902 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11903 fcp_trace, FCP_BUF_LEVEL_8, 0, 11904 "get cap: cap=%s, val/tgtonly/doset/rval = " 11905 "0x%x/0x%x/0x%x/%d", 11906 cap, val, tgtonly, doset, rval); 11907 } 11908 11909 return (rval); 11910 } 11911 11912 /* 11913 * called by the transport to get the port-wwn and lun 11914 * properties of this device, and to create a "name" based on them 11915 * 11916 * these properties don't exist on sun4m 11917 * 11918 * return 1 for success else return 0 11919 */ 11920 /* ARGSUSED */ 11921 static int 11922 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11923 { 11924 int i; 11925 int *lun; 11926 int numChars; 11927 uint_t nlun; 11928 uint_t count; 11929 uint_t nbytes; 11930 uchar_t *bytes; 11931 uint16_t lun_num; 11932 uint32_t tgt_id; 11933 char **conf_wwn; 11934 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11935 uchar_t barray[FC_WWN_SIZE]; 11936 dev_info_t *tgt_dip; 11937 struct fcp_tgt *ptgt; 11938 struct fcp_port *pptr; 11939 struct fcp_lun *plun; 11940 11941 ASSERT(sd != NULL); 11942 ASSERT(name != NULL); 11943 11944 tgt_dip = sd->sd_dev; 11945 pptr = ddi_get_soft_state(fcp_softstate, 11946 ddi_get_instance(ddi_get_parent(tgt_dip))); 11947 if (pptr == NULL) { 11948 return (0); 11949 } 11950 11951 ASSERT(tgt_dip != NULL); 11952 11953 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11954 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11955 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11956 name[0] = '\0'; 11957 return (0); 11958 } 11959 11960 if (nlun == 0) { 11961 ddi_prop_free(lun); 11962 return (0); 11963 } 11964 11965 lun_num = lun[0]; 11966 ddi_prop_free(lun); 11967 11968 /* 11969 * Lookup for .conf WWN property 11970 */ 11971 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11972 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11973 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11974 ASSERT(count >= 1); 11975 11976 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11977 ddi_prop_free(conf_wwn); 11978 mutex_enter(&pptr->port_mutex); 11979 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11980 mutex_exit(&pptr->port_mutex); 11981 return (0); 11982 } 11983 ptgt = plun->lun_tgt; 11984 mutex_exit(&pptr->port_mutex); 11985 11986 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11987 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11988 11989 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11990 ptgt->tgt_hard_addr != 0) { 11991 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11992 ptgt->tgt_hard_addr]; 11993 } else { 11994 tgt_id = ptgt->tgt_d_id; 11995 } 11996 11997 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11998 TARGET_PROP, tgt_id); 11999 } 12000 12001 /* get the our port-wwn property */ 12002 bytes = NULL; 12003 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 12004 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12005 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 12006 if (bytes != NULL) { 12007 ddi_prop_free(bytes); 12008 } 12009 return (0); 12010 } 12011 12012 for (i = 0; i < FC_WWN_SIZE; i++) { 12013 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12014 } 12015 12016 /* Stick in the address of the form "wWWN,LUN" */ 12017 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12018 12019 ASSERT(numChars < len); 12020 if (numChars >= len) { 12021 fcp_log(CE_WARN, pptr->port_dip, 12022 "!fcp_scsi_get_name: " 12023 "name parameter length too small, it needs to be %d", 12024 numChars+1); 12025 } 12026 12027 ddi_prop_free(bytes); 12028 12029 return (1); 12030 } 12031 12032 12033 /* 12034 * called by the transport to get the SCSI target id value, returning 12035 * it in "name" 12036 * 12037 * this isn't needed/used on sun4m 12038 * 12039 * return 1 for success else return 0 12040 */ 12041 /* ARGSUSED */ 12042 static int 12043 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12044 { 12045 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12046 struct fcp_tgt *ptgt; 12047 int numChars; 12048 12049 if (plun == NULL) { 12050 return (0); 12051 } 12052 12053 if ((ptgt = plun->lun_tgt) == NULL) { 12054 return (0); 12055 } 12056 12057 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12058 12059 ASSERT(numChars < len); 12060 if (numChars >= len) { 12061 fcp_log(CE_WARN, NULL, 12062 "!fcp_scsi_get_bus_addr: " 12063 "name parameter length too small, it needs to be %d", 12064 numChars+1); 12065 } 12066 12067 return (1); 12068 } 12069 12070 12071 /* 12072 * called internally to reset the link where the specified port lives 12073 */ 12074 static int 12075 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12076 { 12077 la_wwn_t wwn; 12078 struct fcp_lun *plun; 12079 struct fcp_tgt *ptgt; 12080 12081 /* disable restart of lip if we're suspended */ 12082 mutex_enter(&pptr->port_mutex); 12083 12084 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12085 FCP_STATE_POWER_DOWN)) { 12086 mutex_exit(&pptr->port_mutex); 12087 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12088 fcp_trace, FCP_BUF_LEVEL_2, 0, 12089 "fcp_linkreset, fcp%d: link reset " 12090 "disabled due to DDI_SUSPEND", 12091 ddi_get_instance(pptr->port_dip)); 12092 return (FC_FAILURE); 12093 } 12094 12095 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12096 mutex_exit(&pptr->port_mutex); 12097 return (FC_SUCCESS); 12098 } 12099 12100 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12101 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12102 12103 /* 12104 * If ap == NULL assume local link reset. 12105 */ 12106 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12107 plun = ADDR2LUN(ap); 12108 ptgt = plun->lun_tgt; 12109 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12110 } else { 12111 bzero((caddr_t)&wwn, sizeof (wwn)); 12112 } 12113 mutex_exit(&pptr->port_mutex); 12114 12115 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12116 } 12117 12118 12119 /* 12120 * called from fcp_port_attach() to resume a port 12121 * return DDI_* success/failure status 12122 * acquires and releases the global mutex 12123 * acquires and releases the port mutex 12124 */ 12125 /*ARGSUSED*/ 12126 12127 static int 12128 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12129 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12130 { 12131 int res = DDI_FAILURE; /* default result */ 12132 struct fcp_port *pptr; /* port state ptr */ 12133 uint32_t alloc_cnt; 12134 uint32_t max_cnt; 12135 fc_portmap_t *tmp_list = NULL; 12136 12137 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12138 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12139 instance); 12140 12141 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12142 cmn_err(CE_WARN, "fcp: bad soft state"); 12143 return (res); 12144 } 12145 12146 mutex_enter(&pptr->port_mutex); 12147 switch (cmd) { 12148 case FC_CMD_RESUME: 12149 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12150 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12151 break; 12152 12153 case FC_CMD_POWER_UP: 12154 /* 12155 * If the port is DDI_SUSPENded, defer rediscovery 12156 * until DDI_RESUME occurs 12157 */ 12158 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12159 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12160 mutex_exit(&pptr->port_mutex); 12161 return (DDI_SUCCESS); 12162 } 12163 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12164 } 12165 pptr->port_id = s_id; 12166 pptr->port_state = FCP_STATE_INIT; 12167 mutex_exit(&pptr->port_mutex); 12168 12169 /* 12170 * Make a copy of ulp_port_info as fctl allocates 12171 * a temp struct. 12172 */ 12173 (void) fcp_cp_pinfo(pptr, pinfo); 12174 12175 mutex_enter(&fcp_global_mutex); 12176 if (fcp_watchdog_init++ == 0) { 12177 fcp_watchdog_tick = fcp_watchdog_timeout * 12178 drv_usectohz(1000000); 12179 fcp_watchdog_id = timeout(fcp_watch, 12180 NULL, fcp_watchdog_tick); 12181 } 12182 mutex_exit(&fcp_global_mutex); 12183 12184 /* 12185 * Handle various topologies and link states. 12186 */ 12187 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12188 case FC_STATE_OFFLINE: 12189 /* 12190 * Wait for ONLINE, at which time a state 12191 * change will cause a statec_callback 12192 */ 12193 res = DDI_SUCCESS; 12194 break; 12195 12196 case FC_STATE_ONLINE: 12197 12198 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12199 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12200 res = DDI_SUCCESS; 12201 break; 12202 } 12203 12204 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12205 !fcp_enable_auto_configuration) { 12206 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12207 if (tmp_list == NULL) { 12208 if (!alloc_cnt) { 12209 res = DDI_SUCCESS; 12210 } 12211 break; 12212 } 12213 max_cnt = alloc_cnt; 12214 } else { 12215 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12216 12217 alloc_cnt = FCP_MAX_DEVICES; 12218 12219 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12220 (sizeof (fc_portmap_t)) * alloc_cnt, 12221 KM_NOSLEEP)) == NULL) { 12222 fcp_log(CE_WARN, pptr->port_dip, 12223 "!fcp%d: failed to allocate portmap", 12224 instance); 12225 break; 12226 } 12227 12228 max_cnt = alloc_cnt; 12229 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12230 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12231 FC_SUCCESS) { 12232 caddr_t msg; 12233 12234 (void) fc_ulp_error(res, &msg); 12235 12236 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12237 fcp_trace, FCP_BUF_LEVEL_2, 0, 12238 "resume failed getportmap: reason=0x%x", 12239 res); 12240 12241 fcp_log(CE_WARN, pptr->port_dip, 12242 "!failed to get port map : %s", msg); 12243 break; 12244 } 12245 if (max_cnt > alloc_cnt) { 12246 alloc_cnt = max_cnt; 12247 } 12248 } 12249 12250 /* 12251 * do the SCSI device discovery and create 12252 * the devinfos 12253 */ 12254 fcp_statec_callback(ulph, pptr->port_fp_handle, 12255 pptr->port_phys_state, pptr->port_topology, tmp_list, 12256 max_cnt, pptr->port_id); 12257 12258 res = DDI_SUCCESS; 12259 break; 12260 12261 default: 12262 fcp_log(CE_WARN, pptr->port_dip, 12263 "!fcp%d: invalid port state at attach=0x%x", 12264 instance, pptr->port_phys_state); 12265 12266 mutex_enter(&pptr->port_mutex); 12267 pptr->port_phys_state = FCP_STATE_OFFLINE; 12268 mutex_exit(&pptr->port_mutex); 12269 res = DDI_SUCCESS; 12270 12271 break; 12272 } 12273 12274 if (tmp_list != NULL) { 12275 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12276 } 12277 12278 return (res); 12279 } 12280 12281 12282 static void 12283 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12284 { 12285 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12286 pptr->port_dip = pinfo->port_dip; 12287 pptr->port_fp_handle = pinfo->port_handle; 12288 if (pinfo->port_acc_attr != NULL) { 12289 /* 12290 * FCA supports DMA 12291 */ 12292 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12293 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12294 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12295 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12296 } 12297 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12298 pptr->port_max_exch = pinfo->port_fca_max_exch; 12299 pptr->port_phys_state = pinfo->port_state; 12300 pptr->port_topology = pinfo->port_flags; 12301 pptr->port_reset_action = pinfo->port_reset_action; 12302 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12303 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12304 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12305 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12306 12307 /* Clear FMA caps to avoid fm-capability ereport */ 12308 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12309 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12310 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12311 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12312 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12313 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12314 } 12315 12316 /* 12317 * If the elements wait field is set to 1 then 12318 * another thread is waiting for the operation to complete. Once 12319 * it is complete, the waiting thread is signaled and the element is 12320 * freed by the waiting thread. If the elements wait field is set to 0 12321 * the element is freed. 12322 */ 12323 static void 12324 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12325 { 12326 ASSERT(elem != NULL); 12327 mutex_enter(&elem->mutex); 12328 elem->result = result; 12329 if (elem->wait) { 12330 elem->wait = 0; 12331 cv_signal(&elem->cv); 12332 mutex_exit(&elem->mutex); 12333 } else { 12334 mutex_exit(&elem->mutex); 12335 cv_destroy(&elem->cv); 12336 mutex_destroy(&elem->mutex); 12337 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12338 } 12339 } 12340 12341 /* 12342 * This function is invoked from the taskq thread to allocate 12343 * devinfo nodes and to online/offline them. 12344 */ 12345 static void 12346 fcp_hp_task(void *arg) 12347 { 12348 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12349 struct fcp_lun *plun = elem->lun; 12350 struct fcp_port *pptr = elem->port; 12351 int result; 12352 12353 ASSERT(elem->what == FCP_ONLINE || 12354 elem->what == FCP_OFFLINE || 12355 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12356 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12357 12358 mutex_enter(&pptr->port_mutex); 12359 mutex_enter(&plun->lun_mutex); 12360 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12361 plun->lun_event_count != elem->event_cnt) || 12362 pptr->port_state & (FCP_STATE_SUSPENDED | 12363 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12364 mutex_exit(&plun->lun_mutex); 12365 mutex_exit(&pptr->port_mutex); 12366 fcp_process_elem(elem, NDI_FAILURE); 12367 return; 12368 } 12369 mutex_exit(&plun->lun_mutex); 12370 mutex_exit(&pptr->port_mutex); 12371 12372 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12373 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12374 fcp_process_elem(elem, result); 12375 } 12376 12377 12378 static child_info_t * 12379 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12380 int tcount) 12381 { 12382 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12383 12384 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12385 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12386 12387 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12388 /* 12389 * Child has not been created yet. Create the child device 12390 * based on the per-Lun flags. 12391 */ 12392 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12393 plun->lun_cip = 12394 CIP(fcp_create_dip(plun, lcount, tcount)); 12395 plun->lun_mpxio = 0; 12396 } else { 12397 plun->lun_cip = 12398 CIP(fcp_create_pip(plun, lcount, tcount)); 12399 plun->lun_mpxio = 1; 12400 } 12401 } else { 12402 plun->lun_cip = cip; 12403 } 12404 12405 return (plun->lun_cip); 12406 } 12407 12408 12409 static int 12410 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12411 { 12412 int rval = FC_FAILURE; 12413 dev_info_t *pdip; 12414 struct dev_info *dip; 12415 int circular; 12416 12417 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12418 12419 pdip = plun->lun_tgt->tgt_port->port_dip; 12420 12421 if (plun->lun_cip == NULL) { 12422 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12423 fcp_trace, FCP_BUF_LEVEL_3, 0, 12424 "fcp_is_dip_present: plun->lun_cip is NULL: " 12425 "plun: %p lun state: %x num: %d target state: %x", 12426 plun, plun->lun_state, plun->lun_num, 12427 plun->lun_tgt->tgt_port->port_state); 12428 return (rval); 12429 } 12430 ndi_devi_enter(pdip, &circular); 12431 dip = DEVI(pdip)->devi_child; 12432 while (dip) { 12433 if (dip == DEVI(cdip)) { 12434 rval = FC_SUCCESS; 12435 break; 12436 } 12437 dip = dip->devi_sibling; 12438 } 12439 ndi_devi_exit(pdip, circular); 12440 return (rval); 12441 } 12442 12443 static int 12444 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12445 { 12446 int rval = FC_FAILURE; 12447 12448 ASSERT(plun != NULL); 12449 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12450 12451 if (plun->lun_mpxio == 0) { 12452 rval = fcp_is_dip_present(plun, DIP(cip)); 12453 } else { 12454 rval = fcp_is_pip_present(plun, PIP(cip)); 12455 } 12456 12457 return (rval); 12458 } 12459 12460 /* 12461 * Function: fcp_create_dip 12462 * 12463 * Description: Creates a dev_info_t structure for the LUN specified by the 12464 * caller. 12465 * 12466 * Argument: plun Lun structure 12467 * link_cnt Link state count. 12468 * tgt_cnt Target state change count. 12469 * 12470 * Return Value: NULL if it failed 12471 * dev_info_t structure address if it succeeded 12472 * 12473 * Context: Kernel context 12474 */ 12475 static dev_info_t * 12476 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12477 { 12478 int failure = 0; 12479 uint32_t tgt_id; 12480 uint64_t sam_lun; 12481 struct fcp_tgt *ptgt = plun->lun_tgt; 12482 struct fcp_port *pptr = ptgt->tgt_port; 12483 dev_info_t *pdip = pptr->port_dip; 12484 dev_info_t *cdip = NULL; 12485 dev_info_t *old_dip = DIP(plun->lun_cip); 12486 char *nname = NULL; 12487 char **compatible = NULL; 12488 int ncompatible; 12489 char *scsi_binding_set; 12490 char t_pwwn[17]; 12491 12492 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12493 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12494 12495 /* get the 'scsi-binding-set' property */ 12496 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12497 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12498 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12499 scsi_binding_set = NULL; 12500 } 12501 12502 /* determine the node name and compatible */ 12503 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12504 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12505 if (scsi_binding_set) { 12506 ddi_prop_free(scsi_binding_set); 12507 } 12508 12509 if (nname == NULL) { 12510 #ifdef DEBUG 12511 cmn_err(CE_WARN, "%s%d: no driver for " 12512 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12513 " compatible: %s", 12514 ddi_driver_name(pdip), ddi_get_instance(pdip), 12515 ptgt->tgt_port_wwn.raw_wwn[0], 12516 ptgt->tgt_port_wwn.raw_wwn[1], 12517 ptgt->tgt_port_wwn.raw_wwn[2], 12518 ptgt->tgt_port_wwn.raw_wwn[3], 12519 ptgt->tgt_port_wwn.raw_wwn[4], 12520 ptgt->tgt_port_wwn.raw_wwn[5], 12521 ptgt->tgt_port_wwn.raw_wwn[6], 12522 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12523 *compatible); 12524 #endif /* DEBUG */ 12525 failure++; 12526 goto end_of_fcp_create_dip; 12527 } 12528 12529 cdip = fcp_find_existing_dip(plun, pdip, nname); 12530 12531 /* 12532 * if the old_dip does not match the cdip, that means there is 12533 * some property change. since we'll be using the cdip, we need 12534 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12535 * then the dtype for the device has been updated. Offline the 12536 * the old device and create a new device with the new device type 12537 * Refer to bug: 4764752 12538 */ 12539 if (old_dip && (cdip != old_dip || 12540 plun->lun_state & FCP_LUN_CHANGED)) { 12541 plun->lun_state &= ~(FCP_LUN_INIT); 12542 mutex_exit(&plun->lun_mutex); 12543 mutex_exit(&pptr->port_mutex); 12544 12545 mutex_enter(&ptgt->tgt_mutex); 12546 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12547 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12548 mutex_exit(&ptgt->tgt_mutex); 12549 12550 #ifdef DEBUG 12551 if (cdip != NULL) { 12552 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12553 fcp_trace, FCP_BUF_LEVEL_2, 0, 12554 "Old dip=%p; New dip=%p don't match", old_dip, 12555 cdip); 12556 } else { 12557 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12558 fcp_trace, FCP_BUF_LEVEL_2, 0, 12559 "Old dip=%p; New dip=NULL don't match", old_dip); 12560 } 12561 #endif 12562 12563 mutex_enter(&pptr->port_mutex); 12564 mutex_enter(&plun->lun_mutex); 12565 } 12566 12567 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12568 plun->lun_state &= ~(FCP_LUN_CHANGED); 12569 if (ndi_devi_alloc(pptr->port_dip, nname, 12570 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12571 failure++; 12572 goto end_of_fcp_create_dip; 12573 } 12574 } 12575 12576 /* 12577 * Previously all the properties for the devinfo were destroyed here 12578 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12579 * the devid property (and other properties established by the target 12580 * driver or framework) which the code does not always recreate, this 12581 * call was removed. 12582 * This opens a theoretical possibility that we may return with a 12583 * stale devid on the node if the scsi entity behind the fibre channel 12584 * lun has changed. 12585 */ 12586 12587 /* decorate the node with compatible */ 12588 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12589 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12590 failure++; 12591 goto end_of_fcp_create_dip; 12592 } 12593 12594 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12595 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12596 failure++; 12597 goto end_of_fcp_create_dip; 12598 } 12599 12600 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12601 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12602 failure++; 12603 goto end_of_fcp_create_dip; 12604 } 12605 12606 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12607 t_pwwn[16] = '\0'; 12608 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12609 != DDI_PROP_SUCCESS) { 12610 failure++; 12611 goto end_of_fcp_create_dip; 12612 } 12613 12614 /* 12615 * If there is no hard address - We might have to deal with 12616 * that by using WWN - Having said that it is important to 12617 * recognize this problem early so ssd can be informed of 12618 * the right interconnect type. 12619 */ 12620 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12621 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12622 } else { 12623 tgt_id = ptgt->tgt_d_id; 12624 } 12625 12626 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12627 tgt_id) != DDI_PROP_SUCCESS) { 12628 failure++; 12629 goto end_of_fcp_create_dip; 12630 } 12631 12632 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12633 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12634 failure++; 12635 goto end_of_fcp_create_dip; 12636 } 12637 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12638 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12639 sam_lun) != DDI_PROP_SUCCESS) { 12640 failure++; 12641 goto end_of_fcp_create_dip; 12642 } 12643 12644 end_of_fcp_create_dip: 12645 scsi_hba_nodename_compatible_free(nname, compatible); 12646 12647 if (cdip != NULL && failure) { 12648 (void) ndi_prop_remove_all(cdip); 12649 (void) ndi_devi_free(cdip); 12650 cdip = NULL; 12651 } 12652 12653 return (cdip); 12654 } 12655 12656 /* 12657 * Function: fcp_create_pip 12658 * 12659 * Description: Creates a Path Id for the LUN specified by the caller. 12660 * 12661 * Argument: plun Lun structure 12662 * link_cnt Link state count. 12663 * tgt_cnt Target state count. 12664 * 12665 * Return Value: NULL if it failed 12666 * mdi_pathinfo_t structure address if it succeeded 12667 * 12668 * Context: Kernel context 12669 */ 12670 static mdi_pathinfo_t * 12671 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12672 { 12673 int i; 12674 char buf[MAXNAMELEN]; 12675 char uaddr[MAXNAMELEN]; 12676 int failure = 0; 12677 uint32_t tgt_id; 12678 uint64_t sam_lun; 12679 struct fcp_tgt *ptgt = plun->lun_tgt; 12680 struct fcp_port *pptr = ptgt->tgt_port; 12681 dev_info_t *pdip = pptr->port_dip; 12682 mdi_pathinfo_t *pip = NULL; 12683 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12684 char *nname = NULL; 12685 char **compatible = NULL; 12686 int ncompatible; 12687 char *scsi_binding_set; 12688 char t_pwwn[17]; 12689 12690 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12691 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12692 12693 scsi_binding_set = "vhci"; 12694 12695 /* determine the node name and compatible */ 12696 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12697 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12698 12699 if (nname == NULL) { 12700 #ifdef DEBUG 12701 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12702 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12703 " compatible: %s", 12704 ddi_driver_name(pdip), ddi_get_instance(pdip), 12705 ptgt->tgt_port_wwn.raw_wwn[0], 12706 ptgt->tgt_port_wwn.raw_wwn[1], 12707 ptgt->tgt_port_wwn.raw_wwn[2], 12708 ptgt->tgt_port_wwn.raw_wwn[3], 12709 ptgt->tgt_port_wwn.raw_wwn[4], 12710 ptgt->tgt_port_wwn.raw_wwn[5], 12711 ptgt->tgt_port_wwn.raw_wwn[6], 12712 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12713 *compatible); 12714 #endif /* DEBUG */ 12715 failure++; 12716 goto end_of_fcp_create_pip; 12717 } 12718 12719 pip = fcp_find_existing_pip(plun, pdip); 12720 12721 /* 12722 * if the old_dip does not match the cdip, that means there is 12723 * some property change. since we'll be using the cdip, we need 12724 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12725 * then the dtype for the device has been updated. Offline the 12726 * the old device and create a new device with the new device type 12727 * Refer to bug: 4764752 12728 */ 12729 if (old_pip && (pip != old_pip || 12730 plun->lun_state & FCP_LUN_CHANGED)) { 12731 plun->lun_state &= ~(FCP_LUN_INIT); 12732 mutex_exit(&plun->lun_mutex); 12733 mutex_exit(&pptr->port_mutex); 12734 12735 mutex_enter(&ptgt->tgt_mutex); 12736 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12737 FCP_OFFLINE, lcount, tcount, 12738 NDI_DEVI_REMOVE, 0); 12739 mutex_exit(&ptgt->tgt_mutex); 12740 12741 if (pip != NULL) { 12742 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12743 fcp_trace, FCP_BUF_LEVEL_2, 0, 12744 "Old pip=%p; New pip=%p don't match", 12745 old_pip, pip); 12746 } else { 12747 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12748 fcp_trace, FCP_BUF_LEVEL_2, 0, 12749 "Old pip=%p; New pip=NULL don't match", 12750 old_pip); 12751 } 12752 12753 mutex_enter(&pptr->port_mutex); 12754 mutex_enter(&plun->lun_mutex); 12755 } 12756 12757 /* 12758 * Since FC_WWN_SIZE is 8 bytes and its not like the 12759 * lun_guid_size which is dependent on the target, I don't 12760 * believe the same trancation happens here UNLESS the standards 12761 * change the FC_WWN_SIZE value to something larger than 12762 * MAXNAMELEN(currently 255 bytes). 12763 */ 12764 12765 for (i = 0; i < FC_WWN_SIZE; i++) { 12766 (void) sprintf(&buf[i << 1], "%02x", 12767 ptgt->tgt_port_wwn.raw_wwn[i]); 12768 } 12769 12770 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12771 buf, plun->lun_num); 12772 12773 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12774 /* 12775 * Release the locks before calling into 12776 * mdi_pi_alloc_compatible() since this can result in a 12777 * callback into fcp which can result in a deadlock 12778 * (see bug # 4870272). 12779 * 12780 * Basically, what we are trying to avoid is the scenario where 12781 * one thread does ndi_devi_enter() and tries to grab 12782 * fcp_mutex and another does it the other way round. 12783 * 12784 * But before we do that, make sure that nobody releases the 12785 * port in the meantime. We can do this by setting a flag. 12786 */ 12787 plun->lun_state &= ~(FCP_LUN_CHANGED); 12788 pptr->port_state |= FCP_STATE_IN_MDI; 12789 mutex_exit(&plun->lun_mutex); 12790 mutex_exit(&pptr->port_mutex); 12791 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12792 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12793 fcp_log(CE_WARN, pptr->port_dip, 12794 "!path alloc failed:0x%x", plun); 12795 mutex_enter(&pptr->port_mutex); 12796 mutex_enter(&plun->lun_mutex); 12797 pptr->port_state &= ~FCP_STATE_IN_MDI; 12798 failure++; 12799 goto end_of_fcp_create_pip; 12800 } 12801 mutex_enter(&pptr->port_mutex); 12802 mutex_enter(&plun->lun_mutex); 12803 pptr->port_state &= ~FCP_STATE_IN_MDI; 12804 } else { 12805 (void) mdi_prop_remove(pip, NULL); 12806 } 12807 12808 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12809 12810 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12811 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12812 != DDI_PROP_SUCCESS) { 12813 failure++; 12814 goto end_of_fcp_create_pip; 12815 } 12816 12817 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12818 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12819 != DDI_PROP_SUCCESS) { 12820 failure++; 12821 goto end_of_fcp_create_pip; 12822 } 12823 12824 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12825 t_pwwn[16] = '\0'; 12826 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12827 != DDI_PROP_SUCCESS) { 12828 failure++; 12829 goto end_of_fcp_create_pip; 12830 } 12831 12832 /* 12833 * If there is no hard address - We might have to deal with 12834 * that by using WWN - Having said that it is important to 12835 * recognize this problem early so ssd can be informed of 12836 * the right interconnect type. 12837 */ 12838 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12839 ptgt->tgt_hard_addr != 0) { 12840 tgt_id = (uint32_t) 12841 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12842 } else { 12843 tgt_id = ptgt->tgt_d_id; 12844 } 12845 12846 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12847 != DDI_PROP_SUCCESS) { 12848 failure++; 12849 goto end_of_fcp_create_pip; 12850 } 12851 12852 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12853 != DDI_PROP_SUCCESS) { 12854 failure++; 12855 goto end_of_fcp_create_pip; 12856 } 12857 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12858 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12859 != DDI_PROP_SUCCESS) { 12860 failure++; 12861 goto end_of_fcp_create_pip; 12862 } 12863 12864 end_of_fcp_create_pip: 12865 scsi_hba_nodename_compatible_free(nname, compatible); 12866 12867 if (pip != NULL && failure) { 12868 (void) mdi_prop_remove(pip, NULL); 12869 mutex_exit(&plun->lun_mutex); 12870 mutex_exit(&pptr->port_mutex); 12871 (void) mdi_pi_free(pip, 0); 12872 mutex_enter(&pptr->port_mutex); 12873 mutex_enter(&plun->lun_mutex); 12874 pip = NULL; 12875 } 12876 12877 return (pip); 12878 } 12879 12880 static dev_info_t * 12881 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12882 { 12883 uint_t nbytes; 12884 uchar_t *bytes; 12885 uint_t nwords; 12886 uint32_t tgt_id; 12887 int *words; 12888 dev_info_t *cdip; 12889 dev_info_t *ndip; 12890 struct fcp_tgt *ptgt = plun->lun_tgt; 12891 struct fcp_port *pptr = ptgt->tgt_port; 12892 int circular; 12893 12894 ndi_devi_enter(pdip, &circular); 12895 12896 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12897 while ((cdip = ndip) != NULL) { 12898 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12899 12900 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12901 continue; 12902 } 12903 12904 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12905 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12906 &nbytes) != DDI_PROP_SUCCESS) { 12907 continue; 12908 } 12909 12910 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12911 if (bytes != NULL) { 12912 ddi_prop_free(bytes); 12913 } 12914 continue; 12915 } 12916 ASSERT(bytes != NULL); 12917 12918 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12919 ddi_prop_free(bytes); 12920 continue; 12921 } 12922 12923 ddi_prop_free(bytes); 12924 12925 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12926 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12927 &nbytes) != DDI_PROP_SUCCESS) { 12928 continue; 12929 } 12930 12931 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12932 if (bytes != NULL) { 12933 ddi_prop_free(bytes); 12934 } 12935 continue; 12936 } 12937 ASSERT(bytes != NULL); 12938 12939 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12940 ddi_prop_free(bytes); 12941 continue; 12942 } 12943 12944 ddi_prop_free(bytes); 12945 12946 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12947 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12948 &nwords) != DDI_PROP_SUCCESS) { 12949 continue; 12950 } 12951 12952 if (nwords != 1 || words == NULL) { 12953 if (words != NULL) { 12954 ddi_prop_free(words); 12955 } 12956 continue; 12957 } 12958 ASSERT(words != NULL); 12959 12960 /* 12961 * If there is no hard address - We might have to deal with 12962 * that by using WWN - Having said that it is important to 12963 * recognize this problem early so ssd can be informed of 12964 * the right interconnect type. 12965 */ 12966 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12967 ptgt->tgt_hard_addr != 0) { 12968 tgt_id = 12969 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12970 } else { 12971 tgt_id = ptgt->tgt_d_id; 12972 } 12973 12974 if (tgt_id != (uint32_t)*words) { 12975 ddi_prop_free(words); 12976 continue; 12977 } 12978 ddi_prop_free(words); 12979 12980 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12981 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12982 &nwords) != DDI_PROP_SUCCESS) { 12983 continue; 12984 } 12985 12986 if (nwords != 1 || words == NULL) { 12987 if (words != NULL) { 12988 ddi_prop_free(words); 12989 } 12990 continue; 12991 } 12992 ASSERT(words != NULL); 12993 12994 if (plun->lun_num == (uint16_t)*words) { 12995 ddi_prop_free(words); 12996 break; 12997 } 12998 ddi_prop_free(words); 12999 } 13000 ndi_devi_exit(pdip, circular); 13001 13002 return (cdip); 13003 } 13004 13005 13006 static int 13007 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 13008 { 13009 dev_info_t *pdip; 13010 char buf[MAXNAMELEN]; 13011 char uaddr[MAXNAMELEN]; 13012 int rval = FC_FAILURE; 13013 13014 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13015 13016 pdip = plun->lun_tgt->tgt_port->port_dip; 13017 13018 /* 13019 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13020 * non-NULL even when the LUN is not there as in the case when a LUN is 13021 * configured and then deleted on the device end (for T3/T4 case). In 13022 * such cases, pip will be NULL. 13023 * 13024 * If the device generates an RSCN, it will end up getting offlined when 13025 * it disappeared and a new LUN will get created when it is rediscovered 13026 * on the device. If we check for lun_cip here, the LUN will not end 13027 * up getting onlined since this function will end up returning a 13028 * FC_SUCCESS. 13029 * 13030 * The behavior is different on other devices. For instance, on a HDS, 13031 * there was no RSCN generated by the device but the next I/O generated 13032 * a check condition and rediscovery got triggered that way. So, in 13033 * such cases, this path will not be exercised 13034 */ 13035 if (pip == NULL) { 13036 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13037 fcp_trace, FCP_BUF_LEVEL_4, 0, 13038 "fcp_is_pip_present: plun->lun_cip is NULL: " 13039 "plun: %p lun state: %x num: %d target state: %x", 13040 plun, plun->lun_state, plun->lun_num, 13041 plun->lun_tgt->tgt_port->port_state); 13042 return (rval); 13043 } 13044 13045 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13046 13047 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13048 13049 if (plun->lun_old_guid) { 13050 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 13051 rval = FC_SUCCESS; 13052 } 13053 } else { 13054 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 13055 rval = FC_SUCCESS; 13056 } 13057 } 13058 return (rval); 13059 } 13060 13061 static mdi_pathinfo_t * 13062 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13063 { 13064 char buf[MAXNAMELEN]; 13065 char uaddr[MAXNAMELEN]; 13066 mdi_pathinfo_t *pip; 13067 struct fcp_tgt *ptgt = plun->lun_tgt; 13068 struct fcp_port *pptr = ptgt->tgt_port; 13069 13070 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13071 13072 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13073 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13074 13075 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13076 13077 return (pip); 13078 } 13079 13080 13081 static int 13082 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13083 int tcount, int flags, int *circ) 13084 { 13085 int rval; 13086 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13087 struct fcp_tgt *ptgt = plun->lun_tgt; 13088 dev_info_t *cdip = NULL; 13089 13090 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13091 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13092 13093 if (plun->lun_cip == NULL) { 13094 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13095 fcp_trace, FCP_BUF_LEVEL_3, 0, 13096 "fcp_online_child: plun->lun_cip is NULL: " 13097 "plun: %p state: %x num: %d target state: %x", 13098 plun, plun->lun_state, plun->lun_num, 13099 plun->lun_tgt->tgt_port->port_state); 13100 return (NDI_FAILURE); 13101 } 13102 again: 13103 if (plun->lun_mpxio == 0) { 13104 cdip = DIP(cip); 13105 mutex_exit(&plun->lun_mutex); 13106 mutex_exit(&pptr->port_mutex); 13107 13108 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13109 fcp_trace, FCP_BUF_LEVEL_3, 0, 13110 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13111 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13112 13113 /* 13114 * We could check for FCP_LUN_INIT here but chances 13115 * of getting here when it's already in FCP_LUN_INIT 13116 * is rare and a duplicate ndi_devi_online wouldn't 13117 * hurt either (as the node would already have been 13118 * in CF2) 13119 */ 13120 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13121 rval = ndi_devi_bind_driver(cdip, flags); 13122 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13123 fcp_trace, FCP_BUF_LEVEL_3, 0, 13124 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13125 } else { 13126 rval = ndi_devi_online(cdip, flags); 13127 } 13128 13129 /* 13130 * We log the message into trace buffer if the device 13131 * is "ses" and into syslog for any other device 13132 * type. This is to prevent the ndi_devi_online failure 13133 * message that appears for V880/A5K ses devices. 13134 */ 13135 if (rval == NDI_SUCCESS) { 13136 mutex_enter(&ptgt->tgt_mutex); 13137 plun->lun_state |= FCP_LUN_INIT; 13138 mutex_exit(&ptgt->tgt_mutex); 13139 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13140 fcp_log(CE_NOTE, pptr->port_dip, 13141 "!ndi_devi_online:" 13142 " failed for %s: target=%x lun=%x %x", 13143 ddi_get_name(cdip), ptgt->tgt_d_id, 13144 plun->lun_num, rval); 13145 } else { 13146 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13147 fcp_trace, FCP_BUF_LEVEL_3, 0, 13148 " !ndi_devi_online:" 13149 " failed for %s: target=%x lun=%x %x", 13150 ddi_get_name(cdip), ptgt->tgt_d_id, 13151 plun->lun_num, rval); 13152 } 13153 } else { 13154 cdip = mdi_pi_get_client(PIP(cip)); 13155 mutex_exit(&plun->lun_mutex); 13156 mutex_exit(&pptr->port_mutex); 13157 13158 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13159 fcp_trace, FCP_BUF_LEVEL_3, 0, 13160 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13161 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13162 13163 /* 13164 * Hold path and exit phci to avoid deadlock with power 13165 * management code during mdi_pi_online. 13166 */ 13167 mdi_hold_path(PIP(cip)); 13168 mdi_devi_exit_phci(pptr->port_dip, *circ); 13169 13170 rval = mdi_pi_online(PIP(cip), flags); 13171 13172 mdi_devi_enter_phci(pptr->port_dip, circ); 13173 mdi_rele_path(PIP(cip)); 13174 13175 if (rval == MDI_SUCCESS) { 13176 mutex_enter(&ptgt->tgt_mutex); 13177 plun->lun_state |= FCP_LUN_INIT; 13178 mutex_exit(&ptgt->tgt_mutex); 13179 13180 /* 13181 * Clear MPxIO path permanent disable in case 13182 * fcp hotplug dropped the offline event. 13183 */ 13184 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13185 13186 } else if (rval == MDI_NOT_SUPPORTED) { 13187 child_info_t *old_cip = cip; 13188 13189 /* 13190 * MPxIO does not support this device yet. 13191 * Enumerate in legacy mode. 13192 */ 13193 mutex_enter(&pptr->port_mutex); 13194 mutex_enter(&plun->lun_mutex); 13195 plun->lun_mpxio = 0; 13196 plun->lun_cip = NULL; 13197 cdip = fcp_create_dip(plun, lcount, tcount); 13198 plun->lun_cip = cip = CIP(cdip); 13199 if (cip == NULL) { 13200 fcp_log(CE_WARN, pptr->port_dip, 13201 "!fcp_online_child: " 13202 "Create devinfo failed for LU=%p", plun); 13203 mutex_exit(&plun->lun_mutex); 13204 13205 mutex_enter(&ptgt->tgt_mutex); 13206 plun->lun_state |= FCP_LUN_OFFLINE; 13207 mutex_exit(&ptgt->tgt_mutex); 13208 13209 mutex_exit(&pptr->port_mutex); 13210 13211 /* 13212 * free the mdi_pathinfo node 13213 */ 13214 (void) mdi_pi_free(PIP(old_cip), 0); 13215 } else { 13216 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13217 fcp_trace, FCP_BUF_LEVEL_3, 0, 13218 "fcp_online_child: creating devinfo " 13219 "node 0x%p for plun 0x%p", 13220 cip, plun); 13221 mutex_exit(&plun->lun_mutex); 13222 mutex_exit(&pptr->port_mutex); 13223 /* 13224 * free the mdi_pathinfo node 13225 */ 13226 (void) mdi_pi_free(PIP(old_cip), 0); 13227 mutex_enter(&pptr->port_mutex); 13228 mutex_enter(&plun->lun_mutex); 13229 goto again; 13230 } 13231 } else { 13232 if (cdip) { 13233 fcp_log(CE_NOTE, pptr->port_dip, 13234 "!fcp_online_child: mdi_pi_online:" 13235 " failed for %s: target=%x lun=%x %x", 13236 ddi_get_name(cdip), ptgt->tgt_d_id, 13237 plun->lun_num, rval); 13238 } 13239 } 13240 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13241 } 13242 13243 if (rval == NDI_SUCCESS) { 13244 if (cdip) { 13245 (void) ndi_event_retrieve_cookie( 13246 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13247 &fcp_insert_eid, NDI_EVENT_NOPASS); 13248 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13249 cdip, fcp_insert_eid, NULL); 13250 } 13251 } 13252 mutex_enter(&pptr->port_mutex); 13253 mutex_enter(&plun->lun_mutex); 13254 return (rval); 13255 } 13256 13257 /* ARGSUSED */ 13258 static int 13259 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13260 int tcount, int flags, int *circ) 13261 { 13262 int rval; 13263 int lun_mpxio; 13264 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13265 struct fcp_tgt *ptgt = plun->lun_tgt; 13266 dev_info_t *cdip; 13267 13268 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13269 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13270 13271 if (plun->lun_cip == NULL) { 13272 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13273 fcp_trace, FCP_BUF_LEVEL_3, 0, 13274 "fcp_offline_child: plun->lun_cip is NULL: " 13275 "plun: %p lun state: %x num: %d target state: %x", 13276 plun, plun->lun_state, plun->lun_num, 13277 plun->lun_tgt->tgt_port->port_state); 13278 return (NDI_FAILURE); 13279 } 13280 13281 /* 13282 * We will use this value twice. Make a copy to be sure we use 13283 * the same value in both places. 13284 */ 13285 lun_mpxio = plun->lun_mpxio; 13286 13287 if (lun_mpxio == 0) { 13288 cdip = DIP(cip); 13289 mutex_exit(&plun->lun_mutex); 13290 mutex_exit(&pptr->port_mutex); 13291 rval = ndi_devi_offline(DIP(cip), flags); 13292 if (rval != NDI_SUCCESS) { 13293 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13294 fcp_trace, FCP_BUF_LEVEL_3, 0, 13295 "fcp_offline_child: ndi_devi_offline failed " 13296 "rval=%x cip=%p", rval, cip); 13297 } 13298 } else { 13299 cdip = mdi_pi_get_client(PIP(cip)); 13300 mutex_exit(&plun->lun_mutex); 13301 mutex_exit(&pptr->port_mutex); 13302 13303 /* 13304 * Exit phci to avoid deadlock with power management code 13305 * during mdi_pi_offline 13306 */ 13307 mdi_hold_path(PIP(cip)); 13308 mdi_devi_exit_phci(pptr->port_dip, *circ); 13309 13310 rval = mdi_pi_offline(PIP(cip), flags); 13311 13312 mdi_devi_enter_phci(pptr->port_dip, circ); 13313 mdi_rele_path(PIP(cip)); 13314 13315 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13316 } 13317 13318 mutex_enter(&ptgt->tgt_mutex); 13319 plun->lun_state &= ~FCP_LUN_INIT; 13320 mutex_exit(&ptgt->tgt_mutex); 13321 13322 if (rval == NDI_SUCCESS) { 13323 cdip = NULL; 13324 if (flags & NDI_DEVI_REMOVE) { 13325 mutex_enter(&plun->lun_mutex); 13326 /* 13327 * If the guid of the LUN changes, lun_cip will not 13328 * equal to cip, and after offlining the LUN with the 13329 * old guid, we should keep lun_cip since it's the cip 13330 * of the LUN with the new guid. 13331 * Otherwise remove our reference to child node. 13332 * 13333 * This must be done before the child node is freed, 13334 * otherwise other threads could see a stale lun_cip 13335 * pointer. 13336 */ 13337 if (plun->lun_cip == cip) { 13338 plun->lun_cip = NULL; 13339 } 13340 if (plun->lun_old_guid) { 13341 kmem_free(plun->lun_old_guid, 13342 plun->lun_old_guid_size); 13343 plun->lun_old_guid = NULL; 13344 plun->lun_old_guid_size = 0; 13345 } 13346 mutex_exit(&plun->lun_mutex); 13347 } 13348 } 13349 13350 if (lun_mpxio != 0) { 13351 if (rval == NDI_SUCCESS) { 13352 /* 13353 * Clear MPxIO path permanent disable as the path is 13354 * already offlined. 13355 */ 13356 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13357 13358 if (flags & NDI_DEVI_REMOVE) { 13359 (void) mdi_pi_free(PIP(cip), 0); 13360 } 13361 } else { 13362 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13363 fcp_trace, FCP_BUF_LEVEL_3, 0, 13364 "fcp_offline_child: mdi_pi_offline failed " 13365 "rval=%x cip=%p", rval, cip); 13366 } 13367 } 13368 13369 mutex_enter(&pptr->port_mutex); 13370 mutex_enter(&plun->lun_mutex); 13371 13372 if (cdip) { 13373 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13374 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13375 " target=%x lun=%x", "ndi_offline", 13376 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13377 } 13378 13379 return (rval); 13380 } 13381 13382 static void 13383 fcp_remove_child(struct fcp_lun *plun) 13384 { 13385 child_info_t *cip; 13386 int circ; 13387 13388 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13389 13390 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13391 if (plun->lun_mpxio == 0) { 13392 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13393 (void) ndi_devi_free(DIP(plun->lun_cip)); 13394 plun->lun_cip = NULL; 13395 } else { 13396 /* 13397 * Clear reference to the child node in the lun. 13398 * This must be done before freeing it with mdi_pi_free 13399 * and with lun_mutex held so that other threads always 13400 * see either valid lun_cip or NULL when holding 13401 * lun_mutex. We keep a copy in cip. 13402 */ 13403 cip = plun->lun_cip; 13404 plun->lun_cip = NULL; 13405 13406 mutex_exit(&plun->lun_mutex); 13407 mutex_exit(&plun->lun_tgt->tgt_mutex); 13408 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13409 13410 mdi_devi_enter( 13411 plun->lun_tgt->tgt_port->port_dip, &circ); 13412 13413 /* 13414 * Exit phci to avoid deadlock with power management 13415 * code during mdi_pi_offline 13416 */ 13417 mdi_hold_path(PIP(cip)); 13418 mdi_devi_exit_phci( 13419 plun->lun_tgt->tgt_port->port_dip, circ); 13420 (void) mdi_pi_offline(PIP(cip), 13421 NDI_DEVI_REMOVE); 13422 mdi_devi_enter_phci( 13423 plun->lun_tgt->tgt_port->port_dip, &circ); 13424 mdi_rele_path(PIP(cip)); 13425 13426 mdi_devi_exit( 13427 plun->lun_tgt->tgt_port->port_dip, circ); 13428 13429 FCP_TRACE(fcp_logq, 13430 plun->lun_tgt->tgt_port->port_instbuf, 13431 fcp_trace, FCP_BUF_LEVEL_3, 0, 13432 "lun=%p pip freed %p", plun, cip); 13433 13434 (void) mdi_prop_remove(PIP(cip), NULL); 13435 (void) mdi_pi_free(PIP(cip), 0); 13436 13437 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13438 mutex_enter(&plun->lun_tgt->tgt_mutex); 13439 mutex_enter(&plun->lun_mutex); 13440 } 13441 } else { 13442 plun->lun_cip = NULL; 13443 } 13444 } 13445 13446 /* 13447 * called when a timeout occurs 13448 * 13449 * can be scheduled during an attach or resume (if not already running) 13450 * 13451 * one timeout is set up for all ports 13452 * 13453 * acquires and releases the global mutex 13454 */ 13455 /*ARGSUSED*/ 13456 static void 13457 fcp_watch(void *arg) 13458 { 13459 struct fcp_port *pptr; 13460 struct fcp_ipkt *icmd; 13461 struct fcp_ipkt *nicmd; 13462 struct fcp_pkt *cmd; 13463 struct fcp_pkt *ncmd; 13464 struct fcp_pkt *tail; 13465 struct fcp_pkt *pcmd; 13466 struct fcp_pkt *save_head; 13467 struct fcp_port *save_port; 13468 13469 /* increment global watchdog time */ 13470 fcp_watchdog_time += fcp_watchdog_timeout; 13471 13472 mutex_enter(&fcp_global_mutex); 13473 13474 /* scan each port in our list */ 13475 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13476 save_port = fcp_port_head; 13477 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13478 mutex_exit(&fcp_global_mutex); 13479 13480 mutex_enter(&pptr->port_mutex); 13481 if (pptr->port_ipkt_list == NULL && 13482 (pptr->port_state & (FCP_STATE_SUSPENDED | 13483 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13484 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13485 mutex_exit(&pptr->port_mutex); 13486 mutex_enter(&fcp_global_mutex); 13487 goto end_of_watchdog; 13488 } 13489 13490 /* 13491 * We check if a list of targets need to be offlined. 13492 */ 13493 if (pptr->port_offline_tgts) { 13494 fcp_scan_offline_tgts(pptr); 13495 } 13496 13497 /* 13498 * We check if a list of luns need to be offlined. 13499 */ 13500 if (pptr->port_offline_luns) { 13501 fcp_scan_offline_luns(pptr); 13502 } 13503 13504 /* 13505 * We check if a list of targets or luns need to be reset. 13506 */ 13507 if (pptr->port_reset_list) { 13508 fcp_check_reset_delay(pptr); 13509 } 13510 13511 mutex_exit(&pptr->port_mutex); 13512 13513 /* 13514 * This is where the pending commands (pkt) are checked for 13515 * timeout. 13516 */ 13517 mutex_enter(&pptr->port_pkt_mutex); 13518 tail = pptr->port_pkt_tail; 13519 13520 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13521 cmd != NULL; cmd = ncmd) { 13522 ncmd = cmd->cmd_next; 13523 /* 13524 * If a command is in this queue the bit CFLAG_IN_QUEUE 13525 * must be set. 13526 */ 13527 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13528 /* 13529 * FCP_INVALID_TIMEOUT will be set for those 13530 * command that need to be failed. Mostly those 13531 * cmds that could not be queued down for the 13532 * "timeout" value. cmd->cmd_timeout is used 13533 * to try and requeue the command regularly. 13534 */ 13535 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13536 /* 13537 * This command hasn't timed out yet. Let's 13538 * go to the next one. 13539 */ 13540 pcmd = cmd; 13541 goto end_of_loop; 13542 } 13543 13544 if (cmd == pptr->port_pkt_head) { 13545 ASSERT(pcmd == NULL); 13546 pptr->port_pkt_head = cmd->cmd_next; 13547 } else { 13548 ASSERT(pcmd != NULL); 13549 pcmd->cmd_next = cmd->cmd_next; 13550 } 13551 13552 if (cmd == pptr->port_pkt_tail) { 13553 ASSERT(cmd->cmd_next == NULL); 13554 pptr->port_pkt_tail = pcmd; 13555 if (pcmd) { 13556 pcmd->cmd_next = NULL; 13557 } 13558 } 13559 cmd->cmd_next = NULL; 13560 13561 /* 13562 * save the current head before dropping the 13563 * mutex - If the head doesn't remain the 13564 * same after re acquiring the mutex, just 13565 * bail out and revisit on next tick. 13566 * 13567 * PS: The tail pointer can change as the commands 13568 * get requeued after failure to retransport 13569 */ 13570 save_head = pptr->port_pkt_head; 13571 mutex_exit(&pptr->port_pkt_mutex); 13572 13573 if (cmd->cmd_fp_pkt->pkt_timeout == 13574 FCP_INVALID_TIMEOUT) { 13575 struct scsi_pkt *pkt = cmd->cmd_pkt; 13576 struct fcp_lun *plun; 13577 struct fcp_tgt *ptgt; 13578 13579 plun = ADDR2LUN(&pkt->pkt_address); 13580 ptgt = plun->lun_tgt; 13581 13582 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13583 fcp_trace, FCP_BUF_LEVEL_2, 0, 13584 "SCSI cmd 0x%x to D_ID=%x timed out", 13585 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13586 13587 cmd->cmd_state == FCP_PKT_ABORTING ? 13588 fcp_fail_cmd(cmd, CMD_RESET, 13589 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13590 CMD_TIMEOUT, STAT_ABORTED); 13591 } else { 13592 fcp_retransport_cmd(pptr, cmd); 13593 } 13594 mutex_enter(&pptr->port_pkt_mutex); 13595 if (save_head && save_head != pptr->port_pkt_head) { 13596 /* 13597 * Looks like linked list got changed (mostly 13598 * happens when an an OFFLINE LUN code starts 13599 * returning overflow queue commands in 13600 * parallel. So bail out and revisit during 13601 * next tick 13602 */ 13603 break; 13604 } 13605 end_of_loop: 13606 /* 13607 * Scan only upto the previously known tail pointer 13608 * to avoid excessive processing - lots of new packets 13609 * could have been added to the tail or the old ones 13610 * re-queued. 13611 */ 13612 if (cmd == tail) { 13613 break; 13614 } 13615 } 13616 mutex_exit(&pptr->port_pkt_mutex); 13617 13618 mutex_enter(&pptr->port_mutex); 13619 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13620 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13621 13622 nicmd = icmd->ipkt_next; 13623 if ((icmd->ipkt_restart != 0) && 13624 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13625 /* packet has not timed out */ 13626 continue; 13627 } 13628 13629 /* time for packet re-transport */ 13630 if (icmd == pptr->port_ipkt_list) { 13631 pptr->port_ipkt_list = icmd->ipkt_next; 13632 if (pptr->port_ipkt_list) { 13633 pptr->port_ipkt_list->ipkt_prev = 13634 NULL; 13635 } 13636 } else { 13637 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13638 if (icmd->ipkt_next) { 13639 icmd->ipkt_next->ipkt_prev = 13640 icmd->ipkt_prev; 13641 } 13642 } 13643 icmd->ipkt_next = NULL; 13644 icmd->ipkt_prev = NULL; 13645 mutex_exit(&pptr->port_mutex); 13646 13647 if (fcp_is_retryable(icmd)) { 13648 fc_ulp_rscn_info_t *rscnp = 13649 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13650 pkt_ulp_rscn_infop; 13651 13652 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13653 fcp_trace, FCP_BUF_LEVEL_2, 0, 13654 "%x to D_ID=%x Retrying..", 13655 icmd->ipkt_opcode, 13656 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13657 13658 /* 13659 * Update the RSCN count in the packet 13660 * before resending. 13661 */ 13662 13663 if (rscnp != NULL) { 13664 rscnp->ulp_rscn_count = 13665 fc_ulp_get_rscn_count(pptr-> 13666 port_fp_handle); 13667 } 13668 13669 mutex_enter(&pptr->port_mutex); 13670 mutex_enter(&ptgt->tgt_mutex); 13671 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13672 mutex_exit(&ptgt->tgt_mutex); 13673 mutex_exit(&pptr->port_mutex); 13674 switch (icmd->ipkt_opcode) { 13675 int rval; 13676 case LA_ELS_PLOGI: 13677 if ((rval = fc_ulp_login( 13678 pptr->port_fp_handle, 13679 &icmd->ipkt_fpkt, 1)) == 13680 FC_SUCCESS) { 13681 mutex_enter( 13682 &pptr->port_mutex); 13683 continue; 13684 } 13685 if (fcp_handle_ipkt_errors( 13686 pptr, ptgt, icmd, rval, 13687 "PLOGI") == DDI_SUCCESS) { 13688 mutex_enter( 13689 &pptr->port_mutex); 13690 continue; 13691 } 13692 break; 13693 13694 case LA_ELS_PRLI: 13695 if ((rval = fc_ulp_issue_els( 13696 pptr->port_fp_handle, 13697 icmd->ipkt_fpkt)) == 13698 FC_SUCCESS) { 13699 mutex_enter( 13700 &pptr->port_mutex); 13701 continue; 13702 } 13703 if (fcp_handle_ipkt_errors( 13704 pptr, ptgt, icmd, rval, 13705 "PRLI") == DDI_SUCCESS) { 13706 mutex_enter( 13707 &pptr->port_mutex); 13708 continue; 13709 } 13710 break; 13711 13712 default: 13713 if ((rval = fcp_transport( 13714 pptr->port_fp_handle, 13715 icmd->ipkt_fpkt, 1)) == 13716 FC_SUCCESS) { 13717 mutex_enter( 13718 &pptr->port_mutex); 13719 continue; 13720 } 13721 if (fcp_handle_ipkt_errors( 13722 pptr, ptgt, icmd, rval, 13723 "PRLI") == DDI_SUCCESS) { 13724 mutex_enter( 13725 &pptr->port_mutex); 13726 continue; 13727 } 13728 break; 13729 } 13730 } else { 13731 mutex_exit(&ptgt->tgt_mutex); 13732 mutex_exit(&pptr->port_mutex); 13733 } 13734 } else { 13735 fcp_print_error(icmd->ipkt_fpkt); 13736 } 13737 13738 (void) fcp_call_finish_init(pptr, ptgt, 13739 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13740 icmd->ipkt_cause); 13741 fcp_icmd_free(pptr, icmd); 13742 mutex_enter(&pptr->port_mutex); 13743 } 13744 13745 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13746 mutex_exit(&pptr->port_mutex); 13747 mutex_enter(&fcp_global_mutex); 13748 13749 end_of_watchdog: 13750 /* 13751 * Bail out early before getting into trouble 13752 */ 13753 if (save_port != fcp_port_head) { 13754 break; 13755 } 13756 } 13757 13758 if (fcp_watchdog_init > 0) { 13759 /* reschedule timeout to go again */ 13760 fcp_watchdog_id = 13761 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13762 } 13763 mutex_exit(&fcp_global_mutex); 13764 } 13765 13766 13767 static void 13768 fcp_check_reset_delay(struct fcp_port *pptr) 13769 { 13770 uint32_t tgt_cnt; 13771 int level; 13772 struct fcp_tgt *ptgt; 13773 struct fcp_lun *plun; 13774 struct fcp_reset_elem *cur = NULL; 13775 struct fcp_reset_elem *next = NULL; 13776 struct fcp_reset_elem *prev = NULL; 13777 13778 ASSERT(mutex_owned(&pptr->port_mutex)); 13779 13780 next = pptr->port_reset_list; 13781 while ((cur = next) != NULL) { 13782 next = cur->next; 13783 13784 if (cur->timeout < fcp_watchdog_time) { 13785 prev = cur; 13786 continue; 13787 } 13788 13789 ptgt = cur->tgt; 13790 plun = cur->lun; 13791 tgt_cnt = cur->tgt_cnt; 13792 13793 if (ptgt) { 13794 level = RESET_TARGET; 13795 } else { 13796 ASSERT(plun != NULL); 13797 level = RESET_LUN; 13798 ptgt = plun->lun_tgt; 13799 } 13800 if (prev) { 13801 prev->next = next; 13802 } else { 13803 /* 13804 * Because we drop port mutex while doing aborts for 13805 * packets, we can't rely on reset_list pointing to 13806 * our head 13807 */ 13808 if (cur == pptr->port_reset_list) { 13809 pptr->port_reset_list = next; 13810 } else { 13811 struct fcp_reset_elem *which; 13812 13813 which = pptr->port_reset_list; 13814 while (which && which->next != cur) { 13815 which = which->next; 13816 } 13817 ASSERT(which != NULL); 13818 13819 which->next = next; 13820 prev = which; 13821 } 13822 } 13823 13824 kmem_free(cur, sizeof (*cur)); 13825 13826 if (tgt_cnt == ptgt->tgt_change_cnt) { 13827 mutex_enter(&ptgt->tgt_mutex); 13828 if (level == RESET_TARGET) { 13829 fcp_update_tgt_state(ptgt, 13830 FCP_RESET, FCP_LUN_BUSY); 13831 } else { 13832 fcp_update_lun_state(plun, 13833 FCP_RESET, FCP_LUN_BUSY); 13834 } 13835 mutex_exit(&ptgt->tgt_mutex); 13836 13837 mutex_exit(&pptr->port_mutex); 13838 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13839 mutex_enter(&pptr->port_mutex); 13840 } 13841 } 13842 } 13843 13844 13845 static void 13846 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13847 struct fcp_lun *rlun, int tgt_cnt) 13848 { 13849 int rval; 13850 struct fcp_lun *tlun, *nlun; 13851 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13852 *cmd = NULL, *head = NULL, 13853 *tail = NULL; 13854 13855 mutex_enter(&pptr->port_pkt_mutex); 13856 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13857 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13858 struct fcp_tgt *ptgt = plun->lun_tgt; 13859 13860 ncmd = cmd->cmd_next; 13861 13862 if (ptgt != ttgt && plun != rlun) { 13863 pcmd = cmd; 13864 continue; 13865 } 13866 13867 if (pcmd != NULL) { 13868 ASSERT(pptr->port_pkt_head != cmd); 13869 pcmd->cmd_next = ncmd; 13870 } else { 13871 ASSERT(cmd == pptr->port_pkt_head); 13872 pptr->port_pkt_head = ncmd; 13873 } 13874 if (pptr->port_pkt_tail == cmd) { 13875 ASSERT(cmd->cmd_next == NULL); 13876 pptr->port_pkt_tail = pcmd; 13877 if (pcmd != NULL) { 13878 pcmd->cmd_next = NULL; 13879 } 13880 } 13881 13882 if (head == NULL) { 13883 head = tail = cmd; 13884 } else { 13885 ASSERT(tail != NULL); 13886 tail->cmd_next = cmd; 13887 tail = cmd; 13888 } 13889 cmd->cmd_next = NULL; 13890 } 13891 mutex_exit(&pptr->port_pkt_mutex); 13892 13893 for (cmd = head; cmd != NULL; cmd = ncmd) { 13894 struct scsi_pkt *pkt = cmd->cmd_pkt; 13895 13896 ncmd = cmd->cmd_next; 13897 ASSERT(pkt != NULL); 13898 13899 mutex_enter(&pptr->port_mutex); 13900 if (ttgt->tgt_change_cnt == tgt_cnt) { 13901 mutex_exit(&pptr->port_mutex); 13902 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13903 pkt->pkt_reason = CMD_RESET; 13904 pkt->pkt_statistics |= STAT_DEV_RESET; 13905 cmd->cmd_state = FCP_PKT_IDLE; 13906 fcp_post_callback(cmd); 13907 } else { 13908 mutex_exit(&pptr->port_mutex); 13909 } 13910 } 13911 13912 /* 13913 * If the FCA will return all the commands in its queue then our 13914 * work is easy, just return. 13915 */ 13916 13917 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13918 return; 13919 } 13920 13921 /* 13922 * For RESET_LUN get hold of target pointer 13923 */ 13924 if (ttgt == NULL) { 13925 ASSERT(rlun != NULL); 13926 13927 ttgt = rlun->lun_tgt; 13928 13929 ASSERT(ttgt != NULL); 13930 } 13931 13932 /* 13933 * There are some severe race conditions here. 13934 * While we are trying to abort the pkt, it might be completing 13935 * so mark it aborted and if the abort does not succeed then 13936 * handle it in the watch thread. 13937 */ 13938 mutex_enter(&ttgt->tgt_mutex); 13939 nlun = ttgt->tgt_lun; 13940 mutex_exit(&ttgt->tgt_mutex); 13941 while ((tlun = nlun) != NULL) { 13942 int restart = 0; 13943 if (rlun && rlun != tlun) { 13944 mutex_enter(&ttgt->tgt_mutex); 13945 nlun = tlun->lun_next; 13946 mutex_exit(&ttgt->tgt_mutex); 13947 continue; 13948 } 13949 mutex_enter(&tlun->lun_mutex); 13950 cmd = tlun->lun_pkt_head; 13951 while (cmd != NULL) { 13952 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13953 struct scsi_pkt *pkt; 13954 13955 restart = 1; 13956 cmd->cmd_state = FCP_PKT_ABORTING; 13957 mutex_exit(&tlun->lun_mutex); 13958 rval = fc_ulp_abort(pptr->port_fp_handle, 13959 cmd->cmd_fp_pkt, KM_SLEEP); 13960 if (rval == FC_SUCCESS) { 13961 pkt = cmd->cmd_pkt; 13962 pkt->pkt_reason = CMD_RESET; 13963 pkt->pkt_statistics |= STAT_DEV_RESET; 13964 cmd->cmd_state = FCP_PKT_IDLE; 13965 fcp_post_callback(cmd); 13966 } else { 13967 caddr_t msg; 13968 13969 (void) fc_ulp_error(rval, &msg); 13970 13971 /* 13972 * This part is tricky. The abort 13973 * failed and now the command could 13974 * be completing. The cmd_state == 13975 * FCP_PKT_ABORTING should save 13976 * us in fcp_cmd_callback. If we 13977 * are already aborting ignore the 13978 * command in fcp_cmd_callback. 13979 * Here we leave this packet for 20 13980 * sec to be aborted in the 13981 * fcp_watch thread. 13982 */ 13983 fcp_log(CE_WARN, pptr->port_dip, 13984 "!Abort failed after reset %s", 13985 msg); 13986 13987 cmd->cmd_timeout = 13988 fcp_watchdog_time + 13989 cmd->cmd_pkt->pkt_time + 13990 FCP_FAILED_DELAY; 13991 13992 cmd->cmd_fp_pkt->pkt_timeout = 13993 FCP_INVALID_TIMEOUT; 13994 /* 13995 * This is a hack, cmd is put in the 13996 * overflow queue so that it can be 13997 * timed out finally 13998 */ 13999 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14000 14001 mutex_enter(&pptr->port_pkt_mutex); 14002 if (pptr->port_pkt_head) { 14003 ASSERT(pptr->port_pkt_tail 14004 != NULL); 14005 pptr->port_pkt_tail->cmd_next 14006 = cmd; 14007 pptr->port_pkt_tail = cmd; 14008 } else { 14009 ASSERT(pptr->port_pkt_tail 14010 == NULL); 14011 pptr->port_pkt_head = 14012 pptr->port_pkt_tail 14013 = cmd; 14014 } 14015 cmd->cmd_next = NULL; 14016 mutex_exit(&pptr->port_pkt_mutex); 14017 } 14018 mutex_enter(&tlun->lun_mutex); 14019 cmd = tlun->lun_pkt_head; 14020 } else { 14021 cmd = cmd->cmd_forw; 14022 } 14023 } 14024 mutex_exit(&tlun->lun_mutex); 14025 14026 mutex_enter(&ttgt->tgt_mutex); 14027 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14028 mutex_exit(&ttgt->tgt_mutex); 14029 14030 mutex_enter(&pptr->port_mutex); 14031 if (tgt_cnt != ttgt->tgt_change_cnt) { 14032 mutex_exit(&pptr->port_mutex); 14033 return; 14034 } else { 14035 mutex_exit(&pptr->port_mutex); 14036 } 14037 } 14038 } 14039 14040 14041 /* 14042 * unlink the soft state, returning the soft state found (if any) 14043 * 14044 * acquires and releases the global mutex 14045 */ 14046 struct fcp_port * 14047 fcp_soft_state_unlink(struct fcp_port *pptr) 14048 { 14049 struct fcp_port *hptr; /* ptr index */ 14050 struct fcp_port *tptr; /* prev hptr */ 14051 14052 mutex_enter(&fcp_global_mutex); 14053 for (hptr = fcp_port_head, tptr = NULL; 14054 hptr != NULL; 14055 tptr = hptr, hptr = hptr->port_next) { 14056 if (hptr == pptr) { 14057 /* we found a match -- remove this item */ 14058 if (tptr == NULL) { 14059 /* we're at the head of the list */ 14060 fcp_port_head = hptr->port_next; 14061 } else { 14062 tptr->port_next = hptr->port_next; 14063 } 14064 break; /* success */ 14065 } 14066 } 14067 if (fcp_port_head == NULL) { 14068 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14069 } 14070 mutex_exit(&fcp_global_mutex); 14071 return (hptr); 14072 } 14073 14074 14075 /* 14076 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14077 * WWN and a LUN number 14078 */ 14079 /* ARGSUSED */ 14080 static struct fcp_lun * 14081 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14082 { 14083 int hash; 14084 struct fcp_tgt *ptgt; 14085 struct fcp_lun *plun; 14086 14087 ASSERT(mutex_owned(&pptr->port_mutex)); 14088 14089 hash = FCP_HASH(wwn); 14090 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14091 ptgt = ptgt->tgt_next) { 14092 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14093 sizeof (ptgt->tgt_port_wwn)) == 0) { 14094 mutex_enter(&ptgt->tgt_mutex); 14095 for (plun = ptgt->tgt_lun; 14096 plun != NULL; 14097 plun = plun->lun_next) { 14098 if (plun->lun_num == lun) { 14099 mutex_exit(&ptgt->tgt_mutex); 14100 return (plun); 14101 } 14102 } 14103 mutex_exit(&ptgt->tgt_mutex); 14104 return (NULL); 14105 } 14106 } 14107 return (NULL); 14108 } 14109 14110 /* 14111 * Function: fcp_prepare_pkt 14112 * 14113 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14114 * for fcp_start(). It binds the data or partially maps it. 14115 * Builds the FCP header and starts the initialization of the 14116 * Fibre Channel header. 14117 * 14118 * Argument: *pptr FCP port. 14119 * *cmd FCP packet. 14120 * *plun LUN the command will be sent to. 14121 * 14122 * Context: User, Kernel and Interrupt context. 14123 */ 14124 static void 14125 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14126 struct fcp_lun *plun) 14127 { 14128 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14129 struct fcp_tgt *ptgt = plun->lun_tgt; 14130 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14131 14132 ASSERT(cmd->cmd_pkt->pkt_comp || 14133 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14134 14135 if (cmd->cmd_pkt->pkt_numcookies) { 14136 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14137 fcmd->fcp_cntl.cntl_read_data = 1; 14138 fcmd->fcp_cntl.cntl_write_data = 0; 14139 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14140 } else { 14141 fcmd->fcp_cntl.cntl_read_data = 0; 14142 fcmd->fcp_cntl.cntl_write_data = 1; 14143 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14144 } 14145 14146 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14147 14148 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14149 ASSERT(fpkt->pkt_data_cookie_cnt <= 14150 pptr->port_data_dma_attr.dma_attr_sgllen); 14151 14152 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14153 14154 /* FCA needs pkt_datalen to be set */ 14155 fpkt->pkt_datalen = cmd->cmd_dmacount; 14156 fcmd->fcp_data_len = cmd->cmd_dmacount; 14157 } else { 14158 fcmd->fcp_cntl.cntl_read_data = 0; 14159 fcmd->fcp_cntl.cntl_write_data = 0; 14160 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14161 fpkt->pkt_datalen = 0; 14162 fcmd->fcp_data_len = 0; 14163 } 14164 14165 /* set up the Tagged Queuing type */ 14166 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14167 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14168 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14169 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14170 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14171 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14172 } else { 14173 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14174 } 14175 14176 fcmd->fcp_ent_addr = plun->lun_addr; 14177 14178 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14179 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14180 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14181 } else { 14182 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14183 } 14184 14185 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14186 cmd->cmd_pkt->pkt_state = 0; 14187 cmd->cmd_pkt->pkt_statistics = 0; 14188 cmd->cmd_pkt->pkt_resid = 0; 14189 14190 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14191 14192 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14193 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14194 fpkt->pkt_comp = NULL; 14195 } else { 14196 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14197 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14198 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14199 } 14200 fpkt->pkt_comp = fcp_cmd_callback; 14201 } 14202 14203 mutex_enter(&pptr->port_mutex); 14204 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14205 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14206 } 14207 mutex_exit(&pptr->port_mutex); 14208 14209 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14210 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14211 14212 /* 14213 * Save a few kernel cycles here 14214 */ 14215 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14216 } 14217 14218 static void 14219 fcp_post_callback(struct fcp_pkt *cmd) 14220 { 14221 scsi_hba_pkt_comp(cmd->cmd_pkt); 14222 } 14223 14224 14225 /* 14226 * called to do polled I/O by fcp_start() 14227 * 14228 * return a transport status value, i.e. TRAN_ACCECPT for success 14229 */ 14230 static int 14231 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14232 { 14233 int rval; 14234 14235 #ifdef DEBUG 14236 mutex_enter(&pptr->port_pkt_mutex); 14237 pptr->port_npkts++; 14238 mutex_exit(&pptr->port_pkt_mutex); 14239 #endif /* DEBUG */ 14240 14241 if (cmd->cmd_fp_pkt->pkt_timeout) { 14242 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14243 } else { 14244 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14245 } 14246 14247 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14248 14249 cmd->cmd_state = FCP_PKT_ISSUED; 14250 14251 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14252 14253 #ifdef DEBUG 14254 mutex_enter(&pptr->port_pkt_mutex); 14255 pptr->port_npkts--; 14256 mutex_exit(&pptr->port_pkt_mutex); 14257 #endif /* DEBUG */ 14258 14259 cmd->cmd_state = FCP_PKT_IDLE; 14260 14261 switch (rval) { 14262 case FC_SUCCESS: 14263 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14264 fcp_complete_pkt(cmd->cmd_fp_pkt); 14265 rval = TRAN_ACCEPT; 14266 } else { 14267 rval = TRAN_FATAL_ERROR; 14268 } 14269 break; 14270 14271 case FC_TRAN_BUSY: 14272 rval = TRAN_BUSY; 14273 cmd->cmd_pkt->pkt_resid = 0; 14274 break; 14275 14276 case FC_BADPACKET: 14277 rval = TRAN_BADPKT; 14278 break; 14279 14280 default: 14281 rval = TRAN_FATAL_ERROR; 14282 break; 14283 } 14284 14285 return (rval); 14286 } 14287 14288 14289 /* 14290 * called by some of the following transport-called routines to convert 14291 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14292 */ 14293 static struct fcp_port * 14294 fcp_dip2port(dev_info_t *dip) 14295 { 14296 int instance; 14297 14298 instance = ddi_get_instance(dip); 14299 return (ddi_get_soft_state(fcp_softstate, instance)); 14300 } 14301 14302 14303 /* 14304 * called internally to return a LUN given a dip 14305 */ 14306 struct fcp_lun * 14307 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14308 { 14309 struct fcp_tgt *ptgt; 14310 struct fcp_lun *plun; 14311 int i; 14312 14313 14314 ASSERT(mutex_owned(&pptr->port_mutex)); 14315 14316 for (i = 0; i < FCP_NUM_HASH; i++) { 14317 for (ptgt = pptr->port_tgt_hash_table[i]; 14318 ptgt != NULL; 14319 ptgt = ptgt->tgt_next) { 14320 mutex_enter(&ptgt->tgt_mutex); 14321 for (plun = ptgt->tgt_lun; plun != NULL; 14322 plun = plun->lun_next) { 14323 mutex_enter(&plun->lun_mutex); 14324 if (plun->lun_cip == cip) { 14325 mutex_exit(&plun->lun_mutex); 14326 mutex_exit(&ptgt->tgt_mutex); 14327 return (plun); /* match found */ 14328 } 14329 mutex_exit(&plun->lun_mutex); 14330 } 14331 mutex_exit(&ptgt->tgt_mutex); 14332 } 14333 } 14334 return (NULL); /* no LUN found */ 14335 } 14336 14337 /* 14338 * pass an element to the hotplug list, kick the hotplug thread 14339 * and wait for the element to get processed by the hotplug thread. 14340 * on return the element is freed. 14341 * 14342 * return zero success and non-zero on failure 14343 * 14344 * acquires/releases the target mutex 14345 * 14346 */ 14347 static int 14348 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14349 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14350 { 14351 struct fcp_hp_elem *elem; 14352 int rval; 14353 14354 mutex_enter(&plun->lun_tgt->tgt_mutex); 14355 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14356 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14357 mutex_exit(&plun->lun_tgt->tgt_mutex); 14358 fcp_log(CE_CONT, pptr->port_dip, 14359 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14360 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14361 return (NDI_FAILURE); 14362 } 14363 mutex_exit(&plun->lun_tgt->tgt_mutex); 14364 mutex_enter(&elem->mutex); 14365 if (elem->wait) { 14366 while (elem->wait) { 14367 cv_wait(&elem->cv, &elem->mutex); 14368 } 14369 } 14370 rval = (elem->result); 14371 mutex_exit(&elem->mutex); 14372 mutex_destroy(&elem->mutex); 14373 cv_destroy(&elem->cv); 14374 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14375 return (rval); 14376 } 14377 14378 /* 14379 * pass an element to the hotplug list, and then 14380 * kick the hotplug thread 14381 * 14382 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14383 * 14384 * acquires/releases the hotplug mutex 14385 * 14386 * called with the target mutex owned 14387 * 14388 * memory acquired in NOSLEEP mode 14389 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14390 * for the hp daemon to process the request and is responsible for 14391 * freeing the element 14392 */ 14393 static struct fcp_hp_elem * 14394 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14395 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14396 { 14397 struct fcp_hp_elem *elem; 14398 dev_info_t *pdip; 14399 14400 ASSERT(pptr != NULL); 14401 ASSERT(plun != NULL); 14402 ASSERT(plun->lun_tgt != NULL); 14403 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14404 14405 /* create space for a hotplug element */ 14406 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14407 == NULL) { 14408 fcp_log(CE_WARN, NULL, 14409 "!can't allocate memory for hotplug element"); 14410 return (NULL); 14411 } 14412 14413 /* fill in hotplug element */ 14414 elem->port = pptr; 14415 elem->lun = plun; 14416 elem->cip = cip; 14417 elem->old_lun_mpxio = plun->lun_mpxio; 14418 elem->what = what; 14419 elem->flags = flags; 14420 elem->link_cnt = link_cnt; 14421 elem->tgt_cnt = tgt_cnt; 14422 elem->wait = wait; 14423 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14424 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14425 14426 /* schedule the hotplug task */ 14427 pdip = pptr->port_dip; 14428 mutex_enter(&plun->lun_mutex); 14429 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14430 plun->lun_event_count++; 14431 elem->event_cnt = plun->lun_event_count; 14432 } 14433 mutex_exit(&plun->lun_mutex); 14434 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14435 (void *)elem, KM_NOSLEEP) == NULL) { 14436 mutex_enter(&plun->lun_mutex); 14437 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14438 plun->lun_event_count--; 14439 } 14440 mutex_exit(&plun->lun_mutex); 14441 kmem_free(elem, sizeof (*elem)); 14442 return (0); 14443 } 14444 14445 return (elem); 14446 } 14447 14448 14449 static void 14450 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14451 { 14452 int rval; 14453 struct scsi_address *ap; 14454 struct fcp_lun *plun; 14455 struct fcp_tgt *ptgt; 14456 fc_packet_t *fpkt; 14457 14458 ap = &cmd->cmd_pkt->pkt_address; 14459 plun = ADDR2LUN(ap); 14460 ptgt = plun->lun_tgt; 14461 14462 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14463 14464 cmd->cmd_state = FCP_PKT_IDLE; 14465 14466 mutex_enter(&pptr->port_mutex); 14467 mutex_enter(&ptgt->tgt_mutex); 14468 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14469 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14470 fc_ulp_rscn_info_t *rscnp; 14471 14472 cmd->cmd_state = FCP_PKT_ISSUED; 14473 14474 /* 14475 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14476 * originally NULL, hence we try to set it to the pd pointed 14477 * to by the SCSI device we're trying to get to. 14478 */ 14479 14480 fpkt = cmd->cmd_fp_pkt; 14481 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14482 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14483 /* 14484 * We need to notify the transport that we now have a 14485 * reference to the remote port handle. 14486 */ 14487 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14488 } 14489 14490 mutex_exit(&ptgt->tgt_mutex); 14491 mutex_exit(&pptr->port_mutex); 14492 14493 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14494 14495 /* prepare the packet */ 14496 14497 fcp_prepare_pkt(pptr, cmd, plun); 14498 14499 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14500 pkt_ulp_rscn_infop; 14501 14502 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14503 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14504 14505 if (rscnp != NULL) { 14506 rscnp->ulp_rscn_count = 14507 fc_ulp_get_rscn_count(pptr-> 14508 port_fp_handle); 14509 } 14510 14511 rval = fcp_transport(pptr->port_fp_handle, 14512 cmd->cmd_fp_pkt, 0); 14513 14514 if (rval == FC_SUCCESS) { 14515 return; 14516 } 14517 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14518 } else { 14519 mutex_exit(&ptgt->tgt_mutex); 14520 mutex_exit(&pptr->port_mutex); 14521 } 14522 14523 fcp_queue_pkt(pptr, cmd); 14524 } 14525 14526 14527 static void 14528 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14529 { 14530 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14531 14532 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14533 cmd->cmd_state = FCP_PKT_IDLE; 14534 14535 cmd->cmd_pkt->pkt_reason = reason; 14536 cmd->cmd_pkt->pkt_state = 0; 14537 cmd->cmd_pkt->pkt_statistics = statistics; 14538 14539 fcp_post_callback(cmd); 14540 } 14541 14542 /* 14543 * Function: fcp_queue_pkt 14544 * 14545 * Description: This function queues the packet passed by the caller into 14546 * the list of packets of the FCP port. 14547 * 14548 * Argument: *pptr FCP port. 14549 * *cmd FCP packet to queue. 14550 * 14551 * Return Value: None 14552 * 14553 * Context: User, Kernel and Interrupt context. 14554 */ 14555 static void 14556 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14557 { 14558 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14559 14560 mutex_enter(&pptr->port_pkt_mutex); 14561 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14562 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14563 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14564 14565 /* 14566 * zero pkt_time means hang around for ever 14567 */ 14568 if (cmd->cmd_pkt->pkt_time) { 14569 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14570 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14571 } else { 14572 /* 14573 * Indicate the watch thread to fail the 14574 * command by setting it to highest value 14575 */ 14576 cmd->cmd_timeout = fcp_watchdog_time; 14577 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14578 } 14579 } 14580 14581 if (pptr->port_pkt_head) { 14582 ASSERT(pptr->port_pkt_tail != NULL); 14583 14584 pptr->port_pkt_tail->cmd_next = cmd; 14585 pptr->port_pkt_tail = cmd; 14586 } else { 14587 ASSERT(pptr->port_pkt_tail == NULL); 14588 14589 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14590 } 14591 cmd->cmd_next = NULL; 14592 mutex_exit(&pptr->port_pkt_mutex); 14593 } 14594 14595 /* 14596 * Function: fcp_update_targets 14597 * 14598 * Description: This function applies the specified change of state to all 14599 * the targets listed. The operation applied is 'set'. 14600 * 14601 * Argument: *pptr FCP port. 14602 * *dev_list Array of fc_portmap_t structures. 14603 * count Length of dev_list. 14604 * state State bits to update. 14605 * cause Reason for the update. 14606 * 14607 * Return Value: None 14608 * 14609 * Context: User, Kernel and Interrupt context. 14610 * The mutex pptr->port_mutex must be held. 14611 */ 14612 static void 14613 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14614 uint32_t count, uint32_t state, int cause) 14615 { 14616 fc_portmap_t *map_entry; 14617 struct fcp_tgt *ptgt; 14618 14619 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14620 14621 while (count--) { 14622 map_entry = &(dev_list[count]); 14623 ptgt = fcp_lookup_target(pptr, 14624 (uchar_t *)&(map_entry->map_pwwn)); 14625 if (ptgt == NULL) { 14626 continue; 14627 } 14628 14629 mutex_enter(&ptgt->tgt_mutex); 14630 ptgt->tgt_trace = 0; 14631 ptgt->tgt_change_cnt++; 14632 ptgt->tgt_statec_cause = cause; 14633 ptgt->tgt_tmp_cnt = 1; 14634 fcp_update_tgt_state(ptgt, FCP_SET, state); 14635 mutex_exit(&ptgt->tgt_mutex); 14636 } 14637 } 14638 14639 static int 14640 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14641 int lcount, int tcount, int cause) 14642 { 14643 int rval; 14644 14645 mutex_enter(&pptr->port_mutex); 14646 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14647 mutex_exit(&pptr->port_mutex); 14648 14649 return (rval); 14650 } 14651 14652 14653 static int 14654 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14655 int lcount, int tcount, int cause) 14656 { 14657 int finish_init = 0; 14658 int finish_tgt = 0; 14659 int do_finish_init = 0; 14660 int rval = FCP_NO_CHANGE; 14661 14662 if (cause == FCP_CAUSE_LINK_CHANGE || 14663 cause == FCP_CAUSE_LINK_DOWN) { 14664 do_finish_init = 1; 14665 } 14666 14667 if (ptgt != NULL) { 14668 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14669 FCP_BUF_LEVEL_2, 0, 14670 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14671 " cause = %d, d_id = 0x%x, tgt_done = %d", 14672 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14673 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14674 ptgt->tgt_d_id, ptgt->tgt_done); 14675 14676 mutex_enter(&ptgt->tgt_mutex); 14677 14678 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14679 rval = FCP_DEV_CHANGE; 14680 if (do_finish_init && ptgt->tgt_done == 0) { 14681 ptgt->tgt_done++; 14682 finish_init = 1; 14683 } 14684 } else { 14685 if (--ptgt->tgt_tmp_cnt <= 0) { 14686 ptgt->tgt_tmp_cnt = 0; 14687 finish_tgt = 1; 14688 14689 if (do_finish_init) { 14690 finish_init = 1; 14691 } 14692 } 14693 } 14694 mutex_exit(&ptgt->tgt_mutex); 14695 } else { 14696 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14697 FCP_BUF_LEVEL_2, 0, 14698 "Call Finish Init for NO target"); 14699 14700 if (do_finish_init) { 14701 finish_init = 1; 14702 } 14703 } 14704 14705 if (finish_tgt) { 14706 ASSERT(ptgt != NULL); 14707 14708 mutex_enter(&ptgt->tgt_mutex); 14709 #ifdef DEBUG 14710 bzero(ptgt->tgt_tmp_cnt_stack, 14711 sizeof (ptgt->tgt_tmp_cnt_stack)); 14712 14713 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14714 FCP_STACK_DEPTH); 14715 #endif /* DEBUG */ 14716 mutex_exit(&ptgt->tgt_mutex); 14717 14718 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14719 } 14720 14721 if (finish_init && lcount == pptr->port_link_cnt) { 14722 ASSERT(pptr->port_tmp_cnt > 0); 14723 if (--pptr->port_tmp_cnt == 0) { 14724 fcp_finish_init(pptr); 14725 } 14726 } else if (lcount != pptr->port_link_cnt) { 14727 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14728 fcp_trace, FCP_BUF_LEVEL_2, 0, 14729 "fcp_call_finish_init_held,1: state change occured" 14730 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14731 } 14732 14733 return (rval); 14734 } 14735 14736 static void 14737 fcp_reconfigure_luns(void * tgt_handle) 14738 { 14739 uint32_t dev_cnt; 14740 fc_portmap_t *devlist; 14741 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14742 struct fcp_port *pptr = ptgt->tgt_port; 14743 14744 /* 14745 * If the timer that fires this off got canceled too late, the 14746 * target could have been destroyed. 14747 */ 14748 14749 if (ptgt->tgt_tid == NULL) { 14750 return; 14751 } 14752 14753 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14754 if (devlist == NULL) { 14755 fcp_log(CE_WARN, pptr->port_dip, 14756 "!fcp%d: failed to allocate for portmap", 14757 pptr->port_instance); 14758 return; 14759 } 14760 14761 dev_cnt = 1; 14762 devlist->map_pd = ptgt->tgt_pd_handle; 14763 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14764 devlist->map_did.port_id = ptgt->tgt_d_id; 14765 14766 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14767 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14768 14769 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14770 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14771 devlist->map_flags = 0; 14772 14773 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14774 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14775 14776 /* 14777 * Clear the tgt_tid after no more references to 14778 * the fcp_tgt 14779 */ 14780 mutex_enter(&ptgt->tgt_mutex); 14781 ptgt->tgt_tid = NULL; 14782 mutex_exit(&ptgt->tgt_mutex); 14783 14784 kmem_free(devlist, sizeof (*devlist)); 14785 } 14786 14787 14788 static void 14789 fcp_free_targets(struct fcp_port *pptr) 14790 { 14791 int i; 14792 struct fcp_tgt *ptgt; 14793 14794 mutex_enter(&pptr->port_mutex); 14795 for (i = 0; i < FCP_NUM_HASH; i++) { 14796 ptgt = pptr->port_tgt_hash_table[i]; 14797 while (ptgt != NULL) { 14798 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14799 14800 fcp_free_target(ptgt); 14801 ptgt = next_tgt; 14802 } 14803 } 14804 mutex_exit(&pptr->port_mutex); 14805 } 14806 14807 14808 static void 14809 fcp_free_target(struct fcp_tgt *ptgt) 14810 { 14811 struct fcp_lun *plun; 14812 timeout_id_t tid; 14813 14814 mutex_enter(&ptgt->tgt_mutex); 14815 tid = ptgt->tgt_tid; 14816 14817 /* 14818 * Cancel any pending timeouts for this target. 14819 */ 14820 14821 if (tid != NULL) { 14822 /* 14823 * Set tgt_tid to NULL first to avoid a race in the callback. 14824 * If tgt_tid is NULL, the callback will simply return. 14825 */ 14826 ptgt->tgt_tid = NULL; 14827 mutex_exit(&ptgt->tgt_mutex); 14828 (void) untimeout(tid); 14829 mutex_enter(&ptgt->tgt_mutex); 14830 } 14831 14832 plun = ptgt->tgt_lun; 14833 while (plun != NULL) { 14834 struct fcp_lun *next_lun = plun->lun_next; 14835 14836 fcp_dealloc_lun(plun); 14837 plun = next_lun; 14838 } 14839 14840 mutex_exit(&ptgt->tgt_mutex); 14841 fcp_dealloc_tgt(ptgt); 14842 } 14843 14844 /* 14845 * Function: fcp_is_retryable 14846 * 14847 * Description: Indicates if the internal packet is retryable. 14848 * 14849 * Argument: *icmd FCP internal packet. 14850 * 14851 * Return Value: 0 Not retryable 14852 * 1 Retryable 14853 * 14854 * Context: User, Kernel and Interrupt context 14855 */ 14856 static int 14857 fcp_is_retryable(struct fcp_ipkt *icmd) 14858 { 14859 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14860 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14861 return (0); 14862 } 14863 14864 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14865 icmd->ipkt_port->port_deadline) ? 1 : 0); 14866 } 14867 14868 /* 14869 * Function: fcp_create_on_demand 14870 * 14871 * Argument: *pptr FCP port. 14872 * *pwwn Port WWN. 14873 * 14874 * Return Value: 0 Success 14875 * EIO 14876 * ENOMEM 14877 * EBUSY 14878 * EINVAL 14879 * 14880 * Context: User and Kernel context 14881 */ 14882 static int 14883 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14884 { 14885 int wait_ms; 14886 int tcount; 14887 int lcount; 14888 int ret; 14889 int error; 14890 int rval = EIO; 14891 int ntries; 14892 fc_portmap_t *devlist; 14893 opaque_t pd; 14894 struct fcp_lun *plun; 14895 struct fcp_tgt *ptgt; 14896 int old_manual = 0; 14897 14898 /* Allocates the fc_portmap_t structure. */ 14899 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14900 14901 /* 14902 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14903 * in the commented statement below: 14904 * 14905 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14906 * 14907 * Below, the deadline for the discovery process is set. 14908 */ 14909 mutex_enter(&pptr->port_mutex); 14910 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14911 mutex_exit(&pptr->port_mutex); 14912 14913 /* 14914 * We try to find the remote port based on the WWN provided by the 14915 * caller. We actually ask fp/fctl if it has it. 14916 */ 14917 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14918 (la_wwn_t *)pwwn, &error, 1); 14919 14920 if (pd == NULL) { 14921 kmem_free(devlist, sizeof (*devlist)); 14922 return (rval); 14923 } 14924 14925 /* 14926 * The remote port was found. We ask fp/fctl to update our 14927 * fc_portmap_t structure. 14928 */ 14929 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14930 (la_wwn_t *)pwwn, devlist); 14931 if (ret != FC_SUCCESS) { 14932 kmem_free(devlist, sizeof (*devlist)); 14933 return (rval); 14934 } 14935 14936 /* 14937 * The map flag field is set to indicates that the creation is being 14938 * done at the user request (Ioclt probably luxadm or cfgadm). 14939 */ 14940 devlist->map_type = PORT_DEVICE_USER_CREATE; 14941 14942 mutex_enter(&pptr->port_mutex); 14943 14944 /* 14945 * We check to see if fcp already has a target that describes the 14946 * device being created. If not it is created. 14947 */ 14948 ptgt = fcp_lookup_target(pptr, pwwn); 14949 if (ptgt == NULL) { 14950 lcount = pptr->port_link_cnt; 14951 mutex_exit(&pptr->port_mutex); 14952 14953 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14954 if (ptgt == NULL) { 14955 fcp_log(CE_WARN, pptr->port_dip, 14956 "!FC target allocation failed"); 14957 return (ENOMEM); 14958 } 14959 14960 mutex_enter(&pptr->port_mutex); 14961 } 14962 14963 mutex_enter(&ptgt->tgt_mutex); 14964 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14965 ptgt->tgt_tmp_cnt = 1; 14966 ptgt->tgt_device_created = 0; 14967 /* 14968 * If fabric and auto config is set but the target was 14969 * manually unconfigured then reset to the manual_config_only to 14970 * 0 so the device will get configured. 14971 */ 14972 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14973 fcp_enable_auto_configuration && 14974 ptgt->tgt_manual_config_only == 1) { 14975 old_manual = 1; 14976 ptgt->tgt_manual_config_only = 0; 14977 } 14978 mutex_exit(&ptgt->tgt_mutex); 14979 14980 fcp_update_targets(pptr, devlist, 1, 14981 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14982 14983 lcount = pptr->port_link_cnt; 14984 tcount = ptgt->tgt_change_cnt; 14985 14986 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14987 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14988 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14989 fcp_enable_auto_configuration && old_manual) { 14990 mutex_enter(&ptgt->tgt_mutex); 14991 ptgt->tgt_manual_config_only = 1; 14992 mutex_exit(&ptgt->tgt_mutex); 14993 } 14994 14995 if (pptr->port_link_cnt != lcount || 14996 ptgt->tgt_change_cnt != tcount) { 14997 rval = EBUSY; 14998 } 14999 mutex_exit(&pptr->port_mutex); 15000 15001 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15002 FCP_BUF_LEVEL_3, 0, 15003 "fcp_create_on_demand: mapflags ptgt=%x, " 15004 "lcount=%x::port_link_cnt=%x, " 15005 "tcount=%x: tgt_change_cnt=%x, rval=%x", 15006 ptgt, lcount, pptr->port_link_cnt, 15007 tcount, ptgt->tgt_change_cnt, rval); 15008 return (rval); 15009 } 15010 15011 /* 15012 * Due to lack of synchronization mechanisms, we perform 15013 * periodic monitoring of our request; Because requests 15014 * get dropped when another one supercedes (either because 15015 * of a link change or a target change), it is difficult to 15016 * provide a clean synchronization mechanism (such as a 15017 * semaphore or a conditional variable) without exhaustively 15018 * rewriting the mainline discovery code of this driver. 15019 */ 15020 wait_ms = 500; 15021 15022 ntries = fcp_max_target_retries; 15023 15024 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15025 FCP_BUF_LEVEL_3, 0, 15026 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15027 "lcount=%x::port_link_cnt=%x, " 15028 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15029 "tgt_tmp_cnt =%x", 15030 ntries, ptgt, lcount, pptr->port_link_cnt, 15031 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15032 ptgt->tgt_tmp_cnt); 15033 15034 mutex_enter(&ptgt->tgt_mutex); 15035 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15036 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15037 mutex_exit(&ptgt->tgt_mutex); 15038 mutex_exit(&pptr->port_mutex); 15039 15040 delay(drv_usectohz(wait_ms * 1000)); 15041 15042 mutex_enter(&pptr->port_mutex); 15043 mutex_enter(&ptgt->tgt_mutex); 15044 } 15045 15046 15047 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15048 rval = EBUSY; 15049 } else { 15050 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15051 FCP_TGT_NODE_PRESENT) { 15052 rval = 0; 15053 } 15054 } 15055 15056 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15057 FCP_BUF_LEVEL_3, 0, 15058 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15059 "lcount=%x::port_link_cnt=%x, " 15060 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15061 "tgt_tmp_cnt =%x", 15062 ntries, ptgt, lcount, pptr->port_link_cnt, 15063 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15064 ptgt->tgt_tmp_cnt); 15065 15066 if (rval) { 15067 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15068 fcp_enable_auto_configuration && old_manual) { 15069 ptgt->tgt_manual_config_only = 1; 15070 } 15071 mutex_exit(&ptgt->tgt_mutex); 15072 mutex_exit(&pptr->port_mutex); 15073 kmem_free(devlist, sizeof (*devlist)); 15074 15075 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15076 FCP_BUF_LEVEL_3, 0, 15077 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15078 "lcount=%x::port_link_cnt=%x, " 15079 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15080 "tgt_device_created=%x, tgt D_ID=%x", 15081 ntries, ptgt, lcount, pptr->port_link_cnt, 15082 tcount, ptgt->tgt_change_cnt, rval, 15083 ptgt->tgt_device_created, ptgt->tgt_d_id); 15084 return (rval); 15085 } 15086 15087 if ((plun = ptgt->tgt_lun) != NULL) { 15088 tcount = plun->lun_tgt->tgt_change_cnt; 15089 } else { 15090 rval = EINVAL; 15091 } 15092 lcount = pptr->port_link_cnt; 15093 15094 /* 15095 * Configuring the target with no LUNs will fail. We 15096 * should reset the node state so that it is not 15097 * automatically configured when the LUNs are added 15098 * to this target. 15099 */ 15100 if (ptgt->tgt_lun_cnt == 0) { 15101 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15102 } 15103 mutex_exit(&ptgt->tgt_mutex); 15104 mutex_exit(&pptr->port_mutex); 15105 15106 while (plun) { 15107 child_info_t *cip; 15108 15109 mutex_enter(&plun->lun_mutex); 15110 cip = plun->lun_cip; 15111 mutex_exit(&plun->lun_mutex); 15112 15113 mutex_enter(&ptgt->tgt_mutex); 15114 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15115 mutex_exit(&ptgt->tgt_mutex); 15116 15117 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15118 FCP_ONLINE, lcount, tcount, 15119 NDI_ONLINE_ATTACH); 15120 if (rval != NDI_SUCCESS) { 15121 FCP_TRACE(fcp_logq, 15122 pptr->port_instbuf, fcp_trace, 15123 FCP_BUF_LEVEL_3, 0, 15124 "fcp_create_on_demand: " 15125 "pass_to_hp_and_wait failed " 15126 "rval=%x", rval); 15127 rval = EIO; 15128 } else { 15129 mutex_enter(&LUN_TGT->tgt_mutex); 15130 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15131 FCP_LUN_BUSY); 15132 mutex_exit(&LUN_TGT->tgt_mutex); 15133 } 15134 mutex_enter(&ptgt->tgt_mutex); 15135 } 15136 15137 plun = plun->lun_next; 15138 mutex_exit(&ptgt->tgt_mutex); 15139 } 15140 15141 kmem_free(devlist, sizeof (*devlist)); 15142 15143 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15144 fcp_enable_auto_configuration && old_manual) { 15145 mutex_enter(&ptgt->tgt_mutex); 15146 /* if successful then set manual to 0 */ 15147 if (rval == 0) { 15148 ptgt->tgt_manual_config_only = 0; 15149 } else { 15150 /* reset to 1 so the user has to do the config */ 15151 ptgt->tgt_manual_config_only = 1; 15152 } 15153 mutex_exit(&ptgt->tgt_mutex); 15154 } 15155 15156 return (rval); 15157 } 15158 15159 15160 static void 15161 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15162 { 15163 int count; 15164 uchar_t byte; 15165 15166 count = 0; 15167 while (*string) { 15168 byte = FCP_ATOB(*string); string++; 15169 byte = byte << 4 | FCP_ATOB(*string); string++; 15170 bytes[count++] = byte; 15171 15172 if (count >= byte_len) { 15173 break; 15174 } 15175 } 15176 } 15177 15178 static void 15179 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15180 { 15181 int i; 15182 15183 for (i = 0; i < FC_WWN_SIZE; i++) { 15184 (void) sprintf(string + (i * 2), 15185 "%02x", wwn[i]); 15186 } 15187 15188 } 15189 15190 static void 15191 fcp_print_error(fc_packet_t *fpkt) 15192 { 15193 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15194 fpkt->pkt_ulp_private; 15195 struct fcp_port *pptr; 15196 struct fcp_tgt *ptgt; 15197 struct fcp_lun *plun; 15198 caddr_t buf; 15199 int scsi_cmd = 0; 15200 15201 ptgt = icmd->ipkt_tgt; 15202 plun = icmd->ipkt_lun; 15203 pptr = ptgt->tgt_port; 15204 15205 buf = kmem_zalloc(256, KM_NOSLEEP); 15206 if (buf == NULL) { 15207 return; 15208 } 15209 15210 switch (icmd->ipkt_opcode) { 15211 case SCMD_REPORT_LUN: 15212 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15213 " lun=0x%%x failed"); 15214 scsi_cmd++; 15215 break; 15216 15217 case SCMD_INQUIRY_PAGE83: 15218 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15219 " lun=0x%%x failed"); 15220 scsi_cmd++; 15221 break; 15222 15223 case SCMD_INQUIRY: 15224 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15225 " lun=0x%%x failed"); 15226 scsi_cmd++; 15227 break; 15228 15229 case LA_ELS_PLOGI: 15230 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15231 break; 15232 15233 case LA_ELS_PRLI: 15234 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15235 break; 15236 } 15237 15238 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15239 struct fcp_rsp response, *rsp; 15240 uchar_t asc, ascq; 15241 caddr_t sense_key = NULL; 15242 struct fcp_rsp_info fcp_rsp_err, *bep; 15243 15244 if (icmd->ipkt_nodma) { 15245 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15246 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15247 sizeof (struct fcp_rsp)); 15248 } else { 15249 rsp = &response; 15250 bep = &fcp_rsp_err; 15251 15252 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15253 sizeof (struct fcp_rsp)); 15254 15255 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15256 bep, fpkt->pkt_resp_acc, 15257 sizeof (struct fcp_rsp_info)); 15258 } 15259 15260 15261 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15262 (void) sprintf(buf + strlen(buf), 15263 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15264 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15265 " senselen=%%x. Giving up"); 15266 15267 fcp_log(CE_WARN, pptr->port_dip, buf, 15268 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15269 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15270 rsp->fcp_u.fcp_status.reserved_1, 15271 rsp->fcp_response_len, rsp->fcp_sense_len); 15272 15273 kmem_free(buf, 256); 15274 return; 15275 } 15276 15277 if (rsp->fcp_u.fcp_status.rsp_len_set && 15278 bep->rsp_code != FCP_NO_FAILURE) { 15279 (void) sprintf(buf + strlen(buf), 15280 " FCP Response code = 0x%x", bep->rsp_code); 15281 } 15282 15283 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15284 struct scsi_extended_sense sense_info, *sense_ptr; 15285 15286 if (icmd->ipkt_nodma) { 15287 sense_ptr = (struct scsi_extended_sense *) 15288 ((caddr_t)fpkt->pkt_resp + 15289 sizeof (struct fcp_rsp) + 15290 rsp->fcp_response_len); 15291 } else { 15292 sense_ptr = &sense_info; 15293 15294 FCP_CP_IN(fpkt->pkt_resp + 15295 sizeof (struct fcp_rsp) + 15296 rsp->fcp_response_len, &sense_info, 15297 fpkt->pkt_resp_acc, 15298 sizeof (struct scsi_extended_sense)); 15299 } 15300 15301 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15302 NUM_IMPL_SENSE_KEYS) { 15303 sense_key = sense_keys[sense_ptr->es_key]; 15304 } else { 15305 sense_key = "Undefined"; 15306 } 15307 15308 asc = sense_ptr->es_add_code; 15309 ascq = sense_ptr->es_qual_code; 15310 15311 (void) sprintf(buf + strlen(buf), 15312 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15313 " Giving up"); 15314 15315 fcp_log(CE_WARN, pptr->port_dip, buf, 15316 ptgt->tgt_d_id, plun->lun_num, sense_key, 15317 asc, ascq); 15318 } else { 15319 (void) sprintf(buf + strlen(buf), 15320 " : SCSI status=%%x. Giving up"); 15321 15322 fcp_log(CE_WARN, pptr->port_dip, buf, 15323 ptgt->tgt_d_id, plun->lun_num, 15324 rsp->fcp_u.fcp_status.scsi_status); 15325 } 15326 } else { 15327 caddr_t state, reason, action, expln; 15328 15329 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15330 &action, &expln); 15331 15332 (void) sprintf(buf + strlen(buf), ": State:%%s," 15333 " Reason:%%s. Giving up"); 15334 15335 if (scsi_cmd) { 15336 fcp_log(CE_WARN, pptr->port_dip, buf, 15337 ptgt->tgt_d_id, plun->lun_num, state, reason); 15338 } else { 15339 fcp_log(CE_WARN, pptr->port_dip, buf, 15340 ptgt->tgt_d_id, state, reason); 15341 } 15342 } 15343 15344 kmem_free(buf, 256); 15345 } 15346 15347 15348 static int 15349 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15350 struct fcp_ipkt *icmd, int rval, caddr_t op) 15351 { 15352 int ret = DDI_FAILURE; 15353 char *error; 15354 15355 switch (rval) { 15356 case FC_DEVICE_BUSY_NEW_RSCN: 15357 /* 15358 * This means that there was a new RSCN that the transport 15359 * knows about (which the ULP *may* know about too) but the 15360 * pkt that was sent down was related to an older RSCN. So, we 15361 * are just going to reset the retry count and deadline and 15362 * continue to retry. The idea is that transport is currently 15363 * working on the new RSCN and will soon let the ULPs know 15364 * about it and when it does the existing logic will kick in 15365 * where it will change the tcount to indicate that something 15366 * changed on the target. So, rediscovery will start and there 15367 * will not be an infinite retry. 15368 * 15369 * For a full flow of how the RSCN info is transferred back and 15370 * forth, see fp.c 15371 */ 15372 icmd->ipkt_retries = 0; 15373 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15374 FCP_ICMD_DEADLINE; 15375 15376 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15377 FCP_BUF_LEVEL_3, 0, 15378 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15379 rval, ptgt->tgt_d_id); 15380 /* FALLTHROUGH */ 15381 15382 case FC_STATEC_BUSY: 15383 case FC_DEVICE_BUSY: 15384 case FC_PBUSY: 15385 case FC_FBUSY: 15386 case FC_TRAN_BUSY: 15387 case FC_OFFLINE: 15388 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15389 FCP_BUF_LEVEL_3, 0, 15390 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15391 rval, ptgt->tgt_d_id); 15392 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15393 fcp_is_retryable(icmd)) { 15394 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15395 ret = DDI_SUCCESS; 15396 } 15397 break; 15398 15399 case FC_LOGINREQ: 15400 /* 15401 * FC_LOGINREQ used to be handled just like all the cases 15402 * above. It has been changed to handled a PRLI that fails 15403 * with FC_LOGINREQ different than other ipkts that fail 15404 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15405 * a simple matter to turn it into a PLOGI instead, so that's 15406 * exactly what we do here. 15407 */ 15408 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15409 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15410 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15411 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15412 } else { 15413 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15414 FCP_BUF_LEVEL_3, 0, 15415 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15416 rval, ptgt->tgt_d_id); 15417 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15418 fcp_is_retryable(icmd)) { 15419 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15420 ret = DDI_SUCCESS; 15421 } 15422 } 15423 break; 15424 15425 default: 15426 mutex_enter(&pptr->port_mutex); 15427 mutex_enter(&ptgt->tgt_mutex); 15428 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15429 mutex_exit(&ptgt->tgt_mutex); 15430 mutex_exit(&pptr->port_mutex); 15431 15432 (void) fc_ulp_error(rval, &error); 15433 fcp_log(CE_WARN, pptr->port_dip, 15434 "!Failed to send %s to D_ID=%x error=%s", 15435 op, ptgt->tgt_d_id, error); 15436 } else { 15437 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15438 fcp_trace, FCP_BUF_LEVEL_2, 0, 15439 "fcp_handle_ipkt_errors,1: state change occured" 15440 " for D_ID=0x%x", ptgt->tgt_d_id); 15441 mutex_exit(&ptgt->tgt_mutex); 15442 mutex_exit(&pptr->port_mutex); 15443 } 15444 break; 15445 } 15446 15447 return (ret); 15448 } 15449 15450 15451 /* 15452 * Check of outstanding commands on any LUN for this target 15453 */ 15454 static int 15455 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15456 { 15457 struct fcp_lun *plun; 15458 struct fcp_pkt *cmd; 15459 15460 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15461 mutex_enter(&plun->lun_mutex); 15462 for (cmd = plun->lun_pkt_head; cmd != NULL; 15463 cmd = cmd->cmd_forw) { 15464 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15465 mutex_exit(&plun->lun_mutex); 15466 return (FC_SUCCESS); 15467 } 15468 } 15469 mutex_exit(&plun->lun_mutex); 15470 } 15471 15472 return (FC_FAILURE); 15473 } 15474 15475 static fc_portmap_t * 15476 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15477 { 15478 int i; 15479 fc_portmap_t *devlist; 15480 fc_portmap_t *devptr = NULL; 15481 struct fcp_tgt *ptgt; 15482 15483 mutex_enter(&pptr->port_mutex); 15484 for (i = 0, *dev_cnt = 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 ++*dev_cnt; 15489 } 15490 } 15491 } 15492 15493 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15494 KM_NOSLEEP); 15495 if (devlist == NULL) { 15496 mutex_exit(&pptr->port_mutex); 15497 fcp_log(CE_WARN, pptr->port_dip, 15498 "!fcp%d: failed to allocate for portmap for construct map", 15499 pptr->port_instance); 15500 return (devptr); 15501 } 15502 15503 for (i = 0; i < FCP_NUM_HASH; i++) { 15504 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15505 ptgt = ptgt->tgt_next) { 15506 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15507 int ret; 15508 15509 ret = fc_ulp_pwwn_to_portmap( 15510 pptr->port_fp_handle, 15511 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15512 devlist); 15513 15514 if (ret == FC_SUCCESS) { 15515 devlist++; 15516 continue; 15517 } 15518 15519 devlist->map_pd = NULL; 15520 devlist->map_did.port_id = ptgt->tgt_d_id; 15521 devlist->map_hard_addr.hard_addr = 15522 ptgt->tgt_hard_addr; 15523 15524 devlist->map_state = PORT_DEVICE_INVALID; 15525 devlist->map_type = PORT_DEVICE_OLD; 15526 15527 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15528 &devlist->map_nwwn, FC_WWN_SIZE); 15529 15530 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15531 &devlist->map_pwwn, FC_WWN_SIZE); 15532 15533 devlist++; 15534 } 15535 } 15536 } 15537 15538 mutex_exit(&pptr->port_mutex); 15539 15540 return (devptr); 15541 } 15542 /* 15543 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15544 */ 15545 static void 15546 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15547 { 15548 int i; 15549 struct fcp_tgt *ptgt; 15550 struct fcp_lun *plun; 15551 15552 for (i = 0; i < FCP_NUM_HASH; i++) { 15553 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15554 ptgt = ptgt->tgt_next) { 15555 mutex_enter(&ptgt->tgt_mutex); 15556 for (plun = ptgt->tgt_lun; plun != NULL; 15557 plun = plun->lun_next) { 15558 if (plun->lun_mpxio && 15559 plun->lun_state & FCP_LUN_BUSY) { 15560 if (!fcp_pass_to_hp(pptr, plun, 15561 plun->lun_cip, 15562 FCP_MPXIO_PATH_SET_BUSY, 15563 pptr->port_link_cnt, 15564 ptgt->tgt_change_cnt, 0, 0)) { 15565 FCP_TRACE(fcp_logq, 15566 pptr->port_instbuf, 15567 fcp_trace, 15568 FCP_BUF_LEVEL_2, 0, 15569 "path_verifybusy: " 15570 "disable lun %p failed!", 15571 plun); 15572 } 15573 } 15574 } 15575 mutex_exit(&ptgt->tgt_mutex); 15576 } 15577 } 15578 } 15579 15580 static int 15581 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15582 { 15583 dev_info_t *cdip = NULL; 15584 dev_info_t *pdip = NULL; 15585 15586 ASSERT(plun); 15587 15588 mutex_enter(&plun->lun_mutex); 15589 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15590 mutex_exit(&plun->lun_mutex); 15591 return (NDI_FAILURE); 15592 } 15593 mutex_exit(&plun->lun_mutex); 15594 cdip = mdi_pi_get_client(PIP(cip)); 15595 pdip = mdi_pi_get_phci(PIP(cip)); 15596 15597 ASSERT(cdip != NULL); 15598 ASSERT(pdip != NULL); 15599 15600 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15601 /* LUN ready for IO */ 15602 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15603 } else { 15604 /* LUN busy to accept IO */ 15605 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15606 } 15607 return (NDI_SUCCESS); 15608 } 15609 15610 /* 15611 * Caller must free the returned string of MAXPATHLEN len 15612 * If the device is offline (-1 instance number) NULL 15613 * will be returned. 15614 */ 15615 static char * 15616 fcp_get_lun_path(struct fcp_lun *plun) 15617 { 15618 dev_info_t *dip = NULL; 15619 char *path = NULL; 15620 mdi_pathinfo_t *pip = NULL; 15621 15622 if (plun == NULL) { 15623 return (NULL); 15624 } 15625 15626 mutex_enter(&plun->lun_mutex); 15627 if (plun->lun_mpxio == 0) { 15628 dip = DIP(plun->lun_cip); 15629 mutex_exit(&plun->lun_mutex); 15630 } else { 15631 /* 15632 * lun_cip must be accessed with lun_mutex held. Here 15633 * plun->lun_cip either points to a valid node or it is NULL. 15634 * Make a copy so that we can release lun_mutex. 15635 */ 15636 pip = PIP(plun->lun_cip); 15637 15638 /* 15639 * Increase ref count on the path so that we can release 15640 * lun_mutex and still be sure that the pathinfo node (and thus 15641 * also the client) is not deallocated. If pip is NULL, this 15642 * has no effect. 15643 */ 15644 mdi_hold_path(pip); 15645 15646 mutex_exit(&plun->lun_mutex); 15647 15648 /* Get the client. If pip is NULL, we get NULL. */ 15649 dip = mdi_pi_get_client(pip); 15650 } 15651 15652 if (dip == NULL) 15653 goto out; 15654 if (ddi_get_instance(dip) < 0) 15655 goto out; 15656 15657 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15658 if (path == NULL) 15659 goto out; 15660 15661 (void) ddi_pathname(dip, path); 15662 15663 /* Clean up. */ 15664 out: 15665 if (pip != NULL) 15666 mdi_rele_path(pip); 15667 15668 /* 15669 * In reality, the user wants a fully valid path (one they can open) 15670 * but this string is lacking the mount point, and the minor node. 15671 * It would be nice if we could "figure these out" somehow 15672 * and fill them in. Otherwise, the userland code has to understand 15673 * driver specific details of which minor node is the "best" or 15674 * "right" one to expose. (Ex: which slice is the whole disk, or 15675 * which tape doesn't rewind) 15676 */ 15677 return (path); 15678 } 15679 15680 static int 15681 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15682 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15683 { 15684 int64_t reset_delay; 15685 int rval, retry = 0; 15686 struct fcp_port *pptr = fcp_dip2port(parent); 15687 15688 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15689 (ddi_get_lbolt64() - pptr->port_attach_time); 15690 if (reset_delay < 0) { 15691 reset_delay = 0; 15692 } 15693 15694 if (fcp_bus_config_debug) { 15695 flag |= NDI_DEVI_DEBUG; 15696 } 15697 15698 switch (op) { 15699 case BUS_CONFIG_ONE: 15700 /* 15701 * Retry the command since we need to ensure 15702 * the fabric devices are available for root 15703 */ 15704 while (retry++ < fcp_max_bus_config_retries) { 15705 rval = (ndi_busop_bus_config(parent, 15706 flag | NDI_MDI_FALLBACK, op, 15707 arg, childp, (clock_t)reset_delay)); 15708 if (rval == 0) { 15709 return (rval); 15710 } 15711 } 15712 15713 /* 15714 * drain taskq to make sure nodes are created and then 15715 * try again. 15716 */ 15717 taskq_wait(DEVI(parent)->devi_taskq); 15718 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15719 op, arg, childp, 0)); 15720 15721 case BUS_CONFIG_DRIVER: 15722 case BUS_CONFIG_ALL: { 15723 /* 15724 * delay till all devices report in (port_tmp_cnt == 0) 15725 * or FCP_INIT_WAIT_TIMEOUT 15726 */ 15727 mutex_enter(&pptr->port_mutex); 15728 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15729 (void) cv_timedwait(&pptr->port_config_cv, 15730 &pptr->port_mutex, 15731 ddi_get_lbolt() + (clock_t)reset_delay); 15732 reset_delay = 15733 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15734 (ddi_get_lbolt64() - pptr->port_attach_time); 15735 } 15736 mutex_exit(&pptr->port_mutex); 15737 /* drain taskq to make sure nodes are created */ 15738 taskq_wait(DEVI(parent)->devi_taskq); 15739 return (ndi_busop_bus_config(parent, flag, op, 15740 arg, childp, 0)); 15741 } 15742 15743 default: 15744 return (NDI_FAILURE); 15745 } 15746 /*NOTREACHED*/ 15747 } 15748 15749 static int 15750 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15751 ddi_bus_config_op_t op, void *arg) 15752 { 15753 if (fcp_bus_config_debug) { 15754 flag |= NDI_DEVI_DEBUG; 15755 } 15756 15757 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15758 } 15759 15760 15761 /* 15762 * Routine to copy GUID into the lun structure. 15763 * returns 0 if copy was successful and 1 if encountered a 15764 * failure and did not copy the guid. 15765 */ 15766 static int 15767 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15768 { 15769 15770 int retval = 0; 15771 15772 /* add one for the null terminator */ 15773 const unsigned int len = strlen(guidp) + 1; 15774 15775 if ((guidp == NULL) || (plun == NULL)) { 15776 return (1); 15777 } 15778 15779 /* 15780 * if the plun->lun_guid already has been allocated, 15781 * then check the size. if the size is exact, reuse 15782 * it....if not free it an allocate the required size. 15783 * The reallocation should NOT typically happen 15784 * unless the GUIDs reported changes between passes. 15785 * We free up and alloc again even if the 15786 * size was more than required. This is due to the 15787 * fact that the field lun_guid_size - serves 15788 * dual role of indicating the size of the wwn 15789 * size and ALSO the allocation size. 15790 */ 15791 if (plun->lun_guid) { 15792 if (plun->lun_guid_size != len) { 15793 /* 15794 * free the allocated memory and 15795 * initialize the field 15796 * lun_guid_size to 0. 15797 */ 15798 kmem_free(plun->lun_guid, plun->lun_guid_size); 15799 plun->lun_guid = NULL; 15800 plun->lun_guid_size = 0; 15801 } 15802 } 15803 /* 15804 * alloc only if not already done. 15805 */ 15806 if (plun->lun_guid == NULL) { 15807 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15808 if (plun->lun_guid == NULL) { 15809 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15810 "Unable to allocate" 15811 "Memory for GUID!!! size %d", len); 15812 retval = 1; 15813 } else { 15814 plun->lun_guid_size = len; 15815 } 15816 } 15817 if (plun->lun_guid) { 15818 /* 15819 * now copy the GUID 15820 */ 15821 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15822 } 15823 return (retval); 15824 } 15825 15826 /* 15827 * fcp_reconfig_wait 15828 * 15829 * Wait for a rediscovery/reconfiguration to complete before continuing. 15830 */ 15831 15832 static void 15833 fcp_reconfig_wait(struct fcp_port *pptr) 15834 { 15835 clock_t reconfig_start, wait_timeout; 15836 15837 /* 15838 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15839 * reconfiguration in progress. 15840 */ 15841 15842 mutex_enter(&pptr->port_mutex); 15843 if (pptr->port_tmp_cnt == 0) { 15844 mutex_exit(&pptr->port_mutex); 15845 return; 15846 } 15847 mutex_exit(&pptr->port_mutex); 15848 15849 /* 15850 * If we cause a reconfig by raising power, delay until all devices 15851 * report in (port_tmp_cnt returns to 0) 15852 */ 15853 15854 reconfig_start = ddi_get_lbolt(); 15855 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15856 15857 mutex_enter(&pptr->port_mutex); 15858 15859 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15860 pptr->port_tmp_cnt) { 15861 15862 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15863 reconfig_start + wait_timeout); 15864 } 15865 15866 mutex_exit(&pptr->port_mutex); 15867 15868 /* 15869 * Even if fcp_tmp_count isn't 0, continue without error. The port 15870 * we want may still be ok. If not, it will error out later 15871 */ 15872 } 15873 15874 /* 15875 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15876 * We rely on the fcp_global_mutex to provide protection against changes to 15877 * the fcp_lun_blacklist. 15878 * 15879 * You can describe a list of target port WWNs and LUN numbers which will 15880 * not be configured. LUN numbers will be interpreted as decimal. White 15881 * spaces and ',' can be used in the list of LUN numbers. 15882 * 15883 * To prevent LUNs 1 and 2 from being configured for target 15884 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15885 * 15886 * pwwn-lun-blacklist= 15887 * "510000f010fd92a1,1,2", 15888 * "510000e012079df1,1,2"; 15889 */ 15890 static void 15891 fcp_read_blacklist(dev_info_t *dip, 15892 struct fcp_black_list_entry **pplun_blacklist) 15893 { 15894 char **prop_array = NULL; 15895 char *curr_pwwn = NULL; 15896 char *curr_lun = NULL; 15897 uint32_t prop_item = 0; 15898 int idx = 0; 15899 int len = 0; 15900 15901 ASSERT(mutex_owned(&fcp_global_mutex)); 15902 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15903 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15904 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15905 return; 15906 } 15907 15908 for (idx = 0; idx < prop_item; idx++) { 15909 15910 curr_pwwn = prop_array[idx]; 15911 while (*curr_pwwn == ' ') { 15912 curr_pwwn++; 15913 } 15914 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15915 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15916 ", please check.", curr_pwwn); 15917 continue; 15918 } 15919 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15920 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15921 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15922 ", please check.", curr_pwwn); 15923 continue; 15924 } 15925 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15926 if (isxdigit(curr_pwwn[len]) != TRUE) { 15927 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15928 "blacklist, please check.", curr_pwwn); 15929 break; 15930 } 15931 } 15932 if (len != sizeof (la_wwn_t) * 2) { 15933 continue; 15934 } 15935 15936 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15937 *(curr_lun - 1) = '\0'; 15938 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15939 } 15940 15941 ddi_prop_free(prop_array); 15942 } 15943 15944 /* 15945 * Get the masking info about one remote target port designated by wwn. 15946 * Lun ids could be separated by ',' or white spaces. 15947 */ 15948 static void 15949 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15950 struct fcp_black_list_entry **pplun_blacklist) 15951 { 15952 int idx = 0; 15953 uint32_t offset = 0; 15954 unsigned long lun_id = 0; 15955 char lunid_buf[16]; 15956 char *pend = NULL; 15957 int illegal_digit = 0; 15958 15959 while (offset < strlen(curr_lun)) { 15960 while ((curr_lun[offset + idx] != ',') && 15961 (curr_lun[offset + idx] != '\0') && 15962 (curr_lun[offset + idx] != ' ')) { 15963 if (isdigit(curr_lun[offset + idx]) == 0) { 15964 illegal_digit++; 15965 } 15966 idx++; 15967 } 15968 if (illegal_digit > 0) { 15969 offset += (idx+1); /* To the start of next lun */ 15970 idx = 0; 15971 illegal_digit = 0; 15972 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15973 "the blacklist, please check digits.", 15974 curr_lun, curr_pwwn); 15975 continue; 15976 } 15977 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15978 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15979 "the blacklist, please check the length of LUN#.", 15980 curr_lun, curr_pwwn); 15981 break; 15982 } 15983 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15984 offset++; 15985 continue; 15986 } 15987 15988 bcopy(curr_lun + offset, lunid_buf, idx); 15989 lunid_buf[idx] = '\0'; 15990 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15991 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15992 } else { 15993 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15994 "the blacklist, please check %s.", 15995 curr_lun, curr_pwwn, lunid_buf); 15996 } 15997 offset += (idx+1); /* To the start of next lun */ 15998 idx = 0; 15999 } 16000 } 16001 16002 /* 16003 * Add one masking record 16004 */ 16005 static void 16006 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 16007 struct fcp_black_list_entry **pplun_blacklist) 16008 { 16009 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16010 struct fcp_black_list_entry *new_entry = NULL; 16011 la_wwn_t wwn; 16012 16013 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16014 while (tmp_entry) { 16015 if ((bcmp(&tmp_entry->wwn, &wwn, 16016 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16017 return; 16018 } 16019 16020 tmp_entry = tmp_entry->next; 16021 } 16022 16023 /* add to black list */ 16024 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16025 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16026 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16027 new_entry->lun = lun_id; 16028 new_entry->masked = 0; 16029 new_entry->next = *pplun_blacklist; 16030 *pplun_blacklist = new_entry; 16031 } 16032 16033 /* 16034 * Check if we should mask the specified lun of this fcp_tgt 16035 */ 16036 static int 16037 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) 16038 { 16039 struct fcp_black_list_entry *remote_port; 16040 16041 remote_port = fcp_lun_blacklist; 16042 while (remote_port != NULL) { 16043 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16044 if (remote_port->lun == lun_id) { 16045 remote_port->masked++; 16046 if (remote_port->masked == 1) { 16047 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16048 "%02x%02x%02x%02x%02x%02x%02x%02x " 16049 "is masked due to black listing.\n", 16050 lun_id, wwn->raw_wwn[0], 16051 wwn->raw_wwn[1], wwn->raw_wwn[2], 16052 wwn->raw_wwn[3], wwn->raw_wwn[4], 16053 wwn->raw_wwn[5], wwn->raw_wwn[6], 16054 wwn->raw_wwn[7]); 16055 } 16056 return (TRUE); 16057 } 16058 } 16059 remote_port = remote_port->next; 16060 } 16061 return (FALSE); 16062 } 16063 16064 /* 16065 * Release all allocated resources 16066 */ 16067 static void 16068 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) 16069 { 16070 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16071 struct fcp_black_list_entry *current_entry = NULL; 16072 16073 ASSERT(mutex_owned(&fcp_global_mutex)); 16074 /* 16075 * Traverse all luns 16076 */ 16077 while (tmp_entry) { 16078 current_entry = tmp_entry; 16079 tmp_entry = tmp_entry->next; 16080 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16081 } 16082 *pplun_blacklist = NULL; 16083 } 16084 16085 /* 16086 * In fcp module, 16087 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16088 */ 16089 static struct scsi_pkt * 16090 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16091 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16092 int flags, int (*callback)(), caddr_t arg) 16093 { 16094 fcp_port_t *pptr = ADDR2FCP(ap); 16095 fcp_pkt_t *cmd = NULL; 16096 fc_frame_hdr_t *hp; 16097 16098 /* 16099 * First step: get the packet 16100 */ 16101 if (pkt == NULL) { 16102 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16103 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16104 callback, arg); 16105 if (pkt == NULL) { 16106 return (NULL); 16107 } 16108 16109 /* 16110 * All fields in scsi_pkt will be initialized properly or 16111 * set to zero. We need do nothing for scsi_pkt. 16112 */ 16113 /* 16114 * But it's our responsibility to link other related data 16115 * structures. Their initialization will be done, just 16116 * before the scsi_pkt will be sent to FCA. 16117 */ 16118 cmd = PKT2CMD(pkt); 16119 cmd->cmd_pkt = pkt; 16120 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16121 /* 16122 * fc_packet_t 16123 */ 16124 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16125 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16126 sizeof (struct fcp_pkt)); 16127 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16128 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16129 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16130 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16131 /* 16132 * Fill in the Fabric Channel Header 16133 */ 16134 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16135 hp->r_ctl = R_CTL_COMMAND; 16136 hp->rsvd = 0; 16137 hp->type = FC_TYPE_SCSI_FCP; 16138 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16139 hp->seq_id = 0; 16140 hp->df_ctl = 0; 16141 hp->seq_cnt = 0; 16142 hp->ox_id = 0xffff; 16143 hp->rx_id = 0xffff; 16144 hp->ro = 0; 16145 } else { 16146 /* 16147 * We need think if we should reset any elements in 16148 * related data structures. 16149 */ 16150 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16151 fcp_trace, FCP_BUF_LEVEL_6, 0, 16152 "reusing pkt, flags %d", flags); 16153 cmd = PKT2CMD(pkt); 16154 if (cmd->cmd_fp_pkt->pkt_pd) { 16155 cmd->cmd_fp_pkt->pkt_pd = NULL; 16156 } 16157 } 16158 16159 /* 16160 * Second step: dma allocation/move 16161 */ 16162 if (bp && bp->b_bcount != 0) { 16163 /* 16164 * Mark if it's read or write 16165 */ 16166 if (bp->b_flags & B_READ) { 16167 cmd->cmd_flags |= CFLAG_IS_READ; 16168 } else { 16169 cmd->cmd_flags &= ~CFLAG_IS_READ; 16170 } 16171 16172 bp_mapin(bp); 16173 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16174 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16175 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16176 } else { 16177 /* 16178 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16179 * to send zero-length read/write. 16180 */ 16181 cmd->cmd_fp_pkt->pkt_data = NULL; 16182 cmd->cmd_fp_pkt->pkt_datalen = 0; 16183 } 16184 16185 return (pkt); 16186 } 16187 16188 static void 16189 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16190 { 16191 fcp_port_t *pptr = ADDR2FCP(ap); 16192 16193 /* 16194 * First we let FCA to uninitilize private part. 16195 */ 16196 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16197 PKT2CMD(pkt)->cmd_fp_pkt); 16198 16199 /* 16200 * Then we uninitialize fc_packet. 16201 */ 16202 16203 /* 16204 * Thirdly, we uninitializae fcp_pkt. 16205 */ 16206 16207 /* 16208 * In the end, we free scsi_pkt. 16209 */ 16210 scsi_hba_pkt_free(ap, pkt); 16211 } 16212 16213 static int 16214 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16215 { 16216 fcp_port_t *pptr = ADDR2FCP(ap); 16217 fcp_lun_t *plun = ADDR2LUN(ap); 16218 fcp_tgt_t *ptgt = plun->lun_tgt; 16219 fcp_pkt_t *cmd = PKT2CMD(pkt); 16220 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16221 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16222 int rval; 16223 16224 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16225 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16226 16227 /* 16228 * Firstly, we need initialize fcp_pkt_t 16229 * Secondly, we need initialize fcp_cmd_t. 16230 */ 16231 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16232 fcmd->fcp_data_len = fpkt->pkt_datalen; 16233 fcmd->fcp_ent_addr = plun->lun_addr; 16234 if (pkt->pkt_flags & FLAG_HTAG) { 16235 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16236 } else if (pkt->pkt_flags & FLAG_OTAG) { 16237 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16238 } else if (pkt->pkt_flags & FLAG_STAG) { 16239 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16240 } else { 16241 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16242 } 16243 16244 if (cmd->cmd_flags & CFLAG_IS_READ) { 16245 fcmd->fcp_cntl.cntl_read_data = 1; 16246 fcmd->fcp_cntl.cntl_write_data = 0; 16247 } else { 16248 fcmd->fcp_cntl.cntl_read_data = 0; 16249 fcmd->fcp_cntl.cntl_write_data = 1; 16250 } 16251 16252 /* 16253 * Then we need initialize fc_packet_t too. 16254 */ 16255 fpkt->pkt_timeout = pkt->pkt_time + 2; 16256 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16257 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16258 if (cmd->cmd_flags & CFLAG_IS_READ) { 16259 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16260 } else { 16261 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16262 } 16263 16264 if (pkt->pkt_flags & FLAG_NOINTR) { 16265 fpkt->pkt_comp = NULL; 16266 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16267 } else { 16268 fpkt->pkt_comp = fcp_cmd_callback; 16269 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16270 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16271 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16272 } 16273 } 16274 16275 /* 16276 * Lastly, we need initialize scsi_pkt 16277 */ 16278 pkt->pkt_reason = CMD_CMPLT; 16279 pkt->pkt_state = 0; 16280 pkt->pkt_statistics = 0; 16281 pkt->pkt_resid = 0; 16282 16283 /* 16284 * if interrupts aren't allowed (e.g. at dump time) then we'll 16285 * have to do polled I/O 16286 */ 16287 if (pkt->pkt_flags & FLAG_NOINTR) { 16288 return (fcp_dopoll(pptr, cmd)); 16289 } 16290 16291 cmd->cmd_state = FCP_PKT_ISSUED; 16292 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16293 if (rval == FC_SUCCESS) { 16294 return (TRAN_ACCEPT); 16295 } 16296 16297 /* 16298 * Need more consideration 16299 * 16300 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16301 */ 16302 cmd->cmd_state = FCP_PKT_IDLE; 16303 if (rval == FC_TRAN_BUSY) { 16304 return (TRAN_BUSY); 16305 } else { 16306 return (TRAN_FATAL_ERROR); 16307 } 16308 } 16309 16310 /* 16311 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16312 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16313 */ 16314 static void 16315 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16316 { 16317 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16318 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16319 } 16320 16321 /* 16322 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16323 */ 16324 static void 16325 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16326 { 16327 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16328 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16329 }