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, NULL } 861 }; 862 863 864 static fc_ulp_modinfo_t fcp_modinfo = { 865 &fcp_modinfo, /* ulp_handle */ 866 FCTL_ULP_MODREV_4, /* ulp_rev */ 867 FC4_SCSI_FCP, /* ulp_type */ 868 "fcp", /* ulp_name */ 869 FCP_STATEC_MASK, /* ulp_statec_mask */ 870 fcp_port_attach, /* ulp_port_attach */ 871 fcp_port_detach, /* ulp_port_detach */ 872 fcp_port_ioctl, /* ulp_port_ioctl */ 873 fcp_els_callback, /* ulp_els_callback */ 874 fcp_data_callback, /* ulp_data_callback */ 875 fcp_statec_callback /* ulp_statec_callback */ 876 }; 877 878 #ifdef DEBUG 879 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 880 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 881 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 882 FCP_LEVEL_6 | FCP_LEVEL_7) 883 #else 884 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 885 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 886 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 887 FCP_LEVEL_6 | FCP_LEVEL_7) 888 #endif 889 890 /* FCP global variables */ 891 int fcp_bus_config_debug = 0; 892 static int fcp_log_size = FCP_LOG_SIZE; 893 static int fcp_trace = FCP_TRACE_DEFAULT; 894 static fc_trace_logq_t *fcp_logq = NULL; 895 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 896 /* 897 * The auto-configuration is set by default. The only way of disabling it is 898 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 899 */ 900 static int fcp_enable_auto_configuration = 1; 901 static int fcp_max_bus_config_retries = 4; 902 static int fcp_lun_ready_retry = 300; 903 /* 904 * The value assigned to the following variable has changed several times due 905 * to a problem with the data underruns reporting of some firmware(s). The 906 * current value of 50 gives a timeout value of 25 seconds for a max number 907 * of 256 LUNs. 908 */ 909 static int fcp_max_target_retries = 50; 910 /* 911 * Watchdog variables 912 * ------------------ 913 * 914 * fcp_watchdog_init 915 * 916 * Indicates if the watchdog timer is running or not. This is actually 917 * a counter of the number of Fibre Channel ports that attached. When 918 * the first port attaches the watchdog is started. When the last port 919 * detaches the watchdog timer is stopped. 920 * 921 * fcp_watchdog_time 922 * 923 * This is the watchdog clock counter. It is incremented by 924 * fcp_watchdog_time each time the watchdog timer expires. 925 * 926 * fcp_watchdog_timeout 927 * 928 * Increment value of the variable fcp_watchdog_time as well as the 929 * the timeout value of the watchdog timer. The unit is 1 second. It 930 * is strange that this is not a #define but a variable since the code 931 * never changes this value. The reason why it can be said that the 932 * unit is 1 second is because the number of ticks for the watchdog 933 * timer is determined like this: 934 * 935 * fcp_watchdog_tick = fcp_watchdog_timeout * 936 * drv_usectohz(1000000); 937 * 938 * The value 1000000 is hard coded in the code. 939 * 940 * fcp_watchdog_tick 941 * 942 * Watchdog timer value in ticks. 943 */ 944 static int fcp_watchdog_init = 0; 945 static int fcp_watchdog_time = 0; 946 static int fcp_watchdog_timeout = 1; 947 static int fcp_watchdog_tick; 948 949 /* 950 * fcp_offline_delay is a global variable to enable customisation of 951 * the timeout on link offlines or RSCNs. The default value is set 952 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 953 * specified in FCP4 Chapter 11 (see www.t10.org). 954 * 955 * The variable fcp_offline_delay is specified in SECONDS. 956 * 957 * If we made this a static var then the user would not be able to 958 * change it. This variable is set in fcp_attach(). 959 */ 960 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 961 962 static void *fcp_softstate = NULL; /* for soft state */ 963 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 964 static kmutex_t fcp_global_mutex; 965 static kmutex_t fcp_ioctl_mutex; 966 static dev_info_t *fcp_global_dip = NULL; 967 static timeout_id_t fcp_watchdog_id; 968 const char *fcp_lun_prop = "lun"; 969 const char *fcp_sam_lun_prop = "sam-lun"; 970 const char *fcp_target_prop = "target"; 971 /* 972 * NOTE: consumers of "node-wwn" property include stmsboot in ON 973 * consolidation. 974 */ 975 const char *fcp_node_wwn_prop = "node-wwn"; 976 const char *fcp_port_wwn_prop = "port-wwn"; 977 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 978 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 979 const char *fcp_manual_config_only = "manual_configuration_only"; 980 const char *fcp_init_port_prop = "initiator-port"; 981 const char *fcp_tgt_port_prop = "target-port"; 982 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 983 984 static struct fcp_port *fcp_port_head = NULL; 985 static ddi_eventcookie_t fcp_insert_eid; 986 static ddi_eventcookie_t fcp_remove_eid; 987 988 static ndi_event_definition_t fcp_ndi_event_defs[] = { 989 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 990 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 991 }; 992 993 /* 994 * List of valid commands for the scsi_ioctl call 995 */ 996 static uint8_t scsi_ioctl_list[] = { 997 SCMD_INQUIRY, 998 SCMD_REPORT_LUN, 999 SCMD_READ_CAPACITY 1000 }; 1001 1002 /* 1003 * this is used to dummy up a report lun response for cases 1004 * where the target doesn't support it 1005 */ 1006 static uchar_t fcp_dummy_lun[] = { 1007 0x00, /* MSB length (length = no of luns * 8) */ 1008 0x00, 1009 0x00, 1010 0x08, /* LSB length */ 1011 0x00, /* MSB reserved */ 1012 0x00, 1013 0x00, 1014 0x00, /* LSB reserved */ 1015 FCP_PD_ADDRESSING, 1016 0x00, /* LUN is ZERO at the first level */ 1017 0x00, 1018 0x00, /* second level is zero */ 1019 0x00, 1020 0x00, /* third level is zero */ 1021 0x00, 1022 0x00 /* fourth level is zero */ 1023 }; 1024 1025 static uchar_t fcp_alpa_to_switch[] = { 1026 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1027 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1028 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1029 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1030 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1031 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1032 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1033 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1034 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1035 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1036 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1037 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1038 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1039 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1040 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1041 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1042 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1043 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1044 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1046 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1047 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1048 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1049 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1050 }; 1051 1052 static caddr_t pid = "SESS01 "; 1053 1054 #if !defined(lint) 1055 1056 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1057 fcp_port::fcp_next fcp_watchdog_id)) 1058 1059 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1060 1061 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1062 fcp_insert_eid 1063 fcp_remove_eid 1064 fcp_watchdog_time)) 1065 1066 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1067 fcp_cb_ops 1068 fcp_ops 1069 callb_cpr)) 1070 1071 #endif /* lint */ 1072 1073 /* 1074 * This table is used to determine whether or not it's safe to copy in 1075 * the target node name for a lun. Since all luns behind the same target 1076 * have the same wwnn, only tagets that do not support multiple luns are 1077 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1078 */ 1079 1080 char *fcp_symmetric_disk_table[] = { 1081 "SEAGATE ST", 1082 "IBM DDYFT", 1083 "SUNW SUNWGS", /* Daktari enclosure */ 1084 "SUN SENA", /* SES device */ 1085 "SUN SESS01" /* VICOM SVE box */ 1086 }; 1087 1088 int fcp_symmetric_disk_table_size = 1089 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1090 1091 /* 1092 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1093 * will panic if you don't pass this in to the routine, this information. 1094 * Need to determine what the actual impact to the system is by providing 1095 * this information if any. Since dma allocation is done in pkt_init it may 1096 * not have any impact. These values are straight from the Writing Device 1097 * Driver manual. 1098 */ 1099 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1100 DMA_ATTR_V0, /* ddi_dma_attr version */ 1101 0, /* low address */ 1102 0xffffffff, /* high address */ 1103 0x00ffffff, /* counter upper bound */ 1104 1, /* alignment requirements */ 1105 0x3f, /* burst sizes */ 1106 1, /* minimum DMA access */ 1107 0xffffffff, /* maximum DMA access */ 1108 (1 << 24) - 1, /* segment boundary restrictions */ 1109 1, /* scater/gather list length */ 1110 512, /* device granularity */ 1111 0 /* DMA flags */ 1112 }; 1113 1114 /* 1115 * The _init(9e) return value should be that of mod_install(9f). Under 1116 * some circumstances, a failure may not be related mod_install(9f) and 1117 * one would then require a return value to indicate the failure. Looking 1118 * at mod_install(9f), it is expected to return 0 for success and non-zero 1119 * for failure. mod_install(9f) for device drivers, further goes down the 1120 * calling chain and ends up in ddi_installdrv(), whose return values are 1121 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1122 * calling chain of mod_install(9f) which return values like EINVAL and 1123 * in some even return -1. 1124 * 1125 * To work around the vagaries of the mod_install() calling chain, return 1126 * either 0 or ENODEV depending on the success or failure of mod_install() 1127 */ 1128 int 1129 _init(void) 1130 { 1131 int rval; 1132 1133 /* 1134 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1135 * before registering with the transport first. 1136 */ 1137 if (ddi_soft_state_init(&fcp_softstate, 1138 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1139 return (EINVAL); 1140 } 1141 1142 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1143 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1144 1145 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1146 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1147 mutex_destroy(&fcp_global_mutex); 1148 mutex_destroy(&fcp_ioctl_mutex); 1149 ddi_soft_state_fini(&fcp_softstate); 1150 return (ENODEV); 1151 } 1152 1153 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1154 1155 if ((rval = mod_install(&modlinkage)) != 0) { 1156 fc_trace_free_logq(fcp_logq); 1157 (void) fc_ulp_remove(&fcp_modinfo); 1158 mutex_destroy(&fcp_global_mutex); 1159 mutex_destroy(&fcp_ioctl_mutex); 1160 ddi_soft_state_fini(&fcp_softstate); 1161 rval = ENODEV; 1162 } 1163 1164 return (rval); 1165 } 1166 1167 1168 /* 1169 * the system is done with us as a driver, so clean up 1170 */ 1171 int 1172 _fini(void) 1173 { 1174 int rval; 1175 1176 /* 1177 * don't start cleaning up until we know that the module remove 1178 * has worked -- if this works, then we know that each instance 1179 * has successfully been DDI_DETACHed 1180 */ 1181 if ((rval = mod_remove(&modlinkage)) != 0) { 1182 return (rval); 1183 } 1184 1185 (void) fc_ulp_remove(&fcp_modinfo); 1186 1187 ddi_soft_state_fini(&fcp_softstate); 1188 mutex_destroy(&fcp_global_mutex); 1189 mutex_destroy(&fcp_ioctl_mutex); 1190 fc_trace_free_logq(fcp_logq); 1191 1192 return (rval); 1193 } 1194 1195 1196 int 1197 _info(struct modinfo *modinfop) 1198 { 1199 return (mod_info(&modlinkage, modinfop)); 1200 } 1201 1202 1203 /* 1204 * attach the module 1205 */ 1206 static int 1207 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1208 { 1209 int rval = DDI_SUCCESS; 1210 1211 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1212 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1213 1214 if (cmd == DDI_ATTACH) { 1215 /* The FCP pseudo device is created here. */ 1216 mutex_enter(&fcp_global_mutex); 1217 fcp_global_dip = devi; 1218 mutex_exit(&fcp_global_mutex); 1219 1220 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1221 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1222 ddi_report_dev(fcp_global_dip); 1223 } else { 1224 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1225 mutex_enter(&fcp_global_mutex); 1226 fcp_global_dip = NULL; 1227 mutex_exit(&fcp_global_mutex); 1228 1229 rval = DDI_FAILURE; 1230 } 1231 /* 1232 * We check the fcp_offline_delay property at this 1233 * point. This variable is global for the driver, 1234 * not specific to an instance. 1235 * 1236 * We do not recommend setting the value to less 1237 * than 10 seconds (RA_TOV_els), or greater than 1238 * 60 seconds. 1239 */ 1240 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1241 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1242 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1243 if ((fcp_offline_delay < 10) || 1244 (fcp_offline_delay > 60)) { 1245 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1246 "to %d second(s). This is outside the " 1247 "recommended range of 10..60 seconds.", 1248 fcp_offline_delay); 1249 } 1250 } 1251 1252 return (rval); 1253 } 1254 1255 1256 /*ARGSUSED*/ 1257 static int 1258 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1259 { 1260 int res = DDI_SUCCESS; 1261 1262 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1263 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1264 1265 if (cmd == DDI_DETACH) { 1266 /* 1267 * Check if there are active ports/threads. If there 1268 * are any, we will fail, else we will succeed (there 1269 * should not be much to clean up) 1270 */ 1271 mutex_enter(&fcp_global_mutex); 1272 FCP_DTRACE(fcp_logq, "fcp", 1273 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1274 (void *) fcp_port_head); 1275 1276 if (fcp_port_head == NULL) { 1277 ddi_remove_minor_node(fcp_global_dip, NULL); 1278 fcp_global_dip = NULL; 1279 mutex_exit(&fcp_global_mutex); 1280 } else { 1281 mutex_exit(&fcp_global_mutex); 1282 res = DDI_FAILURE; 1283 } 1284 } 1285 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1286 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1287 1288 return (res); 1289 } 1290 1291 1292 /* ARGSUSED */ 1293 static int 1294 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1295 { 1296 if (otype != OTYP_CHR) { 1297 return (EINVAL); 1298 } 1299 1300 /* 1301 * Allow only root to talk; 1302 */ 1303 if (drv_priv(credp)) { 1304 return (EPERM); 1305 } 1306 1307 mutex_enter(&fcp_global_mutex); 1308 if (fcp_oflag & FCP_EXCL) { 1309 mutex_exit(&fcp_global_mutex); 1310 return (EBUSY); 1311 } 1312 1313 if (flag & FEXCL) { 1314 if (fcp_oflag & FCP_OPEN) { 1315 mutex_exit(&fcp_global_mutex); 1316 return (EBUSY); 1317 } 1318 fcp_oflag |= FCP_EXCL; 1319 } 1320 fcp_oflag |= FCP_OPEN; 1321 mutex_exit(&fcp_global_mutex); 1322 1323 return (0); 1324 } 1325 1326 1327 /* ARGSUSED */ 1328 static int 1329 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1330 { 1331 if (otype != OTYP_CHR) { 1332 return (EINVAL); 1333 } 1334 1335 mutex_enter(&fcp_global_mutex); 1336 if (!(fcp_oflag & FCP_OPEN)) { 1337 mutex_exit(&fcp_global_mutex); 1338 return (ENODEV); 1339 } 1340 fcp_oflag = FCP_IDLE; 1341 mutex_exit(&fcp_global_mutex); 1342 1343 return (0); 1344 } 1345 1346 1347 /* 1348 * fcp_ioctl 1349 * Entry point for the FCP ioctls 1350 * 1351 * Input: 1352 * See ioctl(9E) 1353 * 1354 * Output: 1355 * See ioctl(9E) 1356 * 1357 * Returns: 1358 * See ioctl(9E) 1359 * 1360 * Context: 1361 * Kernel context. 1362 */ 1363 /* ARGSUSED */ 1364 static int 1365 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1366 int *rval) 1367 { 1368 int ret = 0; 1369 1370 mutex_enter(&fcp_global_mutex); 1371 if (!(fcp_oflag & FCP_OPEN)) { 1372 mutex_exit(&fcp_global_mutex); 1373 return (ENXIO); 1374 } 1375 mutex_exit(&fcp_global_mutex); 1376 1377 switch (cmd) { 1378 case FCP_TGT_INQUIRY: 1379 case FCP_TGT_CREATE: 1380 case FCP_TGT_DELETE: 1381 ret = fcp_setup_device_data_ioctl(cmd, 1382 (struct fcp_ioctl *)data, mode, rval); 1383 break; 1384 1385 case FCP_TGT_SEND_SCSI: 1386 mutex_enter(&fcp_ioctl_mutex); 1387 ret = fcp_setup_scsi_ioctl( 1388 (struct fcp_scsi_cmd *)data, mode, rval); 1389 mutex_exit(&fcp_ioctl_mutex); 1390 break; 1391 1392 case FCP_STATE_COUNT: 1393 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1394 mode, rval); 1395 break; 1396 case FCP_GET_TARGET_MAPPINGS: 1397 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1398 mode, rval); 1399 break; 1400 default: 1401 fcp_log(CE_WARN, NULL, 1402 "!Invalid ioctl opcode = 0x%x", cmd); 1403 ret = EINVAL; 1404 } 1405 1406 return (ret); 1407 } 1408 1409 1410 /* 1411 * fcp_setup_device_data_ioctl 1412 * Setup handler for the "device data" style of 1413 * ioctl for FCP. See "fcp_util.h" for data structure 1414 * definition. 1415 * 1416 * Input: 1417 * cmd = FCP ioctl command 1418 * data = ioctl data 1419 * mode = See ioctl(9E) 1420 * 1421 * Output: 1422 * data = ioctl data 1423 * rval = return value - see ioctl(9E) 1424 * 1425 * Returns: 1426 * See ioctl(9E) 1427 * 1428 * Context: 1429 * Kernel context. 1430 */ 1431 /* ARGSUSED */ 1432 static int 1433 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1434 int *rval) 1435 { 1436 struct fcp_port *pptr; 1437 struct device_data *dev_data; 1438 uint32_t link_cnt; 1439 la_wwn_t *wwn_ptr = NULL; 1440 struct fcp_tgt *ptgt = NULL; 1441 struct fcp_lun *plun = NULL; 1442 int i, error; 1443 struct fcp_ioctl fioctl; 1444 1445 #ifdef _MULTI_DATAMODEL 1446 switch (ddi_model_convert_from(mode & FMODELS)) { 1447 case DDI_MODEL_ILP32: { 1448 struct fcp32_ioctl f32_ioctl; 1449 1450 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1451 sizeof (struct fcp32_ioctl), mode)) { 1452 return (EFAULT); 1453 } 1454 fioctl.fp_minor = f32_ioctl.fp_minor; 1455 fioctl.listlen = f32_ioctl.listlen; 1456 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1457 break; 1458 } 1459 case DDI_MODEL_NONE: 1460 if (ddi_copyin((void *)data, (void *)&fioctl, 1461 sizeof (struct fcp_ioctl), mode)) { 1462 return (EFAULT); 1463 } 1464 break; 1465 } 1466 1467 #else /* _MULTI_DATAMODEL */ 1468 if (ddi_copyin((void *)data, (void *)&fioctl, 1469 sizeof (struct fcp_ioctl), mode)) { 1470 return (EFAULT); 1471 } 1472 #endif /* _MULTI_DATAMODEL */ 1473 1474 /* 1475 * Right now we can assume that the minor number matches with 1476 * this instance of fp. If this changes we will need to 1477 * revisit this logic. 1478 */ 1479 mutex_enter(&fcp_global_mutex); 1480 pptr = fcp_port_head; 1481 while (pptr) { 1482 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1483 break; 1484 } else { 1485 pptr = pptr->port_next; 1486 } 1487 } 1488 mutex_exit(&fcp_global_mutex); 1489 if (pptr == NULL) { 1490 return (ENXIO); 1491 } 1492 mutex_enter(&pptr->port_mutex); 1493 1494 1495 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1496 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1497 mutex_exit(&pptr->port_mutex); 1498 return (ENOMEM); 1499 } 1500 1501 if (ddi_copyin(fioctl.list, dev_data, 1502 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1503 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1504 mutex_exit(&pptr->port_mutex); 1505 return (EFAULT); 1506 } 1507 link_cnt = pptr->port_link_cnt; 1508 1509 if (cmd == FCP_TGT_INQUIRY) { 1510 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1511 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1512 sizeof (wwn_ptr->raw_wwn)) == 0) { 1513 /* This ioctl is requesting INQ info of local HBA */ 1514 mutex_exit(&pptr->port_mutex); 1515 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1516 dev_data[0].dev_status = 0; 1517 if (ddi_copyout(dev_data, fioctl.list, 1518 (sizeof (struct device_data)) * fioctl.listlen, 1519 mode)) { 1520 kmem_free(dev_data, 1521 sizeof (*dev_data) * fioctl.listlen); 1522 return (EFAULT); 1523 } 1524 kmem_free(dev_data, 1525 sizeof (*dev_data) * fioctl.listlen); 1526 #ifdef _MULTI_DATAMODEL 1527 switch (ddi_model_convert_from(mode & FMODELS)) { 1528 case DDI_MODEL_ILP32: { 1529 struct fcp32_ioctl f32_ioctl; 1530 f32_ioctl.fp_minor = fioctl.fp_minor; 1531 f32_ioctl.listlen = fioctl.listlen; 1532 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1533 if (ddi_copyout((void *)&f32_ioctl, 1534 (void *)data, 1535 sizeof (struct fcp32_ioctl), mode)) { 1536 return (EFAULT); 1537 } 1538 break; 1539 } 1540 case DDI_MODEL_NONE: 1541 if (ddi_copyout((void *)&fioctl, (void *)data, 1542 sizeof (struct fcp_ioctl), mode)) { 1543 return (EFAULT); 1544 } 1545 break; 1546 } 1547 #else /* _MULTI_DATAMODEL */ 1548 if (ddi_copyout((void *)&fioctl, (void *)data, 1549 sizeof (struct fcp_ioctl), mode)) { 1550 return (EFAULT); 1551 } 1552 #endif /* _MULTI_DATAMODEL */ 1553 return (0); 1554 } 1555 } 1556 1557 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1558 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1559 mutex_exit(&pptr->port_mutex); 1560 return (ENXIO); 1561 } 1562 1563 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1564 i++) { 1565 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1566 1567 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1568 1569 1570 dev_data[i].dev_status = ENXIO; 1571 1572 if ((ptgt = fcp_lookup_target(pptr, 1573 (uchar_t *)wwn_ptr)) == NULL) { 1574 mutex_exit(&pptr->port_mutex); 1575 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1576 wwn_ptr, &error, 0) == NULL) { 1577 dev_data[i].dev_status = ENODEV; 1578 mutex_enter(&pptr->port_mutex); 1579 continue; 1580 } else { 1581 1582 dev_data[i].dev_status = EAGAIN; 1583 1584 mutex_enter(&pptr->port_mutex); 1585 continue; 1586 } 1587 } else { 1588 mutex_enter(&ptgt->tgt_mutex); 1589 if (ptgt->tgt_state & (FCP_TGT_MARK | 1590 FCP_TGT_BUSY)) { 1591 dev_data[i].dev_status = EAGAIN; 1592 mutex_exit(&ptgt->tgt_mutex); 1593 continue; 1594 } 1595 1596 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1597 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1598 dev_data[i].dev_status = ENOTSUP; 1599 } else { 1600 dev_data[i].dev_status = ENXIO; 1601 } 1602 mutex_exit(&ptgt->tgt_mutex); 1603 continue; 1604 } 1605 1606 switch (cmd) { 1607 case FCP_TGT_INQUIRY: 1608 /* 1609 * The reason we give device type of 1610 * lun 0 only even though in some 1611 * cases(like maxstrat) lun 0 device 1612 * type may be 0x3f(invalid) is that 1613 * for bridge boxes target will appear 1614 * as luns and the first lun could be 1615 * a device that utility may not care 1616 * about (like a tape device). 1617 */ 1618 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1619 dev_data[i].dev_status = 0; 1620 mutex_exit(&ptgt->tgt_mutex); 1621 1622 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1623 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1624 } else { 1625 dev_data[i].dev0_type = plun->lun_type; 1626 } 1627 mutex_enter(&ptgt->tgt_mutex); 1628 break; 1629 1630 case FCP_TGT_CREATE: 1631 mutex_exit(&ptgt->tgt_mutex); 1632 mutex_exit(&pptr->port_mutex); 1633 1634 /* 1635 * serialize state change call backs. 1636 * only one call back will be handled 1637 * at a time. 1638 */ 1639 mutex_enter(&fcp_global_mutex); 1640 if (fcp_oflag & FCP_BUSY) { 1641 mutex_exit(&fcp_global_mutex); 1642 if (dev_data) { 1643 kmem_free(dev_data, 1644 sizeof (*dev_data) * 1645 fioctl.listlen); 1646 } 1647 return (EBUSY); 1648 } 1649 fcp_oflag |= FCP_BUSY; 1650 mutex_exit(&fcp_global_mutex); 1651 1652 dev_data[i].dev_status = 1653 fcp_create_on_demand(pptr, 1654 wwn_ptr->raw_wwn); 1655 1656 if (dev_data[i].dev_status != 0) { 1657 char buf[25]; 1658 1659 for (i = 0; i < FC_WWN_SIZE; i++) { 1660 (void) sprintf(&buf[i << 1], 1661 "%02x", 1662 wwn_ptr->raw_wwn[i]); 1663 } 1664 1665 fcp_log(CE_WARN, pptr->port_dip, 1666 "!Failed to create nodes for" 1667 " pwwn=%s; error=%x", buf, 1668 dev_data[i].dev_status); 1669 } 1670 1671 /* allow state change call backs again */ 1672 mutex_enter(&fcp_global_mutex); 1673 fcp_oflag &= ~FCP_BUSY; 1674 mutex_exit(&fcp_global_mutex); 1675 1676 mutex_enter(&pptr->port_mutex); 1677 mutex_enter(&ptgt->tgt_mutex); 1678 1679 break; 1680 1681 case FCP_TGT_DELETE: 1682 break; 1683 1684 default: 1685 fcp_log(CE_WARN, pptr->port_dip, 1686 "!Invalid device data ioctl " 1687 "opcode = 0x%x", cmd); 1688 } 1689 mutex_exit(&ptgt->tgt_mutex); 1690 } 1691 } 1692 mutex_exit(&pptr->port_mutex); 1693 1694 if (ddi_copyout(dev_data, fioctl.list, 1695 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1696 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1697 return (EFAULT); 1698 } 1699 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1700 1701 #ifdef _MULTI_DATAMODEL 1702 switch (ddi_model_convert_from(mode & FMODELS)) { 1703 case DDI_MODEL_ILP32: { 1704 struct fcp32_ioctl f32_ioctl; 1705 1706 f32_ioctl.fp_minor = fioctl.fp_minor; 1707 f32_ioctl.listlen = fioctl.listlen; 1708 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1709 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1710 sizeof (struct fcp32_ioctl), mode)) { 1711 return (EFAULT); 1712 } 1713 break; 1714 } 1715 case DDI_MODEL_NONE: 1716 if (ddi_copyout((void *)&fioctl, (void *)data, 1717 sizeof (struct fcp_ioctl), mode)) { 1718 return (EFAULT); 1719 } 1720 break; 1721 } 1722 #else /* _MULTI_DATAMODEL */ 1723 1724 if (ddi_copyout((void *)&fioctl, (void *)data, 1725 sizeof (struct fcp_ioctl), mode)) { 1726 return (EFAULT); 1727 } 1728 #endif /* _MULTI_DATAMODEL */ 1729 1730 return (0); 1731 } 1732 1733 /* 1734 * Fetch the target mappings (path, etc.) for all LUNs 1735 * on this port. 1736 */ 1737 /* ARGSUSED */ 1738 static int 1739 fcp_get_target_mappings(struct fcp_ioctl *data, 1740 int mode, int *rval) 1741 { 1742 struct fcp_port *pptr; 1743 fc_hba_target_mappings_t *mappings; 1744 fc_hba_mapping_entry_t *map; 1745 struct fcp_tgt *ptgt = NULL; 1746 struct fcp_lun *plun = NULL; 1747 int i, mapIndex, mappingSize; 1748 int listlen; 1749 struct fcp_ioctl fioctl; 1750 char *path; 1751 fcp_ent_addr_t sam_lun_addr; 1752 1753 #ifdef _MULTI_DATAMODEL 1754 switch (ddi_model_convert_from(mode & FMODELS)) { 1755 case DDI_MODEL_ILP32: { 1756 struct fcp32_ioctl f32_ioctl; 1757 1758 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1759 sizeof (struct fcp32_ioctl), mode)) { 1760 return (EFAULT); 1761 } 1762 fioctl.fp_minor = f32_ioctl.fp_minor; 1763 fioctl.listlen = f32_ioctl.listlen; 1764 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1765 break; 1766 } 1767 case DDI_MODEL_NONE: 1768 if (ddi_copyin((void *)data, (void *)&fioctl, 1769 sizeof (struct fcp_ioctl), mode)) { 1770 return (EFAULT); 1771 } 1772 break; 1773 } 1774 1775 #else /* _MULTI_DATAMODEL */ 1776 if (ddi_copyin((void *)data, (void *)&fioctl, 1777 sizeof (struct fcp_ioctl), mode)) { 1778 return (EFAULT); 1779 } 1780 #endif /* _MULTI_DATAMODEL */ 1781 1782 /* 1783 * Right now we can assume that the minor number matches with 1784 * this instance of fp. If this changes we will need to 1785 * revisit this logic. 1786 */ 1787 mutex_enter(&fcp_global_mutex); 1788 pptr = fcp_port_head; 1789 while (pptr) { 1790 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1791 break; 1792 } else { 1793 pptr = pptr->port_next; 1794 } 1795 } 1796 mutex_exit(&fcp_global_mutex); 1797 if (pptr == NULL) { 1798 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1799 fioctl.fp_minor); 1800 return (ENXIO); 1801 } 1802 1803 1804 /* We use listlen to show the total buffer size */ 1805 mappingSize = fioctl.listlen; 1806 1807 /* Now calculate how many mapping entries will fit */ 1808 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1809 - sizeof (fc_hba_target_mappings_t); 1810 if (listlen <= 0) { 1811 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1812 return (ENXIO); 1813 } 1814 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1815 1816 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1817 return (ENOMEM); 1818 } 1819 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1820 1821 /* Now get to work */ 1822 mapIndex = 0; 1823 1824 mutex_enter(&pptr->port_mutex); 1825 /* Loop through all targets on this port */ 1826 for (i = 0; i < FCP_NUM_HASH; i++) { 1827 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1828 ptgt = ptgt->tgt_next) { 1829 1830 mutex_enter(&ptgt->tgt_mutex); 1831 1832 /* Loop through all LUNs on this target */ 1833 for (plun = ptgt->tgt_lun; plun != NULL; 1834 plun = plun->lun_next) { 1835 if (plun->lun_state & FCP_LUN_OFFLINE) { 1836 continue; 1837 } 1838 1839 path = fcp_get_lun_path(plun); 1840 if (path == NULL) { 1841 continue; 1842 } 1843 1844 if (mapIndex >= listlen) { 1845 mapIndex ++; 1846 kmem_free(path, MAXPATHLEN); 1847 continue; 1848 } 1849 map = &mappings->entries[mapIndex++]; 1850 bcopy(path, map->targetDriver, 1851 sizeof (map->targetDriver)); 1852 map->d_id = ptgt->tgt_d_id; 1853 map->busNumber = 0; 1854 map->targetNumber = ptgt->tgt_d_id; 1855 map->osLUN = plun->lun_num; 1856 1857 /* 1858 * We had swapped lun when we stored it in 1859 * lun_addr. We need to swap it back before 1860 * returning it to user land 1861 */ 1862 1863 sam_lun_addr.ent_addr_0 = 1864 BE_16(plun->lun_addr.ent_addr_0); 1865 sam_lun_addr.ent_addr_1 = 1866 BE_16(plun->lun_addr.ent_addr_1); 1867 sam_lun_addr.ent_addr_2 = 1868 BE_16(plun->lun_addr.ent_addr_2); 1869 sam_lun_addr.ent_addr_3 = 1870 BE_16(plun->lun_addr.ent_addr_3); 1871 1872 bcopy(&sam_lun_addr, &map->samLUN, 1873 FCP_LUN_SIZE); 1874 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1875 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1876 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1877 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1878 1879 if (plun->lun_guid) { 1880 1881 /* convert ascii wwn to bytes */ 1882 fcp_ascii_to_wwn(plun->lun_guid, 1883 map->guid, sizeof (map->guid)); 1884 1885 if ((sizeof (map->guid)) < 1886 plun->lun_guid_size / 2) { 1887 cmn_err(CE_WARN, 1888 "fcp_get_target_mappings:" 1889 "guid copy space " 1890 "insufficient." 1891 "Copy Truncation - " 1892 "available %d; need %d", 1893 (int)sizeof (map->guid), 1894 (int) 1895 plun->lun_guid_size / 2); 1896 } 1897 } 1898 kmem_free(path, MAXPATHLEN); 1899 } 1900 mutex_exit(&ptgt->tgt_mutex); 1901 } 1902 } 1903 mutex_exit(&pptr->port_mutex); 1904 mappings->numLuns = mapIndex; 1905 1906 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1907 kmem_free(mappings, mappingSize); 1908 return (EFAULT); 1909 } 1910 kmem_free(mappings, mappingSize); 1911 1912 #ifdef _MULTI_DATAMODEL 1913 switch (ddi_model_convert_from(mode & FMODELS)) { 1914 case DDI_MODEL_ILP32: { 1915 struct fcp32_ioctl f32_ioctl; 1916 1917 f32_ioctl.fp_minor = fioctl.fp_minor; 1918 f32_ioctl.listlen = fioctl.listlen; 1919 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1920 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1921 sizeof (struct fcp32_ioctl), mode)) { 1922 return (EFAULT); 1923 } 1924 break; 1925 } 1926 case DDI_MODEL_NONE: 1927 if (ddi_copyout((void *)&fioctl, (void *)data, 1928 sizeof (struct fcp_ioctl), mode)) { 1929 return (EFAULT); 1930 } 1931 break; 1932 } 1933 #else /* _MULTI_DATAMODEL */ 1934 1935 if (ddi_copyout((void *)&fioctl, (void *)data, 1936 sizeof (struct fcp_ioctl), mode)) { 1937 return (EFAULT); 1938 } 1939 #endif /* _MULTI_DATAMODEL */ 1940 1941 return (0); 1942 } 1943 1944 /* 1945 * fcp_setup_scsi_ioctl 1946 * Setup handler for the "scsi passthru" style of 1947 * ioctl for FCP. See "fcp_util.h" for data structure 1948 * definition. 1949 * 1950 * Input: 1951 * u_fscsi = ioctl data (user address space) 1952 * mode = See ioctl(9E) 1953 * 1954 * Output: 1955 * u_fscsi = ioctl data (user address space) 1956 * rval = return value - see ioctl(9E) 1957 * 1958 * Returns: 1959 * 0 = OK 1960 * EAGAIN = See errno.h 1961 * EBUSY = See errno.h 1962 * EFAULT = See errno.h 1963 * EINTR = See errno.h 1964 * EINVAL = See errno.h 1965 * EIO = See errno.h 1966 * ENOMEM = See errno.h 1967 * ENXIO = See errno.h 1968 * 1969 * Context: 1970 * Kernel context. 1971 */ 1972 /* ARGSUSED */ 1973 static int 1974 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1975 int mode, int *rval) 1976 { 1977 int ret = 0; 1978 int temp_ret; 1979 caddr_t k_cdbbufaddr = NULL; 1980 caddr_t k_bufaddr = NULL; 1981 caddr_t k_rqbufaddr = NULL; 1982 caddr_t u_cdbbufaddr; 1983 caddr_t u_bufaddr; 1984 caddr_t u_rqbufaddr; 1985 struct fcp_scsi_cmd k_fscsi; 1986 1987 /* 1988 * Get fcp_scsi_cmd array element from user address space 1989 */ 1990 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1991 != 0) { 1992 return (ret); 1993 } 1994 1995 1996 /* 1997 * Even though kmem_alloc() checks the validity of the 1998 * buffer length, this check is needed when the 1999 * kmem_flags set and the zero buffer length is passed. 2000 */ 2001 if ((k_fscsi.scsi_cdblen <= 0) || 2002 (k_fscsi.scsi_buflen <= 0) || 2003 (k_fscsi.scsi_rqlen <= 0)) { 2004 return (EINVAL); 2005 } 2006 2007 /* 2008 * Allocate data for fcp_scsi_cmd pointer fields 2009 */ 2010 if (ret == 0) { 2011 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 2012 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 2013 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 2014 2015 if (k_cdbbufaddr == NULL || 2016 k_bufaddr == NULL || 2017 k_rqbufaddr == NULL) { 2018 ret = ENOMEM; 2019 } 2020 } 2021 2022 /* 2023 * Get fcp_scsi_cmd pointer fields from user 2024 * address space 2025 */ 2026 if (ret == 0) { 2027 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2028 u_bufaddr = k_fscsi.scsi_bufaddr; 2029 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2030 2031 if (ddi_copyin(u_cdbbufaddr, 2032 k_cdbbufaddr, 2033 k_fscsi.scsi_cdblen, 2034 mode)) { 2035 ret = EFAULT; 2036 } else if (ddi_copyin(u_bufaddr, 2037 k_bufaddr, 2038 k_fscsi.scsi_buflen, 2039 mode)) { 2040 ret = EFAULT; 2041 } else if (ddi_copyin(u_rqbufaddr, 2042 k_rqbufaddr, 2043 k_fscsi.scsi_rqlen, 2044 mode)) { 2045 ret = EFAULT; 2046 } 2047 } 2048 2049 /* 2050 * Send scsi command (blocking) 2051 */ 2052 if (ret == 0) { 2053 /* 2054 * Prior to sending the scsi command, the 2055 * fcp_scsi_cmd data structure must contain kernel, 2056 * not user, addresses. 2057 */ 2058 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2059 k_fscsi.scsi_bufaddr = k_bufaddr; 2060 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2061 2062 ret = fcp_send_scsi_ioctl(&k_fscsi); 2063 2064 /* 2065 * After sending the scsi command, the 2066 * fcp_scsi_cmd data structure must contain user, 2067 * not kernel, addresses. 2068 */ 2069 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2070 k_fscsi.scsi_bufaddr = u_bufaddr; 2071 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2072 } 2073 2074 /* 2075 * Put fcp_scsi_cmd pointer fields to user address space 2076 */ 2077 if (ret == 0) { 2078 if (ddi_copyout(k_cdbbufaddr, 2079 u_cdbbufaddr, 2080 k_fscsi.scsi_cdblen, 2081 mode)) { 2082 ret = EFAULT; 2083 } else if (ddi_copyout(k_bufaddr, 2084 u_bufaddr, 2085 k_fscsi.scsi_buflen, 2086 mode)) { 2087 ret = EFAULT; 2088 } else if (ddi_copyout(k_rqbufaddr, 2089 u_rqbufaddr, 2090 k_fscsi.scsi_rqlen, 2091 mode)) { 2092 ret = EFAULT; 2093 } 2094 } 2095 2096 /* 2097 * Free data for fcp_scsi_cmd pointer fields 2098 */ 2099 if (k_cdbbufaddr != NULL) { 2100 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2101 } 2102 if (k_bufaddr != NULL) { 2103 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2104 } 2105 if (k_rqbufaddr != NULL) { 2106 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2107 } 2108 2109 /* 2110 * Put fcp_scsi_cmd array element to user address space 2111 */ 2112 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2113 if (temp_ret != 0) { 2114 ret = temp_ret; 2115 } 2116 2117 /* 2118 * Return status 2119 */ 2120 return (ret); 2121 } 2122 2123 2124 /* 2125 * fcp_copyin_scsi_cmd 2126 * Copy in fcp_scsi_cmd data structure from user address space. 2127 * The data may be in 32 bit or 64 bit modes. 2128 * 2129 * Input: 2130 * base_addr = from address (user address space) 2131 * mode = See ioctl(9E) and ddi_copyin(9F) 2132 * 2133 * Output: 2134 * fscsi = to address (kernel address space) 2135 * 2136 * Returns: 2137 * 0 = OK 2138 * EFAULT = Error 2139 * 2140 * Context: 2141 * Kernel context. 2142 */ 2143 static int 2144 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2145 { 2146 #ifdef _MULTI_DATAMODEL 2147 struct fcp32_scsi_cmd f32scsi; 2148 2149 switch (ddi_model_convert_from(mode & FMODELS)) { 2150 case DDI_MODEL_ILP32: 2151 /* 2152 * Copy data from user address space 2153 */ 2154 if (ddi_copyin((void *)base_addr, 2155 &f32scsi, 2156 sizeof (struct fcp32_scsi_cmd), 2157 mode)) { 2158 return (EFAULT); 2159 } 2160 /* 2161 * Convert from 32 bit to 64 bit 2162 */ 2163 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2164 break; 2165 case DDI_MODEL_NONE: 2166 /* 2167 * Copy data from user address space 2168 */ 2169 if (ddi_copyin((void *)base_addr, 2170 fscsi, 2171 sizeof (struct fcp_scsi_cmd), 2172 mode)) { 2173 return (EFAULT); 2174 } 2175 break; 2176 } 2177 #else /* _MULTI_DATAMODEL */ 2178 /* 2179 * Copy data from user address space 2180 */ 2181 if (ddi_copyin((void *)base_addr, 2182 fscsi, 2183 sizeof (struct fcp_scsi_cmd), 2184 mode)) { 2185 return (EFAULT); 2186 } 2187 #endif /* _MULTI_DATAMODEL */ 2188 2189 return (0); 2190 } 2191 2192 2193 /* 2194 * fcp_copyout_scsi_cmd 2195 * Copy out fcp_scsi_cmd data structure to user address space. 2196 * The data may be in 32 bit or 64 bit modes. 2197 * 2198 * Input: 2199 * fscsi = to address (kernel address space) 2200 * mode = See ioctl(9E) and ddi_copyin(9F) 2201 * 2202 * Output: 2203 * base_addr = from address (user address space) 2204 * 2205 * Returns: 2206 * 0 = OK 2207 * EFAULT = Error 2208 * 2209 * Context: 2210 * Kernel context. 2211 */ 2212 static int 2213 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2214 { 2215 #ifdef _MULTI_DATAMODEL 2216 struct fcp32_scsi_cmd f32scsi; 2217 2218 switch (ddi_model_convert_from(mode & FMODELS)) { 2219 case DDI_MODEL_ILP32: 2220 /* 2221 * Convert from 64 bit to 32 bit 2222 */ 2223 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2224 /* 2225 * Copy data to user address space 2226 */ 2227 if (ddi_copyout(&f32scsi, 2228 (void *)base_addr, 2229 sizeof (struct fcp32_scsi_cmd), 2230 mode)) { 2231 return (EFAULT); 2232 } 2233 break; 2234 case DDI_MODEL_NONE: 2235 /* 2236 * Copy data to user address space 2237 */ 2238 if (ddi_copyout(fscsi, 2239 (void *)base_addr, 2240 sizeof (struct fcp_scsi_cmd), 2241 mode)) { 2242 return (EFAULT); 2243 } 2244 break; 2245 } 2246 #else /* _MULTI_DATAMODEL */ 2247 /* 2248 * Copy data to user address space 2249 */ 2250 if (ddi_copyout(fscsi, 2251 (void *)base_addr, 2252 sizeof (struct fcp_scsi_cmd), 2253 mode)) { 2254 return (EFAULT); 2255 } 2256 #endif /* _MULTI_DATAMODEL */ 2257 2258 return (0); 2259 } 2260 2261 2262 /* 2263 * fcp_send_scsi_ioctl 2264 * Sends the SCSI command in blocking mode. 2265 * 2266 * Input: 2267 * fscsi = SCSI command data structure 2268 * 2269 * Output: 2270 * fscsi = SCSI command data structure 2271 * 2272 * Returns: 2273 * 0 = OK 2274 * EAGAIN = See errno.h 2275 * EBUSY = See errno.h 2276 * EINTR = See errno.h 2277 * EINVAL = See errno.h 2278 * EIO = See errno.h 2279 * ENOMEM = See errno.h 2280 * ENXIO = See errno.h 2281 * 2282 * Context: 2283 * Kernel context. 2284 */ 2285 static int 2286 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2287 { 2288 struct fcp_lun *plun = NULL; 2289 struct fcp_port *pptr = NULL; 2290 struct fcp_tgt *ptgt = NULL; 2291 fc_packet_t *fpkt = NULL; 2292 struct fcp_ipkt *icmd = NULL; 2293 int target_created = FALSE; 2294 fc_frame_hdr_t *hp; 2295 struct fcp_cmd fcp_cmd; 2296 struct fcp_cmd *fcmd; 2297 union scsi_cdb *scsi_cdb; 2298 la_wwn_t *wwn_ptr; 2299 int nodma; 2300 struct fcp_rsp *rsp; 2301 struct fcp_rsp_info *rsp_info; 2302 caddr_t rsp_sense; 2303 int buf_len; 2304 int info_len; 2305 int sense_len; 2306 struct scsi_extended_sense *sense_to = NULL; 2307 timeout_id_t tid; 2308 uint8_t reconfig_lun = FALSE; 2309 uint8_t reconfig_pending = FALSE; 2310 uint8_t scsi_cmd; 2311 int rsp_len; 2312 int cmd_index; 2313 int fc_status; 2314 int pkt_state; 2315 int pkt_action; 2316 int pkt_reason; 2317 int ret, xport_retval = ~FC_SUCCESS; 2318 int lcount; 2319 int tcount; 2320 int reconfig_status; 2321 int port_busy = FALSE; 2322 uchar_t *lun_string; 2323 2324 /* 2325 * Check valid SCSI command 2326 */ 2327 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2328 ret = EINVAL; 2329 for (cmd_index = 0; 2330 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2331 ret != 0; 2332 cmd_index++) { 2333 /* 2334 * First byte of CDB is the SCSI command 2335 */ 2336 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2337 ret = 0; 2338 } 2339 } 2340 2341 /* 2342 * Check inputs 2343 */ 2344 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2345 ret = EINVAL; 2346 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2347 /* no larger than */ 2348 ret = EINVAL; 2349 } 2350 2351 2352 /* 2353 * Find FC port 2354 */ 2355 if (ret == 0) { 2356 /* 2357 * Acquire global mutex 2358 */ 2359 mutex_enter(&fcp_global_mutex); 2360 2361 pptr = fcp_port_head; 2362 while (pptr) { 2363 if (pptr->port_instance == 2364 (uint32_t)fscsi->scsi_fc_port_num) { 2365 break; 2366 } else { 2367 pptr = pptr->port_next; 2368 } 2369 } 2370 2371 if (pptr == NULL) { 2372 ret = ENXIO; 2373 } else { 2374 /* 2375 * fc_ulp_busy_port can raise power 2376 * so, we must not hold any mutexes involved in PM 2377 */ 2378 mutex_exit(&fcp_global_mutex); 2379 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2380 } 2381 2382 if (ret == 0) { 2383 2384 /* remember port is busy, so we will release later */ 2385 port_busy = TRUE; 2386 2387 /* 2388 * If there is a reconfiguration in progress, wait 2389 * for it to complete. 2390 */ 2391 2392 fcp_reconfig_wait(pptr); 2393 2394 /* reacquire mutexes in order */ 2395 mutex_enter(&fcp_global_mutex); 2396 mutex_enter(&pptr->port_mutex); 2397 2398 /* 2399 * Will port accept DMA? 2400 */ 2401 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2402 ? 1 : 0; 2403 2404 /* 2405 * If init or offline, device not known 2406 * 2407 * If we are discovering (onlining), we can 2408 * NOT obviously provide reliable data about 2409 * devices until it is complete 2410 */ 2411 if (pptr->port_state & (FCP_STATE_INIT | 2412 FCP_STATE_OFFLINE)) { 2413 ret = ENXIO; 2414 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2415 ret = EBUSY; 2416 } else { 2417 /* 2418 * Find target from pwwn 2419 * 2420 * The wwn must be put into a local 2421 * variable to ensure alignment. 2422 */ 2423 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2424 ptgt = fcp_lookup_target(pptr, 2425 (uchar_t *)wwn_ptr); 2426 2427 /* 2428 * If target not found, 2429 */ 2430 if (ptgt == NULL) { 2431 /* 2432 * Note: Still have global & 2433 * port mutexes 2434 */ 2435 mutex_exit(&pptr->port_mutex); 2436 ptgt = fcp_port_create_tgt(pptr, 2437 wwn_ptr, &ret, &fc_status, 2438 &pkt_state, &pkt_action, 2439 &pkt_reason); 2440 mutex_enter(&pptr->port_mutex); 2441 2442 fscsi->scsi_fc_status = fc_status; 2443 fscsi->scsi_pkt_state = 2444 (uchar_t)pkt_state; 2445 fscsi->scsi_pkt_reason = pkt_reason; 2446 fscsi->scsi_pkt_action = 2447 (uchar_t)pkt_action; 2448 2449 if (ptgt != NULL) { 2450 target_created = TRUE; 2451 } else if (ret == 0) { 2452 ret = ENOMEM; 2453 } 2454 } 2455 2456 if (ret == 0) { 2457 /* 2458 * Acquire target 2459 */ 2460 mutex_enter(&ptgt->tgt_mutex); 2461 2462 /* 2463 * If target is mark or busy, 2464 * then target can not be used 2465 */ 2466 if (ptgt->tgt_state & 2467 (FCP_TGT_MARK | 2468 FCP_TGT_BUSY)) { 2469 ret = EBUSY; 2470 } else { 2471 /* 2472 * Mark target as busy 2473 */ 2474 ptgt->tgt_state |= 2475 FCP_TGT_BUSY; 2476 } 2477 2478 /* 2479 * Release target 2480 */ 2481 lcount = pptr->port_link_cnt; 2482 tcount = ptgt->tgt_change_cnt; 2483 mutex_exit(&ptgt->tgt_mutex); 2484 } 2485 } 2486 2487 /* 2488 * Release port 2489 */ 2490 mutex_exit(&pptr->port_mutex); 2491 } 2492 2493 /* 2494 * Release global mutex 2495 */ 2496 mutex_exit(&fcp_global_mutex); 2497 } 2498 2499 if (ret == 0) { 2500 uint64_t belun = BE_64(fscsi->scsi_lun); 2501 2502 /* 2503 * If it's a target device, find lun from pwwn 2504 * The wwn must be put into a local 2505 * variable to ensure alignment. 2506 */ 2507 mutex_enter(&pptr->port_mutex); 2508 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2509 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2510 /* this is not a target */ 2511 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2512 ret = ENXIO; 2513 } else if ((belun << 16) != 0) { 2514 /* 2515 * Since fcp only support PD and LU addressing method 2516 * so far, the last 6 bytes of a valid LUN are expected 2517 * to be filled with 00h. 2518 */ 2519 fscsi->scsi_fc_status = FC_INVALID_LUN; 2520 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2521 " method 0x%02x with LUN number 0x%016" PRIx64, 2522 (uint8_t)(belun >> 62), belun); 2523 ret = ENXIO; 2524 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2525 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2526 /* 2527 * This is a SCSI target, but no LUN at this 2528 * address. 2529 * 2530 * In the future, we may want to send this to 2531 * the target, and let it respond 2532 * appropriately 2533 */ 2534 ret = ENXIO; 2535 } 2536 mutex_exit(&pptr->port_mutex); 2537 } 2538 2539 /* 2540 * Finished grabbing external resources 2541 * Allocate internal packet (icmd) 2542 */ 2543 if (ret == 0) { 2544 /* 2545 * Calc rsp len assuming rsp info included 2546 */ 2547 rsp_len = sizeof (struct fcp_rsp) + 2548 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2549 2550 icmd = fcp_icmd_alloc(pptr, ptgt, 2551 sizeof (struct fcp_cmd), 2552 rsp_len, 2553 fscsi->scsi_buflen, 2554 nodma, 2555 lcount, /* ipkt_link_cnt */ 2556 tcount, /* ipkt_change_cnt */ 2557 0, /* cause */ 2558 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2559 2560 if (icmd == NULL) { 2561 ret = ENOMEM; 2562 } else { 2563 /* 2564 * Setup internal packet as sema sync 2565 */ 2566 fcp_ipkt_sema_init(icmd); 2567 } 2568 } 2569 2570 if (ret == 0) { 2571 /* 2572 * Init fpkt pointer for use. 2573 */ 2574 2575 fpkt = icmd->ipkt_fpkt; 2576 2577 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2578 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2579 fpkt->pkt_timeout = fscsi->scsi_timeout; 2580 2581 /* 2582 * Init fcmd pointer for use by SCSI command 2583 */ 2584 2585 if (nodma) { 2586 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2587 } else { 2588 fcmd = &fcp_cmd; 2589 } 2590 bzero(fcmd, sizeof (struct fcp_cmd)); 2591 ptgt = plun->lun_tgt; 2592 2593 lun_string = (uchar_t *)&fscsi->scsi_lun; 2594 2595 fcmd->fcp_ent_addr.ent_addr_0 = 2596 BE_16(*(uint16_t *)&(lun_string[0])); 2597 fcmd->fcp_ent_addr.ent_addr_1 = 2598 BE_16(*(uint16_t *)&(lun_string[2])); 2599 fcmd->fcp_ent_addr.ent_addr_2 = 2600 BE_16(*(uint16_t *)&(lun_string[4])); 2601 fcmd->fcp_ent_addr.ent_addr_3 = 2602 BE_16(*(uint16_t *)&(lun_string[6])); 2603 2604 /* 2605 * Setup internal packet(icmd) 2606 */ 2607 icmd->ipkt_lun = plun; 2608 icmd->ipkt_restart = 0; 2609 icmd->ipkt_retries = 0; 2610 icmd->ipkt_opcode = 0; 2611 2612 /* 2613 * Init the frame HEADER Pointer for use 2614 */ 2615 hp = &fpkt->pkt_cmd_fhdr; 2616 2617 hp->s_id = pptr->port_id; 2618 hp->d_id = ptgt->tgt_d_id; 2619 hp->r_ctl = R_CTL_COMMAND; 2620 hp->type = FC_TYPE_SCSI_FCP; 2621 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2622 hp->rsvd = 0; 2623 hp->seq_id = 0; 2624 hp->seq_cnt = 0; 2625 hp->ox_id = 0xffff; 2626 hp->rx_id = 0xffff; 2627 hp->ro = 0; 2628 2629 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2630 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2631 fcmd->fcp_cntl.cntl_write_data = 0; 2632 fcmd->fcp_data_len = fscsi->scsi_buflen; 2633 2634 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2635 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2636 fscsi->scsi_cdblen); 2637 2638 if (!nodma) { 2639 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2640 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2641 } 2642 2643 /* 2644 * Send SCSI command to FC transport 2645 */ 2646 2647 if (ret == 0) { 2648 mutex_enter(&ptgt->tgt_mutex); 2649 2650 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2651 mutex_exit(&ptgt->tgt_mutex); 2652 fscsi->scsi_fc_status = xport_retval = 2653 fc_ulp_transport(pptr->port_fp_handle, 2654 fpkt); 2655 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2656 ret = EIO; 2657 } 2658 } else { 2659 mutex_exit(&ptgt->tgt_mutex); 2660 ret = EBUSY; 2661 } 2662 } 2663 } 2664 2665 /* 2666 * Wait for completion only if fc_ulp_transport was called and it 2667 * returned a success. This is the only time callback will happen. 2668 * Otherwise, there is no point in waiting 2669 */ 2670 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2671 ret = fcp_ipkt_sema_wait(icmd); 2672 } 2673 2674 /* 2675 * Copy data to IOCTL data structures 2676 */ 2677 rsp = NULL; 2678 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2679 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2680 2681 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2682 fcp_log(CE_WARN, pptr->port_dip, 2683 "!SCSI command to d_id=0x%x lun=0x%x" 2684 " failed, Bad FCP response values:" 2685 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2686 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2687 ptgt->tgt_d_id, plun->lun_num, 2688 rsp->reserved_0, rsp->reserved_1, 2689 rsp->fcp_u.fcp_status.reserved_0, 2690 rsp->fcp_u.fcp_status.reserved_1, 2691 rsp->fcp_response_len, rsp->fcp_sense_len); 2692 2693 ret = EIO; 2694 } 2695 } 2696 2697 if ((ret == 0) && (rsp != NULL)) { 2698 /* 2699 * Calc response lengths 2700 */ 2701 sense_len = 0; 2702 info_len = 0; 2703 2704 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2705 info_len = rsp->fcp_response_len; 2706 } 2707 2708 rsp_info = (struct fcp_rsp_info *) 2709 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2710 2711 /* 2712 * Get SCSI status 2713 */ 2714 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2715 /* 2716 * If a lun was just added or removed and the next command 2717 * comes through this interface, we need to capture the check 2718 * condition so we can discover the new topology. 2719 */ 2720 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2721 rsp->fcp_u.fcp_status.sense_len_set) { 2722 sense_len = rsp->fcp_sense_len; 2723 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2724 sense_to = (struct scsi_extended_sense *)rsp_sense; 2725 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2726 (FCP_SENSE_NO_LUN(sense_to))) { 2727 reconfig_lun = TRUE; 2728 } 2729 } 2730 2731 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2732 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2733 if (reconfig_lun == FALSE) { 2734 reconfig_status = 2735 fcp_is_reconfig_needed(ptgt, fpkt); 2736 } 2737 2738 if ((reconfig_lun == TRUE) || 2739 (reconfig_status == TRUE)) { 2740 mutex_enter(&ptgt->tgt_mutex); 2741 if (ptgt->tgt_tid == NULL) { 2742 /* 2743 * Either we've been notified the 2744 * REPORT_LUN data has changed, or 2745 * we've determined on our own that 2746 * we're out of date. Kick off 2747 * rediscovery. 2748 */ 2749 tid = timeout(fcp_reconfigure_luns, 2750 (caddr_t)ptgt, drv_usectohz(1)); 2751 2752 ptgt->tgt_tid = tid; 2753 ptgt->tgt_state |= FCP_TGT_BUSY; 2754 ret = EBUSY; 2755 reconfig_pending = TRUE; 2756 } 2757 mutex_exit(&ptgt->tgt_mutex); 2758 } 2759 } 2760 2761 /* 2762 * Calc residuals and buffer lengths 2763 */ 2764 2765 if (ret == 0) { 2766 buf_len = fscsi->scsi_buflen; 2767 fscsi->scsi_bufresid = 0; 2768 if (rsp->fcp_u.fcp_status.resid_under) { 2769 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2770 fscsi->scsi_bufresid = rsp->fcp_resid; 2771 } else { 2772 cmn_err(CE_WARN, "fcp: bad residue %x " 2773 "for txfer len %x", rsp->fcp_resid, 2774 fscsi->scsi_buflen); 2775 fscsi->scsi_bufresid = 2776 fscsi->scsi_buflen; 2777 } 2778 buf_len -= fscsi->scsi_bufresid; 2779 } 2780 if (rsp->fcp_u.fcp_status.resid_over) { 2781 fscsi->scsi_bufresid = -rsp->fcp_resid; 2782 } 2783 2784 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2785 if (fscsi->scsi_rqlen < sense_len) { 2786 sense_len = fscsi->scsi_rqlen; 2787 } 2788 2789 fscsi->scsi_fc_rspcode = 0; 2790 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2791 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2792 } 2793 fscsi->scsi_pkt_state = fpkt->pkt_state; 2794 fscsi->scsi_pkt_action = fpkt->pkt_action; 2795 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2796 2797 /* 2798 * Copy data and request sense 2799 * 2800 * Data must be copied by using the FCP_CP_IN macro. 2801 * This will ensure the proper byte order since the data 2802 * is being copied directly from the memory mapped 2803 * device register. 2804 * 2805 * The response (and request sense) will be in the 2806 * correct byte order. No special copy is necessary. 2807 */ 2808 2809 if (buf_len) { 2810 FCP_CP_IN(fpkt->pkt_data, 2811 fscsi->scsi_bufaddr, 2812 fpkt->pkt_data_acc, 2813 buf_len); 2814 } 2815 bcopy((void *)rsp_sense, 2816 (void *)fscsi->scsi_rqbufaddr, 2817 sense_len); 2818 } 2819 } 2820 2821 /* 2822 * Cleanup transport data structures if icmd was alloc-ed 2823 * So, cleanup happens in the same thread that icmd was alloc-ed 2824 */ 2825 if (icmd != NULL) { 2826 fcp_ipkt_sema_cleanup(icmd); 2827 } 2828 2829 /* restore pm busy/idle status */ 2830 if (port_busy) { 2831 fc_ulp_idle_port(pptr->port_fp_handle); 2832 } 2833 2834 /* 2835 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2836 * flag, it'll be cleared when the reconfig is complete. 2837 */ 2838 if ((ptgt != NULL) && !reconfig_pending) { 2839 /* 2840 * If target was created, 2841 */ 2842 if (target_created) { 2843 mutex_enter(&ptgt->tgt_mutex); 2844 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2845 mutex_exit(&ptgt->tgt_mutex); 2846 } else { 2847 /* 2848 * De-mark target as busy 2849 */ 2850 mutex_enter(&ptgt->tgt_mutex); 2851 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2852 mutex_exit(&ptgt->tgt_mutex); 2853 } 2854 } 2855 return (ret); 2856 } 2857 2858 2859 static int 2860 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2861 fc_packet_t *fpkt) 2862 { 2863 uchar_t *lun_string; 2864 uint16_t lun_num, i; 2865 int num_luns; 2866 int actual_luns; 2867 int num_masked_luns; 2868 int lun_buflen; 2869 struct fcp_lun *plun = NULL; 2870 struct fcp_reportlun_resp *report_lun; 2871 uint8_t reconfig_needed = FALSE; 2872 uint8_t lun_exists = FALSE; 2873 fcp_port_t *pptr = ptgt->tgt_port; 2874 2875 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2876 2877 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2878 fpkt->pkt_datalen); 2879 2880 /* get number of luns (which is supplied as LUNS * 8) */ 2881 num_luns = BE_32(report_lun->num_lun) >> 3; 2882 2883 /* 2884 * Figure out exactly how many lun strings our response buffer 2885 * can hold. 2886 */ 2887 lun_buflen = (fpkt->pkt_datalen - 2888 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2889 2890 /* 2891 * Is our response buffer full or not? We don't want to 2892 * potentially walk beyond the number of luns we have. 2893 */ 2894 if (num_luns <= lun_buflen) { 2895 actual_luns = num_luns; 2896 } else { 2897 actual_luns = lun_buflen; 2898 } 2899 2900 mutex_enter(&ptgt->tgt_mutex); 2901 2902 /* Scan each lun to see if we have masked it. */ 2903 num_masked_luns = 0; 2904 if (fcp_lun_blacklist != NULL) { 2905 for (i = 0; i < actual_luns; i++) { 2906 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2907 switch (lun_string[0] & 0xC0) { 2908 case FCP_LUN_ADDRESSING: 2909 case FCP_PD_ADDRESSING: 2910 case FCP_VOLUME_ADDRESSING: 2911 lun_num = ((lun_string[0] & 0x3F) << 8) 2912 | lun_string[1]; 2913 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2914 lun_num) == TRUE) { 2915 num_masked_luns++; 2916 } 2917 break; 2918 default: 2919 break; 2920 } 2921 } 2922 } 2923 2924 /* 2925 * The quick and easy check. If the number of LUNs reported 2926 * doesn't match the number we currently know about, we need 2927 * to reconfigure. 2928 */ 2929 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2930 mutex_exit(&ptgt->tgt_mutex); 2931 kmem_free(report_lun, fpkt->pkt_datalen); 2932 return (TRUE); 2933 } 2934 2935 /* 2936 * If the quick and easy check doesn't turn up anything, we walk 2937 * the list of luns from the REPORT_LUN response and look for 2938 * any luns we don't know about. If we find one, we know we need 2939 * to reconfigure. We will skip LUNs that are masked because of the 2940 * blacklist. 2941 */ 2942 for (i = 0; i < actual_luns; i++) { 2943 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2944 lun_exists = FALSE; 2945 switch (lun_string[0] & 0xC0) { 2946 case FCP_LUN_ADDRESSING: 2947 case FCP_PD_ADDRESSING: 2948 case FCP_VOLUME_ADDRESSING: 2949 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2950 2951 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2952 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2953 lun_exists = TRUE; 2954 break; 2955 } 2956 2957 for (plun = ptgt->tgt_lun; plun; 2958 plun = plun->lun_next) { 2959 if (plun->lun_num == lun_num) { 2960 lun_exists = TRUE; 2961 break; 2962 } 2963 } 2964 break; 2965 default: 2966 break; 2967 } 2968 2969 if (lun_exists == FALSE) { 2970 reconfig_needed = TRUE; 2971 break; 2972 } 2973 } 2974 2975 mutex_exit(&ptgt->tgt_mutex); 2976 kmem_free(report_lun, fpkt->pkt_datalen); 2977 2978 return (reconfig_needed); 2979 } 2980 2981 /* 2982 * This function is called by fcp_handle_page83 and uses inquiry response data 2983 * stored in plun->lun_inq to determine whether or not a device is a member of 2984 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2985 * otherwise 1. 2986 */ 2987 static int 2988 fcp_symmetric_device_probe(struct fcp_lun *plun) 2989 { 2990 struct scsi_inquiry *stdinq = &plun->lun_inq; 2991 char *devidptr; 2992 int i, len; 2993 2994 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2995 devidptr = fcp_symmetric_disk_table[i]; 2996 len = (int)strlen(devidptr); 2997 2998 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 2999 return (0); 3000 } 3001 } 3002 return (1); 3003 } 3004 3005 3006 /* 3007 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 3008 * It basically returns the current count of # of state change callbacks 3009 * i.e the value of tgt_change_cnt. 3010 * 3011 * INPUT: 3012 * fcp_ioctl.fp_minor -> The minor # of the fp port 3013 * fcp_ioctl.listlen -> 1 3014 * fcp_ioctl.list -> Pointer to a 32 bit integer 3015 */ 3016 /*ARGSUSED2*/ 3017 static int 3018 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3019 { 3020 int ret; 3021 uint32_t link_cnt; 3022 struct fcp_ioctl fioctl; 3023 struct fcp_port *pptr = NULL; 3024 3025 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3026 &pptr)) != 0) { 3027 return (ret); 3028 } 3029 3030 ASSERT(pptr != NULL); 3031 3032 if (fioctl.listlen != 1) { 3033 return (EINVAL); 3034 } 3035 3036 mutex_enter(&pptr->port_mutex); 3037 if (pptr->port_state & FCP_STATE_OFFLINE) { 3038 mutex_exit(&pptr->port_mutex); 3039 return (ENXIO); 3040 } 3041 3042 /* 3043 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3044 * When the fcp initially attaches to the port and there are nothing 3045 * hanging out of the port or if there was a repeat offline state change 3046 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3047 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3048 * will differentiate the 2 cases. 3049 */ 3050 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3051 mutex_exit(&pptr->port_mutex); 3052 return (ENXIO); 3053 } 3054 3055 link_cnt = pptr->port_link_cnt; 3056 mutex_exit(&pptr->port_mutex); 3057 3058 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3059 return (EFAULT); 3060 } 3061 3062 #ifdef _MULTI_DATAMODEL 3063 switch (ddi_model_convert_from(mode & FMODELS)) { 3064 case DDI_MODEL_ILP32: { 3065 struct fcp32_ioctl f32_ioctl; 3066 3067 f32_ioctl.fp_minor = fioctl.fp_minor; 3068 f32_ioctl.listlen = fioctl.listlen; 3069 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3070 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3071 sizeof (struct fcp32_ioctl), mode)) { 3072 return (EFAULT); 3073 } 3074 break; 3075 } 3076 case DDI_MODEL_NONE: 3077 if (ddi_copyout((void *)&fioctl, (void *)data, 3078 sizeof (struct fcp_ioctl), mode)) { 3079 return (EFAULT); 3080 } 3081 break; 3082 } 3083 #else /* _MULTI_DATAMODEL */ 3084 3085 if (ddi_copyout((void *)&fioctl, (void *)data, 3086 sizeof (struct fcp_ioctl), mode)) { 3087 return (EFAULT); 3088 } 3089 #endif /* _MULTI_DATAMODEL */ 3090 3091 return (0); 3092 } 3093 3094 /* 3095 * This function copies the fcp_ioctl structure passed in from user land 3096 * into kernel land. Handles 32 bit applications. 3097 */ 3098 /*ARGSUSED*/ 3099 static int 3100 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3101 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3102 { 3103 struct fcp_port *t_pptr; 3104 3105 #ifdef _MULTI_DATAMODEL 3106 switch (ddi_model_convert_from(mode & FMODELS)) { 3107 case DDI_MODEL_ILP32: { 3108 struct fcp32_ioctl f32_ioctl; 3109 3110 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3111 sizeof (struct fcp32_ioctl), mode)) { 3112 return (EFAULT); 3113 } 3114 fioctl->fp_minor = f32_ioctl.fp_minor; 3115 fioctl->listlen = f32_ioctl.listlen; 3116 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3117 break; 3118 } 3119 case DDI_MODEL_NONE: 3120 if (ddi_copyin((void *)data, (void *)fioctl, 3121 sizeof (struct fcp_ioctl), mode)) { 3122 return (EFAULT); 3123 } 3124 break; 3125 } 3126 3127 #else /* _MULTI_DATAMODEL */ 3128 if (ddi_copyin((void *)data, (void *)fioctl, 3129 sizeof (struct fcp_ioctl), mode)) { 3130 return (EFAULT); 3131 } 3132 #endif /* _MULTI_DATAMODEL */ 3133 3134 /* 3135 * Right now we can assume that the minor number matches with 3136 * this instance of fp. If this changes we will need to 3137 * revisit this logic. 3138 */ 3139 mutex_enter(&fcp_global_mutex); 3140 t_pptr = fcp_port_head; 3141 while (t_pptr) { 3142 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3143 break; 3144 } else { 3145 t_pptr = t_pptr->port_next; 3146 } 3147 } 3148 *pptr = t_pptr; 3149 mutex_exit(&fcp_global_mutex); 3150 if (t_pptr == NULL) { 3151 return (ENXIO); 3152 } 3153 3154 return (0); 3155 } 3156 3157 /* 3158 * Function: fcp_port_create_tgt 3159 * 3160 * Description: As the name suggest this function creates the target context 3161 * specified by the the WWN provided by the caller. If the 3162 * creation goes well and the target is known by fp/fctl a PLOGI 3163 * followed by a PRLI are issued. 3164 * 3165 * Argument: pptr fcp port structure 3166 * pwwn WWN of the target 3167 * ret_val Address of the return code. It could be: 3168 * EIO, ENOMEM or 0. 3169 * fc_status PLOGI or PRLI status completion 3170 * fc_pkt_state PLOGI or PRLI state completion 3171 * fc_pkt_reason PLOGI or PRLI reason completion 3172 * fc_pkt_action PLOGI or PRLI action completion 3173 * 3174 * Return Value: NULL if it failed 3175 * Target structure address if it succeeds 3176 */ 3177 static struct fcp_tgt * 3178 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3179 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3180 { 3181 struct fcp_tgt *ptgt = NULL; 3182 fc_portmap_t devlist; 3183 int lcount; 3184 int error; 3185 3186 *ret_val = 0; 3187 3188 /* 3189 * Check FC port device & get port map 3190 */ 3191 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3192 &error, 1) == NULL) { 3193 *ret_val = EIO; 3194 } else { 3195 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3196 &devlist) != FC_SUCCESS) { 3197 *ret_val = EIO; 3198 } 3199 } 3200 3201 /* Set port map flags */ 3202 devlist.map_type = PORT_DEVICE_USER_CREATE; 3203 3204 /* Allocate target */ 3205 if (*ret_val == 0) { 3206 lcount = pptr->port_link_cnt; 3207 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3208 if (ptgt == NULL) { 3209 fcp_log(CE_WARN, pptr->port_dip, 3210 "!FC target allocation failed"); 3211 *ret_val = ENOMEM; 3212 } else { 3213 /* Setup target */ 3214 mutex_enter(&ptgt->tgt_mutex); 3215 3216 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3217 ptgt->tgt_tmp_cnt = 1; 3218 ptgt->tgt_d_id = devlist.map_did.port_id; 3219 ptgt->tgt_hard_addr = 3220 devlist.map_hard_addr.hard_addr; 3221 ptgt->tgt_pd_handle = devlist.map_pd; 3222 ptgt->tgt_fca_dev = NULL; 3223 3224 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3225 FC_WWN_SIZE); 3226 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3227 FC_WWN_SIZE); 3228 3229 mutex_exit(&ptgt->tgt_mutex); 3230 } 3231 } 3232 3233 /* Release global mutex for PLOGI and PRLI */ 3234 mutex_exit(&fcp_global_mutex); 3235 3236 /* Send PLOGI (If necessary) */ 3237 if (*ret_val == 0) { 3238 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3239 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3240 } 3241 3242 /* Send PRLI (If necessary) */ 3243 if (*ret_val == 0) { 3244 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3245 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3246 } 3247 3248 mutex_enter(&fcp_global_mutex); 3249 3250 return (ptgt); 3251 } 3252 3253 /* 3254 * Function: fcp_tgt_send_plogi 3255 * 3256 * Description: This function sends a PLOGI to the target specified by the 3257 * caller and waits till it completes. 3258 * 3259 * Argument: ptgt Target to send the plogi to. 3260 * fc_status Status returned by fp/fctl in the PLOGI request. 3261 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3262 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3263 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3264 * 3265 * Return Value: 0 3266 * ENOMEM 3267 * EIO 3268 * 3269 * Context: User context. 3270 */ 3271 static int 3272 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3273 int *fc_pkt_reason, int *fc_pkt_action) 3274 { 3275 struct fcp_port *pptr; 3276 struct fcp_ipkt *icmd; 3277 struct fc_packet *fpkt; 3278 fc_frame_hdr_t *hp; 3279 struct la_els_logi logi; 3280 int tcount; 3281 int lcount; 3282 int ret, login_retval = ~FC_SUCCESS; 3283 3284 ret = 0; 3285 3286 pptr = ptgt->tgt_port; 3287 3288 lcount = pptr->port_link_cnt; 3289 tcount = ptgt->tgt_change_cnt; 3290 3291 /* Alloc internal packet */ 3292 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3293 sizeof (la_els_logi_t), 0, 3294 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3295 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3296 3297 if (icmd == NULL) { 3298 ret = ENOMEM; 3299 } else { 3300 /* 3301 * Setup internal packet as sema sync 3302 */ 3303 fcp_ipkt_sema_init(icmd); 3304 3305 /* 3306 * Setup internal packet (icmd) 3307 */ 3308 icmd->ipkt_lun = NULL; 3309 icmd->ipkt_restart = 0; 3310 icmd->ipkt_retries = 0; 3311 icmd->ipkt_opcode = LA_ELS_PLOGI; 3312 3313 /* 3314 * Setup fc_packet 3315 */ 3316 fpkt = icmd->ipkt_fpkt; 3317 3318 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3319 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3320 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3321 3322 /* 3323 * Setup FC frame header 3324 */ 3325 hp = &fpkt->pkt_cmd_fhdr; 3326 3327 hp->s_id = pptr->port_id; /* source ID */ 3328 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3329 hp->r_ctl = R_CTL_ELS_REQ; 3330 hp->type = FC_TYPE_EXTENDED_LS; 3331 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3332 hp->seq_id = 0; 3333 hp->rsvd = 0; 3334 hp->df_ctl = 0; 3335 hp->seq_cnt = 0; 3336 hp->ox_id = 0xffff; /* i.e. none */ 3337 hp->rx_id = 0xffff; /* i.e. none */ 3338 hp->ro = 0; 3339 3340 /* 3341 * Setup PLOGI 3342 */ 3343 bzero(&logi, sizeof (struct la_els_logi)); 3344 logi.ls_code.ls_code = LA_ELS_PLOGI; 3345 3346 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3347 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3348 3349 /* 3350 * Send PLOGI 3351 */ 3352 *fc_status = login_retval = 3353 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3354 if (*fc_status != FC_SUCCESS) { 3355 ret = EIO; 3356 } 3357 } 3358 3359 /* 3360 * Wait for completion 3361 */ 3362 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3363 ret = fcp_ipkt_sema_wait(icmd); 3364 3365 *fc_pkt_state = fpkt->pkt_state; 3366 *fc_pkt_reason = fpkt->pkt_reason; 3367 *fc_pkt_action = fpkt->pkt_action; 3368 } 3369 3370 /* 3371 * Cleanup transport data structures if icmd was alloc-ed AND if there 3372 * is going to be no callback (i.e if fc_ulp_login() failed). 3373 * Otherwise, cleanup happens in callback routine. 3374 */ 3375 if (icmd != NULL) { 3376 fcp_ipkt_sema_cleanup(icmd); 3377 } 3378 3379 return (ret); 3380 } 3381 3382 /* 3383 * Function: fcp_tgt_send_prli 3384 * 3385 * Description: Does nothing as of today. 3386 * 3387 * Argument: ptgt Target to send the prli to. 3388 * fc_status Status returned by fp/fctl in the PRLI request. 3389 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3390 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3391 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3392 * 3393 * Return Value: 0 3394 */ 3395 /*ARGSUSED*/ 3396 static int 3397 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3398 int *fc_pkt_reason, int *fc_pkt_action) 3399 { 3400 return (0); 3401 } 3402 3403 /* 3404 * Function: fcp_ipkt_sema_init 3405 * 3406 * Description: Initializes the semaphore contained in the internal packet. 3407 * 3408 * Argument: icmd Internal packet the semaphore of which must be 3409 * initialized. 3410 * 3411 * Return Value: None 3412 * 3413 * Context: User context only. 3414 */ 3415 static void 3416 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3417 { 3418 struct fc_packet *fpkt; 3419 3420 fpkt = icmd->ipkt_fpkt; 3421 3422 /* Create semaphore for sync */ 3423 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3424 3425 /* Setup the completion callback */ 3426 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3427 } 3428 3429 /* 3430 * Function: fcp_ipkt_sema_wait 3431 * 3432 * Description: Wait on the semaphore embedded in the internal packet. The 3433 * semaphore is released in the callback. 3434 * 3435 * Argument: icmd Internal packet to wait on for completion. 3436 * 3437 * Return Value: 0 3438 * EIO 3439 * EBUSY 3440 * EAGAIN 3441 * 3442 * Context: User context only. 3443 * 3444 * This function does a conversion between the field pkt_state of the fc_packet 3445 * embedded in the internal packet (icmd) and the code it returns. 3446 */ 3447 static int 3448 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3449 { 3450 struct fc_packet *fpkt; 3451 int ret; 3452 3453 ret = EIO; 3454 fpkt = icmd->ipkt_fpkt; 3455 3456 /* 3457 * Wait on semaphore 3458 */ 3459 sema_p(&(icmd->ipkt_sema)); 3460 3461 /* 3462 * Check the status of the FC packet 3463 */ 3464 switch (fpkt->pkt_state) { 3465 case FC_PKT_SUCCESS: 3466 ret = 0; 3467 break; 3468 case FC_PKT_LOCAL_RJT: 3469 switch (fpkt->pkt_reason) { 3470 case FC_REASON_SEQ_TIMEOUT: 3471 case FC_REASON_RX_BUF_TIMEOUT: 3472 ret = EAGAIN; 3473 break; 3474 case FC_REASON_PKT_BUSY: 3475 ret = EBUSY; 3476 break; 3477 } 3478 break; 3479 case FC_PKT_TIMEOUT: 3480 ret = EAGAIN; 3481 break; 3482 case FC_PKT_LOCAL_BSY: 3483 case FC_PKT_TRAN_BSY: 3484 case FC_PKT_NPORT_BSY: 3485 case FC_PKT_FABRIC_BSY: 3486 ret = EBUSY; 3487 break; 3488 case FC_PKT_LS_RJT: 3489 case FC_PKT_BA_RJT: 3490 switch (fpkt->pkt_reason) { 3491 case FC_REASON_LOGICAL_BSY: 3492 ret = EBUSY; 3493 break; 3494 } 3495 break; 3496 case FC_PKT_FS_RJT: 3497 switch (fpkt->pkt_reason) { 3498 case FC_REASON_FS_LOGICAL_BUSY: 3499 ret = EBUSY; 3500 break; 3501 } 3502 break; 3503 } 3504 3505 return (ret); 3506 } 3507 3508 /* 3509 * Function: fcp_ipkt_sema_callback 3510 * 3511 * Description: Registered as the completion callback function for the FC 3512 * transport when the ipkt semaphore is used for sync. This will 3513 * cleanup the used data structures, if necessary and wake up 3514 * the user thread to complete the transaction. 3515 * 3516 * Argument: fpkt FC packet (points to the icmd) 3517 * 3518 * Return Value: None 3519 * 3520 * Context: User context only 3521 */ 3522 static void 3523 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3524 { 3525 struct fcp_ipkt *icmd; 3526 3527 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3528 3529 /* 3530 * Wake up user thread 3531 */ 3532 sema_v(&(icmd->ipkt_sema)); 3533 } 3534 3535 /* 3536 * Function: fcp_ipkt_sema_cleanup 3537 * 3538 * Description: Called to cleanup (if necessary) the data structures used 3539 * when ipkt sema is used for sync. This function will detect 3540 * whether the caller is the last thread (via counter) and 3541 * cleanup only if necessary. 3542 * 3543 * Argument: icmd Internal command packet 3544 * 3545 * Return Value: None 3546 * 3547 * Context: User context only 3548 */ 3549 static void 3550 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3551 { 3552 struct fcp_tgt *ptgt; 3553 struct fcp_port *pptr; 3554 3555 ptgt = icmd->ipkt_tgt; 3556 pptr = icmd->ipkt_port; 3557 3558 /* 3559 * Acquire data structure 3560 */ 3561 mutex_enter(&ptgt->tgt_mutex); 3562 3563 /* 3564 * Destroy semaphore 3565 */ 3566 sema_destroy(&(icmd->ipkt_sema)); 3567 3568 /* 3569 * Cleanup internal packet 3570 */ 3571 mutex_exit(&ptgt->tgt_mutex); 3572 fcp_icmd_free(pptr, icmd); 3573 } 3574 3575 /* 3576 * Function: fcp_port_attach 3577 * 3578 * Description: Called by the transport framework to resume, suspend or 3579 * attach a new port. 3580 * 3581 * Argument: ulph Port handle 3582 * *pinfo Port information 3583 * cmd Command 3584 * s_id Port ID 3585 * 3586 * Return Value: FC_FAILURE or FC_SUCCESS 3587 */ 3588 /*ARGSUSED*/ 3589 static int 3590 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3591 fc_attach_cmd_t cmd, uint32_t s_id) 3592 { 3593 int instance; 3594 int res = FC_FAILURE; /* default result */ 3595 3596 ASSERT(pinfo != NULL); 3597 3598 instance = ddi_get_instance(pinfo->port_dip); 3599 3600 switch (cmd) { 3601 case FC_CMD_ATTACH: 3602 /* 3603 * this port instance attaching for the first time (or after 3604 * being detached before) 3605 */ 3606 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3607 instance) == DDI_SUCCESS) { 3608 res = FC_SUCCESS; 3609 } else { 3610 ASSERT(ddi_get_soft_state(fcp_softstate, 3611 instance) == NULL); 3612 } 3613 break; 3614 3615 case FC_CMD_RESUME: 3616 case FC_CMD_POWER_UP: 3617 /* 3618 * this port instance was attached and the suspended and 3619 * will now be resumed 3620 */ 3621 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3622 instance) == DDI_SUCCESS) { 3623 res = FC_SUCCESS; 3624 } 3625 break; 3626 3627 default: 3628 /* shouldn't happen */ 3629 FCP_TRACE(fcp_logq, "fcp", 3630 fcp_trace, FCP_BUF_LEVEL_2, 0, 3631 "port_attach: unknown cmdcommand: %d", cmd); 3632 break; 3633 } 3634 3635 /* return result */ 3636 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3637 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3638 3639 return (res); 3640 } 3641 3642 3643 /* 3644 * detach or suspend this port instance 3645 * 3646 * acquires and releases the global mutex 3647 * 3648 * acquires and releases the mutex for this port 3649 * 3650 * acquires and releases the hotplug mutex for this port 3651 */ 3652 /*ARGSUSED*/ 3653 static int 3654 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3655 fc_detach_cmd_t cmd) 3656 { 3657 int flag; 3658 int instance; 3659 struct fcp_port *pptr; 3660 3661 instance = ddi_get_instance(info->port_dip); 3662 pptr = ddi_get_soft_state(fcp_softstate, instance); 3663 3664 switch (cmd) { 3665 case FC_CMD_SUSPEND: 3666 FCP_DTRACE(fcp_logq, "fcp", 3667 fcp_trace, FCP_BUF_LEVEL_8, 0, 3668 "port suspend called for port %d", instance); 3669 flag = FCP_STATE_SUSPENDED; 3670 break; 3671 3672 case FC_CMD_POWER_DOWN: 3673 FCP_DTRACE(fcp_logq, "fcp", 3674 fcp_trace, FCP_BUF_LEVEL_8, 0, 3675 "port power down called for port %d", instance); 3676 flag = FCP_STATE_POWER_DOWN; 3677 break; 3678 3679 case FC_CMD_DETACH: 3680 FCP_DTRACE(fcp_logq, "fcp", 3681 fcp_trace, FCP_BUF_LEVEL_8, 0, 3682 "port detach called for port %d", instance); 3683 flag = FCP_STATE_DETACHING; 3684 break; 3685 3686 default: 3687 /* shouldn't happen */ 3688 return (FC_FAILURE); 3689 } 3690 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3691 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3692 3693 return (fcp_handle_port_detach(pptr, flag, instance)); 3694 } 3695 3696 3697 /* 3698 * called for ioctls on the transport's devctl interface, and the transport 3699 * has passed it to us 3700 * 3701 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3702 * 3703 * return FC_SUCCESS if we decide to claim the ioctl, 3704 * else return FC_UNCLAIMED 3705 * 3706 * *rval is set iff we decide to claim the ioctl 3707 */ 3708 /*ARGSUSED*/ 3709 static int 3710 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3711 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3712 { 3713 int retval = FC_UNCLAIMED; /* return value */ 3714 struct fcp_port *pptr = NULL; /* our soft state */ 3715 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3716 dev_info_t *cdip; 3717 mdi_pathinfo_t *pip = NULL; 3718 char *ndi_nm; /* NDI name */ 3719 char *ndi_addr; /* NDI addr */ 3720 int is_mpxio, circ; 3721 int devi_entered = 0; 3722 clock_t end_time; 3723 3724 ASSERT(rval != NULL); 3725 3726 FCP_DTRACE(fcp_logq, "fcp", 3727 fcp_trace, FCP_BUF_LEVEL_8, 0, 3728 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3729 3730 /* if already claimed then forget it */ 3731 if (claimed) { 3732 /* 3733 * for now, if this ioctl has already been claimed, then 3734 * we just ignore it 3735 */ 3736 return (retval); 3737 } 3738 3739 /* get our port info */ 3740 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3741 fcp_log(CE_WARN, NULL, 3742 "!fcp:Invalid port handle handle in ioctl"); 3743 *rval = ENXIO; 3744 return (retval); 3745 } 3746 is_mpxio = pptr->port_mpxio; 3747 3748 switch (cmd) { 3749 case DEVCTL_BUS_GETSTATE: 3750 case DEVCTL_BUS_QUIESCE: 3751 case DEVCTL_BUS_UNQUIESCE: 3752 case DEVCTL_BUS_RESET: 3753 case DEVCTL_BUS_RESETALL: 3754 3755 case DEVCTL_BUS_DEV_CREATE: 3756 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3757 return (retval); 3758 } 3759 break; 3760 3761 case DEVCTL_DEVICE_GETSTATE: 3762 case DEVCTL_DEVICE_OFFLINE: 3763 case DEVCTL_DEVICE_ONLINE: 3764 case DEVCTL_DEVICE_REMOVE: 3765 case DEVCTL_DEVICE_RESET: 3766 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3767 return (retval); 3768 } 3769 3770 ASSERT(dcp != NULL); 3771 3772 /* ensure we have a name and address */ 3773 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3774 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3775 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3776 fcp_trace, FCP_BUF_LEVEL_2, 0, 3777 "ioctl: can't get name (%s) or addr (%s)", 3778 ndi_nm ? ndi_nm : "<null ptr>", 3779 ndi_addr ? ndi_addr : "<null ptr>"); 3780 ndi_dc_freehdl(dcp); 3781 return (retval); 3782 } 3783 3784 3785 /* get our child's DIP */ 3786 ASSERT(pptr != NULL); 3787 if (is_mpxio) { 3788 mdi_devi_enter(pptr->port_dip, &circ); 3789 } else { 3790 ndi_devi_enter(pptr->port_dip, &circ); 3791 } 3792 devi_entered = 1; 3793 3794 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3795 ndi_addr)) == NULL) { 3796 /* Look for virtually enumerated devices. */ 3797 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3798 if (pip == NULL || 3799 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3800 *rval = ENXIO; 3801 goto out; 3802 } 3803 } 3804 break; 3805 3806 default: 3807 *rval = ENOTTY; 3808 return (retval); 3809 } 3810 3811 /* this ioctl is ours -- process it */ 3812 3813 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3814 3815 /* we assume it will be a success; else we'll set error value */ 3816 *rval = 0; 3817 3818 3819 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3820 fcp_trace, FCP_BUF_LEVEL_8, 0, 3821 "ioctl: claiming this one"); 3822 3823 /* handle ioctls now */ 3824 switch (cmd) { 3825 case DEVCTL_DEVICE_GETSTATE: 3826 ASSERT(cdip != NULL); 3827 ASSERT(dcp != NULL); 3828 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3829 *rval = EFAULT; 3830 } 3831 break; 3832 3833 case DEVCTL_DEVICE_REMOVE: 3834 case DEVCTL_DEVICE_OFFLINE: { 3835 int flag = 0; 3836 int lcount; 3837 int tcount; 3838 struct fcp_pkt *head = NULL; 3839 struct fcp_lun *plun; 3840 child_info_t *cip = CIP(cdip); 3841 int all = 1; 3842 struct fcp_lun *tplun; 3843 struct fcp_tgt *ptgt; 3844 3845 ASSERT(pptr != NULL); 3846 ASSERT(cdip != NULL); 3847 3848 mutex_enter(&pptr->port_mutex); 3849 if (pip != NULL) { 3850 cip = CIP(pip); 3851 } 3852 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3853 mutex_exit(&pptr->port_mutex); 3854 *rval = ENXIO; 3855 break; 3856 } 3857 3858 head = fcp_scan_commands(plun); 3859 if (head != NULL) { 3860 fcp_abort_commands(head, LUN_PORT); 3861 } 3862 lcount = pptr->port_link_cnt; 3863 tcount = plun->lun_tgt->tgt_change_cnt; 3864 mutex_exit(&pptr->port_mutex); 3865 3866 if (cmd == DEVCTL_DEVICE_REMOVE) { 3867 flag = NDI_DEVI_REMOVE; 3868 } 3869 3870 if (is_mpxio) { 3871 mdi_devi_exit(pptr->port_dip, circ); 3872 } else { 3873 ndi_devi_exit(pptr->port_dip, circ); 3874 } 3875 devi_entered = 0; 3876 3877 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3878 FCP_OFFLINE, lcount, tcount, flag); 3879 3880 if (*rval != NDI_SUCCESS) { 3881 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3882 break; 3883 } 3884 3885 fcp_update_offline_flags(plun); 3886 3887 ptgt = plun->lun_tgt; 3888 mutex_enter(&ptgt->tgt_mutex); 3889 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3890 tplun->lun_next) { 3891 mutex_enter(&tplun->lun_mutex); 3892 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3893 all = 0; 3894 } 3895 mutex_exit(&tplun->lun_mutex); 3896 } 3897 3898 if (all) { 3899 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3900 /* 3901 * The user is unconfiguring/offlining the device. 3902 * If fabric and the auto configuration is set 3903 * then make sure the user is the only one who 3904 * can reconfigure the device. 3905 */ 3906 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3907 fcp_enable_auto_configuration) { 3908 ptgt->tgt_manual_config_only = 1; 3909 } 3910 } 3911 mutex_exit(&ptgt->tgt_mutex); 3912 break; 3913 } 3914 3915 case DEVCTL_DEVICE_ONLINE: { 3916 int lcount; 3917 int tcount; 3918 struct fcp_lun *plun; 3919 child_info_t *cip = CIP(cdip); 3920 3921 ASSERT(cdip != NULL); 3922 ASSERT(pptr != NULL); 3923 3924 mutex_enter(&pptr->port_mutex); 3925 if (pip != NULL) { 3926 cip = CIP(pip); 3927 } 3928 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3929 mutex_exit(&pptr->port_mutex); 3930 *rval = ENXIO; 3931 break; 3932 } 3933 lcount = pptr->port_link_cnt; 3934 tcount = plun->lun_tgt->tgt_change_cnt; 3935 mutex_exit(&pptr->port_mutex); 3936 3937 /* 3938 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3939 * to allow the device attach to occur when the device is 3940 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3941 * from the scsi_probe()). 3942 */ 3943 mutex_enter(&LUN_TGT->tgt_mutex); 3944 plun->lun_state |= FCP_LUN_ONLINING; 3945 mutex_exit(&LUN_TGT->tgt_mutex); 3946 3947 if (is_mpxio) { 3948 mdi_devi_exit(pptr->port_dip, circ); 3949 } else { 3950 ndi_devi_exit(pptr->port_dip, circ); 3951 } 3952 devi_entered = 0; 3953 3954 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3955 FCP_ONLINE, lcount, tcount, 0); 3956 3957 if (*rval != NDI_SUCCESS) { 3958 /* Reset the FCP_LUN_ONLINING bit */ 3959 mutex_enter(&LUN_TGT->tgt_mutex); 3960 plun->lun_state &= ~FCP_LUN_ONLINING; 3961 mutex_exit(&LUN_TGT->tgt_mutex); 3962 *rval = EIO; 3963 break; 3964 } 3965 mutex_enter(&LUN_TGT->tgt_mutex); 3966 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3967 FCP_LUN_ONLINING); 3968 mutex_exit(&LUN_TGT->tgt_mutex); 3969 break; 3970 } 3971 3972 case DEVCTL_BUS_DEV_CREATE: { 3973 uchar_t *bytes = NULL; 3974 uint_t nbytes; 3975 struct fcp_tgt *ptgt = NULL; 3976 struct fcp_lun *plun = NULL; 3977 dev_info_t *useless_dip = NULL; 3978 3979 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3980 DEVCTL_CONSTRUCT, &useless_dip); 3981 if (*rval != 0 || useless_dip == NULL) { 3982 break; 3983 } 3984 3985 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3986 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3987 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3988 *rval = EINVAL; 3989 (void) ndi_devi_free(useless_dip); 3990 if (bytes != NULL) { 3991 ddi_prop_free(bytes); 3992 } 3993 break; 3994 } 3995 3996 *rval = fcp_create_on_demand(pptr, bytes); 3997 if (*rval == 0) { 3998 mutex_enter(&pptr->port_mutex); 3999 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 4000 if (ptgt) { 4001 /* 4002 * We now have a pointer to the target that 4003 * was created. Lets point to the first LUN on 4004 * this new target. 4005 */ 4006 mutex_enter(&ptgt->tgt_mutex); 4007 4008 plun = ptgt->tgt_lun; 4009 /* 4010 * There may be stale/offline LUN entries on 4011 * this list (this is by design) and so we have 4012 * to make sure we point to the first online 4013 * LUN 4014 */ 4015 while (plun && 4016 plun->lun_state & FCP_LUN_OFFLINE) { 4017 plun = plun->lun_next; 4018 } 4019 4020 mutex_exit(&ptgt->tgt_mutex); 4021 } 4022 mutex_exit(&pptr->port_mutex); 4023 } 4024 4025 if (*rval == 0 && ptgt && plun) { 4026 mutex_enter(&plun->lun_mutex); 4027 /* 4028 * Allow up to fcp_lun_ready_retry seconds to 4029 * configure all the luns behind the target. 4030 * 4031 * The intent here is to allow targets with long 4032 * reboot/reset-recovery times to become available 4033 * while limiting the maximum wait time for an 4034 * unresponsive target. 4035 */ 4036 end_time = ddi_get_lbolt() + 4037 SEC_TO_TICK(fcp_lun_ready_retry); 4038 4039 while (ddi_get_lbolt() < end_time) { 4040 retval = FC_SUCCESS; 4041 4042 /* 4043 * The new ndi interfaces for on-demand creation 4044 * are inflexible, Do some more work to pass on 4045 * a path name of some LUN (design is broken !) 4046 */ 4047 if (plun->lun_cip) { 4048 if (plun->lun_mpxio == 0) { 4049 cdip = DIP(plun->lun_cip); 4050 } else { 4051 cdip = mdi_pi_get_client( 4052 PIP(plun->lun_cip)); 4053 } 4054 if (cdip == NULL) { 4055 *rval = ENXIO; 4056 break; 4057 } 4058 4059 if (!i_ddi_devi_attached(cdip)) { 4060 mutex_exit(&plun->lun_mutex); 4061 delay(drv_usectohz(1000000)); 4062 mutex_enter(&plun->lun_mutex); 4063 } else { 4064 /* 4065 * This Lun is ready, lets 4066 * check the next one. 4067 */ 4068 mutex_exit(&plun->lun_mutex); 4069 plun = plun->lun_next; 4070 while (plun && (plun->lun_state 4071 & FCP_LUN_OFFLINE)) { 4072 plun = plun->lun_next; 4073 } 4074 if (!plun) { 4075 break; 4076 } 4077 mutex_enter(&plun->lun_mutex); 4078 } 4079 } else { 4080 /* 4081 * lun_cip field for a valid lun 4082 * should never be NULL. Fail the 4083 * command. 4084 */ 4085 *rval = ENXIO; 4086 break; 4087 } 4088 } 4089 if (plun) { 4090 mutex_exit(&plun->lun_mutex); 4091 } else { 4092 char devnm[MAXNAMELEN]; 4093 int nmlen; 4094 4095 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4096 ddi_node_name(cdip), 4097 ddi_get_name_addr(cdip)); 4098 4099 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4100 0) { 4101 *rval = EFAULT; 4102 } 4103 } 4104 } else { 4105 int i; 4106 char buf[25]; 4107 4108 for (i = 0; i < FC_WWN_SIZE; i++) { 4109 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4110 } 4111 4112 fcp_log(CE_WARN, pptr->port_dip, 4113 "!Failed to create nodes for pwwn=%s; error=%x", 4114 buf, *rval); 4115 } 4116 4117 (void) ndi_devi_free(useless_dip); 4118 ddi_prop_free(bytes); 4119 break; 4120 } 4121 4122 case DEVCTL_DEVICE_RESET: { 4123 struct fcp_lun *plun; 4124 child_info_t *cip = CIP(cdip); 4125 4126 ASSERT(cdip != NULL); 4127 ASSERT(pptr != NULL); 4128 mutex_enter(&pptr->port_mutex); 4129 if (pip != NULL) { 4130 cip = CIP(pip); 4131 } 4132 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4133 mutex_exit(&pptr->port_mutex); 4134 *rval = ENXIO; 4135 break; 4136 } 4137 mutex_exit(&pptr->port_mutex); 4138 4139 mutex_enter(&plun->lun_tgt->tgt_mutex); 4140 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4141 mutex_exit(&plun->lun_tgt->tgt_mutex); 4142 4143 *rval = ENXIO; 4144 break; 4145 } 4146 4147 if (plun->lun_sd == NULL) { 4148 mutex_exit(&plun->lun_tgt->tgt_mutex); 4149 4150 *rval = ENXIO; 4151 break; 4152 } 4153 mutex_exit(&plun->lun_tgt->tgt_mutex); 4154 4155 /* 4156 * set up ap so that fcp_reset can figure out 4157 * which target to reset 4158 */ 4159 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4160 RESET_TARGET) == FALSE) { 4161 *rval = EIO; 4162 } 4163 break; 4164 } 4165 4166 case DEVCTL_BUS_GETSTATE: 4167 ASSERT(dcp != NULL); 4168 ASSERT(pptr != NULL); 4169 ASSERT(pptr->port_dip != NULL); 4170 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4171 NDI_SUCCESS) { 4172 *rval = EFAULT; 4173 } 4174 break; 4175 4176 case DEVCTL_BUS_QUIESCE: 4177 case DEVCTL_BUS_UNQUIESCE: 4178 *rval = ENOTSUP; 4179 break; 4180 4181 case DEVCTL_BUS_RESET: 4182 case DEVCTL_BUS_RESETALL: 4183 ASSERT(pptr != NULL); 4184 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4185 break; 4186 4187 default: 4188 ASSERT(dcp != NULL); 4189 *rval = ENOTTY; 4190 break; 4191 } 4192 4193 /* all done -- clean up and return */ 4194 out: if (devi_entered) { 4195 if (is_mpxio) { 4196 mdi_devi_exit(pptr->port_dip, circ); 4197 } else { 4198 ndi_devi_exit(pptr->port_dip, circ); 4199 } 4200 } 4201 4202 if (dcp != NULL) { 4203 ndi_dc_freehdl(dcp); 4204 } 4205 4206 return (retval); 4207 } 4208 4209 4210 /*ARGSUSED*/ 4211 static int 4212 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4213 uint32_t claimed) 4214 { 4215 uchar_t r_ctl; 4216 uchar_t ls_code; 4217 struct fcp_port *pptr; 4218 4219 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4220 return (FC_UNCLAIMED); 4221 } 4222 4223 mutex_enter(&pptr->port_mutex); 4224 if (pptr->port_state & (FCP_STATE_DETACHING | 4225 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4226 mutex_exit(&pptr->port_mutex); 4227 return (FC_UNCLAIMED); 4228 } 4229 mutex_exit(&pptr->port_mutex); 4230 4231 r_ctl = buf->ub_frame.r_ctl; 4232 4233 switch (r_ctl & R_CTL_ROUTING) { 4234 case R_CTL_EXTENDED_SVC: 4235 if (r_ctl == R_CTL_ELS_REQ) { 4236 ls_code = buf->ub_buffer[0]; 4237 4238 switch (ls_code) { 4239 case LA_ELS_PRLI: 4240 /* 4241 * We really don't care if something fails. 4242 * If the PRLI was not sent out, then the 4243 * other end will time it out. 4244 */ 4245 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4246 return (FC_SUCCESS); 4247 } 4248 return (FC_UNCLAIMED); 4249 /* NOTREACHED */ 4250 4251 default: 4252 break; 4253 } 4254 } 4255 /* FALLTHROUGH */ 4256 4257 default: 4258 return (FC_UNCLAIMED); 4259 } 4260 } 4261 4262 4263 /*ARGSUSED*/ 4264 static int 4265 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4266 uint32_t claimed) 4267 { 4268 return (FC_UNCLAIMED); 4269 } 4270 4271 /* 4272 * Function: fcp_statec_callback 4273 * 4274 * Description: The purpose of this function is to handle a port state change. 4275 * It is called from fp/fctl and, in a few instances, internally. 4276 * 4277 * Argument: ulph fp/fctl port handle 4278 * port_handle fcp_port structure 4279 * port_state Physical state of the port 4280 * port_top Topology 4281 * *devlist Pointer to the first entry of a table 4282 * containing the remote ports that can be 4283 * reached. 4284 * dev_cnt Number of entries pointed by devlist. 4285 * port_sid Port ID of the local port. 4286 * 4287 * Return Value: None 4288 */ 4289 /*ARGSUSED*/ 4290 static void 4291 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4292 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4293 uint32_t dev_cnt, uint32_t port_sid) 4294 { 4295 uint32_t link_count; 4296 int map_len = 0; 4297 struct fcp_port *pptr; 4298 fcp_map_tag_t *map_tag = NULL; 4299 4300 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4301 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4302 return; /* nothing to work with! */ 4303 } 4304 4305 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4306 fcp_trace, FCP_BUF_LEVEL_2, 0, 4307 "fcp_statec_callback: port state/dev_cnt/top =" 4308 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4309 dev_cnt, port_top); 4310 4311 mutex_enter(&pptr->port_mutex); 4312 4313 /* 4314 * If a thread is in detach, don't do anything. 4315 */ 4316 if (pptr->port_state & (FCP_STATE_DETACHING | 4317 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4318 mutex_exit(&pptr->port_mutex); 4319 return; 4320 } 4321 4322 /* 4323 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4324 * init_pkt is called, it knows whether or not the target's status 4325 * (or pd) might be changing. 4326 */ 4327 4328 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4329 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4330 } 4331 4332 /* 4333 * the transport doesn't allocate or probe unless being 4334 * asked to by either the applications or ULPs 4335 * 4336 * in cases where the port is OFFLINE at the time of port 4337 * attach callback and the link comes ONLINE later, for 4338 * easier automatic node creation (i.e. without you having to 4339 * go out and run the utility to perform LOGINs) the 4340 * following conditional is helpful 4341 */ 4342 pptr->port_phys_state = port_state; 4343 4344 if (dev_cnt) { 4345 mutex_exit(&pptr->port_mutex); 4346 4347 map_len = sizeof (*map_tag) * dev_cnt; 4348 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4349 if (map_tag == NULL) { 4350 fcp_log(CE_WARN, pptr->port_dip, 4351 "!fcp%d: failed to allocate for map tags; " 4352 " state change will not be processed", 4353 pptr->port_instance); 4354 4355 mutex_enter(&pptr->port_mutex); 4356 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4357 mutex_exit(&pptr->port_mutex); 4358 4359 return; 4360 } 4361 4362 mutex_enter(&pptr->port_mutex); 4363 } 4364 4365 if (pptr->port_id != port_sid) { 4366 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4367 fcp_trace, FCP_BUF_LEVEL_3, 0, 4368 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4369 port_sid); 4370 /* 4371 * The local port changed ID. It is the first time a port ID 4372 * is assigned or something drastic happened. We might have 4373 * been unplugged and replugged on another loop or fabric port 4374 * or somebody grabbed the AL_PA we had or somebody rezoned 4375 * the fabric we were plugged into. 4376 */ 4377 pptr->port_id = port_sid; 4378 } 4379 4380 switch (FC_PORT_STATE_MASK(port_state)) { 4381 case FC_STATE_OFFLINE: 4382 case FC_STATE_RESET_REQUESTED: 4383 /* 4384 * link has gone from online to offline -- just update the 4385 * state of this port to BUSY and MARKed to go offline 4386 */ 4387 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4388 fcp_trace, FCP_BUF_LEVEL_3, 0, 4389 "link went offline"); 4390 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4391 /* 4392 * We were offline a while ago and this one 4393 * seems to indicate that the loop has gone 4394 * dead forever. 4395 */ 4396 pptr->port_tmp_cnt += dev_cnt; 4397 pptr->port_state &= ~FCP_STATE_OFFLINE; 4398 pptr->port_state |= FCP_STATE_INIT; 4399 link_count = pptr->port_link_cnt; 4400 fcp_handle_devices(pptr, devlist, dev_cnt, 4401 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4402 } else { 4403 pptr->port_link_cnt++; 4404 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4405 fcp_update_state(pptr, (FCP_LUN_BUSY | 4406 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4407 if (pptr->port_mpxio) { 4408 fcp_update_mpxio_path_verifybusy(pptr); 4409 } 4410 pptr->port_state |= FCP_STATE_OFFLINE; 4411 pptr->port_state &= 4412 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4413 pptr->port_tmp_cnt = 0; 4414 } 4415 mutex_exit(&pptr->port_mutex); 4416 break; 4417 4418 case FC_STATE_ONLINE: 4419 case FC_STATE_LIP: 4420 case FC_STATE_LIP_LBIT_SET: 4421 /* 4422 * link has gone from offline to online 4423 */ 4424 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4425 fcp_trace, FCP_BUF_LEVEL_3, 0, 4426 "link went online"); 4427 4428 pptr->port_link_cnt++; 4429 4430 while (pptr->port_ipkt_cnt) { 4431 mutex_exit(&pptr->port_mutex); 4432 delay(drv_usectohz(1000000)); 4433 mutex_enter(&pptr->port_mutex); 4434 } 4435 4436 pptr->port_topology = port_top; 4437 4438 /* 4439 * The state of the targets and luns accessible through this 4440 * port is updated. 4441 */ 4442 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4443 FCP_CAUSE_LINK_CHANGE); 4444 4445 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4446 pptr->port_state |= FCP_STATE_ONLINING; 4447 pptr->port_tmp_cnt = dev_cnt; 4448 link_count = pptr->port_link_cnt; 4449 4450 pptr->port_deadline = fcp_watchdog_time + 4451 FCP_ICMD_DEADLINE; 4452 4453 if (!dev_cnt) { 4454 /* 4455 * We go directly to the online state if no remote 4456 * ports were discovered. 4457 */ 4458 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4459 fcp_trace, FCP_BUF_LEVEL_3, 0, 4460 "No remote ports discovered"); 4461 4462 pptr->port_state &= ~FCP_STATE_ONLINING; 4463 pptr->port_state |= FCP_STATE_ONLINE; 4464 } 4465 4466 switch (port_top) { 4467 case FC_TOP_FABRIC: 4468 case FC_TOP_PUBLIC_LOOP: 4469 case FC_TOP_PRIVATE_LOOP: 4470 case FC_TOP_PT_PT: 4471 4472 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4473 fcp_retry_ns_registry(pptr, port_sid); 4474 } 4475 4476 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4477 map_tag, FCP_CAUSE_LINK_CHANGE); 4478 break; 4479 4480 default: 4481 /* 4482 * We got here because we were provided with an unknown 4483 * topology. 4484 */ 4485 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4486 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4487 } 4488 4489 pptr->port_tmp_cnt -= dev_cnt; 4490 fcp_log(CE_WARN, pptr->port_dip, 4491 "!unknown/unsupported topology (0x%x)", port_top); 4492 break; 4493 } 4494 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4495 fcp_trace, FCP_BUF_LEVEL_3, 0, 4496 "Notify ssd of the reset to reinstate the reservations"); 4497 4498 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4499 &pptr->port_reset_notify_listf); 4500 4501 mutex_exit(&pptr->port_mutex); 4502 4503 break; 4504 4505 case FC_STATE_RESET: 4506 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4507 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4508 fcp_trace, FCP_BUF_LEVEL_3, 0, 4509 "RESET state, waiting for Offline/Online state_cb"); 4510 mutex_exit(&pptr->port_mutex); 4511 break; 4512 4513 case FC_STATE_DEVICE_CHANGE: 4514 /* 4515 * We come here when an application has requested 4516 * Dynamic node creation/deletion in Fabric connectivity. 4517 */ 4518 if (pptr->port_state & (FCP_STATE_OFFLINE | 4519 FCP_STATE_INIT)) { 4520 /* 4521 * This case can happen when the FCTL is in the 4522 * process of giving us on online and the host on 4523 * the other side issues a PLOGI/PLOGO. Ideally 4524 * the state changes should be serialized unless 4525 * they are opposite (online-offline). 4526 * The transport will give us a final state change 4527 * so we can ignore this for the time being. 4528 */ 4529 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4530 mutex_exit(&pptr->port_mutex); 4531 break; 4532 } 4533 4534 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4535 fcp_retry_ns_registry(pptr, port_sid); 4536 } 4537 4538 /* 4539 * Extend the deadline under steady state conditions 4540 * to provide more time for the device-change-commands 4541 */ 4542 if (!pptr->port_ipkt_cnt) { 4543 pptr->port_deadline = fcp_watchdog_time + 4544 FCP_ICMD_DEADLINE; 4545 } 4546 4547 /* 4548 * There is another race condition here, where if we were 4549 * in ONLINEING state and a devices in the map logs out, 4550 * fp will give another state change as DEVICE_CHANGE 4551 * and OLD. This will result in that target being offlined. 4552 * The pd_handle is freed. If from the first statec callback 4553 * we were going to fire a PLOGI/PRLI, the system will 4554 * panic in fc_ulp_transport with invalid pd_handle. 4555 * The fix is to check for the link_cnt before issuing 4556 * any command down. 4557 */ 4558 fcp_update_targets(pptr, devlist, dev_cnt, 4559 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4560 4561 link_count = pptr->port_link_cnt; 4562 4563 fcp_handle_devices(pptr, devlist, dev_cnt, 4564 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4565 4566 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4567 4568 mutex_exit(&pptr->port_mutex); 4569 break; 4570 4571 case FC_STATE_TARGET_PORT_RESET: 4572 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4573 fcp_retry_ns_registry(pptr, port_sid); 4574 } 4575 4576 /* Do nothing else */ 4577 mutex_exit(&pptr->port_mutex); 4578 break; 4579 4580 default: 4581 fcp_log(CE_WARN, pptr->port_dip, 4582 "!Invalid state change=0x%x", port_state); 4583 mutex_exit(&pptr->port_mutex); 4584 break; 4585 } 4586 4587 if (map_tag) { 4588 kmem_free(map_tag, map_len); 4589 } 4590 } 4591 4592 /* 4593 * Function: fcp_handle_devices 4594 * 4595 * Description: This function updates the devices currently known by 4596 * walking the list provided by the caller. The list passed 4597 * by the caller is supposed to be the list of reachable 4598 * devices. 4599 * 4600 * Argument: *pptr Fcp port structure. 4601 * *devlist Pointer to the first entry of a table 4602 * containing the remote ports that can be 4603 * reached. 4604 * dev_cnt Number of entries pointed by devlist. 4605 * link_cnt Link state count. 4606 * *map_tag Array of fcp_map_tag_t structures. 4607 * cause What caused this function to be called. 4608 * 4609 * Return Value: None 4610 * 4611 * Notes: The pptr->port_mutex must be held. 4612 */ 4613 static void 4614 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4615 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4616 { 4617 int i; 4618 int check_finish_init = 0; 4619 fc_portmap_t *map_entry; 4620 struct fcp_tgt *ptgt = NULL; 4621 4622 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4623 fcp_trace, FCP_BUF_LEVEL_3, 0, 4624 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4625 4626 if (dev_cnt) { 4627 ASSERT(map_tag != NULL); 4628 } 4629 4630 /* 4631 * The following code goes through the list of remote ports that are 4632 * accessible through this (pptr) local port (The list walked is the 4633 * one provided by the caller which is the list of the remote ports 4634 * currently reachable). It checks if any of them was already 4635 * known by looking for the corresponding target structure based on 4636 * the world wide name. If a target is part of the list it is tagged 4637 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4638 * 4639 * Old comment 4640 * ----------- 4641 * Before we drop port mutex; we MUST get the tags updated; This 4642 * two step process is somewhat slow, but more reliable. 4643 */ 4644 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4645 map_entry = &(devlist[i]); 4646 4647 /* 4648 * get ptr to this map entry in our port's 4649 * list (if any) 4650 */ 4651 ptgt = fcp_lookup_target(pptr, 4652 (uchar_t *)&(map_entry->map_pwwn)); 4653 4654 if (ptgt) { 4655 map_tag[i] = ptgt->tgt_change_cnt; 4656 if (cause == FCP_CAUSE_LINK_CHANGE) { 4657 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4658 } 4659 } 4660 } 4661 4662 /* 4663 * At this point we know which devices of the new list were already 4664 * known (The field tgt_aux_state of the target structure has been 4665 * set to FCP_TGT_TAGGED). 4666 * 4667 * The following code goes through the list of targets currently known 4668 * by the local port (the list is actually a hashing table). If a 4669 * target is found and is not tagged, it means the target cannot 4670 * be reached anymore through the local port (pptr). It is offlined. 4671 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4672 */ 4673 for (i = 0; i < FCP_NUM_HASH; i++) { 4674 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4675 ptgt = ptgt->tgt_next) { 4676 mutex_enter(&ptgt->tgt_mutex); 4677 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4678 (cause == FCP_CAUSE_LINK_CHANGE) && 4679 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4680 fcp_offline_target_now(pptr, ptgt, 4681 link_cnt, ptgt->tgt_change_cnt, 0); 4682 } 4683 mutex_exit(&ptgt->tgt_mutex); 4684 } 4685 } 4686 4687 /* 4688 * At this point, the devices that were known but cannot be reached 4689 * anymore, have most likely been offlined. 4690 * 4691 * The following section of code seems to go through the list of 4692 * remote ports that can now be reached. For every single one it 4693 * checks if it is already known or if it is a new port. 4694 */ 4695 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4696 4697 if (check_finish_init) { 4698 ASSERT(i > 0); 4699 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4700 map_tag[i - 1], cause); 4701 check_finish_init = 0; 4702 } 4703 4704 /* get a pointer to this map entry */ 4705 map_entry = &(devlist[i]); 4706 4707 /* 4708 * Check for the duplicate map entry flag. If we have marked 4709 * this entry as a duplicate we skip it since the correct 4710 * (perhaps even same) state change will be encountered 4711 * later in the list. 4712 */ 4713 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4714 continue; 4715 } 4716 4717 /* get ptr to this map entry in our port's list (if any) */ 4718 ptgt = fcp_lookup_target(pptr, 4719 (uchar_t *)&(map_entry->map_pwwn)); 4720 4721 if (ptgt) { 4722 /* 4723 * This device was already known. The field 4724 * tgt_aux_state is reset (was probably set to 4725 * FCP_TGT_TAGGED previously in this routine). 4726 */ 4727 ptgt->tgt_aux_state = 0; 4728 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4729 fcp_trace, FCP_BUF_LEVEL_3, 0, 4730 "handle_devices: map did/state/type/flags = " 4731 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4732 "tgt_state=%d", 4733 map_entry->map_did.port_id, map_entry->map_state, 4734 map_entry->map_type, map_entry->map_flags, 4735 ptgt->tgt_d_id, ptgt->tgt_state); 4736 } 4737 4738 if (map_entry->map_type == PORT_DEVICE_OLD || 4739 map_entry->map_type == PORT_DEVICE_NEW || 4740 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4741 map_entry->map_type == PORT_DEVICE_CHANGED) { 4742 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4743 fcp_trace, FCP_BUF_LEVEL_2, 0, 4744 "map_type=%x, did = %x", 4745 map_entry->map_type, 4746 map_entry->map_did.port_id); 4747 } 4748 4749 switch (map_entry->map_type) { 4750 case PORT_DEVICE_NOCHANGE: 4751 case PORT_DEVICE_USER_CREATE: 4752 case PORT_DEVICE_USER_LOGIN: 4753 case PORT_DEVICE_NEW: 4754 case PORT_DEVICE_REPORTLUN_CHANGED: 4755 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4756 4757 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4758 link_cnt, (ptgt) ? map_tag[i] : 0, 4759 cause) == TRUE) { 4760 4761 FCP_TGT_TRACE(ptgt, map_tag[i], 4762 FCP_TGT_TRACE_2); 4763 check_finish_init++; 4764 } 4765 break; 4766 4767 case PORT_DEVICE_OLD: 4768 if (ptgt != NULL) { 4769 FCP_TGT_TRACE(ptgt, map_tag[i], 4770 FCP_TGT_TRACE_3); 4771 4772 mutex_enter(&ptgt->tgt_mutex); 4773 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4774 /* 4775 * Must do an in-line wait for I/Os 4776 * to get drained 4777 */ 4778 mutex_exit(&ptgt->tgt_mutex); 4779 mutex_exit(&pptr->port_mutex); 4780 4781 mutex_enter(&ptgt->tgt_mutex); 4782 while (ptgt->tgt_ipkt_cnt || 4783 fcp_outstanding_lun_cmds(ptgt) 4784 == FC_SUCCESS) { 4785 mutex_exit(&ptgt->tgt_mutex); 4786 delay(drv_usectohz(1000000)); 4787 mutex_enter(&ptgt->tgt_mutex); 4788 } 4789 mutex_exit(&ptgt->tgt_mutex); 4790 4791 mutex_enter(&pptr->port_mutex); 4792 mutex_enter(&ptgt->tgt_mutex); 4793 4794 (void) fcp_offline_target(pptr, ptgt, 4795 link_cnt, map_tag[i], 0, 0); 4796 } 4797 mutex_exit(&ptgt->tgt_mutex); 4798 } 4799 check_finish_init++; 4800 break; 4801 4802 case PORT_DEVICE_USER_DELETE: 4803 case PORT_DEVICE_USER_LOGOUT: 4804 if (ptgt != NULL) { 4805 FCP_TGT_TRACE(ptgt, map_tag[i], 4806 FCP_TGT_TRACE_4); 4807 4808 mutex_enter(&ptgt->tgt_mutex); 4809 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4810 (void) fcp_offline_target(pptr, ptgt, 4811 link_cnt, map_tag[i], 1, 0); 4812 } 4813 mutex_exit(&ptgt->tgt_mutex); 4814 } 4815 check_finish_init++; 4816 break; 4817 4818 case PORT_DEVICE_CHANGED: 4819 if (ptgt != NULL) { 4820 FCP_TGT_TRACE(ptgt, map_tag[i], 4821 FCP_TGT_TRACE_5); 4822 4823 if (fcp_device_changed(pptr, ptgt, 4824 map_entry, link_cnt, map_tag[i], 4825 cause) == TRUE) { 4826 check_finish_init++; 4827 } 4828 } else { 4829 if (fcp_handle_mapflags(pptr, ptgt, 4830 map_entry, link_cnt, 0, cause) == TRUE) { 4831 check_finish_init++; 4832 } 4833 } 4834 break; 4835 4836 default: 4837 fcp_log(CE_WARN, pptr->port_dip, 4838 "!Invalid map_type=0x%x", map_entry->map_type); 4839 check_finish_init++; 4840 break; 4841 } 4842 } 4843 4844 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4845 ASSERT(i > 0); 4846 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4847 map_tag[i-1], cause); 4848 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4849 fcp_offline_all(pptr, link_cnt, cause); 4850 } 4851 } 4852 4853 static int 4854 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4855 { 4856 struct fcp_lun *plun; 4857 struct fcp_port *pptr; 4858 int rscn_count; 4859 int lun0_newalloc; 4860 int ret = TRUE; 4861 4862 ASSERT(ptgt); 4863 pptr = ptgt->tgt_port; 4864 lun0_newalloc = 0; 4865 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4866 /* 4867 * no LUN struct for LUN 0 yet exists, 4868 * so create one 4869 */ 4870 plun = fcp_alloc_lun(ptgt); 4871 if (plun == NULL) { 4872 fcp_log(CE_WARN, pptr->port_dip, 4873 "!Failed to allocate lun 0 for" 4874 " D_ID=%x", ptgt->tgt_d_id); 4875 return (ret); 4876 } 4877 lun0_newalloc = 1; 4878 } 4879 4880 mutex_enter(&ptgt->tgt_mutex); 4881 /* 4882 * consider lun 0 as device not connected if it is 4883 * offlined or newly allocated 4884 */ 4885 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4886 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4887 } 4888 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4889 plun->lun_state &= ~FCP_LUN_OFFLINE; 4890 ptgt->tgt_lun_cnt = 1; 4891 ptgt->tgt_report_lun_cnt = 0; 4892 mutex_exit(&ptgt->tgt_mutex); 4893 4894 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4895 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4896 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4897 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4898 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4899 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4900 "to D_ID=%x", ptgt->tgt_d_id); 4901 } else { 4902 ret = FALSE; 4903 } 4904 4905 return (ret); 4906 } 4907 4908 /* 4909 * Function: fcp_handle_mapflags 4910 * 4911 * Description: This function creates a target structure if the ptgt passed 4912 * is NULL. It also kicks off the PLOGI if we are not logged 4913 * into the target yet or the PRLI if we are logged into the 4914 * target already. The rest of the treatment is done in the 4915 * callbacks of the PLOGI or PRLI. 4916 * 4917 * Argument: *pptr FCP Port structure. 4918 * *ptgt Target structure. 4919 * *map_entry Array of fc_portmap_t structures. 4920 * link_cnt Link state count. 4921 * tgt_cnt Target state count. 4922 * cause What caused this function to be called. 4923 * 4924 * Return Value: TRUE Failed 4925 * FALSE Succeeded 4926 * 4927 * Notes: pptr->port_mutex must be owned. 4928 */ 4929 static int 4930 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4931 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4932 { 4933 int lcount; 4934 int tcount; 4935 int ret = TRUE; 4936 int alloc; 4937 struct fcp_ipkt *icmd; 4938 struct fcp_lun *pseq_lun = NULL; 4939 uchar_t opcode; 4940 int valid_ptgt_was_passed = FALSE; 4941 4942 ASSERT(mutex_owned(&pptr->port_mutex)); 4943 4944 /* 4945 * This case is possible where the FCTL has come up and done discovery 4946 * before FCP was loaded and attached. FCTL would have discovered the 4947 * devices and later the ULP came online. In this case ULP's would get 4948 * PORT_DEVICE_NOCHANGE but target would be NULL. 4949 */ 4950 if (ptgt == NULL) { 4951 /* don't already have a target */ 4952 mutex_exit(&pptr->port_mutex); 4953 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4954 mutex_enter(&pptr->port_mutex); 4955 4956 if (ptgt == NULL) { 4957 fcp_log(CE_WARN, pptr->port_dip, 4958 "!FC target allocation failed"); 4959 return (ret); 4960 } 4961 mutex_enter(&ptgt->tgt_mutex); 4962 ptgt->tgt_statec_cause = cause; 4963 ptgt->tgt_tmp_cnt = 1; 4964 mutex_exit(&ptgt->tgt_mutex); 4965 } else { 4966 valid_ptgt_was_passed = TRUE; 4967 } 4968 4969 /* 4970 * Copy in the target parameters 4971 */ 4972 mutex_enter(&ptgt->tgt_mutex); 4973 ptgt->tgt_d_id = map_entry->map_did.port_id; 4974 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4975 ptgt->tgt_pd_handle = map_entry->map_pd; 4976 ptgt->tgt_fca_dev = NULL; 4977 4978 /* Copy port and node WWNs */ 4979 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4980 FC_WWN_SIZE); 4981 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4982 FC_WWN_SIZE); 4983 4984 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4985 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4986 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4987 valid_ptgt_was_passed) { 4988 /* 4989 * determine if there are any tape LUNs on this target 4990 */ 4991 for (pseq_lun = ptgt->tgt_lun; 4992 pseq_lun != NULL; 4993 pseq_lun = pseq_lun->lun_next) { 4994 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4995 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4996 fcp_update_tgt_state(ptgt, FCP_RESET, 4997 FCP_LUN_MARK); 4998 mutex_exit(&ptgt->tgt_mutex); 4999 return (ret); 5000 } 5001 } 5002 } 5003 5004 /* 5005 * if UA'REPORT_LUN_CHANGED received, 5006 * send out REPORT LUN promptly, skip PLOGI/PRLI process 5007 */ 5008 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 5009 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 5010 mutex_exit(&ptgt->tgt_mutex); 5011 mutex_exit(&pptr->port_mutex); 5012 5013 ret = fcp_handle_reportlun_changed(ptgt, cause); 5014 5015 mutex_enter(&pptr->port_mutex); 5016 return (ret); 5017 } 5018 5019 /* 5020 * If ptgt was NULL when this function was entered, then tgt_node_state 5021 * was never specifically initialized but zeroed out which means 5022 * FCP_TGT_NODE_NONE. 5023 */ 5024 switch (ptgt->tgt_node_state) { 5025 case FCP_TGT_NODE_NONE: 5026 case FCP_TGT_NODE_ON_DEMAND: 5027 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5028 !fcp_enable_auto_configuration && 5029 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5030 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5031 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5032 fcp_enable_auto_configuration && 5033 (ptgt->tgt_manual_config_only == 1) && 5034 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5035 /* 5036 * If auto configuration is set and 5037 * the tgt_manual_config_only flag is set then 5038 * we only want the user to be able to change 5039 * the state through create_on_demand. 5040 */ 5041 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5042 } else { 5043 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5044 } 5045 break; 5046 5047 case FCP_TGT_NODE_PRESENT: 5048 break; 5049 } 5050 /* 5051 * If we are booting from a fabric device, make sure we 5052 * mark the node state appropriately for this target to be 5053 * enumerated 5054 */ 5055 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5056 if (bcmp((caddr_t)pptr->port_boot_wwn, 5057 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5058 sizeof (ptgt->tgt_port_wwn)) == 0) { 5059 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5060 } 5061 } 5062 mutex_exit(&ptgt->tgt_mutex); 5063 5064 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5065 fcp_trace, FCP_BUF_LEVEL_3, 0, 5066 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5067 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5068 map_entry->map_rscn_info.ulp_rscn_count); 5069 5070 mutex_enter(&ptgt->tgt_mutex); 5071 5072 /* 5073 * Reset target OFFLINE state and mark the target BUSY 5074 */ 5075 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5076 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5077 5078 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5079 lcount = link_cnt; 5080 5081 mutex_exit(&ptgt->tgt_mutex); 5082 mutex_exit(&pptr->port_mutex); 5083 5084 /* 5085 * if we are already logged in, then we do a PRLI, else 5086 * we do a PLOGI first (to get logged in) 5087 * 5088 * We will not check if we are the PLOGI initiator 5089 */ 5090 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5091 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5092 5093 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5094 5095 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5096 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5097 cause, map_entry->map_rscn_info.ulp_rscn_count); 5098 5099 if (icmd == NULL) { 5100 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5101 /* 5102 * We've exited port_mutex before calling fcp_icmd_alloc, 5103 * we need to make sure we reacquire it before returning. 5104 */ 5105 mutex_enter(&pptr->port_mutex); 5106 return (FALSE); 5107 } 5108 5109 /* TRUE is only returned while target is intended skipped */ 5110 ret = FALSE; 5111 /* discover info about this target */ 5112 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5113 lcount, tcount, cause)) == DDI_SUCCESS) { 5114 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5115 } else { 5116 fcp_icmd_free(pptr, icmd); 5117 ret = TRUE; 5118 } 5119 mutex_enter(&pptr->port_mutex); 5120 5121 return (ret); 5122 } 5123 5124 /* 5125 * Function: fcp_send_els 5126 * 5127 * Description: Sends an ELS to the target specified by the caller. Supports 5128 * PLOGI and PRLI. 5129 * 5130 * Argument: *pptr Fcp port. 5131 * *ptgt Target to send the ELS to. 5132 * *icmd Internal packet 5133 * opcode ELS opcode 5134 * lcount Link state change counter 5135 * tcount Target state change counter 5136 * cause What caused the call 5137 * 5138 * Return Value: DDI_SUCCESS 5139 * Others 5140 */ 5141 static int 5142 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5143 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5144 { 5145 fc_packet_t *fpkt; 5146 fc_frame_hdr_t *hp; 5147 int internal = 0; 5148 int alloc; 5149 int cmd_len; 5150 int resp_len; 5151 int res = DDI_FAILURE; /* default result */ 5152 int rval = DDI_FAILURE; 5153 5154 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5155 ASSERT(ptgt->tgt_port == pptr); 5156 5157 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5158 fcp_trace, FCP_BUF_LEVEL_5, 0, 5159 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5160 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5161 5162 if (opcode == LA_ELS_PLOGI) { 5163 cmd_len = sizeof (la_els_logi_t); 5164 resp_len = sizeof (la_els_logi_t); 5165 } else { 5166 ASSERT(opcode == LA_ELS_PRLI); 5167 cmd_len = sizeof (la_els_prli_t); 5168 resp_len = sizeof (la_els_prli_t); 5169 } 5170 5171 if (icmd == NULL) { 5172 alloc = FCP_MAX(sizeof (la_els_logi_t), 5173 sizeof (la_els_prli_t)); 5174 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5175 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5176 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5177 if (icmd == NULL) { 5178 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5179 return (res); 5180 } 5181 internal++; 5182 } 5183 fpkt = icmd->ipkt_fpkt; 5184 5185 fpkt->pkt_cmdlen = cmd_len; 5186 fpkt->pkt_rsplen = resp_len; 5187 fpkt->pkt_datalen = 0; 5188 icmd->ipkt_retries = 0; 5189 5190 /* fill in fpkt info */ 5191 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5192 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5193 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5194 5195 /* get ptr to frame hdr in fpkt */ 5196 hp = &fpkt->pkt_cmd_fhdr; 5197 5198 /* 5199 * fill in frame hdr 5200 */ 5201 hp->r_ctl = R_CTL_ELS_REQ; 5202 hp->s_id = pptr->port_id; /* source ID */ 5203 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5204 hp->type = FC_TYPE_EXTENDED_LS; 5205 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5206 hp->seq_id = 0; 5207 hp->rsvd = 0; 5208 hp->df_ctl = 0; 5209 hp->seq_cnt = 0; 5210 hp->ox_id = 0xffff; /* i.e. none */ 5211 hp->rx_id = 0xffff; /* i.e. none */ 5212 hp->ro = 0; 5213 5214 /* 5215 * at this point we have a filled in cmd pkt 5216 * 5217 * fill in the respective info, then use the transport to send 5218 * the packet 5219 * 5220 * for a PLOGI call fc_ulp_login(), and 5221 * for a PRLI call fc_ulp_issue_els() 5222 */ 5223 switch (opcode) { 5224 case LA_ELS_PLOGI: { 5225 struct la_els_logi logi; 5226 5227 bzero(&logi, sizeof (struct la_els_logi)); 5228 5229 hp = &fpkt->pkt_cmd_fhdr; 5230 hp->r_ctl = R_CTL_ELS_REQ; 5231 logi.ls_code.ls_code = LA_ELS_PLOGI; 5232 logi.ls_code.mbz = 0; 5233 5234 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5235 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5236 5237 icmd->ipkt_opcode = LA_ELS_PLOGI; 5238 5239 mutex_enter(&pptr->port_mutex); 5240 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5241 5242 mutex_exit(&pptr->port_mutex); 5243 5244 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5245 if (rval == FC_SUCCESS) { 5246 res = DDI_SUCCESS; 5247 break; 5248 } 5249 5250 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5251 5252 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5253 rval, "PLOGI"); 5254 } else { 5255 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5256 fcp_trace, FCP_BUF_LEVEL_5, 0, 5257 "fcp_send_els1: state change occured" 5258 " for D_ID=0x%x", ptgt->tgt_d_id); 5259 mutex_exit(&pptr->port_mutex); 5260 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5261 } 5262 break; 5263 } 5264 5265 case LA_ELS_PRLI: { 5266 struct la_els_prli prli; 5267 struct fcp_prli *fprli; 5268 5269 bzero(&prli, sizeof (struct la_els_prli)); 5270 5271 hp = &fpkt->pkt_cmd_fhdr; 5272 hp->r_ctl = R_CTL_ELS_REQ; 5273 5274 /* fill in PRLI cmd ELS fields */ 5275 prli.ls_code = LA_ELS_PRLI; 5276 prli.page_length = 0x10; /* huh? */ 5277 prli.payload_length = sizeof (struct la_els_prli); 5278 5279 icmd->ipkt_opcode = LA_ELS_PRLI; 5280 5281 /* get ptr to PRLI service params */ 5282 fprli = (struct fcp_prli *)prli.service_params; 5283 5284 /* fill in service params */ 5285 fprli->type = 0x08; 5286 fprli->resvd1 = 0; 5287 fprli->orig_process_assoc_valid = 0; 5288 fprli->resp_process_assoc_valid = 0; 5289 fprli->establish_image_pair = 1; 5290 fprli->resvd2 = 0; 5291 fprli->resvd3 = 0; 5292 fprli->obsolete_1 = 0; 5293 fprli->obsolete_2 = 0; 5294 fprli->data_overlay_allowed = 0; 5295 fprli->initiator_fn = 1; 5296 fprli->confirmed_compl_allowed = 1; 5297 5298 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5299 fprli->target_fn = 1; 5300 } else { 5301 fprli->target_fn = 0; 5302 } 5303 5304 fprli->retry = 1; 5305 fprli->read_xfer_rdy_disabled = 1; 5306 fprli->write_xfer_rdy_disabled = 0; 5307 5308 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5309 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5310 5311 /* issue the PRLI request */ 5312 5313 mutex_enter(&pptr->port_mutex); 5314 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5315 5316 mutex_exit(&pptr->port_mutex); 5317 5318 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5319 if (rval == FC_SUCCESS) { 5320 res = DDI_SUCCESS; 5321 break; 5322 } 5323 5324 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5325 5326 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5327 rval, "PRLI"); 5328 } else { 5329 mutex_exit(&pptr->port_mutex); 5330 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5331 } 5332 break; 5333 } 5334 5335 default: 5336 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5337 break; 5338 } 5339 5340 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5341 fcp_trace, FCP_BUF_LEVEL_5, 0, 5342 "fcp_send_els: returning %d", res); 5343 5344 if (res != DDI_SUCCESS) { 5345 if (internal) { 5346 fcp_icmd_free(pptr, icmd); 5347 } 5348 } 5349 5350 return (res); 5351 } 5352 5353 5354 /* 5355 * called internally update the state of all of the tgts and each LUN 5356 * for this port (i.e. each target known to be attached to this port) 5357 * if they are not already offline 5358 * 5359 * must be called with the port mutex owned 5360 * 5361 * acquires and releases the target mutexes for each target attached 5362 * to this port 5363 */ 5364 void 5365 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5366 { 5367 int i; 5368 struct fcp_tgt *ptgt; 5369 5370 ASSERT(mutex_owned(&pptr->port_mutex)); 5371 5372 for (i = 0; i < FCP_NUM_HASH; i++) { 5373 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5374 ptgt = ptgt->tgt_next) { 5375 mutex_enter(&ptgt->tgt_mutex); 5376 fcp_update_tgt_state(ptgt, FCP_SET, state); 5377 ptgt->tgt_change_cnt++; 5378 ptgt->tgt_statec_cause = cause; 5379 ptgt->tgt_tmp_cnt = 1; 5380 ptgt->tgt_done = 0; 5381 mutex_exit(&ptgt->tgt_mutex); 5382 } 5383 } 5384 } 5385 5386 5387 static void 5388 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5389 { 5390 int i; 5391 int ndevs; 5392 struct fcp_tgt *ptgt; 5393 5394 ASSERT(mutex_owned(&pptr->port_mutex)); 5395 5396 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5397 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5398 ptgt = ptgt->tgt_next) { 5399 ndevs++; 5400 } 5401 } 5402 5403 if (ndevs == 0) { 5404 return; 5405 } 5406 pptr->port_tmp_cnt = ndevs; 5407 5408 for (i = 0; i < FCP_NUM_HASH; i++) { 5409 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5410 ptgt = ptgt->tgt_next) { 5411 (void) fcp_call_finish_init_held(pptr, ptgt, 5412 lcount, ptgt->tgt_change_cnt, cause); 5413 } 5414 } 5415 } 5416 5417 /* 5418 * Function: fcp_update_tgt_state 5419 * 5420 * Description: This function updates the field tgt_state of a target. That 5421 * field is a bitmap and which bit can be set or reset 5422 * individually. The action applied to the target state is also 5423 * applied to all the LUNs belonging to the target (provided the 5424 * LUN is not offline). A side effect of applying the state 5425 * modification to the target and the LUNs is the field tgt_trace 5426 * of the target and lun_trace of the LUNs is set to zero. 5427 * 5428 * 5429 * Argument: *ptgt Target structure. 5430 * flag Flag indication what action to apply (set/reset). 5431 * state State bits to update. 5432 * 5433 * Return Value: None 5434 * 5435 * Context: Interrupt, Kernel or User context. 5436 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5437 * calling this function. 5438 */ 5439 void 5440 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5441 { 5442 struct fcp_lun *plun; 5443 5444 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5445 5446 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5447 /* The target is not offline. */ 5448 if (flag == FCP_SET) { 5449 ptgt->tgt_state |= state; 5450 ptgt->tgt_trace = 0; 5451 } else { 5452 ptgt->tgt_state &= ~state; 5453 } 5454 5455 for (plun = ptgt->tgt_lun; plun != NULL; 5456 plun = plun->lun_next) { 5457 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5458 /* The LUN is not offline. */ 5459 if (flag == FCP_SET) { 5460 plun->lun_state |= state; 5461 plun->lun_trace = 0; 5462 } else { 5463 plun->lun_state &= ~state; 5464 } 5465 } 5466 } 5467 } 5468 } 5469 5470 /* 5471 * Function: fcp_update_tgt_state 5472 * 5473 * Description: This function updates the field lun_state of a LUN. That 5474 * field is a bitmap and which bit can be set or reset 5475 * individually. 5476 * 5477 * Argument: *plun LUN structure. 5478 * flag Flag indication what action to apply (set/reset). 5479 * state State bits to update. 5480 * 5481 * Return Value: None 5482 * 5483 * Context: Interrupt, Kernel or User context. 5484 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5485 * calling this function. 5486 */ 5487 void 5488 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5489 { 5490 struct fcp_tgt *ptgt = plun->lun_tgt; 5491 5492 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5493 5494 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5495 if (flag == FCP_SET) { 5496 plun->lun_state |= state; 5497 } else { 5498 plun->lun_state &= ~state; 5499 } 5500 } 5501 } 5502 5503 /* 5504 * Function: fcp_get_port 5505 * 5506 * Description: This function returns the fcp_port structure from the opaque 5507 * handle passed by the caller. That opaque handle is the handle 5508 * used by fp/fctl to identify a particular local port. That 5509 * handle has been stored in the corresponding fcp_port 5510 * structure. This function is going to walk the global list of 5511 * fcp_port structures till one has a port_fp_handle that matches 5512 * the handle passed by the caller. This function enters the 5513 * mutex fcp_global_mutex while walking the global list and then 5514 * releases it. 5515 * 5516 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5517 * particular port. 5518 * 5519 * Return Value: NULL Not found. 5520 * Not NULL Pointer to the fcp_port structure. 5521 * 5522 * Context: Interrupt, Kernel or User context. 5523 */ 5524 static struct fcp_port * 5525 fcp_get_port(opaque_t port_handle) 5526 { 5527 struct fcp_port *pptr; 5528 5529 ASSERT(port_handle != NULL); 5530 5531 mutex_enter(&fcp_global_mutex); 5532 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5533 if (pptr->port_fp_handle == port_handle) { 5534 break; 5535 } 5536 } 5537 mutex_exit(&fcp_global_mutex); 5538 5539 return (pptr); 5540 } 5541 5542 5543 static void 5544 fcp_unsol_callback(fc_packet_t *fpkt) 5545 { 5546 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5547 struct fcp_port *pptr = icmd->ipkt_port; 5548 5549 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5550 caddr_t state, reason, action, expln; 5551 5552 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5553 &action, &expln); 5554 5555 fcp_log(CE_WARN, pptr->port_dip, 5556 "!couldn't post response to unsolicited request: " 5557 " state=%s reason=%s rx_id=%x ox_id=%x", 5558 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5559 fpkt->pkt_cmd_fhdr.rx_id); 5560 } 5561 fcp_icmd_free(pptr, icmd); 5562 } 5563 5564 5565 /* 5566 * Perform general purpose preparation of a response to an unsolicited request 5567 */ 5568 static void 5569 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5570 uchar_t r_ctl, uchar_t type) 5571 { 5572 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5573 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5574 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5575 pkt->pkt_cmd_fhdr.type = type; 5576 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5577 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5578 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5579 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5580 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5581 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5582 pkt->pkt_cmd_fhdr.ro = 0; 5583 pkt->pkt_cmd_fhdr.rsvd = 0; 5584 pkt->pkt_comp = fcp_unsol_callback; 5585 pkt->pkt_pd = NULL; 5586 pkt->pkt_ub_resp_token = (opaque_t)buf; 5587 } 5588 5589 5590 /*ARGSUSED*/ 5591 static int 5592 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5593 { 5594 fc_packet_t *fpkt; 5595 struct la_els_prli prli; 5596 struct fcp_prli *fprli; 5597 struct fcp_ipkt *icmd; 5598 struct la_els_prli *from; 5599 struct fcp_prli *orig; 5600 struct fcp_tgt *ptgt; 5601 int tcount = 0; 5602 int lcount; 5603 5604 from = (struct la_els_prli *)buf->ub_buffer; 5605 orig = (struct fcp_prli *)from->service_params; 5606 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5607 NULL) { 5608 mutex_enter(&ptgt->tgt_mutex); 5609 tcount = ptgt->tgt_change_cnt; 5610 mutex_exit(&ptgt->tgt_mutex); 5611 } 5612 5613 mutex_enter(&pptr->port_mutex); 5614 lcount = pptr->port_link_cnt; 5615 mutex_exit(&pptr->port_mutex); 5616 5617 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5618 sizeof (la_els_prli_t), 0, 5619 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5620 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5621 return (FC_FAILURE); 5622 } 5623 5624 fpkt = icmd->ipkt_fpkt; 5625 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5626 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5627 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5628 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5629 fpkt->pkt_rsplen = 0; 5630 fpkt->pkt_datalen = 0; 5631 5632 icmd->ipkt_opcode = LA_ELS_PRLI; 5633 5634 bzero(&prli, sizeof (struct la_els_prli)); 5635 fprli = (struct fcp_prli *)prli.service_params; 5636 prli.ls_code = LA_ELS_ACC; 5637 prli.page_length = 0x10; 5638 prli.payload_length = sizeof (struct la_els_prli); 5639 5640 /* fill in service params */ 5641 fprli->type = 0x08; 5642 fprli->resvd1 = 0; 5643 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5644 fprli->orig_process_associator = orig->orig_process_associator; 5645 fprli->resp_process_assoc_valid = 0; 5646 fprli->establish_image_pair = 1; 5647 fprli->resvd2 = 0; 5648 fprli->resvd3 = 0; 5649 fprli->obsolete_1 = 0; 5650 fprli->obsolete_2 = 0; 5651 fprli->data_overlay_allowed = 0; 5652 fprli->initiator_fn = 1; 5653 fprli->confirmed_compl_allowed = 1; 5654 5655 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5656 fprli->target_fn = 1; 5657 } else { 5658 fprli->target_fn = 0; 5659 } 5660 5661 fprli->retry = 1; 5662 fprli->read_xfer_rdy_disabled = 1; 5663 fprli->write_xfer_rdy_disabled = 0; 5664 5665 /* save the unsol prli payload first */ 5666 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5667 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5668 5669 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5670 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5671 5672 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5673 5674 mutex_enter(&pptr->port_mutex); 5675 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5676 int rval; 5677 mutex_exit(&pptr->port_mutex); 5678 5679 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5680 FC_SUCCESS) { 5681 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5682 ptgt != NULL) { 5683 fcp_queue_ipkt(pptr, fpkt); 5684 return (FC_SUCCESS); 5685 } 5686 /* Let it timeout */ 5687 fcp_icmd_free(pptr, icmd); 5688 return (FC_FAILURE); 5689 } 5690 } else { 5691 mutex_exit(&pptr->port_mutex); 5692 fcp_icmd_free(pptr, icmd); 5693 return (FC_FAILURE); 5694 } 5695 5696 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5697 5698 return (FC_SUCCESS); 5699 } 5700 5701 /* 5702 * Function: fcp_icmd_alloc 5703 * 5704 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5705 * field is initialized to fcp_icmd_callback. Sometimes it is 5706 * modified by the caller (such as fcp_send_scsi). The 5707 * structure is also tied to the state of the line and of the 5708 * target at a particular time. That link is established by 5709 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5710 * and tcount which came respectively from pptr->link_cnt and 5711 * ptgt->tgt_change_cnt. 5712 * 5713 * Argument: *pptr Fcp port. 5714 * *ptgt Target (destination of the command). 5715 * cmd_len Length of the command. 5716 * resp_len Length of the expected response. 5717 * data_len Length of the data. 5718 * nodma Indicates weither the command and response. 5719 * will be transfer through DMA or not. 5720 * lcount Link state change counter. 5721 * tcount Target state change counter. 5722 * cause Reason that lead to this call. 5723 * 5724 * Return Value: NULL Failed. 5725 * Not NULL Internal packet address. 5726 */ 5727 static struct fcp_ipkt * 5728 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5729 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5730 uint32_t rscn_count) 5731 { 5732 int dma_setup = 0; 5733 fc_packet_t *fpkt; 5734 struct fcp_ipkt *icmd = NULL; 5735 5736 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5737 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5738 KM_NOSLEEP); 5739 if (icmd == NULL) { 5740 fcp_log(CE_WARN, pptr->port_dip, 5741 "!internal packet allocation failed"); 5742 return (NULL); 5743 } 5744 5745 /* 5746 * initialize the allocated packet 5747 */ 5748 icmd->ipkt_nodma = nodma; 5749 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5750 icmd->ipkt_lun = NULL; 5751 5752 icmd->ipkt_link_cnt = lcount; 5753 icmd->ipkt_change_cnt = tcount; 5754 icmd->ipkt_cause = cause; 5755 5756 mutex_enter(&pptr->port_mutex); 5757 icmd->ipkt_port = pptr; 5758 mutex_exit(&pptr->port_mutex); 5759 5760 /* keep track of amt of data to be sent in pkt */ 5761 icmd->ipkt_cmdlen = cmd_len; 5762 icmd->ipkt_resplen = resp_len; 5763 icmd->ipkt_datalen = data_len; 5764 5765 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5766 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5767 5768 /* set pkt's private ptr to point to cmd pkt */ 5769 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5770 5771 /* set FCA private ptr to memory just beyond */ 5772 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5773 ((char *)icmd + sizeof (struct fcp_ipkt) + 5774 pptr->port_dmacookie_sz); 5775 5776 /* get ptr to fpkt substruct and fill it in */ 5777 fpkt = icmd->ipkt_fpkt; 5778 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5779 sizeof (struct fcp_ipkt)); 5780 5781 if (ptgt != NULL) { 5782 icmd->ipkt_tgt = ptgt; 5783 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5784 } 5785 5786 fpkt->pkt_comp = fcp_icmd_callback; 5787 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5788 fpkt->pkt_cmdlen = cmd_len; 5789 fpkt->pkt_rsplen = resp_len; 5790 fpkt->pkt_datalen = data_len; 5791 5792 /* 5793 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5794 * rscn_count as fcp knows down to the transport. If a valid count was 5795 * passed into this function, we allocate memory to actually pass down 5796 * this info. 5797 * 5798 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5799 * basically mean that fcp will not be able to help transport 5800 * distinguish if a new RSCN has come after fcp was last informed about 5801 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5802 * 5068068 where the device might end up going offline in case of RSCN 5803 * storms. 5804 */ 5805 fpkt->pkt_ulp_rscn_infop = NULL; 5806 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5807 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5808 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5809 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5810 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5811 fcp_trace, FCP_BUF_LEVEL_6, 0, 5812 "Failed to alloc memory to pass rscn info"); 5813 } 5814 } 5815 5816 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5817 fc_ulp_rscn_info_t *rscnp; 5818 5819 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5820 rscnp->ulp_rscn_count = rscn_count; 5821 } 5822 5823 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5824 goto fail; 5825 } 5826 dma_setup++; 5827 5828 /* 5829 * Must hold target mutex across setting of pkt_pd and call to 5830 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5831 * away while we're not looking. 5832 */ 5833 if (ptgt != NULL) { 5834 mutex_enter(&ptgt->tgt_mutex); 5835 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5836 5837 /* ask transport to do its initialization on this pkt */ 5838 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5839 != FC_SUCCESS) { 5840 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5841 fcp_trace, FCP_BUF_LEVEL_6, 0, 5842 "fc_ulp_init_packet failed"); 5843 mutex_exit(&ptgt->tgt_mutex); 5844 goto fail; 5845 } 5846 mutex_exit(&ptgt->tgt_mutex); 5847 } else { 5848 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5849 != FC_SUCCESS) { 5850 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5851 fcp_trace, FCP_BUF_LEVEL_6, 0, 5852 "fc_ulp_init_packet failed"); 5853 goto fail; 5854 } 5855 } 5856 5857 mutex_enter(&pptr->port_mutex); 5858 if (pptr->port_state & (FCP_STATE_DETACHING | 5859 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5860 int rval; 5861 5862 mutex_exit(&pptr->port_mutex); 5863 5864 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5865 ASSERT(rval == FC_SUCCESS); 5866 5867 goto fail; 5868 } 5869 5870 if (ptgt != NULL) { 5871 mutex_enter(&ptgt->tgt_mutex); 5872 ptgt->tgt_ipkt_cnt++; 5873 mutex_exit(&ptgt->tgt_mutex); 5874 } 5875 5876 pptr->port_ipkt_cnt++; 5877 5878 mutex_exit(&pptr->port_mutex); 5879 5880 return (icmd); 5881 5882 fail: 5883 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5884 kmem_free(fpkt->pkt_ulp_rscn_infop, 5885 sizeof (fc_ulp_rscn_info_t)); 5886 fpkt->pkt_ulp_rscn_infop = NULL; 5887 } 5888 5889 if (dma_setup) { 5890 fcp_free_dma(pptr, icmd); 5891 } 5892 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5893 (size_t)pptr->port_dmacookie_sz); 5894 5895 return (NULL); 5896 } 5897 5898 /* 5899 * Function: fcp_icmd_free 5900 * 5901 * Description: Frees the internal command passed by the caller. 5902 * 5903 * Argument: *pptr Fcp port. 5904 * *icmd Internal packet to free. 5905 * 5906 * Return Value: None 5907 */ 5908 static void 5909 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5910 { 5911 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5912 5913 /* Let the underlying layers do their cleanup. */ 5914 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5915 icmd->ipkt_fpkt); 5916 5917 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5918 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5919 sizeof (fc_ulp_rscn_info_t)); 5920 } 5921 5922 fcp_free_dma(pptr, icmd); 5923 5924 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5925 (size_t)pptr->port_dmacookie_sz); 5926 5927 mutex_enter(&pptr->port_mutex); 5928 5929 if (ptgt) { 5930 mutex_enter(&ptgt->tgt_mutex); 5931 ptgt->tgt_ipkt_cnt--; 5932 mutex_exit(&ptgt->tgt_mutex); 5933 } 5934 5935 pptr->port_ipkt_cnt--; 5936 mutex_exit(&pptr->port_mutex); 5937 } 5938 5939 /* 5940 * Function: fcp_alloc_dma 5941 * 5942 * Description: Allocated the DMA resources required for the internal 5943 * packet. 5944 * 5945 * Argument: *pptr FCP port. 5946 * *icmd Internal FCP packet. 5947 * nodma Indicates if the Cmd and Resp will be DMAed. 5948 * flags Allocation flags (Sleep or NoSleep). 5949 * 5950 * Return Value: FC_SUCCESS 5951 * FC_NOMEM 5952 */ 5953 static int 5954 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5955 int nodma, int flags) 5956 { 5957 int rval; 5958 size_t real_size; 5959 uint_t ccount; 5960 int bound = 0; 5961 int cmd_resp = 0; 5962 fc_packet_t *fpkt; 5963 ddi_dma_cookie_t pkt_data_cookie; 5964 ddi_dma_cookie_t *cp; 5965 uint32_t cnt; 5966 5967 fpkt = &icmd->ipkt_fc_packet; 5968 5969 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5970 fpkt->pkt_resp_dma == NULL); 5971 5972 icmd->ipkt_nodma = nodma; 5973 5974 if (nodma) { 5975 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5976 if (fpkt->pkt_cmd == NULL) { 5977 goto fail; 5978 } 5979 5980 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5981 if (fpkt->pkt_resp == NULL) { 5982 goto fail; 5983 } 5984 } else { 5985 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5986 5987 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5988 if (rval == FC_FAILURE) { 5989 ASSERT(fpkt->pkt_cmd_dma == NULL && 5990 fpkt->pkt_resp_dma == NULL); 5991 goto fail; 5992 } 5993 cmd_resp++; 5994 } 5995 5996 if ((fpkt->pkt_datalen != 0) && 5997 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 5998 /* 5999 * set up DMA handle and memory for the data in this packet 6000 */ 6001 if (ddi_dma_alloc_handle(pptr->port_dip, 6002 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 6003 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 6004 goto fail; 6005 } 6006 6007 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 6008 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 6009 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 6010 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 6011 goto fail; 6012 } 6013 6014 /* was DMA mem size gotten < size asked for/needed ?? */ 6015 if (real_size < fpkt->pkt_datalen) { 6016 goto fail; 6017 } 6018 6019 /* bind DMA address and handle together */ 6020 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6021 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6022 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6023 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6024 goto fail; 6025 } 6026 bound++; 6027 6028 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6029 goto fail; 6030 } 6031 6032 fpkt->pkt_data_cookie_cnt = ccount; 6033 6034 cp = fpkt->pkt_data_cookie; 6035 *cp = pkt_data_cookie; 6036 cp++; 6037 6038 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6039 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6040 &pkt_data_cookie); 6041 *cp = pkt_data_cookie; 6042 } 6043 6044 } else if (fpkt->pkt_datalen != 0) { 6045 /* 6046 * If it's a pseudo FCA, then it can't support DMA even in 6047 * SCSI data phase. 6048 */ 6049 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6050 if (fpkt->pkt_data == NULL) { 6051 goto fail; 6052 } 6053 6054 } 6055 6056 return (FC_SUCCESS); 6057 6058 fail: 6059 if (bound) { 6060 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6061 } 6062 6063 if (fpkt->pkt_data_dma) { 6064 if (fpkt->pkt_data) { 6065 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6066 } 6067 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6068 } else { 6069 if (fpkt->pkt_data) { 6070 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6071 } 6072 } 6073 6074 if (nodma) { 6075 if (fpkt->pkt_cmd) { 6076 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6077 } 6078 if (fpkt->pkt_resp) { 6079 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6080 } 6081 } else { 6082 if (cmd_resp) { 6083 fcp_free_cmd_resp(pptr, fpkt); 6084 } 6085 } 6086 6087 return (FC_NOMEM); 6088 } 6089 6090 6091 static void 6092 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6093 { 6094 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6095 6096 if (fpkt->pkt_data_dma) { 6097 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6098 if (fpkt->pkt_data) { 6099 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6100 } 6101 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6102 } else { 6103 if (fpkt->pkt_data) { 6104 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6105 } 6106 /* 6107 * Need we reset pkt_* to zero??? 6108 */ 6109 } 6110 6111 if (icmd->ipkt_nodma) { 6112 if (fpkt->pkt_cmd) { 6113 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6114 } 6115 if (fpkt->pkt_resp) { 6116 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6117 } 6118 } else { 6119 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6120 6121 fcp_free_cmd_resp(pptr, fpkt); 6122 } 6123 } 6124 6125 /* 6126 * Function: fcp_lookup_target 6127 * 6128 * Description: Finds a target given a WWN. 6129 * 6130 * Argument: *pptr FCP port. 6131 * *wwn World Wide Name of the device to look for. 6132 * 6133 * Return Value: NULL No target found 6134 * Not NULL Target structure 6135 * 6136 * Context: Interrupt context. 6137 * The mutex pptr->port_mutex must be owned. 6138 */ 6139 /* ARGSUSED */ 6140 static struct fcp_tgt * 6141 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6142 { 6143 int hash; 6144 struct fcp_tgt *ptgt; 6145 6146 ASSERT(mutex_owned(&pptr->port_mutex)); 6147 6148 hash = FCP_HASH(wwn); 6149 6150 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6151 ptgt = ptgt->tgt_next) { 6152 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6153 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6154 sizeof (ptgt->tgt_port_wwn)) == 0) { 6155 break; 6156 } 6157 } 6158 6159 return (ptgt); 6160 } 6161 6162 6163 /* 6164 * Find target structure given a port identifier 6165 */ 6166 static struct fcp_tgt * 6167 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6168 { 6169 fc_portid_t port_id; 6170 la_wwn_t pwwn; 6171 struct fcp_tgt *ptgt = NULL; 6172 6173 port_id.priv_lilp_posit = 0; 6174 port_id.port_id = d_id; 6175 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6176 &pwwn) == FC_SUCCESS) { 6177 mutex_enter(&pptr->port_mutex); 6178 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6179 mutex_exit(&pptr->port_mutex); 6180 } 6181 6182 return (ptgt); 6183 } 6184 6185 6186 /* 6187 * the packet completion callback routine for info cmd pkts 6188 * 6189 * this means fpkt pts to a response to either a PLOGI or a PRLI 6190 * 6191 * if there is an error an attempt is made to call a routine to resend 6192 * the command that failed 6193 */ 6194 static void 6195 fcp_icmd_callback(fc_packet_t *fpkt) 6196 { 6197 struct fcp_ipkt *icmd; 6198 struct fcp_port *pptr; 6199 struct fcp_tgt *ptgt; 6200 struct la_els_prli *prli; 6201 struct la_els_prli prli_s; 6202 struct fcp_prli *fprli; 6203 struct fcp_lun *plun; 6204 int free_pkt = 1; 6205 int rval; 6206 ls_code_t resp; 6207 uchar_t prli_acc = 0; 6208 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6209 int lun0_newalloc; 6210 6211 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6212 6213 /* get ptrs to the port and target structs for the cmd */ 6214 pptr = icmd->ipkt_port; 6215 ptgt = icmd->ipkt_tgt; 6216 6217 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6218 6219 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6220 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6221 sizeof (prli_s)); 6222 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6223 } 6224 6225 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6226 fcp_trace, FCP_BUF_LEVEL_2, 0, 6227 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6228 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6229 ptgt->tgt_d_id); 6230 6231 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6232 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6233 6234 mutex_enter(&ptgt->tgt_mutex); 6235 if (ptgt->tgt_pd_handle == NULL) { 6236 /* 6237 * in a fabric environment the port device handles 6238 * get created only after successful LOGIN into the 6239 * transport, so the transport makes this port 6240 * device (pd) handle available in this packet, so 6241 * save it now 6242 */ 6243 ASSERT(fpkt->pkt_pd != NULL); 6244 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6245 } 6246 mutex_exit(&ptgt->tgt_mutex); 6247 6248 /* which ELS cmd is this response for ?? */ 6249 switch (icmd->ipkt_opcode) { 6250 case LA_ELS_PLOGI: 6251 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6252 fcp_trace, FCP_BUF_LEVEL_5, 0, 6253 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6254 ptgt->tgt_d_id, 6255 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6256 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6257 6258 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6259 FCP_TGT_TRACE_15); 6260 6261 /* Note that we are not allocating a new icmd */ 6262 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6263 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6264 icmd->ipkt_cause) != DDI_SUCCESS) { 6265 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6266 FCP_TGT_TRACE_16); 6267 goto fail; 6268 } 6269 break; 6270 6271 case LA_ELS_PRLI: 6272 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6273 fcp_trace, FCP_BUF_LEVEL_5, 0, 6274 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6275 6276 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6277 FCP_TGT_TRACE_17); 6278 6279 prli = &prli_s; 6280 6281 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6282 sizeof (prli_s)); 6283 6284 fprli = (struct fcp_prli *)prli->service_params; 6285 6286 mutex_enter(&ptgt->tgt_mutex); 6287 ptgt->tgt_icap = fprli->initiator_fn; 6288 ptgt->tgt_tcap = fprli->target_fn; 6289 mutex_exit(&ptgt->tgt_mutex); 6290 6291 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6292 /* 6293 * this FCP device does not support target mode 6294 */ 6295 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6296 FCP_TGT_TRACE_18); 6297 goto fail; 6298 } 6299 if (fprli->retry == 1) { 6300 fc_ulp_disable_relogin(pptr->port_fp_handle, 6301 &ptgt->tgt_port_wwn); 6302 } 6303 6304 /* target is no longer offline */ 6305 mutex_enter(&pptr->port_mutex); 6306 mutex_enter(&ptgt->tgt_mutex); 6307 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6308 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6309 FCP_TGT_MARK); 6310 } else { 6311 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6312 fcp_trace, FCP_BUF_LEVEL_2, 0, 6313 "fcp_icmd_callback,1: state change " 6314 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6315 mutex_exit(&ptgt->tgt_mutex); 6316 mutex_exit(&pptr->port_mutex); 6317 goto fail; 6318 } 6319 mutex_exit(&ptgt->tgt_mutex); 6320 mutex_exit(&pptr->port_mutex); 6321 6322 /* 6323 * lun 0 should always respond to inquiry, so 6324 * get the LUN struct for LUN 0 6325 * 6326 * Currently we deal with first level of addressing. 6327 * If / when we start supporting 0x device types 6328 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6329 * this logic will need revisiting. 6330 */ 6331 lun0_newalloc = 0; 6332 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6333 /* 6334 * no LUN struct for LUN 0 yet exists, 6335 * so create one 6336 */ 6337 plun = fcp_alloc_lun(ptgt); 6338 if (plun == NULL) { 6339 fcp_log(CE_WARN, pptr->port_dip, 6340 "!Failed to allocate lun 0 for" 6341 " D_ID=%x", ptgt->tgt_d_id); 6342 goto fail; 6343 } 6344 lun0_newalloc = 1; 6345 } 6346 6347 /* fill in LUN info */ 6348 mutex_enter(&ptgt->tgt_mutex); 6349 /* 6350 * consider lun 0 as device not connected if it is 6351 * offlined or newly allocated 6352 */ 6353 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6354 lun0_newalloc) { 6355 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6356 } 6357 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6358 plun->lun_state &= ~FCP_LUN_OFFLINE; 6359 ptgt->tgt_lun_cnt = 1; 6360 ptgt->tgt_report_lun_cnt = 0; 6361 mutex_exit(&ptgt->tgt_mutex); 6362 6363 /* Retrieve the rscn count (if a valid one exists) */ 6364 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6365 rscn_count = ((fc_ulp_rscn_info_t *) 6366 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6367 ->ulp_rscn_count; 6368 } else { 6369 rscn_count = FC_INVALID_RSCN_COUNT; 6370 } 6371 6372 /* send Report Lun request to target */ 6373 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6374 sizeof (struct fcp_reportlun_resp), 6375 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6376 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6377 mutex_enter(&pptr->port_mutex); 6378 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6379 fcp_log(CE_WARN, pptr->port_dip, 6380 "!Failed to send REPORT LUN to" 6381 " D_ID=%x", ptgt->tgt_d_id); 6382 } else { 6383 FCP_TRACE(fcp_logq, 6384 pptr->port_instbuf, fcp_trace, 6385 FCP_BUF_LEVEL_5, 0, 6386 "fcp_icmd_callback,2:state change" 6387 " occured for D_ID=0x%x", 6388 ptgt->tgt_d_id); 6389 } 6390 mutex_exit(&pptr->port_mutex); 6391 6392 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6393 FCP_TGT_TRACE_19); 6394 6395 goto fail; 6396 } else { 6397 free_pkt = 0; 6398 fcp_icmd_free(pptr, icmd); 6399 } 6400 break; 6401 6402 default: 6403 fcp_log(CE_WARN, pptr->port_dip, 6404 "!fcp_icmd_callback Invalid opcode"); 6405 goto fail; 6406 } 6407 6408 return; 6409 } 6410 6411 6412 /* 6413 * Other PLOGI failures are not retried as the 6414 * transport does it already 6415 */ 6416 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6417 if (fcp_is_retryable(icmd) && 6418 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6419 6420 if (FCP_MUST_RETRY(fpkt)) { 6421 fcp_queue_ipkt(pptr, fpkt); 6422 return; 6423 } 6424 6425 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6426 fcp_trace, FCP_BUF_LEVEL_2, 0, 6427 "ELS PRLI is retried for d_id=0x%x, state=%x," 6428 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6429 fpkt->pkt_reason); 6430 6431 /* 6432 * Retry by recalling the routine that 6433 * originally queued this packet 6434 */ 6435 mutex_enter(&pptr->port_mutex); 6436 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6437 caddr_t msg; 6438 6439 mutex_exit(&pptr->port_mutex); 6440 6441 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6442 6443 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6444 fpkt->pkt_timeout += 6445 FCP_TIMEOUT_DELTA; 6446 } 6447 6448 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6449 fpkt); 6450 if (rval == FC_SUCCESS) { 6451 return; 6452 } 6453 6454 if (rval == FC_STATEC_BUSY || 6455 rval == FC_OFFLINE) { 6456 fcp_queue_ipkt(pptr, fpkt); 6457 return; 6458 } 6459 (void) fc_ulp_error(rval, &msg); 6460 6461 fcp_log(CE_NOTE, pptr->port_dip, 6462 "!ELS 0x%x failed to d_id=0x%x;" 6463 " %s", icmd->ipkt_opcode, 6464 ptgt->tgt_d_id, msg); 6465 } else { 6466 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6467 fcp_trace, FCP_BUF_LEVEL_2, 0, 6468 "fcp_icmd_callback,3: state change " 6469 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6470 mutex_exit(&pptr->port_mutex); 6471 } 6472 } 6473 } else { 6474 if (fcp_is_retryable(icmd) && 6475 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6476 if (FCP_MUST_RETRY(fpkt)) { 6477 fcp_queue_ipkt(pptr, fpkt); 6478 return; 6479 } 6480 } 6481 mutex_enter(&pptr->port_mutex); 6482 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6483 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6484 mutex_exit(&pptr->port_mutex); 6485 fcp_print_error(fpkt); 6486 } else { 6487 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6488 fcp_trace, FCP_BUF_LEVEL_2, 0, 6489 "fcp_icmd_callback,4: state change occured" 6490 " for D_ID=0x%x", ptgt->tgt_d_id); 6491 mutex_exit(&pptr->port_mutex); 6492 } 6493 } 6494 6495 fail: 6496 if (free_pkt) { 6497 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6498 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6499 fcp_icmd_free(pptr, icmd); 6500 } 6501 } 6502 6503 6504 /* 6505 * called internally to send an info cmd using the transport 6506 * 6507 * sends either an INQ or a REPORT_LUN 6508 * 6509 * when the packet is completed fcp_scsi_callback is called 6510 */ 6511 static int 6512 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6513 int lcount, int tcount, int cause, uint32_t rscn_count) 6514 { 6515 int nodma; 6516 struct fcp_ipkt *icmd; 6517 struct fcp_tgt *ptgt; 6518 struct fcp_port *pptr; 6519 fc_frame_hdr_t *hp; 6520 fc_packet_t *fpkt; 6521 struct fcp_cmd fcp_cmd; 6522 struct fcp_cmd *fcmd; 6523 union scsi_cdb *scsi_cdb; 6524 6525 ASSERT(plun != NULL); 6526 6527 ptgt = plun->lun_tgt; 6528 ASSERT(ptgt != NULL); 6529 6530 pptr = ptgt->tgt_port; 6531 ASSERT(pptr != NULL); 6532 6533 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6534 fcp_trace, FCP_BUF_LEVEL_5, 0, 6535 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6536 6537 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6538 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6539 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6540 rscn_count); 6541 6542 if (icmd == NULL) { 6543 return (DDI_FAILURE); 6544 } 6545 6546 fpkt = icmd->ipkt_fpkt; 6547 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6548 icmd->ipkt_retries = 0; 6549 icmd->ipkt_opcode = opcode; 6550 icmd->ipkt_lun = plun; 6551 6552 if (nodma) { 6553 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6554 } else { 6555 fcmd = &fcp_cmd; 6556 } 6557 bzero(fcmd, sizeof (struct fcp_cmd)); 6558 6559 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6560 6561 hp = &fpkt->pkt_cmd_fhdr; 6562 6563 hp->s_id = pptr->port_id; 6564 hp->d_id = ptgt->tgt_d_id; 6565 hp->r_ctl = R_CTL_COMMAND; 6566 hp->type = FC_TYPE_SCSI_FCP; 6567 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6568 hp->rsvd = 0; 6569 hp->seq_id = 0; 6570 hp->seq_cnt = 0; 6571 hp->ox_id = 0xffff; 6572 hp->rx_id = 0xffff; 6573 hp->ro = 0; 6574 6575 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6576 6577 /* 6578 * Request SCSI target for expedited processing 6579 */ 6580 6581 /* 6582 * Set up for untagged queuing because we do not 6583 * know if the fibre device supports queuing. 6584 */ 6585 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6586 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6587 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6588 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6589 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6590 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6591 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6592 6593 switch (opcode) { 6594 case SCMD_INQUIRY_PAGE83: 6595 /* 6596 * Prepare to get the Inquiry VPD page 83 information 6597 */ 6598 fcmd->fcp_cntl.cntl_read_data = 1; 6599 fcmd->fcp_cntl.cntl_write_data = 0; 6600 fcmd->fcp_data_len = alloc_len; 6601 6602 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6603 fpkt->pkt_comp = fcp_scsi_callback; 6604 6605 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6606 scsi_cdb->g0_addr2 = 0x01; 6607 scsi_cdb->g0_addr1 = 0x83; 6608 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6609 break; 6610 6611 case SCMD_INQUIRY: 6612 fcmd->fcp_cntl.cntl_read_data = 1; 6613 fcmd->fcp_cntl.cntl_write_data = 0; 6614 fcmd->fcp_data_len = alloc_len; 6615 6616 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6617 fpkt->pkt_comp = fcp_scsi_callback; 6618 6619 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6620 scsi_cdb->g0_count0 = SUN_INQSIZE; 6621 break; 6622 6623 case SCMD_REPORT_LUN: { 6624 fc_portid_t d_id; 6625 opaque_t fca_dev; 6626 6627 ASSERT(alloc_len >= 16); 6628 6629 d_id.priv_lilp_posit = 0; 6630 d_id.port_id = ptgt->tgt_d_id; 6631 6632 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6633 6634 mutex_enter(&ptgt->tgt_mutex); 6635 ptgt->tgt_fca_dev = fca_dev; 6636 mutex_exit(&ptgt->tgt_mutex); 6637 6638 fcmd->fcp_cntl.cntl_read_data = 1; 6639 fcmd->fcp_cntl.cntl_write_data = 0; 6640 fcmd->fcp_data_len = alloc_len; 6641 6642 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6643 fpkt->pkt_comp = fcp_scsi_callback; 6644 6645 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6646 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6647 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6648 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6649 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6650 break; 6651 } 6652 6653 default: 6654 fcp_log(CE_WARN, pptr->port_dip, 6655 "!fcp_send_scsi Invalid opcode"); 6656 break; 6657 } 6658 6659 if (!nodma) { 6660 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6661 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6662 } 6663 6664 mutex_enter(&pptr->port_mutex); 6665 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6666 6667 mutex_exit(&pptr->port_mutex); 6668 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6669 FC_SUCCESS) { 6670 fcp_icmd_free(pptr, icmd); 6671 return (DDI_FAILURE); 6672 } 6673 return (DDI_SUCCESS); 6674 } else { 6675 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6676 fcp_trace, FCP_BUF_LEVEL_2, 0, 6677 "fcp_send_scsi,1: state change occured" 6678 " for D_ID=0x%x", ptgt->tgt_d_id); 6679 mutex_exit(&pptr->port_mutex); 6680 fcp_icmd_free(pptr, icmd); 6681 return (DDI_FAILURE); 6682 } 6683 } 6684 6685 6686 /* 6687 * called by fcp_scsi_callback to check to handle the case where 6688 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6689 */ 6690 static int 6691 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6692 { 6693 uchar_t rqlen; 6694 int rval = DDI_FAILURE; 6695 struct scsi_extended_sense sense_info, *sense; 6696 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6697 fpkt->pkt_ulp_private; 6698 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6699 struct fcp_port *pptr = ptgt->tgt_port; 6700 6701 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6702 6703 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6704 /* 6705 * SCSI-II Reserve Release support. Some older FC drives return 6706 * Reservation conflict for Report Luns command. 6707 */ 6708 if (icmd->ipkt_nodma) { 6709 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6710 rsp->fcp_u.fcp_status.sense_len_set = 0; 6711 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6712 } else { 6713 fcp_rsp_t new_resp; 6714 6715 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6716 fpkt->pkt_resp_acc, sizeof (new_resp)); 6717 6718 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6719 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6720 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6721 6722 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6723 fpkt->pkt_resp_acc, sizeof (new_resp)); 6724 } 6725 6726 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6727 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6728 6729 return (DDI_SUCCESS); 6730 } 6731 6732 sense = &sense_info; 6733 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6734 /* no need to continue if sense length is not set */ 6735 return (rval); 6736 } 6737 6738 /* casting 64-bit integer to 8-bit */ 6739 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6740 sizeof (struct scsi_extended_sense)); 6741 6742 if (rqlen < 14) { 6743 /* no need to continue if request length isn't long enough */ 6744 return (rval); 6745 } 6746 6747 if (icmd->ipkt_nodma) { 6748 /* 6749 * We can safely use fcp_response_len here since the 6750 * only path that calls fcp_check_reportlun, 6751 * fcp_scsi_callback, has already called 6752 * fcp_validate_fcp_response. 6753 */ 6754 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6755 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6756 } else { 6757 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6758 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6759 sizeof (struct scsi_extended_sense)); 6760 } 6761 6762 if (!FCP_SENSE_NO_LUN(sense)) { 6763 mutex_enter(&ptgt->tgt_mutex); 6764 /* clear the flag if any */ 6765 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6766 mutex_exit(&ptgt->tgt_mutex); 6767 } 6768 6769 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6770 (sense->es_add_code == 0x20)) { 6771 if (icmd->ipkt_nodma) { 6772 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6773 rsp->fcp_u.fcp_status.sense_len_set = 0; 6774 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6775 } else { 6776 fcp_rsp_t new_resp; 6777 6778 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6779 fpkt->pkt_resp_acc, sizeof (new_resp)); 6780 6781 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6782 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6783 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6784 6785 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6786 fpkt->pkt_resp_acc, sizeof (new_resp)); 6787 } 6788 6789 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6790 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6791 6792 return (DDI_SUCCESS); 6793 } 6794 6795 /* 6796 * This is for the STK library which returns a check condition, 6797 * to indicate device is not ready, manual assistance needed. 6798 * This is to a report lun command when the door is open. 6799 */ 6800 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6801 if (icmd->ipkt_nodma) { 6802 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6803 rsp->fcp_u.fcp_status.sense_len_set = 0; 6804 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6805 } else { 6806 fcp_rsp_t new_resp; 6807 6808 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6809 fpkt->pkt_resp_acc, sizeof (new_resp)); 6810 6811 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6812 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6813 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6814 6815 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6816 fpkt->pkt_resp_acc, sizeof (new_resp)); 6817 } 6818 6819 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6820 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6821 6822 return (DDI_SUCCESS); 6823 } 6824 6825 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6826 (FCP_SENSE_NO_LUN(sense))) { 6827 mutex_enter(&ptgt->tgt_mutex); 6828 if ((FCP_SENSE_NO_LUN(sense)) && 6829 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6830 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6831 mutex_exit(&ptgt->tgt_mutex); 6832 /* 6833 * reconfig was triggred by ILLEGAL REQUEST but 6834 * got ILLEGAL REQUEST again 6835 */ 6836 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6837 fcp_trace, FCP_BUF_LEVEL_3, 0, 6838 "!FCP: Unable to obtain Report Lun data" 6839 " target=%x", ptgt->tgt_d_id); 6840 } else { 6841 if (ptgt->tgt_tid == NULL) { 6842 timeout_id_t tid; 6843 /* 6844 * REPORT LUN data has changed. Kick off 6845 * rediscovery 6846 */ 6847 tid = timeout(fcp_reconfigure_luns, 6848 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6849 6850 ptgt->tgt_tid = tid; 6851 ptgt->tgt_state |= FCP_TGT_BUSY; 6852 } 6853 if (FCP_SENSE_NO_LUN(sense)) { 6854 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6855 } 6856 mutex_exit(&ptgt->tgt_mutex); 6857 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6858 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6859 fcp_trace, FCP_BUF_LEVEL_3, 0, 6860 "!FCP:Report Lun Has Changed" 6861 " target=%x", ptgt->tgt_d_id); 6862 } else if (FCP_SENSE_NO_LUN(sense)) { 6863 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6864 fcp_trace, FCP_BUF_LEVEL_3, 0, 6865 "!FCP:LU Not Supported" 6866 " target=%x", ptgt->tgt_d_id); 6867 } 6868 } 6869 rval = DDI_SUCCESS; 6870 } 6871 6872 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6873 fcp_trace, FCP_BUF_LEVEL_5, 0, 6874 "D_ID=%x, sense=%x, status=%x", 6875 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6876 rsp->fcp_u.fcp_status.scsi_status); 6877 6878 return (rval); 6879 } 6880 6881 /* 6882 * Function: fcp_scsi_callback 6883 * 6884 * Description: This is the callback routine set by fcp_send_scsi() after 6885 * it calls fcp_icmd_alloc(). The SCSI command completed here 6886 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6887 * INQUIRY_PAGE83. 6888 * 6889 * Argument: *fpkt FC packet used to convey the command 6890 * 6891 * Return Value: None 6892 */ 6893 static void 6894 fcp_scsi_callback(fc_packet_t *fpkt) 6895 { 6896 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6897 fpkt->pkt_ulp_private; 6898 struct fcp_rsp_info fcp_rsp_err, *bep; 6899 struct fcp_port *pptr; 6900 struct fcp_tgt *ptgt; 6901 struct fcp_lun *plun; 6902 struct fcp_rsp response, *rsp; 6903 6904 ptgt = icmd->ipkt_tgt; 6905 pptr = ptgt->tgt_port; 6906 plun = icmd->ipkt_lun; 6907 6908 if (icmd->ipkt_nodma) { 6909 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6910 } else { 6911 rsp = &response; 6912 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6913 sizeof (struct fcp_rsp)); 6914 } 6915 6916 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6917 fcp_trace, FCP_BUF_LEVEL_2, 0, 6918 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6919 "status=%x, lun num=%x", 6920 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6921 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6922 6923 /* 6924 * Pre-init LUN GUID with NWWN if it is not a device that 6925 * supports multiple luns and we know it's not page83 6926 * compliant. Although using a NWWN is not lun unique, 6927 * we will be fine since there is only one lun behind the taget 6928 * in this case. 6929 */ 6930 if ((plun->lun_guid_size == 0) && 6931 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6932 (fcp_symmetric_device_probe(plun) == 0)) { 6933 6934 char ascii_wwn[FC_WWN_SIZE*2+1]; 6935 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6936 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6937 } 6938 6939 /* 6940 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6941 * when thay have more data than what is asked in CDB. An overrun 6942 * is really when FCP_DL is smaller than the data length in CDB. 6943 * In the case here we know that REPORT LUN command we formed within 6944 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6945 * behavior. In reality this is FC_SUCCESS. 6946 */ 6947 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6948 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6949 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6950 fpkt->pkt_state = FC_PKT_SUCCESS; 6951 } 6952 6953 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6954 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6955 fcp_trace, FCP_BUF_LEVEL_2, 0, 6956 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6957 ptgt->tgt_d_id); 6958 6959 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6960 /* 6961 * Inquiry VPD page command on A5K SES devices would 6962 * result in data CRC errors. 6963 */ 6964 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6965 (void) fcp_handle_page83(fpkt, icmd, 1); 6966 return; 6967 } 6968 } 6969 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6970 FCP_MUST_RETRY(fpkt)) { 6971 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6972 fcp_retry_scsi_cmd(fpkt); 6973 return; 6974 } 6975 6976 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6977 FCP_TGT_TRACE_20); 6978 6979 mutex_enter(&pptr->port_mutex); 6980 mutex_enter(&ptgt->tgt_mutex); 6981 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6982 mutex_exit(&ptgt->tgt_mutex); 6983 mutex_exit(&pptr->port_mutex); 6984 fcp_print_error(fpkt); 6985 } else { 6986 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6987 fcp_trace, FCP_BUF_LEVEL_2, 0, 6988 "fcp_scsi_callback,1: 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 } 6993 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6994 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6995 fcp_icmd_free(pptr, icmd); 6996 return; 6997 } 6998 6999 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 7000 7001 mutex_enter(&pptr->port_mutex); 7002 mutex_enter(&ptgt->tgt_mutex); 7003 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7004 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7005 fcp_trace, FCP_BUF_LEVEL_2, 0, 7006 "fcp_scsi_callback,2: state change occured" 7007 " for D_ID=0x%x", ptgt->tgt_d_id); 7008 mutex_exit(&ptgt->tgt_mutex); 7009 mutex_exit(&pptr->port_mutex); 7010 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7011 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7012 fcp_icmd_free(pptr, icmd); 7013 return; 7014 } 7015 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7016 7017 mutex_exit(&ptgt->tgt_mutex); 7018 mutex_exit(&pptr->port_mutex); 7019 7020 if (icmd->ipkt_nodma) { 7021 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7022 sizeof (struct fcp_rsp)); 7023 } else { 7024 bep = &fcp_rsp_err; 7025 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7026 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7027 } 7028 7029 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7030 fcp_retry_scsi_cmd(fpkt); 7031 return; 7032 } 7033 7034 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7035 FCP_NO_FAILURE) { 7036 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7037 fcp_trace, FCP_BUF_LEVEL_2, 0, 7038 "rsp_code=0x%x, rsp_len_set=0x%x", 7039 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7040 fcp_retry_scsi_cmd(fpkt); 7041 return; 7042 } 7043 7044 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7045 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7046 fcp_queue_ipkt(pptr, fpkt); 7047 return; 7048 } 7049 7050 /* 7051 * Devices that do not support INQUIRY_PAGE83, return check condition 7052 * with illegal request as per SCSI spec. 7053 * Crossbridge is one such device and Daktari's SES node is another. 7054 * We want to ideally enumerate these devices as a non-mpxio devices. 7055 * SES nodes (Daktari only currently) are an exception to this. 7056 */ 7057 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7058 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7059 7060 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7061 fcp_trace, FCP_BUF_LEVEL_3, 0, 7062 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7063 "check condition. May enumerate as non-mpxio device", 7064 ptgt->tgt_d_id, plun->lun_type); 7065 7066 /* 7067 * If we let Daktari's SES be enumerated as a non-mpxio 7068 * device, there will be a discrepency in that the other 7069 * internal FC disks will get enumerated as mpxio devices. 7070 * Applications like luxadm expect this to be consistent. 7071 * 7072 * So, we put in a hack here to check if this is an SES device 7073 * and handle it here. 7074 */ 7075 if (plun->lun_type == DTYPE_ESI) { 7076 /* 7077 * Since, pkt_state is actually FC_PKT_SUCCESS 7078 * at this stage, we fake a failure here so that 7079 * fcp_handle_page83 will create a device path using 7080 * the WWN instead of the GUID which is not there anyway 7081 */ 7082 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7083 (void) fcp_handle_page83(fpkt, icmd, 1); 7084 return; 7085 } 7086 7087 mutex_enter(&ptgt->tgt_mutex); 7088 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7089 FCP_LUN_MARK | FCP_LUN_BUSY); 7090 mutex_exit(&ptgt->tgt_mutex); 7091 7092 (void) fcp_call_finish_init(pptr, ptgt, 7093 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7094 icmd->ipkt_cause); 7095 fcp_icmd_free(pptr, icmd); 7096 return; 7097 } 7098 7099 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7100 int rval = DDI_FAILURE; 7101 7102 /* 7103 * handle cases where report lun isn't supported 7104 * by faking up our own REPORT_LUN response or 7105 * UNIT ATTENTION 7106 */ 7107 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7108 rval = fcp_check_reportlun(rsp, fpkt); 7109 7110 /* 7111 * fcp_check_reportlun might have modified the 7112 * FCP response. Copy it in again to get an updated 7113 * FCP response 7114 */ 7115 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7116 rsp = &response; 7117 7118 FCP_CP_IN(fpkt->pkt_resp, rsp, 7119 fpkt->pkt_resp_acc, 7120 sizeof (struct fcp_rsp)); 7121 } 7122 } 7123 7124 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7125 if (rval == DDI_SUCCESS) { 7126 (void) fcp_call_finish_init(pptr, ptgt, 7127 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7128 icmd->ipkt_cause); 7129 fcp_icmd_free(pptr, icmd); 7130 } else { 7131 fcp_retry_scsi_cmd(fpkt); 7132 } 7133 7134 return; 7135 } 7136 } else { 7137 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7138 mutex_enter(&ptgt->tgt_mutex); 7139 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7140 mutex_exit(&ptgt->tgt_mutex); 7141 } 7142 } 7143 7144 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7145 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7146 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7147 DDI_DMA_SYNC_FORCPU); 7148 } 7149 7150 switch (icmd->ipkt_opcode) { 7151 case SCMD_INQUIRY: 7152 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7153 fcp_handle_inquiry(fpkt, icmd); 7154 break; 7155 7156 case SCMD_REPORT_LUN: 7157 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7158 FCP_TGT_TRACE_22); 7159 fcp_handle_reportlun(fpkt, icmd); 7160 break; 7161 7162 case SCMD_INQUIRY_PAGE83: 7163 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7164 (void) fcp_handle_page83(fpkt, icmd, 0); 7165 break; 7166 7167 default: 7168 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7169 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7170 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7171 fcp_icmd_free(pptr, icmd); 7172 break; 7173 } 7174 } 7175 7176 7177 static void 7178 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7179 { 7180 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7181 fpkt->pkt_ulp_private; 7182 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7183 struct fcp_port *pptr = ptgt->tgt_port; 7184 7185 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7186 fcp_is_retryable(icmd)) { 7187 mutex_enter(&pptr->port_mutex); 7188 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7189 mutex_exit(&pptr->port_mutex); 7190 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7191 fcp_trace, FCP_BUF_LEVEL_3, 0, 7192 "Retrying %s to %x; state=%x, reason=%x", 7193 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7194 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7195 fpkt->pkt_state, fpkt->pkt_reason); 7196 7197 fcp_queue_ipkt(pptr, fpkt); 7198 } else { 7199 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7200 fcp_trace, FCP_BUF_LEVEL_3, 0, 7201 "fcp_retry_scsi_cmd,1: state change occured" 7202 " for D_ID=0x%x", ptgt->tgt_d_id); 7203 mutex_exit(&pptr->port_mutex); 7204 (void) fcp_call_finish_init(pptr, ptgt, 7205 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7206 icmd->ipkt_cause); 7207 fcp_icmd_free(pptr, icmd); 7208 } 7209 } else { 7210 fcp_print_error(fpkt); 7211 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7212 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7213 fcp_icmd_free(pptr, icmd); 7214 } 7215 } 7216 7217 /* 7218 * Function: fcp_handle_page83 7219 * 7220 * Description: Treats the response to INQUIRY_PAGE83. 7221 * 7222 * Argument: *fpkt FC packet used to convey the command. 7223 * *icmd Original fcp_ipkt structure. 7224 * ignore_page83_data 7225 * if it's 1, that means it's a special devices's 7226 * page83 response, it should be enumerated under mpxio 7227 * 7228 * Return Value: None 7229 */ 7230 static void 7231 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7232 int ignore_page83_data) 7233 { 7234 struct fcp_port *pptr; 7235 struct fcp_lun *plun; 7236 struct fcp_tgt *ptgt; 7237 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7238 int fail = 0; 7239 ddi_devid_t devid; 7240 char *guid = NULL; 7241 int ret; 7242 7243 ASSERT(icmd != NULL && fpkt != NULL); 7244 7245 pptr = icmd->ipkt_port; 7246 ptgt = icmd->ipkt_tgt; 7247 plun = icmd->ipkt_lun; 7248 7249 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7250 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7251 7252 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7253 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7254 7255 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7256 fcp_trace, FCP_BUF_LEVEL_5, 0, 7257 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7258 "dtype=0x%x, lun num=%x", 7259 pptr->port_instance, ptgt->tgt_d_id, 7260 dev_id_page[0], plun->lun_num); 7261 7262 ret = ddi_devid_scsi_encode( 7263 DEVID_SCSI_ENCODE_VERSION_LATEST, 7264 NULL, /* driver name */ 7265 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7266 sizeof (plun->lun_inq), /* size of standard inquiry */ 7267 NULL, /* page 80 data */ 7268 0, /* page 80 len */ 7269 dev_id_page, /* page 83 data */ 7270 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7271 &devid); 7272 7273 if (ret == DDI_SUCCESS) { 7274 7275 guid = ddi_devid_to_guid(devid); 7276 7277 if (guid) { 7278 /* 7279 * Check our current guid. If it's non null 7280 * and it has changed, we need to copy it into 7281 * lun_old_guid since we might still need it. 7282 */ 7283 if (plun->lun_guid && 7284 strcmp(guid, plun->lun_guid)) { 7285 unsigned int len; 7286 7287 /* 7288 * If the guid of the LUN changes, 7289 * reconfiguration should be triggered 7290 * to reflect the changes. 7291 * i.e. we should offline the LUN with 7292 * the old guid, and online the LUN with 7293 * the new guid. 7294 */ 7295 plun->lun_state |= FCP_LUN_CHANGED; 7296 7297 if (plun->lun_old_guid) { 7298 kmem_free(plun->lun_old_guid, 7299 plun->lun_old_guid_size); 7300 } 7301 7302 len = plun->lun_guid_size; 7303 plun->lun_old_guid_size = len; 7304 7305 plun->lun_old_guid = kmem_zalloc(len, 7306 KM_NOSLEEP); 7307 7308 if (plun->lun_old_guid) { 7309 /* 7310 * The alloc was successful then 7311 * let's do the copy. 7312 */ 7313 bcopy(plun->lun_guid, 7314 plun->lun_old_guid, len); 7315 } else { 7316 fail = 1; 7317 plun->lun_old_guid_size = 0; 7318 } 7319 } 7320 if (!fail) { 7321 if (fcp_copy_guid_2_lun_block( 7322 plun, guid)) { 7323 fail = 1; 7324 } 7325 } 7326 ddi_devid_free_guid(guid); 7327 7328 } else { 7329 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7330 fcp_trace, FCP_BUF_LEVEL_2, 0, 7331 "fcp_handle_page83: unable to create " 7332 "GUID"); 7333 7334 /* couldn't create good guid from devid */ 7335 fail = 1; 7336 } 7337 ddi_devid_free(devid); 7338 7339 } else if (ret == DDI_NOT_WELL_FORMED) { 7340 /* NULL filled data for page 83 */ 7341 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7342 fcp_trace, FCP_BUF_LEVEL_2, 0, 7343 "fcp_handle_page83: retry GUID"); 7344 7345 icmd->ipkt_retries = 0; 7346 fcp_retry_scsi_cmd(fpkt); 7347 return; 7348 } else { 7349 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7350 fcp_trace, FCP_BUF_LEVEL_2, 0, 7351 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7352 ret); 7353 /* 7354 * Since the page83 validation 7355 * introduced late, we are being 7356 * tolerant to the existing devices 7357 * that already found to be working 7358 * under mpxio, like A5200's SES device, 7359 * its page83 response will not be standard-compliant, 7360 * but we still want it to be enumerated under mpxio. 7361 */ 7362 if (fcp_symmetric_device_probe(plun) != 0) { 7363 fail = 1; 7364 } 7365 } 7366 7367 } else { 7368 /* bad packet state */ 7369 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7370 7371 /* 7372 * For some special devices (A5K SES and Daktari's SES devices), 7373 * they should be enumerated under mpxio 7374 * or "luxadm dis" will fail 7375 */ 7376 if (ignore_page83_data) { 7377 fail = 0; 7378 } else { 7379 fail = 1; 7380 } 7381 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7382 fcp_trace, FCP_BUF_LEVEL_2, 0, 7383 "!Devid page cmd failed. " 7384 "fpkt_state: %x fpkt_reason: %x", 7385 "ignore_page83: %d", 7386 fpkt->pkt_state, fpkt->pkt_reason, 7387 ignore_page83_data); 7388 } 7389 7390 mutex_enter(&pptr->port_mutex); 7391 mutex_enter(&plun->lun_mutex); 7392 /* 7393 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7394 * mismatch between lun_cip and lun_mpxio. 7395 */ 7396 if (plun->lun_cip == NULL) { 7397 /* 7398 * If we don't have a guid for this lun it's because we were 7399 * unable to glean one from the page 83 response. Set the 7400 * control flag to 0 here to make sure that we don't attempt to 7401 * enumerate it under mpxio. 7402 */ 7403 if (fail || pptr->port_mpxio == 0) { 7404 plun->lun_mpxio = 0; 7405 } else { 7406 plun->lun_mpxio = 1; 7407 } 7408 } 7409 mutex_exit(&plun->lun_mutex); 7410 mutex_exit(&pptr->port_mutex); 7411 7412 mutex_enter(&ptgt->tgt_mutex); 7413 plun->lun_state &= 7414 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7415 mutex_exit(&ptgt->tgt_mutex); 7416 7417 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7418 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7419 7420 fcp_icmd_free(pptr, icmd); 7421 } 7422 7423 /* 7424 * Function: fcp_handle_inquiry 7425 * 7426 * Description: Called by fcp_scsi_callback to handle the response to an 7427 * INQUIRY request. 7428 * 7429 * Argument: *fpkt FC packet used to convey the command. 7430 * *icmd Original fcp_ipkt structure. 7431 * 7432 * Return Value: None 7433 */ 7434 static void 7435 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7436 { 7437 struct fcp_port *pptr; 7438 struct fcp_lun *plun; 7439 struct fcp_tgt *ptgt; 7440 uchar_t dtype; 7441 uchar_t pqual; 7442 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7443 7444 ASSERT(icmd != NULL && fpkt != NULL); 7445 7446 pptr = icmd->ipkt_port; 7447 ptgt = icmd->ipkt_tgt; 7448 plun = icmd->ipkt_lun; 7449 7450 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7451 sizeof (struct scsi_inquiry)); 7452 7453 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7454 pqual = plun->lun_inq.inq_dtype >> 5; 7455 7456 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7457 fcp_trace, FCP_BUF_LEVEL_5, 0, 7458 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7459 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7460 plun->lun_num, dtype, pqual); 7461 7462 if (pqual != 0) { 7463 /* 7464 * Non-zero peripheral qualifier 7465 */ 7466 fcp_log(CE_CONT, pptr->port_dip, 7467 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7468 "Device type=0x%x Peripheral qual=0x%x\n", 7469 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7470 7471 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7472 fcp_trace, FCP_BUF_LEVEL_5, 0, 7473 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7474 "Device type=0x%x Peripheral qual=0x%x\n", 7475 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7476 7477 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7478 7479 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7480 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7481 fcp_icmd_free(pptr, icmd); 7482 return; 7483 } 7484 7485 /* 7486 * If the device is already initialized, check the dtype 7487 * for a change. If it has changed then update the flags 7488 * so the create_luns will offline the old device and 7489 * create the new device. Refer to bug: 4764752 7490 */ 7491 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7492 plun->lun_state |= FCP_LUN_CHANGED; 7493 } 7494 plun->lun_type = plun->lun_inq.inq_dtype; 7495 7496 /* 7497 * This code is setting/initializing the throttling in the FCA 7498 * driver. 7499 */ 7500 mutex_enter(&pptr->port_mutex); 7501 if (!pptr->port_notify) { 7502 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7503 uint32_t cmd = 0; 7504 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7505 ((cmd & 0xFFFFFF00 >> 8) | 7506 FCP_SVE_THROTTLE << 8)); 7507 pptr->port_notify = 1; 7508 mutex_exit(&pptr->port_mutex); 7509 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7510 mutex_enter(&pptr->port_mutex); 7511 } 7512 } 7513 7514 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7515 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7516 fcp_trace, FCP_BUF_LEVEL_2, 0, 7517 "fcp_handle_inquiry,1:state change occured" 7518 " for D_ID=0x%x", ptgt->tgt_d_id); 7519 mutex_exit(&pptr->port_mutex); 7520 7521 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7522 (void) fcp_call_finish_init(pptr, ptgt, 7523 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7524 icmd->ipkt_cause); 7525 fcp_icmd_free(pptr, icmd); 7526 return; 7527 } 7528 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7529 mutex_exit(&pptr->port_mutex); 7530 7531 /* Retrieve the rscn count (if a valid one exists) */ 7532 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7533 rscn_count = ((fc_ulp_rscn_info_t *) 7534 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7535 } else { 7536 rscn_count = FC_INVALID_RSCN_COUNT; 7537 } 7538 7539 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7540 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7541 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7542 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7543 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7544 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7545 (void) fcp_call_finish_init(pptr, ptgt, 7546 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7547 icmd->ipkt_cause); 7548 } 7549 7550 /* 7551 * Read Inquiry VPD Page 0x83 to uniquely 7552 * identify this logical unit. 7553 */ 7554 fcp_icmd_free(pptr, icmd); 7555 } 7556 7557 /* 7558 * Function: fcp_handle_reportlun 7559 * 7560 * Description: Called by fcp_scsi_callback to handle the response to a 7561 * REPORT_LUN request. 7562 * 7563 * Argument: *fpkt FC packet used to convey the command. 7564 * *icmd Original fcp_ipkt structure. 7565 * 7566 * Return Value: None 7567 */ 7568 static void 7569 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7570 { 7571 int i; 7572 int nluns_claimed; 7573 int nluns_bufmax; 7574 int len; 7575 uint16_t lun_num; 7576 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7577 struct fcp_port *pptr; 7578 struct fcp_tgt *ptgt; 7579 struct fcp_lun *plun; 7580 struct fcp_reportlun_resp *report_lun; 7581 7582 pptr = icmd->ipkt_port; 7583 ptgt = icmd->ipkt_tgt; 7584 len = fpkt->pkt_datalen; 7585 7586 if ((len < FCP_LUN_HEADER) || 7587 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7588 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7589 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7590 fcp_icmd_free(pptr, icmd); 7591 return; 7592 } 7593 7594 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7595 fpkt->pkt_datalen); 7596 7597 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7598 fcp_trace, FCP_BUF_LEVEL_5, 0, 7599 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7600 pptr->port_instance, ptgt->tgt_d_id); 7601 7602 /* 7603 * Get the number of luns (which is supplied as LUNS * 8) the 7604 * device claims it has. 7605 */ 7606 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7607 7608 /* 7609 * Get the maximum number of luns the buffer submitted can hold. 7610 */ 7611 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7612 7613 /* 7614 * Due to limitations of certain hardware, we support only 16 bit LUNs 7615 */ 7616 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7617 kmem_free(report_lun, len); 7618 7619 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7620 " 0x%x number of LUNs for target=%x", nluns_claimed, 7621 ptgt->tgt_d_id); 7622 7623 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7624 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7625 fcp_icmd_free(pptr, icmd); 7626 return; 7627 } 7628 7629 /* 7630 * If there are more LUNs than we have allocated memory for, 7631 * allocate more space and send down yet another report lun if 7632 * the maximum number of attempts hasn't been reached. 7633 */ 7634 mutex_enter(&ptgt->tgt_mutex); 7635 7636 if ((nluns_claimed > nluns_bufmax) && 7637 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7638 7639 struct fcp_lun *plun; 7640 7641 ptgt->tgt_report_lun_cnt++; 7642 plun = ptgt->tgt_lun; 7643 ASSERT(plun != NULL); 7644 mutex_exit(&ptgt->tgt_mutex); 7645 7646 kmem_free(report_lun, len); 7647 7648 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7649 fcp_trace, FCP_BUF_LEVEL_5, 0, 7650 "!Dynamically discovered %d LUNs for D_ID=%x", 7651 nluns_claimed, ptgt->tgt_d_id); 7652 7653 /* Retrieve the rscn count (if a valid one exists) */ 7654 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7655 rscn_count = ((fc_ulp_rscn_info_t *) 7656 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7657 ulp_rscn_count; 7658 } else { 7659 rscn_count = FC_INVALID_RSCN_COUNT; 7660 } 7661 7662 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7663 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7664 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7665 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7666 (void) fcp_call_finish_init(pptr, ptgt, 7667 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7668 icmd->ipkt_cause); 7669 } 7670 7671 fcp_icmd_free(pptr, icmd); 7672 return; 7673 } 7674 7675 if (nluns_claimed > nluns_bufmax) { 7676 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7677 fcp_trace, FCP_BUF_LEVEL_5, 0, 7678 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7679 " Number of LUNs lost=%x", 7680 ptgt->tgt_port_wwn.raw_wwn[0], 7681 ptgt->tgt_port_wwn.raw_wwn[1], 7682 ptgt->tgt_port_wwn.raw_wwn[2], 7683 ptgt->tgt_port_wwn.raw_wwn[3], 7684 ptgt->tgt_port_wwn.raw_wwn[4], 7685 ptgt->tgt_port_wwn.raw_wwn[5], 7686 ptgt->tgt_port_wwn.raw_wwn[6], 7687 ptgt->tgt_port_wwn.raw_wwn[7], 7688 nluns_claimed - nluns_bufmax); 7689 7690 nluns_claimed = nluns_bufmax; 7691 } 7692 ptgt->tgt_lun_cnt = nluns_claimed; 7693 7694 /* 7695 * Identify missing LUNs and print warning messages 7696 */ 7697 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7698 int offline; 7699 int exists = 0; 7700 7701 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7702 7703 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7704 uchar_t *lun_string; 7705 7706 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7707 7708 switch (lun_string[0] & 0xC0) { 7709 case FCP_LUN_ADDRESSING: 7710 case FCP_PD_ADDRESSING: 7711 case FCP_VOLUME_ADDRESSING: 7712 lun_num = ((lun_string[0] & 0x3F) << 8) | 7713 lun_string[1]; 7714 if (plun->lun_num == lun_num) { 7715 exists++; 7716 break; 7717 } 7718 break; 7719 7720 default: 7721 break; 7722 } 7723 } 7724 7725 if (!exists && !offline) { 7726 mutex_exit(&ptgt->tgt_mutex); 7727 7728 mutex_enter(&pptr->port_mutex); 7729 mutex_enter(&ptgt->tgt_mutex); 7730 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7731 /* 7732 * set disappear flag when device was connected 7733 */ 7734 if (!(plun->lun_state & 7735 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7736 plun->lun_state |= FCP_LUN_DISAPPEARED; 7737 } 7738 mutex_exit(&ptgt->tgt_mutex); 7739 mutex_exit(&pptr->port_mutex); 7740 if (!(plun->lun_state & 7741 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7742 fcp_log(CE_NOTE, pptr->port_dip, 7743 "!Lun=%x for target=%x disappeared", 7744 plun->lun_num, ptgt->tgt_d_id); 7745 } 7746 mutex_enter(&ptgt->tgt_mutex); 7747 } else { 7748 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7749 fcp_trace, FCP_BUF_LEVEL_5, 0, 7750 "fcp_handle_reportlun,1: state change" 7751 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7752 mutex_exit(&ptgt->tgt_mutex); 7753 mutex_exit(&pptr->port_mutex); 7754 kmem_free(report_lun, len); 7755 (void) fcp_call_finish_init(pptr, ptgt, 7756 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7757 icmd->ipkt_cause); 7758 fcp_icmd_free(pptr, icmd); 7759 return; 7760 } 7761 } else if (exists) { 7762 /* 7763 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7764 * actually exists in REPORT_LUN response 7765 */ 7766 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7767 plun->lun_state &= 7768 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7769 } 7770 if (offline || plun->lun_num == 0) { 7771 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7772 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7773 mutex_exit(&ptgt->tgt_mutex); 7774 fcp_log(CE_NOTE, pptr->port_dip, 7775 "!Lun=%x for target=%x reappeared", 7776 plun->lun_num, ptgt->tgt_d_id); 7777 mutex_enter(&ptgt->tgt_mutex); 7778 } 7779 } 7780 } 7781 } 7782 7783 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7784 mutex_exit(&ptgt->tgt_mutex); 7785 7786 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7787 fcp_trace, FCP_BUF_LEVEL_5, 0, 7788 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7789 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7790 7791 /* scan each lun */ 7792 for (i = 0; i < nluns_claimed; i++) { 7793 uchar_t *lun_string; 7794 7795 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7796 7797 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7798 fcp_trace, FCP_BUF_LEVEL_5, 0, 7799 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7800 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7801 lun_string[0]); 7802 7803 switch (lun_string[0] & 0xC0) { 7804 case FCP_LUN_ADDRESSING: 7805 case FCP_PD_ADDRESSING: 7806 case FCP_VOLUME_ADDRESSING: 7807 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7808 7809 /* We will skip masked LUNs because of the blacklist. */ 7810 if (fcp_lun_blacklist != NULL) { 7811 mutex_enter(&ptgt->tgt_mutex); 7812 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7813 lun_num) == TRUE) { 7814 ptgt->tgt_lun_cnt--; 7815 mutex_exit(&ptgt->tgt_mutex); 7816 break; 7817 } 7818 mutex_exit(&ptgt->tgt_mutex); 7819 } 7820 7821 /* see if this LUN is already allocated */ 7822 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7823 plun = fcp_alloc_lun(ptgt); 7824 if (plun == NULL) { 7825 fcp_log(CE_NOTE, pptr->port_dip, 7826 "!Lun allocation failed" 7827 " target=%x lun=%x", 7828 ptgt->tgt_d_id, lun_num); 7829 break; 7830 } 7831 } 7832 7833 mutex_enter(&plun->lun_tgt->tgt_mutex); 7834 /* convert to LUN */ 7835 plun->lun_addr.ent_addr_0 = 7836 BE_16(*(uint16_t *)&(lun_string[0])); 7837 plun->lun_addr.ent_addr_1 = 7838 BE_16(*(uint16_t *)&(lun_string[2])); 7839 plun->lun_addr.ent_addr_2 = 7840 BE_16(*(uint16_t *)&(lun_string[4])); 7841 plun->lun_addr.ent_addr_3 = 7842 BE_16(*(uint16_t *)&(lun_string[6])); 7843 7844 plun->lun_num = lun_num; 7845 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7846 plun->lun_state &= ~FCP_LUN_OFFLINE; 7847 mutex_exit(&plun->lun_tgt->tgt_mutex); 7848 7849 /* Retrieve the rscn count (if a valid one exists) */ 7850 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7851 rscn_count = ((fc_ulp_rscn_info_t *) 7852 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7853 ulp_rscn_count; 7854 } else { 7855 rscn_count = FC_INVALID_RSCN_COUNT; 7856 } 7857 7858 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7859 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7860 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7861 mutex_enter(&pptr->port_mutex); 7862 mutex_enter(&plun->lun_tgt->tgt_mutex); 7863 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7864 fcp_log(CE_NOTE, pptr->port_dip, 7865 "!failed to send INQUIRY" 7866 " target=%x lun=%x", 7867 ptgt->tgt_d_id, plun->lun_num); 7868 } else { 7869 FCP_TRACE(fcp_logq, 7870 pptr->port_instbuf, fcp_trace, 7871 FCP_BUF_LEVEL_5, 0, 7872 "fcp_handle_reportlun,2: state" 7873 " change occured for D_ID=0x%x", 7874 ptgt->tgt_d_id); 7875 } 7876 mutex_exit(&plun->lun_tgt->tgt_mutex); 7877 mutex_exit(&pptr->port_mutex); 7878 } else { 7879 continue; 7880 } 7881 break; 7882 7883 default: 7884 fcp_log(CE_WARN, NULL, 7885 "!Unsupported LUN Addressing method %x " 7886 "in response to REPORT_LUN", lun_string[0]); 7887 break; 7888 } 7889 7890 /* 7891 * each time through this loop we should decrement 7892 * the tmp_cnt by one -- since we go through this loop 7893 * one time for each LUN, the tmp_cnt should never be <=0 7894 */ 7895 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7896 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7897 } 7898 7899 if (i == 0) { 7900 fcp_log(CE_WARN, pptr->port_dip, 7901 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7902 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7903 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7904 } 7905 7906 kmem_free(report_lun, len); 7907 fcp_icmd_free(pptr, icmd); 7908 } 7909 7910 7911 /* 7912 * called internally to return a LUN given a target and a LUN number 7913 */ 7914 static struct fcp_lun * 7915 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7916 { 7917 struct fcp_lun *plun; 7918 7919 mutex_enter(&ptgt->tgt_mutex); 7920 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7921 if (plun->lun_num == lun_num) { 7922 mutex_exit(&ptgt->tgt_mutex); 7923 return (plun); 7924 } 7925 } 7926 mutex_exit(&ptgt->tgt_mutex); 7927 7928 return (NULL); 7929 } 7930 7931 7932 /* 7933 * handle finishing one target for fcp_finish_init 7934 * 7935 * return true (non-zero) if we want finish_init to continue with the 7936 * next target 7937 * 7938 * called with the port mutex held 7939 */ 7940 /*ARGSUSED*/ 7941 static int 7942 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7943 int link_cnt, int tgt_cnt, int cause) 7944 { 7945 int rval = 1; 7946 ASSERT(pptr != NULL); 7947 ASSERT(ptgt != NULL); 7948 7949 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7950 fcp_trace, FCP_BUF_LEVEL_5, 0, 7951 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7952 ptgt->tgt_state); 7953 7954 ASSERT(mutex_owned(&pptr->port_mutex)); 7955 7956 if ((pptr->port_link_cnt != link_cnt) || 7957 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7958 /* 7959 * oh oh -- another link reset or target change 7960 * must have occurred while we are in here 7961 */ 7962 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7963 7964 return (0); 7965 } else { 7966 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7967 } 7968 7969 mutex_enter(&ptgt->tgt_mutex); 7970 7971 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7972 /* 7973 * tgt is not offline -- is it marked (i.e. needs 7974 * to be offlined) ?? 7975 */ 7976 if (ptgt->tgt_state & FCP_TGT_MARK) { 7977 /* 7978 * this target not offline *and* 7979 * marked 7980 */ 7981 ptgt->tgt_state &= ~FCP_TGT_MARK; 7982 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7983 tgt_cnt, 0, 0); 7984 } else { 7985 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7986 7987 /* create the LUNs */ 7988 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7989 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7990 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7991 cause); 7992 ptgt->tgt_device_created = 1; 7993 } else { 7994 fcp_update_tgt_state(ptgt, FCP_RESET, 7995 FCP_LUN_BUSY); 7996 } 7997 } 7998 } 7999 8000 mutex_exit(&ptgt->tgt_mutex); 8001 8002 return (rval); 8003 } 8004 8005 8006 /* 8007 * this routine is called to finish port initialization 8008 * 8009 * Each port has a "temp" counter -- when a state change happens (e.g. 8010 * port online), the temp count is set to the number of devices in the map. 8011 * Then, as each device gets "discovered", the temp counter is decremented 8012 * by one. When this count reaches zero we know that all of the devices 8013 * in the map have been discovered (or an error has occurred), so we can 8014 * then finish initialization -- which is done by this routine (well, this 8015 * and fcp-finish_tgt()) 8016 * 8017 * acquires and releases the global mutex 8018 * 8019 * called with the port mutex owned 8020 */ 8021 static void 8022 fcp_finish_init(struct fcp_port *pptr) 8023 { 8024 #ifdef DEBUG 8025 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8026 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8027 FCP_STACK_DEPTH); 8028 #endif /* DEBUG */ 8029 8030 ASSERT(mutex_owned(&pptr->port_mutex)); 8031 8032 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8033 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8034 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8035 8036 if ((pptr->port_state & FCP_STATE_ONLINING) && 8037 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8038 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8039 pptr->port_state &= ~FCP_STATE_ONLINING; 8040 pptr->port_state |= FCP_STATE_ONLINE; 8041 } 8042 8043 /* Wake up threads waiting on config done */ 8044 cv_broadcast(&pptr->port_config_cv); 8045 } 8046 8047 8048 /* 8049 * called from fcp_finish_init to create the LUNs for a target 8050 * 8051 * called with the port mutex owned 8052 */ 8053 static void 8054 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8055 { 8056 struct fcp_lun *plun; 8057 struct fcp_port *pptr; 8058 child_info_t *cip = NULL; 8059 8060 ASSERT(ptgt != NULL); 8061 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8062 8063 pptr = ptgt->tgt_port; 8064 8065 ASSERT(pptr != NULL); 8066 8067 /* scan all LUNs for this target */ 8068 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8069 if (plun->lun_state & FCP_LUN_OFFLINE) { 8070 continue; 8071 } 8072 8073 if (plun->lun_state & FCP_LUN_MARK) { 8074 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8075 fcp_trace, FCP_BUF_LEVEL_2, 0, 8076 "fcp_create_luns: offlining marked LUN!"); 8077 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8078 continue; 8079 } 8080 8081 plun->lun_state &= ~FCP_LUN_BUSY; 8082 8083 /* 8084 * There are conditions in which FCP_LUN_INIT flag is cleared 8085 * but we have a valid plun->lun_cip. To cover this case also 8086 * CLEAR_BUSY whenever we have a valid lun_cip. 8087 */ 8088 if (plun->lun_mpxio && plun->lun_cip && 8089 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8090 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8091 0, 0))) { 8092 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8093 fcp_trace, FCP_BUF_LEVEL_2, 0, 8094 "fcp_create_luns: enable lun %p failed!", 8095 plun); 8096 } 8097 8098 if (plun->lun_state & FCP_LUN_INIT && 8099 !(plun->lun_state & FCP_LUN_CHANGED)) { 8100 continue; 8101 } 8102 8103 if (cause == FCP_CAUSE_USER_CREATE) { 8104 continue; 8105 } 8106 8107 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8108 fcp_trace, FCP_BUF_LEVEL_6, 0, 8109 "create_luns: passing ONLINE elem to HP thread"); 8110 8111 /* 8112 * If lun has changed, prepare for offlining the old path. 8113 * Do not offline the old path right now, since it may be 8114 * still opened. 8115 */ 8116 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8117 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8118 } 8119 8120 /* pass an ONLINE element to the hotplug thread */ 8121 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8122 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8123 8124 /* 8125 * We can not synchronous attach (i.e pass 8126 * NDI_ONLINE_ATTACH) here as we might be 8127 * coming from an interrupt or callback 8128 * thread. 8129 */ 8130 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8131 link_cnt, tgt_cnt, 0, 0)) { 8132 fcp_log(CE_CONT, pptr->port_dip, 8133 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8134 plun->lun_tgt->tgt_d_id, plun->lun_num); 8135 } 8136 } 8137 } 8138 } 8139 8140 8141 /* 8142 * function to online/offline devices 8143 */ 8144 static int 8145 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8146 int online, int lcount, int tcount, int flags) 8147 { 8148 int rval = NDI_FAILURE; 8149 int circ; 8150 child_info_t *ccip; 8151 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8152 int is_mpxio = pptr->port_mpxio; 8153 dev_info_t *cdip, *pdip; 8154 char *devname; 8155 8156 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8157 /* 8158 * When this event gets serviced, lun_cip and lun_mpxio 8159 * has changed, so it should be invalidated now. 8160 */ 8161 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8162 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8163 "plun: %p, cip: %p, what:%d", plun, cip, online); 8164 return (rval); 8165 } 8166 8167 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8168 fcp_trace, FCP_BUF_LEVEL_2, 0, 8169 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8170 "flags=%x mpxio=%x\n", 8171 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8172 plun->lun_mpxio); 8173 8174 /* 8175 * lun_mpxio needs checking here because we can end up in a race 8176 * condition where this task has been dispatched while lun_mpxio is 8177 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8178 * enable MPXIO for the LUN, but was unable to, and hence cleared 8179 * the flag. We rely on the serialization of the tasks here. We return 8180 * NDI_SUCCESS so any callers continue without reporting spurious 8181 * errors, and the still think we're an MPXIO LUN. 8182 */ 8183 8184 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8185 online == FCP_MPXIO_PATH_SET_BUSY) { 8186 if (plun->lun_mpxio) { 8187 rval = fcp_update_mpxio_path(plun, cip, online); 8188 } else { 8189 rval = NDI_SUCCESS; 8190 } 8191 return (rval); 8192 } 8193 8194 /* 8195 * Explicit devfs_clean() due to ndi_devi_offline() not 8196 * executing devfs_clean() if parent lock is held. 8197 */ 8198 ASSERT(!servicing_interrupt()); 8199 if (online == FCP_OFFLINE) { 8200 if (plun->lun_mpxio == 0) { 8201 if (plun->lun_cip == cip) { 8202 cdip = DIP(plun->lun_cip); 8203 } else { 8204 cdip = DIP(cip); 8205 } 8206 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8207 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8208 } else if ((plun->lun_cip != cip) && cip) { 8209 /* 8210 * This means a DTYPE/GUID change, we shall get the 8211 * dip of the old cip instead of the current lun_cip. 8212 */ 8213 cdip = mdi_pi_get_client(PIP(cip)); 8214 } 8215 if (cdip) { 8216 if (i_ddi_devi_attached(cdip)) { 8217 pdip = ddi_get_parent(cdip); 8218 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8219 ndi_devi_enter(pdip, &circ); 8220 (void) ddi_deviname(cdip, devname); 8221 ndi_devi_exit(pdip, circ); 8222 /* 8223 * Release parent lock before calling 8224 * devfs_clean(). 8225 */ 8226 rval = devfs_clean(pdip, devname + 1, 8227 DV_CLEAN_FORCE); 8228 kmem_free(devname, MAXNAMELEN + 1); 8229 /* 8230 * Return if devfs_clean() fails for 8231 * non-MPXIO case. 8232 * For MPXIO case, another path could be 8233 * offlined. 8234 */ 8235 if (rval && plun->lun_mpxio == 0) { 8236 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8237 fcp_trace, FCP_BUF_LEVEL_3, 0, 8238 "fcp_trigger_lun: devfs_clean " 8239 "failed rval=%x dip=%p", 8240 rval, pdip); 8241 return (NDI_FAILURE); 8242 } 8243 } 8244 } 8245 } 8246 8247 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8248 return (NDI_FAILURE); 8249 } 8250 8251 if (is_mpxio) { 8252 mdi_devi_enter(pptr->port_dip, &circ); 8253 } else { 8254 ndi_devi_enter(pptr->port_dip, &circ); 8255 } 8256 8257 mutex_enter(&pptr->port_mutex); 8258 mutex_enter(&plun->lun_mutex); 8259 8260 if (online == FCP_ONLINE) { 8261 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8262 if (ccip == NULL) { 8263 goto fail; 8264 } 8265 } else { 8266 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8267 goto fail; 8268 } 8269 ccip = cip; 8270 } 8271 8272 if (online == FCP_ONLINE) { 8273 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8274 &circ); 8275 fc_ulp_log_device_event(pptr->port_fp_handle, 8276 FC_ULP_DEVICE_ONLINE); 8277 } else { 8278 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8279 &circ); 8280 fc_ulp_log_device_event(pptr->port_fp_handle, 8281 FC_ULP_DEVICE_OFFLINE); 8282 } 8283 8284 fail: mutex_exit(&plun->lun_mutex); 8285 mutex_exit(&pptr->port_mutex); 8286 8287 if (is_mpxio) { 8288 mdi_devi_exit(pptr->port_dip, circ); 8289 } else { 8290 ndi_devi_exit(pptr->port_dip, circ); 8291 } 8292 8293 fc_ulp_idle_port(pptr->port_fp_handle); 8294 8295 return (rval); 8296 } 8297 8298 8299 /* 8300 * take a target offline by taking all of its LUNs offline 8301 */ 8302 /*ARGSUSED*/ 8303 static int 8304 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8305 int link_cnt, int tgt_cnt, int nowait, int flags) 8306 { 8307 struct fcp_tgt_elem *elem; 8308 8309 ASSERT(mutex_owned(&pptr->port_mutex)); 8310 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8311 8312 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8313 8314 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8315 ptgt->tgt_change_cnt)) { 8316 mutex_exit(&ptgt->tgt_mutex); 8317 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8318 mutex_enter(&ptgt->tgt_mutex); 8319 8320 return (0); 8321 } 8322 8323 ptgt->tgt_pd_handle = NULL; 8324 mutex_exit(&ptgt->tgt_mutex); 8325 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8326 mutex_enter(&ptgt->tgt_mutex); 8327 8328 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8329 8330 if (ptgt->tgt_tcap && 8331 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8332 elem->flags = flags; 8333 elem->time = fcp_watchdog_time; 8334 if (nowait == 0) { 8335 elem->time += fcp_offline_delay; 8336 } 8337 elem->ptgt = ptgt; 8338 elem->link_cnt = link_cnt; 8339 elem->tgt_cnt = tgt_cnt; 8340 elem->next = pptr->port_offline_tgts; 8341 pptr->port_offline_tgts = elem; 8342 } else { 8343 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8344 } 8345 8346 return (1); 8347 } 8348 8349 8350 static void 8351 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8352 int link_cnt, int tgt_cnt, int flags) 8353 { 8354 ASSERT(mutex_owned(&pptr->port_mutex)); 8355 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8356 8357 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8358 ptgt->tgt_state = FCP_TGT_OFFLINE; 8359 ptgt->tgt_pd_handle = NULL; 8360 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8361 } 8362 8363 8364 static void 8365 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8366 int flags) 8367 { 8368 struct fcp_lun *plun; 8369 8370 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8371 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8372 8373 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8374 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8375 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8376 } 8377 } 8378 } 8379 8380 8381 /* 8382 * take a LUN offline 8383 * 8384 * enters and leaves with the target mutex held, releasing it in the process 8385 * 8386 * allocates memory in non-sleep mode 8387 */ 8388 static void 8389 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8390 int nowait, int flags) 8391 { 8392 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8393 struct fcp_lun_elem *elem; 8394 8395 ASSERT(plun != NULL); 8396 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8397 8398 if (nowait) { 8399 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8400 return; 8401 } 8402 8403 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8404 elem->flags = flags; 8405 elem->time = fcp_watchdog_time; 8406 if (nowait == 0) { 8407 elem->time += fcp_offline_delay; 8408 } 8409 elem->plun = plun; 8410 elem->link_cnt = link_cnt; 8411 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8412 elem->next = pptr->port_offline_luns; 8413 pptr->port_offline_luns = elem; 8414 } else { 8415 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8416 } 8417 } 8418 8419 8420 static void 8421 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8422 { 8423 struct fcp_pkt *head = NULL; 8424 8425 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8426 8427 mutex_exit(&LUN_TGT->tgt_mutex); 8428 8429 head = fcp_scan_commands(plun); 8430 if (head != NULL) { 8431 fcp_abort_commands(head, LUN_PORT); 8432 } 8433 8434 mutex_enter(&LUN_TGT->tgt_mutex); 8435 8436 if (plun->lun_cip && plun->lun_mpxio) { 8437 /* 8438 * Intimate MPxIO lun busy is cleared 8439 */ 8440 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8441 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8442 0, 0)) { 8443 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8444 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8445 LUN_TGT->tgt_d_id, plun->lun_num); 8446 } 8447 /* 8448 * Intimate MPxIO that the lun is now marked for offline 8449 */ 8450 mutex_exit(&LUN_TGT->tgt_mutex); 8451 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8452 mutex_enter(&LUN_TGT->tgt_mutex); 8453 } 8454 } 8455 8456 static void 8457 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8458 int flags) 8459 { 8460 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8461 8462 mutex_exit(&LUN_TGT->tgt_mutex); 8463 fcp_update_offline_flags(plun); 8464 mutex_enter(&LUN_TGT->tgt_mutex); 8465 8466 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8467 8468 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8469 fcp_trace, FCP_BUF_LEVEL_4, 0, 8470 "offline_lun: passing OFFLINE elem to HP thread"); 8471 8472 if (plun->lun_cip) { 8473 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8474 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8475 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8476 LUN_TGT->tgt_trace); 8477 8478 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8479 link_cnt, tgt_cnt, flags, 0)) { 8480 fcp_log(CE_CONT, LUN_PORT->port_dip, 8481 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8482 LUN_TGT->tgt_d_id, plun->lun_num); 8483 } 8484 } 8485 } 8486 8487 static void 8488 fcp_scan_offline_luns(struct fcp_port *pptr) 8489 { 8490 struct fcp_lun_elem *elem; 8491 struct fcp_lun_elem *prev; 8492 struct fcp_lun_elem *next; 8493 8494 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8495 8496 prev = NULL; 8497 elem = pptr->port_offline_luns; 8498 while (elem) { 8499 next = elem->next; 8500 if (elem->time <= fcp_watchdog_time) { 8501 int changed = 1; 8502 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8503 8504 mutex_enter(&ptgt->tgt_mutex); 8505 if (pptr->port_link_cnt == elem->link_cnt && 8506 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8507 changed = 0; 8508 } 8509 8510 if (!changed && 8511 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8512 fcp_offline_lun_now(elem->plun, 8513 elem->link_cnt, elem->tgt_cnt, elem->flags); 8514 } 8515 mutex_exit(&ptgt->tgt_mutex); 8516 8517 kmem_free(elem, sizeof (*elem)); 8518 8519 if (prev) { 8520 prev->next = next; 8521 } else { 8522 pptr->port_offline_luns = next; 8523 } 8524 } else { 8525 prev = elem; 8526 } 8527 elem = next; 8528 } 8529 } 8530 8531 8532 static void 8533 fcp_scan_offline_tgts(struct fcp_port *pptr) 8534 { 8535 struct fcp_tgt_elem *elem; 8536 struct fcp_tgt_elem *prev; 8537 struct fcp_tgt_elem *next; 8538 8539 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8540 8541 prev = NULL; 8542 elem = pptr->port_offline_tgts; 8543 while (elem) { 8544 next = elem->next; 8545 if (elem->time <= fcp_watchdog_time) { 8546 int outdated = 1; 8547 struct fcp_tgt *ptgt = elem->ptgt; 8548 8549 mutex_enter(&ptgt->tgt_mutex); 8550 8551 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8552 /* No change on tgt since elem was created. */ 8553 outdated = 0; 8554 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8555 pptr->port_link_cnt == elem->link_cnt + 1 && 8556 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8557 /* 8558 * Exactly one thing happened to the target 8559 * inbetween: the local port went offline. 8560 * For fp the remote port is already gone so 8561 * it will not tell us again to offline the 8562 * target. We must offline it now. 8563 */ 8564 outdated = 0; 8565 } 8566 8567 if (!outdated && !(ptgt->tgt_state & 8568 FCP_TGT_OFFLINE)) { 8569 fcp_offline_target_now(pptr, 8570 ptgt, elem->link_cnt, elem->tgt_cnt, 8571 elem->flags); 8572 } 8573 8574 mutex_exit(&ptgt->tgt_mutex); 8575 8576 kmem_free(elem, sizeof (*elem)); 8577 8578 if (prev) { 8579 prev->next = next; 8580 } else { 8581 pptr->port_offline_tgts = next; 8582 } 8583 } else { 8584 prev = elem; 8585 } 8586 elem = next; 8587 } 8588 } 8589 8590 8591 static void 8592 fcp_update_offline_flags(struct fcp_lun *plun) 8593 { 8594 struct fcp_port *pptr = LUN_PORT; 8595 ASSERT(plun != NULL); 8596 8597 mutex_enter(&LUN_TGT->tgt_mutex); 8598 plun->lun_state |= FCP_LUN_OFFLINE; 8599 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8600 8601 mutex_enter(&plun->lun_mutex); 8602 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8603 dev_info_t *cdip = NULL; 8604 8605 mutex_exit(&LUN_TGT->tgt_mutex); 8606 8607 if (plun->lun_mpxio == 0) { 8608 cdip = DIP(plun->lun_cip); 8609 } else if (plun->lun_cip) { 8610 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8611 } 8612 8613 mutex_exit(&plun->lun_mutex); 8614 if (cdip) { 8615 (void) ndi_event_retrieve_cookie( 8616 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8617 &fcp_remove_eid, NDI_EVENT_NOPASS); 8618 (void) ndi_event_run_callbacks( 8619 pptr->port_ndi_event_hdl, cdip, 8620 fcp_remove_eid, NULL); 8621 } 8622 } else { 8623 mutex_exit(&plun->lun_mutex); 8624 mutex_exit(&LUN_TGT->tgt_mutex); 8625 } 8626 } 8627 8628 8629 /* 8630 * Scan all of the command pkts for this port, moving pkts that 8631 * match our LUN onto our own list (headed by "head") 8632 */ 8633 static struct fcp_pkt * 8634 fcp_scan_commands(struct fcp_lun *plun) 8635 { 8636 struct fcp_port *pptr = LUN_PORT; 8637 8638 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8639 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8640 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8641 8642 struct fcp_pkt *head = NULL; /* head of our list */ 8643 struct fcp_pkt *tail = NULL; /* tail of our list */ 8644 8645 int cmds_found = 0; 8646 8647 mutex_enter(&pptr->port_pkt_mutex); 8648 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8649 struct fcp_lun *tlun = 8650 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8651 8652 ncmd = cmd->cmd_next; /* set next command */ 8653 8654 /* 8655 * if this pkt is for a different LUN or the 8656 * command is sent down, skip it. 8657 */ 8658 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8659 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8660 pcmd = cmd; 8661 continue; 8662 } 8663 cmds_found++; 8664 if (pcmd != NULL) { 8665 ASSERT(pptr->port_pkt_head != cmd); 8666 pcmd->cmd_next = cmd->cmd_next; 8667 } else { 8668 ASSERT(cmd == pptr->port_pkt_head); 8669 pptr->port_pkt_head = cmd->cmd_next; 8670 } 8671 8672 if (cmd == pptr->port_pkt_tail) { 8673 pptr->port_pkt_tail = pcmd; 8674 if (pcmd) { 8675 pcmd->cmd_next = NULL; 8676 } 8677 } 8678 8679 if (head == NULL) { 8680 head = tail = cmd; 8681 } else { 8682 ASSERT(tail != NULL); 8683 8684 tail->cmd_next = cmd; 8685 tail = cmd; 8686 } 8687 cmd->cmd_next = NULL; 8688 } 8689 mutex_exit(&pptr->port_pkt_mutex); 8690 8691 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8692 fcp_trace, FCP_BUF_LEVEL_8, 0, 8693 "scan commands: %d cmd(s) found", cmds_found); 8694 8695 return (head); 8696 } 8697 8698 8699 /* 8700 * Abort all the commands in the command queue 8701 */ 8702 static void 8703 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8704 { 8705 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8706 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8707 8708 ASSERT(mutex_owned(&pptr->port_mutex)); 8709 8710 /* scan through the pkts and invalid them */ 8711 for (cmd = head; cmd != NULL; cmd = ncmd) { 8712 struct scsi_pkt *pkt = cmd->cmd_pkt; 8713 8714 ncmd = cmd->cmd_next; 8715 ASSERT(pkt != NULL); 8716 8717 /* 8718 * The lun is going to be marked offline. Indicate 8719 * the target driver not to requeue or retry this command 8720 * as the device is going to be offlined pretty soon. 8721 */ 8722 pkt->pkt_reason = CMD_DEV_GONE; 8723 pkt->pkt_statistics = 0; 8724 pkt->pkt_state = 0; 8725 8726 /* reset cmd flags/state */ 8727 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8728 cmd->cmd_state = FCP_PKT_IDLE; 8729 8730 /* 8731 * ensure we have a packet completion routine, 8732 * then call it. 8733 */ 8734 ASSERT(pkt->pkt_comp != NULL); 8735 8736 mutex_exit(&pptr->port_mutex); 8737 fcp_post_callback(cmd); 8738 mutex_enter(&pptr->port_mutex); 8739 } 8740 } 8741 8742 8743 /* 8744 * the pkt_comp callback for command packets 8745 */ 8746 static void 8747 fcp_cmd_callback(fc_packet_t *fpkt) 8748 { 8749 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8750 struct scsi_pkt *pkt = cmd->cmd_pkt; 8751 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8752 8753 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8754 8755 if (cmd->cmd_state == FCP_PKT_IDLE) { 8756 cmn_err(CE_PANIC, "Packet already completed %p", 8757 (void *)cmd); 8758 } 8759 8760 /* 8761 * Watch thread should be freeing the packet, ignore the pkt. 8762 */ 8763 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8764 fcp_log(CE_CONT, pptr->port_dip, 8765 "!FCP: Pkt completed while aborting\n"); 8766 return; 8767 } 8768 cmd->cmd_state = FCP_PKT_IDLE; 8769 8770 fcp_complete_pkt(fpkt); 8771 8772 #ifdef DEBUG 8773 mutex_enter(&pptr->port_pkt_mutex); 8774 pptr->port_npkts--; 8775 mutex_exit(&pptr->port_pkt_mutex); 8776 #endif /* DEBUG */ 8777 8778 fcp_post_callback(cmd); 8779 } 8780 8781 8782 static void 8783 fcp_complete_pkt(fc_packet_t *fpkt) 8784 { 8785 int error = 0; 8786 struct fcp_pkt *cmd = (struct fcp_pkt *) 8787 fpkt->pkt_ulp_private; 8788 struct scsi_pkt *pkt = cmd->cmd_pkt; 8789 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8790 struct fcp_lun *plun; 8791 struct fcp_tgt *ptgt; 8792 struct fcp_rsp *rsp; 8793 struct scsi_address save; 8794 8795 #ifdef DEBUG 8796 save = pkt->pkt_address; 8797 #endif /* DEBUG */ 8798 8799 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8800 8801 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8802 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8803 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8804 sizeof (struct fcp_rsp)); 8805 } 8806 8807 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8808 STATE_SENT_CMD | STATE_GOT_STATUS; 8809 8810 pkt->pkt_resid = 0; 8811 8812 if (fpkt->pkt_datalen) { 8813 pkt->pkt_state |= STATE_XFERRED_DATA; 8814 if (fpkt->pkt_data_resid) { 8815 error++; 8816 } 8817 } 8818 8819 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8820 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8821 /* 8822 * The next two checks make sure that if there 8823 * is no sense data or a valid response and 8824 * the command came back with check condition, 8825 * the command should be retried. 8826 */ 8827 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8828 !rsp->fcp_u.fcp_status.sense_len_set) { 8829 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8830 pkt->pkt_resid = cmd->cmd_dmacount; 8831 } 8832 } 8833 8834 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8835 return; 8836 } 8837 8838 plun = ADDR2LUN(&pkt->pkt_address); 8839 ptgt = plun->lun_tgt; 8840 ASSERT(ptgt != NULL); 8841 8842 /* 8843 * Update the transfer resid, if appropriate 8844 */ 8845 if (rsp->fcp_u.fcp_status.resid_over || 8846 rsp->fcp_u.fcp_status.resid_under) { 8847 pkt->pkt_resid = rsp->fcp_resid; 8848 } 8849 8850 /* 8851 * First see if we got a FCP protocol error. 8852 */ 8853 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8854 struct fcp_rsp_info *bep; 8855 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8856 sizeof (struct fcp_rsp)); 8857 8858 if (fcp_validate_fcp_response(rsp, pptr) != 8859 FC_SUCCESS) { 8860 pkt->pkt_reason = CMD_CMPLT; 8861 *(pkt->pkt_scbp) = STATUS_CHECK; 8862 8863 fcp_log(CE_WARN, pptr->port_dip, 8864 "!SCSI command to d_id=0x%x lun=0x%x" 8865 " failed, Bad FCP response values:" 8866 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8867 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8868 ptgt->tgt_d_id, plun->lun_num, 8869 rsp->reserved_0, rsp->reserved_1, 8870 rsp->fcp_u.fcp_status.reserved_0, 8871 rsp->fcp_u.fcp_status.reserved_1, 8872 rsp->fcp_response_len, rsp->fcp_sense_len); 8873 8874 return; 8875 } 8876 8877 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8878 FCP_CP_IN(fpkt->pkt_resp + 8879 sizeof (struct fcp_rsp), bep, 8880 fpkt->pkt_resp_acc, 8881 sizeof (struct fcp_rsp_info)); 8882 } 8883 8884 if (bep->rsp_code != FCP_NO_FAILURE) { 8885 child_info_t *cip; 8886 8887 pkt->pkt_reason = CMD_TRAN_ERR; 8888 8889 mutex_enter(&plun->lun_mutex); 8890 cip = plun->lun_cip; 8891 mutex_exit(&plun->lun_mutex); 8892 8893 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8894 fcp_trace, FCP_BUF_LEVEL_2, 0, 8895 "FCP response error on cmd=%p" 8896 " target=0x%x, cip=%p", cmd, 8897 ptgt->tgt_d_id, cip); 8898 } 8899 } 8900 8901 /* 8902 * See if we got a SCSI error with sense data 8903 */ 8904 if (rsp->fcp_u.fcp_status.sense_len_set) { 8905 uchar_t rqlen; 8906 caddr_t sense_from; 8907 child_info_t *cip; 8908 timeout_id_t tid; 8909 struct scsi_arq_status *arq; 8910 struct scsi_extended_sense *sense_to; 8911 8912 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8913 sense_to = &arq->sts_sensedata; 8914 8915 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8916 sizeof (struct scsi_extended_sense)); 8917 8918 sense_from = (caddr_t)fpkt->pkt_resp + 8919 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8920 8921 if (fcp_validate_fcp_response(rsp, pptr) != 8922 FC_SUCCESS) { 8923 pkt->pkt_reason = CMD_CMPLT; 8924 *(pkt->pkt_scbp) = STATUS_CHECK; 8925 8926 fcp_log(CE_WARN, pptr->port_dip, 8927 "!SCSI command to d_id=0x%x lun=0x%x" 8928 " failed, Bad FCP response values:" 8929 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8930 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8931 ptgt->tgt_d_id, plun->lun_num, 8932 rsp->reserved_0, rsp->reserved_1, 8933 rsp->fcp_u.fcp_status.reserved_0, 8934 rsp->fcp_u.fcp_status.reserved_1, 8935 rsp->fcp_response_len, rsp->fcp_sense_len); 8936 8937 return; 8938 } 8939 8940 /* 8941 * copy in sense information 8942 */ 8943 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8944 FCP_CP_IN(sense_from, sense_to, 8945 fpkt->pkt_resp_acc, rqlen); 8946 } else { 8947 bcopy(sense_from, sense_to, rqlen); 8948 } 8949 8950 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8951 (FCP_SENSE_NO_LUN(sense_to))) { 8952 mutex_enter(&ptgt->tgt_mutex); 8953 if (ptgt->tgt_tid == NULL) { 8954 /* 8955 * Kick off rediscovery 8956 */ 8957 tid = timeout(fcp_reconfigure_luns, 8958 (caddr_t)ptgt, drv_usectohz(1)); 8959 8960 ptgt->tgt_tid = tid; 8961 ptgt->tgt_state |= FCP_TGT_BUSY; 8962 } 8963 mutex_exit(&ptgt->tgt_mutex); 8964 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8965 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8966 fcp_trace, FCP_BUF_LEVEL_3, 0, 8967 "!FCP: Report Lun Has Changed" 8968 " target=%x", ptgt->tgt_d_id); 8969 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8970 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8971 fcp_trace, FCP_BUF_LEVEL_3, 0, 8972 "!FCP: LU Not Supported" 8973 " target=%x", ptgt->tgt_d_id); 8974 } 8975 } 8976 ASSERT(pkt->pkt_scbp != NULL); 8977 8978 pkt->pkt_state |= STATE_ARQ_DONE; 8979 8980 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8981 8982 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8983 arq->sts_rqpkt_reason = 0; 8984 arq->sts_rqpkt_statistics = 0; 8985 8986 arq->sts_rqpkt_state = STATE_GOT_BUS | 8987 STATE_GOT_TARGET | STATE_SENT_CMD | 8988 STATE_GOT_STATUS | STATE_ARQ_DONE | 8989 STATE_XFERRED_DATA; 8990 8991 mutex_enter(&plun->lun_mutex); 8992 cip = plun->lun_cip; 8993 mutex_exit(&plun->lun_mutex); 8994 8995 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8996 fcp_trace, FCP_BUF_LEVEL_8, 0, 8997 "SCSI Check condition on cmd=%p target=0x%x" 8998 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8999 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 9000 cmd->cmd_fcp_cmd.fcp_cdb[0], 9001 rsp->fcp_u.fcp_status.scsi_status, 9002 sense_to->es_key, sense_to->es_add_code, 9003 sense_to->es_qual_code); 9004 } 9005 } else { 9006 plun = ADDR2LUN(&pkt->pkt_address); 9007 ptgt = plun->lun_tgt; 9008 ASSERT(ptgt != NULL); 9009 9010 /* 9011 * Work harder to translate errors into target driver 9012 * understandable ones. Note with despair that the target 9013 * drivers don't decode pkt_state and pkt_reason exhaustively 9014 * They resort to using the big hammer most often, which 9015 * may not get fixed in the life time of this driver. 9016 */ 9017 pkt->pkt_state = 0; 9018 pkt->pkt_statistics = 0; 9019 9020 switch (fpkt->pkt_state) { 9021 case FC_PKT_TRAN_ERROR: 9022 switch (fpkt->pkt_reason) { 9023 case FC_REASON_OVERRUN: 9024 pkt->pkt_reason = CMD_CMD_OVR; 9025 pkt->pkt_statistics |= STAT_ABORTED; 9026 break; 9027 9028 case FC_REASON_XCHG_BSY: { 9029 caddr_t ptr; 9030 9031 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9032 9033 ptr = (caddr_t)pkt->pkt_scbp; 9034 if (ptr) { 9035 *ptr = STATUS_BUSY; 9036 } 9037 break; 9038 } 9039 9040 case FC_REASON_ABORTED: 9041 pkt->pkt_reason = CMD_TRAN_ERR; 9042 pkt->pkt_statistics |= STAT_ABORTED; 9043 break; 9044 9045 case FC_REASON_ABORT_FAILED: 9046 pkt->pkt_reason = CMD_ABORT_FAIL; 9047 break; 9048 9049 case FC_REASON_NO_SEQ_INIT: 9050 case FC_REASON_CRC_ERROR: 9051 pkt->pkt_reason = CMD_TRAN_ERR; 9052 pkt->pkt_statistics |= STAT_ABORTED; 9053 break; 9054 default: 9055 pkt->pkt_reason = CMD_TRAN_ERR; 9056 break; 9057 } 9058 break; 9059 9060 case FC_PKT_PORT_OFFLINE: { 9061 dev_info_t *cdip = NULL; 9062 caddr_t ptr; 9063 9064 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9065 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9066 fcp_trace, FCP_BUF_LEVEL_8, 0, 9067 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9068 ptgt->tgt_d_id); 9069 } 9070 9071 mutex_enter(&plun->lun_mutex); 9072 if (plun->lun_mpxio == 0) { 9073 cdip = DIP(plun->lun_cip); 9074 } else if (plun->lun_cip) { 9075 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9076 } 9077 9078 mutex_exit(&plun->lun_mutex); 9079 9080 if (cdip) { 9081 (void) ndi_event_retrieve_cookie( 9082 pptr->port_ndi_event_hdl, cdip, 9083 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9084 NDI_EVENT_NOPASS); 9085 (void) ndi_event_run_callbacks( 9086 pptr->port_ndi_event_hdl, cdip, 9087 fcp_remove_eid, NULL); 9088 } 9089 9090 /* 9091 * If the link goes off-line for a lip, 9092 * this will cause a error to the ST SG 9093 * SGEN drivers. By setting BUSY we will 9094 * give the drivers the chance to retry 9095 * before it blows of the job. ST will 9096 * remember how many times it has retried. 9097 */ 9098 9099 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9100 (plun->lun_type == DTYPE_CHANGER)) { 9101 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9102 ptr = (caddr_t)pkt->pkt_scbp; 9103 if (ptr) { 9104 *ptr = STATUS_BUSY; 9105 } 9106 } else { 9107 pkt->pkt_reason = CMD_TRAN_ERR; 9108 pkt->pkt_statistics |= STAT_BUS_RESET; 9109 } 9110 break; 9111 } 9112 9113 case FC_PKT_TRAN_BSY: 9114 /* 9115 * Use the ssd Qfull handling here. 9116 */ 9117 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9118 pkt->pkt_state = STATE_GOT_BUS; 9119 break; 9120 9121 case FC_PKT_TIMEOUT: 9122 pkt->pkt_reason = CMD_TIMEOUT; 9123 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9124 pkt->pkt_statistics |= STAT_TIMEOUT; 9125 } else { 9126 pkt->pkt_statistics |= STAT_ABORTED; 9127 } 9128 break; 9129 9130 case FC_PKT_LOCAL_RJT: 9131 switch (fpkt->pkt_reason) { 9132 case FC_REASON_OFFLINE: { 9133 dev_info_t *cdip = NULL; 9134 9135 mutex_enter(&plun->lun_mutex); 9136 if (plun->lun_mpxio == 0) { 9137 cdip = DIP(plun->lun_cip); 9138 } else if (plun->lun_cip) { 9139 cdip = mdi_pi_get_client( 9140 PIP(plun->lun_cip)); 9141 } 9142 mutex_exit(&plun->lun_mutex); 9143 9144 if (cdip) { 9145 (void) ndi_event_retrieve_cookie( 9146 pptr->port_ndi_event_hdl, cdip, 9147 FCAL_REMOVE_EVENT, 9148 &fcp_remove_eid, 9149 NDI_EVENT_NOPASS); 9150 (void) ndi_event_run_callbacks( 9151 pptr->port_ndi_event_hdl, 9152 cdip, fcp_remove_eid, NULL); 9153 } 9154 9155 pkt->pkt_reason = CMD_TRAN_ERR; 9156 pkt->pkt_statistics |= STAT_BUS_RESET; 9157 9158 break; 9159 } 9160 9161 case FC_REASON_NOMEM: 9162 case FC_REASON_QFULL: { 9163 caddr_t ptr; 9164 9165 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9166 ptr = (caddr_t)pkt->pkt_scbp; 9167 if (ptr) { 9168 *ptr = STATUS_BUSY; 9169 } 9170 break; 9171 } 9172 9173 case FC_REASON_DMA_ERROR: 9174 pkt->pkt_reason = CMD_DMA_DERR; 9175 pkt->pkt_statistics |= STAT_ABORTED; 9176 break; 9177 9178 case FC_REASON_CRC_ERROR: 9179 case FC_REASON_UNDERRUN: { 9180 uchar_t status; 9181 /* 9182 * Work around for Bugid: 4240945. 9183 * IB on A5k doesn't set the Underrun bit 9184 * in the fcp status, when it is transferring 9185 * less than requested amount of data. Work 9186 * around the ses problem to keep luxadm 9187 * happy till ibfirmware is fixed. 9188 */ 9189 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9190 FCP_CP_IN(fpkt->pkt_resp, rsp, 9191 fpkt->pkt_resp_acc, 9192 sizeof (struct fcp_rsp)); 9193 } 9194 status = rsp->fcp_u.fcp_status.scsi_status; 9195 if (((plun->lun_type & DTYPE_MASK) == 9196 DTYPE_ESI) && (status == STATUS_GOOD)) { 9197 pkt->pkt_reason = CMD_CMPLT; 9198 *pkt->pkt_scbp = status; 9199 pkt->pkt_resid = 0; 9200 } else { 9201 pkt->pkt_reason = CMD_TRAN_ERR; 9202 pkt->pkt_statistics |= STAT_ABORTED; 9203 } 9204 break; 9205 } 9206 9207 case FC_REASON_NO_CONNECTION: 9208 case FC_REASON_UNSUPPORTED: 9209 case FC_REASON_ILLEGAL_REQ: 9210 case FC_REASON_BAD_SID: 9211 case FC_REASON_DIAG_BUSY: 9212 case FC_REASON_FCAL_OPN_FAIL: 9213 case FC_REASON_BAD_XID: 9214 default: 9215 pkt->pkt_reason = CMD_TRAN_ERR; 9216 pkt->pkt_statistics |= STAT_ABORTED; 9217 break; 9218 9219 } 9220 break; 9221 9222 case FC_PKT_NPORT_RJT: 9223 case FC_PKT_FABRIC_RJT: 9224 case FC_PKT_NPORT_BSY: 9225 case FC_PKT_FABRIC_BSY: 9226 default: 9227 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9228 fcp_trace, FCP_BUF_LEVEL_8, 0, 9229 "FC Status 0x%x, reason 0x%x", 9230 fpkt->pkt_state, fpkt->pkt_reason); 9231 pkt->pkt_reason = CMD_TRAN_ERR; 9232 pkt->pkt_statistics |= STAT_ABORTED; 9233 break; 9234 } 9235 9236 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9237 fcp_trace, FCP_BUF_LEVEL_9, 0, 9238 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9239 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9240 fpkt->pkt_reason); 9241 } 9242 9243 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9244 } 9245 9246 9247 static int 9248 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9249 { 9250 if (rsp->reserved_0 || rsp->reserved_1 || 9251 rsp->fcp_u.fcp_status.reserved_0 || 9252 rsp->fcp_u.fcp_status.reserved_1) { 9253 /* 9254 * These reserved fields should ideally be zero. FCP-2 does say 9255 * that the recipient need not check for reserved fields to be 9256 * zero. If they are not zero, we will not make a fuss about it 9257 * - just log it (in debug to both trace buffer and messages 9258 * file and to trace buffer only in non-debug) and move on. 9259 * 9260 * Non-zero reserved fields were seen with minnows. 9261 * 9262 * qlc takes care of some of this but we cannot assume that all 9263 * FCAs will do so. 9264 */ 9265 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9266 FCP_BUF_LEVEL_5, 0, 9267 "Got fcp response packet with non-zero reserved fields " 9268 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9269 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9270 rsp->reserved_0, rsp->reserved_1, 9271 rsp->fcp_u.fcp_status.reserved_0, 9272 rsp->fcp_u.fcp_status.reserved_1); 9273 } 9274 9275 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9276 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9277 return (FC_FAILURE); 9278 } 9279 9280 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9281 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9282 sizeof (struct fcp_rsp))) { 9283 return (FC_FAILURE); 9284 } 9285 9286 return (FC_SUCCESS); 9287 } 9288 9289 9290 /* 9291 * This is called when there is a change the in device state. The case we're 9292 * handling here is, if the d_id s does not match, offline this tgt and online 9293 * a new tgt with the new d_id. called from fcp_handle_devices with 9294 * port_mutex held. 9295 */ 9296 static int 9297 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9298 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9299 { 9300 ASSERT(mutex_owned(&pptr->port_mutex)); 9301 9302 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9303 fcp_trace, FCP_BUF_LEVEL_3, 0, 9304 "Starting fcp_device_changed..."); 9305 9306 /* 9307 * The two cases where the port_device_changed is called is 9308 * either it changes it's d_id or it's hard address. 9309 */ 9310 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9311 (FC_TOP_EXTERNAL(pptr->port_topology) && 9312 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9313 9314 /* offline this target */ 9315 mutex_enter(&ptgt->tgt_mutex); 9316 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9317 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9318 0, 1, NDI_DEVI_REMOVE); 9319 } 9320 mutex_exit(&ptgt->tgt_mutex); 9321 9322 fcp_log(CE_NOTE, pptr->port_dip, 9323 "Change in target properties: Old D_ID=%x New D_ID=%x" 9324 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9325 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9326 map_entry->map_hard_addr.hard_addr); 9327 } 9328 9329 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9330 link_cnt, tgt_cnt, cause)); 9331 } 9332 9333 /* 9334 * Function: fcp_alloc_lun 9335 * 9336 * Description: Creates a new lun structure and adds it to the list 9337 * of luns of the target. 9338 * 9339 * Argument: ptgt Target the lun will belong to. 9340 * 9341 * Return Value: NULL Failed 9342 * Not NULL Succeeded 9343 * 9344 * Context: Kernel context 9345 */ 9346 static struct fcp_lun * 9347 fcp_alloc_lun(struct fcp_tgt *ptgt) 9348 { 9349 struct fcp_lun *plun; 9350 9351 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9352 if (plun != NULL) { 9353 /* 9354 * Initialize the mutex before putting in the target list 9355 * especially before releasing the target mutex. 9356 */ 9357 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9358 plun->lun_tgt = ptgt; 9359 9360 mutex_enter(&ptgt->tgt_mutex); 9361 plun->lun_next = ptgt->tgt_lun; 9362 ptgt->tgt_lun = plun; 9363 plun->lun_old_guid = NULL; 9364 plun->lun_old_guid_size = 0; 9365 mutex_exit(&ptgt->tgt_mutex); 9366 } 9367 9368 return (plun); 9369 } 9370 9371 /* 9372 * Function: fcp_dealloc_lun 9373 * 9374 * Description: Frees the LUN structure passed by the caller. 9375 * 9376 * Argument: plun LUN structure to free. 9377 * 9378 * Return Value: None 9379 * 9380 * Context: Kernel context. 9381 */ 9382 static void 9383 fcp_dealloc_lun(struct fcp_lun *plun) 9384 { 9385 mutex_enter(&plun->lun_mutex); 9386 if (plun->lun_cip) { 9387 fcp_remove_child(plun); 9388 } 9389 mutex_exit(&plun->lun_mutex); 9390 9391 mutex_destroy(&plun->lun_mutex); 9392 if (plun->lun_guid) { 9393 kmem_free(plun->lun_guid, plun->lun_guid_size); 9394 } 9395 if (plun->lun_old_guid) { 9396 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9397 } 9398 kmem_free(plun, sizeof (*plun)); 9399 } 9400 9401 /* 9402 * Function: fcp_alloc_tgt 9403 * 9404 * Description: Creates a new target structure and adds it to the port 9405 * hash list. 9406 * 9407 * Argument: pptr fcp port structure 9408 * *map_entry entry describing the target to create 9409 * link_cnt Link state change counter 9410 * 9411 * Return Value: NULL Failed 9412 * Not NULL Succeeded 9413 * 9414 * Context: Kernel context. 9415 */ 9416 static struct fcp_tgt * 9417 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9418 { 9419 int hash; 9420 uchar_t *wwn; 9421 struct fcp_tgt *ptgt; 9422 9423 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9424 if (ptgt != NULL) { 9425 mutex_enter(&pptr->port_mutex); 9426 if (link_cnt != pptr->port_link_cnt) { 9427 /* 9428 * oh oh -- another link reset 9429 * in progress -- give up 9430 */ 9431 mutex_exit(&pptr->port_mutex); 9432 kmem_free(ptgt, sizeof (*ptgt)); 9433 ptgt = NULL; 9434 } else { 9435 /* 9436 * initialize the mutex before putting in the port 9437 * wwn list, especially before releasing the port 9438 * mutex. 9439 */ 9440 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9441 9442 /* add new target entry to the port's hash list */ 9443 wwn = (uchar_t *)&map_entry->map_pwwn; 9444 hash = FCP_HASH(wwn); 9445 9446 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9447 pptr->port_tgt_hash_table[hash] = ptgt; 9448 9449 /* save cross-ptr */ 9450 ptgt->tgt_port = pptr; 9451 9452 ptgt->tgt_change_cnt = 1; 9453 9454 /* initialize the target manual_config_only flag */ 9455 if (fcp_enable_auto_configuration) { 9456 ptgt->tgt_manual_config_only = 0; 9457 } else { 9458 ptgt->tgt_manual_config_only = 1; 9459 } 9460 9461 mutex_exit(&pptr->port_mutex); 9462 } 9463 } 9464 9465 return (ptgt); 9466 } 9467 9468 /* 9469 * Function: fcp_dealloc_tgt 9470 * 9471 * Description: Frees the target structure passed by the caller. 9472 * 9473 * Argument: ptgt Target structure to free. 9474 * 9475 * Return Value: None 9476 * 9477 * Context: Kernel context. 9478 */ 9479 static void 9480 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9481 { 9482 mutex_destroy(&ptgt->tgt_mutex); 9483 kmem_free(ptgt, sizeof (*ptgt)); 9484 } 9485 9486 9487 /* 9488 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9489 * 9490 * Device discovery commands will not be retried for-ever as 9491 * this will have repercussions on other devices that need to 9492 * be submitted to the hotplug thread. After a quick glance 9493 * at the SCSI-3 spec, it was found that the spec doesn't 9494 * mandate a forever retry, rather recommends a delayed retry. 9495 * 9496 * Since Photon IB is single threaded, STATUS_BUSY is common 9497 * in a 4+initiator environment. Make sure the total time 9498 * spent on retries (including command timeout) does not 9499 * 60 seconds 9500 */ 9501 static void 9502 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9503 { 9504 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9505 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9506 9507 mutex_enter(&pptr->port_mutex); 9508 mutex_enter(&ptgt->tgt_mutex); 9509 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9510 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9511 fcp_trace, FCP_BUF_LEVEL_2, 0, 9512 "fcp_queue_ipkt,1:state change occured" 9513 " for D_ID=0x%x", ptgt->tgt_d_id); 9514 mutex_exit(&ptgt->tgt_mutex); 9515 mutex_exit(&pptr->port_mutex); 9516 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9517 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9518 fcp_icmd_free(pptr, icmd); 9519 return; 9520 } 9521 mutex_exit(&ptgt->tgt_mutex); 9522 9523 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9524 9525 if (pptr->port_ipkt_list != NULL) { 9526 /* add pkt to front of doubly-linked list */ 9527 pptr->port_ipkt_list->ipkt_prev = icmd; 9528 icmd->ipkt_next = pptr->port_ipkt_list; 9529 pptr->port_ipkt_list = icmd; 9530 icmd->ipkt_prev = NULL; 9531 } else { 9532 /* this is the first/only pkt on the list */ 9533 pptr->port_ipkt_list = icmd; 9534 icmd->ipkt_next = NULL; 9535 icmd->ipkt_prev = NULL; 9536 } 9537 mutex_exit(&pptr->port_mutex); 9538 } 9539 9540 /* 9541 * Function: fcp_transport 9542 * 9543 * Description: This function submits the Fibre Channel packet to the transort 9544 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9545 * fails the submission, the treatment depends on the value of 9546 * the variable internal. 9547 * 9548 * Argument: port_handle fp/fctl port handle. 9549 * *fpkt Packet to submit to the transport layer. 9550 * internal Not zero when it's an internal packet. 9551 * 9552 * Return Value: FC_TRAN_BUSY 9553 * FC_STATEC_BUSY 9554 * FC_OFFLINE 9555 * FC_LOGINREQ 9556 * FC_DEVICE_BUSY 9557 * FC_SUCCESS 9558 */ 9559 static int 9560 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9561 { 9562 int rval; 9563 9564 rval = fc_ulp_transport(port_handle, fpkt); 9565 if (rval == FC_SUCCESS) { 9566 return (rval); 9567 } 9568 9569 /* 9570 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9571 * a command, if the underlying modules see that there is a state 9572 * change, or if a port is OFFLINE, that means, that state change 9573 * hasn't reached FCP yet, so re-queue the command for deferred 9574 * submission. 9575 */ 9576 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9577 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9578 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9579 /* 9580 * Defer packet re-submission. Life hang is possible on 9581 * internal commands if the port driver sends FC_STATEC_BUSY 9582 * for ever, but that shouldn't happen in a good environment. 9583 * Limiting re-transport for internal commands is probably a 9584 * good idea.. 9585 * A race condition can happen when a port sees barrage of 9586 * link transitions offline to online. If the FCTL has 9587 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9588 * internal commands should be queued to do the discovery. 9589 * The race condition is when an online comes and FCP starts 9590 * its internal discovery and the link goes offline. It is 9591 * possible that the statec_callback has not reached FCP 9592 * and FCP is carrying on with its internal discovery. 9593 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9594 * that the link has gone offline. At this point FCP should 9595 * drop all the internal commands and wait for the 9596 * statec_callback. It will be facilitated by incrementing 9597 * port_link_cnt. 9598 * 9599 * For external commands, the (FC)pkt_timeout is decremented 9600 * by the QUEUE Delay added by our driver, Care is taken to 9601 * ensure that it doesn't become zero (zero means no timeout) 9602 * If the time expires right inside driver queue itself, 9603 * the watch thread will return it to the original caller 9604 * indicating that the command has timed-out. 9605 */ 9606 if (internal) { 9607 char *op; 9608 struct fcp_ipkt *icmd; 9609 9610 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9611 switch (icmd->ipkt_opcode) { 9612 case SCMD_REPORT_LUN: 9613 op = "REPORT LUN"; 9614 break; 9615 9616 case SCMD_INQUIRY: 9617 op = "INQUIRY"; 9618 break; 9619 9620 case SCMD_INQUIRY_PAGE83: 9621 op = "INQUIRY-83"; 9622 break; 9623 9624 default: 9625 op = "Internal SCSI COMMAND"; 9626 break; 9627 } 9628 9629 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9630 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9631 rval = FC_SUCCESS; 9632 } 9633 } else { 9634 struct fcp_pkt *cmd; 9635 struct fcp_port *pptr; 9636 9637 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9638 cmd->cmd_state = FCP_PKT_IDLE; 9639 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9640 9641 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9642 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9643 fcp_trace, FCP_BUF_LEVEL_9, 0, 9644 "fcp_transport: xport busy for pkt %p", 9645 cmd->cmd_pkt); 9646 rval = FC_TRAN_BUSY; 9647 } else { 9648 fcp_queue_pkt(pptr, cmd); 9649 rval = FC_SUCCESS; 9650 } 9651 } 9652 } 9653 9654 return (rval); 9655 } 9656 9657 /*VARARGS3*/ 9658 static void 9659 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9660 { 9661 char buf[256]; 9662 va_list ap; 9663 9664 if (dip == NULL) { 9665 dip = fcp_global_dip; 9666 } 9667 9668 va_start(ap, fmt); 9669 (void) vsprintf(buf, fmt, ap); 9670 va_end(ap); 9671 9672 scsi_log(dip, "fcp", level, buf); 9673 } 9674 9675 /* 9676 * This function retries NS registry of FC4 type. 9677 * It assumes that fcp_mutex is held. 9678 * The function does nothing if topology is not fabric 9679 * So, the topology has to be set before this function can be called 9680 */ 9681 static void 9682 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9683 { 9684 int rval; 9685 9686 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9687 9688 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9689 ((pptr->port_topology != FC_TOP_FABRIC) && 9690 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9691 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9692 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9693 } 9694 return; 9695 } 9696 mutex_exit(&pptr->port_mutex); 9697 rval = fcp_do_ns_registry(pptr, s_id); 9698 mutex_enter(&pptr->port_mutex); 9699 9700 if (rval == 0) { 9701 /* Registry successful. Reset flag */ 9702 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9703 } 9704 } 9705 9706 /* 9707 * This function registers the ULP with the switch by calling transport i/f 9708 */ 9709 static int 9710 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9711 { 9712 fc_ns_cmd_t ns_cmd; 9713 ns_rfc_type_t rfc; 9714 uint32_t types[8]; 9715 9716 /* 9717 * Prepare the Name server structure to 9718 * register with the transport in case of 9719 * Fabric configuration. 9720 */ 9721 bzero(&rfc, sizeof (rfc)); 9722 bzero(types, sizeof (types)); 9723 9724 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9725 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9726 9727 rfc.rfc_port_id.port_id = s_id; 9728 bcopy(types, rfc.rfc_types, sizeof (types)); 9729 9730 ns_cmd.ns_flags = 0; 9731 ns_cmd.ns_cmd = NS_RFT_ID; 9732 ns_cmd.ns_req_len = sizeof (rfc); 9733 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9734 ns_cmd.ns_resp_len = 0; 9735 ns_cmd.ns_resp_payload = NULL; 9736 9737 /* 9738 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9739 */ 9740 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9741 fcp_log(CE_WARN, pptr->port_dip, 9742 "!ns_registry: failed name server registration"); 9743 return (1); 9744 } 9745 9746 return (0); 9747 } 9748 9749 /* 9750 * Function: fcp_handle_port_attach 9751 * 9752 * Description: This function is called from fcp_port_attach() to attach a 9753 * new port. This routine does the following: 9754 * 9755 * 1) Allocates an fcp_port structure and initializes it. 9756 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9757 * server. 9758 * 3) Kicks off the enumeration of the targets/luns visible 9759 * through this new port. That is done by calling 9760 * fcp_statec_callback() if the port is online. 9761 * 9762 * Argument: ulph fp/fctl port handle. 9763 * *pinfo Port information. 9764 * s_id Port ID. 9765 * instance Device instance number for the local port 9766 * (returned by ddi_get_instance()). 9767 * 9768 * Return Value: DDI_SUCCESS 9769 * DDI_FAILURE 9770 * 9771 * Context: User and Kernel context. 9772 */ 9773 /*ARGSUSED*/ 9774 int 9775 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9776 uint32_t s_id, int instance) 9777 { 9778 int res = DDI_FAILURE; 9779 scsi_hba_tran_t *tran; 9780 int mutex_initted = FALSE; 9781 int hba_attached = FALSE; 9782 int soft_state_linked = FALSE; 9783 int event_bind = FALSE; 9784 struct fcp_port *pptr; 9785 fc_portmap_t *tmp_list = NULL; 9786 uint32_t max_cnt, alloc_cnt; 9787 uchar_t *boot_wwn = NULL; 9788 uint_t nbytes; 9789 int manual_cfg; 9790 9791 /* 9792 * this port instance attaching for the first time (or after 9793 * being detached before) 9794 */ 9795 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9796 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9797 9798 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9799 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9800 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9801 instance); 9802 return (res); 9803 } 9804 9805 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9806 /* this shouldn't happen */ 9807 ddi_soft_state_free(fcp_softstate, instance); 9808 cmn_err(CE_WARN, "fcp: bad soft state"); 9809 return (res); 9810 } 9811 9812 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9813 9814 /* 9815 * Make a copy of ulp_port_info as fctl allocates 9816 * a temp struct. 9817 */ 9818 (void) fcp_cp_pinfo(pptr, pinfo); 9819 9820 /* 9821 * Check for manual_configuration_only property. 9822 * Enable manual configurtion if the property is 9823 * set to 1, otherwise disable manual configuration. 9824 */ 9825 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9826 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9827 MANUAL_CFG_ONLY, 9828 -1)) != -1) { 9829 if (manual_cfg == 1) { 9830 char *pathname; 9831 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9832 (void) ddi_pathname(pptr->port_dip, pathname); 9833 cmn_err(CE_NOTE, 9834 "%s (%s%d) %s is enabled via %s.conf.", 9835 pathname, 9836 ddi_driver_name(pptr->port_dip), 9837 ddi_get_instance(pptr->port_dip), 9838 MANUAL_CFG_ONLY, 9839 ddi_driver_name(pptr->port_dip)); 9840 fcp_enable_auto_configuration = 0; 9841 kmem_free(pathname, MAXPATHLEN); 9842 } 9843 } 9844 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9845 pptr->port_link_cnt = 1; 9846 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9847 pptr->port_id = s_id; 9848 pptr->port_instance = instance; 9849 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9850 pptr->port_state = FCP_STATE_INIT; 9851 if (pinfo->port_acc_attr == NULL) { 9852 /* 9853 * The corresponding FCA doesn't support DMA at all 9854 */ 9855 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9856 } 9857 9858 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9859 9860 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9861 /* 9862 * If FCA supports DMA in SCSI data phase, we need preallocate 9863 * dma cookie, so stash the cookie size 9864 */ 9865 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9866 pptr->port_data_dma_attr.dma_attr_sgllen; 9867 } 9868 9869 /* 9870 * The two mutexes of fcp_port are initialized. The variable 9871 * mutex_initted is incremented to remember that fact. That variable 9872 * is checked when the routine fails and the mutexes have to be 9873 * destroyed. 9874 */ 9875 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9876 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9877 mutex_initted++; 9878 9879 /* 9880 * The SCSI tran structure is allocate and initialized now. 9881 */ 9882 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9883 fcp_log(CE_WARN, pptr->port_dip, 9884 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9885 goto fail; 9886 } 9887 9888 /* link in the transport structure then fill it in */ 9889 pptr->port_tran = tran; 9890 tran->tran_hba_private = pptr; 9891 tran->tran_tgt_init = fcp_scsi_tgt_init; 9892 tran->tran_tgt_probe = NULL; 9893 tran->tran_tgt_free = fcp_scsi_tgt_free; 9894 tran->tran_start = fcp_scsi_start; 9895 tran->tran_reset = fcp_scsi_reset; 9896 tran->tran_abort = fcp_scsi_abort; 9897 tran->tran_getcap = fcp_scsi_getcap; 9898 tran->tran_setcap = fcp_scsi_setcap; 9899 tran->tran_init_pkt = NULL; 9900 tran->tran_destroy_pkt = NULL; 9901 tran->tran_dmafree = NULL; 9902 tran->tran_sync_pkt = NULL; 9903 tran->tran_reset_notify = fcp_scsi_reset_notify; 9904 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9905 tran->tran_get_name = fcp_scsi_get_name; 9906 tran->tran_clear_aca = NULL; 9907 tran->tran_clear_task_set = NULL; 9908 tran->tran_terminate_task = NULL; 9909 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9910 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9911 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9912 tran->tran_post_event = fcp_scsi_bus_post_event; 9913 tran->tran_quiesce = NULL; 9914 tran->tran_unquiesce = NULL; 9915 tran->tran_bus_reset = NULL; 9916 tran->tran_bus_config = fcp_scsi_bus_config; 9917 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9918 tran->tran_bus_power = NULL; 9919 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9920 9921 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9922 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9923 tran->tran_setup_pkt = fcp_pkt_setup; 9924 tran->tran_teardown_pkt = fcp_pkt_teardown; 9925 tran->tran_hba_len = pptr->port_priv_pkt_len + 9926 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9927 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9928 /* 9929 * If FCA don't support DMA, then we use different vectors to 9930 * minimize the effects on DMA code flow path 9931 */ 9932 tran->tran_start = fcp_pseudo_start; 9933 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9934 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9935 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9936 tran->tran_dmafree = fcp_pseudo_dmafree; 9937 tran->tran_setup_pkt = NULL; 9938 tran->tran_teardown_pkt = NULL; 9939 tran->tran_pkt_constructor = NULL; 9940 tran->tran_pkt_destructor = NULL; 9941 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9942 } 9943 9944 /* 9945 * Allocate an ndi event handle 9946 */ 9947 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9948 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9949 9950 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9951 sizeof (fcp_ndi_event_defs)); 9952 9953 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9954 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9955 9956 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9957 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9958 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9959 9960 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9961 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9962 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9963 goto fail; 9964 } 9965 event_bind++; /* Checked in fail case */ 9966 9967 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9968 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9969 != DDI_SUCCESS) { 9970 fcp_log(CE_WARN, pptr->port_dip, 9971 "!fcp%d: scsi_hba_attach_setup failed", instance); 9972 goto fail; 9973 } 9974 hba_attached++; /* Checked in fail case */ 9975 9976 pptr->port_mpxio = 0; 9977 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9978 MDI_SUCCESS) { 9979 pptr->port_mpxio++; 9980 } 9981 9982 /* 9983 * The following code is putting the new port structure in the global 9984 * list of ports and, if it is the first port to attach, it start the 9985 * fcp_watchdog_tick. 9986 * 9987 * Why put this new port in the global before we are done attaching it? 9988 * We are actually making the structure globally known before we are 9989 * done attaching it. The reason for that is: because of the code that 9990 * follows. At this point the resources to handle the port are 9991 * allocated. This function is now going to do the following: 9992 * 9993 * 1) It is going to try to register with the name server advertizing 9994 * the new FCP capability of the port. 9995 * 2) It is going to play the role of the fp/fctl layer by building 9996 * a list of worlwide names reachable through this port and call 9997 * itself on fcp_statec_callback(). That requires the port to 9998 * be part of the global list. 9999 */ 10000 mutex_enter(&fcp_global_mutex); 10001 if (fcp_port_head == NULL) { 10002 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 10003 } 10004 pptr->port_next = fcp_port_head; 10005 fcp_port_head = pptr; 10006 soft_state_linked++; 10007 10008 if (fcp_watchdog_init++ == 0) { 10009 fcp_watchdog_tick = fcp_watchdog_timeout * 10010 drv_usectohz(1000000); 10011 fcp_watchdog_id = timeout(fcp_watch, NULL, 10012 fcp_watchdog_tick); 10013 } 10014 mutex_exit(&fcp_global_mutex); 10015 10016 /* 10017 * Here an attempt is made to register with the name server, the new 10018 * FCP capability. That is done using an RTF_ID to the name server. 10019 * It is done synchronously. The function fcp_do_ns_registry() 10020 * doesn't return till the name server responded. 10021 * On failures, just ignore it for now and it will get retried during 10022 * state change callbacks. We'll set a flag to show this failure 10023 */ 10024 if (fcp_do_ns_registry(pptr, s_id)) { 10025 mutex_enter(&pptr->port_mutex); 10026 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 10027 mutex_exit(&pptr->port_mutex); 10028 } else { 10029 mutex_enter(&pptr->port_mutex); 10030 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 10031 mutex_exit(&pptr->port_mutex); 10032 } 10033 10034 /* 10035 * Lookup for boot WWN property 10036 */ 10037 if (modrootloaded != 1) { 10038 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 10039 ddi_get_parent(pinfo->port_dip), 10040 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 10041 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 10042 (nbytes == FC_WWN_SIZE)) { 10043 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 10044 } 10045 if (boot_wwn) { 10046 ddi_prop_free(boot_wwn); 10047 } 10048 } 10049 10050 /* 10051 * Handle various topologies and link states. 10052 */ 10053 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10054 case FC_STATE_OFFLINE: 10055 10056 /* 10057 * we're attaching a port where the link is offline 10058 * 10059 * Wait for ONLINE, at which time a state 10060 * change will cause a statec_callback 10061 * 10062 * in the mean time, do not do anything 10063 */ 10064 res = DDI_SUCCESS; 10065 pptr->port_state |= FCP_STATE_OFFLINE; 10066 break; 10067 10068 case FC_STATE_ONLINE: { 10069 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10070 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10071 res = DDI_SUCCESS; 10072 break; 10073 } 10074 /* 10075 * discover devices and create nodes (a private 10076 * loop or point-to-point) 10077 */ 10078 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10079 10080 /* 10081 * At this point we are going to build a list of all the ports 10082 * that can be reached through this local port. It looks like 10083 * we cannot handle more than FCP_MAX_DEVICES per local port 10084 * (128). 10085 */ 10086 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10087 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10088 KM_NOSLEEP)) == NULL) { 10089 fcp_log(CE_WARN, pptr->port_dip, 10090 "!fcp%d: failed to allocate portmap", 10091 instance); 10092 goto fail; 10093 } 10094 10095 /* 10096 * fc_ulp_getportmap() is going to provide us with the list of 10097 * remote ports in the buffer we just allocated. The way the 10098 * list is going to be retrieved depends on the topology. 10099 * However, if we are connected to a Fabric, a name server 10100 * request may be sent to get the list of FCP capable ports. 10101 * It should be noted that is the case the request is 10102 * synchronous. This means we are stuck here till the name 10103 * server replies. A lot of things can change during that time 10104 * and including, may be, being called on 10105 * fcp_statec_callback() for different reasons. I'm not sure 10106 * the code can handle that. 10107 */ 10108 max_cnt = FCP_MAX_DEVICES; 10109 alloc_cnt = FCP_MAX_DEVICES; 10110 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10111 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10112 FC_SUCCESS) { 10113 caddr_t msg; 10114 10115 (void) fc_ulp_error(res, &msg); 10116 10117 /* 10118 * this just means the transport is 10119 * busy perhaps building a portmap so, 10120 * for now, succeed this port attach 10121 * when the transport has a new map, 10122 * it'll send us a state change then 10123 */ 10124 fcp_log(CE_WARN, pptr->port_dip, 10125 "!failed to get port map : %s", msg); 10126 10127 res = DDI_SUCCESS; 10128 break; /* go return result */ 10129 } 10130 if (max_cnt > alloc_cnt) { 10131 alloc_cnt = max_cnt; 10132 } 10133 10134 /* 10135 * We are now going to call fcp_statec_callback() ourselves. 10136 * By issuing this call we are trying to kick off the enumera- 10137 * tion process. 10138 */ 10139 /* 10140 * let the state change callback do the SCSI device 10141 * discovery and create the devinfos 10142 */ 10143 fcp_statec_callback(ulph, pptr->port_fp_handle, 10144 pptr->port_phys_state, pptr->port_topology, tmp_list, 10145 max_cnt, pptr->port_id); 10146 10147 res = DDI_SUCCESS; 10148 break; 10149 } 10150 10151 default: 10152 /* unknown port state */ 10153 fcp_log(CE_WARN, pptr->port_dip, 10154 "!fcp%d: invalid port state at attach=0x%x", 10155 instance, pptr->port_phys_state); 10156 10157 mutex_enter(&pptr->port_mutex); 10158 pptr->port_phys_state = FCP_STATE_OFFLINE; 10159 mutex_exit(&pptr->port_mutex); 10160 10161 res = DDI_SUCCESS; 10162 break; 10163 } 10164 10165 /* free temp list if used */ 10166 if (tmp_list != NULL) { 10167 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10168 } 10169 10170 /* note the attach time */ 10171 pptr->port_attach_time = ddi_get_lbolt64(); 10172 10173 /* all done */ 10174 return (res); 10175 10176 /* a failure we have to clean up after */ 10177 fail: 10178 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10179 10180 if (soft_state_linked) { 10181 /* remove this fcp_port from the linked list */ 10182 (void) fcp_soft_state_unlink(pptr); 10183 } 10184 10185 /* unbind and free event set */ 10186 if (pptr->port_ndi_event_hdl) { 10187 if (event_bind) { 10188 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10189 &pptr->port_ndi_events, NDI_SLEEP); 10190 } 10191 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10192 } 10193 10194 if (pptr->port_ndi_event_defs) { 10195 (void) kmem_free(pptr->port_ndi_event_defs, 10196 sizeof (fcp_ndi_event_defs)); 10197 } 10198 10199 /* 10200 * Clean up mpxio stuff 10201 */ 10202 if (pptr->port_mpxio) { 10203 (void) mdi_phci_unregister(pptr->port_dip, 0); 10204 pptr->port_mpxio--; 10205 } 10206 10207 /* undo SCSI HBA setup */ 10208 if (hba_attached) { 10209 (void) scsi_hba_detach(pptr->port_dip); 10210 } 10211 if (pptr->port_tran != NULL) { 10212 scsi_hba_tran_free(pptr->port_tran); 10213 } 10214 10215 mutex_enter(&fcp_global_mutex); 10216 10217 /* 10218 * We check soft_state_linked, because it is incremented right before 10219 * we call increment fcp_watchdog_init. Therefore, we know if 10220 * soft_state_linked is still FALSE, we do not want to decrement 10221 * fcp_watchdog_init or possibly call untimeout. 10222 */ 10223 10224 if (soft_state_linked) { 10225 if (--fcp_watchdog_init == 0) { 10226 timeout_id_t tid = fcp_watchdog_id; 10227 10228 mutex_exit(&fcp_global_mutex); 10229 (void) untimeout(tid); 10230 } else { 10231 mutex_exit(&fcp_global_mutex); 10232 } 10233 } else { 10234 mutex_exit(&fcp_global_mutex); 10235 } 10236 10237 if (mutex_initted) { 10238 mutex_destroy(&pptr->port_mutex); 10239 mutex_destroy(&pptr->port_pkt_mutex); 10240 } 10241 10242 if (tmp_list != NULL) { 10243 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10244 } 10245 10246 /* this makes pptr invalid */ 10247 ddi_soft_state_free(fcp_softstate, instance); 10248 10249 return (DDI_FAILURE); 10250 } 10251 10252 10253 static int 10254 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10255 { 10256 int count = 0; 10257 10258 mutex_enter(&pptr->port_mutex); 10259 10260 /* 10261 * if the port is powered down or suspended, nothing else 10262 * to do; just return. 10263 */ 10264 if (flag != FCP_STATE_DETACHING) { 10265 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10266 FCP_STATE_SUSPENDED)) { 10267 pptr->port_state |= flag; 10268 mutex_exit(&pptr->port_mutex); 10269 return (FC_SUCCESS); 10270 } 10271 } 10272 10273 if (pptr->port_state & FCP_STATE_IN_MDI) { 10274 mutex_exit(&pptr->port_mutex); 10275 return (FC_FAILURE); 10276 } 10277 10278 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10279 fcp_trace, FCP_BUF_LEVEL_2, 0, 10280 "fcp_handle_port_detach: port is detaching"); 10281 10282 pptr->port_state |= flag; 10283 10284 /* 10285 * Wait for any ongoing reconfig/ipkt to complete, that 10286 * ensures the freeing to targets/luns is safe. 10287 * No more ref to this port should happen from statec/ioctl 10288 * after that as it was removed from the global port list. 10289 */ 10290 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10291 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10292 /* 10293 * Let's give sufficient time for reconfig/ipkt 10294 * to complete. 10295 */ 10296 if (count++ >= FCP_ICMD_DEADLINE) { 10297 break; 10298 } 10299 mutex_exit(&pptr->port_mutex); 10300 delay(drv_usectohz(1000000)); 10301 mutex_enter(&pptr->port_mutex); 10302 } 10303 10304 /* 10305 * if the driver is still busy then fail to 10306 * suspend/power down. 10307 */ 10308 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10309 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10310 pptr->port_state &= ~flag; 10311 mutex_exit(&pptr->port_mutex); 10312 return (FC_FAILURE); 10313 } 10314 10315 if (flag == FCP_STATE_DETACHING) { 10316 pptr = fcp_soft_state_unlink(pptr); 10317 ASSERT(pptr != NULL); 10318 } 10319 10320 pptr->port_link_cnt++; 10321 pptr->port_state |= FCP_STATE_OFFLINE; 10322 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10323 10324 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10325 FCP_CAUSE_LINK_DOWN); 10326 mutex_exit(&pptr->port_mutex); 10327 10328 /* kill watch dog timer if we're the last */ 10329 mutex_enter(&fcp_global_mutex); 10330 if (--fcp_watchdog_init == 0) { 10331 timeout_id_t tid = fcp_watchdog_id; 10332 mutex_exit(&fcp_global_mutex); 10333 (void) untimeout(tid); 10334 } else { 10335 mutex_exit(&fcp_global_mutex); 10336 } 10337 10338 /* clean up the port structures */ 10339 if (flag == FCP_STATE_DETACHING) { 10340 fcp_cleanup_port(pptr, instance); 10341 } 10342 10343 return (FC_SUCCESS); 10344 } 10345 10346 10347 static void 10348 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10349 { 10350 ASSERT(pptr != NULL); 10351 10352 /* unbind and free event set */ 10353 if (pptr->port_ndi_event_hdl) { 10354 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10355 &pptr->port_ndi_events, NDI_SLEEP); 10356 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10357 } 10358 10359 if (pptr->port_ndi_event_defs) { 10360 (void) kmem_free(pptr->port_ndi_event_defs, 10361 sizeof (fcp_ndi_event_defs)); 10362 } 10363 10364 /* free the lun/target structures and devinfos */ 10365 fcp_free_targets(pptr); 10366 10367 /* 10368 * Clean up mpxio stuff 10369 */ 10370 if (pptr->port_mpxio) { 10371 (void) mdi_phci_unregister(pptr->port_dip, 0); 10372 pptr->port_mpxio--; 10373 } 10374 10375 /* clean up SCSA stuff */ 10376 (void) scsi_hba_detach(pptr->port_dip); 10377 if (pptr->port_tran != NULL) { 10378 scsi_hba_tran_free(pptr->port_tran); 10379 } 10380 10381 #ifdef KSTATS_CODE 10382 /* clean up kstats */ 10383 if (pptr->fcp_ksp != NULL) { 10384 kstat_delete(pptr->fcp_ksp); 10385 } 10386 #endif 10387 10388 /* clean up soft state mutexes/condition variables */ 10389 mutex_destroy(&pptr->port_mutex); 10390 mutex_destroy(&pptr->port_pkt_mutex); 10391 10392 /* all done with soft state */ 10393 ddi_soft_state_free(fcp_softstate, instance); 10394 } 10395 10396 /* 10397 * Function: fcp_kmem_cache_constructor 10398 * 10399 * Description: This function allocates and initializes the resources required 10400 * to build a scsi_pkt structure the target driver. The result 10401 * of the allocation and initialization will be cached in the 10402 * memory cache. As DMA resources may be allocated here, that 10403 * means DMA resources will be tied up in the cache manager. 10404 * This is a tradeoff that has been made for performance reasons. 10405 * 10406 * Argument: *buf Memory to preinitialize. 10407 * *arg FCP port structure (fcp_port). 10408 * kmflags Value passed to kmem_cache_alloc() and 10409 * propagated to the constructor. 10410 * 10411 * Return Value: 0 Allocation/Initialization was successful. 10412 * -1 Allocation or Initialization failed. 10413 * 10414 * 10415 * If the returned value is 0, the buffer is initialized like this: 10416 * 10417 * +================================+ 10418 * +----> | struct scsi_pkt | 10419 * | | | 10420 * | +--- | pkt_ha_private | 10421 * | | | | 10422 * | | +================================+ 10423 * | | 10424 * | | +================================+ 10425 * | +--> | struct fcp_pkt | <---------+ 10426 * | | | | 10427 * +----- | cmd_pkt | | 10428 * | cmd_fp_pkt | ---+ | 10429 * +-------->| cmd_fcp_rsp[] | | | 10430 * | +--->| cmd_fcp_cmd[] | | | 10431 * | | |--------------------------------| | | 10432 * | | | struct fc_packet | <--+ | 10433 * | | | | | 10434 * | | | pkt_ulp_private | ----------+ 10435 * | | | pkt_fca_private | -----+ 10436 * | | | pkt_data_cookie | ---+ | 10437 * | | | pkt_cmdlen | | | 10438 * | |(a) | pkt_rsplen | | | 10439 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10440 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10441 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10442 * | pkt_resp_cookie | ---|-|--+ | | | 10443 * | pkt_cmd_dma | | | | | | | 10444 * | pkt_cmd_acc | | | | | | | 10445 * +================================+ | | | | | | 10446 * | dma_cookies | <--+ | | | | | 10447 * | | | | | | | 10448 * +================================+ | | | | | 10449 * | fca_private | <----+ | | | | 10450 * | | | | | | 10451 * +================================+ | | | | 10452 * | | | | 10453 * | | | | 10454 * +================================+ (d) | | | | 10455 * | fcp_resp cookies | <-------+ | | | 10456 * | | | | | 10457 * +================================+ | | | 10458 * | | | 10459 * +================================+ (d) | | | 10460 * | fcp_resp | <-----------+ | | 10461 * | (DMA resources associated) | | | 10462 * +================================+ | | 10463 * | | 10464 * | | 10465 * | | 10466 * +================================+ (c) | | 10467 * | fcp_cmd cookies | <---------------+ | 10468 * | | | 10469 * +================================+ | 10470 * | 10471 * +================================+ (c) | 10472 * | fcp_cmd | <--------------------+ 10473 * | (DMA resources associated) | 10474 * +================================+ 10475 * 10476 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10477 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10478 * (c) Only if DMA is used for the FCP_CMD buffer. 10479 * (d) Only if DMA is used for the FCP_RESP buffer 10480 */ 10481 static int 10482 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10483 int kmflags) 10484 { 10485 struct fcp_pkt *cmd; 10486 struct fcp_port *pptr; 10487 fc_packet_t *fpkt; 10488 10489 pptr = (struct fcp_port *)tran->tran_hba_private; 10490 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10491 bzero(cmd, tran->tran_hba_len); 10492 10493 cmd->cmd_pkt = pkt; 10494 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10495 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10496 cmd->cmd_fp_pkt = fpkt; 10497 10498 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10499 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10500 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10501 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10502 10503 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10504 sizeof (struct fcp_pkt)); 10505 10506 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10507 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10508 10509 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10510 /* 10511 * The underlying HBA doesn't want to DMA the fcp_cmd or 10512 * fcp_resp. The transfer of information will be done by 10513 * bcopy. 10514 * The naming of the flags (that is actually a value) is 10515 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10516 * DMA" but instead "NO DMA". 10517 */ 10518 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10519 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10520 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10521 } else { 10522 /* 10523 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10524 * buffer. A buffer is allocated for each one the ddi_dma_* 10525 * interfaces. 10526 */ 10527 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10528 return (-1); 10529 } 10530 } 10531 10532 return (0); 10533 } 10534 10535 /* 10536 * Function: fcp_kmem_cache_destructor 10537 * 10538 * Description: Called by the destructor of the cache managed by SCSA. 10539 * All the resources pre-allocated in fcp_pkt_constructor 10540 * and the data also pre-initialized in fcp_pkt_constructor 10541 * are freed and uninitialized here. 10542 * 10543 * Argument: *buf Memory to uninitialize. 10544 * *arg FCP port structure (fcp_port). 10545 * 10546 * Return Value: None 10547 * 10548 * Context: kernel 10549 */ 10550 static void 10551 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10552 { 10553 struct fcp_pkt *cmd; 10554 struct fcp_port *pptr; 10555 10556 pptr = (struct fcp_port *)(tran->tran_hba_private); 10557 cmd = pkt->pkt_ha_private; 10558 10559 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10560 /* 10561 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10562 * buffer and DMA resources allocated to do so are released. 10563 */ 10564 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10565 } 10566 } 10567 10568 /* 10569 * Function: fcp_alloc_cmd_resp 10570 * 10571 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10572 * will be DMAed by the HBA. The buffer is allocated applying 10573 * the DMA requirements for the HBA. The buffers allocated will 10574 * also be bound. DMA resources are allocated in the process. 10575 * They will be released by fcp_free_cmd_resp(). 10576 * 10577 * Argument: *pptr FCP port. 10578 * *fpkt fc packet for which the cmd and resp packet should be 10579 * allocated. 10580 * flags Allocation flags. 10581 * 10582 * Return Value: FC_FAILURE 10583 * FC_SUCCESS 10584 * 10585 * Context: User or Kernel context only if flags == KM_SLEEP. 10586 * Interrupt context if the KM_SLEEP is not specified. 10587 */ 10588 static int 10589 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10590 { 10591 int rval; 10592 int cmd_len; 10593 int resp_len; 10594 ulong_t real_len; 10595 int (*cb) (caddr_t); 10596 ddi_dma_cookie_t pkt_cookie; 10597 ddi_dma_cookie_t *cp; 10598 uint32_t cnt; 10599 10600 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10601 10602 cmd_len = fpkt->pkt_cmdlen; 10603 resp_len = fpkt->pkt_rsplen; 10604 10605 ASSERT(fpkt->pkt_cmd_dma == NULL); 10606 10607 /* Allocation of a DMA handle used in subsequent calls. */ 10608 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10609 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10610 return (FC_FAILURE); 10611 } 10612 10613 /* A buffer is allocated that satisfies the DMA requirements. */ 10614 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10615 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10616 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10617 10618 if (rval != DDI_SUCCESS) { 10619 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10620 return (FC_FAILURE); 10621 } 10622 10623 if (real_len < cmd_len) { 10624 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10625 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10626 return (FC_FAILURE); 10627 } 10628 10629 /* The buffer allocated is DMA bound. */ 10630 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10631 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10632 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10633 10634 if (rval != DDI_DMA_MAPPED) { 10635 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10636 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10637 return (FC_FAILURE); 10638 } 10639 10640 if (fpkt->pkt_cmd_cookie_cnt > 10641 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10642 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10643 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10644 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10645 return (FC_FAILURE); 10646 } 10647 10648 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10649 10650 /* 10651 * The buffer where the scatter/gather list is going to be built is 10652 * allocated. 10653 */ 10654 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10655 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10656 KM_NOSLEEP); 10657 10658 if (cp == NULL) { 10659 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10660 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10661 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10662 return (FC_FAILURE); 10663 } 10664 10665 /* 10666 * The scatter/gather list for the buffer we just allocated is built 10667 * here. 10668 */ 10669 *cp = pkt_cookie; 10670 cp++; 10671 10672 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10673 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10674 &pkt_cookie); 10675 *cp = pkt_cookie; 10676 } 10677 10678 ASSERT(fpkt->pkt_resp_dma == NULL); 10679 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10680 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10681 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10682 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10683 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10684 return (FC_FAILURE); 10685 } 10686 10687 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10688 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10689 (caddr_t *)&fpkt->pkt_resp, &real_len, 10690 &fpkt->pkt_resp_acc); 10691 10692 if (rval != DDI_SUCCESS) { 10693 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10694 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10695 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10696 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10697 kmem_free(fpkt->pkt_cmd_cookie, 10698 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10699 return (FC_FAILURE); 10700 } 10701 10702 if (real_len < resp_len) { 10703 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10704 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10705 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10706 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10707 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10708 kmem_free(fpkt->pkt_cmd_cookie, 10709 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10710 return (FC_FAILURE); 10711 } 10712 10713 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10714 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10715 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10716 10717 if (rval != DDI_DMA_MAPPED) { 10718 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10719 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10720 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10721 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10722 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10723 kmem_free(fpkt->pkt_cmd_cookie, 10724 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10725 return (FC_FAILURE); 10726 } 10727 10728 if (fpkt->pkt_resp_cookie_cnt > 10729 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10730 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10731 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10732 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10733 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10734 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10735 kmem_free(fpkt->pkt_cmd_cookie, 10736 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10737 return (FC_FAILURE); 10738 } 10739 10740 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10741 10742 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10743 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10744 KM_NOSLEEP); 10745 10746 if (cp == NULL) { 10747 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10748 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10749 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10750 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10751 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10752 kmem_free(fpkt->pkt_cmd_cookie, 10753 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10754 return (FC_FAILURE); 10755 } 10756 10757 *cp = pkt_cookie; 10758 cp++; 10759 10760 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10761 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10762 &pkt_cookie); 10763 *cp = pkt_cookie; 10764 } 10765 10766 return (FC_SUCCESS); 10767 } 10768 10769 /* 10770 * Function: fcp_free_cmd_resp 10771 * 10772 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10773 * allocated by fcp_alloc_cmd_resp() and all the resources 10774 * associated with them. That includes the DMA resources and the 10775 * buffer allocated for the cookies of each one of them. 10776 * 10777 * Argument: *pptr FCP port context. 10778 * *fpkt fc packet containing the cmd and resp packet 10779 * to be released. 10780 * 10781 * Return Value: None 10782 * 10783 * Context: Interrupt, User and Kernel context. 10784 */ 10785 /* ARGSUSED */ 10786 static void 10787 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10788 { 10789 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10790 10791 if (fpkt->pkt_resp_dma) { 10792 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10793 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10794 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10795 } 10796 10797 if (fpkt->pkt_resp_cookie) { 10798 kmem_free(fpkt->pkt_resp_cookie, 10799 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10800 fpkt->pkt_resp_cookie = NULL; 10801 } 10802 10803 if (fpkt->pkt_cmd_dma) { 10804 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10805 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10806 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10807 } 10808 10809 if (fpkt->pkt_cmd_cookie) { 10810 kmem_free(fpkt->pkt_cmd_cookie, 10811 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10812 fpkt->pkt_cmd_cookie = NULL; 10813 } 10814 } 10815 10816 10817 /* 10818 * called by the transport to do our own target initialization 10819 * 10820 * can acquire and release the global mutex 10821 */ 10822 /* ARGSUSED */ 10823 static int 10824 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10825 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10826 { 10827 uchar_t *bytes; 10828 uint_t nbytes; 10829 uint16_t lun_num; 10830 struct fcp_tgt *ptgt; 10831 struct fcp_lun *plun; 10832 struct fcp_port *pptr = (struct fcp_port *) 10833 hba_tran->tran_hba_private; 10834 10835 ASSERT(pptr != NULL); 10836 10837 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10838 FCP_BUF_LEVEL_8, 0, 10839 "fcp_phys_tgt_init: called for %s (instance %d)", 10840 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10841 10842 /* get our port WWN property */ 10843 bytes = NULL; 10844 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10845 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10846 (nbytes != FC_WWN_SIZE)) { 10847 /* no port WWN property */ 10848 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10849 FCP_BUF_LEVEL_8, 0, 10850 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10851 " for %s (instance %d): bytes=%p nbytes=%x", 10852 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10853 nbytes); 10854 10855 if (bytes != NULL) { 10856 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10857 } 10858 10859 return (DDI_NOT_WELL_FORMED); 10860 } 10861 ASSERT(bytes != NULL); 10862 10863 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10864 LUN_PROP, 0xFFFF); 10865 if (lun_num == 0xFFFF) { 10866 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10867 FCP_BUF_LEVEL_8, 0, 10868 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10869 " for %s (instance %d)", ddi_get_name(tgt_dip), 10870 ddi_get_instance(tgt_dip)); 10871 10872 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10873 return (DDI_NOT_WELL_FORMED); 10874 } 10875 10876 mutex_enter(&pptr->port_mutex); 10877 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10878 mutex_exit(&pptr->port_mutex); 10879 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10880 FCP_BUF_LEVEL_8, 0, 10881 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10882 " for %s (instance %d)", ddi_get_name(tgt_dip), 10883 ddi_get_instance(tgt_dip)); 10884 10885 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10886 return (DDI_FAILURE); 10887 } 10888 10889 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10890 FC_WWN_SIZE) == 0); 10891 ASSERT(plun->lun_num == lun_num); 10892 10893 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10894 10895 ptgt = plun->lun_tgt; 10896 10897 mutex_enter(&ptgt->tgt_mutex); 10898 plun->lun_tgt_count++; 10899 scsi_device_hba_private_set(sd, plun); 10900 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10901 plun->lun_sd = sd; 10902 mutex_exit(&ptgt->tgt_mutex); 10903 mutex_exit(&pptr->port_mutex); 10904 10905 return (DDI_SUCCESS); 10906 } 10907 10908 /*ARGSUSED*/ 10909 static int 10910 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10911 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10912 { 10913 uchar_t *bytes; 10914 uint_t nbytes; 10915 uint16_t lun_num; 10916 struct fcp_tgt *ptgt; 10917 struct fcp_lun *plun; 10918 struct fcp_port *pptr = (struct fcp_port *) 10919 hba_tran->tran_hba_private; 10920 child_info_t *cip; 10921 10922 ASSERT(pptr != NULL); 10923 10924 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10925 fcp_trace, FCP_BUF_LEVEL_8, 0, 10926 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10927 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10928 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10929 10930 cip = (child_info_t *)sd->sd_pathinfo; 10931 if (cip == NULL) { 10932 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10933 fcp_trace, FCP_BUF_LEVEL_8, 0, 10934 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10935 " for %s (instance %d)", ddi_get_name(tgt_dip), 10936 ddi_get_instance(tgt_dip)); 10937 10938 return (DDI_NOT_WELL_FORMED); 10939 } 10940 10941 /* get our port WWN property */ 10942 bytes = NULL; 10943 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10944 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10945 (nbytes != FC_WWN_SIZE)) { 10946 if (bytes) { 10947 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10948 } 10949 return (DDI_NOT_WELL_FORMED); 10950 } 10951 10952 ASSERT(bytes != NULL); 10953 10954 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10955 LUN_PROP, 0xFFFF); 10956 if (lun_num == 0xFFFF) { 10957 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10958 fcp_trace, FCP_BUF_LEVEL_8, 0, 10959 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10960 " for %s (instance %d)", ddi_get_name(tgt_dip), 10961 ddi_get_instance(tgt_dip)); 10962 10963 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10964 return (DDI_NOT_WELL_FORMED); 10965 } 10966 10967 mutex_enter(&pptr->port_mutex); 10968 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10969 mutex_exit(&pptr->port_mutex); 10970 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10971 fcp_trace, FCP_BUF_LEVEL_8, 0, 10972 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10973 " for %s (instance %d)", ddi_get_name(tgt_dip), 10974 ddi_get_instance(tgt_dip)); 10975 10976 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10977 return (DDI_FAILURE); 10978 } 10979 10980 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10981 FC_WWN_SIZE) == 0); 10982 ASSERT(plun->lun_num == lun_num); 10983 10984 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10985 10986 ptgt = plun->lun_tgt; 10987 10988 mutex_enter(&ptgt->tgt_mutex); 10989 plun->lun_tgt_count++; 10990 scsi_device_hba_private_set(sd, plun); 10991 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10992 plun->lun_sd = sd; 10993 mutex_exit(&ptgt->tgt_mutex); 10994 mutex_exit(&pptr->port_mutex); 10995 10996 return (DDI_SUCCESS); 10997 } 10998 10999 11000 /* 11001 * called by the transport to do our own target initialization 11002 * 11003 * can acquire and release the global mutex 11004 */ 11005 /* ARGSUSED */ 11006 static int 11007 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11008 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11009 { 11010 struct fcp_port *pptr = (struct fcp_port *) 11011 hba_tran->tran_hba_private; 11012 int rval; 11013 11014 ASSERT(pptr != NULL); 11015 11016 /* 11017 * Child node is getting initialized. Look at the mpxio component 11018 * type on the child device to see if this device is mpxio managed 11019 * or not. 11020 */ 11021 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 11022 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11023 } else { 11024 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11025 } 11026 11027 return (rval); 11028 } 11029 11030 11031 /* ARGSUSED */ 11032 static void 11033 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11034 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11035 { 11036 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 11037 struct fcp_tgt *ptgt; 11038 11039 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 11040 fcp_trace, FCP_BUF_LEVEL_8, 0, 11041 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 11042 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 11043 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 11044 11045 if (plun == NULL) { 11046 return; 11047 } 11048 ptgt = plun->lun_tgt; 11049 11050 ASSERT(ptgt != NULL); 11051 11052 mutex_enter(&ptgt->tgt_mutex); 11053 ASSERT(plun->lun_tgt_count > 0); 11054 11055 if (--plun->lun_tgt_count == 0) { 11056 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11057 } 11058 plun->lun_sd = NULL; 11059 mutex_exit(&ptgt->tgt_mutex); 11060 } 11061 11062 /* 11063 * Function: fcp_scsi_start 11064 * 11065 * Description: This function is called by the target driver to request a 11066 * command to be sent. 11067 * 11068 * Argument: *ap SCSI address of the device. 11069 * *pkt SCSI packet containing the cmd to send. 11070 * 11071 * Return Value: TRAN_ACCEPT 11072 * TRAN_BUSY 11073 * TRAN_BADPKT 11074 * TRAN_FATAL_ERROR 11075 */ 11076 static int 11077 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11078 { 11079 struct fcp_port *pptr = ADDR2FCP(ap); 11080 struct fcp_lun *plun = ADDR2LUN(ap); 11081 struct fcp_pkt *cmd = PKT2CMD(pkt); 11082 struct fcp_tgt *ptgt = plun->lun_tgt; 11083 int rval; 11084 11085 /* ensure command isn't already issued */ 11086 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11087 11088 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11089 fcp_trace, FCP_BUF_LEVEL_9, 0, 11090 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11091 11092 /* 11093 * It is strange that we enter the fcp_port mutex and the target 11094 * mutex to check the lun state (which has a mutex of its own). 11095 */ 11096 mutex_enter(&pptr->port_mutex); 11097 mutex_enter(&ptgt->tgt_mutex); 11098 11099 /* 11100 * If the device is offline and is not in the process of coming 11101 * online, fail the request. 11102 */ 11103 11104 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11105 !(plun->lun_state & FCP_LUN_ONLINING)) { 11106 mutex_exit(&ptgt->tgt_mutex); 11107 mutex_exit(&pptr->port_mutex); 11108 11109 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11110 pkt->pkt_reason = CMD_DEV_GONE; 11111 } 11112 11113 return (TRAN_FATAL_ERROR); 11114 } 11115 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11116 11117 /* 11118 * If we are suspended, kernel is trying to dump, so don't 11119 * block, fail or defer requests - send them down right away. 11120 * NOTE: If we are in panic (i.e. trying to dump), we can't 11121 * assume we have been suspended. There is hardware such as 11122 * the v880 that doesn't do PM. Thus, the check for 11123 * ddi_in_panic. 11124 * 11125 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11126 * of changing. So, if we can queue the packet, do it. Eventually, 11127 * either the device will have gone away or changed and we can fail 11128 * the request, or we can proceed if the device didn't change. 11129 * 11130 * If the pd in the target or the packet is NULL it's probably 11131 * because the device has gone away, we allow the request to be 11132 * put on the internal queue here in case the device comes back within 11133 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11134 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11135 * could be NULL because the device was disappearing during or since 11136 * packet initialization. 11137 */ 11138 11139 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11140 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11141 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11142 (ptgt->tgt_pd_handle == NULL) || 11143 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11144 /* 11145 * If ((LUN is busy AND 11146 * LUN not suspended AND 11147 * The system is not in panic state) OR 11148 * (The port is coming up)) 11149 * 11150 * We check to see if the any of the flags FLAG_NOINTR or 11151 * FLAG_NOQUEUE is set. If one of them is set the value 11152 * returned will be TRAN_BUSY. If not, the request is queued. 11153 */ 11154 mutex_exit(&ptgt->tgt_mutex); 11155 mutex_exit(&pptr->port_mutex); 11156 11157 /* see if using interrupts is allowed (so queueing'll work) */ 11158 if (pkt->pkt_flags & FLAG_NOINTR) { 11159 pkt->pkt_resid = 0; 11160 return (TRAN_BUSY); 11161 } 11162 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11163 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11164 fcp_trace, FCP_BUF_LEVEL_9, 0, 11165 "fcp_scsi_start: lun busy for pkt %p", pkt); 11166 return (TRAN_BUSY); 11167 } 11168 #ifdef DEBUG 11169 mutex_enter(&pptr->port_pkt_mutex); 11170 pptr->port_npkts++; 11171 mutex_exit(&pptr->port_pkt_mutex); 11172 #endif /* DEBUG */ 11173 11174 /* got queue up the pkt for later */ 11175 fcp_queue_pkt(pptr, cmd); 11176 return (TRAN_ACCEPT); 11177 } 11178 cmd->cmd_state = FCP_PKT_ISSUED; 11179 11180 mutex_exit(&ptgt->tgt_mutex); 11181 mutex_exit(&pptr->port_mutex); 11182 11183 /* 11184 * Now that we released the mutexes, what was protected by them can 11185 * change. 11186 */ 11187 11188 /* 11189 * If there is a reconfiguration in progress, wait for it to complete. 11190 */ 11191 fcp_reconfig_wait(pptr); 11192 11193 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11194 pkt->pkt_time : 0; 11195 11196 /* prepare the packet */ 11197 11198 fcp_prepare_pkt(pptr, cmd, plun); 11199 11200 if (cmd->cmd_pkt->pkt_time) { 11201 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11202 } else { 11203 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11204 } 11205 11206 /* 11207 * if interrupts aren't allowed (e.g. at dump time) then we'll 11208 * have to do polled I/O 11209 */ 11210 if (pkt->pkt_flags & FLAG_NOINTR) { 11211 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11212 return (fcp_dopoll(pptr, cmd)); 11213 } 11214 11215 #ifdef DEBUG 11216 mutex_enter(&pptr->port_pkt_mutex); 11217 pptr->port_npkts++; 11218 mutex_exit(&pptr->port_pkt_mutex); 11219 #endif /* DEBUG */ 11220 11221 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11222 if (rval == FC_SUCCESS) { 11223 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11224 fcp_trace, FCP_BUF_LEVEL_9, 0, 11225 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11226 return (TRAN_ACCEPT); 11227 } 11228 11229 cmd->cmd_state = FCP_PKT_IDLE; 11230 11231 #ifdef DEBUG 11232 mutex_enter(&pptr->port_pkt_mutex); 11233 pptr->port_npkts--; 11234 mutex_exit(&pptr->port_pkt_mutex); 11235 #endif /* DEBUG */ 11236 11237 /* 11238 * For lack of clearer definitions, choose 11239 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11240 */ 11241 11242 if (rval == FC_TRAN_BUSY) { 11243 pkt->pkt_resid = 0; 11244 rval = TRAN_BUSY; 11245 } else { 11246 mutex_enter(&ptgt->tgt_mutex); 11247 if (plun->lun_state & FCP_LUN_OFFLINE) { 11248 child_info_t *cip; 11249 11250 mutex_enter(&plun->lun_mutex); 11251 cip = plun->lun_cip; 11252 mutex_exit(&plun->lun_mutex); 11253 11254 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11255 fcp_trace, FCP_BUF_LEVEL_6, 0, 11256 "fcp_transport failed 2 for %x: %x; dip=%p", 11257 plun->lun_tgt->tgt_d_id, rval, cip); 11258 11259 rval = TRAN_FATAL_ERROR; 11260 } else { 11261 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11262 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11263 fcp_trace, FCP_BUF_LEVEL_9, 0, 11264 "fcp_scsi_start: FC_BUSY for pkt %p", 11265 pkt); 11266 rval = TRAN_BUSY; 11267 } else { 11268 rval = TRAN_ACCEPT; 11269 fcp_queue_pkt(pptr, cmd); 11270 } 11271 } 11272 mutex_exit(&ptgt->tgt_mutex); 11273 } 11274 11275 return (rval); 11276 } 11277 11278 /* 11279 * called by the transport to abort a packet 11280 */ 11281 /*ARGSUSED*/ 11282 static int 11283 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11284 { 11285 int tgt_cnt; 11286 struct fcp_port *pptr = ADDR2FCP(ap); 11287 struct fcp_lun *plun = ADDR2LUN(ap); 11288 struct fcp_tgt *ptgt = plun->lun_tgt; 11289 11290 if (pkt == NULL) { 11291 if (ptgt) { 11292 mutex_enter(&ptgt->tgt_mutex); 11293 tgt_cnt = ptgt->tgt_change_cnt; 11294 mutex_exit(&ptgt->tgt_mutex); 11295 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11296 return (TRUE); 11297 } 11298 } 11299 return (FALSE); 11300 } 11301 11302 11303 /* 11304 * Perform reset 11305 */ 11306 int 11307 fcp_scsi_reset(struct scsi_address *ap, int level) 11308 { 11309 int rval = 0; 11310 struct fcp_port *pptr = ADDR2FCP(ap); 11311 struct fcp_lun *plun = ADDR2LUN(ap); 11312 struct fcp_tgt *ptgt = plun->lun_tgt; 11313 11314 if (level == RESET_ALL) { 11315 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11316 rval = 1; 11317 } 11318 } else if (level == RESET_TARGET || level == RESET_LUN) { 11319 /* 11320 * If we are in the middle of discovery, return 11321 * SUCCESS as this target will be rediscovered 11322 * anyway 11323 */ 11324 mutex_enter(&ptgt->tgt_mutex); 11325 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11326 mutex_exit(&ptgt->tgt_mutex); 11327 return (1); 11328 } 11329 mutex_exit(&ptgt->tgt_mutex); 11330 11331 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11332 rval = 1; 11333 } 11334 } 11335 return (rval); 11336 } 11337 11338 11339 /* 11340 * called by the framework to get a SCSI capability 11341 */ 11342 static int 11343 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11344 { 11345 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11346 } 11347 11348 11349 /* 11350 * called by the framework to set a SCSI capability 11351 */ 11352 static int 11353 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11354 { 11355 return (fcp_commoncap(ap, cap, value, whom, 1)); 11356 } 11357 11358 /* 11359 * Function: fcp_pkt_setup 11360 * 11361 * Description: This function sets up the scsi_pkt structure passed by the 11362 * caller. This function assumes fcp_pkt_constructor has been 11363 * called previously for the packet passed by the caller. If 11364 * successful this call will have the following results: 11365 * 11366 * - The resources needed that will be constant through out 11367 * the whole transaction are allocated. 11368 * - The fields that will be constant through out the whole 11369 * transaction are initialized. 11370 * - The scsi packet will be linked to the LUN structure 11371 * addressed by the transaction. 11372 * 11373 * Argument: 11374 * *pkt Pointer to a scsi_pkt structure. 11375 * callback 11376 * arg 11377 * 11378 * Return Value: 0 Success 11379 * !0 Failure 11380 * 11381 * Context: Kernel context or interrupt context 11382 */ 11383 /* ARGSUSED */ 11384 static int 11385 fcp_pkt_setup(struct scsi_pkt *pkt, 11386 int (*callback)(caddr_t arg), 11387 caddr_t arg) 11388 { 11389 struct fcp_pkt *cmd; 11390 struct fcp_port *pptr; 11391 struct fcp_lun *plun; 11392 struct fcp_tgt *ptgt; 11393 int kf; 11394 fc_packet_t *fpkt; 11395 fc_frame_hdr_t *hp; 11396 11397 pptr = ADDR2FCP(&pkt->pkt_address); 11398 plun = ADDR2LUN(&pkt->pkt_address); 11399 ptgt = plun->lun_tgt; 11400 11401 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11402 fpkt = cmd->cmd_fp_pkt; 11403 11404 /* 11405 * this request is for dma allocation only 11406 */ 11407 /* 11408 * First step of fcp_scsi_init_pkt: pkt allocation 11409 * We determine if the caller is willing to wait for the 11410 * resources. 11411 */ 11412 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11413 11414 /* 11415 * Selective zeroing of the pkt. 11416 */ 11417 cmd->cmd_back = NULL; 11418 cmd->cmd_next = NULL; 11419 11420 /* 11421 * Zero out fcp command 11422 */ 11423 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11424 11425 cmd->cmd_state = FCP_PKT_IDLE; 11426 11427 fpkt = cmd->cmd_fp_pkt; 11428 fpkt->pkt_data_acc = NULL; 11429 11430 /* 11431 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11432 * could be destroyed. We need fail pkt_setup. 11433 */ 11434 if (pptr->port_state & FCP_STATE_OFFLINE) { 11435 return (-1); 11436 } 11437 11438 mutex_enter(&ptgt->tgt_mutex); 11439 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11440 11441 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11442 != FC_SUCCESS) { 11443 mutex_exit(&ptgt->tgt_mutex); 11444 return (-1); 11445 } 11446 11447 mutex_exit(&ptgt->tgt_mutex); 11448 11449 /* Fill in the Fabric Channel Header */ 11450 hp = &fpkt->pkt_cmd_fhdr; 11451 hp->r_ctl = R_CTL_COMMAND; 11452 hp->rsvd = 0; 11453 hp->type = FC_TYPE_SCSI_FCP; 11454 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11455 hp->seq_id = 0; 11456 hp->df_ctl = 0; 11457 hp->seq_cnt = 0; 11458 hp->ox_id = 0xffff; 11459 hp->rx_id = 0xffff; 11460 hp->ro = 0; 11461 11462 /* 11463 * A doubly linked list (cmd_forw, cmd_back) is built 11464 * out of every allocated packet on a per-lun basis 11465 * 11466 * The packets are maintained in the list so as to satisfy 11467 * scsi_abort() requests. At present (which is unlikely to 11468 * change in the future) nobody performs a real scsi_abort 11469 * in the SCSI target drivers (as they don't keep the packets 11470 * after doing scsi_transport - so they don't know how to 11471 * abort a packet other than sending a NULL to abort all 11472 * outstanding packets) 11473 */ 11474 mutex_enter(&plun->lun_mutex); 11475 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11476 plun->lun_pkt_head->cmd_back = cmd; 11477 } else { 11478 plun->lun_pkt_tail = cmd; 11479 } 11480 plun->lun_pkt_head = cmd; 11481 mutex_exit(&plun->lun_mutex); 11482 return (0); 11483 } 11484 11485 /* 11486 * Function: fcp_pkt_teardown 11487 * 11488 * Description: This function releases a scsi_pkt structure and all the 11489 * resources attached to it. 11490 * 11491 * Argument: *pkt Pointer to a scsi_pkt structure. 11492 * 11493 * Return Value: None 11494 * 11495 * Context: User, Kernel or Interrupt context. 11496 */ 11497 static void 11498 fcp_pkt_teardown(struct scsi_pkt *pkt) 11499 { 11500 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11501 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11502 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11503 11504 /* 11505 * Remove the packet from the per-lun list 11506 */ 11507 mutex_enter(&plun->lun_mutex); 11508 if (cmd->cmd_back) { 11509 ASSERT(cmd != plun->lun_pkt_head); 11510 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11511 } else { 11512 ASSERT(cmd == plun->lun_pkt_head); 11513 plun->lun_pkt_head = cmd->cmd_forw; 11514 } 11515 11516 if (cmd->cmd_forw) { 11517 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11518 } else { 11519 ASSERT(cmd == plun->lun_pkt_tail); 11520 plun->lun_pkt_tail = cmd->cmd_back; 11521 } 11522 11523 mutex_exit(&plun->lun_mutex); 11524 11525 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11526 } 11527 11528 /* 11529 * Routine for reset notification setup, to register or cancel. 11530 * This function is called by SCSA 11531 */ 11532 /*ARGSUSED*/ 11533 static int 11534 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11535 void (*callback)(caddr_t), caddr_t arg) 11536 { 11537 struct fcp_port *pptr = ADDR2FCP(ap); 11538 11539 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11540 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11541 } 11542 11543 11544 static int 11545 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11546 ddi_eventcookie_t *event_cookiep) 11547 { 11548 struct fcp_port *pptr = fcp_dip2port(dip); 11549 11550 if (pptr == NULL) { 11551 return (DDI_FAILURE); 11552 } 11553 11554 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11555 event_cookiep, NDI_EVENT_NOPASS)); 11556 } 11557 11558 11559 static int 11560 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11561 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11562 ddi_callback_id_t *cb_id) 11563 { 11564 struct fcp_port *pptr = fcp_dip2port(dip); 11565 11566 if (pptr == NULL) { 11567 return (DDI_FAILURE); 11568 } 11569 11570 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11571 eventid, callback, arg, NDI_SLEEP, cb_id)); 11572 } 11573 11574 11575 static int 11576 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11577 { 11578 11579 struct fcp_port *pptr = fcp_dip2port(dip); 11580 11581 if (pptr == NULL) { 11582 return (DDI_FAILURE); 11583 } 11584 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11585 } 11586 11587 11588 /* 11589 * called by the transport to post an event 11590 */ 11591 static int 11592 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11593 ddi_eventcookie_t eventid, void *impldata) 11594 { 11595 struct fcp_port *pptr = fcp_dip2port(dip); 11596 11597 if (pptr == NULL) { 11598 return (DDI_FAILURE); 11599 } 11600 11601 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11602 eventid, impldata)); 11603 } 11604 11605 11606 /* 11607 * A target in in many cases in Fibre Channel has a one to one relation 11608 * with a port identifier (which is also known as D_ID and also as AL_PA 11609 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11610 * will most likely result in resetting all LUNs (which means a reset will 11611 * occur on all the SCSI devices connected at the other end of the bridge) 11612 * That is the latest favorite topic for discussion, for, one can debate as 11613 * hot as one likes and come up with arguably a best solution to one's 11614 * satisfaction 11615 * 11616 * To stay on track and not digress much, here are the problems stated 11617 * briefly: 11618 * 11619 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11620 * target drivers use RESET_TARGET even if their instance is on a 11621 * LUN. Doesn't that sound a bit broken ? 11622 * 11623 * FCP SCSI (the current spec) only defines RESET TARGET in the 11624 * control fields of an FCP_CMND structure. It should have been 11625 * fixed right there, giving flexibility to the initiators to 11626 * minimize havoc that could be caused by resetting a target. 11627 */ 11628 static int 11629 fcp_reset_target(struct scsi_address *ap, int level) 11630 { 11631 int rval = FC_FAILURE; 11632 char lun_id[25]; 11633 struct fcp_port *pptr = ADDR2FCP(ap); 11634 struct fcp_lun *plun = ADDR2LUN(ap); 11635 struct fcp_tgt *ptgt = plun->lun_tgt; 11636 struct scsi_pkt *pkt; 11637 struct fcp_pkt *cmd; 11638 struct fcp_rsp *rsp; 11639 uint32_t tgt_cnt; 11640 struct fcp_rsp_info *rsp_info; 11641 struct fcp_reset_elem *p; 11642 int bval; 11643 11644 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11645 KM_NOSLEEP)) == NULL) { 11646 return (rval); 11647 } 11648 11649 mutex_enter(&ptgt->tgt_mutex); 11650 if (level == RESET_TARGET) { 11651 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11652 mutex_exit(&ptgt->tgt_mutex); 11653 kmem_free(p, sizeof (struct fcp_reset_elem)); 11654 return (rval); 11655 } 11656 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11657 (void) strcpy(lun_id, " "); 11658 } else { 11659 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11660 mutex_exit(&ptgt->tgt_mutex); 11661 kmem_free(p, sizeof (struct fcp_reset_elem)); 11662 return (rval); 11663 } 11664 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11665 11666 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11667 } 11668 tgt_cnt = ptgt->tgt_change_cnt; 11669 11670 mutex_exit(&ptgt->tgt_mutex); 11671 11672 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11673 0, 0, NULL, 0)) == NULL) { 11674 kmem_free(p, sizeof (struct fcp_reset_elem)); 11675 mutex_enter(&ptgt->tgt_mutex); 11676 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11677 mutex_exit(&ptgt->tgt_mutex); 11678 return (rval); 11679 } 11680 pkt->pkt_time = FCP_POLL_TIMEOUT; 11681 11682 /* fill in cmd part of packet */ 11683 cmd = PKT2CMD(pkt); 11684 if (level == RESET_TARGET) { 11685 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11686 } else { 11687 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11688 } 11689 cmd->cmd_fp_pkt->pkt_comp = NULL; 11690 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11691 11692 /* prepare a packet for transport */ 11693 fcp_prepare_pkt(pptr, cmd, plun); 11694 11695 if (cmd->cmd_pkt->pkt_time) { 11696 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11697 } else { 11698 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11699 } 11700 11701 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11702 bval = fcp_dopoll(pptr, cmd); 11703 fc_ulp_idle_port(pptr->port_fp_handle); 11704 11705 /* submit the packet */ 11706 if (bval == TRAN_ACCEPT) { 11707 int error = 3; 11708 11709 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11710 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11711 sizeof (struct fcp_rsp)); 11712 11713 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11714 if (fcp_validate_fcp_response(rsp, pptr) == 11715 FC_SUCCESS) { 11716 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11717 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11718 sizeof (struct fcp_rsp), rsp_info, 11719 cmd->cmd_fp_pkt->pkt_resp_acc, 11720 sizeof (struct fcp_rsp_info)); 11721 } 11722 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11723 rval = FC_SUCCESS; 11724 error = 0; 11725 } else { 11726 error = 1; 11727 } 11728 } else { 11729 error = 2; 11730 } 11731 } 11732 11733 switch (error) { 11734 case 0: 11735 fcp_log(CE_WARN, pptr->port_dip, 11736 "!FCP: WWN 0x%08x%08x %s reset successfully", 11737 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11738 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11739 break; 11740 11741 case 1: 11742 fcp_log(CE_WARN, pptr->port_dip, 11743 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11744 " response code=%x", 11745 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11746 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11747 rsp_info->rsp_code); 11748 break; 11749 11750 case 2: 11751 fcp_log(CE_WARN, pptr->port_dip, 11752 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11753 " Bad FCP response values: rsvd1=%x," 11754 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11755 " rsplen=%x, senselen=%x", 11756 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11757 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11758 rsp->reserved_0, rsp->reserved_1, 11759 rsp->fcp_u.fcp_status.reserved_0, 11760 rsp->fcp_u.fcp_status.reserved_1, 11761 rsp->fcp_response_len, rsp->fcp_sense_len); 11762 break; 11763 11764 default: 11765 fcp_log(CE_WARN, pptr->port_dip, 11766 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11767 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11768 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11769 break; 11770 } 11771 } 11772 scsi_destroy_pkt(pkt); 11773 11774 if (rval == FC_FAILURE) { 11775 mutex_enter(&ptgt->tgt_mutex); 11776 if (level == RESET_TARGET) { 11777 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11778 } else { 11779 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11780 } 11781 mutex_exit(&ptgt->tgt_mutex); 11782 kmem_free(p, sizeof (struct fcp_reset_elem)); 11783 return (rval); 11784 } 11785 11786 mutex_enter(&pptr->port_mutex); 11787 if (level == RESET_TARGET) { 11788 p->tgt = ptgt; 11789 p->lun = NULL; 11790 } else { 11791 p->tgt = NULL; 11792 p->lun = plun; 11793 } 11794 p->tgt = ptgt; 11795 p->tgt_cnt = tgt_cnt; 11796 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11797 p->next = pptr->port_reset_list; 11798 pptr->port_reset_list = p; 11799 11800 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11801 fcp_trace, FCP_BUF_LEVEL_3, 0, 11802 "Notify ssd of the reset to reinstate the reservations"); 11803 11804 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11805 &pptr->port_reset_notify_listf); 11806 11807 mutex_exit(&pptr->port_mutex); 11808 11809 return (rval); 11810 } 11811 11812 11813 /* 11814 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11815 * SCSI capabilities 11816 */ 11817 /* ARGSUSED */ 11818 static int 11819 fcp_commoncap(struct scsi_address *ap, char *cap, 11820 int val, int tgtonly, int doset) 11821 { 11822 struct fcp_port *pptr = ADDR2FCP(ap); 11823 struct fcp_lun *plun = ADDR2LUN(ap); 11824 struct fcp_tgt *ptgt = plun->lun_tgt; 11825 int cidx; 11826 int rval = FALSE; 11827 11828 if (cap == (char *)0) { 11829 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11830 fcp_trace, FCP_BUF_LEVEL_3, 0, 11831 "fcp_commoncap: invalid arg"); 11832 return (rval); 11833 } 11834 11835 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11836 return (UNDEFINED); 11837 } 11838 11839 /* 11840 * Process setcap request. 11841 */ 11842 if (doset) { 11843 /* 11844 * At present, we can only set binary (0/1) values 11845 */ 11846 switch (cidx) { 11847 case SCSI_CAP_ARQ: 11848 if (val == 0) { 11849 rval = FALSE; 11850 } else { 11851 rval = TRUE; 11852 } 11853 break; 11854 11855 case SCSI_CAP_LUN_RESET: 11856 if (val) { 11857 plun->lun_cap |= FCP_LUN_CAP_RESET; 11858 } else { 11859 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11860 } 11861 rval = TRUE; 11862 break; 11863 11864 case SCSI_CAP_SECTOR_SIZE: 11865 rval = TRUE; 11866 break; 11867 default: 11868 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11869 fcp_trace, FCP_BUF_LEVEL_4, 0, 11870 "fcp_setcap: unsupported %d", cidx); 11871 rval = UNDEFINED; 11872 break; 11873 } 11874 11875 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11876 fcp_trace, FCP_BUF_LEVEL_5, 0, 11877 "set cap: cap=%s, val/tgtonly/doset/rval = " 11878 "0x%x/0x%x/0x%x/%d", 11879 cap, val, tgtonly, doset, rval); 11880 11881 } else { 11882 /* 11883 * Process getcap request. 11884 */ 11885 switch (cidx) { 11886 case SCSI_CAP_DMA_MAX: 11887 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11888 11889 /* 11890 * Need to make an adjustment qlc is uint_t 64 11891 * st is int, so we will make the adjustment here 11892 * being as nobody wants to touch this. 11893 * It still leaves the max single block length 11894 * of 2 gig. This should last . 11895 */ 11896 11897 if (rval == -1) { 11898 rval = MAX_INT_DMA; 11899 } 11900 11901 break; 11902 11903 case SCSI_CAP_INITIATOR_ID: 11904 rval = pptr->port_id; 11905 break; 11906 11907 case SCSI_CAP_ARQ: 11908 case SCSI_CAP_RESET_NOTIFICATION: 11909 case SCSI_CAP_TAGGED_QING: 11910 rval = TRUE; 11911 break; 11912 11913 case SCSI_CAP_SCSI_VERSION: 11914 rval = 3; 11915 break; 11916 11917 case SCSI_CAP_INTERCONNECT_TYPE: 11918 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11919 (ptgt->tgt_hard_addr == 0)) { 11920 rval = INTERCONNECT_FABRIC; 11921 } else { 11922 rval = INTERCONNECT_FIBRE; 11923 } 11924 break; 11925 11926 case SCSI_CAP_LUN_RESET: 11927 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11928 TRUE : FALSE; 11929 break; 11930 11931 default: 11932 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11933 fcp_trace, FCP_BUF_LEVEL_4, 0, 11934 "fcp_getcap: unsupported %d", cidx); 11935 rval = UNDEFINED; 11936 break; 11937 } 11938 11939 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11940 fcp_trace, FCP_BUF_LEVEL_8, 0, 11941 "get cap: cap=%s, val/tgtonly/doset/rval = " 11942 "0x%x/0x%x/0x%x/%d", 11943 cap, val, tgtonly, doset, rval); 11944 } 11945 11946 return (rval); 11947 } 11948 11949 /* 11950 * called by the transport to get the port-wwn and lun 11951 * properties of this device, and to create a "name" based on them 11952 * 11953 * these properties don't exist on sun4m 11954 * 11955 * return 1 for success else return 0 11956 */ 11957 /* ARGSUSED */ 11958 static int 11959 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11960 { 11961 int i; 11962 int *lun; 11963 int numChars; 11964 uint_t nlun; 11965 uint_t count; 11966 uint_t nbytes; 11967 uchar_t *bytes; 11968 uint16_t lun_num; 11969 uint32_t tgt_id; 11970 char **conf_wwn; 11971 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11972 uchar_t barray[FC_WWN_SIZE]; 11973 dev_info_t *tgt_dip; 11974 struct fcp_tgt *ptgt; 11975 struct fcp_port *pptr; 11976 struct fcp_lun *plun; 11977 11978 ASSERT(sd != NULL); 11979 ASSERT(name != NULL); 11980 11981 tgt_dip = sd->sd_dev; 11982 pptr = ddi_get_soft_state(fcp_softstate, 11983 ddi_get_instance(ddi_get_parent(tgt_dip))); 11984 if (pptr == NULL) { 11985 return (0); 11986 } 11987 11988 ASSERT(tgt_dip != NULL); 11989 11990 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11991 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11992 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11993 name[0] = '\0'; 11994 return (0); 11995 } 11996 11997 if (nlun == 0) { 11998 ddi_prop_free(lun); 11999 return (0); 12000 } 12001 12002 lun_num = lun[0]; 12003 ddi_prop_free(lun); 12004 12005 /* 12006 * Lookup for .conf WWN property 12007 */ 12008 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 12009 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 12010 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 12011 ASSERT(count >= 1); 12012 12013 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 12014 ddi_prop_free(conf_wwn); 12015 mutex_enter(&pptr->port_mutex); 12016 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 12017 mutex_exit(&pptr->port_mutex); 12018 return (0); 12019 } 12020 ptgt = plun->lun_tgt; 12021 mutex_exit(&pptr->port_mutex); 12022 12023 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 12024 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 12025 12026 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12027 ptgt->tgt_hard_addr != 0) { 12028 tgt_id = (uint32_t)fcp_alpa_to_switch[ 12029 ptgt->tgt_hard_addr]; 12030 } else { 12031 tgt_id = ptgt->tgt_d_id; 12032 } 12033 12034 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 12035 TARGET_PROP, tgt_id); 12036 } 12037 12038 /* get the our port-wwn property */ 12039 bytes = NULL; 12040 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 12041 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12042 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 12043 if (bytes != NULL) { 12044 ddi_prop_free(bytes); 12045 } 12046 return (0); 12047 } 12048 12049 for (i = 0; i < FC_WWN_SIZE; i++) { 12050 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12051 } 12052 12053 /* Stick in the address of the form "wWWN,LUN" */ 12054 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12055 12056 ASSERT(numChars < len); 12057 if (numChars >= len) { 12058 fcp_log(CE_WARN, pptr->port_dip, 12059 "!fcp_scsi_get_name: " 12060 "name parameter length too small, it needs to be %d", 12061 numChars+1); 12062 } 12063 12064 ddi_prop_free(bytes); 12065 12066 return (1); 12067 } 12068 12069 12070 /* 12071 * called by the transport to get the SCSI target id value, returning 12072 * it in "name" 12073 * 12074 * this isn't needed/used on sun4m 12075 * 12076 * return 1 for success else return 0 12077 */ 12078 /* ARGSUSED */ 12079 static int 12080 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12081 { 12082 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12083 struct fcp_tgt *ptgt; 12084 int numChars; 12085 12086 if (plun == NULL) { 12087 return (0); 12088 } 12089 12090 if ((ptgt = plun->lun_tgt) == NULL) { 12091 return (0); 12092 } 12093 12094 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12095 12096 ASSERT(numChars < len); 12097 if (numChars >= len) { 12098 fcp_log(CE_WARN, NULL, 12099 "!fcp_scsi_get_bus_addr: " 12100 "name parameter length too small, it needs to be %d", 12101 numChars+1); 12102 } 12103 12104 return (1); 12105 } 12106 12107 12108 /* 12109 * called internally to reset the link where the specified port lives 12110 */ 12111 static int 12112 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12113 { 12114 la_wwn_t wwn; 12115 struct fcp_lun *plun; 12116 struct fcp_tgt *ptgt; 12117 12118 /* disable restart of lip if we're suspended */ 12119 mutex_enter(&pptr->port_mutex); 12120 12121 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12122 FCP_STATE_POWER_DOWN)) { 12123 mutex_exit(&pptr->port_mutex); 12124 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12125 fcp_trace, FCP_BUF_LEVEL_2, 0, 12126 "fcp_linkreset, fcp%d: link reset " 12127 "disabled due to DDI_SUSPEND", 12128 ddi_get_instance(pptr->port_dip)); 12129 return (FC_FAILURE); 12130 } 12131 12132 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12133 mutex_exit(&pptr->port_mutex); 12134 return (FC_SUCCESS); 12135 } 12136 12137 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12138 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12139 12140 /* 12141 * If ap == NULL assume local link reset. 12142 */ 12143 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12144 plun = ADDR2LUN(ap); 12145 ptgt = plun->lun_tgt; 12146 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12147 } else { 12148 bzero((caddr_t)&wwn, sizeof (wwn)); 12149 } 12150 mutex_exit(&pptr->port_mutex); 12151 12152 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12153 } 12154 12155 12156 /* 12157 * called from fcp_port_attach() to resume a port 12158 * return DDI_* success/failure status 12159 * acquires and releases the global mutex 12160 * acquires and releases the port mutex 12161 */ 12162 /*ARGSUSED*/ 12163 12164 static int 12165 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12166 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12167 { 12168 int res = DDI_FAILURE; /* default result */ 12169 struct fcp_port *pptr; /* port state ptr */ 12170 uint32_t alloc_cnt; 12171 uint32_t max_cnt; 12172 fc_portmap_t *tmp_list = NULL; 12173 12174 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12175 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12176 instance); 12177 12178 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12179 cmn_err(CE_WARN, "fcp: bad soft state"); 12180 return (res); 12181 } 12182 12183 mutex_enter(&pptr->port_mutex); 12184 switch (cmd) { 12185 case FC_CMD_RESUME: 12186 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12187 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12188 break; 12189 12190 case FC_CMD_POWER_UP: 12191 /* 12192 * If the port is DDI_SUSPENded, defer rediscovery 12193 * until DDI_RESUME occurs 12194 */ 12195 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12196 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12197 mutex_exit(&pptr->port_mutex); 12198 return (DDI_SUCCESS); 12199 } 12200 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12201 } 12202 pptr->port_id = s_id; 12203 pptr->port_state = FCP_STATE_INIT; 12204 mutex_exit(&pptr->port_mutex); 12205 12206 /* 12207 * Make a copy of ulp_port_info as fctl allocates 12208 * a temp struct. 12209 */ 12210 (void) fcp_cp_pinfo(pptr, pinfo); 12211 12212 mutex_enter(&fcp_global_mutex); 12213 if (fcp_watchdog_init++ == 0) { 12214 fcp_watchdog_tick = fcp_watchdog_timeout * 12215 drv_usectohz(1000000); 12216 fcp_watchdog_id = timeout(fcp_watch, 12217 NULL, fcp_watchdog_tick); 12218 } 12219 mutex_exit(&fcp_global_mutex); 12220 12221 /* 12222 * Handle various topologies and link states. 12223 */ 12224 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12225 case FC_STATE_OFFLINE: 12226 /* 12227 * Wait for ONLINE, at which time a state 12228 * change will cause a statec_callback 12229 */ 12230 res = DDI_SUCCESS; 12231 break; 12232 12233 case FC_STATE_ONLINE: 12234 12235 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12236 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12237 res = DDI_SUCCESS; 12238 break; 12239 } 12240 12241 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12242 !fcp_enable_auto_configuration) { 12243 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12244 if (tmp_list == NULL) { 12245 if (!alloc_cnt) { 12246 res = DDI_SUCCESS; 12247 } 12248 break; 12249 } 12250 max_cnt = alloc_cnt; 12251 } else { 12252 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12253 12254 alloc_cnt = FCP_MAX_DEVICES; 12255 12256 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12257 (sizeof (fc_portmap_t)) * alloc_cnt, 12258 KM_NOSLEEP)) == NULL) { 12259 fcp_log(CE_WARN, pptr->port_dip, 12260 "!fcp%d: failed to allocate portmap", 12261 instance); 12262 break; 12263 } 12264 12265 max_cnt = alloc_cnt; 12266 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12267 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12268 FC_SUCCESS) { 12269 caddr_t msg; 12270 12271 (void) fc_ulp_error(res, &msg); 12272 12273 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12274 fcp_trace, FCP_BUF_LEVEL_2, 0, 12275 "resume failed getportmap: reason=0x%x", 12276 res); 12277 12278 fcp_log(CE_WARN, pptr->port_dip, 12279 "!failed to get port map : %s", msg); 12280 break; 12281 } 12282 if (max_cnt > alloc_cnt) { 12283 alloc_cnt = max_cnt; 12284 } 12285 } 12286 12287 /* 12288 * do the SCSI device discovery and create 12289 * the devinfos 12290 */ 12291 fcp_statec_callback(ulph, pptr->port_fp_handle, 12292 pptr->port_phys_state, pptr->port_topology, tmp_list, 12293 max_cnt, pptr->port_id); 12294 12295 res = DDI_SUCCESS; 12296 break; 12297 12298 default: 12299 fcp_log(CE_WARN, pptr->port_dip, 12300 "!fcp%d: invalid port state at attach=0x%x", 12301 instance, pptr->port_phys_state); 12302 12303 mutex_enter(&pptr->port_mutex); 12304 pptr->port_phys_state = FCP_STATE_OFFLINE; 12305 mutex_exit(&pptr->port_mutex); 12306 res = DDI_SUCCESS; 12307 12308 break; 12309 } 12310 12311 if (tmp_list != NULL) { 12312 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12313 } 12314 12315 return (res); 12316 } 12317 12318 12319 static void 12320 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12321 { 12322 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12323 pptr->port_dip = pinfo->port_dip; 12324 pptr->port_fp_handle = pinfo->port_handle; 12325 if (pinfo->port_acc_attr != NULL) { 12326 /* 12327 * FCA supports DMA 12328 */ 12329 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12330 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12331 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12332 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12333 } 12334 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12335 pptr->port_max_exch = pinfo->port_fca_max_exch; 12336 pptr->port_phys_state = pinfo->port_state; 12337 pptr->port_topology = pinfo->port_flags; 12338 pptr->port_reset_action = pinfo->port_reset_action; 12339 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12340 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12341 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12342 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12343 12344 /* Clear FMA caps to avoid fm-capability ereport */ 12345 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12346 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12347 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12348 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12349 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12350 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12351 } 12352 12353 /* 12354 * If the elements wait field is set to 1 then 12355 * another thread is waiting for the operation to complete. Once 12356 * it is complete, the waiting thread is signaled and the element is 12357 * freed by the waiting thread. If the elements wait field is set to 0 12358 * the element is freed. 12359 */ 12360 static void 12361 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12362 { 12363 ASSERT(elem != NULL); 12364 mutex_enter(&elem->mutex); 12365 elem->result = result; 12366 if (elem->wait) { 12367 elem->wait = 0; 12368 cv_signal(&elem->cv); 12369 mutex_exit(&elem->mutex); 12370 } else { 12371 mutex_exit(&elem->mutex); 12372 cv_destroy(&elem->cv); 12373 mutex_destroy(&elem->mutex); 12374 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12375 } 12376 } 12377 12378 /* 12379 * This function is invoked from the taskq thread to allocate 12380 * devinfo nodes and to online/offline them. 12381 */ 12382 static void 12383 fcp_hp_task(void *arg) 12384 { 12385 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12386 struct fcp_lun *plun = elem->lun; 12387 struct fcp_port *pptr = elem->port; 12388 int result; 12389 12390 ASSERT(elem->what == FCP_ONLINE || 12391 elem->what == FCP_OFFLINE || 12392 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12393 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12394 12395 mutex_enter(&pptr->port_mutex); 12396 mutex_enter(&plun->lun_mutex); 12397 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12398 plun->lun_event_count != elem->event_cnt) || 12399 pptr->port_state & (FCP_STATE_SUSPENDED | 12400 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12401 mutex_exit(&plun->lun_mutex); 12402 mutex_exit(&pptr->port_mutex); 12403 fcp_process_elem(elem, NDI_FAILURE); 12404 return; 12405 } 12406 mutex_exit(&plun->lun_mutex); 12407 mutex_exit(&pptr->port_mutex); 12408 12409 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12410 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12411 fcp_process_elem(elem, result); 12412 } 12413 12414 12415 static child_info_t * 12416 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12417 int tcount) 12418 { 12419 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12420 12421 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12422 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12423 12424 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12425 /* 12426 * Child has not been created yet. Create the child device 12427 * based on the per-Lun flags. 12428 */ 12429 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12430 plun->lun_cip = 12431 CIP(fcp_create_dip(plun, lcount, tcount)); 12432 plun->lun_mpxio = 0; 12433 } else { 12434 plun->lun_cip = 12435 CIP(fcp_create_pip(plun, lcount, tcount)); 12436 plun->lun_mpxio = 1; 12437 } 12438 } else { 12439 plun->lun_cip = cip; 12440 } 12441 12442 return (plun->lun_cip); 12443 } 12444 12445 12446 static int 12447 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12448 { 12449 int rval = FC_FAILURE; 12450 dev_info_t *pdip; 12451 struct dev_info *dip; 12452 int circular; 12453 12454 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12455 12456 pdip = plun->lun_tgt->tgt_port->port_dip; 12457 12458 if (plun->lun_cip == NULL) { 12459 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12460 fcp_trace, FCP_BUF_LEVEL_3, 0, 12461 "fcp_is_dip_present: plun->lun_cip is NULL: " 12462 "plun: %p lun state: %x num: %d target state: %x", 12463 plun, plun->lun_state, plun->lun_num, 12464 plun->lun_tgt->tgt_port->port_state); 12465 return (rval); 12466 } 12467 ndi_devi_enter(pdip, &circular); 12468 dip = DEVI(pdip)->devi_child; 12469 while (dip) { 12470 if (dip == DEVI(cdip)) { 12471 rval = FC_SUCCESS; 12472 break; 12473 } 12474 dip = dip->devi_sibling; 12475 } 12476 ndi_devi_exit(pdip, circular); 12477 return (rval); 12478 } 12479 12480 static int 12481 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12482 { 12483 int rval = FC_FAILURE; 12484 12485 ASSERT(plun != NULL); 12486 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12487 12488 if (plun->lun_mpxio == 0) { 12489 rval = fcp_is_dip_present(plun, DIP(cip)); 12490 } else { 12491 rval = fcp_is_pip_present(plun, PIP(cip)); 12492 } 12493 12494 return (rval); 12495 } 12496 12497 /* 12498 * Function: fcp_create_dip 12499 * 12500 * Description: Creates a dev_info_t structure for the LUN specified by the 12501 * caller. 12502 * 12503 * Argument: plun Lun structure 12504 * link_cnt Link state count. 12505 * tgt_cnt Target state change count. 12506 * 12507 * Return Value: NULL if it failed 12508 * dev_info_t structure address if it succeeded 12509 * 12510 * Context: Kernel context 12511 */ 12512 static dev_info_t * 12513 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12514 { 12515 int failure = 0; 12516 uint32_t tgt_id; 12517 uint64_t sam_lun; 12518 struct fcp_tgt *ptgt = plun->lun_tgt; 12519 struct fcp_port *pptr = ptgt->tgt_port; 12520 dev_info_t *pdip = pptr->port_dip; 12521 dev_info_t *cdip = NULL; 12522 dev_info_t *old_dip = DIP(plun->lun_cip); 12523 char *nname = NULL; 12524 char **compatible = NULL; 12525 int ncompatible; 12526 char *scsi_binding_set; 12527 char t_pwwn[17]; 12528 12529 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12530 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12531 12532 /* get the 'scsi-binding-set' property */ 12533 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12534 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12535 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12536 scsi_binding_set = NULL; 12537 } 12538 12539 /* determine the node name and compatible */ 12540 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12541 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12542 if (scsi_binding_set) { 12543 ddi_prop_free(scsi_binding_set); 12544 } 12545 12546 if (nname == NULL) { 12547 #ifdef DEBUG 12548 cmn_err(CE_WARN, "%s%d: no driver for " 12549 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12550 " compatible: %s", 12551 ddi_driver_name(pdip), ddi_get_instance(pdip), 12552 ptgt->tgt_port_wwn.raw_wwn[0], 12553 ptgt->tgt_port_wwn.raw_wwn[1], 12554 ptgt->tgt_port_wwn.raw_wwn[2], 12555 ptgt->tgt_port_wwn.raw_wwn[3], 12556 ptgt->tgt_port_wwn.raw_wwn[4], 12557 ptgt->tgt_port_wwn.raw_wwn[5], 12558 ptgt->tgt_port_wwn.raw_wwn[6], 12559 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12560 *compatible); 12561 #endif /* DEBUG */ 12562 failure++; 12563 goto end_of_fcp_create_dip; 12564 } 12565 12566 cdip = fcp_find_existing_dip(plun, pdip, nname); 12567 12568 /* 12569 * if the old_dip does not match the cdip, that means there is 12570 * some property change. since we'll be using the cdip, we need 12571 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12572 * then the dtype for the device has been updated. Offline the 12573 * the old device and create a new device with the new device type 12574 * Refer to bug: 4764752 12575 */ 12576 if (old_dip && (cdip != old_dip || 12577 plun->lun_state & FCP_LUN_CHANGED)) { 12578 plun->lun_state &= ~(FCP_LUN_INIT); 12579 mutex_exit(&plun->lun_mutex); 12580 mutex_exit(&pptr->port_mutex); 12581 12582 mutex_enter(&ptgt->tgt_mutex); 12583 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12584 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12585 mutex_exit(&ptgt->tgt_mutex); 12586 12587 #ifdef DEBUG 12588 if (cdip != NULL) { 12589 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12590 fcp_trace, FCP_BUF_LEVEL_2, 0, 12591 "Old dip=%p; New dip=%p don't match", old_dip, 12592 cdip); 12593 } else { 12594 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12595 fcp_trace, FCP_BUF_LEVEL_2, 0, 12596 "Old dip=%p; New dip=NULL don't match", old_dip); 12597 } 12598 #endif 12599 12600 mutex_enter(&pptr->port_mutex); 12601 mutex_enter(&plun->lun_mutex); 12602 } 12603 12604 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12605 plun->lun_state &= ~(FCP_LUN_CHANGED); 12606 if (ndi_devi_alloc(pptr->port_dip, nname, 12607 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12608 failure++; 12609 goto end_of_fcp_create_dip; 12610 } 12611 } 12612 12613 /* 12614 * Previously all the properties for the devinfo were destroyed here 12615 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12616 * the devid property (and other properties established by the target 12617 * driver or framework) which the code does not always recreate, this 12618 * call was removed. 12619 * This opens a theoretical possibility that we may return with a 12620 * stale devid on the node if the scsi entity behind the fibre channel 12621 * lun has changed. 12622 */ 12623 12624 /* decorate the node with compatible */ 12625 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12626 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12627 failure++; 12628 goto end_of_fcp_create_dip; 12629 } 12630 12631 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12632 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12633 failure++; 12634 goto end_of_fcp_create_dip; 12635 } 12636 12637 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12638 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12639 failure++; 12640 goto end_of_fcp_create_dip; 12641 } 12642 12643 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12644 t_pwwn[16] = '\0'; 12645 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12646 != DDI_PROP_SUCCESS) { 12647 failure++; 12648 goto end_of_fcp_create_dip; 12649 } 12650 12651 /* 12652 * If there is no hard address - We might have to deal with 12653 * that by using WWN - Having said that it is important to 12654 * recognize this problem early so ssd can be informed of 12655 * the right interconnect type. 12656 */ 12657 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12658 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12659 } else { 12660 tgt_id = ptgt->tgt_d_id; 12661 } 12662 12663 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12664 tgt_id) != DDI_PROP_SUCCESS) { 12665 failure++; 12666 goto end_of_fcp_create_dip; 12667 } 12668 12669 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12670 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12671 failure++; 12672 goto end_of_fcp_create_dip; 12673 } 12674 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12675 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12676 sam_lun) != DDI_PROP_SUCCESS) { 12677 failure++; 12678 goto end_of_fcp_create_dip; 12679 } 12680 12681 end_of_fcp_create_dip: 12682 scsi_hba_nodename_compatible_free(nname, compatible); 12683 12684 if (cdip != NULL && failure) { 12685 (void) ndi_prop_remove_all(cdip); 12686 (void) ndi_devi_free(cdip); 12687 cdip = NULL; 12688 } 12689 12690 return (cdip); 12691 } 12692 12693 /* 12694 * Function: fcp_create_pip 12695 * 12696 * Description: Creates a Path Id for the LUN specified by the caller. 12697 * 12698 * Argument: plun Lun structure 12699 * link_cnt Link state count. 12700 * tgt_cnt Target state count. 12701 * 12702 * Return Value: NULL if it failed 12703 * mdi_pathinfo_t structure address if it succeeded 12704 * 12705 * Context: Kernel context 12706 */ 12707 static mdi_pathinfo_t * 12708 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12709 { 12710 int i; 12711 char buf[MAXNAMELEN]; 12712 char uaddr[MAXNAMELEN]; 12713 int failure = 0; 12714 uint32_t tgt_id; 12715 uint64_t sam_lun; 12716 struct fcp_tgt *ptgt = plun->lun_tgt; 12717 struct fcp_port *pptr = ptgt->tgt_port; 12718 dev_info_t *pdip = pptr->port_dip; 12719 mdi_pathinfo_t *pip = NULL; 12720 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12721 char *nname = NULL; 12722 char **compatible = NULL; 12723 int ncompatible; 12724 char *scsi_binding_set; 12725 char t_pwwn[17]; 12726 12727 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12728 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12729 12730 scsi_binding_set = "vhci"; 12731 12732 /* determine the node name and compatible */ 12733 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12734 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12735 12736 if (nname == NULL) { 12737 #ifdef DEBUG 12738 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12739 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12740 " compatible: %s", 12741 ddi_driver_name(pdip), ddi_get_instance(pdip), 12742 ptgt->tgt_port_wwn.raw_wwn[0], 12743 ptgt->tgt_port_wwn.raw_wwn[1], 12744 ptgt->tgt_port_wwn.raw_wwn[2], 12745 ptgt->tgt_port_wwn.raw_wwn[3], 12746 ptgt->tgt_port_wwn.raw_wwn[4], 12747 ptgt->tgt_port_wwn.raw_wwn[5], 12748 ptgt->tgt_port_wwn.raw_wwn[6], 12749 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12750 *compatible); 12751 #endif /* DEBUG */ 12752 failure++; 12753 goto end_of_fcp_create_pip; 12754 } 12755 12756 pip = fcp_find_existing_pip(plun, pdip); 12757 12758 /* 12759 * if the old_dip does not match the cdip, that means there is 12760 * some property change. since we'll be using the cdip, we need 12761 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12762 * then the dtype for the device has been updated. Offline the 12763 * the old device and create a new device with the new device type 12764 * Refer to bug: 4764752 12765 */ 12766 if (old_pip && (pip != old_pip || 12767 plun->lun_state & FCP_LUN_CHANGED)) { 12768 plun->lun_state &= ~(FCP_LUN_INIT); 12769 mutex_exit(&plun->lun_mutex); 12770 mutex_exit(&pptr->port_mutex); 12771 12772 mutex_enter(&ptgt->tgt_mutex); 12773 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12774 FCP_OFFLINE, lcount, tcount, 12775 NDI_DEVI_REMOVE, 0); 12776 mutex_exit(&ptgt->tgt_mutex); 12777 12778 if (pip != NULL) { 12779 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12780 fcp_trace, FCP_BUF_LEVEL_2, 0, 12781 "Old pip=%p; New pip=%p don't match", 12782 old_pip, pip); 12783 } else { 12784 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12785 fcp_trace, FCP_BUF_LEVEL_2, 0, 12786 "Old pip=%p; New pip=NULL don't match", 12787 old_pip); 12788 } 12789 12790 mutex_enter(&pptr->port_mutex); 12791 mutex_enter(&plun->lun_mutex); 12792 } 12793 12794 /* 12795 * Since FC_WWN_SIZE is 8 bytes and its not like the 12796 * lun_guid_size which is dependent on the target, I don't 12797 * believe the same trancation happens here UNLESS the standards 12798 * change the FC_WWN_SIZE value to something larger than 12799 * MAXNAMELEN(currently 255 bytes). 12800 */ 12801 12802 for (i = 0; i < FC_WWN_SIZE; i++) { 12803 (void) sprintf(&buf[i << 1], "%02x", 12804 ptgt->tgt_port_wwn.raw_wwn[i]); 12805 } 12806 12807 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12808 buf, plun->lun_num); 12809 12810 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12811 /* 12812 * Release the locks before calling into 12813 * mdi_pi_alloc_compatible() since this can result in a 12814 * callback into fcp which can result in a deadlock 12815 * (see bug # 4870272). 12816 * 12817 * Basically, what we are trying to avoid is the scenario where 12818 * one thread does ndi_devi_enter() and tries to grab 12819 * fcp_mutex and another does it the other way round. 12820 * 12821 * But before we do that, make sure that nobody releases the 12822 * port in the meantime. We can do this by setting a flag. 12823 */ 12824 plun->lun_state &= ~(FCP_LUN_CHANGED); 12825 pptr->port_state |= FCP_STATE_IN_MDI; 12826 mutex_exit(&plun->lun_mutex); 12827 mutex_exit(&pptr->port_mutex); 12828 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12829 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12830 fcp_log(CE_WARN, pptr->port_dip, 12831 "!path alloc failed:0x%x", plun); 12832 mutex_enter(&pptr->port_mutex); 12833 mutex_enter(&plun->lun_mutex); 12834 pptr->port_state &= ~FCP_STATE_IN_MDI; 12835 failure++; 12836 goto end_of_fcp_create_pip; 12837 } 12838 mutex_enter(&pptr->port_mutex); 12839 mutex_enter(&plun->lun_mutex); 12840 pptr->port_state &= ~FCP_STATE_IN_MDI; 12841 } else { 12842 (void) mdi_prop_remove(pip, NULL); 12843 } 12844 12845 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12846 12847 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12848 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12849 != DDI_PROP_SUCCESS) { 12850 failure++; 12851 goto end_of_fcp_create_pip; 12852 } 12853 12854 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12855 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12856 != DDI_PROP_SUCCESS) { 12857 failure++; 12858 goto end_of_fcp_create_pip; 12859 } 12860 12861 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12862 t_pwwn[16] = '\0'; 12863 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12864 != DDI_PROP_SUCCESS) { 12865 failure++; 12866 goto end_of_fcp_create_pip; 12867 } 12868 12869 /* 12870 * If there is no hard address - We might have to deal with 12871 * that by using WWN - Having said that it is important to 12872 * recognize this problem early so ssd can be informed of 12873 * the right interconnect type. 12874 */ 12875 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12876 ptgt->tgt_hard_addr != 0) { 12877 tgt_id = (uint32_t) 12878 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12879 } else { 12880 tgt_id = ptgt->tgt_d_id; 12881 } 12882 12883 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12884 != DDI_PROP_SUCCESS) { 12885 failure++; 12886 goto end_of_fcp_create_pip; 12887 } 12888 12889 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12890 != DDI_PROP_SUCCESS) { 12891 failure++; 12892 goto end_of_fcp_create_pip; 12893 } 12894 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12895 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12896 != DDI_PROP_SUCCESS) { 12897 failure++; 12898 goto end_of_fcp_create_pip; 12899 } 12900 12901 end_of_fcp_create_pip: 12902 scsi_hba_nodename_compatible_free(nname, compatible); 12903 12904 if (pip != NULL && failure) { 12905 (void) mdi_prop_remove(pip, NULL); 12906 mutex_exit(&plun->lun_mutex); 12907 mutex_exit(&pptr->port_mutex); 12908 (void) mdi_pi_free(pip, 0); 12909 mutex_enter(&pptr->port_mutex); 12910 mutex_enter(&plun->lun_mutex); 12911 pip = NULL; 12912 } 12913 12914 return (pip); 12915 } 12916 12917 static dev_info_t * 12918 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12919 { 12920 uint_t nbytes; 12921 uchar_t *bytes; 12922 uint_t nwords; 12923 uint32_t tgt_id; 12924 int *words; 12925 dev_info_t *cdip; 12926 dev_info_t *ndip; 12927 struct fcp_tgt *ptgt = plun->lun_tgt; 12928 struct fcp_port *pptr = ptgt->tgt_port; 12929 int circular; 12930 12931 ndi_devi_enter(pdip, &circular); 12932 12933 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12934 while ((cdip = ndip) != NULL) { 12935 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12936 12937 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12938 continue; 12939 } 12940 12941 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12942 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12943 &nbytes) != DDI_PROP_SUCCESS) { 12944 continue; 12945 } 12946 12947 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12948 if (bytes != NULL) { 12949 ddi_prop_free(bytes); 12950 } 12951 continue; 12952 } 12953 ASSERT(bytes != NULL); 12954 12955 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12956 ddi_prop_free(bytes); 12957 continue; 12958 } 12959 12960 ddi_prop_free(bytes); 12961 12962 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12963 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12964 &nbytes) != DDI_PROP_SUCCESS) { 12965 continue; 12966 } 12967 12968 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12969 if (bytes != NULL) { 12970 ddi_prop_free(bytes); 12971 } 12972 continue; 12973 } 12974 ASSERT(bytes != NULL); 12975 12976 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12977 ddi_prop_free(bytes); 12978 continue; 12979 } 12980 12981 ddi_prop_free(bytes); 12982 12983 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12984 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12985 &nwords) != DDI_PROP_SUCCESS) { 12986 continue; 12987 } 12988 12989 if (nwords != 1 || words == NULL) { 12990 if (words != NULL) { 12991 ddi_prop_free(words); 12992 } 12993 continue; 12994 } 12995 ASSERT(words != NULL); 12996 12997 /* 12998 * If there is no hard address - We might have to deal with 12999 * that by using WWN - Having said that it is important to 13000 * recognize this problem early so ssd can be informed of 13001 * the right interconnect type. 13002 */ 13003 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 13004 ptgt->tgt_hard_addr != 0) { 13005 tgt_id = 13006 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 13007 } else { 13008 tgt_id = ptgt->tgt_d_id; 13009 } 13010 13011 if (tgt_id != (uint32_t)*words) { 13012 ddi_prop_free(words); 13013 continue; 13014 } 13015 ddi_prop_free(words); 13016 13017 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 13018 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 13019 &nwords) != DDI_PROP_SUCCESS) { 13020 continue; 13021 } 13022 13023 if (nwords != 1 || words == NULL) { 13024 if (words != NULL) { 13025 ddi_prop_free(words); 13026 } 13027 continue; 13028 } 13029 ASSERT(words != NULL); 13030 13031 if (plun->lun_num == (uint16_t)*words) { 13032 ddi_prop_free(words); 13033 break; 13034 } 13035 ddi_prop_free(words); 13036 } 13037 ndi_devi_exit(pdip, circular); 13038 13039 return (cdip); 13040 } 13041 13042 13043 static int 13044 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 13045 { 13046 dev_info_t *pdip; 13047 char buf[MAXNAMELEN]; 13048 char uaddr[MAXNAMELEN]; 13049 int rval = FC_FAILURE; 13050 13051 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13052 13053 pdip = plun->lun_tgt->tgt_port->port_dip; 13054 13055 /* 13056 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13057 * non-NULL even when the LUN is not there as in the case when a LUN is 13058 * configured and then deleted on the device end (for T3/T4 case). In 13059 * such cases, pip will be NULL. 13060 * 13061 * If the device generates an RSCN, it will end up getting offlined when 13062 * it disappeared and a new LUN will get created when it is rediscovered 13063 * on the device. If we check for lun_cip here, the LUN will not end 13064 * up getting onlined since this function will end up returning a 13065 * FC_SUCCESS. 13066 * 13067 * The behavior is different on other devices. For instance, on a HDS, 13068 * there was no RSCN generated by the device but the next I/O generated 13069 * a check condition and rediscovery got triggered that way. So, in 13070 * such cases, this path will not be exercised 13071 */ 13072 if (pip == NULL) { 13073 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13074 fcp_trace, FCP_BUF_LEVEL_4, 0, 13075 "fcp_is_pip_present: plun->lun_cip is NULL: " 13076 "plun: %p lun state: %x num: %d target state: %x", 13077 plun, plun->lun_state, plun->lun_num, 13078 plun->lun_tgt->tgt_port->port_state); 13079 return (rval); 13080 } 13081 13082 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13083 13084 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13085 13086 if (plun->lun_old_guid) { 13087 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 13088 rval = FC_SUCCESS; 13089 } 13090 } else { 13091 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 13092 rval = FC_SUCCESS; 13093 } 13094 } 13095 return (rval); 13096 } 13097 13098 static mdi_pathinfo_t * 13099 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13100 { 13101 char buf[MAXNAMELEN]; 13102 char uaddr[MAXNAMELEN]; 13103 mdi_pathinfo_t *pip; 13104 struct fcp_tgt *ptgt = plun->lun_tgt; 13105 struct fcp_port *pptr = ptgt->tgt_port; 13106 13107 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13108 13109 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13110 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13111 13112 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13113 13114 return (pip); 13115 } 13116 13117 13118 static int 13119 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13120 int tcount, int flags, int *circ) 13121 { 13122 int rval; 13123 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13124 struct fcp_tgt *ptgt = plun->lun_tgt; 13125 dev_info_t *cdip = NULL; 13126 13127 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13128 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13129 13130 if (plun->lun_cip == NULL) { 13131 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13132 fcp_trace, FCP_BUF_LEVEL_3, 0, 13133 "fcp_online_child: plun->lun_cip is NULL: " 13134 "plun: %p state: %x num: %d target state: %x", 13135 plun, plun->lun_state, plun->lun_num, 13136 plun->lun_tgt->tgt_port->port_state); 13137 return (NDI_FAILURE); 13138 } 13139 again: 13140 if (plun->lun_mpxio == 0) { 13141 cdip = DIP(cip); 13142 mutex_exit(&plun->lun_mutex); 13143 mutex_exit(&pptr->port_mutex); 13144 13145 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13146 fcp_trace, FCP_BUF_LEVEL_3, 0, 13147 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13148 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13149 13150 /* 13151 * We could check for FCP_LUN_INIT here but chances 13152 * of getting here when it's already in FCP_LUN_INIT 13153 * is rare and a duplicate ndi_devi_online wouldn't 13154 * hurt either (as the node would already have been 13155 * in CF2) 13156 */ 13157 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13158 rval = ndi_devi_bind_driver(cdip, flags); 13159 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13160 fcp_trace, FCP_BUF_LEVEL_3, 0, 13161 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13162 } else { 13163 rval = ndi_devi_online(cdip, flags); 13164 } 13165 13166 /* 13167 * We log the message into trace buffer if the device 13168 * is "ses" and into syslog for any other device 13169 * type. This is to prevent the ndi_devi_online failure 13170 * message that appears for V880/A5K ses devices. 13171 */ 13172 if (rval == NDI_SUCCESS) { 13173 mutex_enter(&ptgt->tgt_mutex); 13174 plun->lun_state |= FCP_LUN_INIT; 13175 mutex_exit(&ptgt->tgt_mutex); 13176 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13177 fcp_log(CE_NOTE, pptr->port_dip, 13178 "!ndi_devi_online:" 13179 " failed for %s: target=%x lun=%x %x", 13180 ddi_get_name(cdip), ptgt->tgt_d_id, 13181 plun->lun_num, rval); 13182 } else { 13183 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13184 fcp_trace, FCP_BUF_LEVEL_3, 0, 13185 " !ndi_devi_online:" 13186 " failed for %s: target=%x lun=%x %x", 13187 ddi_get_name(cdip), ptgt->tgt_d_id, 13188 plun->lun_num, rval); 13189 } 13190 } else { 13191 cdip = mdi_pi_get_client(PIP(cip)); 13192 mutex_exit(&plun->lun_mutex); 13193 mutex_exit(&pptr->port_mutex); 13194 13195 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13196 fcp_trace, FCP_BUF_LEVEL_3, 0, 13197 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13198 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13199 13200 /* 13201 * Hold path and exit phci to avoid deadlock with power 13202 * management code during mdi_pi_online. 13203 */ 13204 mdi_hold_path(PIP(cip)); 13205 mdi_devi_exit_phci(pptr->port_dip, *circ); 13206 13207 rval = mdi_pi_online(PIP(cip), flags); 13208 13209 mdi_devi_enter_phci(pptr->port_dip, circ); 13210 mdi_rele_path(PIP(cip)); 13211 13212 if (rval == MDI_SUCCESS) { 13213 mutex_enter(&ptgt->tgt_mutex); 13214 plun->lun_state |= FCP_LUN_INIT; 13215 mutex_exit(&ptgt->tgt_mutex); 13216 13217 /* 13218 * Clear MPxIO path permanent disable in case 13219 * fcp hotplug dropped the offline event. 13220 */ 13221 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13222 13223 } else if (rval == MDI_NOT_SUPPORTED) { 13224 child_info_t *old_cip = cip; 13225 13226 /* 13227 * MPxIO does not support this device yet. 13228 * Enumerate in legacy mode. 13229 */ 13230 mutex_enter(&pptr->port_mutex); 13231 mutex_enter(&plun->lun_mutex); 13232 plun->lun_mpxio = 0; 13233 plun->lun_cip = NULL; 13234 cdip = fcp_create_dip(plun, lcount, tcount); 13235 plun->lun_cip = cip = CIP(cdip); 13236 if (cip == NULL) { 13237 fcp_log(CE_WARN, pptr->port_dip, 13238 "!fcp_online_child: " 13239 "Create devinfo failed for LU=%p", plun); 13240 mutex_exit(&plun->lun_mutex); 13241 13242 mutex_enter(&ptgt->tgt_mutex); 13243 plun->lun_state |= FCP_LUN_OFFLINE; 13244 mutex_exit(&ptgt->tgt_mutex); 13245 13246 mutex_exit(&pptr->port_mutex); 13247 13248 /* 13249 * free the mdi_pathinfo node 13250 */ 13251 (void) mdi_pi_free(PIP(old_cip), 0); 13252 } else { 13253 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13254 fcp_trace, FCP_BUF_LEVEL_3, 0, 13255 "fcp_online_child: creating devinfo " 13256 "node 0x%p for plun 0x%p", 13257 cip, plun); 13258 mutex_exit(&plun->lun_mutex); 13259 mutex_exit(&pptr->port_mutex); 13260 /* 13261 * free the mdi_pathinfo node 13262 */ 13263 (void) mdi_pi_free(PIP(old_cip), 0); 13264 mutex_enter(&pptr->port_mutex); 13265 mutex_enter(&plun->lun_mutex); 13266 goto again; 13267 } 13268 } else { 13269 if (cdip) { 13270 fcp_log(CE_NOTE, pptr->port_dip, 13271 "!fcp_online_child: mdi_pi_online:" 13272 " failed for %s: target=%x lun=%x %x", 13273 ddi_get_name(cdip), ptgt->tgt_d_id, 13274 plun->lun_num, rval); 13275 } 13276 } 13277 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13278 } 13279 13280 if (rval == NDI_SUCCESS) { 13281 if (cdip) { 13282 (void) ndi_event_retrieve_cookie( 13283 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13284 &fcp_insert_eid, NDI_EVENT_NOPASS); 13285 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13286 cdip, fcp_insert_eid, NULL); 13287 } 13288 } 13289 mutex_enter(&pptr->port_mutex); 13290 mutex_enter(&plun->lun_mutex); 13291 return (rval); 13292 } 13293 13294 /* ARGSUSED */ 13295 static int 13296 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13297 int tcount, int flags, int *circ) 13298 { 13299 int rval; 13300 int lun_mpxio; 13301 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13302 struct fcp_tgt *ptgt = plun->lun_tgt; 13303 dev_info_t *cdip; 13304 13305 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13306 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13307 13308 if (plun->lun_cip == NULL) { 13309 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13310 fcp_trace, FCP_BUF_LEVEL_3, 0, 13311 "fcp_offline_child: plun->lun_cip is NULL: " 13312 "plun: %p lun state: %x num: %d target state: %x", 13313 plun, plun->lun_state, plun->lun_num, 13314 plun->lun_tgt->tgt_port->port_state); 13315 return (NDI_FAILURE); 13316 } 13317 13318 /* 13319 * We will use this value twice. Make a copy to be sure we use 13320 * the same value in both places. 13321 */ 13322 lun_mpxio = plun->lun_mpxio; 13323 13324 if (lun_mpxio == 0) { 13325 cdip = DIP(cip); 13326 mutex_exit(&plun->lun_mutex); 13327 mutex_exit(&pptr->port_mutex); 13328 rval = ndi_devi_offline(DIP(cip), flags); 13329 if (rval != NDI_SUCCESS) { 13330 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13331 fcp_trace, FCP_BUF_LEVEL_3, 0, 13332 "fcp_offline_child: ndi_devi_offline failed " 13333 "rval=%x cip=%p", rval, cip); 13334 } 13335 } else { 13336 cdip = mdi_pi_get_client(PIP(cip)); 13337 mutex_exit(&plun->lun_mutex); 13338 mutex_exit(&pptr->port_mutex); 13339 13340 /* 13341 * Exit phci to avoid deadlock with power management code 13342 * during mdi_pi_offline 13343 */ 13344 mdi_hold_path(PIP(cip)); 13345 mdi_devi_exit_phci(pptr->port_dip, *circ); 13346 13347 rval = mdi_pi_offline(PIP(cip), flags); 13348 13349 mdi_devi_enter_phci(pptr->port_dip, circ); 13350 mdi_rele_path(PIP(cip)); 13351 13352 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13353 } 13354 13355 mutex_enter(&ptgt->tgt_mutex); 13356 plun->lun_state &= ~FCP_LUN_INIT; 13357 mutex_exit(&ptgt->tgt_mutex); 13358 13359 if (rval == NDI_SUCCESS) { 13360 cdip = NULL; 13361 if (flags & NDI_DEVI_REMOVE) { 13362 mutex_enter(&plun->lun_mutex); 13363 /* 13364 * If the guid of the LUN changes, lun_cip will not 13365 * equal to cip, and after offlining the LUN with the 13366 * old guid, we should keep lun_cip since it's the cip 13367 * of the LUN with the new guid. 13368 * Otherwise remove our reference to child node. 13369 * 13370 * This must be done before the child node is freed, 13371 * otherwise other threads could see a stale lun_cip 13372 * pointer. 13373 */ 13374 if (plun->lun_cip == cip) { 13375 plun->lun_cip = NULL; 13376 } 13377 if (plun->lun_old_guid) { 13378 kmem_free(plun->lun_old_guid, 13379 plun->lun_old_guid_size); 13380 plun->lun_old_guid = NULL; 13381 plun->lun_old_guid_size = 0; 13382 } 13383 mutex_exit(&plun->lun_mutex); 13384 } 13385 } 13386 13387 if (lun_mpxio != 0) { 13388 if (rval == NDI_SUCCESS) { 13389 /* 13390 * Clear MPxIO path permanent disable as the path is 13391 * already offlined. 13392 */ 13393 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13394 13395 if (flags & NDI_DEVI_REMOVE) { 13396 (void) mdi_pi_free(PIP(cip), 0); 13397 } 13398 } else { 13399 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13400 fcp_trace, FCP_BUF_LEVEL_3, 0, 13401 "fcp_offline_child: mdi_pi_offline failed " 13402 "rval=%x cip=%p", rval, cip); 13403 } 13404 } 13405 13406 mutex_enter(&pptr->port_mutex); 13407 mutex_enter(&plun->lun_mutex); 13408 13409 if (cdip) { 13410 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13411 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13412 " target=%x lun=%x", "ndi_offline", 13413 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13414 } 13415 13416 return (rval); 13417 } 13418 13419 static void 13420 fcp_remove_child(struct fcp_lun *plun) 13421 { 13422 child_info_t *cip; 13423 int circ; 13424 13425 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13426 13427 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13428 if (plun->lun_mpxio == 0) { 13429 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13430 (void) ndi_devi_free(DIP(plun->lun_cip)); 13431 plun->lun_cip = NULL; 13432 } else { 13433 /* 13434 * Clear reference to the child node in the lun. 13435 * This must be done before freeing it with mdi_pi_free 13436 * and with lun_mutex held so that other threads always 13437 * see either valid lun_cip or NULL when holding 13438 * lun_mutex. We keep a copy in cip. 13439 */ 13440 cip = plun->lun_cip; 13441 plun->lun_cip = NULL; 13442 13443 mutex_exit(&plun->lun_mutex); 13444 mutex_exit(&plun->lun_tgt->tgt_mutex); 13445 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13446 13447 mdi_devi_enter( 13448 plun->lun_tgt->tgt_port->port_dip, &circ); 13449 13450 /* 13451 * Exit phci to avoid deadlock with power management 13452 * code during mdi_pi_offline 13453 */ 13454 mdi_hold_path(PIP(cip)); 13455 mdi_devi_exit_phci( 13456 plun->lun_tgt->tgt_port->port_dip, circ); 13457 (void) mdi_pi_offline(PIP(cip), 13458 NDI_DEVI_REMOVE); 13459 mdi_devi_enter_phci( 13460 plun->lun_tgt->tgt_port->port_dip, &circ); 13461 mdi_rele_path(PIP(cip)); 13462 13463 mdi_devi_exit( 13464 plun->lun_tgt->tgt_port->port_dip, circ); 13465 13466 FCP_TRACE(fcp_logq, 13467 plun->lun_tgt->tgt_port->port_instbuf, 13468 fcp_trace, FCP_BUF_LEVEL_3, 0, 13469 "lun=%p pip freed %p", plun, cip); 13470 13471 (void) mdi_prop_remove(PIP(cip), NULL); 13472 (void) mdi_pi_free(PIP(cip), 0); 13473 13474 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13475 mutex_enter(&plun->lun_tgt->tgt_mutex); 13476 mutex_enter(&plun->lun_mutex); 13477 } 13478 } else { 13479 plun->lun_cip = NULL; 13480 } 13481 } 13482 13483 /* 13484 * called when a timeout occurs 13485 * 13486 * can be scheduled during an attach or resume (if not already running) 13487 * 13488 * one timeout is set up for all ports 13489 * 13490 * acquires and releases the global mutex 13491 */ 13492 /*ARGSUSED*/ 13493 static void 13494 fcp_watch(void *arg) 13495 { 13496 struct fcp_port *pptr; 13497 struct fcp_ipkt *icmd; 13498 struct fcp_ipkt *nicmd; 13499 struct fcp_pkt *cmd; 13500 struct fcp_pkt *ncmd; 13501 struct fcp_pkt *tail; 13502 struct fcp_pkt *pcmd; 13503 struct fcp_pkt *save_head; 13504 struct fcp_port *save_port; 13505 13506 /* increment global watchdog time */ 13507 fcp_watchdog_time += fcp_watchdog_timeout; 13508 13509 mutex_enter(&fcp_global_mutex); 13510 13511 /* scan each port in our list */ 13512 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13513 save_port = fcp_port_head; 13514 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13515 mutex_exit(&fcp_global_mutex); 13516 13517 mutex_enter(&pptr->port_mutex); 13518 if (pptr->port_ipkt_list == NULL && 13519 (pptr->port_state & (FCP_STATE_SUSPENDED | 13520 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13521 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13522 mutex_exit(&pptr->port_mutex); 13523 mutex_enter(&fcp_global_mutex); 13524 goto end_of_watchdog; 13525 } 13526 13527 /* 13528 * We check if a list of targets need to be offlined. 13529 */ 13530 if (pptr->port_offline_tgts) { 13531 fcp_scan_offline_tgts(pptr); 13532 } 13533 13534 /* 13535 * We check if a list of luns need to be offlined. 13536 */ 13537 if (pptr->port_offline_luns) { 13538 fcp_scan_offline_luns(pptr); 13539 } 13540 13541 /* 13542 * We check if a list of targets or luns need to be reset. 13543 */ 13544 if (pptr->port_reset_list) { 13545 fcp_check_reset_delay(pptr); 13546 } 13547 13548 mutex_exit(&pptr->port_mutex); 13549 13550 /* 13551 * This is where the pending commands (pkt) are checked for 13552 * timeout. 13553 */ 13554 mutex_enter(&pptr->port_pkt_mutex); 13555 tail = pptr->port_pkt_tail; 13556 13557 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13558 cmd != NULL; cmd = ncmd) { 13559 ncmd = cmd->cmd_next; 13560 /* 13561 * If a command is in this queue the bit CFLAG_IN_QUEUE 13562 * must be set. 13563 */ 13564 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13565 /* 13566 * FCP_INVALID_TIMEOUT will be set for those 13567 * command that need to be failed. Mostly those 13568 * cmds that could not be queued down for the 13569 * "timeout" value. cmd->cmd_timeout is used 13570 * to try and requeue the command regularly. 13571 */ 13572 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13573 /* 13574 * This command hasn't timed out yet. Let's 13575 * go to the next one. 13576 */ 13577 pcmd = cmd; 13578 goto end_of_loop; 13579 } 13580 13581 if (cmd == pptr->port_pkt_head) { 13582 ASSERT(pcmd == NULL); 13583 pptr->port_pkt_head = cmd->cmd_next; 13584 } else { 13585 ASSERT(pcmd != NULL); 13586 pcmd->cmd_next = cmd->cmd_next; 13587 } 13588 13589 if (cmd == pptr->port_pkt_tail) { 13590 ASSERT(cmd->cmd_next == NULL); 13591 pptr->port_pkt_tail = pcmd; 13592 if (pcmd) { 13593 pcmd->cmd_next = NULL; 13594 } 13595 } 13596 cmd->cmd_next = NULL; 13597 13598 /* 13599 * save the current head before dropping the 13600 * mutex - If the head doesn't remain the 13601 * same after re acquiring the mutex, just 13602 * bail out and revisit on next tick. 13603 * 13604 * PS: The tail pointer can change as the commands 13605 * get requeued after failure to retransport 13606 */ 13607 save_head = pptr->port_pkt_head; 13608 mutex_exit(&pptr->port_pkt_mutex); 13609 13610 if (cmd->cmd_fp_pkt->pkt_timeout == 13611 FCP_INVALID_TIMEOUT) { 13612 struct scsi_pkt *pkt = cmd->cmd_pkt; 13613 struct fcp_lun *plun; 13614 struct fcp_tgt *ptgt; 13615 13616 plun = ADDR2LUN(&pkt->pkt_address); 13617 ptgt = plun->lun_tgt; 13618 13619 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13620 fcp_trace, FCP_BUF_LEVEL_2, 0, 13621 "SCSI cmd 0x%x to D_ID=%x timed out", 13622 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13623 13624 cmd->cmd_state == FCP_PKT_ABORTING ? 13625 fcp_fail_cmd(cmd, CMD_RESET, 13626 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13627 CMD_TIMEOUT, STAT_ABORTED); 13628 } else { 13629 fcp_retransport_cmd(pptr, cmd); 13630 } 13631 mutex_enter(&pptr->port_pkt_mutex); 13632 if (save_head && save_head != pptr->port_pkt_head) { 13633 /* 13634 * Looks like linked list got changed (mostly 13635 * happens when an an OFFLINE LUN code starts 13636 * returning overflow queue commands in 13637 * parallel. So bail out and revisit during 13638 * next tick 13639 */ 13640 break; 13641 } 13642 end_of_loop: 13643 /* 13644 * Scan only upto the previously known tail pointer 13645 * to avoid excessive processing - lots of new packets 13646 * could have been added to the tail or the old ones 13647 * re-queued. 13648 */ 13649 if (cmd == tail) { 13650 break; 13651 } 13652 } 13653 mutex_exit(&pptr->port_pkt_mutex); 13654 13655 mutex_enter(&pptr->port_mutex); 13656 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13657 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13658 13659 nicmd = icmd->ipkt_next; 13660 if ((icmd->ipkt_restart != 0) && 13661 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13662 /* packet has not timed out */ 13663 continue; 13664 } 13665 13666 /* time for packet re-transport */ 13667 if (icmd == pptr->port_ipkt_list) { 13668 pptr->port_ipkt_list = icmd->ipkt_next; 13669 if (pptr->port_ipkt_list) { 13670 pptr->port_ipkt_list->ipkt_prev = 13671 NULL; 13672 } 13673 } else { 13674 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13675 if (icmd->ipkt_next) { 13676 icmd->ipkt_next->ipkt_prev = 13677 icmd->ipkt_prev; 13678 } 13679 } 13680 icmd->ipkt_next = NULL; 13681 icmd->ipkt_prev = NULL; 13682 mutex_exit(&pptr->port_mutex); 13683 13684 if (fcp_is_retryable(icmd)) { 13685 fc_ulp_rscn_info_t *rscnp = 13686 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13687 pkt_ulp_rscn_infop; 13688 13689 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13690 fcp_trace, FCP_BUF_LEVEL_2, 0, 13691 "%x to D_ID=%x Retrying..", 13692 icmd->ipkt_opcode, 13693 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13694 13695 /* 13696 * Update the RSCN count in the packet 13697 * before resending. 13698 */ 13699 13700 if (rscnp != NULL) { 13701 rscnp->ulp_rscn_count = 13702 fc_ulp_get_rscn_count(pptr-> 13703 port_fp_handle); 13704 } 13705 13706 mutex_enter(&pptr->port_mutex); 13707 mutex_enter(&ptgt->tgt_mutex); 13708 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13709 mutex_exit(&ptgt->tgt_mutex); 13710 mutex_exit(&pptr->port_mutex); 13711 switch (icmd->ipkt_opcode) { 13712 int rval; 13713 case LA_ELS_PLOGI: 13714 if ((rval = fc_ulp_login( 13715 pptr->port_fp_handle, 13716 &icmd->ipkt_fpkt, 1)) == 13717 FC_SUCCESS) { 13718 mutex_enter( 13719 &pptr->port_mutex); 13720 continue; 13721 } 13722 if (fcp_handle_ipkt_errors( 13723 pptr, ptgt, icmd, rval, 13724 "PLOGI") == DDI_SUCCESS) { 13725 mutex_enter( 13726 &pptr->port_mutex); 13727 continue; 13728 } 13729 break; 13730 13731 case LA_ELS_PRLI: 13732 if ((rval = fc_ulp_issue_els( 13733 pptr->port_fp_handle, 13734 icmd->ipkt_fpkt)) == 13735 FC_SUCCESS) { 13736 mutex_enter( 13737 &pptr->port_mutex); 13738 continue; 13739 } 13740 if (fcp_handle_ipkt_errors( 13741 pptr, ptgt, icmd, rval, 13742 "PRLI") == DDI_SUCCESS) { 13743 mutex_enter( 13744 &pptr->port_mutex); 13745 continue; 13746 } 13747 break; 13748 13749 default: 13750 if ((rval = fcp_transport( 13751 pptr->port_fp_handle, 13752 icmd->ipkt_fpkt, 1)) == 13753 FC_SUCCESS) { 13754 mutex_enter( 13755 &pptr->port_mutex); 13756 continue; 13757 } 13758 if (fcp_handle_ipkt_errors( 13759 pptr, ptgt, icmd, rval, 13760 "PRLI") == DDI_SUCCESS) { 13761 mutex_enter( 13762 &pptr->port_mutex); 13763 continue; 13764 } 13765 break; 13766 } 13767 } else { 13768 mutex_exit(&ptgt->tgt_mutex); 13769 mutex_exit(&pptr->port_mutex); 13770 } 13771 } else { 13772 fcp_print_error(icmd->ipkt_fpkt); 13773 } 13774 13775 (void) fcp_call_finish_init(pptr, ptgt, 13776 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13777 icmd->ipkt_cause); 13778 fcp_icmd_free(pptr, icmd); 13779 mutex_enter(&pptr->port_mutex); 13780 } 13781 13782 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13783 mutex_exit(&pptr->port_mutex); 13784 mutex_enter(&fcp_global_mutex); 13785 13786 end_of_watchdog: 13787 /* 13788 * Bail out early before getting into trouble 13789 */ 13790 if (save_port != fcp_port_head) { 13791 break; 13792 } 13793 } 13794 13795 if (fcp_watchdog_init > 0) { 13796 /* reschedule timeout to go again */ 13797 fcp_watchdog_id = 13798 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13799 } 13800 mutex_exit(&fcp_global_mutex); 13801 } 13802 13803 13804 static void 13805 fcp_check_reset_delay(struct fcp_port *pptr) 13806 { 13807 uint32_t tgt_cnt; 13808 int level; 13809 struct fcp_tgt *ptgt; 13810 struct fcp_lun *plun; 13811 struct fcp_reset_elem *cur = NULL; 13812 struct fcp_reset_elem *next = NULL; 13813 struct fcp_reset_elem *prev = NULL; 13814 13815 ASSERT(mutex_owned(&pptr->port_mutex)); 13816 13817 next = pptr->port_reset_list; 13818 while ((cur = next) != NULL) { 13819 next = cur->next; 13820 13821 if (cur->timeout < fcp_watchdog_time) { 13822 prev = cur; 13823 continue; 13824 } 13825 13826 ptgt = cur->tgt; 13827 plun = cur->lun; 13828 tgt_cnt = cur->tgt_cnt; 13829 13830 if (ptgt) { 13831 level = RESET_TARGET; 13832 } else { 13833 ASSERT(plun != NULL); 13834 level = RESET_LUN; 13835 ptgt = plun->lun_tgt; 13836 } 13837 if (prev) { 13838 prev->next = next; 13839 } else { 13840 /* 13841 * Because we drop port mutex while doing aborts for 13842 * packets, we can't rely on reset_list pointing to 13843 * our head 13844 */ 13845 if (cur == pptr->port_reset_list) { 13846 pptr->port_reset_list = next; 13847 } else { 13848 struct fcp_reset_elem *which; 13849 13850 which = pptr->port_reset_list; 13851 while (which && which->next != cur) { 13852 which = which->next; 13853 } 13854 ASSERT(which != NULL); 13855 13856 which->next = next; 13857 prev = which; 13858 } 13859 } 13860 13861 kmem_free(cur, sizeof (*cur)); 13862 13863 if (tgt_cnt == ptgt->tgt_change_cnt) { 13864 mutex_enter(&ptgt->tgt_mutex); 13865 if (level == RESET_TARGET) { 13866 fcp_update_tgt_state(ptgt, 13867 FCP_RESET, FCP_LUN_BUSY); 13868 } else { 13869 fcp_update_lun_state(plun, 13870 FCP_RESET, FCP_LUN_BUSY); 13871 } 13872 mutex_exit(&ptgt->tgt_mutex); 13873 13874 mutex_exit(&pptr->port_mutex); 13875 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13876 mutex_enter(&pptr->port_mutex); 13877 } 13878 } 13879 } 13880 13881 13882 static void 13883 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13884 struct fcp_lun *rlun, int tgt_cnt) 13885 { 13886 int rval; 13887 struct fcp_lun *tlun, *nlun; 13888 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13889 *cmd = NULL, *head = NULL, 13890 *tail = NULL; 13891 13892 mutex_enter(&pptr->port_pkt_mutex); 13893 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13894 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13895 struct fcp_tgt *ptgt = plun->lun_tgt; 13896 13897 ncmd = cmd->cmd_next; 13898 13899 if (ptgt != ttgt && plun != rlun) { 13900 pcmd = cmd; 13901 continue; 13902 } 13903 13904 if (pcmd != NULL) { 13905 ASSERT(pptr->port_pkt_head != cmd); 13906 pcmd->cmd_next = ncmd; 13907 } else { 13908 ASSERT(cmd == pptr->port_pkt_head); 13909 pptr->port_pkt_head = ncmd; 13910 } 13911 if (pptr->port_pkt_tail == cmd) { 13912 ASSERT(cmd->cmd_next == NULL); 13913 pptr->port_pkt_tail = pcmd; 13914 if (pcmd != NULL) { 13915 pcmd->cmd_next = NULL; 13916 } 13917 } 13918 13919 if (head == NULL) { 13920 head = tail = cmd; 13921 } else { 13922 ASSERT(tail != NULL); 13923 tail->cmd_next = cmd; 13924 tail = cmd; 13925 } 13926 cmd->cmd_next = NULL; 13927 } 13928 mutex_exit(&pptr->port_pkt_mutex); 13929 13930 for (cmd = head; cmd != NULL; cmd = ncmd) { 13931 struct scsi_pkt *pkt = cmd->cmd_pkt; 13932 13933 ncmd = cmd->cmd_next; 13934 ASSERT(pkt != NULL); 13935 13936 mutex_enter(&pptr->port_mutex); 13937 if (ttgt->tgt_change_cnt == tgt_cnt) { 13938 mutex_exit(&pptr->port_mutex); 13939 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13940 pkt->pkt_reason = CMD_RESET; 13941 pkt->pkt_statistics |= STAT_DEV_RESET; 13942 cmd->cmd_state = FCP_PKT_IDLE; 13943 fcp_post_callback(cmd); 13944 } else { 13945 mutex_exit(&pptr->port_mutex); 13946 } 13947 } 13948 13949 /* 13950 * If the FCA will return all the commands in its queue then our 13951 * work is easy, just return. 13952 */ 13953 13954 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13955 return; 13956 } 13957 13958 /* 13959 * For RESET_LUN get hold of target pointer 13960 */ 13961 if (ttgt == NULL) { 13962 ASSERT(rlun != NULL); 13963 13964 ttgt = rlun->lun_tgt; 13965 13966 ASSERT(ttgt != NULL); 13967 } 13968 13969 /* 13970 * There are some severe race conditions here. 13971 * While we are trying to abort the pkt, it might be completing 13972 * so mark it aborted and if the abort does not succeed then 13973 * handle it in the watch thread. 13974 */ 13975 mutex_enter(&ttgt->tgt_mutex); 13976 nlun = ttgt->tgt_lun; 13977 mutex_exit(&ttgt->tgt_mutex); 13978 while ((tlun = nlun) != NULL) { 13979 int restart = 0; 13980 if (rlun && rlun != tlun) { 13981 mutex_enter(&ttgt->tgt_mutex); 13982 nlun = tlun->lun_next; 13983 mutex_exit(&ttgt->tgt_mutex); 13984 continue; 13985 } 13986 mutex_enter(&tlun->lun_mutex); 13987 cmd = tlun->lun_pkt_head; 13988 while (cmd != NULL) { 13989 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13990 struct scsi_pkt *pkt; 13991 13992 restart = 1; 13993 cmd->cmd_state = FCP_PKT_ABORTING; 13994 mutex_exit(&tlun->lun_mutex); 13995 rval = fc_ulp_abort(pptr->port_fp_handle, 13996 cmd->cmd_fp_pkt, KM_SLEEP); 13997 if (rval == FC_SUCCESS) { 13998 pkt = cmd->cmd_pkt; 13999 pkt->pkt_reason = CMD_RESET; 14000 pkt->pkt_statistics |= STAT_DEV_RESET; 14001 cmd->cmd_state = FCP_PKT_IDLE; 14002 fcp_post_callback(cmd); 14003 } else { 14004 caddr_t msg; 14005 14006 (void) fc_ulp_error(rval, &msg); 14007 14008 /* 14009 * This part is tricky. The abort 14010 * failed and now the command could 14011 * be completing. The cmd_state == 14012 * FCP_PKT_ABORTING should save 14013 * us in fcp_cmd_callback. If we 14014 * are already aborting ignore the 14015 * command in fcp_cmd_callback. 14016 * Here we leave this packet for 20 14017 * sec to be aborted in the 14018 * fcp_watch thread. 14019 */ 14020 fcp_log(CE_WARN, pptr->port_dip, 14021 "!Abort failed after reset %s", 14022 msg); 14023 14024 cmd->cmd_timeout = 14025 fcp_watchdog_time + 14026 cmd->cmd_pkt->pkt_time + 14027 FCP_FAILED_DELAY; 14028 14029 cmd->cmd_fp_pkt->pkt_timeout = 14030 FCP_INVALID_TIMEOUT; 14031 /* 14032 * This is a hack, cmd is put in the 14033 * overflow queue so that it can be 14034 * timed out finally 14035 */ 14036 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14037 14038 mutex_enter(&pptr->port_pkt_mutex); 14039 if (pptr->port_pkt_head) { 14040 ASSERT(pptr->port_pkt_tail 14041 != NULL); 14042 pptr->port_pkt_tail->cmd_next 14043 = cmd; 14044 pptr->port_pkt_tail = cmd; 14045 } else { 14046 ASSERT(pptr->port_pkt_tail 14047 == NULL); 14048 pptr->port_pkt_head = 14049 pptr->port_pkt_tail 14050 = cmd; 14051 } 14052 cmd->cmd_next = NULL; 14053 mutex_exit(&pptr->port_pkt_mutex); 14054 } 14055 mutex_enter(&tlun->lun_mutex); 14056 cmd = tlun->lun_pkt_head; 14057 } else { 14058 cmd = cmd->cmd_forw; 14059 } 14060 } 14061 mutex_exit(&tlun->lun_mutex); 14062 14063 mutex_enter(&ttgt->tgt_mutex); 14064 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14065 mutex_exit(&ttgt->tgt_mutex); 14066 14067 mutex_enter(&pptr->port_mutex); 14068 if (tgt_cnt != ttgt->tgt_change_cnt) { 14069 mutex_exit(&pptr->port_mutex); 14070 return; 14071 } else { 14072 mutex_exit(&pptr->port_mutex); 14073 } 14074 } 14075 } 14076 14077 14078 /* 14079 * unlink the soft state, returning the soft state found (if any) 14080 * 14081 * acquires and releases the global mutex 14082 */ 14083 struct fcp_port * 14084 fcp_soft_state_unlink(struct fcp_port *pptr) 14085 { 14086 struct fcp_port *hptr; /* ptr index */ 14087 struct fcp_port *tptr; /* prev hptr */ 14088 14089 mutex_enter(&fcp_global_mutex); 14090 for (hptr = fcp_port_head, tptr = NULL; 14091 hptr != NULL; 14092 tptr = hptr, hptr = hptr->port_next) { 14093 if (hptr == pptr) { 14094 /* we found a match -- remove this item */ 14095 if (tptr == NULL) { 14096 /* we're at the head of the list */ 14097 fcp_port_head = hptr->port_next; 14098 } else { 14099 tptr->port_next = hptr->port_next; 14100 } 14101 break; /* success */ 14102 } 14103 } 14104 if (fcp_port_head == NULL) { 14105 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14106 } 14107 mutex_exit(&fcp_global_mutex); 14108 return (hptr); 14109 } 14110 14111 14112 /* 14113 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14114 * WWN and a LUN number 14115 */ 14116 /* ARGSUSED */ 14117 static struct fcp_lun * 14118 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14119 { 14120 int hash; 14121 struct fcp_tgt *ptgt; 14122 struct fcp_lun *plun; 14123 14124 ASSERT(mutex_owned(&pptr->port_mutex)); 14125 14126 hash = FCP_HASH(wwn); 14127 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14128 ptgt = ptgt->tgt_next) { 14129 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14130 sizeof (ptgt->tgt_port_wwn)) == 0) { 14131 mutex_enter(&ptgt->tgt_mutex); 14132 for (plun = ptgt->tgt_lun; 14133 plun != NULL; 14134 plun = plun->lun_next) { 14135 if (plun->lun_num == lun) { 14136 mutex_exit(&ptgt->tgt_mutex); 14137 return (plun); 14138 } 14139 } 14140 mutex_exit(&ptgt->tgt_mutex); 14141 return (NULL); 14142 } 14143 } 14144 return (NULL); 14145 } 14146 14147 /* 14148 * Function: fcp_prepare_pkt 14149 * 14150 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14151 * for fcp_start(). It binds the data or partially maps it. 14152 * Builds the FCP header and starts the initialization of the 14153 * Fibre Channel header. 14154 * 14155 * Argument: *pptr FCP port. 14156 * *cmd FCP packet. 14157 * *plun LUN the command will be sent to. 14158 * 14159 * Context: User, Kernel and Interrupt context. 14160 */ 14161 static void 14162 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14163 struct fcp_lun *plun) 14164 { 14165 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14166 struct fcp_tgt *ptgt = plun->lun_tgt; 14167 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14168 14169 ASSERT(cmd->cmd_pkt->pkt_comp || 14170 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14171 14172 if (cmd->cmd_pkt->pkt_numcookies) { 14173 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14174 fcmd->fcp_cntl.cntl_read_data = 1; 14175 fcmd->fcp_cntl.cntl_write_data = 0; 14176 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14177 } else { 14178 fcmd->fcp_cntl.cntl_read_data = 0; 14179 fcmd->fcp_cntl.cntl_write_data = 1; 14180 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14181 } 14182 14183 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14184 14185 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14186 ASSERT(fpkt->pkt_data_cookie_cnt <= 14187 pptr->port_data_dma_attr.dma_attr_sgllen); 14188 14189 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14190 14191 /* FCA needs pkt_datalen to be set */ 14192 fpkt->pkt_datalen = cmd->cmd_dmacount; 14193 fcmd->fcp_data_len = cmd->cmd_dmacount; 14194 } else { 14195 fcmd->fcp_cntl.cntl_read_data = 0; 14196 fcmd->fcp_cntl.cntl_write_data = 0; 14197 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14198 fpkt->pkt_datalen = 0; 14199 fcmd->fcp_data_len = 0; 14200 } 14201 14202 /* set up the Tagged Queuing type */ 14203 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14204 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14205 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14206 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14207 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14208 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14209 } else { 14210 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14211 } 14212 14213 fcmd->fcp_ent_addr = plun->lun_addr; 14214 14215 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14216 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14217 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14218 } else { 14219 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14220 } 14221 14222 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14223 cmd->cmd_pkt->pkt_state = 0; 14224 cmd->cmd_pkt->pkt_statistics = 0; 14225 cmd->cmd_pkt->pkt_resid = 0; 14226 14227 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14228 14229 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14230 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14231 fpkt->pkt_comp = NULL; 14232 } else { 14233 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14234 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14235 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14236 } 14237 fpkt->pkt_comp = fcp_cmd_callback; 14238 } 14239 14240 mutex_enter(&pptr->port_mutex); 14241 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14242 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14243 } 14244 mutex_exit(&pptr->port_mutex); 14245 14246 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14247 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14248 14249 /* 14250 * Save a few kernel cycles here 14251 */ 14252 #ifndef __lock_lint 14253 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14254 #endif /* __lock_lint */ 14255 } 14256 14257 static void 14258 fcp_post_callback(struct fcp_pkt *cmd) 14259 { 14260 scsi_hba_pkt_comp(cmd->cmd_pkt); 14261 } 14262 14263 14264 /* 14265 * called to do polled I/O by fcp_start() 14266 * 14267 * return a transport status value, i.e. TRAN_ACCECPT for success 14268 */ 14269 static int 14270 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14271 { 14272 int rval; 14273 14274 #ifdef DEBUG 14275 mutex_enter(&pptr->port_pkt_mutex); 14276 pptr->port_npkts++; 14277 mutex_exit(&pptr->port_pkt_mutex); 14278 #endif /* DEBUG */ 14279 14280 if (cmd->cmd_fp_pkt->pkt_timeout) { 14281 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14282 } else { 14283 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14284 } 14285 14286 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14287 14288 cmd->cmd_state = FCP_PKT_ISSUED; 14289 14290 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14291 14292 #ifdef DEBUG 14293 mutex_enter(&pptr->port_pkt_mutex); 14294 pptr->port_npkts--; 14295 mutex_exit(&pptr->port_pkt_mutex); 14296 #endif /* DEBUG */ 14297 14298 cmd->cmd_state = FCP_PKT_IDLE; 14299 14300 switch (rval) { 14301 case FC_SUCCESS: 14302 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14303 fcp_complete_pkt(cmd->cmd_fp_pkt); 14304 rval = TRAN_ACCEPT; 14305 } else { 14306 rval = TRAN_FATAL_ERROR; 14307 } 14308 break; 14309 14310 case FC_TRAN_BUSY: 14311 rval = TRAN_BUSY; 14312 cmd->cmd_pkt->pkt_resid = 0; 14313 break; 14314 14315 case FC_BADPACKET: 14316 rval = TRAN_BADPKT; 14317 break; 14318 14319 default: 14320 rval = TRAN_FATAL_ERROR; 14321 break; 14322 } 14323 14324 return (rval); 14325 } 14326 14327 14328 /* 14329 * called by some of the following transport-called routines to convert 14330 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14331 */ 14332 static struct fcp_port * 14333 fcp_dip2port(dev_info_t *dip) 14334 { 14335 int instance; 14336 14337 instance = ddi_get_instance(dip); 14338 return (ddi_get_soft_state(fcp_softstate, instance)); 14339 } 14340 14341 14342 /* 14343 * called internally to return a LUN given a dip 14344 */ 14345 struct fcp_lun * 14346 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14347 { 14348 struct fcp_tgt *ptgt; 14349 struct fcp_lun *plun; 14350 int i; 14351 14352 14353 ASSERT(mutex_owned(&pptr->port_mutex)); 14354 14355 for (i = 0; i < FCP_NUM_HASH; i++) { 14356 for (ptgt = pptr->port_tgt_hash_table[i]; 14357 ptgt != NULL; 14358 ptgt = ptgt->tgt_next) { 14359 mutex_enter(&ptgt->tgt_mutex); 14360 for (plun = ptgt->tgt_lun; plun != NULL; 14361 plun = plun->lun_next) { 14362 mutex_enter(&plun->lun_mutex); 14363 if (plun->lun_cip == cip) { 14364 mutex_exit(&plun->lun_mutex); 14365 mutex_exit(&ptgt->tgt_mutex); 14366 return (plun); /* match found */ 14367 } 14368 mutex_exit(&plun->lun_mutex); 14369 } 14370 mutex_exit(&ptgt->tgt_mutex); 14371 } 14372 } 14373 return (NULL); /* no LUN found */ 14374 } 14375 14376 /* 14377 * pass an element to the hotplug list, kick the hotplug thread 14378 * and wait for the element to get processed by the hotplug thread. 14379 * on return the element is freed. 14380 * 14381 * return zero success and non-zero on failure 14382 * 14383 * acquires/releases the target mutex 14384 * 14385 */ 14386 static int 14387 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14388 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14389 { 14390 struct fcp_hp_elem *elem; 14391 int rval; 14392 14393 mutex_enter(&plun->lun_tgt->tgt_mutex); 14394 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14395 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14396 mutex_exit(&plun->lun_tgt->tgt_mutex); 14397 fcp_log(CE_CONT, pptr->port_dip, 14398 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14399 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14400 return (NDI_FAILURE); 14401 } 14402 mutex_exit(&plun->lun_tgt->tgt_mutex); 14403 mutex_enter(&elem->mutex); 14404 if (elem->wait) { 14405 while (elem->wait) { 14406 cv_wait(&elem->cv, &elem->mutex); 14407 } 14408 } 14409 rval = (elem->result); 14410 mutex_exit(&elem->mutex); 14411 mutex_destroy(&elem->mutex); 14412 cv_destroy(&elem->cv); 14413 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14414 return (rval); 14415 } 14416 14417 /* 14418 * pass an element to the hotplug list, and then 14419 * kick the hotplug thread 14420 * 14421 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14422 * 14423 * acquires/releases the hotplug mutex 14424 * 14425 * called with the target mutex owned 14426 * 14427 * memory acquired in NOSLEEP mode 14428 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14429 * for the hp daemon to process the request and is responsible for 14430 * freeing the element 14431 */ 14432 static struct fcp_hp_elem * 14433 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14434 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14435 { 14436 struct fcp_hp_elem *elem; 14437 dev_info_t *pdip; 14438 14439 ASSERT(pptr != NULL); 14440 ASSERT(plun != NULL); 14441 ASSERT(plun->lun_tgt != NULL); 14442 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14443 14444 /* create space for a hotplug element */ 14445 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14446 == NULL) { 14447 fcp_log(CE_WARN, NULL, 14448 "!can't allocate memory for hotplug element"); 14449 return (NULL); 14450 } 14451 14452 /* fill in hotplug element */ 14453 elem->port = pptr; 14454 elem->lun = plun; 14455 elem->cip = cip; 14456 elem->old_lun_mpxio = plun->lun_mpxio; 14457 elem->what = what; 14458 elem->flags = flags; 14459 elem->link_cnt = link_cnt; 14460 elem->tgt_cnt = tgt_cnt; 14461 elem->wait = wait; 14462 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14463 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14464 14465 /* schedule the hotplug task */ 14466 pdip = pptr->port_dip; 14467 mutex_enter(&plun->lun_mutex); 14468 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14469 plun->lun_event_count++; 14470 elem->event_cnt = plun->lun_event_count; 14471 } 14472 mutex_exit(&plun->lun_mutex); 14473 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14474 (void *)elem, KM_NOSLEEP) == NULL) { 14475 mutex_enter(&plun->lun_mutex); 14476 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14477 plun->lun_event_count--; 14478 } 14479 mutex_exit(&plun->lun_mutex); 14480 kmem_free(elem, sizeof (*elem)); 14481 return (0); 14482 } 14483 14484 return (elem); 14485 } 14486 14487 14488 static void 14489 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14490 { 14491 int rval; 14492 struct scsi_address *ap; 14493 struct fcp_lun *plun; 14494 struct fcp_tgt *ptgt; 14495 fc_packet_t *fpkt; 14496 14497 ap = &cmd->cmd_pkt->pkt_address; 14498 plun = ADDR2LUN(ap); 14499 ptgt = plun->lun_tgt; 14500 14501 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14502 14503 cmd->cmd_state = FCP_PKT_IDLE; 14504 14505 mutex_enter(&pptr->port_mutex); 14506 mutex_enter(&ptgt->tgt_mutex); 14507 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14508 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14509 fc_ulp_rscn_info_t *rscnp; 14510 14511 cmd->cmd_state = FCP_PKT_ISSUED; 14512 14513 /* 14514 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14515 * originally NULL, hence we try to set it to the pd pointed 14516 * to by the SCSI device we're trying to get to. 14517 */ 14518 14519 fpkt = cmd->cmd_fp_pkt; 14520 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14521 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14522 /* 14523 * We need to notify the transport that we now have a 14524 * reference to the remote port handle. 14525 */ 14526 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14527 } 14528 14529 mutex_exit(&ptgt->tgt_mutex); 14530 mutex_exit(&pptr->port_mutex); 14531 14532 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14533 14534 /* prepare the packet */ 14535 14536 fcp_prepare_pkt(pptr, cmd, plun); 14537 14538 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14539 pkt_ulp_rscn_infop; 14540 14541 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14542 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14543 14544 if (rscnp != NULL) { 14545 rscnp->ulp_rscn_count = 14546 fc_ulp_get_rscn_count(pptr-> 14547 port_fp_handle); 14548 } 14549 14550 rval = fcp_transport(pptr->port_fp_handle, 14551 cmd->cmd_fp_pkt, 0); 14552 14553 if (rval == FC_SUCCESS) { 14554 return; 14555 } 14556 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14557 } else { 14558 mutex_exit(&ptgt->tgt_mutex); 14559 mutex_exit(&pptr->port_mutex); 14560 } 14561 14562 fcp_queue_pkt(pptr, cmd); 14563 } 14564 14565 14566 static void 14567 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14568 { 14569 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14570 14571 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14572 cmd->cmd_state = FCP_PKT_IDLE; 14573 14574 cmd->cmd_pkt->pkt_reason = reason; 14575 cmd->cmd_pkt->pkt_state = 0; 14576 cmd->cmd_pkt->pkt_statistics = statistics; 14577 14578 fcp_post_callback(cmd); 14579 } 14580 14581 /* 14582 * Function: fcp_queue_pkt 14583 * 14584 * Description: This function queues the packet passed by the caller into 14585 * the list of packets of the FCP port. 14586 * 14587 * Argument: *pptr FCP port. 14588 * *cmd FCP packet to queue. 14589 * 14590 * Return Value: None 14591 * 14592 * Context: User, Kernel and Interrupt context. 14593 */ 14594 static void 14595 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14596 { 14597 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14598 14599 mutex_enter(&pptr->port_pkt_mutex); 14600 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14601 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14602 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14603 14604 /* 14605 * zero pkt_time means hang around for ever 14606 */ 14607 if (cmd->cmd_pkt->pkt_time) { 14608 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14609 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14610 } else { 14611 /* 14612 * Indicate the watch thread to fail the 14613 * command by setting it to highest value 14614 */ 14615 cmd->cmd_timeout = fcp_watchdog_time; 14616 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14617 } 14618 } 14619 14620 if (pptr->port_pkt_head) { 14621 ASSERT(pptr->port_pkt_tail != NULL); 14622 14623 pptr->port_pkt_tail->cmd_next = cmd; 14624 pptr->port_pkt_tail = cmd; 14625 } else { 14626 ASSERT(pptr->port_pkt_tail == NULL); 14627 14628 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14629 } 14630 cmd->cmd_next = NULL; 14631 mutex_exit(&pptr->port_pkt_mutex); 14632 } 14633 14634 /* 14635 * Function: fcp_update_targets 14636 * 14637 * Description: This function applies the specified change of state to all 14638 * the targets listed. The operation applied is 'set'. 14639 * 14640 * Argument: *pptr FCP port. 14641 * *dev_list Array of fc_portmap_t structures. 14642 * count Length of dev_list. 14643 * state State bits to update. 14644 * cause Reason for the update. 14645 * 14646 * Return Value: None 14647 * 14648 * Context: User, Kernel and Interrupt context. 14649 * The mutex pptr->port_mutex must be held. 14650 */ 14651 static void 14652 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14653 uint32_t count, uint32_t state, int cause) 14654 { 14655 fc_portmap_t *map_entry; 14656 struct fcp_tgt *ptgt; 14657 14658 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14659 14660 while (count--) { 14661 map_entry = &(dev_list[count]); 14662 ptgt = fcp_lookup_target(pptr, 14663 (uchar_t *)&(map_entry->map_pwwn)); 14664 if (ptgt == NULL) { 14665 continue; 14666 } 14667 14668 mutex_enter(&ptgt->tgt_mutex); 14669 ptgt->tgt_trace = 0; 14670 ptgt->tgt_change_cnt++; 14671 ptgt->tgt_statec_cause = cause; 14672 ptgt->tgt_tmp_cnt = 1; 14673 fcp_update_tgt_state(ptgt, FCP_SET, state); 14674 mutex_exit(&ptgt->tgt_mutex); 14675 } 14676 } 14677 14678 static int 14679 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14680 int lcount, int tcount, int cause) 14681 { 14682 int rval; 14683 14684 mutex_enter(&pptr->port_mutex); 14685 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14686 mutex_exit(&pptr->port_mutex); 14687 14688 return (rval); 14689 } 14690 14691 14692 static int 14693 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14694 int lcount, int tcount, int cause) 14695 { 14696 int finish_init = 0; 14697 int finish_tgt = 0; 14698 int do_finish_init = 0; 14699 int rval = FCP_NO_CHANGE; 14700 14701 if (cause == FCP_CAUSE_LINK_CHANGE || 14702 cause == FCP_CAUSE_LINK_DOWN) { 14703 do_finish_init = 1; 14704 } 14705 14706 if (ptgt != NULL) { 14707 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14708 FCP_BUF_LEVEL_2, 0, 14709 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14710 " cause = %d, d_id = 0x%x, tgt_done = %d", 14711 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14712 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14713 ptgt->tgt_d_id, ptgt->tgt_done); 14714 14715 mutex_enter(&ptgt->tgt_mutex); 14716 14717 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14718 rval = FCP_DEV_CHANGE; 14719 if (do_finish_init && ptgt->tgt_done == 0) { 14720 ptgt->tgt_done++; 14721 finish_init = 1; 14722 } 14723 } else { 14724 if (--ptgt->tgt_tmp_cnt <= 0) { 14725 ptgt->tgt_tmp_cnt = 0; 14726 finish_tgt = 1; 14727 14728 if (do_finish_init) { 14729 finish_init = 1; 14730 } 14731 } 14732 } 14733 mutex_exit(&ptgt->tgt_mutex); 14734 } else { 14735 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14736 FCP_BUF_LEVEL_2, 0, 14737 "Call Finish Init for NO target"); 14738 14739 if (do_finish_init) { 14740 finish_init = 1; 14741 } 14742 } 14743 14744 if (finish_tgt) { 14745 ASSERT(ptgt != NULL); 14746 14747 mutex_enter(&ptgt->tgt_mutex); 14748 #ifdef DEBUG 14749 bzero(ptgt->tgt_tmp_cnt_stack, 14750 sizeof (ptgt->tgt_tmp_cnt_stack)); 14751 14752 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14753 FCP_STACK_DEPTH); 14754 #endif /* DEBUG */ 14755 mutex_exit(&ptgt->tgt_mutex); 14756 14757 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14758 } 14759 14760 if (finish_init && lcount == pptr->port_link_cnt) { 14761 ASSERT(pptr->port_tmp_cnt > 0); 14762 if (--pptr->port_tmp_cnt == 0) { 14763 fcp_finish_init(pptr); 14764 } 14765 } else if (lcount != pptr->port_link_cnt) { 14766 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14767 fcp_trace, FCP_BUF_LEVEL_2, 0, 14768 "fcp_call_finish_init_held,1: state change occured" 14769 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14770 } 14771 14772 return (rval); 14773 } 14774 14775 static void 14776 fcp_reconfigure_luns(void * tgt_handle) 14777 { 14778 uint32_t dev_cnt; 14779 fc_portmap_t *devlist; 14780 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14781 struct fcp_port *pptr = ptgt->tgt_port; 14782 14783 /* 14784 * If the timer that fires this off got canceled too late, the 14785 * target could have been destroyed. 14786 */ 14787 14788 if (ptgt->tgt_tid == NULL) { 14789 return; 14790 } 14791 14792 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14793 if (devlist == NULL) { 14794 fcp_log(CE_WARN, pptr->port_dip, 14795 "!fcp%d: failed to allocate for portmap", 14796 pptr->port_instance); 14797 return; 14798 } 14799 14800 dev_cnt = 1; 14801 devlist->map_pd = ptgt->tgt_pd_handle; 14802 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14803 devlist->map_did.port_id = ptgt->tgt_d_id; 14804 14805 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14806 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14807 14808 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14809 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14810 devlist->map_flags = 0; 14811 14812 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14813 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14814 14815 /* 14816 * Clear the tgt_tid after no more references to 14817 * the fcp_tgt 14818 */ 14819 mutex_enter(&ptgt->tgt_mutex); 14820 ptgt->tgt_tid = NULL; 14821 mutex_exit(&ptgt->tgt_mutex); 14822 14823 kmem_free(devlist, sizeof (*devlist)); 14824 } 14825 14826 14827 static void 14828 fcp_free_targets(struct fcp_port *pptr) 14829 { 14830 int i; 14831 struct fcp_tgt *ptgt; 14832 14833 mutex_enter(&pptr->port_mutex); 14834 for (i = 0; i < FCP_NUM_HASH; i++) { 14835 ptgt = pptr->port_tgt_hash_table[i]; 14836 while (ptgt != NULL) { 14837 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14838 14839 fcp_free_target(ptgt); 14840 ptgt = next_tgt; 14841 } 14842 } 14843 mutex_exit(&pptr->port_mutex); 14844 } 14845 14846 14847 static void 14848 fcp_free_target(struct fcp_tgt *ptgt) 14849 { 14850 struct fcp_lun *plun; 14851 timeout_id_t tid; 14852 14853 mutex_enter(&ptgt->tgt_mutex); 14854 tid = ptgt->tgt_tid; 14855 14856 /* 14857 * Cancel any pending timeouts for this target. 14858 */ 14859 14860 if (tid != NULL) { 14861 /* 14862 * Set tgt_tid to NULL first to avoid a race in the callback. 14863 * If tgt_tid is NULL, the callback will simply return. 14864 */ 14865 ptgt->tgt_tid = NULL; 14866 mutex_exit(&ptgt->tgt_mutex); 14867 (void) untimeout(tid); 14868 mutex_enter(&ptgt->tgt_mutex); 14869 } 14870 14871 plun = ptgt->tgt_lun; 14872 while (plun != NULL) { 14873 struct fcp_lun *next_lun = plun->lun_next; 14874 14875 fcp_dealloc_lun(plun); 14876 plun = next_lun; 14877 } 14878 14879 mutex_exit(&ptgt->tgt_mutex); 14880 fcp_dealloc_tgt(ptgt); 14881 } 14882 14883 /* 14884 * Function: fcp_is_retryable 14885 * 14886 * Description: Indicates if the internal packet is retryable. 14887 * 14888 * Argument: *icmd FCP internal packet. 14889 * 14890 * Return Value: 0 Not retryable 14891 * 1 Retryable 14892 * 14893 * Context: User, Kernel and Interrupt context 14894 */ 14895 static int 14896 fcp_is_retryable(struct fcp_ipkt *icmd) 14897 { 14898 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14899 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14900 return (0); 14901 } 14902 14903 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14904 icmd->ipkt_port->port_deadline) ? 1 : 0); 14905 } 14906 14907 /* 14908 * Function: fcp_create_on_demand 14909 * 14910 * Argument: *pptr FCP port. 14911 * *pwwn Port WWN. 14912 * 14913 * Return Value: 0 Success 14914 * EIO 14915 * ENOMEM 14916 * EBUSY 14917 * EINVAL 14918 * 14919 * Context: User and Kernel context 14920 */ 14921 static int 14922 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14923 { 14924 int wait_ms; 14925 int tcount; 14926 int lcount; 14927 int ret; 14928 int error; 14929 int rval = EIO; 14930 int ntries; 14931 fc_portmap_t *devlist; 14932 opaque_t pd; 14933 struct fcp_lun *plun; 14934 struct fcp_tgt *ptgt; 14935 int old_manual = 0; 14936 14937 /* Allocates the fc_portmap_t structure. */ 14938 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14939 14940 /* 14941 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14942 * in the commented statement below: 14943 * 14944 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14945 * 14946 * Below, the deadline for the discovery process is set. 14947 */ 14948 mutex_enter(&pptr->port_mutex); 14949 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14950 mutex_exit(&pptr->port_mutex); 14951 14952 /* 14953 * We try to find the remote port based on the WWN provided by the 14954 * caller. We actually ask fp/fctl if it has it. 14955 */ 14956 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14957 (la_wwn_t *)pwwn, &error, 1); 14958 14959 if (pd == NULL) { 14960 kmem_free(devlist, sizeof (*devlist)); 14961 return (rval); 14962 } 14963 14964 /* 14965 * The remote port was found. We ask fp/fctl to update our 14966 * fc_portmap_t structure. 14967 */ 14968 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14969 (la_wwn_t *)pwwn, devlist); 14970 if (ret != FC_SUCCESS) { 14971 kmem_free(devlist, sizeof (*devlist)); 14972 return (rval); 14973 } 14974 14975 /* 14976 * The map flag field is set to indicates that the creation is being 14977 * done at the user request (Ioclt probably luxadm or cfgadm). 14978 */ 14979 devlist->map_type = PORT_DEVICE_USER_CREATE; 14980 14981 mutex_enter(&pptr->port_mutex); 14982 14983 /* 14984 * We check to see if fcp already has a target that describes the 14985 * device being created. If not it is created. 14986 */ 14987 ptgt = fcp_lookup_target(pptr, pwwn); 14988 if (ptgt == NULL) { 14989 lcount = pptr->port_link_cnt; 14990 mutex_exit(&pptr->port_mutex); 14991 14992 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14993 if (ptgt == NULL) { 14994 fcp_log(CE_WARN, pptr->port_dip, 14995 "!FC target allocation failed"); 14996 return (ENOMEM); 14997 } 14998 14999 mutex_enter(&pptr->port_mutex); 15000 } 15001 15002 mutex_enter(&ptgt->tgt_mutex); 15003 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 15004 ptgt->tgt_tmp_cnt = 1; 15005 ptgt->tgt_device_created = 0; 15006 /* 15007 * If fabric and auto config is set but the target was 15008 * manually unconfigured then reset to the manual_config_only to 15009 * 0 so the device will get configured. 15010 */ 15011 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15012 fcp_enable_auto_configuration && 15013 ptgt->tgt_manual_config_only == 1) { 15014 old_manual = 1; 15015 ptgt->tgt_manual_config_only = 0; 15016 } 15017 mutex_exit(&ptgt->tgt_mutex); 15018 15019 fcp_update_targets(pptr, devlist, 1, 15020 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 15021 15022 lcount = pptr->port_link_cnt; 15023 tcount = ptgt->tgt_change_cnt; 15024 15025 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 15026 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 15027 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15028 fcp_enable_auto_configuration && old_manual) { 15029 mutex_enter(&ptgt->tgt_mutex); 15030 ptgt->tgt_manual_config_only = 1; 15031 mutex_exit(&ptgt->tgt_mutex); 15032 } 15033 15034 if (pptr->port_link_cnt != lcount || 15035 ptgt->tgt_change_cnt != tcount) { 15036 rval = EBUSY; 15037 } 15038 mutex_exit(&pptr->port_mutex); 15039 15040 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15041 FCP_BUF_LEVEL_3, 0, 15042 "fcp_create_on_demand: mapflags ptgt=%x, " 15043 "lcount=%x::port_link_cnt=%x, " 15044 "tcount=%x: tgt_change_cnt=%x, rval=%x", 15045 ptgt, lcount, pptr->port_link_cnt, 15046 tcount, ptgt->tgt_change_cnt, rval); 15047 return (rval); 15048 } 15049 15050 /* 15051 * Due to lack of synchronization mechanisms, we perform 15052 * periodic monitoring of our request; Because requests 15053 * get dropped when another one supercedes (either because 15054 * of a link change or a target change), it is difficult to 15055 * provide a clean synchronization mechanism (such as a 15056 * semaphore or a conditional variable) without exhaustively 15057 * rewriting the mainline discovery code of this driver. 15058 */ 15059 wait_ms = 500; 15060 15061 ntries = fcp_max_target_retries; 15062 15063 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15064 FCP_BUF_LEVEL_3, 0, 15065 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15066 "lcount=%x::port_link_cnt=%x, " 15067 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15068 "tgt_tmp_cnt =%x", 15069 ntries, ptgt, lcount, pptr->port_link_cnt, 15070 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15071 ptgt->tgt_tmp_cnt); 15072 15073 mutex_enter(&ptgt->tgt_mutex); 15074 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15075 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15076 mutex_exit(&ptgt->tgt_mutex); 15077 mutex_exit(&pptr->port_mutex); 15078 15079 delay(drv_usectohz(wait_ms * 1000)); 15080 15081 mutex_enter(&pptr->port_mutex); 15082 mutex_enter(&ptgt->tgt_mutex); 15083 } 15084 15085 15086 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15087 rval = EBUSY; 15088 } else { 15089 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15090 FCP_TGT_NODE_PRESENT) { 15091 rval = 0; 15092 } 15093 } 15094 15095 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15096 FCP_BUF_LEVEL_3, 0, 15097 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15098 "lcount=%x::port_link_cnt=%x, " 15099 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15100 "tgt_tmp_cnt =%x", 15101 ntries, ptgt, lcount, pptr->port_link_cnt, 15102 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15103 ptgt->tgt_tmp_cnt); 15104 15105 if (rval) { 15106 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15107 fcp_enable_auto_configuration && old_manual) { 15108 ptgt->tgt_manual_config_only = 1; 15109 } 15110 mutex_exit(&ptgt->tgt_mutex); 15111 mutex_exit(&pptr->port_mutex); 15112 kmem_free(devlist, sizeof (*devlist)); 15113 15114 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15115 FCP_BUF_LEVEL_3, 0, 15116 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15117 "lcount=%x::port_link_cnt=%x, " 15118 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15119 "tgt_device_created=%x, tgt D_ID=%x", 15120 ntries, ptgt, lcount, pptr->port_link_cnt, 15121 tcount, ptgt->tgt_change_cnt, rval, 15122 ptgt->tgt_device_created, ptgt->tgt_d_id); 15123 return (rval); 15124 } 15125 15126 if ((plun = ptgt->tgt_lun) != NULL) { 15127 tcount = plun->lun_tgt->tgt_change_cnt; 15128 } else { 15129 rval = EINVAL; 15130 } 15131 lcount = pptr->port_link_cnt; 15132 15133 /* 15134 * Configuring the target with no LUNs will fail. We 15135 * should reset the node state so that it is not 15136 * automatically configured when the LUNs are added 15137 * to this target. 15138 */ 15139 if (ptgt->tgt_lun_cnt == 0) { 15140 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15141 } 15142 mutex_exit(&ptgt->tgt_mutex); 15143 mutex_exit(&pptr->port_mutex); 15144 15145 while (plun) { 15146 child_info_t *cip; 15147 15148 mutex_enter(&plun->lun_mutex); 15149 cip = plun->lun_cip; 15150 mutex_exit(&plun->lun_mutex); 15151 15152 mutex_enter(&ptgt->tgt_mutex); 15153 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15154 mutex_exit(&ptgt->tgt_mutex); 15155 15156 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15157 FCP_ONLINE, lcount, tcount, 15158 NDI_ONLINE_ATTACH); 15159 if (rval != NDI_SUCCESS) { 15160 FCP_TRACE(fcp_logq, 15161 pptr->port_instbuf, fcp_trace, 15162 FCP_BUF_LEVEL_3, 0, 15163 "fcp_create_on_demand: " 15164 "pass_to_hp_and_wait failed " 15165 "rval=%x", rval); 15166 rval = EIO; 15167 } else { 15168 mutex_enter(&LUN_TGT->tgt_mutex); 15169 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15170 FCP_LUN_BUSY); 15171 mutex_exit(&LUN_TGT->tgt_mutex); 15172 } 15173 mutex_enter(&ptgt->tgt_mutex); 15174 } 15175 15176 plun = plun->lun_next; 15177 mutex_exit(&ptgt->tgt_mutex); 15178 } 15179 15180 kmem_free(devlist, sizeof (*devlist)); 15181 15182 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15183 fcp_enable_auto_configuration && old_manual) { 15184 mutex_enter(&ptgt->tgt_mutex); 15185 /* if successful then set manual to 0 */ 15186 if (rval == 0) { 15187 ptgt->tgt_manual_config_only = 0; 15188 } else { 15189 /* reset to 1 so the user has to do the config */ 15190 ptgt->tgt_manual_config_only = 1; 15191 } 15192 mutex_exit(&ptgt->tgt_mutex); 15193 } 15194 15195 return (rval); 15196 } 15197 15198 15199 static void 15200 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15201 { 15202 int count; 15203 uchar_t byte; 15204 15205 count = 0; 15206 while (*string) { 15207 byte = FCP_ATOB(*string); string++; 15208 byte = byte << 4 | FCP_ATOB(*string); string++; 15209 bytes[count++] = byte; 15210 15211 if (count >= byte_len) { 15212 break; 15213 } 15214 } 15215 } 15216 15217 static void 15218 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15219 { 15220 int i; 15221 15222 for (i = 0; i < FC_WWN_SIZE; i++) { 15223 (void) sprintf(string + (i * 2), 15224 "%02x", wwn[i]); 15225 } 15226 15227 } 15228 15229 static void 15230 fcp_print_error(fc_packet_t *fpkt) 15231 { 15232 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15233 fpkt->pkt_ulp_private; 15234 struct fcp_port *pptr; 15235 struct fcp_tgt *ptgt; 15236 struct fcp_lun *plun; 15237 caddr_t buf; 15238 int scsi_cmd = 0; 15239 15240 ptgt = icmd->ipkt_tgt; 15241 plun = icmd->ipkt_lun; 15242 pptr = ptgt->tgt_port; 15243 15244 buf = kmem_zalloc(256, KM_NOSLEEP); 15245 if (buf == NULL) { 15246 return; 15247 } 15248 15249 switch (icmd->ipkt_opcode) { 15250 case SCMD_REPORT_LUN: 15251 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15252 " lun=0x%%x failed"); 15253 scsi_cmd++; 15254 break; 15255 15256 case SCMD_INQUIRY_PAGE83: 15257 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15258 " lun=0x%%x failed"); 15259 scsi_cmd++; 15260 break; 15261 15262 case SCMD_INQUIRY: 15263 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15264 " lun=0x%%x failed"); 15265 scsi_cmd++; 15266 break; 15267 15268 case LA_ELS_PLOGI: 15269 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15270 break; 15271 15272 case LA_ELS_PRLI: 15273 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15274 break; 15275 } 15276 15277 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15278 struct fcp_rsp response, *rsp; 15279 uchar_t asc, ascq; 15280 caddr_t sense_key = NULL; 15281 struct fcp_rsp_info fcp_rsp_err, *bep; 15282 15283 if (icmd->ipkt_nodma) { 15284 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15285 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15286 sizeof (struct fcp_rsp)); 15287 } else { 15288 rsp = &response; 15289 bep = &fcp_rsp_err; 15290 15291 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15292 sizeof (struct fcp_rsp)); 15293 15294 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15295 bep, fpkt->pkt_resp_acc, 15296 sizeof (struct fcp_rsp_info)); 15297 } 15298 15299 15300 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15301 (void) sprintf(buf + strlen(buf), 15302 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15303 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15304 " senselen=%%x. Giving up"); 15305 15306 fcp_log(CE_WARN, pptr->port_dip, buf, 15307 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15308 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15309 rsp->fcp_u.fcp_status.reserved_1, 15310 rsp->fcp_response_len, rsp->fcp_sense_len); 15311 15312 kmem_free(buf, 256); 15313 return; 15314 } 15315 15316 if (rsp->fcp_u.fcp_status.rsp_len_set && 15317 bep->rsp_code != FCP_NO_FAILURE) { 15318 (void) sprintf(buf + strlen(buf), 15319 " FCP Response code = 0x%x", bep->rsp_code); 15320 } 15321 15322 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15323 struct scsi_extended_sense sense_info, *sense_ptr; 15324 15325 if (icmd->ipkt_nodma) { 15326 sense_ptr = (struct scsi_extended_sense *) 15327 ((caddr_t)fpkt->pkt_resp + 15328 sizeof (struct fcp_rsp) + 15329 rsp->fcp_response_len); 15330 } else { 15331 sense_ptr = &sense_info; 15332 15333 FCP_CP_IN(fpkt->pkt_resp + 15334 sizeof (struct fcp_rsp) + 15335 rsp->fcp_response_len, &sense_info, 15336 fpkt->pkt_resp_acc, 15337 sizeof (struct scsi_extended_sense)); 15338 } 15339 15340 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15341 NUM_IMPL_SENSE_KEYS) { 15342 sense_key = sense_keys[sense_ptr->es_key]; 15343 } else { 15344 sense_key = "Undefined"; 15345 } 15346 15347 asc = sense_ptr->es_add_code; 15348 ascq = sense_ptr->es_qual_code; 15349 15350 (void) sprintf(buf + strlen(buf), 15351 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15352 " Giving up"); 15353 15354 fcp_log(CE_WARN, pptr->port_dip, buf, 15355 ptgt->tgt_d_id, plun->lun_num, sense_key, 15356 asc, ascq); 15357 } else { 15358 (void) sprintf(buf + strlen(buf), 15359 " : SCSI status=%%x. Giving up"); 15360 15361 fcp_log(CE_WARN, pptr->port_dip, buf, 15362 ptgt->tgt_d_id, plun->lun_num, 15363 rsp->fcp_u.fcp_status.scsi_status); 15364 } 15365 } else { 15366 caddr_t state, reason, action, expln; 15367 15368 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15369 &action, &expln); 15370 15371 (void) sprintf(buf + strlen(buf), ": State:%%s," 15372 " Reason:%%s. Giving up"); 15373 15374 if (scsi_cmd) { 15375 fcp_log(CE_WARN, pptr->port_dip, buf, 15376 ptgt->tgt_d_id, plun->lun_num, state, reason); 15377 } else { 15378 fcp_log(CE_WARN, pptr->port_dip, buf, 15379 ptgt->tgt_d_id, state, reason); 15380 } 15381 } 15382 15383 kmem_free(buf, 256); 15384 } 15385 15386 15387 static int 15388 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15389 struct fcp_ipkt *icmd, int rval, caddr_t op) 15390 { 15391 int ret = DDI_FAILURE; 15392 char *error; 15393 15394 switch (rval) { 15395 case FC_DEVICE_BUSY_NEW_RSCN: 15396 /* 15397 * This means that there was a new RSCN that the transport 15398 * knows about (which the ULP *may* know about too) but the 15399 * pkt that was sent down was related to an older RSCN. So, we 15400 * are just going to reset the retry count and deadline and 15401 * continue to retry. The idea is that transport is currently 15402 * working on the new RSCN and will soon let the ULPs know 15403 * about it and when it does the existing logic will kick in 15404 * where it will change the tcount to indicate that something 15405 * changed on the target. So, rediscovery will start and there 15406 * will not be an infinite retry. 15407 * 15408 * For a full flow of how the RSCN info is transferred back and 15409 * forth, see fp.c 15410 */ 15411 icmd->ipkt_retries = 0; 15412 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15413 FCP_ICMD_DEADLINE; 15414 15415 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15416 FCP_BUF_LEVEL_3, 0, 15417 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15418 rval, ptgt->tgt_d_id); 15419 /* FALLTHROUGH */ 15420 15421 case FC_STATEC_BUSY: 15422 case FC_DEVICE_BUSY: 15423 case FC_PBUSY: 15424 case FC_FBUSY: 15425 case FC_TRAN_BUSY: 15426 case FC_OFFLINE: 15427 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15428 FCP_BUF_LEVEL_3, 0, 15429 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15430 rval, ptgt->tgt_d_id); 15431 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15432 fcp_is_retryable(icmd)) { 15433 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15434 ret = DDI_SUCCESS; 15435 } 15436 break; 15437 15438 case FC_LOGINREQ: 15439 /* 15440 * FC_LOGINREQ used to be handled just like all the cases 15441 * above. It has been changed to handled a PRLI that fails 15442 * with FC_LOGINREQ different than other ipkts that fail 15443 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15444 * a simple matter to turn it into a PLOGI instead, so that's 15445 * exactly what we do here. 15446 */ 15447 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15448 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15449 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15450 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15451 } else { 15452 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15453 FCP_BUF_LEVEL_3, 0, 15454 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15455 rval, ptgt->tgt_d_id); 15456 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15457 fcp_is_retryable(icmd)) { 15458 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15459 ret = DDI_SUCCESS; 15460 } 15461 } 15462 break; 15463 15464 default: 15465 mutex_enter(&pptr->port_mutex); 15466 mutex_enter(&ptgt->tgt_mutex); 15467 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15468 mutex_exit(&ptgt->tgt_mutex); 15469 mutex_exit(&pptr->port_mutex); 15470 15471 (void) fc_ulp_error(rval, &error); 15472 fcp_log(CE_WARN, pptr->port_dip, 15473 "!Failed to send %s to D_ID=%x error=%s", 15474 op, ptgt->tgt_d_id, error); 15475 } else { 15476 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15477 fcp_trace, FCP_BUF_LEVEL_2, 0, 15478 "fcp_handle_ipkt_errors,1: state change occured" 15479 " for D_ID=0x%x", ptgt->tgt_d_id); 15480 mutex_exit(&ptgt->tgt_mutex); 15481 mutex_exit(&pptr->port_mutex); 15482 } 15483 break; 15484 } 15485 15486 return (ret); 15487 } 15488 15489 15490 /* 15491 * Check of outstanding commands on any LUN for this target 15492 */ 15493 static int 15494 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15495 { 15496 struct fcp_lun *plun; 15497 struct fcp_pkt *cmd; 15498 15499 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15500 mutex_enter(&plun->lun_mutex); 15501 for (cmd = plun->lun_pkt_head; cmd != NULL; 15502 cmd = cmd->cmd_forw) { 15503 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15504 mutex_exit(&plun->lun_mutex); 15505 return (FC_SUCCESS); 15506 } 15507 } 15508 mutex_exit(&plun->lun_mutex); 15509 } 15510 15511 return (FC_FAILURE); 15512 } 15513 15514 static fc_portmap_t * 15515 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15516 { 15517 int i; 15518 fc_portmap_t *devlist; 15519 fc_portmap_t *devptr = NULL; 15520 struct fcp_tgt *ptgt; 15521 15522 mutex_enter(&pptr->port_mutex); 15523 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15524 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15525 ptgt = ptgt->tgt_next) { 15526 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15527 ++*dev_cnt; 15528 } 15529 } 15530 } 15531 15532 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15533 KM_NOSLEEP); 15534 if (devlist == NULL) { 15535 mutex_exit(&pptr->port_mutex); 15536 fcp_log(CE_WARN, pptr->port_dip, 15537 "!fcp%d: failed to allocate for portmap for construct map", 15538 pptr->port_instance); 15539 return (devptr); 15540 } 15541 15542 for (i = 0; i < FCP_NUM_HASH; i++) { 15543 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15544 ptgt = ptgt->tgt_next) { 15545 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15546 int ret; 15547 15548 ret = fc_ulp_pwwn_to_portmap( 15549 pptr->port_fp_handle, 15550 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15551 devlist); 15552 15553 if (ret == FC_SUCCESS) { 15554 devlist++; 15555 continue; 15556 } 15557 15558 devlist->map_pd = NULL; 15559 devlist->map_did.port_id = ptgt->tgt_d_id; 15560 devlist->map_hard_addr.hard_addr = 15561 ptgt->tgt_hard_addr; 15562 15563 devlist->map_state = PORT_DEVICE_INVALID; 15564 devlist->map_type = PORT_DEVICE_OLD; 15565 15566 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15567 &devlist->map_nwwn, FC_WWN_SIZE); 15568 15569 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15570 &devlist->map_pwwn, FC_WWN_SIZE); 15571 15572 devlist++; 15573 } 15574 } 15575 } 15576 15577 mutex_exit(&pptr->port_mutex); 15578 15579 return (devptr); 15580 } 15581 /* 15582 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15583 */ 15584 static void 15585 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15586 { 15587 int i; 15588 struct fcp_tgt *ptgt; 15589 struct fcp_lun *plun; 15590 15591 for (i = 0; i < FCP_NUM_HASH; i++) { 15592 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15593 ptgt = ptgt->tgt_next) { 15594 mutex_enter(&ptgt->tgt_mutex); 15595 for (plun = ptgt->tgt_lun; plun != NULL; 15596 plun = plun->lun_next) { 15597 if (plun->lun_mpxio && 15598 plun->lun_state & FCP_LUN_BUSY) { 15599 if (!fcp_pass_to_hp(pptr, plun, 15600 plun->lun_cip, 15601 FCP_MPXIO_PATH_SET_BUSY, 15602 pptr->port_link_cnt, 15603 ptgt->tgt_change_cnt, 0, 0)) { 15604 FCP_TRACE(fcp_logq, 15605 pptr->port_instbuf, 15606 fcp_trace, 15607 FCP_BUF_LEVEL_2, 0, 15608 "path_verifybusy: " 15609 "disable lun %p failed!", 15610 plun); 15611 } 15612 } 15613 } 15614 mutex_exit(&ptgt->tgt_mutex); 15615 } 15616 } 15617 } 15618 15619 static int 15620 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15621 { 15622 dev_info_t *cdip = NULL; 15623 dev_info_t *pdip = NULL; 15624 15625 ASSERT(plun); 15626 15627 mutex_enter(&plun->lun_mutex); 15628 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15629 mutex_exit(&plun->lun_mutex); 15630 return (NDI_FAILURE); 15631 } 15632 mutex_exit(&plun->lun_mutex); 15633 cdip = mdi_pi_get_client(PIP(cip)); 15634 pdip = mdi_pi_get_phci(PIP(cip)); 15635 15636 ASSERT(cdip != NULL); 15637 ASSERT(pdip != NULL); 15638 15639 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15640 /* LUN ready for IO */ 15641 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15642 } else { 15643 /* LUN busy to accept IO */ 15644 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15645 } 15646 return (NDI_SUCCESS); 15647 } 15648 15649 /* 15650 * Caller must free the returned string of MAXPATHLEN len 15651 * If the device is offline (-1 instance number) NULL 15652 * will be returned. 15653 */ 15654 static char * 15655 fcp_get_lun_path(struct fcp_lun *plun) { 15656 dev_info_t *dip = NULL; 15657 char *path = NULL; 15658 mdi_pathinfo_t *pip = NULL; 15659 15660 if (plun == NULL) { 15661 return (NULL); 15662 } 15663 15664 mutex_enter(&plun->lun_mutex); 15665 if (plun->lun_mpxio == 0) { 15666 dip = DIP(plun->lun_cip); 15667 mutex_exit(&plun->lun_mutex); 15668 } else { 15669 /* 15670 * lun_cip must be accessed with lun_mutex held. Here 15671 * plun->lun_cip either points to a valid node or it is NULL. 15672 * Make a copy so that we can release lun_mutex. 15673 */ 15674 pip = PIP(plun->lun_cip); 15675 15676 /* 15677 * Increase ref count on the path so that we can release 15678 * lun_mutex and still be sure that the pathinfo node (and thus 15679 * also the client) is not deallocated. If pip is NULL, this 15680 * has no effect. 15681 */ 15682 mdi_hold_path(pip); 15683 15684 mutex_exit(&plun->lun_mutex); 15685 15686 /* Get the client. If pip is NULL, we get NULL. */ 15687 dip = mdi_pi_get_client(pip); 15688 } 15689 15690 if (dip == NULL) 15691 goto out; 15692 if (ddi_get_instance(dip) < 0) 15693 goto out; 15694 15695 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15696 if (path == NULL) 15697 goto out; 15698 15699 (void) ddi_pathname(dip, path); 15700 15701 /* Clean up. */ 15702 out: 15703 if (pip != NULL) 15704 mdi_rele_path(pip); 15705 15706 /* 15707 * In reality, the user wants a fully valid path (one they can open) 15708 * but this string is lacking the mount point, and the minor node. 15709 * It would be nice if we could "figure these out" somehow 15710 * and fill them in. Otherwise, the userland code has to understand 15711 * driver specific details of which minor node is the "best" or 15712 * "right" one to expose. (Ex: which slice is the whole disk, or 15713 * which tape doesn't rewind) 15714 */ 15715 return (path); 15716 } 15717 15718 static int 15719 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15720 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15721 { 15722 int64_t reset_delay; 15723 int rval, retry = 0; 15724 struct fcp_port *pptr = fcp_dip2port(parent); 15725 15726 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15727 (ddi_get_lbolt64() - pptr->port_attach_time); 15728 if (reset_delay < 0) { 15729 reset_delay = 0; 15730 } 15731 15732 if (fcp_bus_config_debug) { 15733 flag |= NDI_DEVI_DEBUG; 15734 } 15735 15736 switch (op) { 15737 case BUS_CONFIG_ONE: 15738 /* 15739 * Retry the command since we need to ensure 15740 * the fabric devices are available for root 15741 */ 15742 while (retry++ < fcp_max_bus_config_retries) { 15743 rval = (ndi_busop_bus_config(parent, 15744 flag | NDI_MDI_FALLBACK, op, 15745 arg, childp, (clock_t)reset_delay)); 15746 if (rval == 0) { 15747 return (rval); 15748 } 15749 } 15750 15751 /* 15752 * drain taskq to make sure nodes are created and then 15753 * try again. 15754 */ 15755 taskq_wait(DEVI(parent)->devi_taskq); 15756 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15757 op, arg, childp, 0)); 15758 15759 case BUS_CONFIG_DRIVER: 15760 case BUS_CONFIG_ALL: { 15761 /* 15762 * delay till all devices report in (port_tmp_cnt == 0) 15763 * or FCP_INIT_WAIT_TIMEOUT 15764 */ 15765 mutex_enter(&pptr->port_mutex); 15766 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15767 (void) cv_timedwait(&pptr->port_config_cv, 15768 &pptr->port_mutex, 15769 ddi_get_lbolt() + (clock_t)reset_delay); 15770 reset_delay = 15771 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15772 (ddi_get_lbolt64() - pptr->port_attach_time); 15773 } 15774 mutex_exit(&pptr->port_mutex); 15775 /* drain taskq to make sure nodes are created */ 15776 taskq_wait(DEVI(parent)->devi_taskq); 15777 return (ndi_busop_bus_config(parent, flag, op, 15778 arg, childp, 0)); 15779 } 15780 15781 default: 15782 return (NDI_FAILURE); 15783 } 15784 /*NOTREACHED*/ 15785 } 15786 15787 static int 15788 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15789 ddi_bus_config_op_t op, void *arg) 15790 { 15791 if (fcp_bus_config_debug) { 15792 flag |= NDI_DEVI_DEBUG; 15793 } 15794 15795 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15796 } 15797 15798 15799 /* 15800 * Routine to copy GUID into the lun structure. 15801 * returns 0 if copy was successful and 1 if encountered a 15802 * failure and did not copy the guid. 15803 */ 15804 static int 15805 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15806 { 15807 15808 int retval = 0; 15809 15810 /* add one for the null terminator */ 15811 const unsigned int len = strlen(guidp) + 1; 15812 15813 if ((guidp == NULL) || (plun == NULL)) { 15814 return (1); 15815 } 15816 15817 /* 15818 * if the plun->lun_guid already has been allocated, 15819 * then check the size. if the size is exact, reuse 15820 * it....if not free it an allocate the required size. 15821 * The reallocation should NOT typically happen 15822 * unless the GUIDs reported changes between passes. 15823 * We free up and alloc again even if the 15824 * size was more than required. This is due to the 15825 * fact that the field lun_guid_size - serves 15826 * dual role of indicating the size of the wwn 15827 * size and ALSO the allocation size. 15828 */ 15829 if (plun->lun_guid) { 15830 if (plun->lun_guid_size != len) { 15831 /* 15832 * free the allocated memory and 15833 * initialize the field 15834 * lun_guid_size to 0. 15835 */ 15836 kmem_free(plun->lun_guid, plun->lun_guid_size); 15837 plun->lun_guid = NULL; 15838 plun->lun_guid_size = 0; 15839 } 15840 } 15841 /* 15842 * alloc only if not already done. 15843 */ 15844 if (plun->lun_guid == NULL) { 15845 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15846 if (plun->lun_guid == NULL) { 15847 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15848 "Unable to allocate" 15849 "Memory for GUID!!! size %d", len); 15850 retval = 1; 15851 } else { 15852 plun->lun_guid_size = len; 15853 } 15854 } 15855 if (plun->lun_guid) { 15856 /* 15857 * now copy the GUID 15858 */ 15859 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15860 } 15861 return (retval); 15862 } 15863 15864 /* 15865 * fcp_reconfig_wait 15866 * 15867 * Wait for a rediscovery/reconfiguration to complete before continuing. 15868 */ 15869 15870 static void 15871 fcp_reconfig_wait(struct fcp_port *pptr) 15872 { 15873 clock_t reconfig_start, wait_timeout; 15874 15875 /* 15876 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15877 * reconfiguration in progress. 15878 */ 15879 15880 mutex_enter(&pptr->port_mutex); 15881 if (pptr->port_tmp_cnt == 0) { 15882 mutex_exit(&pptr->port_mutex); 15883 return; 15884 } 15885 mutex_exit(&pptr->port_mutex); 15886 15887 /* 15888 * If we cause a reconfig by raising power, delay until all devices 15889 * report in (port_tmp_cnt returns to 0) 15890 */ 15891 15892 reconfig_start = ddi_get_lbolt(); 15893 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15894 15895 mutex_enter(&pptr->port_mutex); 15896 15897 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15898 pptr->port_tmp_cnt) { 15899 15900 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15901 reconfig_start + wait_timeout); 15902 } 15903 15904 mutex_exit(&pptr->port_mutex); 15905 15906 /* 15907 * Even if fcp_tmp_count isn't 0, continue without error. The port 15908 * we want may still be ok. If not, it will error out later 15909 */ 15910 } 15911 15912 /* 15913 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15914 * We rely on the fcp_global_mutex to provide protection against changes to 15915 * the fcp_lun_blacklist. 15916 * 15917 * You can describe a list of target port WWNs and LUN numbers which will 15918 * not be configured. LUN numbers will be interpreted as decimal. White 15919 * spaces and ',' can be used in the list of LUN numbers. 15920 * 15921 * To prevent LUNs 1 and 2 from being configured for target 15922 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15923 * 15924 * pwwn-lun-blacklist= 15925 * "510000f010fd92a1,1,2", 15926 * "510000e012079df1,1,2"; 15927 */ 15928 static void 15929 fcp_read_blacklist(dev_info_t *dip, 15930 struct fcp_black_list_entry **pplun_blacklist) { 15931 char **prop_array = NULL; 15932 char *curr_pwwn = NULL; 15933 char *curr_lun = NULL; 15934 uint32_t prop_item = 0; 15935 int idx = 0; 15936 int len = 0; 15937 15938 ASSERT(mutex_owned(&fcp_global_mutex)); 15939 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15940 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15941 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15942 return; 15943 } 15944 15945 for (idx = 0; idx < prop_item; idx++) { 15946 15947 curr_pwwn = prop_array[idx]; 15948 while (*curr_pwwn == ' ') { 15949 curr_pwwn++; 15950 } 15951 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15952 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15953 ", please check.", curr_pwwn); 15954 continue; 15955 } 15956 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15957 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15958 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15959 ", please check.", curr_pwwn); 15960 continue; 15961 } 15962 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15963 if (isxdigit(curr_pwwn[len]) != TRUE) { 15964 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15965 "blacklist, please check.", curr_pwwn); 15966 break; 15967 } 15968 } 15969 if (len != sizeof (la_wwn_t) * 2) { 15970 continue; 15971 } 15972 15973 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15974 *(curr_lun - 1) = '\0'; 15975 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15976 } 15977 15978 ddi_prop_free(prop_array); 15979 } 15980 15981 /* 15982 * Get the masking info about one remote target port designated by wwn. 15983 * Lun ids could be separated by ',' or white spaces. 15984 */ 15985 static void 15986 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15987 struct fcp_black_list_entry **pplun_blacklist) { 15988 int idx = 0; 15989 uint32_t offset = 0; 15990 unsigned long lun_id = 0; 15991 char lunid_buf[16]; 15992 char *pend = NULL; 15993 int illegal_digit = 0; 15994 15995 while (offset < strlen(curr_lun)) { 15996 while ((curr_lun[offset + idx] != ',') && 15997 (curr_lun[offset + idx] != '\0') && 15998 (curr_lun[offset + idx] != ' ')) { 15999 if (isdigit(curr_lun[offset + idx]) == 0) { 16000 illegal_digit++; 16001 } 16002 idx++; 16003 } 16004 if (illegal_digit > 0) { 16005 offset += (idx+1); /* To the start of next lun */ 16006 idx = 0; 16007 illegal_digit = 0; 16008 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16009 "the blacklist, please check digits.", 16010 curr_lun, curr_pwwn); 16011 continue; 16012 } 16013 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 16014 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16015 "the blacklist, please check the length of LUN#.", 16016 curr_lun, curr_pwwn); 16017 break; 16018 } 16019 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 16020 offset++; 16021 continue; 16022 } 16023 16024 bcopy(curr_lun + offset, lunid_buf, idx); 16025 lunid_buf[idx] = '\0'; 16026 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 16027 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 16028 } else { 16029 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16030 "the blacklist, please check %s.", 16031 curr_lun, curr_pwwn, lunid_buf); 16032 } 16033 offset += (idx+1); /* To the start of next lun */ 16034 idx = 0; 16035 } 16036 } 16037 16038 /* 16039 * Add one masking record 16040 */ 16041 static void 16042 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 16043 struct fcp_black_list_entry **pplun_blacklist) { 16044 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16045 struct fcp_black_list_entry *new_entry = NULL; 16046 la_wwn_t wwn; 16047 16048 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16049 while (tmp_entry) { 16050 if ((bcmp(&tmp_entry->wwn, &wwn, 16051 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16052 return; 16053 } 16054 16055 tmp_entry = tmp_entry->next; 16056 } 16057 16058 /* add to black list */ 16059 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16060 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16061 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16062 new_entry->lun = lun_id; 16063 new_entry->masked = 0; 16064 new_entry->next = *pplun_blacklist; 16065 *pplun_blacklist = new_entry; 16066 } 16067 16068 /* 16069 * Check if we should mask the specified lun of this fcp_tgt 16070 */ 16071 static int 16072 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 16073 struct fcp_black_list_entry *remote_port; 16074 16075 remote_port = fcp_lun_blacklist; 16076 while (remote_port != NULL) { 16077 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16078 if (remote_port->lun == lun_id) { 16079 remote_port->masked++; 16080 if (remote_port->masked == 1) { 16081 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16082 "%02x%02x%02x%02x%02x%02x%02x%02x " 16083 "is masked due to black listing.\n", 16084 lun_id, wwn->raw_wwn[0], 16085 wwn->raw_wwn[1], wwn->raw_wwn[2], 16086 wwn->raw_wwn[3], wwn->raw_wwn[4], 16087 wwn->raw_wwn[5], wwn->raw_wwn[6], 16088 wwn->raw_wwn[7]); 16089 } 16090 return (TRUE); 16091 } 16092 } 16093 remote_port = remote_port->next; 16094 } 16095 return (FALSE); 16096 } 16097 16098 /* 16099 * Release all allocated resources 16100 */ 16101 static void 16102 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 16103 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16104 struct fcp_black_list_entry *current_entry = NULL; 16105 16106 ASSERT(mutex_owned(&fcp_global_mutex)); 16107 /* 16108 * Traverse all luns 16109 */ 16110 while (tmp_entry) { 16111 current_entry = tmp_entry; 16112 tmp_entry = tmp_entry->next; 16113 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16114 } 16115 *pplun_blacklist = NULL; 16116 } 16117 16118 /* 16119 * In fcp module, 16120 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16121 */ 16122 static struct scsi_pkt * 16123 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16124 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16125 int flags, int (*callback)(), caddr_t arg) 16126 { 16127 fcp_port_t *pptr = ADDR2FCP(ap); 16128 fcp_pkt_t *cmd = NULL; 16129 fc_frame_hdr_t *hp; 16130 16131 /* 16132 * First step: get the packet 16133 */ 16134 if (pkt == NULL) { 16135 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16136 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16137 callback, arg); 16138 if (pkt == NULL) { 16139 return (NULL); 16140 } 16141 16142 /* 16143 * All fields in scsi_pkt will be initialized properly or 16144 * set to zero. We need do nothing for scsi_pkt. 16145 */ 16146 /* 16147 * But it's our responsibility to link other related data 16148 * structures. Their initialization will be done, just 16149 * before the scsi_pkt will be sent to FCA. 16150 */ 16151 cmd = PKT2CMD(pkt); 16152 cmd->cmd_pkt = pkt; 16153 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16154 /* 16155 * fc_packet_t 16156 */ 16157 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16158 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16159 sizeof (struct fcp_pkt)); 16160 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16161 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16162 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16163 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16164 /* 16165 * Fill in the Fabric Channel Header 16166 */ 16167 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16168 hp->r_ctl = R_CTL_COMMAND; 16169 hp->rsvd = 0; 16170 hp->type = FC_TYPE_SCSI_FCP; 16171 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16172 hp->seq_id = 0; 16173 hp->df_ctl = 0; 16174 hp->seq_cnt = 0; 16175 hp->ox_id = 0xffff; 16176 hp->rx_id = 0xffff; 16177 hp->ro = 0; 16178 } else { 16179 /* 16180 * We need think if we should reset any elements in 16181 * related data structures. 16182 */ 16183 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16184 fcp_trace, FCP_BUF_LEVEL_6, 0, 16185 "reusing pkt, flags %d", flags); 16186 cmd = PKT2CMD(pkt); 16187 if (cmd->cmd_fp_pkt->pkt_pd) { 16188 cmd->cmd_fp_pkt->pkt_pd = NULL; 16189 } 16190 } 16191 16192 /* 16193 * Second step: dma allocation/move 16194 */ 16195 if (bp && bp->b_bcount != 0) { 16196 /* 16197 * Mark if it's read or write 16198 */ 16199 if (bp->b_flags & B_READ) { 16200 cmd->cmd_flags |= CFLAG_IS_READ; 16201 } else { 16202 cmd->cmd_flags &= ~CFLAG_IS_READ; 16203 } 16204 16205 bp_mapin(bp); 16206 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16207 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16208 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16209 } else { 16210 /* 16211 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16212 * to send zero-length read/write. 16213 */ 16214 cmd->cmd_fp_pkt->pkt_data = NULL; 16215 cmd->cmd_fp_pkt->pkt_datalen = 0; 16216 } 16217 16218 return (pkt); 16219 } 16220 16221 static void 16222 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16223 { 16224 fcp_port_t *pptr = ADDR2FCP(ap); 16225 16226 /* 16227 * First we let FCA to uninitilize private part. 16228 */ 16229 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16230 PKT2CMD(pkt)->cmd_fp_pkt); 16231 16232 /* 16233 * Then we uninitialize fc_packet. 16234 */ 16235 16236 /* 16237 * Thirdly, we uninitializae fcp_pkt. 16238 */ 16239 16240 /* 16241 * In the end, we free scsi_pkt. 16242 */ 16243 scsi_hba_pkt_free(ap, pkt); 16244 } 16245 16246 static int 16247 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16248 { 16249 fcp_port_t *pptr = ADDR2FCP(ap); 16250 fcp_lun_t *plun = ADDR2LUN(ap); 16251 fcp_tgt_t *ptgt = plun->lun_tgt; 16252 fcp_pkt_t *cmd = PKT2CMD(pkt); 16253 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16254 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16255 int rval; 16256 16257 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16258 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16259 16260 /* 16261 * Firstly, we need initialize fcp_pkt_t 16262 * Secondly, we need initialize fcp_cmd_t. 16263 */ 16264 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16265 fcmd->fcp_data_len = fpkt->pkt_datalen; 16266 fcmd->fcp_ent_addr = plun->lun_addr; 16267 if (pkt->pkt_flags & FLAG_HTAG) { 16268 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16269 } else if (pkt->pkt_flags & FLAG_OTAG) { 16270 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16271 } else if (pkt->pkt_flags & FLAG_STAG) { 16272 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16273 } else { 16274 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16275 } 16276 16277 if (cmd->cmd_flags & CFLAG_IS_READ) { 16278 fcmd->fcp_cntl.cntl_read_data = 1; 16279 fcmd->fcp_cntl.cntl_write_data = 0; 16280 } else { 16281 fcmd->fcp_cntl.cntl_read_data = 0; 16282 fcmd->fcp_cntl.cntl_write_data = 1; 16283 } 16284 16285 /* 16286 * Then we need initialize fc_packet_t too. 16287 */ 16288 fpkt->pkt_timeout = pkt->pkt_time + 2; 16289 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16290 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16291 if (cmd->cmd_flags & CFLAG_IS_READ) { 16292 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16293 } else { 16294 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16295 } 16296 16297 if (pkt->pkt_flags & FLAG_NOINTR) { 16298 fpkt->pkt_comp = NULL; 16299 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16300 } else { 16301 fpkt->pkt_comp = fcp_cmd_callback; 16302 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16303 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16304 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16305 } 16306 } 16307 16308 /* 16309 * Lastly, we need initialize scsi_pkt 16310 */ 16311 pkt->pkt_reason = CMD_CMPLT; 16312 pkt->pkt_state = 0; 16313 pkt->pkt_statistics = 0; 16314 pkt->pkt_resid = 0; 16315 16316 /* 16317 * if interrupts aren't allowed (e.g. at dump time) then we'll 16318 * have to do polled I/O 16319 */ 16320 if (pkt->pkt_flags & FLAG_NOINTR) { 16321 return (fcp_dopoll(pptr, cmd)); 16322 } 16323 16324 cmd->cmd_state = FCP_PKT_ISSUED; 16325 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16326 if (rval == FC_SUCCESS) { 16327 return (TRAN_ACCEPT); 16328 } 16329 16330 /* 16331 * Need more consideration 16332 * 16333 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16334 */ 16335 cmd->cmd_state = FCP_PKT_IDLE; 16336 if (rval == FC_TRAN_BUSY) { 16337 return (TRAN_BUSY); 16338 } else { 16339 return (TRAN_FATAL_ERROR); 16340 } 16341 } 16342 16343 /* 16344 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16345 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16346 */ 16347 static void 16348 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16349 { 16350 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16351 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16352 } 16353 16354 /* 16355 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16356 */ 16357 static void 16358 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16359 { 16360 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16361 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16362 }