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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Fibre Channel SCSI ULP Mapping driver 26 */ 27 28 #include <sys/scsi/scsi.h> 29 #include <sys/types.h> 30 #include <sys/varargs.h> 31 #include <sys/devctl.h> 32 #include <sys/thread.h> 33 #include <sys/thread.h> 34 #include <sys/open.h> 35 #include <sys/file.h> 36 #include <sys/sunndi.h> 37 #include <sys/console.h> 38 #include <sys/proc.h> 39 #include <sys/time.h> 40 #include <sys/utsname.h> 41 #include <sys/scsi/impl/scsi_reset_notify.h> 42 #include <sys/ndi_impldefs.h> 43 #include <sys/byteorder.h> 44 #include <sys/fs/dv_node.h> 45 #include <sys/ctype.h> 46 #include <sys/sunmdi.h> 47 48 #include <sys/fibre-channel/fc.h> 49 #include <sys/fibre-channel/impl/fc_ulpif.h> 50 #include <sys/fibre-channel/ulp/fcpvar.h> 51 52 /* 53 * Discovery Process 54 * ================= 55 * 56 * The discovery process is a major function of FCP. In order to help 57 * understand that function a flow diagram is given here. This diagram 58 * doesn't claim to cover all the cases and the events that can occur during 59 * the discovery process nor the subtleties of the code. The code paths shown 60 * are simplified. Its purpose is to help the reader (and potentially bug 61 * fixer) have an overall view of the logic of the code. For that reason the 62 * diagram covers the simple case of the line coming up cleanly or of a new 63 * port attaching to FCP the link being up. The reader must keep in mind 64 * that: 65 * 66 * - There are special cases where bringing devices online and offline 67 * is driven by Ioctl. 68 * 69 * - The behavior of the discovery process can be modified through the 70 * .conf file. 71 * 72 * - The line can go down and come back up at any time during the 73 * discovery process which explains some of the complexity of the code. 74 * 75 * ............................................................................ 76 * 77 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 78 * 79 * 80 * +-------------------------+ 81 * fp/fctl module --->| fcp_port_attach | 82 * +-------------------------+ 83 * | | 84 * | | 85 * | v 86 * | +-------------------------+ 87 * | | fcp_handle_port_attach | 88 * | +-------------------------+ 89 * | | 90 * | | 91 * +--------------------+ | 92 * | | 93 * v v 94 * +-------------------------+ 95 * | fcp_statec_callback | 96 * +-------------------------+ 97 * | 98 * | 99 * v 100 * +-------------------------+ 101 * | fcp_handle_devices | 102 * +-------------------------+ 103 * | 104 * | 105 * v 106 * +-------------------------+ 107 * | fcp_handle_mapflags | 108 * +-------------------------+ 109 * | 110 * | 111 * v 112 * +-------------------------+ 113 * | fcp_send_els | 114 * | | 115 * | PLOGI or PRLI To all the| 116 * | reachable devices. | 117 * +-------------------------+ 118 * 119 * 120 * ............................................................................ 121 * 122 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 123 * STEP 1 are called (it is actually the same function). 124 * 125 * 126 * +-------------------------+ 127 * | fcp_icmd_callback | 128 * fp/fctl module --->| | 129 * | callback for PLOGI and | 130 * | PRLI. | 131 * +-------------------------+ 132 * | 133 * | 134 * Received PLOGI Accept /-\ Received PRLI Accept 135 * _ _ _ _ _ _ / \_ _ _ _ _ _ 136 * | \ / | 137 * | \-/ | 138 * | | 139 * v v 140 * +-------------------------+ +-------------------------+ 141 * | fcp_send_els | | fcp_send_scsi | 142 * | | | | 143 * | PRLI | | REPORT_LUN | 144 * +-------------------------+ +-------------------------+ 145 * 146 * ............................................................................ 147 * 148 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 149 * (It is actually the same function). 150 * 151 * 152 * +-------------------------+ 153 * fp/fctl module ------->| fcp_scsi_callback | 154 * +-------------------------+ 155 * | 156 * | 157 * | 158 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 159 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 160 * | \ / | 161 * | \-/ | 162 * | | | 163 * | Receive INQUIRY reply| | 164 * | | | 165 * v v v 166 * +------------------------+ +----------------------+ +----------------------+ 167 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 168 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 169 * +------------------------+ +----------------------+ +----------------------+ 170 * | | | 171 * | | | 172 * | | | 173 * v v | 174 * +-----------------+ +-----------------+ | 175 * | fcp_send_scsi | | fcp_send_scsi | | 176 * | | | | | 177 * | INQUIRY | | INQUIRY PAGE83 | | 178 * | (To each LUN) | +-----------------+ | 179 * +-----------------+ | 180 * | 181 * v 182 * +------------------------+ 183 * | fcp_call_finish_init | 184 * +------------------------+ 185 * | 186 * v 187 * +-----------------------------+ 188 * | fcp_call_finish_init_held | 189 * +-----------------------------+ 190 * | 191 * | 192 * All LUNs scanned /-\ 193 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 194 * | \ / 195 * | \-/ 196 * v | 197 * +------------------+ | 198 * | fcp_finish_tgt | | 199 * +------------------+ | 200 * | Target Not Offline and | 201 * Target Not Offline and | not marked and tgt_node_state | 202 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 203 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 204 * | \ / | | 205 * | \-/ | | 206 * v v | 207 * +----------------------------+ +-------------------+ | 208 * | fcp_offline_target | | fcp_create_luns | | 209 * | | +-------------------+ | 210 * | A structure fcp_tgt_elem | | | 211 * | is created and queued in | v | 212 * | the FCP port list | +-------------------+ | 213 * | port_offline_tgts. It | | fcp_pass_to_hp | | 214 * | will be unqueued by the | | | | 215 * | watchdog timer. | | Called for each | | 216 * +----------------------------+ | LUN. Dispatches | | 217 * | | fcp_hp_task | | 218 * | +-------------------+ | 219 * | | | 220 * | | | 221 * | | | 222 * | +---------------->| 223 * | | 224 * +---------------------------------------------->| 225 * | 226 * | 227 * All the targets (devices) have been scanned /-\ 228 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 229 * | \ / 230 * | \-/ 231 * +-------------------------------------+ | 232 * | fcp_finish_init | | 233 * | | | 234 * | Signal broadcasts the condition | | 235 * | variable port_config_cv of the FCP | | 236 * | port. One potential code sequence | | 237 * | waiting on the condition variable | | 238 * | the code sequence handling | | 239 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 240 * | The other is in the function | | 241 * | fcp_reconfig_wait which is called | | 242 * | in the transmit path preventing IOs | | 243 * | from going through till the disco- | | 244 * | very process is over. | | 245 * +-------------------------------------+ | 246 * | | 247 * | | 248 * +--------------------------------->| 249 * | 250 * v 251 * Return 252 * 253 * ............................................................................ 254 * 255 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 256 * 257 * 258 * +-------------------------+ 259 * | fcp_hp_task | 260 * +-------------------------+ 261 * | 262 * | 263 * v 264 * +-------------------------+ 265 * | fcp_trigger_lun | 266 * +-------------------------+ 267 * | 268 * | 269 * v 270 * Bring offline /-\ Bring online 271 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 272 * | \ / | 273 * | \-/ | 274 * v v 275 * +---------------------+ +-----------------------+ 276 * | fcp_offline_child | | fcp_get_cip | 277 * +---------------------+ | | 278 * | Creates a dev_info_t | 279 * | or a mdi_pathinfo_t | 280 * | depending on whether | 281 * | mpxio is on or off. | 282 * +-----------------------+ 283 * | 284 * | 285 * v 286 * +-----------------------+ 287 * | fcp_online_child | 288 * | | 289 * | Set device online | 290 * | using NDI or MDI. | 291 * +-----------------------+ 292 * 293 * ............................................................................ 294 * 295 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 296 * what is described here. We only show the target offline path. 297 * 298 * 299 * +--------------------------+ 300 * | fcp_watch | 301 * +--------------------------+ 302 * | 303 * | 304 * v 305 * +--------------------------+ 306 * | fcp_scan_offline_tgts | 307 * +--------------------------+ 308 * | 309 * | 310 * v 311 * +--------------------------+ 312 * | fcp_offline_target_now | 313 * +--------------------------+ 314 * | 315 * | 316 * v 317 * +--------------------------+ 318 * | fcp_offline_tgt_luns | 319 * +--------------------------+ 320 * | 321 * | 322 * v 323 * +--------------------------+ 324 * | fcp_offline_lun | 325 * +--------------------------+ 326 * | 327 * | 328 * v 329 * +----------------------------------+ 330 * | fcp_offline_lun_now | 331 * | | 332 * | A request (or two if mpxio) is | 333 * | sent to the hot plug task using | 334 * | a fcp_hp_elem structure. | 335 * +----------------------------------+ 336 */ 337 338 /* 339 * Functions registered with DDI framework 340 */ 341 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 342 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 343 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 344 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 345 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 346 cred_t *credp, int *rval); 347 348 /* 349 * Functions registered with FC Transport framework 350 */ 351 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 352 fc_attach_cmd_t cmd, uint32_t s_id); 353 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 354 fc_detach_cmd_t cmd); 355 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 356 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 357 uint32_t claimed); 358 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 359 fc_unsol_buf_t *buf, uint32_t claimed); 360 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 361 fc_unsol_buf_t *buf, uint32_t claimed); 362 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 363 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 364 uint32_t dev_cnt, uint32_t port_sid); 365 366 /* 367 * Functions registered with SCSA framework 368 */ 369 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 370 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 371 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 372 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 373 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 374 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 375 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 376 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 377 static int fcp_scsi_reset(struct scsi_address *ap, int level); 378 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 379 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 380 int whom); 381 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 382 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 383 void (*callback)(caddr_t), caddr_t arg); 384 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 385 char *name, ddi_eventcookie_t *event_cookiep); 386 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 387 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 388 ddi_callback_id_t *cb_id); 389 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 390 ddi_callback_id_t cb_id); 391 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 392 ddi_eventcookie_t eventid, void *impldata); 393 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 394 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 395 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 396 ddi_bus_config_op_t op, void *arg); 397 398 /* 399 * Internal functions 400 */ 401 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 402 int mode, int *rval); 403 404 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 405 int mode, int *rval); 406 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 407 struct fcp_scsi_cmd *fscsi, int mode); 408 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 409 caddr_t base_addr, int mode); 410 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 411 412 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 413 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 414 int *fc_pkt_reason, int *fc_pkt_action); 415 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 416 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 417 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 418 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 419 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 420 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 421 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 422 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 423 424 static void fcp_handle_devices(struct fcp_port *pptr, 425 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 426 fcp_map_tag_t *map_tag, int cause); 427 static int fcp_handle_mapflags(struct fcp_port *pptr, 428 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 429 int tgt_cnt, 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 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 extern struct mod_ops mod_driverops; 628 /* 629 * This variable is defined in modctl.c and set to '1' after the root driver 630 * and fs are loaded. It serves as an indication that the root filesystem can 631 * be used. 632 */ 633 extern int modrootloaded; 634 /* 635 * This table contains strings associated with the SCSI sense key codes. It 636 * is used by FCP to print a clear explanation of the code returned in the 637 * sense information by a device. 638 */ 639 extern char *sense_keys[]; 640 /* 641 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 642 * under this device that the paths to a physical device are created when 643 * MPxIO is used. 644 */ 645 extern dev_info_t *scsi_vhci_dip; 646 647 /* 648 * Report lun processing 649 */ 650 #define FCP_LUN_ADDRESSING 0x80 651 #define FCP_PD_ADDRESSING 0x00 652 #define FCP_VOLUME_ADDRESSING 0x40 653 654 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 655 #define MAX_INT_DMA 0x7fffffff 656 #define FCP_MAX_SENSE_LEN 252 657 #define FCP_MAX_RESPONSE_LEN 0xffffff 658 /* 659 * Property definitions 660 */ 661 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 662 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 663 #define TARGET_PROP (char *)fcp_target_prop 664 #define LUN_PROP (char *)fcp_lun_prop 665 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 666 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 667 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 668 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 669 #define INIT_PORT_PROP (char *)fcp_init_port_prop 670 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 671 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 672 /* 673 * Short hand macros. 674 */ 675 #define LUN_PORT (plun->lun_tgt->tgt_port) 676 #define LUN_TGT (plun->lun_tgt) 677 678 /* 679 * Driver private macros 680 */ 681 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') :\ 682 ((x) >= 'a' && (x) <= 'f') ?\ 683 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 684 685 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 686 687 #define FCP_N_NDI_EVENTS \ 688 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 689 690 #define FCP_LINK_STATE_CHANGED(p, c)\ 691 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 692 693 #define FCP_TGT_STATE_CHANGED(t, c)\ 694 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 695 696 #define FCP_STATE_CHANGED(p, t, c)\ 697 (FCP_TGT_STATE_CHANGED(t, c)) 698 699 #define FCP_MUST_RETRY(fpkt)\ 700 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY ||\ 701 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT ||\ 702 (fpkt)->pkt_state == FC_PKT_TRAN_BSY ||\ 703 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS ||\ 704 (fpkt)->pkt_state == FC_PKT_NPORT_BSY ||\ 705 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY ||\ 706 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE ||\ 707 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 708 709 #define FCP_SENSE_REPORTLUN_CHANGED(es)\ 710 ((es)->es_key == KEY_UNIT_ATTENTION &&\ 711 (es)->es_add_code == 0x3f &&\ 712 (es)->es_qual_code == 0x0e) 713 714 #define FCP_SENSE_NO_LUN(es)\ 715 ((es)->es_key == KEY_ILLEGAL_REQUEST &&\ 716 (es)->es_add_code == 0x25 &&\ 717 (es)->es_qual_code == 0x0) 718 719 #define FCP_VERSION "1.185" 720 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 721 722 #define FCP_NUM_ELEMENTS(array)\ 723 (sizeof (array) / sizeof ((array)[0])) 724 725 /* 726 * Debugging, Error reporting, and tracing 727 */ 728 #define FCP_LOG_SIZE 1024 * 1024 729 730 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 731 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 732 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 733 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 734 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 735 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 736 #define FCP_LEVEL_7 0x00040 737 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 738 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 739 740 741 742 /* 743 * Log contents to system messages file 744 */ 745 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 746 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 747 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 748 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 749 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 750 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 751 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 752 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 753 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 754 755 756 /* 757 * Log contents to trace buffer 758 */ 759 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 760 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 761 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 762 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 763 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 764 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 765 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 766 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 767 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 768 769 770 /* 771 * Log contents to both system messages file and trace buffer 772 */ 773 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF |\ 774 FC_TRACE_LOG_MSG) 775 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF |\ 776 FC_TRACE_LOG_MSG) 777 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF |\ 778 FC_TRACE_LOG_MSG) 779 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF |\ 780 FC_TRACE_LOG_MSG) 781 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF |\ 782 FC_TRACE_LOG_MSG) 783 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF |\ 784 FC_TRACE_LOG_MSG) 785 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF |\ 786 FC_TRACE_LOG_MSG) 787 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF |\ 788 FC_TRACE_LOG_MSG) 789 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF |\ 790 FC_TRACE_LOG_MSG) 791 #ifdef DEBUG 792 #define FCP_DTRACE fc_trace_debug 793 #else 794 #define FCP_DTRACE 795 #endif 796 797 #define FCP_TRACE fc_trace_debug 798 799 static struct cb_ops fcp_cb_ops = { 800 fcp_open, /* open */ 801 fcp_close, /* close */ 802 nodev, /* strategy */ 803 nodev, /* print */ 804 nodev, /* dump */ 805 nodev, /* read */ 806 nodev, /* write */ 807 fcp_ioctl, /* ioctl */ 808 nodev, /* devmap */ 809 nodev, /* mmap */ 810 nodev, /* segmap */ 811 nochpoll, /* chpoll */ 812 ddi_prop_op, /* cb_prop_op */ 813 0, /* streamtab */ 814 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 815 CB_REV, /* rev */ 816 nodev, /* aread */ 817 nodev /* awrite */ 818 }; 819 820 821 static struct dev_ops fcp_ops = { 822 DEVO_REV, 823 0, 824 ddi_getinfo_1to1, 825 nulldev, /* identify */ 826 nulldev, /* probe */ 827 fcp_attach, /* attach and detach are mandatory */ 828 fcp_detach, 829 nodev, /* reset */ 830 &fcp_cb_ops, /* cb_ops */ 831 NULL, /* bus_ops */ 832 NULL, /* power */ 833 }; 834 835 836 char *fcp_version = FCP_NAME_VERSION; 837 838 static struct modldrv modldrv = { 839 &mod_driverops, 840 FCP_NAME_VERSION, 841 &fcp_ops 842 }; 843 844 845 static struct modlinkage modlinkage = { 846 MODREV_1, 847 &modldrv, 848 NULL 849 }; 850 851 852 static fc_ulp_modinfo_t fcp_modinfo = { 853 &fcp_modinfo, /* ulp_handle */ 854 FCTL_ULP_MODREV_4, /* ulp_rev */ 855 FC4_SCSI_FCP, /* ulp_type */ 856 "fcp", /* ulp_name */ 857 FCP_STATEC_MASK, /* ulp_statec_mask */ 858 fcp_port_attach, /* ulp_port_attach */ 859 fcp_port_detach, /* ulp_port_detach */ 860 fcp_port_ioctl, /* ulp_port_ioctl */ 861 fcp_els_callback, /* ulp_els_callback */ 862 fcp_data_callback, /* ulp_data_callback */ 863 fcp_statec_callback /* ulp_statec_callback */ 864 }; 865 866 #ifdef DEBUG 867 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |\ 868 FCP_LEVEL_2 | FCP_LEVEL_3 |\ 869 FCP_LEVEL_4 | FCP_LEVEL_5 |\ 870 FCP_LEVEL_6 | FCP_LEVEL_7) 871 #else 872 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 |\ 873 FCP_LEVEL_2 | FCP_LEVEL_3 |\ 874 FCP_LEVEL_4 | FCP_LEVEL_5 |\ 875 FCP_LEVEL_6 | FCP_LEVEL_7) 876 #endif 877 878 /* FCP global variables */ 879 int fcp_bus_config_debug = 0; 880 static int fcp_log_size = FCP_LOG_SIZE; 881 static int fcp_trace = FCP_TRACE_DEFAULT; 882 static fc_trace_logq_t *fcp_logq = NULL; 883 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 884 /* 885 * The auto-configuration is set by default. The only way of disabling it is 886 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 887 */ 888 static int fcp_enable_auto_configuration = 1; 889 static int fcp_max_bus_config_retries = 4; 890 static int fcp_lun_ready_retry = 300; 891 /* 892 * The value assigned to the following variable has changed several times due 893 * to a problem with the data underruns reporting of some firmware(s). The 894 * current value of 50 gives a timeout value of 25 seconds for a max number 895 * of 256 LUNs. 896 */ 897 static int fcp_max_target_retries = 50; 898 /* 899 * Watchdog variables 900 * ------------------ 901 * 902 * fcp_watchdog_init 903 * 904 * Indicates if the watchdog timer is running or not. This is actually 905 * a counter of the number of Fibre Channel ports that attached. When 906 * the first port attaches the watchdog is started. When the last port 907 * detaches the watchdog timer is stopped. 908 * 909 * fcp_watchdog_time 910 * 911 * This is the watchdog clock counter. It is incremented by 912 * fcp_watchdog_time each time the watchdog timer expires. 913 * 914 * fcp_watchdog_timeout 915 * 916 * Increment value of the variable fcp_watchdog_time as well as the 917 * the timeout value of the watchdog timer. The unit is 1 second. It 918 * is strange that this is not a #define but a variable since the code 919 * never changes this value. The reason why it can be said that the 920 * unit is 1 second is because the number of ticks for the watchdog 921 * timer is determined like this: 922 * 923 * fcp_watchdog_tick = fcp_watchdog_timeout * 924 * drv_usectohz(1000000); 925 * 926 * The value 1000000 is hard coded in the code. 927 * 928 * fcp_watchdog_tick 929 * 930 * Watchdog timer value in ticks. 931 */ 932 static int fcp_watchdog_init = 0; 933 static int fcp_watchdog_time = 0; 934 static int fcp_watchdog_timeout = 1; 935 static int fcp_watchdog_tick; 936 937 /* 938 * fcp_offline_delay is a global variable to enable customisation of 939 * the timeout on link offlines or RSCNs. The default value is set 940 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 941 * specified in FCP4 Chapter 11 (see www.t10.org). 942 * 943 * The variable fcp_offline_delay is specified in SECONDS. 944 * 945 * If we made this a static var then the user would not be able to 946 * change it. This variable is set in fcp_attach(). 947 */ 948 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 949 950 static void *fcp_softstate = NULL; /* for soft state */ 951 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 952 static kmutex_t fcp_global_mutex; 953 static kmutex_t fcp_ioctl_mutex; 954 static dev_info_t *fcp_global_dip = NULL; 955 static timeout_id_t fcp_watchdog_id; 956 const char *fcp_lun_prop = "lun"; 957 const char *fcp_sam_lun_prop = "sam-lun"; 958 const char *fcp_target_prop = "target"; 959 /* 960 * NOTE: consumers of "node-wwn" property include stmsboot in ON 961 * consolidation. 962 */ 963 const char *fcp_node_wwn_prop = "node-wwn"; 964 const char *fcp_port_wwn_prop = "port-wwn"; 965 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 966 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 967 const char *fcp_manual_config_only = "manual_configuration_only"; 968 const char *fcp_init_port_prop = "initiator-port"; 969 const char *fcp_tgt_port_prop = "target-port"; 970 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 971 972 static struct fcp_port *fcp_port_head = NULL; 973 static ddi_eventcookie_t fcp_insert_eid; 974 static ddi_eventcookie_t fcp_remove_eid; 975 976 static ndi_event_definition_t fcp_ndi_event_defs[] = { 977 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 978 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 979 }; 980 981 /* 982 * List of valid commands for the scsi_ioctl call 983 */ 984 static uint8_t scsi_ioctl_list[] = { 985 SCMD_INQUIRY, 986 SCMD_REPORT_LUN, 987 SCMD_READ_CAPACITY 988 }; 989 990 /* 991 * this is used to dummy up a report lun response for cases 992 * where the target doesn't support it 993 */ 994 static uchar_t fcp_dummy_lun[] = { 995 0x00, /* MSB length (length = no of luns * 8) */ 996 0x00, 997 0x00, 998 0x08, /* LSB length */ 999 0x00, /* MSB reserved */ 1000 0x00, 1001 0x00, 1002 0x00, /* LSB reserved */ 1003 FCP_PD_ADDRESSING, 1004 0x00, /* LUN is ZERO at the first level */ 1005 0x00, 1006 0x00, /* second level is zero */ 1007 0x00, 1008 0x00, /* third level is zero */ 1009 0x00, 1010 0x00 /* fourth level is zero */ 1011 }; 1012 1013 static uchar_t fcp_alpa_to_switch[] = { 1014 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1016 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1017 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1018 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1019 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1020 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1021 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1022 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1023 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1024 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1025 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1026 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1027 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1028 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1029 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1030 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1031 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1032 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1034 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1035 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1036 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1037 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1038 }; 1039 1040 static caddr_t pid = "SESS01 "; 1041 1042 #if !defined(lint) 1043 1044 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1045 fcp_port::fcp_next fcp_watchdog_id)) 1046 1047 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1048 1049 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1050 fcp_insert_eid 1051 fcp_remove_eid 1052 fcp_watchdog_time)) 1053 1054 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1055 fcp_cb_ops 1056 fcp_ops 1057 callb_cpr)) 1058 1059 #endif /* lint */ 1060 1061 /* 1062 * This table is used to determine whether or not it's safe to copy in 1063 * the target node name for a lun. Since all luns behind the same target 1064 * have the same wwnn, only tagets that do not support multiple luns are 1065 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1066 */ 1067 1068 char *fcp_symmetric_disk_table[] = { 1069 "SEAGATE ST", 1070 "IBM DDYFT", 1071 "SUNW SUNWGS", /* Daktari enclosure */ 1072 "SUN SENA", /* SES device */ 1073 "SUN SESS01" /* VICOM SVE box */ 1074 }; 1075 1076 int fcp_symmetric_disk_table_size = 1077 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1078 1079 /* 1080 * The _init(9e) return value should be that of mod_install(9f). Under 1081 * some circumstances, a failure may not be related mod_install(9f) and 1082 * one would then require a return value to indicate the failure. Looking 1083 * at mod_install(9f), it is expected to return 0 for success and non-zero 1084 * for failure. mod_install(9f) for device drivers, further goes down the 1085 * calling chain and ends up in ddi_installdrv(), whose return values are 1086 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1087 * calling chain of mod_install(9f) which return values like EINVAL and 1088 * in some even return -1. 1089 * 1090 * To work around the vagaries of the mod_install() calling chain, return 1091 * either 0 or ENODEV depending on the success or failure of mod_install() 1092 */ 1093 int 1094 _init(void) 1095 { 1096 int rval; 1097 1098 /* 1099 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1100 * before registering with the transport first. 1101 */ 1102 if (ddi_soft_state_init(&fcp_softstate, 1103 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1104 return (EINVAL); 1105 } 1106 1107 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1108 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1109 1110 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1111 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1112 mutex_destroy(&fcp_global_mutex); 1113 mutex_destroy(&fcp_ioctl_mutex); 1114 ddi_soft_state_fini(&fcp_softstate); 1115 return (ENODEV); 1116 } 1117 1118 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1119 1120 if ((rval = mod_install(&modlinkage)) != 0) { 1121 fc_trace_free_logq(fcp_logq); 1122 (void) fc_ulp_remove(&fcp_modinfo); 1123 mutex_destroy(&fcp_global_mutex); 1124 mutex_destroy(&fcp_ioctl_mutex); 1125 ddi_soft_state_fini(&fcp_softstate); 1126 rval = ENODEV; 1127 } 1128 1129 return (rval); 1130 } 1131 1132 1133 /* 1134 * the system is done with us as a driver, so clean up 1135 */ 1136 int 1137 _fini(void) 1138 { 1139 int rval; 1140 1141 /* 1142 * don't start cleaning up until we know that the module remove 1143 * has worked -- if this works, then we know that each instance 1144 * has successfully been DDI_DETACHed 1145 */ 1146 if ((rval = mod_remove(&modlinkage)) != 0) { 1147 return (rval); 1148 } 1149 1150 (void) fc_ulp_remove(&fcp_modinfo); 1151 1152 ddi_soft_state_fini(&fcp_softstate); 1153 mutex_destroy(&fcp_global_mutex); 1154 mutex_destroy(&fcp_ioctl_mutex); 1155 fc_trace_free_logq(fcp_logq); 1156 1157 return (rval); 1158 } 1159 1160 1161 int 1162 _info(struct modinfo *modinfop) 1163 { 1164 return (mod_info(&modlinkage, modinfop)); 1165 } 1166 1167 1168 /* 1169 * attach the module 1170 */ 1171 static int 1172 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1173 { 1174 int rval = DDI_SUCCESS; 1175 1176 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1177 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1178 1179 if (cmd == DDI_ATTACH) { 1180 /* The FCP pseudo device is created here. */ 1181 mutex_enter(&fcp_global_mutex); 1182 fcp_global_dip = devi; 1183 mutex_exit(&fcp_global_mutex); 1184 1185 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1186 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1187 ddi_report_dev(fcp_global_dip); 1188 } else { 1189 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1190 mutex_enter(&fcp_global_mutex); 1191 fcp_global_dip = NULL; 1192 mutex_exit(&fcp_global_mutex); 1193 1194 rval = DDI_FAILURE; 1195 } 1196 /* 1197 * We check the fcp_offline_delay property at this 1198 * point. This variable is global for the driver, 1199 * not specific to an instance. 1200 * 1201 * We do not recommend setting the value to less 1202 * than 10 seconds (RA_TOV_els), or greater than 1203 * 60 seconds. 1204 */ 1205 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1206 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1207 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1208 if ((fcp_offline_delay < 10) || 1209 (fcp_offline_delay > 60)) { 1210 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1211 "to %d second(s). This is outside the " 1212 "recommended range of 10..60 seconds.", 1213 fcp_offline_delay); 1214 } 1215 } 1216 1217 return (rval); 1218 } 1219 1220 1221 /*ARGSUSED*/ 1222 static int 1223 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1224 { 1225 int res = DDI_SUCCESS; 1226 1227 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1228 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1229 1230 if (cmd == DDI_DETACH) { 1231 /* 1232 * Check if there are active ports/threads. If there 1233 * are any, we will fail, else we will succeed (there 1234 * should not be much to clean up) 1235 */ 1236 mutex_enter(&fcp_global_mutex); 1237 FCP_DTRACE(fcp_logq, "fcp", 1238 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1239 (void *) fcp_port_head); 1240 1241 if (fcp_port_head == NULL) { 1242 ddi_remove_minor_node(fcp_global_dip, NULL); 1243 fcp_global_dip = NULL; 1244 mutex_exit(&fcp_global_mutex); 1245 } else { 1246 mutex_exit(&fcp_global_mutex); 1247 res = DDI_FAILURE; 1248 } 1249 } 1250 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1251 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1252 1253 return (res); 1254 } 1255 1256 1257 /* ARGSUSED */ 1258 static int 1259 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1260 { 1261 if (otype != OTYP_CHR) { 1262 return (EINVAL); 1263 } 1264 1265 /* 1266 * Allow only root to talk; 1267 */ 1268 if (drv_priv(credp)) { 1269 return (EPERM); 1270 } 1271 1272 mutex_enter(&fcp_global_mutex); 1273 if (fcp_oflag & FCP_EXCL) { 1274 mutex_exit(&fcp_global_mutex); 1275 return (EBUSY); 1276 } 1277 1278 if (flag & FEXCL) { 1279 if (fcp_oflag & FCP_OPEN) { 1280 mutex_exit(&fcp_global_mutex); 1281 return (EBUSY); 1282 } 1283 fcp_oflag |= FCP_EXCL; 1284 } 1285 fcp_oflag |= FCP_OPEN; 1286 mutex_exit(&fcp_global_mutex); 1287 1288 return (0); 1289 } 1290 1291 1292 /* ARGSUSED */ 1293 static int 1294 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1295 { 1296 if (otype != OTYP_CHR) { 1297 return (EINVAL); 1298 } 1299 1300 mutex_enter(&fcp_global_mutex); 1301 if (!(fcp_oflag & FCP_OPEN)) { 1302 mutex_exit(&fcp_global_mutex); 1303 return (ENODEV); 1304 } 1305 fcp_oflag = FCP_IDLE; 1306 mutex_exit(&fcp_global_mutex); 1307 1308 return (0); 1309 } 1310 1311 1312 /* 1313 * fcp_ioctl 1314 * Entry point for the FCP ioctls 1315 * 1316 * Input: 1317 * See ioctl(9E) 1318 * 1319 * Output: 1320 * See ioctl(9E) 1321 * 1322 * Returns: 1323 * See ioctl(9E) 1324 * 1325 * Context: 1326 * Kernel context. 1327 */ 1328 /* ARGSUSED */ 1329 static int 1330 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1331 int *rval) 1332 { 1333 int ret = 0; 1334 1335 mutex_enter(&fcp_global_mutex); 1336 if (!(fcp_oflag & FCP_OPEN)) { 1337 mutex_exit(&fcp_global_mutex); 1338 return (ENXIO); 1339 } 1340 mutex_exit(&fcp_global_mutex); 1341 1342 switch (cmd) { 1343 case FCP_TGT_INQUIRY: 1344 case FCP_TGT_CREATE: 1345 case FCP_TGT_DELETE: 1346 ret = fcp_setup_device_data_ioctl(cmd, 1347 (struct fcp_ioctl *)data, mode, rval); 1348 break; 1349 1350 case FCP_TGT_SEND_SCSI: 1351 mutex_enter(&fcp_ioctl_mutex); 1352 ret = fcp_setup_scsi_ioctl( 1353 (struct fcp_scsi_cmd *)data, mode, rval); 1354 mutex_exit(&fcp_ioctl_mutex); 1355 break; 1356 1357 case FCP_STATE_COUNT: 1358 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1359 mode, rval); 1360 break; 1361 case FCP_GET_TARGET_MAPPINGS: 1362 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1363 mode, rval); 1364 break; 1365 default: 1366 fcp_log(CE_WARN, NULL, 1367 "!Invalid ioctl opcode = 0x%x", cmd); 1368 ret = EINVAL; 1369 } 1370 1371 return (ret); 1372 } 1373 1374 1375 /* 1376 * fcp_setup_device_data_ioctl 1377 * Setup handler for the "device data" style of 1378 * ioctl for FCP. See "fcp_util.h" for data structure 1379 * definition. 1380 * 1381 * Input: 1382 * cmd = FCP ioctl command 1383 * data = ioctl data 1384 * mode = See ioctl(9E) 1385 * 1386 * Output: 1387 * data = ioctl data 1388 * rval = return value - see ioctl(9E) 1389 * 1390 * Returns: 1391 * See ioctl(9E) 1392 * 1393 * Context: 1394 * Kernel context. 1395 */ 1396 /* ARGSUSED */ 1397 static int 1398 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1399 int *rval) 1400 { 1401 struct fcp_port *pptr; 1402 struct device_data *dev_data; 1403 uint32_t link_cnt; 1404 la_wwn_t *wwn_ptr = NULL; 1405 struct fcp_tgt *ptgt = NULL; 1406 struct fcp_lun *plun = NULL; 1407 int i, error; 1408 struct fcp_ioctl fioctl; 1409 1410 #ifdef _MULTI_DATAMODEL 1411 switch (ddi_model_convert_from(mode & FMODELS)) { 1412 case DDI_MODEL_ILP32: { 1413 struct fcp32_ioctl f32_ioctl; 1414 1415 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1416 sizeof (struct fcp32_ioctl), mode)) { 1417 return (EFAULT); 1418 } 1419 fioctl.fp_minor = f32_ioctl.fp_minor; 1420 fioctl.listlen = f32_ioctl.listlen; 1421 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1422 break; 1423 } 1424 case DDI_MODEL_NONE: 1425 if (ddi_copyin((void *)data, (void *)&fioctl, 1426 sizeof (struct fcp_ioctl), mode)) { 1427 return (EFAULT); 1428 } 1429 break; 1430 } 1431 1432 #else /* _MULTI_DATAMODEL */ 1433 if (ddi_copyin((void *)data, (void *)&fioctl, 1434 sizeof (struct fcp_ioctl), mode)) { 1435 return (EFAULT); 1436 } 1437 #endif /* _MULTI_DATAMODEL */ 1438 1439 /* 1440 * Right now we can assume that the minor number matches with 1441 * this instance of fp. If this changes we will need to 1442 * revisit this logic. 1443 */ 1444 mutex_enter(&fcp_global_mutex); 1445 pptr = fcp_port_head; 1446 while (pptr) { 1447 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) 1448 break; 1449 else 1450 pptr = pptr->port_next; 1451 } 1452 mutex_exit(&fcp_global_mutex); 1453 if (pptr == NULL) { 1454 return (ENXIO); 1455 } 1456 mutex_enter(&pptr->port_mutex); 1457 1458 1459 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1460 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1461 mutex_exit(&pptr->port_mutex); 1462 return (ENOMEM); 1463 } 1464 1465 if (ddi_copyin(fioctl.list, dev_data, 1466 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1467 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1468 mutex_exit(&pptr->port_mutex); 1469 return (EFAULT); 1470 } 1471 link_cnt = pptr->port_link_cnt; 1472 1473 if (cmd == FCP_TGT_INQUIRY) { 1474 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1475 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1476 sizeof (wwn_ptr->raw_wwn)) == 0) { 1477 /* This ioctl is requesting INQ info of local HBA */ 1478 mutex_exit(&pptr->port_mutex); 1479 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1480 dev_data[0].dev_status = 0; 1481 if (ddi_copyout(dev_data, fioctl.list, 1482 (sizeof (struct device_data)) * fioctl.listlen, 1483 mode)) { 1484 kmem_free(dev_data, 1485 sizeof (*dev_data) * fioctl.listlen); 1486 return (EFAULT); 1487 } 1488 kmem_free(dev_data, 1489 sizeof (*dev_data) * fioctl.listlen); 1490 #ifdef _MULTI_DATAMODEL 1491 switch (ddi_model_convert_from(mode & FMODELS)) { 1492 case DDI_MODEL_ILP32: { 1493 struct fcp32_ioctl f32_ioctl; 1494 f32_ioctl.fp_minor = fioctl.fp_minor; 1495 f32_ioctl.listlen = fioctl.listlen; 1496 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1497 if (ddi_copyout((void *)&f32_ioctl, 1498 (void *)data, 1499 sizeof (struct fcp32_ioctl), mode)) { 1500 return (EFAULT); 1501 } 1502 break; 1503 } 1504 case DDI_MODEL_NONE: 1505 if (ddi_copyout((void *)&fioctl, (void *)data, 1506 sizeof (struct fcp_ioctl), mode)) { 1507 return (EFAULT); 1508 } 1509 break; 1510 } 1511 #else /* _MULTI_DATAMODEL */ 1512 if (ddi_copyout((void *)&fioctl, (void *)data, 1513 sizeof (struct fcp_ioctl), mode)) { 1514 return (EFAULT); 1515 } 1516 #endif /* _MULTI_DATAMODEL */ 1517 return (0); 1518 } 1519 } 1520 1521 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1522 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1523 mutex_exit(&pptr->port_mutex); 1524 return (ENXIO); 1525 } 1526 1527 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1528 i++) { 1529 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1530 1531 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1532 1533 1534 dev_data[i].dev_status = ENXIO; 1535 1536 if ((ptgt = fcp_lookup_target(pptr, 1537 (uchar_t *)wwn_ptr)) == NULL) { 1538 mutex_exit(&pptr->port_mutex); 1539 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1540 wwn_ptr, &error, 0) == NULL) { 1541 dev_data[i].dev_status = ENODEV; 1542 mutex_enter(&pptr->port_mutex); 1543 continue; 1544 } else { 1545 1546 dev_data[i].dev_status = EAGAIN; 1547 1548 mutex_enter(&pptr->port_mutex); 1549 continue; 1550 } 1551 } else { 1552 mutex_enter(&ptgt->tgt_mutex); 1553 if (ptgt->tgt_state & (FCP_TGT_MARK | 1554 FCP_TGT_BUSY)) { 1555 dev_data[i].dev_status = EAGAIN; 1556 mutex_exit(&ptgt->tgt_mutex); 1557 continue; 1558 } 1559 1560 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1561 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1562 dev_data[i].dev_status = ENOTSUP; 1563 } else { 1564 dev_data[i].dev_status = ENXIO; 1565 } 1566 mutex_exit(&ptgt->tgt_mutex); 1567 continue; 1568 } 1569 1570 switch (cmd) { 1571 case FCP_TGT_INQUIRY: 1572 /* 1573 * The reason we give device type of 1574 * lun 0 only even though in some 1575 * cases(like maxstrat) lun 0 device 1576 * type may be 0x3f(invalid) is that 1577 * for bridge boxes target will appear 1578 * as luns and the first lun could be 1579 * a device that utility may not care 1580 * about (like a tape device). 1581 */ 1582 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1583 dev_data[i].dev_status = 0; 1584 mutex_exit(&ptgt->tgt_mutex); 1585 1586 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1587 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1588 } else { 1589 dev_data[i].dev0_type = plun->lun_type; 1590 } 1591 mutex_enter(&ptgt->tgt_mutex); 1592 break; 1593 1594 case FCP_TGT_CREATE: 1595 mutex_exit(&ptgt->tgt_mutex); 1596 mutex_exit(&pptr->port_mutex); 1597 1598 /* 1599 * serialize state change call backs. 1600 * only one call back will be handled 1601 * at a time. 1602 */ 1603 mutex_enter(&fcp_global_mutex); 1604 if (fcp_oflag & FCP_BUSY) { 1605 mutex_exit(&fcp_global_mutex); 1606 if (dev_data) { 1607 kmem_free(dev_data, 1608 sizeof (*dev_data) * 1609 fioctl.listlen); 1610 } 1611 return (EBUSY); 1612 } 1613 fcp_oflag |= FCP_BUSY; 1614 mutex_exit(&fcp_global_mutex); 1615 1616 dev_data[i].dev_status = 1617 fcp_create_on_demand(pptr, 1618 wwn_ptr->raw_wwn); 1619 1620 if (dev_data[i].dev_status != 0) { 1621 char buf[25]; 1622 1623 for (i = 0; i < FC_WWN_SIZE; i++) { 1624 (void) sprintf(&buf[i << 1], 1625 "%02x", 1626 wwn_ptr->raw_wwn[i]); 1627 } 1628 1629 fcp_log(CE_WARN, pptr->port_dip, 1630 "!Failed to create nodes for" 1631 " pwwn=%s; error=%x", buf, 1632 dev_data[i].dev_status); 1633 } 1634 1635 /* allow state change call backs again */ 1636 mutex_enter(&fcp_global_mutex); 1637 fcp_oflag &= ~FCP_BUSY; 1638 mutex_exit(&fcp_global_mutex); 1639 1640 mutex_enter(&pptr->port_mutex); 1641 mutex_enter(&ptgt->tgt_mutex); 1642 1643 break; 1644 1645 case FCP_TGT_DELETE: 1646 break; 1647 1648 default: 1649 fcp_log(CE_WARN, pptr->port_dip, 1650 "!Invalid device data ioctl " 1651 "opcode = 0x%x", cmd); 1652 } 1653 mutex_exit(&ptgt->tgt_mutex); 1654 } 1655 } 1656 mutex_exit(&pptr->port_mutex); 1657 1658 if (ddi_copyout(dev_data, fioctl.list, 1659 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1660 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1661 return (EFAULT); 1662 } 1663 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1664 1665 #ifdef _MULTI_DATAMODEL 1666 switch (ddi_model_convert_from(mode & FMODELS)) { 1667 case DDI_MODEL_ILP32: { 1668 struct fcp32_ioctl f32_ioctl; 1669 1670 f32_ioctl.fp_minor = fioctl.fp_minor; 1671 f32_ioctl.listlen = fioctl.listlen; 1672 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1673 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1674 sizeof (struct fcp32_ioctl), mode)) { 1675 return (EFAULT); 1676 } 1677 break; 1678 } 1679 case DDI_MODEL_NONE: 1680 if (ddi_copyout((void *)&fioctl, (void *)data, 1681 sizeof (struct fcp_ioctl), mode)) { 1682 return (EFAULT); 1683 } 1684 break; 1685 } 1686 #else /* _MULTI_DATAMODEL */ 1687 1688 if (ddi_copyout((void *)&fioctl, (void *)data, 1689 sizeof (struct fcp_ioctl), mode)) { 1690 return (EFAULT); 1691 } 1692 #endif /* _MULTI_DATAMODEL */ 1693 1694 return (0); 1695 } 1696 1697 /* 1698 * Fetch the target mappings (path, etc.) for all LUNs 1699 * on this port. 1700 */ 1701 /* ARGSUSED */ 1702 static int 1703 fcp_get_target_mappings(struct fcp_ioctl *data, 1704 int mode, int *rval) 1705 { 1706 struct fcp_port *pptr; 1707 fc_hba_target_mappings_t *mappings; 1708 fc_hba_mapping_entry_t *map; 1709 struct fcp_tgt *ptgt = NULL; 1710 struct fcp_lun *plun = NULL; 1711 int i, mapIndex, mappingSize; 1712 int listlen; 1713 struct fcp_ioctl fioctl; 1714 char *path; 1715 fcp_ent_addr_t sam_lun_addr; 1716 1717 #ifdef _MULTI_DATAMODEL 1718 switch (ddi_model_convert_from(mode & FMODELS)) { 1719 case DDI_MODEL_ILP32: { 1720 struct fcp32_ioctl f32_ioctl; 1721 1722 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1723 sizeof (struct fcp32_ioctl), mode)) { 1724 return (EFAULT); 1725 } 1726 fioctl.fp_minor = f32_ioctl.fp_minor; 1727 fioctl.listlen = f32_ioctl.listlen; 1728 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1729 break; 1730 } 1731 case DDI_MODEL_NONE: 1732 if (ddi_copyin((void *)data, (void *)&fioctl, 1733 sizeof (struct fcp_ioctl), mode)) { 1734 return (EFAULT); 1735 } 1736 break; 1737 } 1738 1739 #else /* _MULTI_DATAMODEL */ 1740 if (ddi_copyin((void *)data, (void *)&fioctl, 1741 sizeof (struct fcp_ioctl), mode)) { 1742 return (EFAULT); 1743 } 1744 #endif /* _MULTI_DATAMODEL */ 1745 1746 /* 1747 * Right now we can assume that the minor number matches with 1748 * this instance of fp. If this changes we will need to 1749 * revisit this logic. 1750 */ 1751 mutex_enter(&fcp_global_mutex); 1752 pptr = fcp_port_head; 1753 while (pptr) { 1754 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) 1755 break; 1756 else 1757 pptr = pptr->port_next; 1758 } 1759 mutex_exit(&fcp_global_mutex); 1760 if (pptr == NULL) { 1761 cmn_err(CE_NOTE, "target mappings: unknown instance number : %d", 1762 fioctl.fp_minor); 1763 return (ENXIO); 1764 } 1765 1766 1767 /* We use listlen to show the total buffer size */ 1768 mappingSize = fioctl.listlen; 1769 1770 /* Now calculate how many mapping entries will fit */ 1771 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1772 - sizeof (fc_hba_target_mappings_t); 1773 if (listlen <= 0) { 1774 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1775 return (ENXIO); 1776 } 1777 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1778 1779 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1780 return (ENOMEM); 1781 } 1782 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1783 1784 /* Now get to work */ 1785 mapIndex = 0; 1786 1787 mutex_enter(&pptr->port_mutex); 1788 /* Loop through all targets on this port */ 1789 for (i = 0; i < FCP_NUM_HASH; i++) { 1790 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1791 ptgt = ptgt->tgt_next) { 1792 1793 1794 /* Loop through all LUNs on this target */ 1795 for (plun = ptgt->tgt_lun; plun != NULL; 1796 plun = plun->lun_next) { 1797 if (plun->lun_state & FCP_LUN_OFFLINE) { 1798 continue; 1799 } 1800 1801 path = fcp_get_lun_path(plun); 1802 if (path == NULL) { 1803 continue; 1804 } 1805 1806 if (mapIndex >= listlen) { 1807 mapIndex ++; 1808 kmem_free(path, MAXPATHLEN); 1809 continue; 1810 } 1811 map = &mappings->entries[mapIndex++]; 1812 bcopy(path, map->targetDriver, sizeof (map->targetDriver)); 1813 map->d_id = ptgt->tgt_d_id; 1814 map->busNumber = 0; 1815 map->targetNumber = ptgt->tgt_d_id; 1816 map->osLUN = plun->lun_num; 1817 1818 /* 1819 * We had swapped lun when we stored it in 1820 * lun_addr. We need to swap it back before 1821 * returning it to user land 1822 */ 1823 1824 sam_lun_addr.ent_addr_0 = BE_16(plun->lun_addr.ent_addr_0); 1825 sam_lun_addr.ent_addr_1 = BE_16(plun->lun_addr.ent_addr_1); 1826 sam_lun_addr.ent_addr_2 = BE_16(plun->lun_addr.ent_addr_2); 1827 sam_lun_addr.ent_addr_3 = BE_16(plun->lun_addr.ent_addr_3); 1828 1829 bcopy(&sam_lun_addr, &map->samLUN, FCP_LUN_SIZE); 1830 1831 bcopy(ptgt->tgt_node_wwn.raw_wwn, map->NodeWWN.raw_wwn, 1832 sizeof (la_wwn_t)); 1833 bcopy(ptgt->tgt_port_wwn.raw_wwn, map->PortWWN.raw_wwn, 1834 sizeof (la_wwn_t)); 1835 1836 if (plun->lun_guid) { 1837 1838 /* convert ascii wwn to bytes */ 1839 fcp_ascii_to_wwn(plun->lun_guid, map->guid, 1840 sizeof (map->guid)); 1841 1842 if ((sizeof (map->guid)) < plun->lun_guid_size/2) { 1843 cmn_err(CE_WARN, "fcp_get_target_mappings:" 1844 "guid copy space insufficient." 1845 "Copy Truncation - " 1846 "available %d; need %d", 1847 (int)sizeof (map->guid), 1848 (int)plun->lun_guid_size/2); 1849 } 1850 } 1851 kmem_free(path, MAXPATHLEN); 1852 } 1853 } 1854 } 1855 mutex_exit(&pptr->port_mutex); 1856 mappings->numLuns = mapIndex; 1857 1858 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1859 kmem_free(mappings, mappingSize); 1860 return (EFAULT); 1861 } 1862 kmem_free(mappings, mappingSize); 1863 1864 #ifdef _MULTI_DATAMODEL 1865 switch (ddi_model_convert_from(mode & FMODELS)) { 1866 case DDI_MODEL_ILP32: { 1867 struct fcp32_ioctl f32_ioctl; 1868 1869 f32_ioctl.fp_minor = fioctl.fp_minor; 1870 f32_ioctl.listlen = fioctl.listlen; 1871 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1872 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1873 sizeof (struct fcp32_ioctl), mode)) { 1874 return (EFAULT); 1875 } 1876 break; 1877 } 1878 case DDI_MODEL_NONE: 1879 if (ddi_copyout((void *)&fioctl, (void *)data, 1880 sizeof (struct fcp_ioctl), mode)) { 1881 return (EFAULT); 1882 } 1883 break; 1884 } 1885 #else /* _MULTI_DATAMODEL */ 1886 1887 if (ddi_copyout((void *)&fioctl, (void *)data, 1888 sizeof (struct fcp_ioctl), mode)) { 1889 return (EFAULT); 1890 } 1891 #endif /* _MULTI_DATAMODEL */ 1892 1893 return (0); 1894 } 1895 1896 /* 1897 * fcp_setup_scsi_ioctl 1898 * Setup handler for the "scsi passthru" style of 1899 * ioctl for FCP. See "fcp_util.h" for data structure 1900 * definition. 1901 * 1902 * Input: 1903 * u_fscsi = ioctl data (user address space) 1904 * mode = See ioctl(9E) 1905 * 1906 * Output: 1907 * u_fscsi = ioctl data (user address space) 1908 * rval = return value - see ioctl(9E) 1909 * 1910 * Returns: 1911 * 0 = OK 1912 * EAGAIN = See errno.h 1913 * EBUSY = See errno.h 1914 * EFAULT = See errno.h 1915 * EINTR = See errno.h 1916 * EINVAL = See errno.h 1917 * EIO = See errno.h 1918 * ENOMEM = See errno.h 1919 * ENXIO = See errno.h 1920 * 1921 * Context: 1922 * Kernel context. 1923 */ 1924 /* ARGSUSED */ 1925 static int 1926 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1927 int mode, int *rval) 1928 { 1929 int ret = 0; 1930 int temp_ret; 1931 caddr_t k_cdbbufaddr = NULL; 1932 caddr_t k_bufaddr = NULL; 1933 caddr_t k_rqbufaddr = NULL; 1934 caddr_t u_cdbbufaddr; 1935 caddr_t u_bufaddr; 1936 caddr_t u_rqbufaddr; 1937 struct fcp_scsi_cmd k_fscsi; 1938 1939 /* 1940 * Get fcp_scsi_cmd array element from user address space 1941 */ 1942 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1943 != 0) { 1944 return (ret); 1945 } 1946 1947 1948 /* 1949 * Even though kmem_alloc() checks the validity of the 1950 * buffer length, this check is needed when the 1951 * kmem_flags set and the zero buffer length is passed. 1952 */ 1953 if ((k_fscsi.scsi_cdblen <= 0) || 1954 (k_fscsi.scsi_buflen <= 0) || 1955 (k_fscsi.scsi_buflen > FCP_MAX_RESPONSE_LEN) || 1956 (k_fscsi.scsi_rqlen <= 0) || 1957 (k_fscsi.scsi_rqlen > FCP_MAX_SENSE_LEN)) { 1958 return (EINVAL); 1959 } 1960 1961 /* 1962 * Allocate data for fcp_scsi_cmd pointer fields 1963 */ 1964 if (ret == 0) { 1965 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 1966 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 1967 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 1968 1969 if (k_cdbbufaddr == NULL || 1970 k_bufaddr == NULL || 1971 k_rqbufaddr == NULL) { 1972 ret = ENOMEM; 1973 } 1974 } 1975 1976 /* 1977 * Get fcp_scsi_cmd pointer fields from user 1978 * address space 1979 */ 1980 if (ret == 0) { 1981 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 1982 u_bufaddr = k_fscsi.scsi_bufaddr; 1983 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 1984 1985 if (ddi_copyin(u_cdbbufaddr, 1986 k_cdbbufaddr, 1987 k_fscsi.scsi_cdblen, 1988 mode)) { 1989 ret = EFAULT; 1990 } else if (ddi_copyin(u_bufaddr, 1991 k_bufaddr, 1992 k_fscsi.scsi_buflen, 1993 mode)) { 1994 ret = EFAULT; 1995 } else if (ddi_copyin(u_rqbufaddr, 1996 k_rqbufaddr, 1997 k_fscsi.scsi_rqlen, 1998 mode)) { 1999 ret = EFAULT; 2000 } 2001 } 2002 2003 /* 2004 * Send scsi command (blocking) 2005 */ 2006 if (ret == 0) { 2007 /* 2008 * Prior to sending the scsi command, the 2009 * fcp_scsi_cmd data structure must contain kernel, 2010 * not user, addresses. 2011 */ 2012 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2013 k_fscsi.scsi_bufaddr = k_bufaddr; 2014 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2015 2016 ret = fcp_send_scsi_ioctl(&k_fscsi); 2017 2018 /* 2019 * After sending the scsi command, the 2020 * fcp_scsi_cmd data structure must contain user, 2021 * not kernel, addresses. 2022 */ 2023 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2024 k_fscsi.scsi_bufaddr = u_bufaddr; 2025 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2026 } 2027 2028 /* 2029 * Put fcp_scsi_cmd pointer fields to user address space 2030 */ 2031 if (ret == 0) { 2032 if (ddi_copyout(k_cdbbufaddr, 2033 u_cdbbufaddr, 2034 k_fscsi.scsi_cdblen, 2035 mode)) { 2036 ret = EFAULT; 2037 } else if (ddi_copyout(k_bufaddr, 2038 u_bufaddr, 2039 k_fscsi.scsi_buflen, 2040 mode)) { 2041 ret = EFAULT; 2042 } else if (ddi_copyout(k_rqbufaddr, 2043 u_rqbufaddr, 2044 k_fscsi.scsi_rqlen, 2045 mode)) { 2046 ret = EFAULT; 2047 } 2048 } 2049 2050 /* 2051 * Free data for fcp_scsi_cmd pointer fields 2052 */ 2053 if (k_cdbbufaddr != NULL) { 2054 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2055 } 2056 if (k_bufaddr != NULL) { 2057 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2058 } 2059 if (k_rqbufaddr != NULL) { 2060 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2061 } 2062 2063 /* 2064 * Put fcp_scsi_cmd array element to user address space 2065 */ 2066 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2067 if (temp_ret != 0) { 2068 ret = temp_ret; 2069 } 2070 2071 /* 2072 * Return status 2073 */ 2074 return (ret); 2075 } 2076 2077 2078 /* 2079 * fcp_copyin_scsi_cmd 2080 * Copy in fcp_scsi_cmd data structure from user address space. 2081 * The data may be in 32 bit or 64 bit modes. 2082 * 2083 * Input: 2084 * base_addr = from address (user address space) 2085 * mode = See ioctl(9E) and ddi_copyin(9F) 2086 * 2087 * Output: 2088 * fscsi = to address (kernel address space) 2089 * 2090 * Returns: 2091 * 0 = OK 2092 * EFAULT = Error 2093 * 2094 * Context: 2095 * Kernel context. 2096 */ 2097 static int 2098 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2099 { 2100 #ifdef _MULTI_DATAMODEL 2101 struct fcp32_scsi_cmd f32scsi; 2102 2103 switch (ddi_model_convert_from(mode & FMODELS)) { 2104 case DDI_MODEL_ILP32: 2105 /* 2106 * Copy data from user address space 2107 */ 2108 if (ddi_copyin((void *)base_addr, 2109 &f32scsi, 2110 sizeof (struct fcp32_scsi_cmd), 2111 mode)) { 2112 return (EFAULT); 2113 } 2114 /* 2115 * Convert from 32 bit to 64 bit 2116 */ 2117 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2118 break; 2119 case DDI_MODEL_NONE: 2120 /* 2121 * Copy data from user address space 2122 */ 2123 if (ddi_copyin((void *)base_addr, 2124 fscsi, 2125 sizeof (struct fcp_scsi_cmd), 2126 mode)) { 2127 return (EFAULT); 2128 } 2129 break; 2130 } 2131 #else /* _MULTI_DATAMODEL */ 2132 /* 2133 * Copy data from user address space 2134 */ 2135 if (ddi_copyin((void *)base_addr, 2136 fscsi, 2137 sizeof (struct fcp_scsi_cmd), 2138 mode)) { 2139 return (EFAULT); 2140 } 2141 #endif /* _MULTI_DATAMODEL */ 2142 2143 return (0); 2144 } 2145 2146 2147 /* 2148 * fcp_copyout_scsi_cmd 2149 * Copy out fcp_scsi_cmd data structure to user address space. 2150 * The data may be in 32 bit or 64 bit modes. 2151 * 2152 * Input: 2153 * fscsi = to address (kernel address space) 2154 * mode = See ioctl(9E) and ddi_copyin(9F) 2155 * 2156 * Output: 2157 * base_addr = from address (user address space) 2158 * 2159 * Returns: 2160 * 0 = OK 2161 * EFAULT = Error 2162 * 2163 * Context: 2164 * Kernel context. 2165 */ 2166 static int 2167 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2168 { 2169 #ifdef _MULTI_DATAMODEL 2170 struct fcp32_scsi_cmd f32scsi; 2171 2172 switch (ddi_model_convert_from(mode & FMODELS)) { 2173 case DDI_MODEL_ILP32: 2174 /* 2175 * Convert from 64 bit to 32 bit 2176 */ 2177 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2178 /* 2179 * Copy data to user address space 2180 */ 2181 if (ddi_copyout(&f32scsi, 2182 (void *)base_addr, 2183 sizeof (struct fcp32_scsi_cmd), 2184 mode)) { 2185 return (EFAULT); 2186 } 2187 break; 2188 case DDI_MODEL_NONE: 2189 /* 2190 * Copy data to user address space 2191 */ 2192 if (ddi_copyout(fscsi, 2193 (void *)base_addr, 2194 sizeof (struct fcp_scsi_cmd), 2195 mode)) { 2196 return (EFAULT); 2197 } 2198 break; 2199 } 2200 #else /* _MULTI_DATAMODEL */ 2201 /* 2202 * Copy data to user address space 2203 */ 2204 if (ddi_copyout(fscsi, 2205 (void *)base_addr, 2206 sizeof (struct fcp_scsi_cmd), 2207 mode)) { 2208 return (EFAULT); 2209 } 2210 #endif /* _MULTI_DATAMODEL */ 2211 2212 return (0); 2213 } 2214 2215 2216 /* 2217 * fcp_send_scsi_ioctl 2218 * Sends the SCSI command in blocking mode. 2219 * 2220 * Input: 2221 * fscsi = SCSI command data structure 2222 * 2223 * Output: 2224 * fscsi = SCSI command data structure 2225 * 2226 * Returns: 2227 * 0 = OK 2228 * EAGAIN = See errno.h 2229 * EBUSY = See errno.h 2230 * EINTR = See errno.h 2231 * EINVAL = See errno.h 2232 * EIO = See errno.h 2233 * ENOMEM = See errno.h 2234 * ENXIO = See errno.h 2235 * 2236 * Context: 2237 * Kernel context. 2238 */ 2239 static int 2240 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2241 { 2242 struct fcp_lun *plun = NULL; 2243 struct fcp_port *pptr = NULL; 2244 struct fcp_tgt *ptgt = NULL; 2245 fc_packet_t *fpkt = NULL; 2246 struct fcp_ipkt *icmd = NULL; 2247 int target_created = FALSE; 2248 fc_frame_hdr_t *hp; 2249 struct fcp_cmd fcp_cmd; 2250 struct fcp_cmd *fcmd; 2251 union scsi_cdb *scsi_cdb; 2252 la_wwn_t *wwn_ptr; 2253 int nodma; 2254 struct fcp_rsp *rsp; 2255 struct fcp_rsp_info *rsp_info; 2256 caddr_t rsp_sense; 2257 int buf_len; 2258 int info_len; 2259 int sense_len; 2260 struct scsi_extended_sense *sense_to = NULL; 2261 timeout_id_t tid; 2262 uint8_t reconfig_lun = FALSE; 2263 uint8_t reconfig_pending = FALSE; 2264 uint8_t scsi_cmd; 2265 int rsp_len; 2266 int cmd_index; 2267 int fc_status; 2268 int pkt_state; 2269 int pkt_action; 2270 int pkt_reason; 2271 int ret, xport_retval = ~FC_SUCCESS; 2272 int lcount; 2273 int tcount; 2274 int reconfig_status; 2275 int port_busy = FALSE; 2276 uchar_t *lun_string; 2277 2278 /* 2279 * Check valid SCSI command 2280 */ 2281 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2282 ret = EINVAL; 2283 for (cmd_index = 0; 2284 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2285 ret != 0; 2286 cmd_index++) { 2287 /* 2288 * First byte of CDB is the SCSI command 2289 */ 2290 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2291 ret = 0; 2292 } 2293 } 2294 2295 /* 2296 * Check inputs 2297 */ 2298 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2299 ret = EINVAL; 2300 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { /* no larger than */ 2301 ret = EINVAL; 2302 } 2303 2304 2305 /* 2306 * Find FC port 2307 */ 2308 if (ret == 0) { 2309 /* 2310 * Acquire global mutex 2311 */ 2312 mutex_enter(&fcp_global_mutex); 2313 2314 pptr = fcp_port_head; 2315 while (pptr) { 2316 if (pptr->port_instance == 2317 (uint32_t)fscsi->scsi_fc_port_num) 2318 break; 2319 else 2320 pptr = pptr->port_next; 2321 } 2322 2323 if (pptr == NULL) { 2324 ret = ENXIO; 2325 } else { 2326 /* 2327 * fc_ulp_busy_port can raise power 2328 * so, we must not hold any mutexes involved in PM 2329 */ 2330 mutex_exit(&fcp_global_mutex); 2331 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2332 } 2333 2334 if (ret == 0) { 2335 2336 /* remember port is busy, so we will release later */ 2337 port_busy = TRUE; 2338 2339 /* 2340 * If there is a reconfiguration in progress, wait 2341 * for it to complete. 2342 */ 2343 2344 fcp_reconfig_wait(pptr); 2345 2346 /* reacquire mutexes in order */ 2347 mutex_enter(&fcp_global_mutex); 2348 mutex_enter(&pptr->port_mutex); 2349 2350 /* 2351 * Will port accept DMA? 2352 */ 2353 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2354 ? 1 : 0; 2355 2356 /* 2357 * If init or offline, device not known 2358 * 2359 * If we are discovering (onlining), we can 2360 * NOT obviously provide reliable data about 2361 * devices until it is complete 2362 */ 2363 if (pptr->port_state & (FCP_STATE_INIT | 2364 FCP_STATE_OFFLINE)) { 2365 ret = ENXIO; 2366 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2367 ret = EBUSY; 2368 } else { 2369 /* 2370 * Find target from pwwn 2371 * 2372 * The wwn must be put into a local 2373 * variable to ensure alignment. 2374 */ 2375 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2376 ptgt = fcp_lookup_target(pptr, 2377 (uchar_t *)wwn_ptr); 2378 2379 /* 2380 * If target not found, 2381 */ 2382 if (ptgt == NULL) { 2383 /* 2384 * Note: Still have global & 2385 * port mutexes 2386 */ 2387 mutex_exit(&pptr->port_mutex); 2388 ptgt = fcp_port_create_tgt(pptr, 2389 wwn_ptr, &ret, &fc_status, 2390 &pkt_state, &pkt_action, 2391 &pkt_reason); 2392 mutex_enter(&pptr->port_mutex); 2393 2394 fscsi->scsi_fc_status = fc_status; 2395 fscsi->scsi_pkt_state = 2396 (uchar_t)pkt_state; 2397 fscsi->scsi_pkt_reason = pkt_reason; 2398 fscsi->scsi_pkt_action = 2399 (uchar_t)pkt_action; 2400 2401 if (ptgt != NULL) { 2402 target_created = TRUE; 2403 } else if (ret == 0) { 2404 ret = ENOMEM; 2405 } 2406 } 2407 2408 if (ret == 0) { 2409 /* 2410 * Acquire target 2411 */ 2412 mutex_enter(&ptgt->tgt_mutex); 2413 2414 /* 2415 * If target is mark or busy, 2416 * then target can not be used 2417 */ 2418 if (ptgt->tgt_state & 2419 (FCP_TGT_MARK | 2420 FCP_TGT_BUSY)) { 2421 ret = EBUSY; 2422 } else { 2423 /* 2424 * Mark target as busy 2425 */ 2426 ptgt->tgt_state |= 2427 FCP_TGT_BUSY; 2428 } 2429 2430 /* 2431 * Release target 2432 */ 2433 lcount = pptr->port_link_cnt; 2434 tcount = ptgt->tgt_change_cnt; 2435 mutex_exit(&ptgt->tgt_mutex); 2436 } 2437 } 2438 2439 /* 2440 * Release port 2441 */ 2442 mutex_exit(&pptr->port_mutex); 2443 } 2444 2445 /* 2446 * Release global mutex 2447 */ 2448 mutex_exit(&fcp_global_mutex); 2449 } 2450 2451 if (ret == 0) { 2452 uint64_t belun = BE_64(fscsi->scsi_lun); 2453 2454 /* 2455 * If it's a target device, find lun from pwwn 2456 * The wwn must be put into a local 2457 * variable to ensure alignment. 2458 */ 2459 mutex_enter(&pptr->port_mutex); 2460 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2461 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2462 /* this is not a target */ 2463 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2464 ret = ENXIO; 2465 } else if ((belun << 16) != 0) { 2466 /* 2467 * Since fcp only support PD and LU addressing method 2468 * so far, the last 6 bytes of a valid LUN are expected 2469 * to be filled with 00h. 2470 */ 2471 fscsi->scsi_fc_status = FC_INVALID_LUN; 2472 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2473 " method 0x%02x with LUN number 0x%016" PRIx64, 2474 (uint8_t)(belun >> 62), belun); 2475 ret = ENXIO; 2476 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2477 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2478 /* 2479 * This is a SCSI target, but no LUN at this 2480 * address. 2481 * 2482 * In the future, we may want to send this to 2483 * the target, and let it respond 2484 * appropriately 2485 */ 2486 ret = ENXIO; 2487 } 2488 mutex_exit(&pptr->port_mutex); 2489 } 2490 2491 /* 2492 * Finished grabbing external resources 2493 * Allocate internal packet (icmd) 2494 */ 2495 if (ret == 0) { 2496 /* 2497 * Calc rsp len assuming rsp info included 2498 */ 2499 rsp_len = sizeof (struct fcp_rsp) + 2500 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2501 2502 icmd = fcp_icmd_alloc(pptr, ptgt, 2503 sizeof (struct fcp_cmd), 2504 rsp_len, 2505 fscsi->scsi_buflen, 2506 nodma, 2507 lcount, /* ipkt_link_cnt */ 2508 tcount, /* ipkt_change_cnt */ 2509 0, /* cause */ 2510 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2511 2512 if (icmd == NULL) { 2513 ret = ENOMEM; 2514 } else { 2515 /* 2516 * Setup internal packet as sema sync 2517 */ 2518 fcp_ipkt_sema_init(icmd); 2519 } 2520 } 2521 2522 if (ret == 0) { 2523 /* 2524 * Init fpkt pointer for use. 2525 */ 2526 2527 fpkt = icmd->ipkt_fpkt; 2528 2529 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2530 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2531 fpkt->pkt_timeout = fscsi->scsi_timeout; 2532 2533 /* 2534 * Init fcmd pointer for use by SCSI command 2535 */ 2536 2537 if (nodma) { 2538 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2539 } else { 2540 fcmd = &fcp_cmd; 2541 } 2542 bzero(fcmd, sizeof (struct fcp_cmd)); 2543 ptgt = plun->lun_tgt; 2544 2545 lun_string = (uchar_t *)&fscsi->scsi_lun; 2546 2547 fcmd->fcp_ent_addr.ent_addr_0 = 2548 BE_16(*(uint16_t *)&(lun_string[0])); 2549 fcmd->fcp_ent_addr.ent_addr_1 = 2550 BE_16(*(uint16_t *)&(lun_string[2])); 2551 fcmd->fcp_ent_addr.ent_addr_2 = 2552 BE_16(*(uint16_t *)&(lun_string[4])); 2553 fcmd->fcp_ent_addr.ent_addr_3 = 2554 BE_16(*(uint16_t *)&(lun_string[6])); 2555 2556 /* 2557 * Setup internal packet(icmd) 2558 */ 2559 icmd->ipkt_lun = plun; 2560 icmd->ipkt_restart = 0; 2561 icmd->ipkt_retries = 0; 2562 icmd->ipkt_opcode = 0; 2563 2564 /* 2565 * Init the frame HEADER Pointer for use 2566 */ 2567 hp = &fpkt->pkt_cmd_fhdr; 2568 2569 hp->s_id = pptr->port_id; 2570 hp->d_id = ptgt->tgt_d_id; 2571 hp->r_ctl = R_CTL_COMMAND; 2572 hp->type = FC_TYPE_SCSI_FCP; 2573 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2574 hp->rsvd = 0; 2575 hp->seq_id = 0; 2576 hp->seq_cnt = 0; 2577 hp->ox_id = 0xffff; 2578 hp->rx_id = 0xffff; 2579 hp->ro = 0; 2580 2581 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2582 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2583 fcmd->fcp_cntl.cntl_write_data = 0; 2584 fcmd->fcp_data_len = fscsi->scsi_buflen; 2585 2586 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2587 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2588 fscsi->scsi_cdblen); 2589 2590 if (!nodma) { 2591 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2592 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2593 } 2594 2595 /* 2596 * Send SCSI command to FC transport 2597 */ 2598 2599 if (ret == 0) { 2600 mutex_enter(&ptgt->tgt_mutex); 2601 2602 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2603 mutex_exit(&ptgt->tgt_mutex); 2604 fscsi->scsi_fc_status = xport_retval = 2605 fc_ulp_transport(pptr->port_fp_handle, 2606 fpkt); 2607 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2608 ret = EIO; 2609 } 2610 } else { 2611 mutex_exit(&ptgt->tgt_mutex); 2612 ret = EBUSY; 2613 } 2614 } 2615 } 2616 2617 /* 2618 * Wait for completion only if fc_ulp_transport was called and it 2619 * returned a success. This is the only time callback will happen. 2620 * Otherwise, there is no point in waiting 2621 */ 2622 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2623 ret = fcp_ipkt_sema_wait(icmd); 2624 } 2625 2626 /* 2627 * Copy data to IOCTL data structures 2628 */ 2629 rsp = NULL; 2630 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2631 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2632 2633 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2634 fcp_log(CE_WARN, pptr->port_dip, 2635 "!SCSI command to d_id=0x%x lun=0x%x" 2636 " failed, Bad FCP response values:" 2637 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2638 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2639 ptgt->tgt_d_id, plun->lun_num, 2640 rsp->reserved_0, rsp->reserved_1, 2641 rsp->fcp_u.fcp_status.reserved_0, 2642 rsp->fcp_u.fcp_status.reserved_1, 2643 rsp->fcp_response_len, rsp->fcp_sense_len); 2644 2645 ret = EIO; 2646 } 2647 } 2648 2649 if ((ret == 0) && (rsp != NULL)) { 2650 /* 2651 * Calc response lengths 2652 */ 2653 sense_len = 0; 2654 info_len = 0; 2655 2656 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2657 info_len = rsp->fcp_response_len; 2658 } 2659 2660 rsp_info = (struct fcp_rsp_info *) 2661 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2662 2663 /* 2664 * Get SCSI status 2665 */ 2666 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2667 /* 2668 * If a lun was just added or removed and the next command 2669 * comes through this interface, we need to capture the check 2670 * condition so we can discover the new topology. 2671 */ 2672 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2673 rsp->fcp_u.fcp_status.sense_len_set) { 2674 sense_len = rsp->fcp_sense_len; 2675 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2676 sense_to = (struct scsi_extended_sense *)rsp_sense; 2677 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2678 (FCP_SENSE_NO_LUN(sense_to))) { 2679 reconfig_lun = TRUE; 2680 } 2681 } 2682 2683 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2684 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2685 if (reconfig_lun == FALSE) { 2686 reconfig_status = 2687 fcp_is_reconfig_needed(ptgt, fpkt); 2688 } 2689 2690 if ((reconfig_lun == TRUE) || 2691 (reconfig_status == TRUE)) { 2692 mutex_enter(&ptgt->tgt_mutex); 2693 if (ptgt->tgt_tid == NULL) { 2694 /* 2695 * Either we've been notified the 2696 * REPORT_LUN data has changed, or 2697 * we've determined on our own that 2698 * we're out of date. Kick off 2699 * rediscovery. 2700 */ 2701 tid = timeout(fcp_reconfigure_luns, 2702 (caddr_t)ptgt, drv_usectohz(1)); 2703 2704 ptgt->tgt_tid = tid; 2705 ptgt->tgt_state |= FCP_TGT_BUSY; 2706 ret = EBUSY; 2707 reconfig_pending = TRUE; 2708 } 2709 mutex_exit(&ptgt->tgt_mutex); 2710 } 2711 } 2712 2713 /* 2714 * Calc residuals and buffer lengths 2715 */ 2716 2717 if (ret == 0) { 2718 buf_len = fscsi->scsi_buflen; 2719 fscsi->scsi_bufresid = 0; 2720 if (rsp->fcp_u.fcp_status.resid_under) { 2721 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2722 fscsi->scsi_bufresid = rsp->fcp_resid; 2723 } else { 2724 cmn_err(CE_WARN, "fcp: bad residue %x " 2725 "for txfer len %x", rsp->fcp_resid, 2726 fscsi->scsi_buflen); 2727 fscsi->scsi_bufresid = 2728 fscsi->scsi_buflen; 2729 } 2730 buf_len -= fscsi->scsi_bufresid; 2731 } 2732 if (rsp->fcp_u.fcp_status.resid_over) { 2733 fscsi->scsi_bufresid = -rsp->fcp_resid; 2734 } 2735 2736 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2737 if (fscsi->scsi_rqlen < sense_len) { 2738 sense_len = fscsi->scsi_rqlen; 2739 } 2740 2741 fscsi->scsi_fc_rspcode = 0; 2742 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2743 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2744 } 2745 fscsi->scsi_pkt_state = fpkt->pkt_state; 2746 fscsi->scsi_pkt_action = fpkt->pkt_action; 2747 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2748 2749 /* 2750 * Copy data and request sense 2751 * 2752 * Data must be copied by using the FCP_CP_IN macro. 2753 * This will ensure the proper byte order since the data 2754 * is being copied directly from the memory mapped 2755 * device register. 2756 * 2757 * The response (and request sense) will be in the 2758 * correct byte order. No special copy is necessary. 2759 */ 2760 2761 if (buf_len) { 2762 FCP_CP_IN(fpkt->pkt_data, 2763 fscsi->scsi_bufaddr, 2764 fpkt->pkt_data_acc, 2765 buf_len); 2766 } 2767 bcopy((void *)rsp_sense, 2768 (void *)fscsi->scsi_rqbufaddr, 2769 sense_len); 2770 } 2771 } 2772 2773 /* 2774 * Cleanup transport data structures if icmd was alloc-ed 2775 * So, cleanup happens in the same thread that icmd was alloc-ed 2776 */ 2777 if (icmd != NULL) { 2778 fcp_ipkt_sema_cleanup(icmd); 2779 } 2780 2781 /* restore pm busy/idle status */ 2782 if (port_busy) { 2783 fc_ulp_idle_port(pptr->port_fp_handle); 2784 } 2785 2786 /* 2787 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2788 * flag, it'll be cleared when the reconfig is complete. 2789 */ 2790 if ((ptgt != NULL) && !reconfig_pending) { 2791 /* 2792 * If target was created, 2793 */ 2794 if (target_created) { 2795 mutex_enter(&ptgt->tgt_mutex); 2796 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2797 mutex_exit(&ptgt->tgt_mutex); 2798 } else { 2799 /* 2800 * De-mark target as busy 2801 */ 2802 mutex_enter(&ptgt->tgt_mutex); 2803 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2804 mutex_exit(&ptgt->tgt_mutex); 2805 } 2806 } 2807 return (ret); 2808 } 2809 2810 2811 static int 2812 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2813 fc_packet_t *fpkt) 2814 { 2815 uchar_t *lun_string; 2816 uint16_t lun_num, i; 2817 int num_luns; 2818 int actual_luns; 2819 int num_masked_luns; 2820 int lun_buflen; 2821 struct fcp_lun *plun = NULL; 2822 struct fcp_reportlun_resp *report_lun; 2823 uint8_t reconfig_needed = FALSE; 2824 uint8_t lun_exists = FALSE; 2825 2826 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2827 2828 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2829 fpkt->pkt_datalen); 2830 2831 /* get number of luns (which is supplied as LUNS * 8) */ 2832 num_luns = BE_32(report_lun->num_lun) >> 3; 2833 2834 /* 2835 * Figure out exactly how many lun strings our response buffer 2836 * can hold. 2837 */ 2838 lun_buflen = (fpkt->pkt_datalen - 2839 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2840 2841 /* 2842 * Is our response buffer full or not? We don't want to 2843 * potentially walk beyond the number of luns we have. 2844 */ 2845 if (num_luns <= lun_buflen) { 2846 actual_luns = num_luns; 2847 } else { 2848 actual_luns = lun_buflen; 2849 } 2850 2851 mutex_enter(&ptgt->tgt_mutex); 2852 2853 /* Scan each lun to see if we have masked it. */ 2854 num_masked_luns = 0; 2855 if (fcp_lun_blacklist != NULL) { 2856 for (i = 0; i < num_luns; i++) { 2857 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2858 switch (lun_string[0] & 0xC0) { 2859 case FCP_LUN_ADDRESSING: 2860 case FCP_PD_ADDRESSING: 2861 lun_num = ((lun_string[0] & 0x3F) << 8) 2862 | lun_string[1]; 2863 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2864 lun_num) == TRUE) { 2865 num_masked_luns++; 2866 } 2867 break; 2868 default: 2869 break; 2870 } 2871 } 2872 } 2873 2874 /* 2875 * The quick and easy check. If the number of LUNs reported 2876 * doesn't match the number we currently know about, we need 2877 * to reconfigure. 2878 */ 2879 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2880 mutex_exit(&ptgt->tgt_mutex); 2881 kmem_free(report_lun, fpkt->pkt_datalen); 2882 return (TRUE); 2883 } 2884 2885 /* 2886 * If the quick and easy check doesn't turn up anything, we walk 2887 * the list of luns from the REPORT_LUN response and look for 2888 * any luns we don't know about. If we find one, we know we need 2889 * to reconfigure. We will skip LUNs that are masked because of the 2890 * blacklist. 2891 */ 2892 for (i = 0; i < actual_luns; i++) { 2893 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2894 lun_exists = FALSE; 2895 switch (lun_string[0] & 0xC0) { 2896 case FCP_LUN_ADDRESSING: 2897 case FCP_PD_ADDRESSING: 2898 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2899 2900 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2901 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2902 lun_exists = TRUE; 2903 break; 2904 } 2905 2906 for (plun = ptgt->tgt_lun; plun; 2907 plun = plun->lun_next) { 2908 if (plun->lun_num == lun_num) { 2909 lun_exists = TRUE; 2910 break; 2911 } 2912 } 2913 break; 2914 default: 2915 break; 2916 } 2917 2918 if (lun_exists == FALSE) { 2919 reconfig_needed = TRUE; 2920 break; 2921 } 2922 } 2923 2924 mutex_exit(&ptgt->tgt_mutex); 2925 kmem_free(report_lun, fpkt->pkt_datalen); 2926 2927 return (reconfig_needed); 2928 } 2929 2930 /* 2931 * This function is called by fcp_handle_page83 and uses inquiry response data 2932 * stored in plun->lun_inq to determine whether or not a device is a member of 2933 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2934 * otherwise 1. 2935 */ 2936 static int 2937 fcp_symmetric_device_probe(struct fcp_lun *plun) 2938 { 2939 struct scsi_inquiry *stdinq = &plun->lun_inq; 2940 char *devidptr; 2941 int i, len; 2942 2943 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2944 devidptr = fcp_symmetric_disk_table[i]; 2945 len = (int)strlen(devidptr); 2946 2947 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 2948 return (0); 2949 } 2950 } 2951 return (1); 2952 } 2953 2954 2955 /* 2956 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 2957 * It basically returns the current count of # of state change callbacks 2958 * i.e the value of tgt_change_cnt. 2959 * 2960 * INPUT: 2961 * fcp_ioctl.fp_minor -> The minor # of the fp port 2962 * fcp_ioctl.listlen -> 1 2963 * fcp_ioctl.list -> Pointer to a 32 bit integer 2964 */ 2965 /*ARGSUSED2*/ 2966 static int 2967 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 2968 { 2969 int ret; 2970 uint32_t link_cnt; 2971 struct fcp_ioctl fioctl; 2972 struct fcp_port *pptr = NULL; 2973 2974 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 2975 &pptr)) != 0) { 2976 return (ret); 2977 } 2978 2979 ASSERT(pptr != NULL); 2980 2981 if (fioctl.listlen != 1) 2982 return (EINVAL); 2983 2984 mutex_enter(&pptr->port_mutex); 2985 if (pptr->port_state & FCP_STATE_OFFLINE) { 2986 mutex_exit(&pptr->port_mutex); 2987 return (ENXIO); 2988 } 2989 2990 /* 2991 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 2992 * When the fcp initially attaches to the port and there are nothing 2993 * hanging out of the port or if there was a repeat offline state change 2994 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 2995 * In the latter case, port_tmp_cnt will be non-zero and that is how we 2996 * will differentiate the 2 cases. 2997 */ 2998 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 2999 mutex_exit(&pptr->port_mutex); 3000 return (ENXIO); 3001 } 3002 3003 link_cnt = pptr->port_link_cnt; 3004 mutex_exit(&pptr->port_mutex); 3005 3006 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3007 return (EFAULT); 3008 } 3009 3010 #ifdef _MULTI_DATAMODEL 3011 switch (ddi_model_convert_from(mode & FMODELS)) { 3012 case DDI_MODEL_ILP32: { 3013 struct fcp32_ioctl f32_ioctl; 3014 3015 f32_ioctl.fp_minor = fioctl.fp_minor; 3016 f32_ioctl.listlen = fioctl.listlen; 3017 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3018 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3019 sizeof (struct fcp32_ioctl), mode)) { 3020 return (EFAULT); 3021 } 3022 break; 3023 } 3024 case DDI_MODEL_NONE: 3025 if (ddi_copyout((void *)&fioctl, (void *)data, 3026 sizeof (struct fcp_ioctl), mode)) { 3027 return (EFAULT); 3028 } 3029 break; 3030 } 3031 #else /* _MULTI_DATAMODEL */ 3032 3033 if (ddi_copyout((void *)&fioctl, (void *)data, 3034 sizeof (struct fcp_ioctl), mode)) { 3035 return (EFAULT); 3036 } 3037 #endif /* _MULTI_DATAMODEL */ 3038 3039 return (0); 3040 } 3041 3042 /* 3043 * This function copies the fcp_ioctl structure passed in from user land 3044 * into kernel land. Handles 32 bit applications. 3045 */ 3046 /*ARGSUSED*/ 3047 static int 3048 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3049 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3050 { 3051 struct fcp_port *t_pptr; 3052 3053 #ifdef _MULTI_DATAMODEL 3054 switch (ddi_model_convert_from(mode & FMODELS)) { 3055 case DDI_MODEL_ILP32: { 3056 struct fcp32_ioctl f32_ioctl; 3057 3058 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3059 sizeof (struct fcp32_ioctl), mode)) { 3060 return (EFAULT); 3061 } 3062 fioctl->fp_minor = f32_ioctl.fp_minor; 3063 fioctl->listlen = f32_ioctl.listlen; 3064 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3065 break; 3066 } 3067 case DDI_MODEL_NONE: 3068 if (ddi_copyin((void *)data, (void *)fioctl, 3069 sizeof (struct fcp_ioctl), mode)) { 3070 return (EFAULT); 3071 } 3072 break; 3073 } 3074 3075 #else /* _MULTI_DATAMODEL */ 3076 if (ddi_copyin((void *)data, (void *)fioctl, 3077 sizeof (struct fcp_ioctl), mode)) { 3078 return (EFAULT); 3079 } 3080 #endif /* _MULTI_DATAMODEL */ 3081 3082 /* 3083 * Right now we can assume that the minor number matches with 3084 * this instance of fp. If this changes we will need to 3085 * revisit this logic. 3086 */ 3087 mutex_enter(&fcp_global_mutex); 3088 t_pptr = fcp_port_head; 3089 while (t_pptr) { 3090 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) 3091 break; 3092 else 3093 t_pptr = t_pptr->port_next; 3094 } 3095 *pptr = t_pptr; 3096 mutex_exit(&fcp_global_mutex); 3097 if (t_pptr == NULL) 3098 return (ENXIO); 3099 3100 return (0); 3101 } 3102 3103 /* 3104 * Function: fcp_port_create_tgt 3105 * 3106 * Description: As the name suggest this function creates the target context 3107 * specified by the the WWN provided by the caller. If the 3108 * creation goes well and the target is known by fp/fctl a PLOGI 3109 * followed by a PRLI are issued. 3110 * 3111 * Argument: pptr fcp port structure 3112 * pwwn WWN of the target 3113 * ret_val Address of the return code. It could be: 3114 * EIO, ENOMEM or 0. 3115 * fc_status PLOGI or PRLI status completion 3116 * fc_pkt_state PLOGI or PRLI state completion 3117 * fc_pkt_reason PLOGI or PRLI reason completion 3118 * fc_pkt_action PLOGI or PRLI action completion 3119 * 3120 * Return Value: NULL if it failed 3121 * Target structure address if it succeeds 3122 */ 3123 static struct fcp_tgt * 3124 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3125 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3126 { 3127 struct fcp_tgt *ptgt = NULL; 3128 fc_portmap_t devlist; 3129 int lcount; 3130 int error; 3131 3132 *ret_val = 0; 3133 3134 /* 3135 * Check FC port device & get port map 3136 */ 3137 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3138 &error, 1) == NULL) { 3139 *ret_val = EIO; 3140 } else { 3141 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3142 &devlist) != FC_SUCCESS) { 3143 *ret_val = EIO; 3144 } 3145 } 3146 3147 /* Set port map flags */ 3148 devlist.map_type = PORT_DEVICE_USER_CREATE; 3149 3150 /* Allocate target */ 3151 if (*ret_val == 0) { 3152 lcount = pptr->port_link_cnt; 3153 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3154 if (ptgt == NULL) { 3155 fcp_log(CE_WARN, pptr->port_dip, 3156 "!FC target allocation failed"); 3157 *ret_val = ENOMEM; 3158 } else { 3159 /* Setup target */ 3160 mutex_enter(&ptgt->tgt_mutex); 3161 3162 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3163 ptgt->tgt_tmp_cnt = 1; 3164 ptgt->tgt_d_id = devlist.map_did.port_id; 3165 ptgt->tgt_hard_addr = 3166 devlist.map_hard_addr.hard_addr; 3167 ptgt->tgt_pd_handle = devlist.map_pd; 3168 ptgt->tgt_fca_dev = NULL; 3169 3170 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3171 FC_WWN_SIZE); 3172 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3173 FC_WWN_SIZE); 3174 3175 mutex_exit(&ptgt->tgt_mutex); 3176 } 3177 } 3178 3179 /* Release global mutex for PLOGI and PRLI */ 3180 mutex_exit(&fcp_global_mutex); 3181 3182 /* Send PLOGI (If necessary) */ 3183 if (*ret_val == 0) { 3184 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3185 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3186 } 3187 3188 /* Send PRLI (If necessary) */ 3189 if (*ret_val == 0) { 3190 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3191 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3192 } 3193 3194 mutex_enter(&fcp_global_mutex); 3195 3196 return (ptgt); 3197 } 3198 3199 /* 3200 * Function: fcp_tgt_send_plogi 3201 * 3202 * Description: This function sends a PLOGI to the target specified by the 3203 * caller and waits till it completes. 3204 * 3205 * Argument: ptgt Target to send the plogi to. 3206 * fc_status Status returned by fp/fctl in the PLOGI request. 3207 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3208 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3209 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3210 * 3211 * Return Value: 0 3212 * ENOMEM 3213 * EIO 3214 * 3215 * Context: User context. 3216 */ 3217 static int 3218 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3219 int *fc_pkt_reason, int *fc_pkt_action) 3220 { 3221 struct fcp_port *pptr; 3222 struct fcp_ipkt *icmd; 3223 struct fc_packet *fpkt; 3224 fc_frame_hdr_t *hp; 3225 struct la_els_logi logi; 3226 int tcount; 3227 int lcount; 3228 int ret, login_retval = ~FC_SUCCESS; 3229 3230 ret = 0; 3231 3232 pptr = ptgt->tgt_port; 3233 3234 lcount = pptr->port_link_cnt; 3235 tcount = ptgt->tgt_change_cnt; 3236 3237 /* Alloc internal packet */ 3238 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3239 sizeof (la_els_logi_t), 0, 0, lcount, tcount, 0, 3240 FC_INVALID_RSCN_COUNT); 3241 3242 if (icmd == NULL) { 3243 ret = ENOMEM; 3244 } else { 3245 /* 3246 * Setup internal packet as sema sync 3247 */ 3248 fcp_ipkt_sema_init(icmd); 3249 3250 /* 3251 * Setup internal packet (icmd) 3252 */ 3253 icmd->ipkt_lun = NULL; 3254 icmd->ipkt_restart = 0; 3255 icmd->ipkt_retries = 0; 3256 icmd->ipkt_opcode = LA_ELS_PLOGI; 3257 3258 /* 3259 * Setup fc_packet 3260 */ 3261 fpkt = icmd->ipkt_fpkt; 3262 3263 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3264 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3265 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3266 3267 /* 3268 * Setup FC frame header 3269 */ 3270 hp = &fpkt->pkt_cmd_fhdr; 3271 3272 hp->s_id = pptr->port_id; /* source ID */ 3273 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3274 hp->r_ctl = R_CTL_ELS_REQ; 3275 hp->type = FC_TYPE_EXTENDED_LS; 3276 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3277 hp->seq_id = 0; 3278 hp->rsvd = 0; 3279 hp->df_ctl = 0; 3280 hp->seq_cnt = 0; 3281 hp->ox_id = 0xffff; /* i.e. none */ 3282 hp->rx_id = 0xffff; /* i.e. none */ 3283 hp->ro = 0; 3284 3285 /* 3286 * Setup PLOGI 3287 */ 3288 bzero(&logi, sizeof (struct la_els_logi)); 3289 logi.ls_code.ls_code = LA_ELS_PLOGI; 3290 3291 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3292 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3293 3294 /* 3295 * Send PLOGI 3296 */ 3297 *fc_status = login_retval = 3298 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3299 if (*fc_status != FC_SUCCESS) { 3300 ret = EIO; 3301 } 3302 } 3303 3304 /* 3305 * Wait for completion 3306 */ 3307 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3308 ret = fcp_ipkt_sema_wait(icmd); 3309 3310 *fc_pkt_state = fpkt->pkt_state; 3311 *fc_pkt_reason = fpkt->pkt_reason; 3312 *fc_pkt_action = fpkt->pkt_action; 3313 } 3314 3315 /* 3316 * Cleanup transport data structures if icmd was alloc-ed AND if there 3317 * is going to be no callback (i.e if fc_ulp_login() failed). 3318 * Otherwise, cleanup happens in callback routine. 3319 */ 3320 if (icmd != NULL) { 3321 fcp_ipkt_sema_cleanup(icmd); 3322 } 3323 3324 return (ret); 3325 } 3326 3327 /* 3328 * Function: fcp_tgt_send_prli 3329 * 3330 * Description: Does nothing as of today. 3331 * 3332 * Argument: ptgt Target to send the prli to. 3333 * fc_status Status returned by fp/fctl in the PRLI request. 3334 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3335 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3336 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3337 * 3338 * Return Value: 0 3339 */ 3340 /*ARGSUSED*/ 3341 static int 3342 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3343 int *fc_pkt_reason, int *fc_pkt_action) 3344 { 3345 return (0); 3346 } 3347 3348 /* 3349 * Function: fcp_ipkt_sema_init 3350 * 3351 * Description: Initializes the semaphore contained in the internal packet. 3352 * 3353 * Argument: icmd Internal packet the semaphore of which must be 3354 * initialized. 3355 * 3356 * Return Value: None 3357 * 3358 * Context: User context only. 3359 */ 3360 static void 3361 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3362 { 3363 struct fc_packet *fpkt; 3364 3365 fpkt = icmd->ipkt_fpkt; 3366 3367 /* Create semaphore for sync */ 3368 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3369 3370 /* Setup the completion callback */ 3371 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3372 } 3373 3374 /* 3375 * Function: fcp_ipkt_sema_wait 3376 * 3377 * Description: Wait on the semaphore embedded in the internal packet. The 3378 * semaphore is released in the callback. 3379 * 3380 * Argument: icmd Internal packet to wait on for completion. 3381 * 3382 * Return Value: 0 3383 * EIO 3384 * EBUSY 3385 * EAGAIN 3386 * 3387 * Context: User context only. 3388 * 3389 * This function does a conversion between the field pkt_state of the fc_packet 3390 * embedded in the internal packet (icmd) and the code it returns. 3391 */ 3392 static int 3393 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3394 { 3395 struct fc_packet *fpkt; 3396 int ret; 3397 3398 ret = EIO; 3399 fpkt = icmd->ipkt_fpkt; 3400 3401 /* 3402 * Wait on semaphore 3403 */ 3404 sema_p(&(icmd->ipkt_sema)); 3405 3406 /* 3407 * Check the status of the FC packet 3408 */ 3409 switch (fpkt->pkt_state) { 3410 case FC_PKT_SUCCESS: 3411 ret = 0; 3412 break; 3413 case FC_PKT_LOCAL_RJT: 3414 switch (fpkt->pkt_reason) { 3415 case FC_REASON_SEQ_TIMEOUT: 3416 case FC_REASON_RX_BUF_TIMEOUT: 3417 ret = EAGAIN; 3418 break; 3419 case FC_REASON_PKT_BUSY: 3420 ret = EBUSY; 3421 break; 3422 } 3423 break; 3424 case FC_PKT_TIMEOUT: 3425 ret = EAGAIN; 3426 break; 3427 case FC_PKT_LOCAL_BSY: 3428 case FC_PKT_TRAN_BSY: 3429 case FC_PKT_NPORT_BSY: 3430 case FC_PKT_FABRIC_BSY: 3431 ret = EBUSY; 3432 break; 3433 case FC_PKT_LS_RJT: 3434 case FC_PKT_BA_RJT: 3435 switch (fpkt->pkt_reason) { 3436 case FC_REASON_LOGICAL_BSY: 3437 ret = EBUSY; 3438 break; 3439 } 3440 break; 3441 case FC_PKT_FS_RJT: 3442 switch (fpkt->pkt_reason) { 3443 case FC_REASON_FS_LOGICAL_BUSY: 3444 ret = EBUSY; 3445 break; 3446 } 3447 break; 3448 } 3449 3450 return (ret); 3451 } 3452 3453 /* 3454 * Function: fcp_ipkt_sema_callback 3455 * 3456 * Description: Registered as the completion callback function for the FC 3457 * transport when the ipkt semaphore is used for sync. This will 3458 * cleanup the used data structures, if necessary and wake up 3459 * the user thread to complete the transaction. 3460 * 3461 * Argument: fpkt FC packet (points to the icmd) 3462 * 3463 * Return Value: None 3464 * 3465 * Context: User context only 3466 */ 3467 static void 3468 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3469 { 3470 struct fcp_ipkt *icmd; 3471 3472 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3473 3474 /* 3475 * Wake up user thread 3476 */ 3477 sema_v(&(icmd->ipkt_sema)); 3478 } 3479 3480 /* 3481 * Function: fcp_ipkt_sema_cleanup 3482 * 3483 * Description: Called to cleanup (if necessary) the data structures used 3484 * when ipkt sema is used for sync. This function will detect 3485 * whether the caller is the last thread (via counter) and 3486 * cleanup only if necessary. 3487 * 3488 * Argument: icmd Internal command packet 3489 * 3490 * Return Value: None 3491 * 3492 * Context: User context only 3493 */ 3494 static void 3495 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3496 { 3497 struct fcp_tgt *ptgt; 3498 struct fcp_port *pptr; 3499 3500 ptgt = icmd->ipkt_tgt; 3501 pptr = icmd->ipkt_port; 3502 3503 /* 3504 * Acquire data structure 3505 */ 3506 mutex_enter(&ptgt->tgt_mutex); 3507 3508 /* 3509 * Destroy semaphore 3510 */ 3511 sema_destroy(&(icmd->ipkt_sema)); 3512 3513 /* 3514 * Cleanup internal packet 3515 */ 3516 mutex_exit(&ptgt->tgt_mutex); 3517 fcp_icmd_free(pptr, icmd); 3518 } 3519 3520 /* 3521 * Function: fcp_port_attach 3522 * 3523 * Description: Called by the transport framework to resume, suspend or 3524 * attach a new port. 3525 * 3526 * Argument: ulph Port handle 3527 * *pinfo Port information 3528 * cmd Command 3529 * s_id Port ID 3530 * 3531 * Return Value: FC_FAILURE or FC_SUCCESS 3532 */ 3533 /*ARGSUSED*/ 3534 static int 3535 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3536 fc_attach_cmd_t cmd, uint32_t s_id) 3537 { 3538 int instance; 3539 int res = FC_FAILURE; /* default result */ 3540 3541 ASSERT(pinfo != NULL); 3542 3543 instance = ddi_get_instance(pinfo->port_dip); 3544 3545 switch (cmd) { 3546 case FC_CMD_ATTACH: 3547 /* 3548 * this port instance attaching for the first time (or after 3549 * being detached before) 3550 */ 3551 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3552 instance) == DDI_SUCCESS) { 3553 res = FC_SUCCESS; 3554 } else { 3555 ASSERT(ddi_get_soft_state(fcp_softstate, 3556 instance) == NULL); 3557 } 3558 break; 3559 3560 case FC_CMD_RESUME: 3561 case FC_CMD_POWER_UP: 3562 /* 3563 * this port instance was attached and the suspended and 3564 * will now be resumed 3565 */ 3566 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3567 instance) == DDI_SUCCESS) { 3568 res = FC_SUCCESS; 3569 } 3570 break; 3571 3572 default: 3573 /* shouldn't happen */ 3574 FCP_TRACE(fcp_logq, "fcp", 3575 fcp_trace, FCP_BUF_LEVEL_2, 0, 3576 "port_attach: unknown cmdcommand: %d", cmd); 3577 break; 3578 } 3579 3580 /* return result */ 3581 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3582 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3583 3584 return (res); 3585 } 3586 3587 3588 /* 3589 * detach or suspend this port instance 3590 * 3591 * acquires and releases the global mutex 3592 * 3593 * acquires and releases the mutex for this port 3594 * 3595 * acquires and releases the hotplug mutex for this port 3596 */ 3597 /*ARGSUSED*/ 3598 static int 3599 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3600 fc_detach_cmd_t cmd) 3601 { 3602 int flag; 3603 int instance; 3604 struct fcp_port *pptr; 3605 3606 instance = ddi_get_instance(info->port_dip); 3607 pptr = ddi_get_soft_state(fcp_softstate, instance); 3608 3609 switch (cmd) { 3610 case FC_CMD_SUSPEND: 3611 FCP_DTRACE(fcp_logq, "fcp", 3612 fcp_trace, FCP_BUF_LEVEL_8, 0, 3613 "port suspend called for port %d", instance); 3614 flag = FCP_STATE_SUSPENDED; 3615 break; 3616 3617 case FC_CMD_POWER_DOWN: 3618 FCP_DTRACE(fcp_logq, "fcp", 3619 fcp_trace, FCP_BUF_LEVEL_8, 0, 3620 "port power down called for port %d", instance); 3621 flag = FCP_STATE_POWER_DOWN; 3622 break; 3623 3624 case FC_CMD_DETACH: 3625 FCP_DTRACE(fcp_logq, "fcp", 3626 fcp_trace, FCP_BUF_LEVEL_8, 0, 3627 "port detach called for port %d", instance); 3628 flag = FCP_STATE_DETACHING; 3629 break; 3630 3631 default: 3632 /* shouldn't happen */ 3633 return (FC_FAILURE); 3634 } 3635 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3636 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3637 3638 return (fcp_handle_port_detach(pptr, flag, instance)); 3639 } 3640 3641 3642 /* 3643 * called for ioctls on the transport's devctl interface, and the transport 3644 * has passed it to us 3645 * 3646 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3647 * 3648 * return FC_SUCCESS if we decide to claim the ioctl, 3649 * else return FC_UNCLAIMED 3650 * 3651 * *rval is set iff we decide to claim the ioctl 3652 */ 3653 /*ARGSUSED*/ 3654 static int 3655 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3656 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3657 { 3658 int retval = FC_UNCLAIMED; /* return value */ 3659 struct fcp_port *pptr = NULL; /* our soft state */ 3660 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3661 dev_info_t *cdip; 3662 mdi_pathinfo_t *pip = NULL; 3663 char *ndi_nm; /* NDI name */ 3664 char *ndi_addr; /* NDI addr */ 3665 int is_mpxio, circ; 3666 int devi_entered = 0; 3667 time_t end_time; 3668 3669 ASSERT(rval != NULL); 3670 3671 FCP_DTRACE(fcp_logq, "fcp", 3672 fcp_trace, FCP_BUF_LEVEL_8, 0, 3673 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3674 3675 /* if already claimed then forget it */ 3676 if (claimed) { 3677 /* 3678 * for now, if this ioctl has already been claimed, then 3679 * we just ignore it 3680 */ 3681 return (retval); 3682 } 3683 3684 /* get our port info */ 3685 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3686 fcp_log(CE_WARN, NULL, 3687 "!fcp:Invalid port handle handle in ioctl"); 3688 *rval = ENXIO; 3689 return (retval); 3690 } 3691 is_mpxio = pptr->port_mpxio; 3692 3693 switch (cmd) { 3694 case DEVCTL_BUS_GETSTATE: 3695 case DEVCTL_BUS_QUIESCE: 3696 case DEVCTL_BUS_UNQUIESCE: 3697 case DEVCTL_BUS_RESET: 3698 case DEVCTL_BUS_RESETALL: 3699 3700 case DEVCTL_BUS_DEV_CREATE: 3701 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3702 return (retval); 3703 } 3704 break; 3705 3706 case DEVCTL_DEVICE_GETSTATE: 3707 case DEVCTL_DEVICE_OFFLINE: 3708 case DEVCTL_DEVICE_ONLINE: 3709 case DEVCTL_DEVICE_REMOVE: 3710 case DEVCTL_DEVICE_RESET: 3711 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3712 return (retval); 3713 } 3714 3715 ASSERT(dcp != NULL); 3716 3717 /* ensure we have a name and address */ 3718 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3719 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3720 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3721 fcp_trace, FCP_BUF_LEVEL_2, 0, 3722 "ioctl: can't get name (%s) or addr (%s)", 3723 ndi_nm ? ndi_nm : "<null ptr>", 3724 ndi_addr ? ndi_addr : "<null ptr>"); 3725 ndi_dc_freehdl(dcp); 3726 return (retval); 3727 } 3728 3729 3730 /* get our child's DIP */ 3731 ASSERT(pptr != NULL); 3732 if (is_mpxio) 3733 mdi_devi_enter(pptr->port_dip, &circ); 3734 else 3735 ndi_devi_enter(pptr->port_dip, &circ); 3736 devi_entered = 1; 3737 3738 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3739 ndi_addr)) == NULL) { 3740 /* Look for virtually enumerated devices. */ 3741 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3742 if (pip == NULL || 3743 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3744 *rval = ENXIO; 3745 goto out; 3746 } 3747 } 3748 break; 3749 3750 default: 3751 *rval = ENOTTY; 3752 return (retval); 3753 } 3754 3755 /* this ioctl is ours -- process it */ 3756 3757 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3758 3759 /* we assume it will be a success; else we'll set error value */ 3760 *rval = 0; 3761 3762 3763 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3764 fcp_trace, FCP_BUF_LEVEL_8, 0, 3765 "ioctl: claiming this one"); 3766 3767 /* handle ioctls now */ 3768 switch (cmd) { 3769 case DEVCTL_DEVICE_GETSTATE: 3770 ASSERT(cdip != NULL); 3771 ASSERT(dcp != NULL); 3772 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3773 *rval = EFAULT; 3774 } 3775 break; 3776 3777 case DEVCTL_DEVICE_REMOVE: 3778 case DEVCTL_DEVICE_OFFLINE: { 3779 int flag = 0; 3780 int lcount; 3781 int tcount; 3782 struct fcp_pkt *head = NULL; 3783 struct fcp_lun *plun; 3784 child_info_t *cip = CIP(cdip); 3785 int all = 1; 3786 struct fcp_lun *tplun; 3787 struct fcp_tgt *ptgt; 3788 3789 ASSERT(pptr != NULL); 3790 ASSERT(cdip != NULL); 3791 3792 mutex_enter(&pptr->port_mutex); 3793 if (pip != NULL) { 3794 cip = CIP(pip); 3795 } 3796 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3797 mutex_exit(&pptr->port_mutex); 3798 *rval = ENXIO; 3799 break; 3800 } 3801 3802 head = fcp_scan_commands(plun); 3803 if (head != NULL) { 3804 fcp_abort_commands(head, LUN_PORT); 3805 } 3806 lcount = pptr->port_link_cnt; 3807 tcount = plun->lun_tgt->tgt_change_cnt; 3808 mutex_exit(&pptr->port_mutex); 3809 3810 if (cmd == DEVCTL_DEVICE_REMOVE) { 3811 flag = NDI_DEVI_REMOVE; 3812 } 3813 3814 if (is_mpxio) 3815 mdi_devi_exit(pptr->port_dip, circ); 3816 else 3817 ndi_devi_exit(pptr->port_dip, circ); 3818 devi_entered = 0; 3819 3820 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3821 FCP_OFFLINE, lcount, tcount, flag); 3822 3823 if (*rval != NDI_SUCCESS) { 3824 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3825 break; 3826 } 3827 3828 fcp_update_offline_flags(plun); 3829 3830 ptgt = plun->lun_tgt; 3831 mutex_enter(&ptgt->tgt_mutex); 3832 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3833 tplun->lun_next) { 3834 mutex_enter(&tplun->lun_mutex); 3835 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3836 all = 0; 3837 } 3838 mutex_exit(&tplun->lun_mutex); 3839 } 3840 3841 if (all) { 3842 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3843 /* 3844 * The user is unconfiguring/offlining the device. 3845 * If fabric and the auto configuration is set 3846 * then make sure the user is the only one who 3847 * can reconfigure the device. 3848 */ 3849 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3850 fcp_enable_auto_configuration) { 3851 ptgt->tgt_manual_config_only = 1; 3852 } 3853 } 3854 mutex_exit(&ptgt->tgt_mutex); 3855 break; 3856 } 3857 3858 case DEVCTL_DEVICE_ONLINE: { 3859 int lcount; 3860 int tcount; 3861 struct fcp_lun *plun; 3862 child_info_t *cip = CIP(cdip); 3863 3864 ASSERT(cdip != NULL); 3865 ASSERT(pptr != NULL); 3866 3867 mutex_enter(&pptr->port_mutex); 3868 if (pip != NULL) { 3869 cip = CIP(pip); 3870 } 3871 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3872 mutex_exit(&pptr->port_mutex); 3873 *rval = ENXIO; 3874 break; 3875 } 3876 lcount = pptr->port_link_cnt; 3877 tcount = plun->lun_tgt->tgt_change_cnt; 3878 mutex_exit(&pptr->port_mutex); 3879 3880 /* 3881 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3882 * to allow the device attach to occur when the device is 3883 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3884 * from the scsi_probe()). 3885 */ 3886 mutex_enter(&LUN_TGT->tgt_mutex); 3887 plun->lun_state |= FCP_LUN_ONLINING; 3888 mutex_exit(&LUN_TGT->tgt_mutex); 3889 3890 if (is_mpxio) 3891 mdi_devi_exit(pptr->port_dip, circ); 3892 else 3893 ndi_devi_exit(pptr->port_dip, circ); 3894 devi_entered = 0; 3895 3896 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3897 FCP_ONLINE, lcount, tcount, 0); 3898 3899 if (*rval != NDI_SUCCESS) { 3900 /* Reset the FCP_LUN_ONLINING bit */ 3901 mutex_enter(&LUN_TGT->tgt_mutex); 3902 plun->lun_state &= ~FCP_LUN_ONLINING; 3903 mutex_exit(&LUN_TGT->tgt_mutex); 3904 *rval = EIO; 3905 break; 3906 } 3907 mutex_enter(&LUN_TGT->tgt_mutex); 3908 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3909 FCP_LUN_ONLINING); 3910 mutex_exit(&LUN_TGT->tgt_mutex); 3911 break; 3912 } 3913 3914 case DEVCTL_BUS_DEV_CREATE: { 3915 uchar_t *bytes = NULL; 3916 uint_t nbytes; 3917 struct fcp_tgt *ptgt = NULL; 3918 struct fcp_lun *plun = NULL; 3919 dev_info_t *useless_dip = NULL; 3920 3921 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3922 DEVCTL_CONSTRUCT, &useless_dip); 3923 if (*rval != 0 || useless_dip == NULL) { 3924 break; 3925 } 3926 3927 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3928 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3929 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3930 *rval = EINVAL; 3931 (void) ndi_devi_free(useless_dip); 3932 if (bytes != NULL) { 3933 ddi_prop_free(bytes); 3934 } 3935 break; 3936 } 3937 3938 *rval = fcp_create_on_demand(pptr, bytes); 3939 if (*rval == 0) { 3940 mutex_enter(&pptr->port_mutex); 3941 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 3942 if (ptgt) { 3943 /* 3944 * We now have a pointer to the target that 3945 * was created. Lets point to the first LUN on 3946 * this new target. 3947 */ 3948 mutex_enter(&ptgt->tgt_mutex); 3949 3950 plun = ptgt->tgt_lun; 3951 /* 3952 * There may be stale/offline LUN entries on 3953 * this list (this is by design) and so we have 3954 * to make sure we point to the first online 3955 * LUN 3956 */ 3957 while (plun && 3958 plun->lun_state & FCP_LUN_OFFLINE) { 3959 plun = plun->lun_next; 3960 } 3961 3962 mutex_exit(&ptgt->tgt_mutex); 3963 } 3964 mutex_exit(&pptr->port_mutex); 3965 } 3966 3967 if (*rval == 0 && ptgt && plun) { 3968 mutex_enter(&plun->lun_mutex); 3969 /* 3970 * Allow up to fcp_lun_ready_retry seconds to 3971 * configure all the luns behind the target. 3972 * 3973 * The intent here is to allow targets with long 3974 * reboot/reset-recovery times to become available 3975 * while limiting the maximum wait time for an 3976 * unresponsive target. 3977 */ 3978 end_time = ddi_get_lbolt() + 3979 SEC_TO_TICK(fcp_lun_ready_retry); 3980 3981 while (ddi_get_lbolt() < end_time) { 3982 retval = FC_SUCCESS; 3983 3984 /* 3985 * The new ndi interfaces for on-demand creation 3986 * are inflexible, Do some more work to pass on 3987 * a path name of some LUN (design is broken !) 3988 */ 3989 if (plun->lun_cip) { 3990 if (plun->lun_mpxio == 0) { 3991 cdip = DIP(plun->lun_cip); 3992 } else { 3993 cdip = mdi_pi_get_client( 3994 PIP(plun->lun_cip)); 3995 } 3996 if (cdip == NULL) { 3997 *rval = ENXIO; 3998 break; 3999 } 4000 4001 if (!i_ddi_devi_attached(cdip)) { 4002 mutex_exit(&plun->lun_mutex); 4003 delay(drv_usectohz(1000000)); 4004 mutex_enter(&plun->lun_mutex); 4005 } else { 4006 /* 4007 * This Lun is ready, lets 4008 * check the next one. 4009 */ 4010 mutex_exit(&plun->lun_mutex); 4011 plun = plun->lun_next; 4012 while (plun && (plun->lun_state 4013 & FCP_LUN_OFFLINE)) { 4014 plun = plun->lun_next; 4015 } 4016 if (!plun) { 4017 break; 4018 } 4019 mutex_enter(&plun->lun_mutex); 4020 } 4021 } else { 4022 /* 4023 * lun_cip field for a valid lun 4024 * should never be NULL. Fail the 4025 * command. 4026 */ 4027 *rval = ENXIO; 4028 break; 4029 } 4030 } 4031 if (plun) { 4032 mutex_exit(&plun->lun_mutex); 4033 } else { 4034 char devnm[MAXNAMELEN]; 4035 int nmlen; 4036 4037 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4038 ddi_node_name(cdip), 4039 ddi_get_name_addr(cdip)); 4040 4041 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4042 0) { 4043 *rval = EFAULT; 4044 } 4045 } 4046 } else { 4047 int i; 4048 char buf[25]; 4049 4050 for (i = 0; i < FC_WWN_SIZE; i++) { 4051 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4052 } 4053 4054 fcp_log(CE_WARN, pptr->port_dip, 4055 "!Failed to create nodes for pwwn=%s; error=%x", 4056 buf, *rval); 4057 } 4058 4059 (void) ndi_devi_free(useless_dip); 4060 ddi_prop_free(bytes); 4061 break; 4062 } 4063 4064 case DEVCTL_DEVICE_RESET: { 4065 struct fcp_lun *plun; 4066 struct scsi_address ap; 4067 child_info_t *cip = CIP(cdip); 4068 4069 ASSERT(cdip != NULL); 4070 ASSERT(pptr != NULL); 4071 mutex_enter(&pptr->port_mutex); 4072 if (pip != NULL) { 4073 cip = CIP(pip); 4074 } 4075 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4076 mutex_exit(&pptr->port_mutex); 4077 *rval = ENXIO; 4078 break; 4079 } 4080 mutex_exit(&pptr->port_mutex); 4081 4082 mutex_enter(&plun->lun_tgt->tgt_mutex); 4083 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4084 mutex_exit(&plun->lun_tgt->tgt_mutex); 4085 *rval = ENXIO; 4086 break; 4087 } 4088 ap.a_hba_tran = plun->lun_tran; 4089 ASSERT(pptr->port_tran != NULL); 4090 mutex_exit(&plun->lun_tgt->tgt_mutex); 4091 4092 /* 4093 * There is a chance lun_tran is NULL at this point. So check 4094 * for it. If it is NULL, it basically means that the tgt has 4095 * been freed. So, just return a "No such device or address" 4096 * error. 4097 */ 4098 if (ap.a_hba_tran == NULL) { 4099 *rval = ENXIO; 4100 break; 4101 } 4102 4103 /* 4104 * set up ap so that fcp_reset can figure out 4105 * which target to reset 4106 */ 4107 if (fcp_scsi_reset(&ap, RESET_TARGET) == FALSE) { 4108 *rval = EIO; 4109 } 4110 break; 4111 } 4112 4113 case DEVCTL_BUS_GETSTATE: 4114 ASSERT(dcp != NULL); 4115 ASSERT(pptr != NULL); 4116 ASSERT(pptr->port_dip != NULL); 4117 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4118 NDI_SUCCESS) { 4119 *rval = EFAULT; 4120 } 4121 break; 4122 4123 case DEVCTL_BUS_QUIESCE: 4124 case DEVCTL_BUS_UNQUIESCE: 4125 *rval = ENOTSUP; 4126 break; 4127 4128 case DEVCTL_BUS_RESET: 4129 case DEVCTL_BUS_RESETALL: 4130 ASSERT(pptr != NULL); 4131 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4132 break; 4133 4134 default: 4135 ASSERT(dcp != NULL); 4136 *rval = ENOTTY; 4137 break; 4138 } 4139 4140 /* all done -- clean up and return */ 4141 out: if (devi_entered) { 4142 if (is_mpxio) 4143 mdi_devi_exit(pptr->port_dip, circ); 4144 else 4145 ndi_devi_exit(pptr->port_dip, circ); 4146 } 4147 4148 if (dcp != NULL) { 4149 ndi_dc_freehdl(dcp); 4150 } 4151 4152 return (retval); 4153 } 4154 4155 4156 /*ARGSUSED*/ 4157 static int 4158 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4159 uint32_t claimed) 4160 { 4161 uchar_t r_ctl; 4162 uchar_t ls_code; 4163 struct fcp_port *pptr; 4164 4165 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4166 return (FC_UNCLAIMED); 4167 } 4168 4169 mutex_enter(&pptr->port_mutex); 4170 if (pptr->port_state & (FCP_STATE_DETACHING | 4171 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4172 mutex_exit(&pptr->port_mutex); 4173 return (FC_UNCLAIMED); 4174 } 4175 mutex_exit(&pptr->port_mutex); 4176 4177 r_ctl = buf->ub_frame.r_ctl; 4178 4179 switch (r_ctl & R_CTL_ROUTING) { 4180 case R_CTL_EXTENDED_SVC: 4181 if (r_ctl == R_CTL_ELS_REQ) { 4182 ls_code = buf->ub_buffer[0]; 4183 4184 switch (ls_code) { 4185 case LA_ELS_PRLI: 4186 /* 4187 * We really don't care if something fails. 4188 * If the PRLI was not sent out, then the 4189 * other end will time it out. 4190 */ 4191 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4192 return (FC_SUCCESS); 4193 } 4194 return (FC_UNCLAIMED); 4195 /* NOTREACHED */ 4196 4197 default: 4198 break; 4199 } 4200 } 4201 /* FALLTHROUGH */ 4202 4203 default: 4204 return (FC_UNCLAIMED); 4205 } 4206 } 4207 4208 4209 /*ARGSUSED*/ 4210 static int 4211 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4212 uint32_t claimed) 4213 { 4214 return (FC_UNCLAIMED); 4215 } 4216 4217 /* 4218 * Function: fcp_statec_callback 4219 * 4220 * Description: The purpose of this function is to handle a port state change. 4221 * It is called from fp/fctl and, in a few instances, internally. 4222 * 4223 * Argument: ulph fp/fctl port handle 4224 * port_handle fcp_port structure 4225 * port_state Physical state of the port 4226 * port_top Topology 4227 * *devlist Pointer to the first entry of a table 4228 * containing the remote ports that can be 4229 * reached. 4230 * dev_cnt Number of entries pointed by devlist. 4231 * port_sid Port ID of the local port. 4232 * 4233 * Return Value: None 4234 */ 4235 /*ARGSUSED*/ 4236 static void 4237 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4238 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4239 uint32_t dev_cnt, uint32_t port_sid) 4240 { 4241 uint32_t link_count; 4242 int map_len = 0; 4243 struct fcp_port *pptr; 4244 fcp_map_tag_t *map_tag = NULL; 4245 4246 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4247 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4248 return; /* nothing to work with! */ 4249 } 4250 4251 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4252 fcp_trace, FCP_BUF_LEVEL_2, 0, 4253 "fcp_statec_callback: port state/dev_cnt/top =" 4254 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4255 dev_cnt, port_top); 4256 4257 mutex_enter(&pptr->port_mutex); 4258 4259 /* 4260 * If a thread is in detach, don't do anything. 4261 */ 4262 if (pptr->port_state & (FCP_STATE_DETACHING | 4263 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4264 mutex_exit(&pptr->port_mutex); 4265 return; 4266 } 4267 4268 /* 4269 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4270 * init_pkt is called, it knows whether or not the target's status 4271 * (or pd) might be changing. 4272 */ 4273 4274 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4275 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4276 } 4277 4278 /* 4279 * the transport doesn't allocate or probe unless being 4280 * asked to by either the applications or ULPs 4281 * 4282 * in cases where the port is OFFLINE at the time of port 4283 * attach callback and the link comes ONLINE later, for 4284 * easier automatic node creation (i.e. without you having to 4285 * go out and run the utility to perform LOGINs) the 4286 * following conditional is helpful 4287 */ 4288 pptr->port_phys_state = port_state; 4289 4290 if (dev_cnt) { 4291 mutex_exit(&pptr->port_mutex); 4292 4293 map_len = sizeof (*map_tag) * dev_cnt; 4294 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4295 if (map_tag == NULL) { 4296 fcp_log(CE_WARN, pptr->port_dip, 4297 "!fcp%d: failed to allocate for map tags; " 4298 " state change will not be processed", 4299 pptr->port_instance); 4300 4301 mutex_enter(&pptr->port_mutex); 4302 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4303 mutex_exit(&pptr->port_mutex); 4304 4305 return; 4306 } 4307 4308 mutex_enter(&pptr->port_mutex); 4309 } 4310 4311 if (pptr->port_id != port_sid) { 4312 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4313 fcp_trace, FCP_BUF_LEVEL_3, 0, 4314 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4315 port_sid); 4316 /* 4317 * The local port changed ID. It is the first time a port ID 4318 * is assigned or something drastic happened. We might have 4319 * been unplugged and replugged on another loop or fabric port 4320 * or somebody grabbed the AL_PA we had or somebody rezoned 4321 * the fabric we were plugged into. 4322 */ 4323 pptr->port_id = port_sid; 4324 } 4325 4326 switch (FC_PORT_STATE_MASK(port_state)) { 4327 case FC_STATE_OFFLINE: 4328 case FC_STATE_RESET_REQUESTED: 4329 /* 4330 * link has gone from online to offline -- just update the 4331 * state of this port to BUSY and MARKed to go offline 4332 */ 4333 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4334 fcp_trace, FCP_BUF_LEVEL_3, 0, 4335 "link went offline"); 4336 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4337 /* 4338 * We were offline a while ago and this one 4339 * seems to indicate that the loop has gone 4340 * dead forever. 4341 */ 4342 pptr->port_tmp_cnt += dev_cnt; 4343 pptr->port_state &= ~FCP_STATE_OFFLINE; 4344 pptr->port_state |= FCP_STATE_INIT; 4345 link_count = pptr->port_link_cnt; 4346 fcp_handle_devices(pptr, devlist, dev_cnt, 4347 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4348 } else { 4349 pptr->port_link_cnt++; 4350 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4351 fcp_update_state(pptr, (FCP_LUN_BUSY | 4352 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4353 if (pptr->port_mpxio) { 4354 fcp_update_mpxio_path_verifybusy(pptr); 4355 } 4356 pptr->port_state |= FCP_STATE_OFFLINE; 4357 pptr->port_state &= 4358 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4359 pptr->port_tmp_cnt = 0; 4360 } 4361 mutex_exit(&pptr->port_mutex); 4362 break; 4363 4364 case FC_STATE_ONLINE: 4365 case FC_STATE_LIP: 4366 case FC_STATE_LIP_LBIT_SET: 4367 /* 4368 * link has gone from offline to online 4369 */ 4370 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4371 fcp_trace, FCP_BUF_LEVEL_3, 0, 4372 "link went online"); 4373 4374 pptr->port_link_cnt++; 4375 4376 while (pptr->port_ipkt_cnt) { 4377 mutex_exit(&pptr->port_mutex); 4378 delay(drv_usectohz(1000000)); 4379 mutex_enter(&pptr->port_mutex); 4380 } 4381 4382 pptr->port_topology = port_top; 4383 4384 /* 4385 * The state of the targets and luns accessible through this 4386 * port is updated. 4387 */ 4388 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4389 FCP_CAUSE_LINK_CHANGE); 4390 4391 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4392 pptr->port_state |= FCP_STATE_ONLINING; 4393 pptr->port_tmp_cnt = dev_cnt; 4394 link_count = pptr->port_link_cnt; 4395 4396 pptr->port_deadline = fcp_watchdog_time + 4397 FCP_ICMD_DEADLINE; 4398 4399 if (!dev_cnt) { 4400 /* 4401 * We go directly to the online state if no remote 4402 * ports were discovered. 4403 */ 4404 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4405 fcp_trace, FCP_BUF_LEVEL_3, 0, 4406 "No remote ports discovered"); 4407 4408 pptr->port_state &= ~FCP_STATE_ONLINING; 4409 pptr->port_state |= FCP_STATE_ONLINE; 4410 } 4411 4412 switch (port_top) { 4413 case FC_TOP_FABRIC: 4414 case FC_TOP_PUBLIC_LOOP: 4415 case FC_TOP_PRIVATE_LOOP: 4416 case FC_TOP_PT_PT: 4417 4418 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4419 fcp_retry_ns_registry(pptr, port_sid); 4420 } 4421 4422 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4423 map_tag, FCP_CAUSE_LINK_CHANGE); 4424 break; 4425 4426 default: 4427 /* 4428 * We got here because we were provided with an unknown 4429 * topology. 4430 */ 4431 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4432 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4433 } 4434 4435 pptr->port_tmp_cnt -= dev_cnt; 4436 fcp_log(CE_WARN, pptr->port_dip, 4437 "!unknown/unsupported topology (0x%x)", port_top); 4438 break; 4439 } 4440 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4441 fcp_trace, FCP_BUF_LEVEL_3, 0, 4442 "Notify ssd of the reset to reinstate the reservations"); 4443 4444 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4445 &pptr->port_reset_notify_listf); 4446 4447 mutex_exit(&pptr->port_mutex); 4448 4449 break; 4450 4451 case FC_STATE_RESET: 4452 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4453 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4454 fcp_trace, FCP_BUF_LEVEL_3, 0, 4455 "RESET state, waiting for Offline/Online state_cb"); 4456 mutex_exit(&pptr->port_mutex); 4457 break; 4458 4459 case FC_STATE_DEVICE_CHANGE: 4460 /* 4461 * We come here when an application has requested 4462 * Dynamic node creation/deletion in Fabric connectivity. 4463 */ 4464 if (pptr->port_state & (FCP_STATE_OFFLINE | 4465 FCP_STATE_INIT)) { 4466 /* 4467 * This case can happen when the FCTL is in the 4468 * process of giving us on online and the host on 4469 * the other side issues a PLOGI/PLOGO. Ideally 4470 * the state changes should be serialized unless 4471 * they are opposite (online-offline). 4472 * The transport will give us a final state change 4473 * so we can ignore this for the time being. 4474 */ 4475 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4476 mutex_exit(&pptr->port_mutex); 4477 break; 4478 } 4479 4480 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4481 fcp_retry_ns_registry(pptr, port_sid); 4482 } 4483 4484 /* 4485 * Extend the deadline under steady state conditions 4486 * to provide more time for the device-change-commands 4487 */ 4488 if (!pptr->port_ipkt_cnt) { 4489 pptr->port_deadline = fcp_watchdog_time + 4490 FCP_ICMD_DEADLINE; 4491 } 4492 4493 /* 4494 * There is another race condition here, where if we were 4495 * in ONLINEING state and a devices in the map logs out, 4496 * fp will give another state change as DEVICE_CHANGE 4497 * and OLD. This will result in that target being offlined. 4498 * The pd_handle is freed. If from the first statec callback 4499 * we were going to fire a PLOGI/PRLI, the system will 4500 * panic in fc_ulp_transport with invalid pd_handle. 4501 * The fix is to check for the link_cnt before issuing 4502 * any command down. 4503 */ 4504 fcp_update_targets(pptr, devlist, dev_cnt, 4505 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4506 4507 link_count = pptr->port_link_cnt; 4508 4509 fcp_handle_devices(pptr, devlist, dev_cnt, 4510 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4511 4512 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4513 4514 mutex_exit(&pptr->port_mutex); 4515 break; 4516 4517 case FC_STATE_TARGET_PORT_RESET: 4518 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4519 fcp_retry_ns_registry(pptr, port_sid); 4520 } 4521 4522 /* Do nothing else */ 4523 mutex_exit(&pptr->port_mutex); 4524 break; 4525 4526 default: 4527 fcp_log(CE_WARN, pptr->port_dip, 4528 "!Invalid state change=0x%x", port_state); 4529 mutex_exit(&pptr->port_mutex); 4530 break; 4531 } 4532 4533 if (map_tag) { 4534 kmem_free(map_tag, map_len); 4535 } 4536 } 4537 4538 /* 4539 * Function: fcp_handle_devices 4540 * 4541 * Description: This function updates the devices currently known by 4542 * walking the list provided by the caller. The list passed 4543 * by the caller is supposed to be the list of reachable 4544 * devices. 4545 * 4546 * Argument: *pptr Fcp port structure. 4547 * *devlist Pointer to the first entry of a table 4548 * containing the remote ports that can be 4549 * reached. 4550 * dev_cnt Number of entries pointed by devlist. 4551 * link_cnt Link state count. 4552 * *map_tag Array of fcp_map_tag_t structures. 4553 * cause What caused this function to be called. 4554 * 4555 * Return Value: None 4556 * 4557 * Notes: The pptr->port_mutex must be held. 4558 */ 4559 static void 4560 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4561 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4562 { 4563 int i; 4564 int check_finish_init = 0; 4565 fc_portmap_t *map_entry; 4566 struct fcp_tgt *ptgt = NULL; 4567 4568 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4569 fcp_trace, FCP_BUF_LEVEL_3, 0, 4570 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4571 4572 if (dev_cnt) { 4573 ASSERT(map_tag != NULL); 4574 } 4575 4576 /* 4577 * The following code goes through the list of remote ports that are 4578 * accessible through this (pptr) local port (The list walked is the 4579 * one provided by the caller which is the list of the remote ports 4580 * currently reachable). It checks if any of them was already 4581 * known by looking for the corresponding target structure based on 4582 * the world wide name. If a target is part of the list it is tagged 4583 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4584 * 4585 * Old comment 4586 * ----------- 4587 * Before we drop port mutex; we MUST get the tags updated; This 4588 * two step process is somewhat slow, but more reliable. 4589 */ 4590 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4591 map_entry = &(devlist[i]); 4592 4593 /* 4594 * get ptr to this map entry in our port's 4595 * list (if any) 4596 */ 4597 ptgt = fcp_lookup_target(pptr, 4598 (uchar_t *)&(map_entry->map_pwwn)); 4599 4600 if (ptgt) { 4601 map_tag[i] = ptgt->tgt_change_cnt; 4602 if (cause == FCP_CAUSE_LINK_CHANGE) { 4603 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4604 } 4605 } 4606 } 4607 4608 /* 4609 * At this point we know which devices of the new list were already 4610 * known (The field tgt_aux_state of the target structure has been 4611 * set to FCP_TGT_TAGGED). 4612 * 4613 * The following code goes through the list of targets currently known 4614 * by the local port (the list is actually a hashing table). If a 4615 * target is found and is not tagged, it means the target cannot 4616 * be reached anymore through the local port (pptr). It is offlined. 4617 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4618 */ 4619 for (i = 0; i < FCP_NUM_HASH; i++) { 4620 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4621 ptgt = ptgt->tgt_next) { 4622 mutex_enter(&ptgt->tgt_mutex); 4623 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4624 (cause == FCP_CAUSE_LINK_CHANGE) && 4625 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4626 fcp_offline_target_now(pptr, ptgt, 4627 link_cnt, ptgt->tgt_change_cnt, 0); 4628 } 4629 mutex_exit(&ptgt->tgt_mutex); 4630 } 4631 } 4632 4633 /* 4634 * At this point, the devices that were known but cannot be reached 4635 * anymore, have most likely been offlined. 4636 * 4637 * The following section of code seems to go through the list of 4638 * remote ports that can now be reached. For every single one it 4639 * checks if it is already known or if it is a new port. 4640 */ 4641 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4642 4643 if (check_finish_init) { 4644 ASSERT(i > 0); 4645 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4646 map_tag[i - 1], cause); 4647 check_finish_init = 0; 4648 } 4649 4650 /* get a pointer to this map entry */ 4651 map_entry = &(devlist[i]); 4652 4653 /* 4654 * Check for the duplicate map entry flag. If we have marked 4655 * this entry as a duplicate we skip it since the correct 4656 * (perhaps even same) state change will be encountered 4657 * later in the list. 4658 */ 4659 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) 4660 continue; 4661 4662 /* get ptr to this map entry in our port's list (if any) */ 4663 ptgt = fcp_lookup_target(pptr, 4664 (uchar_t *)&(map_entry->map_pwwn)); 4665 4666 if (ptgt) { 4667 /* 4668 * This device was already known. The field 4669 * tgt_aux_state is reset (was probably set to 4670 * FCP_TGT_TAGGED previously in this routine). 4671 */ 4672 ptgt->tgt_aux_state = 0; 4673 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4674 fcp_trace, FCP_BUF_LEVEL_3, 0, 4675 "handle_devices: map did/state/type/flags = " 4676 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4677 "tgt_state=%d", 4678 map_entry->map_did.port_id, map_entry->map_state, 4679 map_entry->map_type, map_entry->map_flags, 4680 ptgt->tgt_d_id, ptgt->tgt_state); 4681 } 4682 4683 if (map_entry->map_type == PORT_DEVICE_OLD || 4684 map_entry->map_type == PORT_DEVICE_NEW || 4685 map_entry->map_type == PORT_DEVICE_CHANGED) { 4686 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4687 fcp_trace, FCP_BUF_LEVEL_2, 0, 4688 "map_type=%x, did = %x", 4689 map_entry->map_type, 4690 map_entry->map_did.port_id); 4691 } 4692 4693 switch (map_entry->map_type) { 4694 case PORT_DEVICE_NOCHANGE: 4695 case PORT_DEVICE_USER_CREATE: 4696 case PORT_DEVICE_USER_LOGIN: 4697 case PORT_DEVICE_NEW: 4698 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4699 4700 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4701 link_cnt, (ptgt) ? map_tag[i] : 0, 4702 cause) == TRUE) { 4703 4704 FCP_TGT_TRACE(ptgt, map_tag[i], 4705 FCP_TGT_TRACE_2); 4706 check_finish_init++; 4707 } 4708 break; 4709 4710 case PORT_DEVICE_OLD: 4711 if (ptgt != NULL) { 4712 FCP_TGT_TRACE(ptgt, map_tag[i], 4713 FCP_TGT_TRACE_3); 4714 4715 mutex_enter(&ptgt->tgt_mutex); 4716 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4717 /* 4718 * Must do an in-line wait for I/Os 4719 * to get drained 4720 */ 4721 mutex_exit(&ptgt->tgt_mutex); 4722 mutex_exit(&pptr->port_mutex); 4723 4724 mutex_enter(&ptgt->tgt_mutex); 4725 while (ptgt->tgt_ipkt_cnt || 4726 fcp_outstanding_lun_cmds(ptgt) 4727 == FC_SUCCESS) { 4728 mutex_exit(&ptgt->tgt_mutex); 4729 delay(drv_usectohz(1000000)); 4730 mutex_enter(&ptgt->tgt_mutex); 4731 } 4732 mutex_exit(&ptgt->tgt_mutex); 4733 4734 mutex_enter(&pptr->port_mutex); 4735 mutex_enter(&ptgt->tgt_mutex); 4736 4737 (void) fcp_offline_target(pptr, ptgt, 4738 link_cnt, map_tag[i], 0, 0); 4739 } 4740 mutex_exit(&ptgt->tgt_mutex); 4741 } 4742 check_finish_init++; 4743 break; 4744 4745 case PORT_DEVICE_USER_DELETE: 4746 case PORT_DEVICE_USER_LOGOUT: 4747 if (ptgt != NULL) { 4748 FCP_TGT_TRACE(ptgt, map_tag[i], 4749 FCP_TGT_TRACE_4); 4750 4751 mutex_enter(&ptgt->tgt_mutex); 4752 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4753 (void) fcp_offline_target(pptr, ptgt, 4754 link_cnt, map_tag[i], 1, 0); 4755 } 4756 mutex_exit(&ptgt->tgt_mutex); 4757 } 4758 check_finish_init++; 4759 break; 4760 4761 case PORT_DEVICE_CHANGED: 4762 if (ptgt != NULL) { 4763 FCP_TGT_TRACE(ptgt, map_tag[i], 4764 FCP_TGT_TRACE_5); 4765 4766 if (fcp_device_changed(pptr, ptgt, 4767 map_entry, link_cnt, map_tag[i], 4768 cause) == TRUE) { 4769 check_finish_init++; 4770 } 4771 } else { 4772 if (fcp_handle_mapflags(pptr, ptgt, 4773 map_entry, link_cnt, 0, cause) == TRUE) { 4774 check_finish_init++; 4775 } 4776 } 4777 break; 4778 4779 default: 4780 fcp_log(CE_WARN, pptr->port_dip, 4781 "!Invalid map_type=0x%x", map_entry->map_type); 4782 check_finish_init++; 4783 break; 4784 } 4785 } 4786 4787 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4788 ASSERT(i > 0); 4789 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4790 map_tag[i-1], cause); 4791 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4792 fcp_offline_all(pptr, link_cnt, cause); 4793 } 4794 } 4795 4796 /* 4797 * Function: fcp_handle_mapflags 4798 * 4799 * Description: This function creates a target structure if the ptgt passed 4800 * is NULL. It also kicks off the PLOGI if we are not logged 4801 * into the target yet or the PRLI if we are logged into the 4802 * target already. The rest of the treatment is done in the 4803 * callbacks of the PLOGI or PRLI. 4804 * 4805 * Argument: *pptr FCP Port structure. 4806 * *ptgt Target structure. 4807 * *map_entry Array of fc_portmap_t structures. 4808 * link_cnt Link state count. 4809 * tgt_cnt Target state count. 4810 * cause What caused this function to be called. 4811 * 4812 * Return Value: TRUE Failed 4813 * FALSE Succeeded 4814 * 4815 * Notes: pptr->port_mutex must be owned. 4816 */ 4817 static int 4818 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4819 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4820 { 4821 int lcount; 4822 int tcount; 4823 int ret = TRUE; 4824 int alloc; 4825 struct fcp_ipkt *icmd; 4826 struct fcp_lun *pseq_lun = NULL; 4827 uchar_t opcode; 4828 int valid_ptgt_was_passed = FALSE; 4829 4830 ASSERT(mutex_owned(&pptr->port_mutex)); 4831 4832 /* 4833 * This case is possible where the FCTL has come up and done discovery 4834 * before FCP was loaded and attached. FCTL would have discovered the 4835 * devices and later the ULP came online. In this case ULP's would get 4836 * PORT_DEVICE_NOCHANGE but target would be NULL. 4837 */ 4838 if (ptgt == NULL) { 4839 /* don't already have a target */ 4840 mutex_exit(&pptr->port_mutex); 4841 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4842 mutex_enter(&pptr->port_mutex); 4843 4844 if (ptgt == NULL) { 4845 fcp_log(CE_WARN, pptr->port_dip, 4846 "!FC target allocation failed"); 4847 return (ret); 4848 } 4849 mutex_enter(&ptgt->tgt_mutex); 4850 ptgt->tgt_statec_cause = cause; 4851 ptgt->tgt_tmp_cnt = 1; 4852 mutex_exit(&ptgt->tgt_mutex); 4853 } else { 4854 valid_ptgt_was_passed = TRUE; 4855 } 4856 4857 /* 4858 * Copy in the target parameters 4859 */ 4860 mutex_enter(&ptgt->tgt_mutex); 4861 ptgt->tgt_d_id = map_entry->map_did.port_id; 4862 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4863 ptgt->tgt_pd_handle = map_entry->map_pd; 4864 ptgt->tgt_fca_dev = NULL; 4865 4866 /* Copy port and node WWNs */ 4867 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4868 FC_WWN_SIZE); 4869 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4870 FC_WWN_SIZE); 4871 4872 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4873 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4874 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4875 valid_ptgt_was_passed) { 4876 /* 4877 * determine if there are any tape LUNs on this target 4878 */ 4879 for (pseq_lun = ptgt->tgt_lun; 4880 pseq_lun != NULL; 4881 pseq_lun = pseq_lun->lun_next) { 4882 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4883 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4884 fcp_update_tgt_state(ptgt, FCP_RESET, 4885 FCP_LUN_MARK); 4886 mutex_exit(&ptgt->tgt_mutex); 4887 return (ret); 4888 } 4889 } 4890 } 4891 4892 /* 4893 * If ptgt was NULL when this function was entered, then tgt_node_state 4894 * was never specifically initialized but zeroed out which means 4895 * FCP_TGT_NODE_NONE. 4896 */ 4897 switch (ptgt->tgt_node_state) { 4898 case FCP_TGT_NODE_NONE: 4899 case FCP_TGT_NODE_ON_DEMAND: 4900 if (FC_TOP_EXTERNAL(pptr->port_topology) && 4901 !fcp_enable_auto_configuration && 4902 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 4903 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 4904 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 4905 fcp_enable_auto_configuration && 4906 (ptgt->tgt_manual_config_only == 1) && 4907 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 4908 /* 4909 * If auto configuration is set and 4910 * the tgt_manual_config_only flag is set then 4911 * we only want the user to be able to change 4912 * the state through create_on_demand. 4913 */ 4914 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 4915 } else { 4916 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 4917 } 4918 break; 4919 4920 case FCP_TGT_NODE_PRESENT: 4921 break; 4922 } 4923 /* 4924 * If we are booting from a fabric device, make sure we 4925 * mark the node state appropriately for this target to be 4926 * enumerated 4927 */ 4928 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 4929 if (bcmp((caddr_t)pptr->port_boot_wwn, 4930 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 4931 sizeof (ptgt->tgt_port_wwn)) == 0) { 4932 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 4933 } 4934 } 4935 mutex_exit(&ptgt->tgt_mutex); 4936 4937 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4938 fcp_trace, FCP_BUF_LEVEL_3, 0, 4939 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 4940 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 4941 map_entry->map_rscn_info.ulp_rscn_count); 4942 4943 mutex_enter(&ptgt->tgt_mutex); 4944 4945 /* 4946 * Reset target OFFLINE state and mark the target BUSY 4947 */ 4948 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 4949 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 4950 4951 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 4952 lcount = link_cnt; 4953 4954 mutex_exit(&ptgt->tgt_mutex); 4955 mutex_exit(&pptr->port_mutex); 4956 4957 /* 4958 * if we are already logged in, then we do a PRLI, else 4959 * we do a PLOGI first (to get logged in) 4960 * 4961 * We will not check if we are the PLOGI initiator 4962 */ 4963 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 4964 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 4965 4966 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 4967 4968 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0, lcount, tcount, 4969 cause, map_entry->map_rscn_info.ulp_rscn_count); 4970 4971 if (icmd == NULL) { 4972 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 4973 /* 4974 * We've exited port_mutex before calling fcp_icmd_alloc, 4975 * we need to make sure we reacquire it before returning. 4976 */ 4977 mutex_enter(&pptr->port_mutex); 4978 return (FALSE); 4979 } 4980 4981 /* TRUE is only returned while target is intended skipped */ 4982 ret = FALSE; 4983 /* discover info about this target */ 4984 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 4985 lcount, tcount, cause)) == DDI_SUCCESS) { 4986 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 4987 } else { 4988 fcp_icmd_free(pptr, icmd); 4989 ret = TRUE; 4990 } 4991 mutex_enter(&pptr->port_mutex); 4992 4993 return (ret); 4994 } 4995 4996 /* 4997 * Function: fcp_send_els 4998 * 4999 * Description: Sends an ELS to the target specified by the caller. Supports 5000 * PLOGI and PRLI. 5001 * 5002 * Argument: *pptr Fcp port. 5003 * *ptgt Target to send the ELS to. 5004 * *icmd Internal packet 5005 * opcode ELS opcode 5006 * lcount Link state change counter 5007 * tcount Target state change counter 5008 * cause What caused the call 5009 * 5010 * Return Value: DDI_SUCCESS 5011 * Others 5012 */ 5013 static int 5014 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5015 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5016 { 5017 fc_packet_t *fpkt; 5018 fc_frame_hdr_t *hp; 5019 int internal = 0; 5020 int alloc; 5021 int cmd_len; 5022 int resp_len; 5023 int res = DDI_FAILURE; /* default result */ 5024 int rval = DDI_FAILURE; 5025 5026 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5027 ASSERT(ptgt->tgt_port == pptr); 5028 5029 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5030 fcp_trace, FCP_BUF_LEVEL_5, 0, 5031 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5032 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5033 5034 if (opcode == LA_ELS_PLOGI) { 5035 cmd_len = sizeof (la_els_logi_t); 5036 resp_len = sizeof (la_els_logi_t); 5037 } else { 5038 ASSERT(opcode == LA_ELS_PRLI); 5039 cmd_len = sizeof (la_els_prli_t); 5040 resp_len = sizeof (la_els_prli_t); 5041 } 5042 5043 if (icmd == NULL) { 5044 alloc = FCP_MAX(sizeof (la_els_logi_t), 5045 sizeof (la_els_prli_t)); 5046 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0, 5047 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5048 if (icmd == NULL) { 5049 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5050 return (res); 5051 } 5052 internal++; 5053 } 5054 fpkt = icmd->ipkt_fpkt; 5055 5056 fpkt->pkt_cmdlen = cmd_len; 5057 fpkt->pkt_rsplen = resp_len; 5058 fpkt->pkt_datalen = 0; 5059 icmd->ipkt_retries = 0; 5060 5061 /* fill in fpkt info */ 5062 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5063 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5064 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5065 5066 /* get ptr to frame hdr in fpkt */ 5067 hp = &fpkt->pkt_cmd_fhdr; 5068 5069 /* 5070 * fill in frame hdr 5071 */ 5072 hp->r_ctl = R_CTL_ELS_REQ; 5073 hp->s_id = pptr->port_id; /* source ID */ 5074 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5075 hp->type = FC_TYPE_EXTENDED_LS; 5076 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5077 hp->seq_id = 0; 5078 hp->rsvd = 0; 5079 hp->df_ctl = 0; 5080 hp->seq_cnt = 0; 5081 hp->ox_id = 0xffff; /* i.e. none */ 5082 hp->rx_id = 0xffff; /* i.e. none */ 5083 hp->ro = 0; 5084 5085 /* 5086 * at this point we have a filled in cmd pkt 5087 * 5088 * fill in the respective info, then use the transport to send 5089 * the packet 5090 * 5091 * for a PLOGI call fc_ulp_login(), and 5092 * for a PRLI call fc_ulp_issue_els() 5093 */ 5094 switch (opcode) { 5095 case LA_ELS_PLOGI: { 5096 struct la_els_logi logi; 5097 5098 bzero(&logi, sizeof (struct la_els_logi)); 5099 5100 hp = &fpkt->pkt_cmd_fhdr; 5101 hp->r_ctl = R_CTL_ELS_REQ; 5102 logi.ls_code.ls_code = LA_ELS_PLOGI; 5103 logi.ls_code.mbz = 0; 5104 5105 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5106 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5107 5108 icmd->ipkt_opcode = LA_ELS_PLOGI; 5109 5110 mutex_enter(&pptr->port_mutex); 5111 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5112 5113 mutex_exit(&pptr->port_mutex); 5114 5115 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5116 if (rval == FC_SUCCESS) { 5117 res = DDI_SUCCESS; 5118 break; 5119 } 5120 5121 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5122 5123 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5124 rval, "PLOGI"); 5125 } else { 5126 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5127 fcp_trace, FCP_BUF_LEVEL_5, 0, 5128 "fcp_send_els1: state change occured" 5129 " for D_ID=0x%x", ptgt->tgt_d_id); 5130 mutex_exit(&pptr->port_mutex); 5131 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5132 } 5133 break; 5134 } 5135 5136 case LA_ELS_PRLI: { 5137 struct la_els_prli prli; 5138 struct fcp_prli *fprli; 5139 5140 bzero(&prli, sizeof (struct la_els_prli)); 5141 5142 hp = &fpkt->pkt_cmd_fhdr; 5143 hp->r_ctl = R_CTL_ELS_REQ; 5144 5145 /* fill in PRLI cmd ELS fields */ 5146 prli.ls_code = LA_ELS_PRLI; 5147 prli.page_length = 0x10; /* huh? */ 5148 prli.payload_length = sizeof (struct la_els_prli); 5149 5150 icmd->ipkt_opcode = LA_ELS_PRLI; 5151 5152 /* get ptr to PRLI service params */ 5153 fprli = (struct fcp_prli *)prli.service_params; 5154 5155 /* fill in service params */ 5156 fprli->type = 0x08; 5157 fprli->resvd1 = 0; 5158 fprli->orig_process_assoc_valid = 0; 5159 fprli->resp_process_assoc_valid = 0; 5160 fprli->establish_image_pair = 1; 5161 fprli->resvd2 = 0; 5162 fprli->resvd3 = 0; 5163 fprli->obsolete_1 = 0; 5164 fprli->obsolete_2 = 0; 5165 fprli->data_overlay_allowed = 0; 5166 fprli->initiator_fn = 1; 5167 fprli->confirmed_compl_allowed = 1; 5168 5169 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5170 fprli->target_fn = 1; 5171 } else { 5172 fprli->target_fn = 0; 5173 } 5174 5175 fprli->retry = 1; 5176 fprli->read_xfer_rdy_disabled = 1; 5177 fprli->write_xfer_rdy_disabled = 0; 5178 5179 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5180 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5181 5182 /* issue the PRLI request */ 5183 5184 mutex_enter(&pptr->port_mutex); 5185 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5186 5187 mutex_exit(&pptr->port_mutex); 5188 5189 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5190 if (rval == FC_SUCCESS) { 5191 res = DDI_SUCCESS; 5192 break; 5193 } 5194 5195 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5196 5197 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5198 rval, "PRLI"); 5199 } else { 5200 mutex_exit(&pptr->port_mutex); 5201 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5202 } 5203 break; 5204 } 5205 5206 default: 5207 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5208 break; 5209 } 5210 5211 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5212 fcp_trace, FCP_BUF_LEVEL_5, 0, 5213 "fcp_send_els: returning %d", res); 5214 5215 if (res != DDI_SUCCESS) { 5216 if (internal) { 5217 fcp_icmd_free(pptr, icmd); 5218 } 5219 } 5220 5221 return (res); 5222 } 5223 5224 5225 /* 5226 * called internally update the state of all of the tgts and each LUN 5227 * for this port (i.e. each target known to be attached to this port) 5228 * if they are not already offline 5229 * 5230 * must be called with the port mutex owned 5231 * 5232 * acquires and releases the target mutexes for each target attached 5233 * to this port 5234 */ 5235 void 5236 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5237 { 5238 int i; 5239 struct fcp_tgt *ptgt; 5240 5241 ASSERT(mutex_owned(&pptr->port_mutex)); 5242 5243 for (i = 0; i < FCP_NUM_HASH; i++) { 5244 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5245 ptgt = ptgt->tgt_next) { 5246 mutex_enter(&ptgt->tgt_mutex); 5247 fcp_update_tgt_state(ptgt, FCP_SET, state); 5248 ptgt->tgt_change_cnt++; 5249 ptgt->tgt_statec_cause = cause; 5250 ptgt->tgt_tmp_cnt = 1; 5251 ptgt->tgt_done = 0; 5252 mutex_exit(&ptgt->tgt_mutex); 5253 } 5254 } 5255 } 5256 5257 5258 static void 5259 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5260 { 5261 int i; 5262 int ndevs; 5263 struct fcp_tgt *ptgt; 5264 5265 ASSERT(mutex_owned(&pptr->port_mutex)); 5266 5267 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5268 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5269 ptgt = ptgt->tgt_next) { 5270 ndevs++; 5271 } 5272 } 5273 5274 if (ndevs == 0) { 5275 return; 5276 } 5277 pptr->port_tmp_cnt = ndevs; 5278 5279 for (i = 0; i < FCP_NUM_HASH; i++) { 5280 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5281 ptgt = ptgt->tgt_next) { 5282 (void) fcp_call_finish_init_held(pptr, ptgt, 5283 lcount, ptgt->tgt_change_cnt, cause); 5284 } 5285 } 5286 } 5287 5288 /* 5289 * Function: fcp_update_tgt_state 5290 * 5291 * Description: This function updates the field tgt_state of a target. That 5292 * field is a bitmap and which bit can be set or reset 5293 * individually. The action applied to the target state is also 5294 * applied to all the LUNs belonging to the target (provided the 5295 * LUN is not offline). A side effect of applying the state 5296 * modification to the target and the LUNs is the field tgt_trace 5297 * of the target and lun_trace of the LUNs is set to zero. 5298 * 5299 * 5300 * Argument: *ptgt Target structure. 5301 * flag Flag indication what action to apply (set/reset). 5302 * state State bits to update. 5303 * 5304 * Return Value: None 5305 * 5306 * Context: Interrupt, Kernel or User context. 5307 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5308 * calling this function. 5309 */ 5310 void 5311 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5312 { 5313 struct fcp_lun *plun; 5314 5315 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5316 5317 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5318 /* The target is not offline. */ 5319 if (flag == FCP_SET) { 5320 ptgt->tgt_state |= state; 5321 ptgt->tgt_trace = 0; 5322 } else { 5323 ptgt->tgt_state &= ~state; 5324 } 5325 5326 for (plun = ptgt->tgt_lun; plun != NULL; 5327 plun = plun->lun_next) { 5328 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5329 /* The LUN is not offline. */ 5330 if (flag == FCP_SET) { 5331 plun->lun_state |= state; 5332 plun->lun_trace = 0; 5333 } else { 5334 plun->lun_state &= ~state; 5335 } 5336 } 5337 } 5338 } 5339 } 5340 5341 /* 5342 * Function: fcp_update_tgt_state 5343 * 5344 * Description: This function updates the field lun_state of a LUN. That 5345 * field is a bitmap and which bit can be set or reset 5346 * individually. 5347 * 5348 * Argument: *plun LUN structure. 5349 * flag Flag indication what action to apply (set/reset). 5350 * state State bits to update. 5351 * 5352 * Return Value: None 5353 * 5354 * Context: Interrupt, Kernel or User context. 5355 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5356 * calling this function. 5357 */ 5358 void 5359 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5360 { 5361 struct fcp_tgt *ptgt = plun->lun_tgt; 5362 5363 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5364 5365 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5366 flag == FCP_SET ? (plun->lun_state |= state) : 5367 (plun->lun_state &= ~state); 5368 } 5369 } 5370 5371 /* 5372 * Function: fcp_get_port 5373 * 5374 * Description: This function returns the fcp_port structure from the opaque 5375 * handle passed by the caller. That opaque handle is the handle 5376 * used by fp/fctl to identify a particular local port. That 5377 * handle has been stored in the corresponding fcp_port 5378 * structure. This function is going to walk the global list of 5379 * fcp_port structures till one has a port_fp_handle that matches 5380 * the handle passed by the caller. This function enters the 5381 * mutex fcp_global_mutex while walking the global list and then 5382 * releases it. 5383 * 5384 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5385 * particular port. 5386 * 5387 * Return Value: NULL Not found. 5388 * Not NULL Pointer to the fcp_port structure. 5389 * 5390 * Context: Interrupt, Kernel or User context. 5391 */ 5392 static struct fcp_port * 5393 fcp_get_port(opaque_t port_handle) 5394 { 5395 struct fcp_port *pptr; 5396 5397 ASSERT(port_handle != NULL); 5398 5399 mutex_enter(&fcp_global_mutex); 5400 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5401 if (pptr->port_fp_handle == port_handle) { 5402 break; 5403 } 5404 } 5405 mutex_exit(&fcp_global_mutex); 5406 5407 return (pptr); 5408 } 5409 5410 5411 static void 5412 fcp_unsol_callback(fc_packet_t *fpkt) 5413 { 5414 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5415 struct fcp_port *pptr = icmd->ipkt_port; 5416 5417 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5418 caddr_t state, reason, action, expln; 5419 5420 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5421 &action, &expln); 5422 5423 fcp_log(CE_WARN, pptr->port_dip, 5424 "!couldn't post response to unsolicited request: " 5425 " state=%s reason=%s rx_id=%x ox_id=%x", 5426 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5427 fpkt->pkt_cmd_fhdr.rx_id); 5428 } 5429 fcp_icmd_free(pptr, icmd); 5430 } 5431 5432 5433 /* 5434 * Perform general purpose preparation of a response to an unsolicited request 5435 */ 5436 static void 5437 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5438 uchar_t r_ctl, uchar_t type) 5439 { 5440 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5441 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5442 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5443 pkt->pkt_cmd_fhdr.type = type; 5444 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5445 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5446 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5447 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5448 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5449 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5450 pkt->pkt_cmd_fhdr.ro = 0; 5451 pkt->pkt_cmd_fhdr.rsvd = 0; 5452 pkt->pkt_comp = fcp_unsol_callback; 5453 pkt->pkt_pd = NULL; 5454 } 5455 5456 5457 /*ARGSUSED*/ 5458 static int 5459 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5460 { 5461 fc_packet_t *fpkt; 5462 struct la_els_prli prli; 5463 struct fcp_prli *fprli; 5464 struct fcp_ipkt *icmd; 5465 struct la_els_prli *from; 5466 struct fcp_prli *orig; 5467 struct fcp_tgt *ptgt; 5468 int tcount = 0; 5469 int lcount; 5470 5471 from = (struct la_els_prli *)buf->ub_buffer; 5472 orig = (struct fcp_prli *)from->service_params; 5473 5474 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5475 NULL) { 5476 mutex_enter(&ptgt->tgt_mutex); 5477 tcount = ptgt->tgt_change_cnt; 5478 mutex_exit(&ptgt->tgt_mutex); 5479 } 5480 mutex_enter(&pptr->port_mutex); 5481 lcount = pptr->port_link_cnt; 5482 mutex_exit(&pptr->port_mutex); 5483 5484 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5485 sizeof (la_els_prli_t), 0, 0, lcount, tcount, 0, 5486 FC_INVALID_RSCN_COUNT)) == NULL) { 5487 return (FC_FAILURE); 5488 } 5489 fpkt = icmd->ipkt_fpkt; 5490 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5491 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5492 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5493 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5494 fpkt->pkt_rsplen = 0; 5495 fpkt->pkt_datalen = 0; 5496 5497 icmd->ipkt_opcode = LA_ELS_PRLI; 5498 5499 bzero(&prli, sizeof (struct la_els_prli)); 5500 fprli = (struct fcp_prli *)prli.service_params; 5501 prli.ls_code = LA_ELS_ACC; 5502 prli.page_length = 0x10; 5503 prli.payload_length = sizeof (struct la_els_prli); 5504 5505 /* fill in service params */ 5506 fprli->type = 0x08; 5507 fprli->resvd1 = 0; 5508 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5509 fprli->orig_process_associator = orig->orig_process_associator; 5510 fprli->resp_process_assoc_valid = 0; 5511 fprli->establish_image_pair = 1; 5512 fprli->resvd2 = 0; 5513 fprli->resvd3 = 0; 5514 fprli->obsolete_1 = 0; 5515 fprli->obsolete_2 = 0; 5516 fprli->data_overlay_allowed = 0; 5517 fprli->initiator_fn = 1; 5518 fprli->confirmed_compl_allowed = 1; 5519 5520 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5521 fprli->target_fn = 1; 5522 } else { 5523 fprli->target_fn = 0; 5524 } 5525 5526 fprli->retry = 1; 5527 fprli->read_xfer_rdy_disabled = 1; 5528 fprli->write_xfer_rdy_disabled = 0; 5529 5530 /* save the unsol prli payload first */ 5531 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5532 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5533 5534 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5535 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5536 5537 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5538 5539 mutex_enter(&pptr->port_mutex); 5540 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5541 int rval; 5542 mutex_exit(&pptr->port_mutex); 5543 5544 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5545 FC_SUCCESS) { 5546 if (rval == FC_STATEC_BUSY || rval == FC_OFFLINE) { 5547 fcp_queue_ipkt(pptr, fpkt); 5548 return (FC_SUCCESS); 5549 } 5550 /* Let it timeout */ 5551 fcp_icmd_free(pptr, icmd); 5552 return (FC_FAILURE); 5553 } 5554 } else { 5555 mutex_exit(&pptr->port_mutex); 5556 fcp_icmd_free(pptr, icmd); 5557 return (FC_FAILURE); 5558 } 5559 5560 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5561 5562 return (FC_SUCCESS); 5563 } 5564 5565 /* 5566 * Function: fcp_icmd_alloc 5567 * 5568 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5569 * field is initialized to fcp_icmd_callback. Sometimes it is 5570 * modified by the caller (such as fcp_send_scsi). The 5571 * structure is also tied to the state of the line and of the 5572 * target at a particular time. That link is established by 5573 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5574 * and tcount which came respectively from pptr->link_cnt and 5575 * ptgt->tgt_change_cnt. 5576 * 5577 * Argument: *pptr Fcp port. 5578 * *ptgt Target (destination of the command). 5579 * cmd_len Length of the command. 5580 * resp_len Length of the expected response. 5581 * data_len Length of the data. 5582 * nodma Indicates weither the command and response. 5583 * will be transfer through DMA or not. 5584 * lcount Link state change counter. 5585 * tcount Target state change counter. 5586 * cause Reason that lead to this call. 5587 * 5588 * Return Value: NULL Failed. 5589 * Not NULL Internal packet address. 5590 */ 5591 static struct fcp_ipkt * 5592 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5593 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5594 uint32_t rscn_count) 5595 { 5596 int dma_setup = 0; 5597 fc_packet_t *fpkt; 5598 struct fcp_ipkt *icmd = NULL; 5599 5600 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5601 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5602 KM_NOSLEEP); 5603 if (icmd == NULL) { 5604 fcp_log(CE_WARN, pptr->port_dip, 5605 "!internal packet allocation failed"); 5606 return (NULL); 5607 } 5608 5609 /* 5610 * initialize the allocated packet 5611 */ 5612 icmd->ipkt_nodma = nodma; 5613 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5614 icmd->ipkt_lun = NULL; 5615 5616 icmd->ipkt_link_cnt = lcount; 5617 icmd->ipkt_change_cnt = tcount; 5618 icmd->ipkt_cause = cause; 5619 5620 mutex_enter(&pptr->port_mutex); 5621 icmd->ipkt_port = pptr; 5622 mutex_exit(&pptr->port_mutex); 5623 5624 /* keep track of amt of data to be sent in pkt */ 5625 icmd->ipkt_cmdlen = cmd_len; 5626 icmd->ipkt_resplen = resp_len; 5627 icmd->ipkt_datalen = data_len; 5628 5629 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5630 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5631 5632 /* set pkt's private ptr to point to cmd pkt */ 5633 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5634 5635 /* set FCA private ptr to memory just beyond */ 5636 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5637 ((char *)icmd + sizeof (struct fcp_ipkt) + 5638 pptr->port_dmacookie_sz); 5639 5640 /* get ptr to fpkt substruct and fill it in */ 5641 fpkt = icmd->ipkt_fpkt; 5642 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5643 sizeof (struct fcp_ipkt)); 5644 5645 if (ptgt != NULL) { 5646 icmd->ipkt_tgt = ptgt; 5647 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5648 } 5649 5650 fpkt->pkt_comp = fcp_icmd_callback; 5651 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5652 fpkt->pkt_cmdlen = cmd_len; 5653 fpkt->pkt_rsplen = resp_len; 5654 fpkt->pkt_datalen = data_len; 5655 5656 /* 5657 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5658 * rscn_count as fcp knows down to the transport. If a valid count was 5659 * passed into this function, we allocate memory to actually pass down 5660 * this info. 5661 * 5662 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5663 * basically mean that fcp will not be able to help transport 5664 * distinguish if a new RSCN has come after fcp was last informed about 5665 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5666 * 5068068 where the device might end up going offline in case of RSCN 5667 * storms. 5668 */ 5669 fpkt->pkt_ulp_rscn_infop = NULL; 5670 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5671 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5672 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5673 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5674 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5675 fcp_trace, FCP_BUF_LEVEL_6, 0, 5676 "Failed to alloc memory to pass rscn info"); 5677 } 5678 } 5679 5680 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5681 fc_ulp_rscn_info_t *rscnp; 5682 5683 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5684 rscnp->ulp_rscn_count = rscn_count; 5685 } 5686 5687 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5688 goto fail; 5689 } 5690 dma_setup++; 5691 5692 /* 5693 * Must hold target mutex across setting of pkt_pd and call to 5694 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5695 * away while we're not looking. 5696 */ 5697 if (ptgt != NULL) { 5698 mutex_enter(&ptgt->tgt_mutex); 5699 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5700 5701 /* ask transport to do its initialization on this pkt */ 5702 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5703 != FC_SUCCESS) { 5704 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5705 fcp_trace, FCP_BUF_LEVEL_6, 0, 5706 "fc_ulp_init_packet failed"); 5707 mutex_exit(&ptgt->tgt_mutex); 5708 goto fail; 5709 } 5710 mutex_exit(&ptgt->tgt_mutex); 5711 } else { 5712 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5713 != FC_SUCCESS) { 5714 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5715 fcp_trace, FCP_BUF_LEVEL_6, 0, 5716 "fc_ulp_init_packet failed"); 5717 goto fail; 5718 } 5719 } 5720 5721 mutex_enter(&pptr->port_mutex); 5722 if (pptr->port_state & (FCP_STATE_DETACHING | 5723 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5724 int rval; 5725 5726 mutex_exit(&pptr->port_mutex); 5727 5728 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5729 ASSERT(rval == FC_SUCCESS); 5730 5731 goto fail; 5732 } 5733 5734 if (ptgt != NULL) { 5735 mutex_enter(&ptgt->tgt_mutex); 5736 ptgt->tgt_ipkt_cnt++; 5737 mutex_exit(&ptgt->tgt_mutex); 5738 } 5739 5740 pptr->port_ipkt_cnt++; 5741 5742 mutex_exit(&pptr->port_mutex); 5743 5744 return (icmd); 5745 5746 fail: 5747 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5748 kmem_free(fpkt->pkt_ulp_rscn_infop, 5749 sizeof (fc_ulp_rscn_info_t)); 5750 fpkt->pkt_ulp_rscn_infop = NULL; 5751 } 5752 5753 if (dma_setup) { 5754 fcp_free_dma(pptr, icmd); 5755 } 5756 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5757 (size_t)pptr->port_dmacookie_sz); 5758 5759 return (NULL); 5760 } 5761 5762 /* 5763 * Function: fcp_icmd_free 5764 * 5765 * Description: Frees the internal command passed by the caller. 5766 * 5767 * Argument: *pptr Fcp port. 5768 * *icmd Internal packet to free. 5769 * 5770 * Return Value: None 5771 */ 5772 static void 5773 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5774 { 5775 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5776 5777 /* Let the underlying layers do their cleanup. */ 5778 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5779 icmd->ipkt_fpkt); 5780 5781 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5782 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5783 sizeof (fc_ulp_rscn_info_t)); 5784 } 5785 5786 fcp_free_dma(pptr, icmd); 5787 5788 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5789 (size_t)pptr->port_dmacookie_sz); 5790 5791 mutex_enter(&pptr->port_mutex); 5792 5793 if (ptgt) { 5794 mutex_enter(&ptgt->tgt_mutex); 5795 ptgt->tgt_ipkt_cnt--; 5796 mutex_exit(&ptgt->tgt_mutex); 5797 } 5798 5799 pptr->port_ipkt_cnt--; 5800 mutex_exit(&pptr->port_mutex); 5801 } 5802 5803 /* 5804 * Function: fcp_alloc_dma 5805 * 5806 * Description: Allocated the DMA resources required for the internal 5807 * packet. 5808 * 5809 * Argument: *pptr FCP port. 5810 * *icmd Internal FCP packet. 5811 * nodma Indicates if the Cmd and Resp will be DMAed. 5812 * flags Allocation flags (Sleep or NoSleep). 5813 * 5814 * Return Value: FC_SUCCESS 5815 * FC_NOMEM 5816 */ 5817 static int 5818 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5819 int nodma, int flags) 5820 { 5821 int rval; 5822 size_t real_size; 5823 uint_t ccount; 5824 int bound = 0; 5825 int cmd_resp = 0; 5826 fc_packet_t *fpkt; 5827 ddi_dma_cookie_t pkt_data_cookie; 5828 ddi_dma_cookie_t *cp; 5829 uint32_t cnt; 5830 5831 fpkt = &icmd->ipkt_fc_packet; 5832 5833 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5834 fpkt->pkt_resp_dma == NULL); 5835 5836 icmd->ipkt_nodma = nodma; 5837 5838 if (nodma) { 5839 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5840 if (fpkt->pkt_cmd == NULL) { 5841 goto fail; 5842 } 5843 5844 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5845 if (fpkt->pkt_resp == NULL) { 5846 goto fail; 5847 } 5848 } else { 5849 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5850 5851 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5852 if (rval == FC_FAILURE) { 5853 ASSERT(fpkt->pkt_cmd_dma == NULL && 5854 fpkt->pkt_resp_dma == NULL); 5855 goto fail; 5856 } 5857 cmd_resp++; 5858 } 5859 5860 if (fpkt->pkt_datalen != 0) { 5861 /* 5862 * set up DMA handle and memory for the data in this packet 5863 */ 5864 if (ddi_dma_alloc_handle(pptr->port_dip, 5865 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 5866 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 5867 goto fail; 5868 } 5869 5870 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 5871 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 5872 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 5873 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 5874 goto fail; 5875 } 5876 5877 /* was DMA mem size gotten < size asked for/needed ?? */ 5878 if (real_size < fpkt->pkt_datalen) { 5879 goto fail; 5880 } 5881 5882 /* bind DMA address and handle together */ 5883 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 5884 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 5885 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 5886 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 5887 goto fail; 5888 } 5889 bound++; 5890 5891 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 5892 goto fail; 5893 } 5894 5895 fpkt->pkt_data_cookie_cnt = ccount; 5896 5897 cp = fpkt->pkt_data_cookie; 5898 *cp = pkt_data_cookie; 5899 cp++; 5900 5901 for (cnt = 1; cnt < ccount; cnt++, cp++) { 5902 ddi_dma_nextcookie(fpkt->pkt_data_dma, 5903 &pkt_data_cookie); 5904 *cp = pkt_data_cookie; 5905 } 5906 5907 } 5908 5909 return (FC_SUCCESS); 5910 5911 fail: 5912 if (bound) { 5913 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 5914 } 5915 5916 if (fpkt->pkt_data_dma) { 5917 if (fpkt->pkt_data) { 5918 ddi_dma_mem_free(&fpkt->pkt_data_acc); 5919 } 5920 ddi_dma_free_handle(&fpkt->pkt_data_dma); 5921 } 5922 5923 if (nodma) { 5924 if (fpkt->pkt_cmd) { 5925 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 5926 } 5927 if (fpkt->pkt_resp) { 5928 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 5929 } 5930 } else { 5931 if (cmd_resp) { 5932 fcp_free_cmd_resp(pptr, fpkt); 5933 } 5934 } 5935 5936 return (FC_NOMEM); 5937 } 5938 5939 5940 static void 5941 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5942 { 5943 fc_packet_t *fpkt = icmd->ipkt_fpkt; 5944 5945 if (fpkt->pkt_data_dma) { 5946 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 5947 if (fpkt->pkt_data) { 5948 ddi_dma_mem_free(&fpkt->pkt_data_acc); 5949 } 5950 ddi_dma_free_handle(&fpkt->pkt_data_dma); 5951 } 5952 5953 if (icmd->ipkt_nodma) { 5954 if (fpkt->pkt_cmd) { 5955 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 5956 } 5957 if (fpkt->pkt_resp) { 5958 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 5959 } 5960 } else { 5961 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 5962 5963 fcp_free_cmd_resp(pptr, fpkt); 5964 } 5965 } 5966 5967 /* 5968 * Function: fcp_lookup_target 5969 * 5970 * Description: Finds a target given a WWN. 5971 * 5972 * Argument: *pptr FCP port. 5973 * *wwn World Wide Name of the device to look for. 5974 * 5975 * Return Value: NULL No target found 5976 * Not NULL Target structure 5977 * 5978 * Context: Interrupt context. 5979 * The mutex pptr->port_mutex must be owned. 5980 */ 5981 /* ARGSUSED */ 5982 static struct fcp_tgt * 5983 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 5984 { 5985 int hash; 5986 struct fcp_tgt *ptgt; 5987 5988 ASSERT(mutex_owned(&pptr->port_mutex)); 5989 5990 hash = FCP_HASH(wwn); 5991 5992 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 5993 ptgt = ptgt->tgt_next) { 5994 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 5995 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5996 sizeof (ptgt->tgt_port_wwn)) == 0) { 5997 break; 5998 } 5999 } 6000 6001 return (ptgt); 6002 } 6003 6004 6005 /* 6006 * Find target structure given a port identifier 6007 */ 6008 static struct fcp_tgt * 6009 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6010 { 6011 fc_portid_t port_id; 6012 la_wwn_t pwwn; 6013 struct fcp_tgt *ptgt = NULL; 6014 6015 port_id.priv_lilp_posit = 0; 6016 port_id.port_id = d_id; 6017 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6018 &pwwn) == FC_SUCCESS) { 6019 mutex_enter(&pptr->port_mutex); 6020 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6021 mutex_exit(&pptr->port_mutex); 6022 } 6023 6024 return (ptgt); 6025 } 6026 6027 6028 /* 6029 * the packet completion callback routine for info cmd pkts 6030 * 6031 * this means fpkt pts to a response to either a PLOGI or a PRLI 6032 * 6033 * if there is an error an attempt is made to call a routine to resend 6034 * the command that failed 6035 */ 6036 static void 6037 fcp_icmd_callback(fc_packet_t *fpkt) 6038 { 6039 struct fcp_ipkt *icmd; 6040 struct fcp_port *pptr; 6041 struct fcp_tgt *ptgt; 6042 struct la_els_prli *prli; 6043 struct la_els_prli prli_s; 6044 struct fcp_prli *fprli; 6045 struct fcp_lun *plun; 6046 int free_pkt = 1; 6047 int rval; 6048 ls_code_t resp; 6049 uchar_t prli_acc = 0; 6050 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6051 int lun0_newalloc; 6052 6053 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6054 6055 /* get ptrs to the port and target structs for the cmd */ 6056 pptr = icmd->ipkt_port; 6057 ptgt = icmd->ipkt_tgt; 6058 6059 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6060 6061 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6062 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6063 sizeof (prli_s)); 6064 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6065 } 6066 6067 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6068 fcp_trace, FCP_BUF_LEVEL_2, 0, 6069 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6070 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6071 ptgt->tgt_d_id); 6072 6073 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6074 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6075 6076 mutex_enter(&ptgt->tgt_mutex); 6077 if (ptgt->tgt_pd_handle == NULL) { 6078 /* 6079 * in a fabric environment the port device handles 6080 * get created only after successful LOGIN into the 6081 * transport, so the transport makes this port 6082 * device (pd) handle available in this packet, so 6083 * save it now 6084 */ 6085 ASSERT(fpkt->pkt_pd != NULL); 6086 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6087 } 6088 mutex_exit(&ptgt->tgt_mutex); 6089 6090 /* which ELS cmd is this response for ?? */ 6091 switch (icmd->ipkt_opcode) { 6092 case LA_ELS_PLOGI: 6093 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6094 fcp_trace, FCP_BUF_LEVEL_5, 0, 6095 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6096 ptgt->tgt_d_id, 6097 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6098 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6099 6100 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6101 FCP_TGT_TRACE_15); 6102 6103 /* Note that we are not allocating a new icmd */ 6104 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6105 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6106 icmd->ipkt_cause) != DDI_SUCCESS) { 6107 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6108 FCP_TGT_TRACE_16); 6109 goto fail; 6110 } 6111 break; 6112 6113 case LA_ELS_PRLI: 6114 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6115 fcp_trace, FCP_BUF_LEVEL_5, 0, 6116 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6117 6118 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6119 FCP_TGT_TRACE_17); 6120 6121 prli = &prli_s; 6122 6123 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6124 sizeof (prli_s)); 6125 6126 fprli = (struct fcp_prli *)prli->service_params; 6127 6128 mutex_enter(&ptgt->tgt_mutex); 6129 ptgt->tgt_icap = fprli->initiator_fn; 6130 ptgt->tgt_tcap = fprli->target_fn; 6131 mutex_exit(&ptgt->tgt_mutex); 6132 6133 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6134 /* 6135 * this FCP device does not support target mode 6136 */ 6137 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6138 FCP_TGT_TRACE_18); 6139 goto fail; 6140 } 6141 if (fprli->retry == 1) { 6142 fc_ulp_disable_relogin(pptr->port_fp_handle, 6143 &ptgt->tgt_port_wwn); 6144 } 6145 6146 /* target is no longer offline */ 6147 mutex_enter(&pptr->port_mutex); 6148 mutex_enter(&ptgt->tgt_mutex); 6149 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6150 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6151 FCP_TGT_MARK); 6152 } else { 6153 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6154 fcp_trace, FCP_BUF_LEVEL_2, 0, 6155 "fcp_icmd_callback,1: state change " 6156 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6157 mutex_exit(&ptgt->tgt_mutex); 6158 mutex_exit(&pptr->port_mutex); 6159 goto fail; 6160 } 6161 mutex_exit(&ptgt->tgt_mutex); 6162 mutex_exit(&pptr->port_mutex); 6163 6164 /* 6165 * lun 0 should always respond to inquiry, so 6166 * get the LUN struct for LUN 0 6167 * 6168 * Currently we deal with first level of addressing. 6169 * If / when we start supporting 0x device types 6170 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6171 * this logic will need revisiting. 6172 */ 6173 lun0_newalloc = 0; 6174 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6175 /* 6176 * no LUN struct for LUN 0 yet exists, 6177 * so create one 6178 */ 6179 plun = fcp_alloc_lun(ptgt); 6180 if (plun == NULL) { 6181 fcp_log(CE_WARN, pptr->port_dip, 6182 "!Failed to allocate lun 0 for" 6183 " D_ID=%x", ptgt->tgt_d_id); 6184 goto fail; 6185 } 6186 lun0_newalloc = 1; 6187 } 6188 6189 /* fill in LUN info */ 6190 mutex_enter(&ptgt->tgt_mutex); 6191 /* 6192 * consider lun 0 as device not connected if it is 6193 * offlined or newly allocated 6194 */ 6195 if (plun->lun_state & FCP_LUN_OFFLINE || lun0_newalloc) 6196 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6197 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6198 plun->lun_state &= ~FCP_LUN_OFFLINE; 6199 ptgt->tgt_lun_cnt = 1; 6200 ptgt->tgt_report_lun_cnt = 0; 6201 mutex_exit(&ptgt->tgt_mutex); 6202 6203 /* Retrieve the rscn count (if a valid one exists) */ 6204 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6205 rscn_count = ((fc_ulp_rscn_info_t *) 6206 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6207 ->ulp_rscn_count; 6208 } else { 6209 rscn_count = FC_INVALID_RSCN_COUNT; 6210 } 6211 6212 /* send Report Lun request to target */ 6213 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6214 sizeof (struct fcp_reportlun_resp), 6215 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6216 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6217 mutex_enter(&pptr->port_mutex); 6218 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6219 fcp_log(CE_WARN, pptr->port_dip, 6220 "!Failed to send REPORT LUN to" 6221 " D_ID=%x", ptgt->tgt_d_id); 6222 } else { 6223 FCP_TRACE(fcp_logq, 6224 pptr->port_instbuf, fcp_trace, 6225 FCP_BUF_LEVEL_5, 0, 6226 "fcp_icmd_callback,2:state change" 6227 " occured for D_ID=0x%x", 6228 ptgt->tgt_d_id); 6229 } 6230 mutex_exit(&pptr->port_mutex); 6231 6232 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6233 FCP_TGT_TRACE_19); 6234 6235 goto fail; 6236 } else { 6237 free_pkt = 0; 6238 fcp_icmd_free(pptr, icmd); 6239 } 6240 break; 6241 6242 default: 6243 fcp_log(CE_WARN, pptr->port_dip, 6244 "!fcp_icmd_callback Invalid opcode"); 6245 goto fail; 6246 } 6247 6248 return; 6249 } 6250 6251 6252 /* 6253 * Other PLOGI failures are not retried as the 6254 * transport does it already 6255 */ 6256 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6257 if (fcp_is_retryable(icmd) && 6258 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6259 6260 if (FCP_MUST_RETRY(fpkt)) { 6261 fcp_queue_ipkt(pptr, fpkt); 6262 return; 6263 } 6264 6265 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6266 fcp_trace, FCP_BUF_LEVEL_2, 0, 6267 "ELS PRLI is retried for d_id=0x%x, state=%x," 6268 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6269 fpkt->pkt_reason); 6270 6271 /* 6272 * Retry by recalling the routine that 6273 * originally queued this packet 6274 */ 6275 mutex_enter(&pptr->port_mutex); 6276 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6277 caddr_t msg; 6278 6279 mutex_exit(&pptr->port_mutex); 6280 6281 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6282 6283 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6284 fpkt->pkt_timeout += 6285 FCP_TIMEOUT_DELTA; 6286 } 6287 6288 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6289 fpkt); 6290 if (rval == FC_SUCCESS) { 6291 return; 6292 } 6293 6294 if (rval == FC_STATEC_BUSY || 6295 rval == FC_OFFLINE) { 6296 fcp_queue_ipkt(pptr, fpkt); 6297 return; 6298 } 6299 (void) fc_ulp_error(rval, &msg); 6300 6301 fcp_log(CE_NOTE, pptr->port_dip, 6302 "!ELS 0x%x failed to d_id=0x%x;" 6303 " %s", icmd->ipkt_opcode, 6304 ptgt->tgt_d_id, msg); 6305 } else { 6306 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6307 fcp_trace, FCP_BUF_LEVEL_2, 0, 6308 "fcp_icmd_callback,3: state change " 6309 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6310 mutex_exit(&pptr->port_mutex); 6311 } 6312 } 6313 } else { 6314 if (fcp_is_retryable(icmd) && 6315 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6316 if (FCP_MUST_RETRY(fpkt)) { 6317 fcp_queue_ipkt(pptr, fpkt); 6318 return; 6319 } 6320 } 6321 mutex_enter(&pptr->port_mutex); 6322 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6323 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6324 mutex_exit(&pptr->port_mutex); 6325 fcp_print_error(fpkt); 6326 } else { 6327 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6328 fcp_trace, FCP_BUF_LEVEL_2, 0, 6329 "fcp_icmd_callback,4: state change occured" 6330 " for D_ID=0x%x", ptgt->tgt_d_id); 6331 mutex_exit(&pptr->port_mutex); 6332 } 6333 } 6334 6335 fail: 6336 if (free_pkt) { 6337 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6338 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6339 fcp_icmd_free(pptr, icmd); 6340 } 6341 } 6342 6343 6344 /* 6345 * called internally to send an info cmd using the transport 6346 * 6347 * sends either an INQ or a REPORT_LUN 6348 * 6349 * when the packet is completed fcp_scsi_callback is called 6350 */ 6351 static int 6352 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6353 int lcount, int tcount, int cause, uint32_t rscn_count) 6354 { 6355 int nodma; 6356 struct fcp_ipkt *icmd; 6357 struct fcp_tgt *ptgt; 6358 struct fcp_port *pptr; 6359 fc_frame_hdr_t *hp; 6360 fc_packet_t *fpkt; 6361 struct fcp_cmd fcp_cmd; 6362 struct fcp_cmd *fcmd; 6363 union scsi_cdb *scsi_cdb; 6364 6365 ASSERT(plun != NULL); 6366 6367 ptgt = plun->lun_tgt; 6368 ASSERT(ptgt != NULL); 6369 6370 pptr = ptgt->tgt_port; 6371 ASSERT(pptr != NULL); 6372 6373 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6374 fcp_trace, FCP_BUF_LEVEL_5, 0, 6375 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6376 6377 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6378 6379 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6380 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6381 rscn_count); 6382 6383 if (icmd == NULL) { 6384 return (DDI_FAILURE); 6385 } 6386 6387 fpkt = icmd->ipkt_fpkt; 6388 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6389 icmd->ipkt_retries = 0; 6390 icmd->ipkt_opcode = opcode; 6391 icmd->ipkt_lun = plun; 6392 6393 if (nodma) { 6394 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6395 } else { 6396 fcmd = &fcp_cmd; 6397 } 6398 bzero(fcmd, sizeof (struct fcp_cmd)); 6399 6400 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6401 6402 hp = &fpkt->pkt_cmd_fhdr; 6403 6404 hp->s_id = pptr->port_id; 6405 hp->d_id = ptgt->tgt_d_id; 6406 hp->r_ctl = R_CTL_COMMAND; 6407 hp->type = FC_TYPE_SCSI_FCP; 6408 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6409 hp->rsvd = 0; 6410 hp->seq_id = 0; 6411 hp->seq_cnt = 0; 6412 hp->ox_id = 0xffff; 6413 hp->rx_id = 0xffff; 6414 hp->ro = 0; 6415 6416 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6417 6418 /* 6419 * Request SCSI target for expedited processing 6420 */ 6421 6422 /* 6423 * Set up for untagged queuing because we do not 6424 * know if the fibre device supports queuing. 6425 */ 6426 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6427 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6428 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6429 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6430 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6431 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6432 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6433 6434 switch (opcode) { 6435 case SCMD_INQUIRY_PAGE83: 6436 /* 6437 * Prepare to get the Inquiry VPD page 83 information 6438 */ 6439 fcmd->fcp_cntl.cntl_read_data = 1; 6440 fcmd->fcp_cntl.cntl_write_data = 0; 6441 fcmd->fcp_data_len = alloc_len; 6442 6443 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6444 fpkt->pkt_comp = fcp_scsi_callback; 6445 6446 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6447 scsi_cdb->g0_addr2 = 0x01; 6448 scsi_cdb->g0_addr1 = 0x83; 6449 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6450 break; 6451 6452 case SCMD_INQUIRY: 6453 fcmd->fcp_cntl.cntl_read_data = 1; 6454 fcmd->fcp_cntl.cntl_write_data = 0; 6455 fcmd->fcp_data_len = alloc_len; 6456 6457 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6458 fpkt->pkt_comp = fcp_scsi_callback; 6459 6460 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6461 scsi_cdb->g0_count0 = SUN_INQSIZE; 6462 break; 6463 6464 case SCMD_REPORT_LUN: { 6465 fc_portid_t d_id; 6466 opaque_t fca_dev; 6467 6468 ASSERT(alloc_len >= 16); 6469 6470 d_id.priv_lilp_posit = 0; 6471 d_id.port_id = ptgt->tgt_d_id; 6472 6473 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6474 6475 mutex_enter(&ptgt->tgt_mutex); 6476 ptgt->tgt_fca_dev = fca_dev; 6477 mutex_exit(&ptgt->tgt_mutex); 6478 6479 fcmd->fcp_cntl.cntl_read_data = 1; 6480 fcmd->fcp_cntl.cntl_write_data = 0; 6481 fcmd->fcp_data_len = alloc_len; 6482 6483 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6484 fpkt->pkt_comp = fcp_scsi_callback; 6485 6486 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6487 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6488 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6489 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6490 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6491 break; 6492 } 6493 6494 default: 6495 fcp_log(CE_WARN, pptr->port_dip, 6496 "!fcp_send_scsi Invalid opcode"); 6497 break; 6498 } 6499 6500 if (!nodma) { 6501 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6502 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6503 } 6504 6505 mutex_enter(&pptr->port_mutex); 6506 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6507 6508 mutex_exit(&pptr->port_mutex); 6509 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6510 FC_SUCCESS) { 6511 fcp_icmd_free(pptr, icmd); 6512 return (DDI_FAILURE); 6513 } 6514 return (DDI_SUCCESS); 6515 } else { 6516 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6517 fcp_trace, FCP_BUF_LEVEL_2, 0, 6518 "fcp_send_scsi,1: state change occured" 6519 " for D_ID=0x%x", ptgt->tgt_d_id); 6520 mutex_exit(&pptr->port_mutex); 6521 fcp_icmd_free(pptr, icmd); 6522 return (DDI_FAILURE); 6523 } 6524 } 6525 6526 6527 /* 6528 * called by fcp_scsi_callback to check to handle the case where 6529 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6530 */ 6531 static int 6532 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6533 { 6534 uchar_t rqlen; 6535 int rval = DDI_FAILURE; 6536 struct scsi_extended_sense sense_info, *sense; 6537 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6538 fpkt->pkt_ulp_private; 6539 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6540 struct fcp_port *pptr = ptgt->tgt_port; 6541 6542 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6543 6544 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6545 /* 6546 * SCSI-II Reserve Release support. Some older FC drives return 6547 * Reservation conflict for Report Luns command. 6548 */ 6549 if (icmd->ipkt_nodma) { 6550 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6551 rsp->fcp_u.fcp_status.sense_len_set = 0; 6552 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6553 } else { 6554 fcp_rsp_t new_resp; 6555 6556 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6557 fpkt->pkt_resp_acc, sizeof (new_resp)); 6558 6559 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6560 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6561 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6562 6563 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6564 fpkt->pkt_resp_acc, sizeof (new_resp)); 6565 } 6566 6567 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6568 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6569 6570 return (DDI_SUCCESS); 6571 } 6572 6573 sense = &sense_info; 6574 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6575 /* no need to continue if sense length is not set */ 6576 return (rval); 6577 } 6578 6579 /* casting 64-bit integer to 8-bit */ 6580 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6581 sizeof (struct scsi_extended_sense)); 6582 6583 if (rqlen < 14) { 6584 /* no need to continue if request length isn't long enough */ 6585 return (rval); 6586 } 6587 6588 if (icmd->ipkt_nodma) { 6589 /* 6590 * We can safely use fcp_response_len here since the 6591 * only path that calls fcp_check_reportlun, 6592 * fcp_scsi_callback, has already called 6593 * fcp_validate_fcp_response. 6594 */ 6595 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6596 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6597 } else { 6598 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6599 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6600 sizeof (struct scsi_extended_sense)); 6601 } 6602 6603 if (!FCP_SENSE_NO_LUN(sense)) { 6604 mutex_enter(&ptgt->tgt_mutex); 6605 /* clear the flag if any */ 6606 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6607 mutex_exit(&ptgt->tgt_mutex); 6608 } 6609 6610 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6611 (sense->es_add_code == 0x20)) { 6612 if (icmd->ipkt_nodma) { 6613 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6614 rsp->fcp_u.fcp_status.sense_len_set = 0; 6615 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6616 } else { 6617 fcp_rsp_t new_resp; 6618 6619 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6620 fpkt->pkt_resp_acc, sizeof (new_resp)); 6621 6622 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6623 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6624 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6625 6626 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6627 fpkt->pkt_resp_acc, sizeof (new_resp)); 6628 } 6629 6630 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6631 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6632 6633 return (DDI_SUCCESS); 6634 } 6635 6636 /* 6637 * This is for the STK library which returns a check condition, 6638 * to indicate device is not ready, manual assistance needed. 6639 * This is to a report lun command when the door is open. 6640 */ 6641 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6642 if (icmd->ipkt_nodma) { 6643 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6644 rsp->fcp_u.fcp_status.sense_len_set = 0; 6645 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6646 } else { 6647 fcp_rsp_t new_resp; 6648 6649 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6650 fpkt->pkt_resp_acc, sizeof (new_resp)); 6651 6652 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6653 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6654 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6655 6656 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6657 fpkt->pkt_resp_acc, sizeof (new_resp)); 6658 } 6659 6660 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6661 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6662 6663 return (DDI_SUCCESS); 6664 } 6665 6666 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6667 (FCP_SENSE_NO_LUN(sense))) { 6668 mutex_enter(&ptgt->tgt_mutex); 6669 if ((FCP_SENSE_NO_LUN(sense)) && 6670 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6671 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6672 mutex_exit(&ptgt->tgt_mutex); 6673 /* 6674 * reconfig was triggred by ILLEGAL REQUEST but 6675 * got ILLEGAL REQUEST again 6676 */ 6677 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6678 fcp_trace, FCP_BUF_LEVEL_3, 0, 6679 "!FCP: Unable to obtain Report Lun data" 6680 " target=%x", ptgt->tgt_d_id); 6681 } else { 6682 if (ptgt->tgt_tid == NULL) { 6683 timeout_id_t tid; 6684 /* 6685 * REPORT LUN data has changed. Kick off 6686 * rediscovery 6687 */ 6688 tid = timeout(fcp_reconfigure_luns, 6689 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6690 6691 ptgt->tgt_tid = tid; 6692 ptgt->tgt_state |= FCP_TGT_BUSY; 6693 } 6694 if (FCP_SENSE_NO_LUN(sense)) { 6695 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6696 } 6697 mutex_exit(&ptgt->tgt_mutex); 6698 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6699 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6700 fcp_trace, FCP_BUF_LEVEL_3, 0, 6701 "!FCP:Report Lun Has Changed" 6702 " target=%x", ptgt->tgt_d_id); 6703 } else if (FCP_SENSE_NO_LUN(sense)) { 6704 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6705 fcp_trace, FCP_BUF_LEVEL_3, 0, 6706 "!FCP:LU Not Supported" 6707 " target=%x", ptgt->tgt_d_id); 6708 } 6709 } 6710 rval = DDI_SUCCESS; 6711 } 6712 6713 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6714 fcp_trace, FCP_BUF_LEVEL_5, 0, 6715 "D_ID=%x, sense=%x, status=%x", 6716 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6717 rsp->fcp_u.fcp_status.scsi_status); 6718 6719 return (rval); 6720 } 6721 6722 /* 6723 * Function: fcp_scsi_callback 6724 * 6725 * Description: This is the callback routine set by fcp_send_scsi() after 6726 * it calls fcp_icmd_alloc(). The SCSI command completed here 6727 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6728 * INQUIRY_PAGE83. 6729 * 6730 * Argument: *fpkt FC packet used to convey the command 6731 * 6732 * Return Value: None 6733 */ 6734 static void 6735 fcp_scsi_callback(fc_packet_t *fpkt) 6736 { 6737 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6738 fpkt->pkt_ulp_private; 6739 struct fcp_rsp_info fcp_rsp_err, *bep; 6740 struct fcp_port *pptr; 6741 struct fcp_tgt *ptgt; 6742 struct fcp_lun *plun; 6743 struct fcp_rsp response, *rsp; 6744 6745 if (icmd->ipkt_nodma) { 6746 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6747 } else { 6748 rsp = &response; 6749 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6750 sizeof (struct fcp_rsp)); 6751 } 6752 6753 ptgt = icmd->ipkt_tgt; 6754 pptr = ptgt->tgt_port; 6755 plun = icmd->ipkt_lun; 6756 6757 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6758 fcp_trace, FCP_BUF_LEVEL_2, 0, 6759 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6760 "status=%x, lun num=%x", 6761 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6762 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6763 6764 /* 6765 * Pre-init LUN GUID with NWWN if it is not a device that 6766 * supports multiple luns and we know it's not page83 6767 * compliant. Although using a NWWN is not lun unique, 6768 * we will be fine since there is only one lun behind the taget 6769 * in this case. 6770 */ 6771 if ((plun->lun_guid_size == 0) && 6772 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6773 (fcp_symmetric_device_probe(plun) == 0)) { 6774 6775 char ascii_wwn[FC_WWN_SIZE*2+1]; 6776 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6777 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6778 } 6779 6780 /* 6781 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6782 * when thay have more data than what is asked in CDB. An overrun 6783 * is really when FCP_DL is smaller than the data length in CDB. 6784 * In the case here we know that REPORT LUN command we formed within 6785 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6786 * behavior. In reality this is FC_SUCCESS. 6787 */ 6788 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6789 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6790 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6791 fpkt->pkt_state = FC_PKT_SUCCESS; 6792 } 6793 6794 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6795 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6796 fcp_trace, FCP_BUF_LEVEL_2, 0, 6797 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6798 ptgt->tgt_d_id); 6799 6800 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6801 /* 6802 * Inquiry VPD page command on A5K SES devices would 6803 * result in data CRC errors. 6804 */ 6805 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6806 (void) fcp_handle_page83(fpkt, icmd, 1); 6807 return; 6808 } 6809 } 6810 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6811 FCP_MUST_RETRY(fpkt)) { 6812 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6813 fcp_retry_scsi_cmd(fpkt); 6814 return; 6815 } 6816 6817 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6818 FCP_TGT_TRACE_20); 6819 6820 mutex_enter(&pptr->port_mutex); 6821 mutex_enter(&ptgt->tgt_mutex); 6822 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6823 mutex_exit(&ptgt->tgt_mutex); 6824 mutex_exit(&pptr->port_mutex); 6825 fcp_print_error(fpkt); 6826 } else { 6827 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6828 fcp_trace, FCP_BUF_LEVEL_2, 0, 6829 "fcp_scsi_callback,1: state change occured" 6830 " for D_ID=0x%x", ptgt->tgt_d_id); 6831 mutex_exit(&ptgt->tgt_mutex); 6832 mutex_exit(&pptr->port_mutex); 6833 } 6834 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6835 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6836 fcp_icmd_free(pptr, icmd); 6837 return; 6838 } 6839 6840 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 6841 6842 mutex_enter(&pptr->port_mutex); 6843 mutex_enter(&ptgt->tgt_mutex); 6844 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6845 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6846 fcp_trace, FCP_BUF_LEVEL_2, 0, 6847 "fcp_scsi_callback,2: state change occured" 6848 " for D_ID=0x%x", ptgt->tgt_d_id); 6849 mutex_exit(&ptgt->tgt_mutex); 6850 mutex_exit(&pptr->port_mutex); 6851 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6852 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6853 fcp_icmd_free(pptr, icmd); 6854 return; 6855 } 6856 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 6857 6858 mutex_exit(&ptgt->tgt_mutex); 6859 mutex_exit(&pptr->port_mutex); 6860 6861 if (icmd->ipkt_nodma) { 6862 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 6863 sizeof (struct fcp_rsp)); 6864 } else { 6865 bep = &fcp_rsp_err; 6866 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 6867 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 6868 } 6869 6870 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 6871 fcp_retry_scsi_cmd(fpkt); 6872 return; 6873 } 6874 6875 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 6876 FCP_NO_FAILURE) { 6877 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6878 fcp_trace, FCP_BUF_LEVEL_2, 0, 6879 "rsp_code=0x%x, rsp_len_set=0x%x", 6880 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 6881 fcp_retry_scsi_cmd(fpkt); 6882 return; 6883 } 6884 6885 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 6886 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 6887 fcp_queue_ipkt(pptr, fpkt); 6888 return; 6889 } 6890 6891 /* 6892 * Devices that do not support INQUIRY_PAGE83, return check condition 6893 * with illegal request as per SCSI spec. 6894 * Crossbridge is one such device and Daktari's SES node is another. 6895 * We want to ideally enumerate these devices as a non-mpxio devices. 6896 * SES nodes (Daktari only currently) are an exception to this. 6897 */ 6898 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6899 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 6900 6901 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6902 fcp_trace, FCP_BUF_LEVEL_3, 0, 6903 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 6904 "check condition. May enumerate as non-mpxio device", 6905 ptgt->tgt_d_id, plun->lun_type); 6906 6907 /* 6908 * If we let Daktari's SES be enumerated as a non-mpxio 6909 * device, there will be a discrepency in that the other 6910 * internal FC disks will get enumerated as mpxio devices. 6911 * Applications like luxadm expect this to be consistent. 6912 * 6913 * So, we put in a hack here to check if this is an SES device 6914 * and handle it here. 6915 */ 6916 if (plun->lun_type == DTYPE_ESI) { 6917 /* 6918 * Since, pkt_state is actually FC_PKT_SUCCESS 6919 * at this stage, we fake a failure here so that 6920 * fcp_handle_page83 will create a device path using 6921 * the WWN instead of the GUID which is not there anyway 6922 */ 6923 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 6924 (void) fcp_handle_page83(fpkt, icmd, 1); 6925 return; 6926 } 6927 6928 mutex_enter(&ptgt->tgt_mutex); 6929 plun->lun_state &= ~(FCP_LUN_OFFLINE | 6930 FCP_LUN_MARK | FCP_LUN_BUSY); 6931 mutex_exit(&ptgt->tgt_mutex); 6932 6933 (void) fcp_call_finish_init(pptr, ptgt, 6934 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6935 icmd->ipkt_cause); 6936 fcp_icmd_free(pptr, icmd); 6937 return; 6938 } 6939 6940 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 6941 int rval = DDI_FAILURE; 6942 6943 /* 6944 * handle cases where report lun isn't supported 6945 * by faking up our own REPORT_LUN response or 6946 * UNIT ATTENTION 6947 */ 6948 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 6949 rval = fcp_check_reportlun(rsp, fpkt); 6950 6951 /* 6952 * fcp_check_reportlun might have modified the 6953 * FCP response. Copy it in again to get an updated 6954 * FCP response 6955 */ 6956 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 6957 rsp = &response; 6958 6959 FCP_CP_IN(fpkt->pkt_resp, rsp, 6960 fpkt->pkt_resp_acc, 6961 sizeof (struct fcp_rsp)); 6962 } 6963 } 6964 6965 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 6966 if (rval == DDI_SUCCESS) { 6967 (void) fcp_call_finish_init(pptr, ptgt, 6968 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6969 icmd->ipkt_cause); 6970 fcp_icmd_free(pptr, icmd); 6971 } else { 6972 fcp_retry_scsi_cmd(fpkt); 6973 } 6974 6975 return; 6976 } 6977 } else { 6978 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 6979 mutex_enter(&ptgt->tgt_mutex); 6980 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6981 mutex_exit(&ptgt->tgt_mutex); 6982 } 6983 } 6984 6985 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 6986 6987 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, DDI_DMA_SYNC_FORCPU); 6988 6989 switch (icmd->ipkt_opcode) { 6990 case SCMD_INQUIRY: 6991 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 6992 fcp_handle_inquiry(fpkt, icmd); 6993 break; 6994 6995 case SCMD_REPORT_LUN: 6996 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6997 FCP_TGT_TRACE_22); 6998 fcp_handle_reportlun(fpkt, icmd); 6999 break; 7000 7001 case SCMD_INQUIRY_PAGE83: 7002 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7003 (void) fcp_handle_page83(fpkt, icmd, 0); 7004 break; 7005 7006 default: 7007 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7008 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7009 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7010 fcp_icmd_free(pptr, icmd); 7011 break; 7012 } 7013 } 7014 7015 7016 static void 7017 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7018 { 7019 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7020 fpkt->pkt_ulp_private; 7021 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7022 struct fcp_port *pptr = ptgt->tgt_port; 7023 7024 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7025 fcp_is_retryable(icmd)) { 7026 mutex_enter(&pptr->port_mutex); 7027 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7028 mutex_exit(&pptr->port_mutex); 7029 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7030 fcp_trace, FCP_BUF_LEVEL_3, 0, 7031 "Retrying %s to %x; state=%x, reason=%x", 7032 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7033 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7034 fpkt->pkt_state, fpkt->pkt_reason); 7035 7036 fcp_queue_ipkt(pptr, fpkt); 7037 } else { 7038 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7039 fcp_trace, FCP_BUF_LEVEL_3, 0, 7040 "fcp_retry_scsi_cmd,1: state change occured" 7041 " for D_ID=0x%x", ptgt->tgt_d_id); 7042 mutex_exit(&pptr->port_mutex); 7043 (void) fcp_call_finish_init(pptr, ptgt, 7044 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7045 icmd->ipkt_cause); 7046 fcp_icmd_free(pptr, icmd); 7047 } 7048 } else { 7049 fcp_print_error(fpkt); 7050 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7051 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7052 fcp_icmd_free(pptr, icmd); 7053 } 7054 } 7055 7056 /* 7057 * Function: fcp_handle_page83 7058 * 7059 * Description: Treats the response to INQUIRY_PAGE83. 7060 * 7061 * Argument: *fpkt FC packet used to convey the command. 7062 * *icmd Original fcp_ipkt structure. 7063 * ignore_page83_data 7064 * if it's 1, that means it's a special devices's 7065 * page83 response, it should be enumerated under mpxio 7066 * 7067 * Return Value: None 7068 */ 7069 static void 7070 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7071 int ignore_page83_data) 7072 { 7073 struct fcp_port *pptr; 7074 struct fcp_lun *plun; 7075 struct fcp_tgt *ptgt; 7076 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7077 int fail = 0; 7078 ddi_devid_t devid; 7079 char *guid = NULL; 7080 int ret; 7081 7082 ASSERT(icmd != NULL && fpkt != NULL); 7083 7084 pptr = icmd->ipkt_port; 7085 ptgt = icmd->ipkt_tgt; 7086 plun = icmd->ipkt_lun; 7087 7088 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7089 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7090 7091 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7092 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7093 7094 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7095 fcp_trace, FCP_BUF_LEVEL_5, 0, 7096 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7097 "dtype=0x%x, lun num=%x", 7098 pptr->port_instance, ptgt->tgt_d_id, 7099 dev_id_page[0], plun->lun_num); 7100 7101 ret = ddi_devid_scsi_encode( 7102 DEVID_SCSI_ENCODE_VERSION_LATEST, 7103 NULL, /* driver name */ 7104 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7105 sizeof (plun->lun_inq), /* size of standard inquiry */ 7106 NULL, /* page 80 data */ 7107 0, /* page 80 len */ 7108 dev_id_page, /* page 83 data */ 7109 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7110 &devid); 7111 7112 if (ret == DDI_SUCCESS) { 7113 7114 guid = ddi_devid_to_guid(devid); 7115 7116 if (guid) { 7117 /* 7118 * Check our current guid. If it's non null 7119 * and it has changed, we need to copy it into 7120 * lun_old_guid since we might still need it. 7121 */ 7122 if (plun->lun_guid && 7123 strcmp(guid, plun->lun_guid)) { 7124 unsigned int len; 7125 7126 /* 7127 * If the guid of the LUN changes, 7128 * reconfiguration should be triggered 7129 * to reflect the changes. 7130 * i.e. we should offline the LUN with 7131 * the old guid, and online the LUN with 7132 * the new guid. 7133 */ 7134 plun->lun_state |= FCP_LUN_CHANGED; 7135 7136 if (plun->lun_old_guid) { 7137 kmem_free(plun->lun_old_guid, 7138 plun->lun_old_guid_size); 7139 } 7140 7141 len = plun->lun_guid_size; 7142 plun->lun_old_guid_size = len; 7143 7144 plun->lun_old_guid = kmem_zalloc(len, 7145 KM_NOSLEEP); 7146 7147 if (plun->lun_old_guid) { 7148 /* 7149 * The alloc was successful then 7150 * let's do the copy. 7151 */ 7152 bcopy(plun->lun_guid, 7153 plun->lun_old_guid, len); 7154 } else { 7155 fail = 1; 7156 plun->lun_old_guid_size = 0; 7157 } 7158 } 7159 if (!fail) { 7160 if (fcp_copy_guid_2_lun_block( 7161 plun, guid)) { 7162 fail = 1; 7163 } 7164 } 7165 ddi_devid_free_guid(guid); 7166 7167 } else { 7168 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7169 fcp_trace, FCP_BUF_LEVEL_2, 0, 7170 "fcp_handle_page83: unable to create " 7171 "GUID"); 7172 7173 /* couldn't create good guid from devid */ 7174 fail = 1; 7175 } 7176 ddi_devid_free(devid); 7177 7178 } else if (ret == DDI_NOT_WELL_FORMED) { 7179 /* NULL filled data for page 83 */ 7180 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7181 fcp_trace, FCP_BUF_LEVEL_2, 0, 7182 "fcp_handle_page83: retry GUID"); 7183 7184 icmd->ipkt_retries = 0; 7185 fcp_retry_scsi_cmd(fpkt); 7186 return; 7187 } else { 7188 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7189 fcp_trace, FCP_BUF_LEVEL_2, 0, 7190 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7191 ret); 7192 /* 7193 * Since the page83 validation 7194 * introduced late, we are being 7195 * tolerant to the existing devices 7196 * that already found to be working 7197 * under mpxio, like A5200's SES device, 7198 * its page83 response will not be standard-compliant, 7199 * but we still want it to be enumerated under mpxio. 7200 */ 7201 if (fcp_symmetric_device_probe(plun) != 0) { 7202 fail = 1; 7203 } 7204 } 7205 7206 } else { 7207 /* bad packet state */ 7208 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7209 7210 /* 7211 * For some special devices (A5K SES and Daktari's SES devices), 7212 * they should be enumerated under mpxio 7213 * or "luxadm dis" will fail 7214 */ 7215 if (ignore_page83_data) { 7216 fail = 0; 7217 } else { 7218 fail = 1; 7219 } 7220 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7221 fcp_trace, FCP_BUF_LEVEL_2, 0, 7222 "!Devid page cmd failed. " 7223 "fpkt_state: %x fpkt_reason: %x", 7224 "ignore_page83: %d", 7225 fpkt->pkt_state, fpkt->pkt_reason, 7226 ignore_page83_data); 7227 } 7228 7229 mutex_enter(&pptr->port_mutex); 7230 mutex_enter(&plun->lun_mutex); 7231 /* 7232 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7233 * mismatch between lun_cip and lun_mpxio. 7234 */ 7235 if (plun->lun_cip == NULL) { 7236 /* 7237 * If we don't have a guid for this lun it's because we were 7238 * unable to glean one from the page 83 response. Set the 7239 * control flag to 0 here to make sure that we don't attempt to 7240 * enumerate it under mpxio. 7241 */ 7242 if (fail || pptr->port_mpxio == 0) { 7243 plun->lun_mpxio = 0; 7244 } else { 7245 plun->lun_mpxio = 1; 7246 } 7247 } 7248 mutex_exit(&plun->lun_mutex); 7249 mutex_exit(&pptr->port_mutex); 7250 7251 mutex_enter(&ptgt->tgt_mutex); 7252 plun->lun_state &= 7253 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7254 mutex_exit(&ptgt->tgt_mutex); 7255 7256 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7257 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7258 7259 fcp_icmd_free(pptr, icmd); 7260 } 7261 7262 /* 7263 * Function: fcp_handle_inquiry 7264 * 7265 * Description: Called by fcp_scsi_callback to handle the response to an 7266 * INQUIRY request. 7267 * 7268 * Argument: *fpkt FC packet used to convey the command. 7269 * *icmd Original fcp_ipkt structure. 7270 * 7271 * Return Value: None 7272 */ 7273 static void 7274 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7275 { 7276 struct fcp_port *pptr; 7277 struct fcp_lun *plun; 7278 struct fcp_tgt *ptgt; 7279 uchar_t dtype; 7280 uchar_t pqual; 7281 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7282 7283 ASSERT(icmd != NULL && fpkt != NULL); 7284 7285 pptr = icmd->ipkt_port; 7286 ptgt = icmd->ipkt_tgt; 7287 plun = icmd->ipkt_lun; 7288 7289 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7290 sizeof (struct scsi_inquiry)); 7291 7292 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7293 pqual = plun->lun_inq.inq_dtype >> 5; 7294 7295 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7296 fcp_trace, FCP_BUF_LEVEL_5, 0, 7297 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7298 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7299 plun->lun_num, dtype, pqual); 7300 7301 if (pqual != 0) { 7302 /* 7303 * Non-zero peripheral qualifier 7304 */ 7305 fcp_log(CE_CONT, pptr->port_dip, 7306 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7307 "Device type=0x%x Peripheral qual=0x%x\n", 7308 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7309 7310 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7311 fcp_trace, FCP_BUF_LEVEL_5, 0, 7312 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7313 "Device type=0x%x Peripheral qual=0x%x\n", 7314 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7315 7316 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7317 7318 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7319 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7320 fcp_icmd_free(pptr, icmd); 7321 return; 7322 } 7323 7324 /* 7325 * If the device is already initialized, check the dtype 7326 * for a change. If it has changed then update the flags 7327 * so the create_luns will offline the old device and 7328 * create the new device. Refer to bug: 4764752 7329 */ 7330 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7331 plun->lun_state |= FCP_LUN_CHANGED; 7332 } 7333 plun->lun_type = plun->lun_inq.inq_dtype; 7334 7335 /* 7336 * This code is setting/initializing the throttling in the FCA 7337 * driver. 7338 */ 7339 mutex_enter(&pptr->port_mutex); 7340 if (!pptr->port_notify) { 7341 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7342 uint32_t cmd = 0; 7343 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7344 ((cmd & 0xFFFFFF00 >> 8) | 7345 FCP_SVE_THROTTLE << 8)); 7346 pptr->port_notify = 1; 7347 mutex_exit(&pptr->port_mutex); 7348 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7349 mutex_enter(&pptr->port_mutex); 7350 } 7351 } 7352 7353 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7354 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7355 fcp_trace, FCP_BUF_LEVEL_2, 0, 7356 "fcp_handle_inquiry,1:state change occured" 7357 " for D_ID=0x%x", ptgt->tgt_d_id); 7358 mutex_exit(&pptr->port_mutex); 7359 7360 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7361 (void) fcp_call_finish_init(pptr, ptgt, 7362 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7363 icmd->ipkt_cause); 7364 fcp_icmd_free(pptr, icmd); 7365 return; 7366 } 7367 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7368 mutex_exit(&pptr->port_mutex); 7369 7370 /* Retrieve the rscn count (if a valid one exists) */ 7371 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7372 rscn_count = ((fc_ulp_rscn_info_t *) 7373 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7374 } else { 7375 rscn_count = FC_INVALID_RSCN_COUNT; 7376 } 7377 7378 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7379 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7380 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7381 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7382 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7383 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7384 (void) fcp_call_finish_init(pptr, ptgt, 7385 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7386 icmd->ipkt_cause); 7387 } 7388 7389 /* 7390 * Read Inquiry VPD Page 0x83 to uniquely 7391 * identify this logical unit. 7392 */ 7393 fcp_icmd_free(pptr, icmd); 7394 } 7395 7396 /* 7397 * Function: fcp_handle_reportlun 7398 * 7399 * Description: Called by fcp_scsi_callback to handle the response to a 7400 * REPORT_LUN request. 7401 * 7402 * Argument: *fpkt FC packet used to convey the command. 7403 * *icmd Original fcp_ipkt structure. 7404 * 7405 * Return Value: None 7406 */ 7407 static void 7408 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7409 { 7410 int i; 7411 int nluns_claimed; 7412 int nluns_bufmax; 7413 int len; 7414 uint16_t lun_num; 7415 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7416 struct fcp_port *pptr; 7417 struct fcp_tgt *ptgt; 7418 struct fcp_lun *plun; 7419 struct fcp_reportlun_resp *report_lun; 7420 7421 pptr = icmd->ipkt_port; 7422 ptgt = icmd->ipkt_tgt; 7423 len = fpkt->pkt_datalen; 7424 7425 if ((len < FCP_LUN_HEADER) || 7426 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7427 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7428 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7429 fcp_icmd_free(pptr, icmd); 7430 return; 7431 } 7432 7433 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7434 fpkt->pkt_datalen); 7435 7436 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7437 fcp_trace, FCP_BUF_LEVEL_5, 0, 7438 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7439 pptr->port_instance, ptgt->tgt_d_id); 7440 7441 /* 7442 * Get the number of luns (which is supplied as LUNS * 8) the 7443 * device claims it has. 7444 */ 7445 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7446 7447 /* 7448 * Get the maximum number of luns the buffer submitted can hold. 7449 */ 7450 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7451 7452 /* 7453 * Due to limitations of certain hardware, we support only 16 bit LUNs 7454 */ 7455 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7456 kmem_free(report_lun, len); 7457 7458 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7459 " 0x%x number of LUNs for target=%x", nluns_claimed, 7460 ptgt->tgt_d_id); 7461 7462 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7463 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7464 fcp_icmd_free(pptr, icmd); 7465 return; 7466 } 7467 7468 /* 7469 * If there are more LUNs than we have allocated memory for, 7470 * allocate more space and send down yet another report lun if 7471 * the maximum number of attempts hasn't been reached. 7472 */ 7473 mutex_enter(&ptgt->tgt_mutex); 7474 7475 if ((nluns_claimed > nluns_bufmax) && 7476 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7477 7478 struct fcp_lun *plun; 7479 7480 ptgt->tgt_report_lun_cnt++; 7481 plun = ptgt->tgt_lun; 7482 ASSERT(plun != NULL); 7483 mutex_exit(&ptgt->tgt_mutex); 7484 7485 kmem_free(report_lun, len); 7486 7487 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7488 fcp_trace, FCP_BUF_LEVEL_5, 0, 7489 "!Dynamically discovered %d LUNs for D_ID=%x", 7490 nluns_claimed, ptgt->tgt_d_id); 7491 7492 /* Retrieve the rscn count (if a valid one exists) */ 7493 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7494 rscn_count = ((fc_ulp_rscn_info_t *) 7495 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7496 ulp_rscn_count; 7497 } else { 7498 rscn_count = FC_INVALID_RSCN_COUNT; 7499 } 7500 7501 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7502 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7503 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7504 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7505 (void) fcp_call_finish_init(pptr, ptgt, 7506 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7507 icmd->ipkt_cause); 7508 } 7509 7510 fcp_icmd_free(pptr, icmd); 7511 return; 7512 } 7513 7514 if (nluns_claimed > nluns_bufmax) { 7515 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7516 fcp_trace, FCP_BUF_LEVEL_5, 0, 7517 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7518 " Number of LUNs lost=%x", 7519 ptgt->tgt_port_wwn.raw_wwn[0], 7520 ptgt->tgt_port_wwn.raw_wwn[1], 7521 ptgt->tgt_port_wwn.raw_wwn[2], 7522 ptgt->tgt_port_wwn.raw_wwn[3], 7523 ptgt->tgt_port_wwn.raw_wwn[4], 7524 ptgt->tgt_port_wwn.raw_wwn[5], 7525 ptgt->tgt_port_wwn.raw_wwn[6], 7526 ptgt->tgt_port_wwn.raw_wwn[7], 7527 nluns_claimed - nluns_bufmax); 7528 7529 nluns_claimed = nluns_bufmax; 7530 } 7531 ptgt->tgt_lun_cnt = nluns_claimed; 7532 7533 /* 7534 * Identify missing LUNs and print warning messages 7535 */ 7536 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7537 int offline; 7538 int exists = 0; 7539 7540 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7541 7542 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7543 uchar_t *lun_string; 7544 7545 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7546 7547 switch (lun_string[0] & 0xC0) { 7548 case FCP_LUN_ADDRESSING: 7549 case FCP_PD_ADDRESSING: 7550 lun_num = ((lun_string[0] & 0x3F) << 8) | 7551 lun_string[1]; 7552 if (plun->lun_num == lun_num) { 7553 exists++; 7554 break; 7555 } 7556 break; 7557 7558 default: 7559 break; 7560 } 7561 } 7562 7563 if (!exists && !offline) { 7564 mutex_exit(&ptgt->tgt_mutex); 7565 7566 mutex_enter(&pptr->port_mutex); 7567 mutex_enter(&ptgt->tgt_mutex); 7568 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7569 /* 7570 * set disappear flag when device was connected 7571 */ 7572 if (!(plun->lun_state & 7573 FCP_LUN_DEVICE_NOT_CONNECTED)) 7574 plun->lun_state |= FCP_LUN_DISAPPEARED; 7575 mutex_exit(&ptgt->tgt_mutex); 7576 mutex_exit(&pptr->port_mutex); 7577 if (!(plun->lun_state & 7578 FCP_LUN_DEVICE_NOT_CONNECTED)) 7579 fcp_log(CE_NOTE, pptr->port_dip, 7580 "!Lun=%x for target=%x disappeared", 7581 plun->lun_num, ptgt->tgt_d_id); 7582 mutex_enter(&ptgt->tgt_mutex); 7583 } else { 7584 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7585 fcp_trace, FCP_BUF_LEVEL_5, 0, 7586 "fcp_handle_reportlun,1: state change" 7587 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7588 mutex_exit(&ptgt->tgt_mutex); 7589 mutex_exit(&pptr->port_mutex); 7590 kmem_free(report_lun, len); 7591 (void) fcp_call_finish_init(pptr, ptgt, 7592 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7593 icmd->ipkt_cause); 7594 fcp_icmd_free(pptr, icmd); 7595 return; 7596 } 7597 } else if (exists) { 7598 /* 7599 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7600 * actually exists in REPORT_LUN response 7601 */ 7602 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) 7603 plun->lun_state &= 7604 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7605 if (offline || plun->lun_num == 0) { 7606 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7607 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7608 mutex_exit(&ptgt->tgt_mutex); 7609 fcp_log(CE_NOTE, pptr->port_dip, 7610 "!Lun=%x for target=%x reappeared", 7611 plun->lun_num, ptgt->tgt_d_id); 7612 mutex_enter(&ptgt->tgt_mutex); 7613 } 7614 } 7615 } 7616 } 7617 7618 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7619 mutex_exit(&ptgt->tgt_mutex); 7620 7621 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7622 fcp_trace, FCP_BUF_LEVEL_5, 0, 7623 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7624 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7625 7626 /* scan each lun */ 7627 for (i = 0; i < nluns_claimed; i++) { 7628 uchar_t *lun_string; 7629 7630 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7631 7632 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7633 fcp_trace, FCP_BUF_LEVEL_5, 0, 7634 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7635 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7636 lun_string[0]); 7637 7638 switch (lun_string[0] & 0xC0) { 7639 case FCP_LUN_ADDRESSING: 7640 case FCP_PD_ADDRESSING: 7641 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7642 7643 /* We will skip masked LUNs because of the blacklist. */ 7644 if (fcp_lun_blacklist != NULL) { 7645 mutex_enter(&ptgt->tgt_mutex); 7646 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7647 lun_num) == TRUE) { 7648 ptgt->tgt_lun_cnt--; 7649 mutex_exit(&ptgt->tgt_mutex); 7650 break; 7651 } 7652 mutex_exit(&ptgt->tgt_mutex); 7653 } 7654 7655 /* see if this LUN is already allocated */ 7656 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7657 plun = fcp_alloc_lun(ptgt); 7658 if (plun == NULL) { 7659 fcp_log(CE_NOTE, pptr->port_dip, 7660 "!Lun allocation failed" 7661 " target=%x lun=%x", 7662 ptgt->tgt_d_id, lun_num); 7663 break; 7664 } 7665 } 7666 7667 mutex_enter(&plun->lun_tgt->tgt_mutex); 7668 /* convert to LUN */ 7669 plun->lun_addr.ent_addr_0 = 7670 BE_16(*(uint16_t *)&(lun_string[0])); 7671 plun->lun_addr.ent_addr_1 = 7672 BE_16(*(uint16_t *)&(lun_string[2])); 7673 plun->lun_addr.ent_addr_2 = 7674 BE_16(*(uint16_t *)&(lun_string[4])); 7675 plun->lun_addr.ent_addr_3 = 7676 BE_16(*(uint16_t *)&(lun_string[6])); 7677 7678 plun->lun_num = lun_num; 7679 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7680 plun->lun_state &= ~FCP_LUN_OFFLINE; 7681 mutex_exit(&plun->lun_tgt->tgt_mutex); 7682 7683 /* Retrieve the rscn count (if a valid one exists) */ 7684 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7685 rscn_count = ((fc_ulp_rscn_info_t *) 7686 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7687 ulp_rscn_count; 7688 } else { 7689 rscn_count = FC_INVALID_RSCN_COUNT; 7690 } 7691 7692 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7693 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7694 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7695 mutex_enter(&pptr->port_mutex); 7696 mutex_enter(&plun->lun_tgt->tgt_mutex); 7697 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7698 fcp_log(CE_NOTE, pptr->port_dip, 7699 "!failed to send INQUIRY" 7700 " target=%x lun=%x", 7701 ptgt->tgt_d_id, plun->lun_num); 7702 } else { 7703 FCP_TRACE(fcp_logq, 7704 pptr->port_instbuf, fcp_trace, 7705 FCP_BUF_LEVEL_5, 0, 7706 "fcp_handle_reportlun,2: state" 7707 " change occured for D_ID=0x%x", 7708 ptgt->tgt_d_id); 7709 } 7710 mutex_exit(&plun->lun_tgt->tgt_mutex); 7711 mutex_exit(&pptr->port_mutex); 7712 } else { 7713 continue; 7714 } 7715 break; 7716 7717 case FCP_VOLUME_ADDRESSING: 7718 /* FALLTHROUGH */ 7719 default: 7720 fcp_log(CE_WARN, NULL, 7721 "!Unsupported LUN Addressing method %x " 7722 "in response to REPORT_LUN", lun_string[0]); 7723 break; 7724 } 7725 7726 /* 7727 * each time through this loop we should decrement 7728 * the tmp_cnt by one -- since we go through this loop 7729 * one time for each LUN, the tmp_cnt should never be <=0 7730 */ 7731 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7732 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7733 } 7734 7735 if (i == 0) { 7736 fcp_log(CE_WARN, pptr->port_dip, 7737 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7738 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7739 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7740 } 7741 7742 kmem_free(report_lun, len); 7743 fcp_icmd_free(pptr, icmd); 7744 } 7745 7746 7747 /* 7748 * called internally to return a LUN given a target and a LUN number 7749 */ 7750 static struct fcp_lun * 7751 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7752 { 7753 struct fcp_lun *plun; 7754 7755 mutex_enter(&ptgt->tgt_mutex); 7756 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7757 if (plun->lun_num == lun_num) { 7758 mutex_exit(&ptgt->tgt_mutex); 7759 return (plun); 7760 } 7761 } 7762 mutex_exit(&ptgt->tgt_mutex); 7763 7764 return (NULL); 7765 } 7766 7767 7768 /* 7769 * handle finishing one target for fcp_finish_init 7770 * 7771 * return true (non-zero) if we want finish_init to continue with the 7772 * next target 7773 * 7774 * called with the port mutex held 7775 */ 7776 /*ARGSUSED*/ 7777 static int 7778 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7779 int link_cnt, int tgt_cnt, int cause) 7780 { 7781 int rval = 1; 7782 ASSERT(pptr != NULL); 7783 ASSERT(ptgt != NULL); 7784 7785 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7786 fcp_trace, FCP_BUF_LEVEL_5, 0, 7787 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7788 ptgt->tgt_state); 7789 7790 ASSERT(mutex_owned(&pptr->port_mutex)); 7791 7792 if ((pptr->port_link_cnt != link_cnt) || 7793 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7794 /* 7795 * oh oh -- another link reset or target change 7796 * must have occurred while we are in here 7797 */ 7798 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7799 7800 return (0); 7801 } else { 7802 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7803 } 7804 7805 mutex_enter(&ptgt->tgt_mutex); 7806 7807 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7808 /* 7809 * tgt is not offline -- is it marked (i.e. needs 7810 * to be offlined) ?? 7811 */ 7812 if (ptgt->tgt_state & FCP_TGT_MARK) { 7813 /* 7814 * this target not offline *and* 7815 * marked 7816 */ 7817 ptgt->tgt_state &= ~FCP_TGT_MARK; 7818 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7819 tgt_cnt, 0, 0); 7820 } else { 7821 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7822 7823 /* create the LUNs */ 7824 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7825 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7826 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7827 cause); 7828 ptgt->tgt_device_created = 1; 7829 } else { 7830 fcp_update_tgt_state(ptgt, FCP_RESET, 7831 FCP_LUN_BUSY); 7832 } 7833 } 7834 } 7835 7836 mutex_exit(&ptgt->tgt_mutex); 7837 7838 return (rval); 7839 } 7840 7841 7842 /* 7843 * this routine is called to finish port initialization 7844 * 7845 * Each port has a "temp" counter -- when a state change happens (e.g. 7846 * port online), the temp count is set to the number of devices in the map. 7847 * Then, as each device gets "discovered", the temp counter is decremented 7848 * by one. When this count reaches zero we know that all of the devices 7849 * in the map have been discovered (or an error has occurred), so we can 7850 * then finish initialization -- which is done by this routine (well, this 7851 * and fcp-finish_tgt()) 7852 * 7853 * acquires and releases the global mutex 7854 * 7855 * called with the port mutex owned 7856 */ 7857 static void 7858 fcp_finish_init(struct fcp_port *pptr) 7859 { 7860 #ifdef DEBUG 7861 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 7862 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 7863 FCP_STACK_DEPTH); 7864 #endif /* DEBUG */ 7865 7866 ASSERT(mutex_owned(&pptr->port_mutex)); 7867 7868 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7869 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 7870 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 7871 7872 if ((pptr->port_state & FCP_STATE_ONLINING) && 7873 !(pptr->port_state & (FCP_STATE_SUSPENDED | 7874 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 7875 pptr->port_state &= ~FCP_STATE_ONLINING; 7876 pptr->port_state |= FCP_STATE_ONLINE; 7877 } 7878 7879 /* Wake up threads waiting on config done */ 7880 cv_broadcast(&pptr->port_config_cv); 7881 } 7882 7883 7884 /* 7885 * called from fcp_finish_init to create the LUNs for a target 7886 * 7887 * called with the port mutex owned 7888 */ 7889 static void 7890 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 7891 { 7892 struct fcp_lun *plun; 7893 struct fcp_port *pptr; 7894 child_info_t *cip = NULL; 7895 7896 ASSERT(ptgt != NULL); 7897 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 7898 7899 pptr = ptgt->tgt_port; 7900 7901 ASSERT(pptr != NULL); 7902 7903 /* scan all LUNs for this target */ 7904 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7905 if (plun->lun_state & FCP_LUN_OFFLINE) { 7906 continue; 7907 } 7908 7909 if (plun->lun_state & FCP_LUN_MARK) { 7910 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7911 fcp_trace, FCP_BUF_LEVEL_2, 0, 7912 "fcp_create_luns: offlining marked LUN!"); 7913 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 7914 continue; 7915 } 7916 7917 plun->lun_state &= ~FCP_LUN_BUSY; 7918 7919 /* 7920 * There are conditions in which FCP_LUN_INIT flag is cleared 7921 * but we have a valid plun->lun_cip. To cover this case also 7922 * CLEAR_BUSY whenever we have a valid lun_cip. 7923 */ 7924 if (plun->lun_mpxio && plun->lun_cip && 7925 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 7926 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 7927 0, 0))) { 7928 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7929 fcp_trace, FCP_BUF_LEVEL_2, 0, 7930 "fcp_create_luns: enable lun %p failed!", 7931 plun); 7932 } 7933 7934 if (plun->lun_state & FCP_LUN_INIT && 7935 !(plun->lun_state & FCP_LUN_CHANGED)) { 7936 continue; 7937 } 7938 7939 if (cause == FCP_CAUSE_USER_CREATE) { 7940 continue; 7941 } 7942 7943 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7944 fcp_trace, FCP_BUF_LEVEL_6, 0, 7945 "create_luns: passing ONLINE elem to HP thread"); 7946 7947 /* 7948 * If lun has changed, prepare for offlining the old path. 7949 * Do not offline the old path right now, since it may be 7950 * still opened. 7951 */ 7952 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 7953 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 7954 } 7955 7956 /* pass an ONLINE element to the hotplug thread */ 7957 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 7958 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 7959 7960 /* 7961 * We can not synchronous attach (i.e pass 7962 * NDI_ONLINE_ATTACH) here as we might be 7963 * coming from an interrupt or callback 7964 * thread. 7965 */ 7966 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 7967 link_cnt, tgt_cnt, 0, 0)) { 7968 fcp_log(CE_CONT, pptr->port_dip, 7969 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 7970 plun->lun_tgt->tgt_d_id, plun->lun_num); 7971 } 7972 } 7973 } 7974 } 7975 7976 7977 /* 7978 * function to online/offline devices 7979 */ 7980 static int 7981 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int online, 7982 int lcount, int tcount, int flags) 7983 { 7984 int rval = NDI_FAILURE; 7985 int circ; 7986 child_info_t *ccip; 7987 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 7988 int is_mpxio = pptr->port_mpxio; 7989 dev_info_t *cdip, *pdip; 7990 char *devname; 7991 7992 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7993 fcp_trace, FCP_BUF_LEVEL_2, 0, 7994 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 7995 "flags=%x mpxio=%x\n", 7996 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 7997 plun->lun_mpxio); 7998 7999 /* 8000 * lun_mpxio needs checking here because we can end up in a race 8001 * condition where this task has been dispatched while lun_mpxio is 8002 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8003 * enable MPXIO for the LUN, but was unable to, and hence cleared 8004 * the flag. We rely on the serialization of the tasks here. We return 8005 * NDI_SUCCESS so any callers continue without reporting spurious 8006 * errors, and the still think we're an MPXIO LUN. 8007 */ 8008 8009 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8010 online == FCP_MPXIO_PATH_SET_BUSY) { 8011 if (plun->lun_mpxio) 8012 rval = fcp_update_mpxio_path(plun, cip, online); 8013 else 8014 rval = NDI_SUCCESS; 8015 return (rval); 8016 } 8017 8018 /* 8019 * Explicit devfs_clean() due to ndi_devi_offline() not 8020 * executing devfs_clean() if parent lock is held. 8021 */ 8022 ASSERT(!servicing_interrupt()); 8023 if (online == FCP_OFFLINE) { 8024 if (plun->lun_mpxio == 0) { 8025 if (plun->lun_cip == cip) 8026 cdip = DIP(plun->lun_cip); 8027 else 8028 cdip = DIP(cip); 8029 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8030 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8031 } else if ((plun->lun_cip != cip) && cip) { 8032 /* 8033 * This means a DTYPE/GUID change, we shall get the 8034 * dip of the old cip instead of the current lun_cip. 8035 */ 8036 cdip = mdi_pi_get_client(PIP(cip)); 8037 } 8038 if (cdip) { 8039 if (i_ddi_devi_attached(cdip)) { 8040 pdip = ddi_get_parent(cdip); 8041 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8042 ndi_devi_enter(pdip, &circ); 8043 (void) ddi_deviname(cdip, devname); 8044 ndi_devi_exit(pdip, circ); 8045 /* 8046 * Release parent lock before calling 8047 * devfs_clean(). 8048 */ 8049 rval = devfs_clean(pdip, devname + 1, 8050 DV_CLEAN_FORCE); 8051 kmem_free(devname, MAXNAMELEN + 1); 8052 /* 8053 * Return if devfs_clean() fails for 8054 * non-MPXIO case. 8055 * For MPXIO case, another path could be 8056 * offlined. 8057 */ 8058 if (rval && plun->lun_mpxio == 0) { 8059 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8060 fcp_trace, FCP_BUF_LEVEL_3, 0, 8061 "fcp_trigger_lun: devfs_clean " 8062 "failed rval=%x dip=%p", 8063 rval, pdip); 8064 return (NDI_FAILURE); 8065 } 8066 } 8067 } 8068 } 8069 8070 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8071 return (NDI_FAILURE); 8072 } 8073 8074 if (is_mpxio) 8075 mdi_devi_enter(pptr->port_dip, &circ); 8076 else 8077 ndi_devi_enter(pptr->port_dip, &circ); 8078 8079 mutex_enter(&pptr->port_mutex); 8080 mutex_enter(&plun->lun_mutex); 8081 8082 if (online == FCP_ONLINE) { 8083 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8084 if (ccip == NULL) { 8085 goto fail; 8086 } 8087 } else { 8088 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8089 goto fail; 8090 } 8091 ccip = cip; 8092 } 8093 8094 if (online == FCP_ONLINE) { 8095 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8096 &circ); 8097 fc_ulp_log_device_event(pptr->port_fp_handle, 8098 FC_ULP_DEVICE_ONLINE); 8099 } else { 8100 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8101 &circ); 8102 fc_ulp_log_device_event(pptr->port_fp_handle, 8103 FC_ULP_DEVICE_OFFLINE); 8104 } 8105 8106 fail: mutex_exit(&plun->lun_mutex); 8107 mutex_exit(&pptr->port_mutex); 8108 8109 if (is_mpxio) 8110 mdi_devi_exit(pptr->port_dip, circ); 8111 else 8112 ndi_devi_exit(pptr->port_dip, circ); 8113 8114 fc_ulp_idle_port(pptr->port_fp_handle); 8115 8116 return (rval); 8117 } 8118 8119 8120 /* 8121 * take a target offline by taking all of its LUNs offline 8122 */ 8123 /*ARGSUSED*/ 8124 static int 8125 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8126 int link_cnt, int tgt_cnt, int nowait, int flags) 8127 { 8128 struct fcp_tgt_elem *elem; 8129 8130 ASSERT(mutex_owned(&pptr->port_mutex)); 8131 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8132 8133 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8134 8135 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8136 ptgt->tgt_change_cnt)) { 8137 mutex_exit(&ptgt->tgt_mutex); 8138 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8139 mutex_enter(&ptgt->tgt_mutex); 8140 8141 return (0); 8142 } 8143 8144 ptgt->tgt_pd_handle = NULL; 8145 mutex_exit(&ptgt->tgt_mutex); 8146 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8147 mutex_enter(&ptgt->tgt_mutex); 8148 8149 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8150 8151 if (ptgt->tgt_tcap && 8152 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8153 elem->flags = flags; 8154 elem->time = fcp_watchdog_time; 8155 if (nowait == 0) { 8156 elem->time += fcp_offline_delay; 8157 } 8158 elem->ptgt = ptgt; 8159 elem->link_cnt = link_cnt; 8160 elem->tgt_cnt = tgt_cnt; 8161 elem->next = pptr->port_offline_tgts; 8162 pptr->port_offline_tgts = elem; 8163 } else { 8164 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8165 } 8166 8167 return (1); 8168 } 8169 8170 8171 static void 8172 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8173 int link_cnt, int tgt_cnt, int flags) 8174 { 8175 ASSERT(mutex_owned(&pptr->port_mutex)); 8176 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8177 8178 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8179 ptgt->tgt_state = FCP_TGT_OFFLINE; 8180 ptgt->tgt_pd_handle = NULL; 8181 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8182 } 8183 8184 8185 static void 8186 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8187 int flags) 8188 { 8189 struct fcp_lun *plun; 8190 8191 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8192 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8193 8194 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8195 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8196 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8197 } 8198 } 8199 } 8200 8201 8202 /* 8203 * take a LUN offline 8204 * 8205 * enters and leaves with the target mutex held, releasing it in the process 8206 * 8207 * allocates memory in non-sleep mode 8208 */ 8209 static void 8210 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8211 int nowait, int flags) 8212 { 8213 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8214 struct fcp_lun_elem *elem; 8215 8216 ASSERT(plun != NULL); 8217 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8218 8219 if (nowait) { 8220 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8221 return; 8222 } 8223 8224 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8225 elem->flags = flags; 8226 elem->time = fcp_watchdog_time; 8227 if (nowait == 0) { 8228 elem->time += fcp_offline_delay; 8229 } 8230 elem->plun = plun; 8231 elem->link_cnt = link_cnt; 8232 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8233 elem->next = pptr->port_offline_luns; 8234 pptr->port_offline_luns = elem; 8235 } else { 8236 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8237 } 8238 } 8239 8240 8241 static void 8242 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8243 { 8244 struct fcp_pkt *head = NULL; 8245 8246 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8247 8248 mutex_exit(&LUN_TGT->tgt_mutex); 8249 8250 head = fcp_scan_commands(plun); 8251 if (head != NULL) { 8252 fcp_abort_commands(head, LUN_PORT); 8253 } 8254 8255 mutex_enter(&LUN_TGT->tgt_mutex); 8256 8257 if (plun->lun_cip && plun->lun_mpxio) { 8258 /* 8259 * Intimate MPxIO lun busy is cleared 8260 */ 8261 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8262 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8263 0, 0)) { 8264 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8265 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8266 LUN_TGT->tgt_d_id, plun->lun_num); 8267 } 8268 /* 8269 * Intimate MPxIO that the lun is now marked for offline 8270 */ 8271 mutex_exit(&LUN_TGT->tgt_mutex); 8272 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8273 mutex_enter(&LUN_TGT->tgt_mutex); 8274 } 8275 } 8276 8277 static void 8278 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8279 int flags) 8280 { 8281 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8282 8283 mutex_exit(&LUN_TGT->tgt_mutex); 8284 fcp_update_offline_flags(plun); 8285 mutex_enter(&LUN_TGT->tgt_mutex); 8286 8287 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8288 8289 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8290 fcp_trace, FCP_BUF_LEVEL_4, 0, 8291 "offline_lun: passing OFFLINE elem to HP thread"); 8292 8293 if (plun->lun_cip) { 8294 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8295 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8296 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8297 LUN_TGT->tgt_trace); 8298 8299 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8300 link_cnt, tgt_cnt, flags, 0)) { 8301 fcp_log(CE_CONT, LUN_PORT->port_dip, 8302 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8303 LUN_TGT->tgt_d_id, plun->lun_num); 8304 } 8305 } 8306 } 8307 8308 static void 8309 fcp_scan_offline_luns(struct fcp_port *pptr) 8310 { 8311 struct fcp_lun_elem *elem; 8312 struct fcp_lun_elem *prev; 8313 struct fcp_lun_elem *next; 8314 8315 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8316 8317 prev = NULL; 8318 elem = pptr->port_offline_luns; 8319 while (elem) { 8320 next = elem->next; 8321 if (elem->time <= fcp_watchdog_time) { 8322 int changed = 1; 8323 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8324 8325 mutex_enter(&ptgt->tgt_mutex); 8326 if (pptr->port_link_cnt == elem->link_cnt && 8327 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8328 changed = 0; 8329 } 8330 8331 if (!changed && 8332 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8333 fcp_offline_lun_now(elem->plun, 8334 elem->link_cnt, elem->tgt_cnt, elem->flags); 8335 } 8336 mutex_exit(&ptgt->tgt_mutex); 8337 8338 kmem_free(elem, sizeof (*elem)); 8339 8340 if (prev) { 8341 prev->next = next; 8342 } else { 8343 pptr->port_offline_luns = next; 8344 } 8345 } else { 8346 prev = elem; 8347 } 8348 elem = next; 8349 } 8350 } 8351 8352 8353 static void 8354 fcp_scan_offline_tgts(struct fcp_port *pptr) 8355 { 8356 struct fcp_tgt_elem *elem; 8357 struct fcp_tgt_elem *prev; 8358 struct fcp_tgt_elem *next; 8359 8360 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8361 8362 prev = NULL; 8363 elem = pptr->port_offline_tgts; 8364 while (elem) { 8365 next = elem->next; 8366 if (elem->time <= fcp_watchdog_time) { 8367 int changed = 1; 8368 struct fcp_tgt *ptgt = elem->ptgt; 8369 8370 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8371 changed = 0; 8372 } 8373 8374 mutex_enter(&ptgt->tgt_mutex); 8375 if (!changed && !(ptgt->tgt_state & 8376 FCP_TGT_OFFLINE)) { 8377 fcp_offline_target_now(pptr, 8378 ptgt, elem->link_cnt, elem->tgt_cnt, 8379 elem->flags); 8380 } 8381 mutex_exit(&ptgt->tgt_mutex); 8382 8383 kmem_free(elem, sizeof (*elem)); 8384 8385 if (prev) { 8386 prev->next = next; 8387 } else { 8388 pptr->port_offline_tgts = next; 8389 } 8390 } else { 8391 prev = elem; 8392 } 8393 elem = next; 8394 } 8395 } 8396 8397 8398 static void 8399 fcp_update_offline_flags(struct fcp_lun *plun) 8400 { 8401 struct fcp_port *pptr = LUN_PORT; 8402 ASSERT(plun != NULL); 8403 8404 mutex_enter(&LUN_TGT->tgt_mutex); 8405 plun->lun_state |= FCP_LUN_OFFLINE; 8406 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8407 8408 mutex_enter(&plun->lun_mutex); 8409 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8410 dev_info_t *cdip = NULL; 8411 8412 mutex_exit(&LUN_TGT->tgt_mutex); 8413 8414 if (plun->lun_mpxio == 0) { 8415 cdip = DIP(plun->lun_cip); 8416 } else if (plun->lun_cip) { 8417 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8418 } 8419 8420 mutex_exit(&plun->lun_mutex); 8421 if (cdip) { 8422 (void) ndi_event_retrieve_cookie( 8423 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8424 &fcp_remove_eid, NDI_EVENT_NOPASS); 8425 (void) ndi_event_run_callbacks( 8426 pptr->port_ndi_event_hdl, cdip, 8427 fcp_remove_eid, NULL); 8428 } 8429 } else { 8430 mutex_exit(&plun->lun_mutex); 8431 mutex_exit(&LUN_TGT->tgt_mutex); 8432 } 8433 } 8434 8435 8436 /* 8437 * Scan all of the command pkts for this port, moving pkts that 8438 * match our LUN onto our own list (headed by "head") 8439 */ 8440 static struct fcp_pkt * 8441 fcp_scan_commands(struct fcp_lun *plun) 8442 { 8443 struct fcp_port *pptr = LUN_PORT; 8444 8445 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8446 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8447 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8448 8449 struct fcp_pkt *head = NULL; /* head of our list */ 8450 struct fcp_pkt *tail = NULL; /* tail of our list */ 8451 8452 int cmds_found = 0; 8453 8454 mutex_enter(&pptr->port_pkt_mutex); 8455 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8456 struct fcp_lun *tlun = 8457 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8458 8459 ncmd = cmd->cmd_next; /* set next command */ 8460 8461 /* 8462 * if this pkt is for a different LUN or the 8463 * command is sent down, skip it. 8464 */ 8465 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8466 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8467 pcmd = cmd; 8468 continue; 8469 } 8470 cmds_found++; 8471 if (pcmd != NULL) { 8472 ASSERT(pptr->port_pkt_head != cmd); 8473 pcmd->cmd_next = cmd->cmd_next; 8474 } else { 8475 ASSERT(cmd == pptr->port_pkt_head); 8476 pptr->port_pkt_head = cmd->cmd_next; 8477 } 8478 8479 if (cmd == pptr->port_pkt_tail) { 8480 pptr->port_pkt_tail = pcmd; 8481 if (pcmd) { 8482 pcmd->cmd_next = NULL; 8483 } 8484 } 8485 8486 if (head == NULL) { 8487 head = tail = cmd; 8488 } else { 8489 ASSERT(tail != NULL); 8490 8491 tail->cmd_next = cmd; 8492 tail = cmd; 8493 } 8494 cmd->cmd_next = NULL; 8495 } 8496 mutex_exit(&pptr->port_pkt_mutex); 8497 8498 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8499 fcp_trace, FCP_BUF_LEVEL_8, 0, 8500 "scan commands: %d cmd(s) found", cmds_found); 8501 8502 return (head); 8503 } 8504 8505 8506 /* 8507 * Abort all the commands in the command queue 8508 */ 8509 static void 8510 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8511 { 8512 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8513 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8514 8515 ASSERT(mutex_owned(&pptr->port_mutex)); 8516 8517 /* scan through the pkts and invalid them */ 8518 for (cmd = head; cmd != NULL; cmd = ncmd) { 8519 struct scsi_pkt *pkt = cmd->cmd_pkt; 8520 8521 ncmd = cmd->cmd_next; 8522 ASSERT(pkt != NULL); 8523 8524 /* 8525 * The lun is going to be marked offline. Indicate 8526 * the target driver not to requeue or retry this command 8527 * as the device is going to be offlined pretty soon. 8528 */ 8529 pkt->pkt_reason = CMD_DEV_GONE; 8530 pkt->pkt_statistics = 0; 8531 pkt->pkt_state = 0; 8532 8533 /* reset cmd flags/state */ 8534 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8535 cmd->cmd_state = FCP_PKT_IDLE; 8536 8537 /* 8538 * ensure we have a packet completion routine, 8539 * then call it. 8540 */ 8541 ASSERT(pkt->pkt_comp != NULL); 8542 8543 mutex_exit(&pptr->port_mutex); 8544 fcp_post_callback(cmd); 8545 mutex_enter(&pptr->port_mutex); 8546 } 8547 } 8548 8549 8550 /* 8551 * the pkt_comp callback for command packets 8552 */ 8553 static void 8554 fcp_cmd_callback(fc_packet_t *fpkt) 8555 { 8556 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8557 struct scsi_pkt *pkt = cmd->cmd_pkt; 8558 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8559 8560 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8561 8562 if (cmd->cmd_state == FCP_PKT_IDLE) { 8563 cmn_err(CE_PANIC, "Packet already completed %p", 8564 (void *)cmd); 8565 } 8566 8567 /* 8568 * Watch thread should be freeing the packet, ignore the pkt. 8569 */ 8570 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8571 fcp_log(CE_CONT, pptr->port_dip, 8572 "!FCP: Pkt completed while aborting\n"); 8573 return; 8574 } 8575 cmd->cmd_state = FCP_PKT_IDLE; 8576 8577 fcp_complete_pkt(fpkt); 8578 8579 #ifdef DEBUG 8580 mutex_enter(&pptr->port_pkt_mutex); 8581 pptr->port_npkts--; 8582 mutex_exit(&pptr->port_pkt_mutex); 8583 #endif /* DEBUG */ 8584 8585 fcp_post_callback(cmd); 8586 } 8587 8588 8589 static void 8590 fcp_complete_pkt(fc_packet_t *fpkt) 8591 { 8592 int error = 0; 8593 struct fcp_pkt *cmd = (struct fcp_pkt *) 8594 fpkt->pkt_ulp_private; 8595 struct scsi_pkt *pkt = cmd->cmd_pkt; 8596 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8597 struct fcp_lun *plun; 8598 struct fcp_tgt *ptgt; 8599 struct fcp_rsp *rsp; 8600 struct scsi_address save; 8601 8602 #ifdef DEBUG 8603 save = pkt->pkt_address; 8604 #endif /* DEBUG */ 8605 8606 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8607 8608 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8609 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8610 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8611 sizeof (struct fcp_rsp)); 8612 } 8613 8614 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8615 STATE_SENT_CMD | STATE_GOT_STATUS; 8616 8617 pkt->pkt_resid = 0; 8618 8619 if (cmd->cmd_pkt->pkt_numcookies) { 8620 pkt->pkt_state |= STATE_XFERRED_DATA; 8621 if (fpkt->pkt_data_resid) { 8622 error++; 8623 } 8624 } 8625 8626 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8627 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8628 /* 8629 * The next two checks make sure that if there 8630 * is no sense data or a valid response and 8631 * the command came back with check condition, 8632 * the command should be retried. 8633 */ 8634 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8635 !rsp->fcp_u.fcp_status.sense_len_set) { 8636 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8637 pkt->pkt_resid = cmd->cmd_dmacount; 8638 } 8639 } 8640 8641 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8642 return; 8643 } 8644 8645 plun = ADDR2LUN(&pkt->pkt_address); 8646 ptgt = plun->lun_tgt; 8647 ASSERT(ptgt != NULL); 8648 8649 /* 8650 * Update the transfer resid, if appropriate 8651 */ 8652 if (rsp->fcp_u.fcp_status.resid_over || 8653 rsp->fcp_u.fcp_status.resid_under) { 8654 pkt->pkt_resid = rsp->fcp_resid; 8655 } 8656 8657 /* 8658 * First see if we got a FCP protocol error. 8659 */ 8660 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8661 struct fcp_rsp_info *bep; 8662 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8663 sizeof (struct fcp_rsp)); 8664 8665 if (fcp_validate_fcp_response(rsp, pptr) != 8666 FC_SUCCESS) { 8667 pkt->pkt_reason = CMD_CMPLT; 8668 *(pkt->pkt_scbp) = STATUS_CHECK; 8669 8670 fcp_log(CE_WARN, pptr->port_dip, 8671 "!SCSI command to d_id=0x%x lun=0x%x" 8672 " failed, Bad FCP response values:" 8673 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8674 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8675 ptgt->tgt_d_id, plun->lun_num, 8676 rsp->reserved_0, rsp->reserved_1, 8677 rsp->fcp_u.fcp_status.reserved_0, 8678 rsp->fcp_u.fcp_status.reserved_1, 8679 rsp->fcp_response_len, rsp->fcp_sense_len); 8680 8681 return; 8682 } 8683 8684 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8685 FCP_CP_IN(fpkt->pkt_resp + 8686 sizeof (struct fcp_rsp), bep, 8687 fpkt->pkt_resp_acc, 8688 sizeof (struct fcp_rsp_info)); 8689 } 8690 8691 if (bep->rsp_code != FCP_NO_FAILURE) { 8692 child_info_t *cip; 8693 8694 pkt->pkt_reason = CMD_TRAN_ERR; 8695 8696 mutex_enter(&plun->lun_mutex); 8697 cip = plun->lun_cip; 8698 mutex_exit(&plun->lun_mutex); 8699 8700 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8701 fcp_trace, FCP_BUF_LEVEL_2, 0, 8702 "FCP response error on cmd=%p" 8703 " target=0x%x, cip=%p", cmd, 8704 ptgt->tgt_d_id, cip); 8705 } 8706 } 8707 8708 /* 8709 * See if we got a SCSI error with sense data 8710 */ 8711 if (rsp->fcp_u.fcp_status.sense_len_set) { 8712 uchar_t rqlen; 8713 caddr_t sense_from; 8714 child_info_t *cip; 8715 timeout_id_t tid; 8716 struct scsi_arq_status *arq; 8717 struct scsi_extended_sense *sense_to; 8718 8719 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8720 sense_to = &arq->sts_sensedata; 8721 8722 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8723 sizeof (struct scsi_extended_sense)); 8724 8725 sense_from = (caddr_t)fpkt->pkt_resp + 8726 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8727 8728 if (fcp_validate_fcp_response(rsp, pptr) != 8729 FC_SUCCESS) { 8730 pkt->pkt_reason = CMD_CMPLT; 8731 *(pkt->pkt_scbp) = STATUS_CHECK; 8732 8733 fcp_log(CE_WARN, pptr->port_dip, 8734 "!SCSI command to d_id=0x%x lun=0x%x" 8735 " failed, Bad FCP response values:" 8736 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8737 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8738 ptgt->tgt_d_id, plun->lun_num, 8739 rsp->reserved_0, rsp->reserved_1, 8740 rsp->fcp_u.fcp_status.reserved_0, 8741 rsp->fcp_u.fcp_status.reserved_1, 8742 rsp->fcp_response_len, rsp->fcp_sense_len); 8743 8744 return; 8745 } 8746 8747 /* 8748 * copy in sense information 8749 */ 8750 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8751 FCP_CP_IN(sense_from, sense_to, 8752 fpkt->pkt_resp_acc, rqlen); 8753 } else { 8754 bcopy(sense_from, sense_to, rqlen); 8755 } 8756 8757 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8758 (FCP_SENSE_NO_LUN(sense_to))) { 8759 mutex_enter(&ptgt->tgt_mutex); 8760 if (ptgt->tgt_tid == NULL) { 8761 /* 8762 * Kick off rediscovery 8763 */ 8764 tid = timeout(fcp_reconfigure_luns, 8765 (caddr_t)ptgt, drv_usectohz(1)); 8766 8767 ptgt->tgt_tid = tid; 8768 ptgt->tgt_state |= FCP_TGT_BUSY; 8769 } 8770 mutex_exit(&ptgt->tgt_mutex); 8771 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8772 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8773 fcp_trace, FCP_BUF_LEVEL_3, 0, 8774 "!FCP: Report Lun Has Changed" 8775 " target=%x", ptgt->tgt_d_id); 8776 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8777 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8778 fcp_trace, FCP_BUF_LEVEL_3, 0, 8779 "!FCP: LU Not Supported" 8780 " target=%x", ptgt->tgt_d_id); 8781 } 8782 } 8783 ASSERT(pkt->pkt_scbp != NULL); 8784 8785 pkt->pkt_state |= STATE_ARQ_DONE; 8786 8787 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8788 8789 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8790 arq->sts_rqpkt_reason = 0; 8791 arq->sts_rqpkt_statistics = 0; 8792 8793 arq->sts_rqpkt_state = STATE_GOT_BUS | 8794 STATE_GOT_TARGET | STATE_SENT_CMD | 8795 STATE_GOT_STATUS | STATE_ARQ_DONE | 8796 STATE_XFERRED_DATA; 8797 8798 mutex_enter(&plun->lun_mutex); 8799 cip = plun->lun_cip; 8800 mutex_exit(&plun->lun_mutex); 8801 8802 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8803 fcp_trace, FCP_BUF_LEVEL_8, 0, 8804 "SCSI Check condition on cmd=%p target=0x%x" 8805 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8806 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8807 cmd->cmd_fcp_cmd.fcp_cdb[0], 8808 rsp->fcp_u.fcp_status.scsi_status, 8809 sense_to->es_key, sense_to->es_add_code, 8810 sense_to->es_qual_code); 8811 } 8812 } else { 8813 plun = ADDR2LUN(&pkt->pkt_address); 8814 ptgt = plun->lun_tgt; 8815 ASSERT(ptgt != NULL); 8816 8817 /* 8818 * Work harder to translate errors into target driver 8819 * understandable ones. Note with despair that the target 8820 * drivers don't decode pkt_state and pkt_reason exhaustively 8821 * They resort to using the big hammer most often, which 8822 * may not get fixed in the life time of this driver. 8823 */ 8824 pkt->pkt_state = 0; 8825 pkt->pkt_statistics = 0; 8826 8827 switch (fpkt->pkt_state) { 8828 case FC_PKT_TRAN_ERROR: 8829 switch (fpkt->pkt_reason) { 8830 case FC_REASON_OVERRUN: 8831 pkt->pkt_reason = CMD_CMD_OVR; 8832 pkt->pkt_statistics |= STAT_ABORTED; 8833 break; 8834 8835 case FC_REASON_XCHG_BSY: { 8836 caddr_t ptr; 8837 8838 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8839 8840 ptr = (caddr_t)pkt->pkt_scbp; 8841 if (ptr) { 8842 *ptr = STATUS_BUSY; 8843 } 8844 break; 8845 } 8846 8847 case FC_REASON_ABORTED: 8848 pkt->pkt_reason = CMD_TRAN_ERR; 8849 pkt->pkt_statistics |= STAT_ABORTED; 8850 break; 8851 8852 case FC_REASON_ABORT_FAILED: 8853 pkt->pkt_reason = CMD_ABORT_FAIL; 8854 break; 8855 8856 case FC_REASON_NO_SEQ_INIT: 8857 case FC_REASON_CRC_ERROR: 8858 pkt->pkt_reason = CMD_TRAN_ERR; 8859 pkt->pkt_statistics |= STAT_ABORTED; 8860 break; 8861 default: 8862 pkt->pkt_reason = CMD_TRAN_ERR; 8863 break; 8864 } 8865 break; 8866 8867 case FC_PKT_PORT_OFFLINE: { 8868 dev_info_t *cdip = NULL; 8869 caddr_t ptr; 8870 8871 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 8872 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8873 fcp_trace, FCP_BUF_LEVEL_8, 0, 8874 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 8875 ptgt->tgt_d_id); 8876 } 8877 8878 mutex_enter(&plun->lun_mutex); 8879 if (plun->lun_mpxio == 0) { 8880 cdip = DIP(plun->lun_cip); 8881 } else if (plun->lun_cip) { 8882 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8883 } 8884 8885 mutex_exit(&plun->lun_mutex); 8886 8887 if (cdip) { 8888 (void) ndi_event_retrieve_cookie( 8889 pptr->port_ndi_event_hdl, cdip, 8890 FCAL_REMOVE_EVENT, &fcp_remove_eid, 8891 NDI_EVENT_NOPASS); 8892 (void) ndi_event_run_callbacks( 8893 pptr->port_ndi_event_hdl, cdip, 8894 fcp_remove_eid, NULL); 8895 } 8896 8897 /* 8898 * If the link goes off-line for a lip, 8899 * this will cause a error to the ST SG 8900 * SGEN drivers. By setting BUSY we will 8901 * give the drivers the chance to retry 8902 * before it blows of the job. ST will 8903 * remember how many times it has retried. 8904 */ 8905 8906 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 8907 (plun->lun_type == DTYPE_CHANGER)) { 8908 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8909 ptr = (caddr_t)pkt->pkt_scbp; 8910 if (ptr) { 8911 *ptr = STATUS_BUSY; 8912 } 8913 } else { 8914 pkt->pkt_reason = CMD_TRAN_ERR; 8915 pkt->pkt_statistics |= STAT_BUS_RESET; 8916 } 8917 break; 8918 } 8919 8920 case FC_PKT_TRAN_BSY: 8921 /* 8922 * Use the ssd Qfull handling here. 8923 */ 8924 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 8925 pkt->pkt_state = STATE_GOT_BUS; 8926 break; 8927 8928 case FC_PKT_TIMEOUT: 8929 pkt->pkt_reason = CMD_TIMEOUT; 8930 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 8931 pkt->pkt_statistics |= STAT_TIMEOUT; 8932 } else { 8933 pkt->pkt_statistics |= STAT_ABORTED; 8934 } 8935 break; 8936 8937 case FC_PKT_LOCAL_RJT: 8938 switch (fpkt->pkt_reason) { 8939 case FC_REASON_OFFLINE: { 8940 dev_info_t *cdip = NULL; 8941 8942 mutex_enter(&plun->lun_mutex); 8943 if (plun->lun_mpxio == 0) { 8944 cdip = DIP(plun->lun_cip); 8945 } else if (plun->lun_cip) { 8946 cdip = mdi_pi_get_client( 8947 PIP(plun->lun_cip)); 8948 } 8949 mutex_exit(&plun->lun_mutex); 8950 8951 if (cdip) { 8952 (void) ndi_event_retrieve_cookie( 8953 pptr->port_ndi_event_hdl, cdip, 8954 FCAL_REMOVE_EVENT, 8955 &fcp_remove_eid, 8956 NDI_EVENT_NOPASS); 8957 (void) ndi_event_run_callbacks( 8958 pptr->port_ndi_event_hdl, 8959 cdip, fcp_remove_eid, NULL); 8960 } 8961 8962 pkt->pkt_reason = CMD_TRAN_ERR; 8963 pkt->pkt_statistics |= STAT_BUS_RESET; 8964 8965 break; 8966 } 8967 8968 case FC_REASON_NOMEM: 8969 case FC_REASON_QFULL: { 8970 caddr_t ptr; 8971 8972 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8973 ptr = (caddr_t)pkt->pkt_scbp; 8974 if (ptr) { 8975 *ptr = STATUS_BUSY; 8976 } 8977 break; 8978 } 8979 8980 case FC_REASON_DMA_ERROR: 8981 pkt->pkt_reason = CMD_DMA_DERR; 8982 pkt->pkt_statistics |= STAT_ABORTED; 8983 break; 8984 8985 case FC_REASON_CRC_ERROR: 8986 case FC_REASON_UNDERRUN: { 8987 uchar_t status; 8988 /* 8989 * Work around for Bugid: 4240945. 8990 * IB on A5k doesn't set the Underrun bit 8991 * in the fcp status, when it is transferring 8992 * less than requested amount of data. Work 8993 * around the ses problem to keep luxadm 8994 * happy till ibfirmware is fixed. 8995 */ 8996 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8997 FCP_CP_IN(fpkt->pkt_resp, rsp, 8998 fpkt->pkt_resp_acc, 8999 sizeof (struct fcp_rsp)); 9000 } 9001 status = rsp->fcp_u.fcp_status.scsi_status; 9002 if (((plun->lun_type & DTYPE_MASK) == 9003 DTYPE_ESI) && (status == STATUS_GOOD)) { 9004 pkt->pkt_reason = CMD_CMPLT; 9005 *pkt->pkt_scbp = status; 9006 pkt->pkt_resid = 0; 9007 } else { 9008 pkt->pkt_reason = CMD_TRAN_ERR; 9009 pkt->pkt_statistics |= STAT_ABORTED; 9010 } 9011 break; 9012 } 9013 9014 case FC_REASON_NO_CONNECTION: 9015 case FC_REASON_UNSUPPORTED: 9016 case FC_REASON_ILLEGAL_REQ: 9017 case FC_REASON_BAD_SID: 9018 case FC_REASON_DIAG_BUSY: 9019 case FC_REASON_FCAL_OPN_FAIL: 9020 case FC_REASON_BAD_XID: 9021 default: 9022 pkt->pkt_reason = CMD_TRAN_ERR; 9023 pkt->pkt_statistics |= STAT_ABORTED; 9024 break; 9025 9026 } 9027 break; 9028 9029 case FC_PKT_NPORT_RJT: 9030 case FC_PKT_FABRIC_RJT: 9031 case FC_PKT_NPORT_BSY: 9032 case FC_PKT_FABRIC_BSY: 9033 default: 9034 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9035 fcp_trace, FCP_BUF_LEVEL_8, 0, 9036 "FC Status 0x%x, reason 0x%x", 9037 fpkt->pkt_state, fpkt->pkt_reason); 9038 pkt->pkt_reason = CMD_TRAN_ERR; 9039 pkt->pkt_statistics |= STAT_ABORTED; 9040 break; 9041 } 9042 9043 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9044 fcp_trace, FCP_BUF_LEVEL_9, 0, 9045 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9046 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9047 fpkt->pkt_reason); 9048 } 9049 9050 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9051 } 9052 9053 9054 static int 9055 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9056 { 9057 if (rsp->reserved_0 || rsp->reserved_1 || 9058 rsp->fcp_u.fcp_status.reserved_0 || 9059 rsp->fcp_u.fcp_status.reserved_1) { 9060 /* 9061 * These reserved fields should ideally be zero. FCP-2 does say 9062 * that the recipient need not check for reserved fields to be 9063 * zero. If they are not zero, we will not make a fuss about it 9064 * - just log it (in debug to both trace buffer and messages 9065 * file and to trace buffer only in non-debug) and move on. 9066 * 9067 * Non-zero reserved fields were seen with minnows. 9068 * 9069 * qlc takes care of some of this but we cannot assume that all 9070 * FCAs will do so. 9071 */ 9072 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9073 FCP_BUF_LEVEL_5, 0, 9074 "Got fcp response packet with non-zero reserved fields " 9075 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9076 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9077 rsp->reserved_0, rsp->reserved_1, 9078 rsp->fcp_u.fcp_status.reserved_0, 9079 rsp->fcp_u.fcp_status.reserved_1); 9080 } 9081 9082 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9083 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9084 return (FC_FAILURE); 9085 } 9086 9087 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9088 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9089 sizeof (struct fcp_rsp))) { 9090 return (FC_FAILURE); 9091 } 9092 9093 return (FC_SUCCESS); 9094 } 9095 9096 9097 /* 9098 * This is called when there is a change the in device state. The case we're 9099 * handling here is, if the d_id s does not match, offline this tgt and online 9100 * a new tgt with the new d_id. called from fcp_handle_devices with 9101 * port_mutex held. 9102 */ 9103 static int 9104 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9105 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9106 { 9107 ASSERT(mutex_owned(&pptr->port_mutex)); 9108 9109 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9110 fcp_trace, FCP_BUF_LEVEL_3, 0, 9111 "Starting fcp_device_changed..."); 9112 9113 /* 9114 * The two cases where the port_device_changed is called is 9115 * either it changes it's d_id or it's hard address. 9116 */ 9117 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9118 (FC_TOP_EXTERNAL(pptr->port_topology) && 9119 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9120 9121 /* offline this target */ 9122 mutex_enter(&ptgt->tgt_mutex); 9123 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9124 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9125 0, 1, NDI_DEVI_REMOVE); 9126 } 9127 mutex_exit(&ptgt->tgt_mutex); 9128 9129 fcp_log(CE_NOTE, pptr->port_dip, 9130 "Change in target properties: Old D_ID=%x New D_ID=%x" 9131 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9132 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9133 map_entry->map_hard_addr.hard_addr); 9134 } 9135 9136 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9137 link_cnt, tgt_cnt, cause)); 9138 } 9139 9140 /* 9141 * Function: fcp_alloc_lun 9142 * 9143 * Description: Creates a new lun structure and adds it to the list 9144 * of luns of the target. 9145 * 9146 * Argument: ptgt Target the lun will belong to. 9147 * 9148 * Return Value: NULL Failed 9149 * Not NULL Succeeded 9150 * 9151 * Context: Kernel context 9152 */ 9153 static struct fcp_lun * 9154 fcp_alloc_lun(struct fcp_tgt *ptgt) 9155 { 9156 struct fcp_lun *plun; 9157 9158 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9159 if (plun != NULL) { 9160 /* 9161 * Initialize the mutex before putting in the target list 9162 * especially before releasing the target mutex. 9163 */ 9164 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9165 plun->lun_tgt = ptgt; 9166 9167 mutex_enter(&ptgt->tgt_mutex); 9168 plun->lun_next = ptgt->tgt_lun; 9169 ptgt->tgt_lun = plun; 9170 plun->lun_old_guid = NULL; 9171 plun->lun_old_guid_size = 0; 9172 mutex_exit(&ptgt->tgt_mutex); 9173 } 9174 9175 return (plun); 9176 } 9177 9178 /* 9179 * Function: fcp_dealloc_lun 9180 * 9181 * Description: Frees the LUN structure passed by the caller. 9182 * 9183 * Argument: plun LUN structure to free. 9184 * 9185 * Return Value: None 9186 * 9187 * Context: Kernel context. 9188 */ 9189 static void 9190 fcp_dealloc_lun(struct fcp_lun *plun) 9191 { 9192 mutex_enter(&plun->lun_mutex); 9193 if (plun->lun_cip) { 9194 fcp_remove_child(plun); 9195 } 9196 mutex_exit(&plun->lun_mutex); 9197 9198 mutex_destroy(&plun->lun_mutex); 9199 if (plun->lun_guid) { 9200 kmem_free(plun->lun_guid, plun->lun_guid_size); 9201 } 9202 if (plun->lun_old_guid) { 9203 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9204 } 9205 kmem_free(plun, sizeof (*plun)); 9206 } 9207 9208 /* 9209 * Function: fcp_alloc_tgt 9210 * 9211 * Description: Creates a new target structure and adds it to the port 9212 * hash list. 9213 * 9214 * Argument: pptr fcp port structure 9215 * *map_entry entry describing the target to create 9216 * link_cnt Link state change counter 9217 * 9218 * Return Value: NULL Failed 9219 * Not NULL Succeeded 9220 * 9221 * Context: Kernel context. 9222 */ 9223 static struct fcp_tgt * 9224 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9225 { 9226 int hash; 9227 uchar_t *wwn; 9228 struct fcp_tgt *ptgt; 9229 9230 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9231 if (ptgt != NULL) { 9232 mutex_enter(&pptr->port_mutex); 9233 if (link_cnt != pptr->port_link_cnt) { 9234 /* 9235 * oh oh -- another link reset 9236 * in progress -- give up 9237 */ 9238 mutex_exit(&pptr->port_mutex); 9239 kmem_free(ptgt, sizeof (*ptgt)); 9240 ptgt = NULL; 9241 } else { 9242 /* 9243 * initialize the mutex before putting in the port 9244 * wwn list, especially before releasing the port 9245 * mutex. 9246 */ 9247 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9248 9249 /* add new target entry to the port's hash list */ 9250 wwn = (uchar_t *)&map_entry->map_pwwn; 9251 hash = FCP_HASH(wwn); 9252 9253 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9254 pptr->port_tgt_hash_table[hash] = ptgt; 9255 9256 /* save cross-ptr */ 9257 ptgt->tgt_port = pptr; 9258 9259 ptgt->tgt_change_cnt = 1; 9260 9261 /* initialize the target manual_config_only flag */ 9262 if (fcp_enable_auto_configuration) { 9263 ptgt->tgt_manual_config_only = 0; 9264 } else { 9265 ptgt->tgt_manual_config_only = 1; 9266 } 9267 9268 mutex_exit(&pptr->port_mutex); 9269 } 9270 } 9271 9272 return (ptgt); 9273 } 9274 9275 /* 9276 * Function: fcp_dealloc_tgt 9277 * 9278 * Description: Frees the target structure passed by the caller. 9279 * 9280 * Argument: ptgt Target structure to free. 9281 * 9282 * Return Value: None 9283 * 9284 * Context: Kernel context. 9285 */ 9286 static void 9287 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9288 { 9289 mutex_destroy(&ptgt->tgt_mutex); 9290 kmem_free(ptgt, sizeof (*ptgt)); 9291 } 9292 9293 9294 /* 9295 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9296 * 9297 * Device discovery commands will not be retried for-ever as 9298 * this will have repercussions on other devices that need to 9299 * be submitted to the hotplug thread. After a quick glance 9300 * at the SCSI-3 spec, it was found that the spec doesn't 9301 * mandate a forever retry, rather recommends a delayed retry. 9302 * 9303 * Since Photon IB is single threaded, STATUS_BUSY is common 9304 * in a 4+initiator environment. Make sure the total time 9305 * spent on retries (including command timeout) does not 9306 * 60 seconds 9307 */ 9308 static void 9309 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9310 { 9311 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9312 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9313 9314 mutex_enter(&pptr->port_mutex); 9315 mutex_enter(&ptgt->tgt_mutex); 9316 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9317 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9318 fcp_trace, FCP_BUF_LEVEL_2, 0, 9319 "fcp_queue_ipkt,1:state change occured" 9320 " for D_ID=0x%x", ptgt->tgt_d_id); 9321 mutex_exit(&ptgt->tgt_mutex); 9322 mutex_exit(&pptr->port_mutex); 9323 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9324 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9325 fcp_icmd_free(pptr, icmd); 9326 return; 9327 } 9328 mutex_exit(&ptgt->tgt_mutex); 9329 9330 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9331 9332 if (pptr->port_ipkt_list != NULL) { 9333 /* add pkt to front of doubly-linked list */ 9334 pptr->port_ipkt_list->ipkt_prev = icmd; 9335 icmd->ipkt_next = pptr->port_ipkt_list; 9336 pptr->port_ipkt_list = icmd; 9337 icmd->ipkt_prev = NULL; 9338 } else { 9339 /* this is the first/only pkt on the list */ 9340 pptr->port_ipkt_list = icmd; 9341 icmd->ipkt_next = NULL; 9342 icmd->ipkt_prev = NULL; 9343 } 9344 mutex_exit(&pptr->port_mutex); 9345 } 9346 9347 /* 9348 * Function: fcp_transport 9349 * 9350 * Description: This function submits the Fibre Channel packet to the transort 9351 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9352 * fails the submission, the treatment depends on the value of 9353 * the variable internal. 9354 * 9355 * Argument: port_handle fp/fctl port handle. 9356 * *fpkt Packet to submit to the transport layer. 9357 * internal Not zero when it's an internal packet. 9358 * 9359 * Return Value: FC_TRAN_BUSY 9360 * FC_STATEC_BUSY 9361 * FC_OFFLINE 9362 * FC_LOGINREQ 9363 * FC_DEVICE_BUSY 9364 * FC_SUCCESS 9365 */ 9366 static int 9367 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9368 { 9369 int rval; 9370 9371 rval = fc_ulp_transport(port_handle, fpkt); 9372 if (rval == FC_SUCCESS) { 9373 return (rval); 9374 } 9375 9376 /* 9377 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9378 * a command, if the underlying modules see that there is a state 9379 * change, or if a port is OFFLINE, that means, that state change 9380 * hasn't reached FCP yet, so re-queue the command for deferred 9381 * submission. 9382 */ 9383 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9384 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9385 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9386 /* 9387 * Defer packet re-submission. Life hang is possible on 9388 * internal commands if the port driver sends FC_STATEC_BUSY 9389 * for ever, but that shouldn't happen in a good environment. 9390 * Limiting re-transport for internal commands is probably a 9391 * good idea.. 9392 * A race condition can happen when a port sees barrage of 9393 * link transitions offline to online. If the FCTL has 9394 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9395 * internal commands should be queued to do the discovery. 9396 * The race condition is when an online comes and FCP starts 9397 * its internal discovery and the link goes offline. It is 9398 * possible that the statec_callback has not reached FCP 9399 * and FCP is carrying on with its internal discovery. 9400 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9401 * that the link has gone offline. At this point FCP should 9402 * drop all the internal commands and wait for the 9403 * statec_callback. It will be facilitated by incrementing 9404 * port_link_cnt. 9405 * 9406 * For external commands, the (FC)pkt_timeout is decremented 9407 * by the QUEUE Delay added by our driver, Care is taken to 9408 * ensure that it doesn't become zero (zero means no timeout) 9409 * If the time expires right inside driver queue itself, 9410 * the watch thread will return it to the original caller 9411 * indicating that the command has timed-out. 9412 */ 9413 if (internal) { 9414 char *op; 9415 struct fcp_ipkt *icmd; 9416 9417 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9418 switch (icmd->ipkt_opcode) { 9419 case SCMD_REPORT_LUN: 9420 op = "REPORT LUN"; 9421 break; 9422 9423 case SCMD_INQUIRY: 9424 op = "INQUIRY"; 9425 break; 9426 9427 case SCMD_INQUIRY_PAGE83: 9428 op = "INQUIRY-83"; 9429 break; 9430 9431 default: 9432 op = "Internal SCSI COMMAND"; 9433 break; 9434 } 9435 9436 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9437 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9438 rval = FC_SUCCESS; 9439 } 9440 } else { 9441 struct fcp_pkt *cmd; 9442 struct fcp_port *pptr; 9443 9444 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9445 cmd->cmd_state = FCP_PKT_IDLE; 9446 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9447 9448 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9449 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9450 fcp_trace, FCP_BUF_LEVEL_9, 0, 9451 "fcp_transport: xport busy for pkt %p", 9452 cmd->cmd_pkt); 9453 rval = FC_TRAN_BUSY; 9454 } else { 9455 fcp_queue_pkt(pptr, cmd); 9456 rval = FC_SUCCESS; 9457 } 9458 } 9459 } 9460 9461 return (rval); 9462 } 9463 9464 /*VARARGS3*/ 9465 static void 9466 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9467 { 9468 char buf[256]; 9469 va_list ap; 9470 9471 if (dip == NULL) { 9472 dip = fcp_global_dip; 9473 } 9474 9475 va_start(ap, fmt); 9476 (void) vsprintf(buf, fmt, ap); 9477 va_end(ap); 9478 9479 scsi_log(dip, "fcp", level, buf); 9480 } 9481 9482 /* 9483 * This function retries NS registry of FC4 type. 9484 * It assumes that fcp_mutex is held. 9485 * The function does nothing if topology is not fabric 9486 * So, the topology has to be set before this function can be called 9487 */ 9488 static void 9489 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9490 { 9491 int rval; 9492 9493 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9494 9495 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9496 ((pptr->port_topology != FC_TOP_FABRIC) && 9497 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9498 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9499 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9500 } 9501 return; 9502 } 9503 mutex_exit(&pptr->port_mutex); 9504 rval = fcp_do_ns_registry(pptr, s_id); 9505 mutex_enter(&pptr->port_mutex); 9506 9507 if (rval == 0) { 9508 /* Registry successful. Reset flag */ 9509 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9510 } 9511 } 9512 9513 /* 9514 * This function registers the ULP with the switch by calling transport i/f 9515 */ 9516 static int 9517 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9518 { 9519 fc_ns_cmd_t ns_cmd; 9520 ns_rfc_type_t rfc; 9521 uint32_t types[8]; 9522 9523 /* 9524 * Prepare the Name server structure to 9525 * register with the transport in case of 9526 * Fabric configuration. 9527 */ 9528 bzero(&rfc, sizeof (rfc)); 9529 bzero(types, sizeof (types)); 9530 9531 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9532 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9533 9534 rfc.rfc_port_id.port_id = s_id; 9535 bcopy(types, rfc.rfc_types, sizeof (types)); 9536 9537 ns_cmd.ns_flags = 0; 9538 ns_cmd.ns_cmd = NS_RFT_ID; 9539 ns_cmd.ns_req_len = sizeof (rfc); 9540 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9541 ns_cmd.ns_resp_len = 0; 9542 ns_cmd.ns_resp_payload = NULL; 9543 9544 /* 9545 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9546 */ 9547 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9548 fcp_log(CE_WARN, pptr->port_dip, 9549 "!ns_registry: failed name server registration"); 9550 return (1); 9551 } 9552 9553 return (0); 9554 } 9555 9556 /* 9557 * Function: fcp_handle_port_attach 9558 * 9559 * Description: This function is called from fcp_port_attach() to attach a 9560 * new port. This routine does the following: 9561 * 9562 * 1) Allocates an fcp_port structure and initializes it. 9563 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9564 * server. 9565 * 3) Kicks off the enumeration of the targets/luns visible 9566 * through this new port. That is done by calling 9567 * fcp_statec_callback() if the port is online. 9568 * 9569 * Argument: ulph fp/fctl port handle. 9570 * *pinfo Port information. 9571 * s_id Port ID. 9572 * instance Device instance number for the local port 9573 * (returned by ddi_get_instance()). 9574 * 9575 * Return Value: DDI_SUCCESS 9576 * DDI_FAILURE 9577 * 9578 * Context: User and Kernel context. 9579 */ 9580 /*ARGSUSED*/ 9581 int 9582 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9583 uint32_t s_id, int instance) 9584 { 9585 int res = DDI_FAILURE; 9586 scsi_hba_tran_t *tran; 9587 int mutex_initted = FALSE; 9588 int hba_attached = FALSE; 9589 int soft_state_linked = FALSE; 9590 int event_bind = FALSE; 9591 struct fcp_port *pptr; 9592 fc_portmap_t *tmp_list = NULL; 9593 uint32_t max_cnt, alloc_cnt; 9594 uchar_t *boot_wwn = NULL; 9595 uint_t nbytes; 9596 int manual_cfg; 9597 9598 /* 9599 * this port instance attaching for the first time (or after 9600 * being detached before) 9601 */ 9602 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9603 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9604 9605 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9606 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9607 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9608 instance); 9609 return (res); 9610 } 9611 9612 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9613 /* this shouldn't happen */ 9614 ddi_soft_state_free(fcp_softstate, instance); 9615 cmn_err(CE_WARN, "fcp: bad soft state"); 9616 return (res); 9617 } 9618 9619 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9620 9621 /* 9622 * Make a copy of ulp_port_info as fctl allocates 9623 * a temp struct. 9624 */ 9625 (void) fcp_cp_pinfo(pptr, pinfo); 9626 9627 /* 9628 * Check for manual_configuration_only property. 9629 * Enable manual configurtion if the property is 9630 * set to 1, otherwise disable manual configuration. 9631 */ 9632 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9633 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9634 MANUAL_CFG_ONLY, 9635 -1)) != -1) { 9636 if (manual_cfg == 1) { 9637 char *pathname; 9638 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9639 (void) ddi_pathname(pptr->port_dip, pathname); 9640 cmn_err(CE_NOTE, 9641 "%s (%s%d) %s is enabled via %s.conf.", 9642 pathname, 9643 ddi_driver_name(pptr->port_dip), 9644 ddi_get_instance(pptr->port_dip), 9645 MANUAL_CFG_ONLY, 9646 ddi_driver_name(pptr->port_dip)); 9647 fcp_enable_auto_configuration = 0; 9648 kmem_free(pathname, MAXPATHLEN); 9649 } 9650 } 9651 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)) 9652 pptr->port_link_cnt = 1; 9653 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)) 9654 pptr->port_id = s_id; 9655 pptr->port_instance = instance; 9656 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)) 9657 pptr->port_state = FCP_STATE_INIT; 9658 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)) 9659 9660 pptr->port_dmacookie_sz = (pptr->port_data_dma_attr.dma_attr_sgllen * 9661 sizeof (ddi_dma_cookie_t)); 9662 9663 /* 9664 * The two mutexes of fcp_port are initialized. The variable 9665 * mutex_initted is incremented to remember that fact. That variable 9666 * is checked when the routine fails and the mutexes have to be 9667 * destroyed. 9668 */ 9669 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9670 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9671 mutex_initted++; 9672 9673 /* 9674 * The SCSI tran structure is allocate and initialized now. 9675 */ 9676 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9677 fcp_log(CE_WARN, pptr->port_dip, 9678 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9679 goto fail; 9680 } 9681 9682 /* link in the transport structure then fill it in */ 9683 pptr->port_tran = tran; 9684 tran->tran_hba_private = pptr; 9685 tran->tran_tgt_private = NULL; 9686 tran->tran_tgt_init = fcp_scsi_tgt_init; 9687 tran->tran_tgt_probe = NULL; 9688 tran->tran_tgt_free = fcp_scsi_tgt_free; 9689 tran->tran_start = fcp_scsi_start; 9690 tran->tran_reset = fcp_scsi_reset; 9691 tran->tran_abort = fcp_scsi_abort; 9692 tran->tran_getcap = fcp_scsi_getcap; 9693 tran->tran_setcap = fcp_scsi_setcap; 9694 tran->tran_init_pkt = NULL; 9695 tran->tran_destroy_pkt = NULL; 9696 tran->tran_dmafree = NULL; 9697 tran->tran_sync_pkt = NULL; 9698 tran->tran_reset_notify = fcp_scsi_reset_notify; 9699 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9700 tran->tran_get_name = fcp_scsi_get_name; 9701 tran->tran_clear_aca = NULL; 9702 tran->tran_clear_task_set = NULL; 9703 tran->tran_terminate_task = NULL; 9704 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9705 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9706 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9707 tran->tran_post_event = fcp_scsi_bus_post_event; 9708 tran->tran_quiesce = NULL; 9709 tran->tran_unquiesce = NULL; 9710 tran->tran_bus_reset = NULL; 9711 tran->tran_bus_config = fcp_scsi_bus_config; 9712 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9713 tran->tran_bus_power = NULL; 9714 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9715 9716 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9717 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9718 tran->tran_setup_pkt = fcp_pkt_setup; 9719 tran->tran_teardown_pkt = fcp_pkt_teardown; 9720 tran->tran_hba_len = pptr->port_priv_pkt_len + 9721 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9722 9723 /* 9724 * Allocate an ndi event handle 9725 */ 9726 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9727 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9728 9729 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9730 sizeof (fcp_ndi_event_defs)); 9731 9732 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9733 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9734 9735 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9736 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9737 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9738 9739 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9740 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9741 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9742 goto fail; 9743 } 9744 event_bind++; /* Checked in fail case */ 9745 9746 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9747 tran, SCSI_HBA_TRAN_CLONE | SCSI_HBA_TRAN_SCB) 9748 != DDI_SUCCESS) { 9749 fcp_log(CE_WARN, pptr->port_dip, 9750 "!fcp%d: scsi_hba_attach_setup failed", instance); 9751 goto fail; 9752 } 9753 hba_attached++; /* Checked in fail case */ 9754 9755 pptr->port_mpxio = 0; 9756 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9757 MDI_SUCCESS) { 9758 pptr->port_mpxio++; 9759 } 9760 9761 /* 9762 * The following code is putting the new port structure in the global 9763 * list of ports and, if it is the first port to attach, it start the 9764 * fcp_watchdog_tick. 9765 * 9766 * Why put this new port in the global before we are done attaching it? 9767 * We are actually making the structure globally known before we are 9768 * done attaching it. The reason for that is: because of the code that 9769 * follows. At this point the resources to handle the port are 9770 * allocated. This function is now going to do the following: 9771 * 9772 * 1) It is going to try to register with the name server advertizing 9773 * the new FCP capability of the port. 9774 * 2) It is going to play the role of the fp/fctl layer by building 9775 * a list of worlwide names reachable through this port and call 9776 * itself on fcp_statec_callback(). That requires the port to 9777 * be part of the global list. 9778 */ 9779 mutex_enter(&fcp_global_mutex); 9780 if (fcp_port_head == NULL) { 9781 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9782 } 9783 pptr->port_next = fcp_port_head; 9784 fcp_port_head = pptr; 9785 soft_state_linked++; 9786 9787 if (fcp_watchdog_init++ == 0) { 9788 fcp_watchdog_tick = fcp_watchdog_timeout * 9789 drv_usectohz(1000000); 9790 fcp_watchdog_id = timeout(fcp_watch, NULL, 9791 fcp_watchdog_tick); 9792 } 9793 mutex_exit(&fcp_global_mutex); 9794 9795 /* 9796 * Here an attempt is made to register with the name server, the new 9797 * FCP capability. That is done using an RTF_ID to the name server. 9798 * It is done synchronously. The function fcp_do_ns_registry() 9799 * doesn't return till the name server responded. 9800 * On failures, just ignore it for now and it will get retried during 9801 * state change callbacks. We'll set a flag to show this failure 9802 */ 9803 if (fcp_do_ns_registry(pptr, s_id)) { 9804 mutex_enter(&pptr->port_mutex); 9805 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 9806 mutex_exit(&pptr->port_mutex); 9807 } else { 9808 mutex_enter(&pptr->port_mutex); 9809 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9810 mutex_exit(&pptr->port_mutex); 9811 } 9812 9813 /* 9814 * Lookup for boot WWN property 9815 */ 9816 if (modrootloaded != 1) { 9817 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 9818 ddi_get_parent(pinfo->port_dip), 9819 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 9820 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 9821 (nbytes == FC_WWN_SIZE)) { 9822 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 9823 } 9824 if (boot_wwn) { 9825 ddi_prop_free(boot_wwn); 9826 } 9827 } 9828 9829 /* 9830 * Handle various topologies and link states. 9831 */ 9832 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 9833 case FC_STATE_OFFLINE: 9834 9835 /* 9836 * we're attaching a port where the link is offline 9837 * 9838 * Wait for ONLINE, at which time a state 9839 * change will cause a statec_callback 9840 * 9841 * in the mean time, do not do anything 9842 */ 9843 res = DDI_SUCCESS; 9844 pptr->port_state |= FCP_STATE_OFFLINE; 9845 break; 9846 9847 case FC_STATE_ONLINE: { 9848 if (pptr->port_topology == FC_TOP_UNKNOWN) { 9849 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 9850 res = DDI_SUCCESS; 9851 break; 9852 } 9853 /* 9854 * discover devices and create nodes (a private 9855 * loop or point-to-point) 9856 */ 9857 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 9858 9859 /* 9860 * At this point we are going to build a list of all the ports 9861 * that can be reached through this local port. It looks like 9862 * we cannot handle more than FCP_MAX_DEVICES per local port 9863 * (128). 9864 */ 9865 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 9866 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 9867 KM_NOSLEEP)) == NULL) { 9868 fcp_log(CE_WARN, pptr->port_dip, 9869 "!fcp%d: failed to allocate portmap", 9870 instance); 9871 goto fail; 9872 } 9873 9874 /* 9875 * fc_ulp_getportmap() is going to provide us with the list of 9876 * remote ports in the buffer we just allocated. The way the 9877 * list is going to be retrieved depends on the topology. 9878 * However, if we are connected to a Fabric, a name server 9879 * request may be sent to get the list of FCP capable ports. 9880 * It should be noted that is the case the request is 9881 * synchronous. This means we are stuck here till the name 9882 * server replies. A lot of things can change during that time 9883 * and including, may be, being called on 9884 * fcp_statec_callback() for different reasons. I'm not sure 9885 * the code can handle that. 9886 */ 9887 max_cnt = FCP_MAX_DEVICES; 9888 alloc_cnt = FCP_MAX_DEVICES; 9889 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 9890 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 9891 FC_SUCCESS) { 9892 caddr_t msg; 9893 9894 (void) fc_ulp_error(res, &msg); 9895 9896 /* 9897 * this just means the transport is 9898 * busy perhaps building a portmap so, 9899 * for now, succeed this port attach 9900 * when the transport has a new map, 9901 * it'll send us a state change then 9902 */ 9903 fcp_log(CE_WARN, pptr->port_dip, 9904 "!failed to get port map : %s", msg); 9905 9906 res = DDI_SUCCESS; 9907 break; /* go return result */ 9908 } 9909 if (max_cnt > alloc_cnt) { 9910 alloc_cnt = max_cnt; 9911 } 9912 9913 /* 9914 * We are now going to call fcp_statec_callback() ourselves. 9915 * By issuing this call we are trying to kick off the enumera- 9916 * tion process. 9917 */ 9918 /* 9919 * let the state change callback do the SCSI device 9920 * discovery and create the devinfos 9921 */ 9922 fcp_statec_callback(ulph, pptr->port_fp_handle, 9923 pptr->port_phys_state, pptr->port_topology, tmp_list, 9924 max_cnt, pptr->port_id); 9925 9926 res = DDI_SUCCESS; 9927 break; 9928 } 9929 9930 default: 9931 /* unknown port state */ 9932 fcp_log(CE_WARN, pptr->port_dip, 9933 "!fcp%d: invalid port state at attach=0x%x", 9934 instance, pptr->port_phys_state); 9935 9936 mutex_enter(&pptr->port_mutex); 9937 pptr->port_phys_state = FCP_STATE_OFFLINE; 9938 mutex_exit(&pptr->port_mutex); 9939 9940 res = DDI_SUCCESS; 9941 break; 9942 } 9943 9944 /* free temp list if used */ 9945 if (tmp_list != NULL) { 9946 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 9947 } 9948 9949 /* note the attach time */ 9950 pptr->port_attach_time = lbolt64; 9951 9952 /* all done */ 9953 return (res); 9954 9955 /* a failure we have to clean up after */ 9956 fail: 9957 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 9958 9959 if (soft_state_linked) { 9960 /* remove this fcp_port from the linked list */ 9961 (void) fcp_soft_state_unlink(pptr); 9962 } 9963 9964 /* unbind and free event set */ 9965 if (pptr->port_ndi_event_hdl) { 9966 if (event_bind) { 9967 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 9968 &pptr->port_ndi_events, NDI_SLEEP); 9969 } 9970 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 9971 } 9972 9973 if (pptr->port_ndi_event_defs) { 9974 (void) kmem_free(pptr->port_ndi_event_defs, 9975 sizeof (fcp_ndi_event_defs)); 9976 } 9977 9978 /* 9979 * Clean up mpxio stuff 9980 */ 9981 if (pptr->port_mpxio) { 9982 (void) mdi_phci_unregister(pptr->port_dip, 0); 9983 pptr->port_mpxio--; 9984 } 9985 9986 /* undo SCSI HBA setup */ 9987 if (hba_attached) { 9988 (void) scsi_hba_detach(pptr->port_dip); 9989 } 9990 if (pptr->port_tran != NULL) { 9991 scsi_hba_tran_free(pptr->port_tran); 9992 } 9993 9994 mutex_enter(&fcp_global_mutex); 9995 9996 /* 9997 * We check soft_state_linked, because it is incremented right before 9998 * we call increment fcp_watchdog_init. Therefore, we know if 9999 * soft_state_linked is still FALSE, we do not want to decrement 10000 * fcp_watchdog_init or possibly call untimeout. 10001 */ 10002 10003 if (soft_state_linked) { 10004 if (--fcp_watchdog_init == 0) { 10005 timeout_id_t tid = fcp_watchdog_id; 10006 10007 mutex_exit(&fcp_global_mutex); 10008 (void) untimeout(tid); 10009 } else { 10010 mutex_exit(&fcp_global_mutex); 10011 } 10012 } else { 10013 mutex_exit(&fcp_global_mutex); 10014 } 10015 10016 if (mutex_initted) { 10017 mutex_destroy(&pptr->port_mutex); 10018 mutex_destroy(&pptr->port_pkt_mutex); 10019 } 10020 10021 if (tmp_list != NULL) { 10022 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10023 } 10024 10025 /* this makes pptr invalid */ 10026 ddi_soft_state_free(fcp_softstate, instance); 10027 10028 return (DDI_FAILURE); 10029 } 10030 10031 10032 static int 10033 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10034 { 10035 int count = 0; 10036 10037 mutex_enter(&pptr->port_mutex); 10038 10039 /* 10040 * if the port is powered down or suspended, nothing else 10041 * to do; just return. 10042 */ 10043 if (flag != FCP_STATE_DETACHING) { 10044 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10045 FCP_STATE_SUSPENDED)) { 10046 pptr->port_state |= flag; 10047 mutex_exit(&pptr->port_mutex); 10048 return (FC_SUCCESS); 10049 } 10050 } 10051 10052 if (pptr->port_state & FCP_STATE_IN_MDI) { 10053 mutex_exit(&pptr->port_mutex); 10054 return (FC_FAILURE); 10055 } 10056 10057 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10058 fcp_trace, FCP_BUF_LEVEL_2, 0, 10059 "fcp_handle_port_detach: port is detaching"); 10060 10061 pptr->port_state |= flag; 10062 10063 /* 10064 * Wait for any ongoing reconfig/ipkt to complete, that 10065 * ensures the freeing to targets/luns is safe. 10066 * No more ref to this port should happen from statec/ioctl 10067 * after that as it was removed from the global port list. 10068 */ 10069 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10070 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10071 /* 10072 * Let's give sufficient time for reconfig/ipkt 10073 * to complete. 10074 */ 10075 if (count++ >= FCP_ICMD_DEADLINE) { 10076 break; 10077 } 10078 mutex_exit(&pptr->port_mutex); 10079 delay(drv_usectohz(1000000)); 10080 mutex_enter(&pptr->port_mutex); 10081 } 10082 10083 /* 10084 * if the driver is still busy then fail to 10085 * suspend/power down. 10086 */ 10087 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10088 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10089 pptr->port_state &= ~flag; 10090 mutex_exit(&pptr->port_mutex); 10091 return (FC_FAILURE); 10092 } 10093 10094 if (flag == FCP_STATE_DETACHING) { 10095 pptr = fcp_soft_state_unlink(pptr); 10096 ASSERT(pptr != NULL); 10097 } 10098 10099 pptr->port_link_cnt++; 10100 pptr->port_state |= FCP_STATE_OFFLINE; 10101 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10102 10103 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10104 FCP_CAUSE_LINK_DOWN); 10105 mutex_exit(&pptr->port_mutex); 10106 10107 /* kill watch dog timer if we're the last */ 10108 mutex_enter(&fcp_global_mutex); 10109 if (--fcp_watchdog_init == 0) { 10110 timeout_id_t tid = fcp_watchdog_id; 10111 mutex_exit(&fcp_global_mutex); 10112 (void) untimeout(tid); 10113 } else { 10114 mutex_exit(&fcp_global_mutex); 10115 } 10116 10117 /* clean up the port structures */ 10118 if (flag == FCP_STATE_DETACHING) { 10119 fcp_cleanup_port(pptr, instance); 10120 } 10121 10122 return (FC_SUCCESS); 10123 } 10124 10125 10126 static void 10127 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10128 { 10129 ASSERT(pptr != NULL); 10130 10131 /* unbind and free event set */ 10132 if (pptr->port_ndi_event_hdl) { 10133 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10134 &pptr->port_ndi_events, NDI_SLEEP); 10135 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10136 } 10137 10138 if (pptr->port_ndi_event_defs) { 10139 (void) kmem_free(pptr->port_ndi_event_defs, 10140 sizeof (fcp_ndi_event_defs)); 10141 } 10142 10143 /* free the lun/target structures and devinfos */ 10144 fcp_free_targets(pptr); 10145 10146 /* 10147 * Clean up mpxio stuff 10148 */ 10149 if (pptr->port_mpxio) { 10150 (void) mdi_phci_unregister(pptr->port_dip, 0); 10151 pptr->port_mpxio--; 10152 } 10153 10154 /* clean up SCSA stuff */ 10155 (void) scsi_hba_detach(pptr->port_dip); 10156 if (pptr->port_tran != NULL) { 10157 scsi_hba_tran_free(pptr->port_tran); 10158 } 10159 10160 #ifdef KSTATS_CODE 10161 /* clean up kstats */ 10162 if (pptr->fcp_ksp != NULL) { 10163 kstat_delete(pptr->fcp_ksp); 10164 } 10165 #endif 10166 10167 /* clean up soft state mutexes/condition variables */ 10168 mutex_destroy(&pptr->port_mutex); 10169 mutex_destroy(&pptr->port_pkt_mutex); 10170 10171 /* all done with soft state */ 10172 ddi_soft_state_free(fcp_softstate, instance); 10173 } 10174 10175 /* 10176 * Function: fcp_kmem_cache_constructor 10177 * 10178 * Description: This function allocates and initializes the resources required 10179 * to build a scsi_pkt structure the target driver. The result 10180 * of the allocation and initialization will be cached in the 10181 * memory cache. As DMA resources may be allocated here, that 10182 * means DMA resources will be tied up in the cache manager. 10183 * This is a tradeoff that has been made for performance reasons. 10184 * 10185 * Argument: *buf Memory to preinitialize. 10186 * *arg FCP port structure (fcp_port). 10187 * kmflags Value passed to kmem_cache_alloc() and 10188 * propagated to the constructor. 10189 * 10190 * Return Value: 0 Allocation/Initialization was successful. 10191 * -1 Allocation or Initialization failed. 10192 * 10193 * 10194 * If the returned value is 0, the buffer is initialized like this: 10195 * 10196 * +================================+ 10197 * +----> | struct scsi_pkt | 10198 * | | | 10199 * | +--- | pkt_ha_private | 10200 * | | | | 10201 * | | +================================+ 10202 * | | 10203 * | | +================================+ 10204 * | +--> | struct fcp_pkt | <---------+ 10205 * | | | | 10206 * +----- | cmd_pkt | | 10207 * | cmd_fp_pkt | ---+ | 10208 * +-------->| cmd_fcp_rsp[] | | | 10209 * | +--->| cmd_fcp_cmd[] | | | 10210 * | | |--------------------------------| | | 10211 * | | | struct fc_packet | <--+ | 10212 * | | | | | 10213 * | | | pkt_ulp_private | ----------+ 10214 * | | | pkt_fca_private | -----+ 10215 * | | | pkt_data_cookie | ---+ | 10216 * | | | pkt_cmdlen | | | 10217 * | |(a) | pkt_rsplen | | | 10218 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10219 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10220 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10221 * | pkt_resp_cookie | ---|-|--+ | | | 10222 * | pkt_cmd_dma | | | | | | | 10223 * | pkt_cmd_acc | | | | | | | 10224 * +================================+ | | | | | | 10225 * | dma_cookies | <--+ | | | | | 10226 * | | | | | | | 10227 * +================================+ | | | | | 10228 * | fca_private | <----+ | | | | 10229 * | | | | | | 10230 * +================================+ | | | | 10231 * | | | | 10232 * | | | | 10233 * +================================+ (d) | | | | 10234 * | fcp_resp cookies | <-------+ | | | 10235 * | | | | | 10236 * +================================+ | | | 10237 * | | | 10238 * +================================+ (d) | | | 10239 * | fcp_resp | <-----------+ | | 10240 * | (DMA resources associated) | | | 10241 * +================================+ | | 10242 * | | 10243 * | | 10244 * | | 10245 * +================================+ (c) | | 10246 * | fcp_cmd cookies | <---------------+ | 10247 * | | | 10248 * +================================+ | 10249 * | 10250 * +================================+ (c) | 10251 * | fcp_cmd | <--------------------+ 10252 * | (DMA resources associated) | 10253 * +================================+ 10254 * 10255 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10256 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10257 * (c) Only if DMA is used for the FCP_CMD buffer. 10258 * (d) Only if DMA is used for the FCP_RESP buffer 10259 */ 10260 static int 10261 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10262 int kmflags) 10263 { 10264 struct fcp_pkt *cmd; 10265 struct fcp_port *pptr; 10266 fc_packet_t *fpkt; 10267 10268 pptr = (struct fcp_port *)tran->tran_hba_private; 10269 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10270 bzero(cmd, tran->tran_hba_len); 10271 10272 cmd->cmd_pkt = pkt; 10273 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10274 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10275 cmd->cmd_fp_pkt = fpkt; 10276 10277 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10278 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10279 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10280 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10281 10282 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10283 sizeof (struct fcp_pkt)); 10284 10285 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10286 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10287 10288 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10289 /* 10290 * The underlying HBA doesn't want to DMA the fcp_cmd or 10291 * fcp_resp. The transfer of information will be done by 10292 * bcopy. 10293 * The naming of the flags (that is actually a value) is 10294 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10295 * DMA" but instead "NO DMA". 10296 */ 10297 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10298 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10299 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10300 } else { 10301 /* 10302 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10303 * buffer. A buffer is allocated for each one the ddi_dma_* 10304 * interfaces. 10305 */ 10306 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10307 return (-1); 10308 } 10309 } 10310 10311 return (0); 10312 } 10313 10314 /* 10315 * Function: fcp_kmem_cache_destructor 10316 * 10317 * Description: Called by the destructor of the cache managed by SCSA. 10318 * All the resources pre-allocated in fcp_pkt_constructor 10319 * and the data also pre-initialized in fcp_pkt_constructor 10320 * are freed and uninitialized here. 10321 * 10322 * Argument: *buf Memory to uninitialize. 10323 * *arg FCP port structure (fcp_port). 10324 * 10325 * Return Value: None 10326 * 10327 * Context: kernel 10328 */ 10329 static void 10330 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10331 { 10332 struct fcp_pkt *cmd; 10333 struct fcp_port *pptr; 10334 10335 pptr = (struct fcp_port *)(tran->tran_hba_private); 10336 cmd = pkt->pkt_ha_private; 10337 10338 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10339 /* 10340 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10341 * buffer and DMA resources allocated to do so are released. 10342 */ 10343 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10344 } 10345 } 10346 10347 /* 10348 * Function: fcp_alloc_cmd_resp 10349 * 10350 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10351 * will be DMAed by the HBA. The buffer is allocated applying 10352 * the DMA requirements for the HBA. The buffers allocated will 10353 * also be bound. DMA resources are allocated in the process. 10354 * They will be released by fcp_free_cmd_resp(). 10355 * 10356 * Argument: *pptr FCP port. 10357 * *fpkt fc packet for which the cmd and resp packet should be 10358 * allocated. 10359 * flags Allocation flags. 10360 * 10361 * Return Value: FC_FAILURE 10362 * FC_SUCCESS 10363 * 10364 * Context: User or Kernel context only if flags == KM_SLEEP. 10365 * Interrupt context if the KM_SLEEP is not specified. 10366 */ 10367 static int 10368 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10369 { 10370 int rval; 10371 int cmd_len; 10372 int resp_len; 10373 ulong_t real_len; 10374 int (*cb) (caddr_t); 10375 ddi_dma_cookie_t pkt_cookie; 10376 ddi_dma_cookie_t *cp; 10377 uint32_t cnt; 10378 10379 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10380 10381 cmd_len = fpkt->pkt_cmdlen; 10382 resp_len = fpkt->pkt_rsplen; 10383 10384 ASSERT(fpkt->pkt_cmd_dma == NULL); 10385 10386 /* Allocation of a DMA handle used in subsequent calls. */ 10387 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10388 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10389 return (FC_FAILURE); 10390 } 10391 10392 /* A buffer is allocated that satisfies the DMA requirements. */ 10393 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10394 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10395 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10396 10397 if (rval != DDI_SUCCESS) { 10398 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10399 return (FC_FAILURE); 10400 } 10401 10402 if (real_len < cmd_len) { 10403 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10404 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10405 return (FC_FAILURE); 10406 } 10407 10408 /* The buffer allocated is DMA bound. */ 10409 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10410 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10411 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10412 10413 if (rval != DDI_DMA_MAPPED) { 10414 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10415 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10416 return (FC_FAILURE); 10417 } 10418 10419 if (fpkt->pkt_cmd_cookie_cnt > 10420 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10421 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10422 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10423 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10424 return (FC_FAILURE); 10425 } 10426 10427 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10428 10429 /* 10430 * The buffer where the scatter/gather list is going to be built is 10431 * allocated. 10432 */ 10433 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10434 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10435 KM_NOSLEEP); 10436 10437 if (cp == NULL) { 10438 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10439 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10440 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10441 return (FC_FAILURE); 10442 } 10443 10444 /* 10445 * The scatter/gather list for the buffer we just allocated is built 10446 * here. 10447 */ 10448 *cp = pkt_cookie; 10449 cp++; 10450 10451 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10452 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10453 &pkt_cookie); 10454 *cp = pkt_cookie; 10455 } 10456 10457 ASSERT(fpkt->pkt_resp_dma == NULL); 10458 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10459 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10460 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10461 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10462 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10463 return (FC_FAILURE); 10464 } 10465 10466 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10467 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10468 (caddr_t *)&fpkt->pkt_resp, &real_len, 10469 &fpkt->pkt_resp_acc); 10470 10471 if (rval != DDI_SUCCESS) { 10472 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10473 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10474 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10475 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10476 kmem_free(fpkt->pkt_cmd_cookie, 10477 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10478 return (FC_FAILURE); 10479 } 10480 10481 if (real_len < resp_len) { 10482 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10483 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10484 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10485 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10486 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10487 kmem_free(fpkt->pkt_cmd_cookie, 10488 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10489 return (FC_FAILURE); 10490 } 10491 10492 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10493 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10494 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10495 10496 if (rval != DDI_DMA_MAPPED) { 10497 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10498 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10499 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10500 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10501 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10502 kmem_free(fpkt->pkt_cmd_cookie, 10503 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10504 return (FC_FAILURE); 10505 } 10506 10507 if (fpkt->pkt_resp_cookie_cnt > 10508 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10509 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10510 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10511 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10512 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10513 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10514 kmem_free(fpkt->pkt_cmd_cookie, 10515 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10516 return (FC_FAILURE); 10517 } 10518 10519 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10520 10521 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10522 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10523 KM_NOSLEEP); 10524 10525 if (cp == NULL) { 10526 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10527 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10528 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10529 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10530 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10531 kmem_free(fpkt->pkt_cmd_cookie, 10532 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10533 return (FC_FAILURE); 10534 } 10535 10536 *cp = pkt_cookie; 10537 cp++; 10538 10539 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10540 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10541 &pkt_cookie); 10542 *cp = pkt_cookie; 10543 } 10544 10545 return (FC_SUCCESS); 10546 } 10547 10548 /* 10549 * Function: fcp_free_cmd_resp 10550 * 10551 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10552 * allocated by fcp_alloc_cmd_resp() and all the resources 10553 * associated with them. That includes the DMA resources and the 10554 * buffer allocated for the cookies of each one of them. 10555 * 10556 * Argument: *pptr FCP port context. 10557 * *fpkt fc packet containing the cmd and resp packet 10558 * to be released. 10559 * 10560 * Return Value: None 10561 * 10562 * Context: Interrupt, User and Kernel context. 10563 */ 10564 /* ARGSUSED */ 10565 static void 10566 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10567 { 10568 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10569 10570 if (fpkt->pkt_resp_dma) { 10571 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10572 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10573 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10574 } 10575 10576 if (fpkt->pkt_resp_cookie) { 10577 kmem_free(fpkt->pkt_resp_cookie, 10578 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10579 fpkt->pkt_resp_cookie = NULL; 10580 } 10581 10582 if (fpkt->pkt_cmd_dma) { 10583 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10584 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10585 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10586 } 10587 10588 if (fpkt->pkt_cmd_cookie) { 10589 kmem_free(fpkt->pkt_cmd_cookie, 10590 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10591 fpkt->pkt_cmd_cookie = NULL; 10592 } 10593 } 10594 10595 10596 /* 10597 * called by the transport to do our own target initialization 10598 * 10599 * can acquire and release the global mutex 10600 */ 10601 /* ARGSUSED */ 10602 static int 10603 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10604 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10605 { 10606 int *words; 10607 uchar_t *bytes; 10608 uint_t nbytes; 10609 uint_t nwords; 10610 struct fcp_tgt *ptgt; 10611 struct fcp_lun *plun; 10612 struct fcp_port *pptr = (struct fcp_port *) 10613 hba_tran->tran_hba_private; 10614 10615 ASSERT(pptr != NULL); 10616 10617 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10618 FCP_BUF_LEVEL_8, 0, 10619 "fcp_phys_tgt_init: called for %s (instance %d)", 10620 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10621 10622 /* get our port WWN property */ 10623 bytes = NULL; 10624 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 10625 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 10626 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 10627 /* no port WWN property */ 10628 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10629 FCP_BUF_LEVEL_8, 0, 10630 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10631 " for %s (instance %d): bytes=%p nbytes=%x", 10632 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10633 nbytes); 10634 10635 if (bytes != NULL) { 10636 ddi_prop_free(bytes); 10637 } 10638 10639 return (DDI_NOT_WELL_FORMED); 10640 } 10641 10642 words = NULL; 10643 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tgt_dip, 10644 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 10645 LUN_PROP, &words, &nwords) != DDI_PROP_SUCCESS) { 10646 ASSERT(bytes != NULL); 10647 10648 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10649 FCP_BUF_LEVEL_8, 0, 10650 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10651 " for %s (instance %d)", ddi_get_name(tgt_dip), 10652 ddi_get_instance(tgt_dip)); 10653 10654 ddi_prop_free(bytes); 10655 10656 return (DDI_NOT_WELL_FORMED); 10657 } 10658 10659 if (nwords == 0) { 10660 ddi_prop_free(bytes); 10661 ddi_prop_free(words); 10662 return (DDI_NOT_WELL_FORMED); 10663 } 10664 10665 ASSERT(bytes != NULL && words != NULL); 10666 10667 mutex_enter(&pptr->port_mutex); 10668 if ((plun = fcp_lookup_lun(pptr, bytes, *words)) == NULL) { 10669 mutex_exit(&pptr->port_mutex); 10670 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10671 FCP_BUF_LEVEL_8, 0, 10672 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10673 " for %s (instance %d)", ddi_get_name(tgt_dip), 10674 ddi_get_instance(tgt_dip)); 10675 10676 ddi_prop_free(bytes); 10677 ddi_prop_free(words); 10678 10679 return (DDI_FAILURE); 10680 } 10681 10682 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10683 FC_WWN_SIZE) == 0); 10684 ASSERT(plun->lun_num == (uint16_t)*words); 10685 10686 ddi_prop_free(bytes); 10687 ddi_prop_free(words); 10688 10689 ptgt = plun->lun_tgt; 10690 10691 mutex_enter(&ptgt->tgt_mutex); 10692 plun->lun_tgt_count++; 10693 hba_tran->tran_tgt_private = plun; 10694 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10695 plun->lun_tran = hba_tran; 10696 mutex_exit(&ptgt->tgt_mutex); 10697 mutex_exit(&pptr->port_mutex); 10698 10699 return (DDI_SUCCESS); 10700 } 10701 10702 /*ARGSUSED*/ 10703 static int 10704 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10705 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10706 { 10707 int words; 10708 uchar_t *bytes; 10709 uint_t nbytes; 10710 struct fcp_tgt *ptgt; 10711 struct fcp_lun *plun; 10712 struct fcp_port *pptr = (struct fcp_port *) 10713 hba_tran->tran_hba_private; 10714 child_info_t *cip; 10715 10716 ASSERT(pptr != NULL); 10717 10718 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10719 fcp_trace, FCP_BUF_LEVEL_8, 0, 10720 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10721 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10722 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10723 10724 cip = (child_info_t *)sd->sd_private; 10725 if (cip == NULL) { 10726 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10727 fcp_trace, FCP_BUF_LEVEL_8, 0, 10728 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10729 " for %s (instance %d)", ddi_get_name(tgt_dip), 10730 ddi_get_instance(tgt_dip)); 10731 10732 return (DDI_NOT_WELL_FORMED); 10733 } 10734 10735 /* get our port WWN property */ 10736 bytes = NULL; 10737 if ((mdi_prop_lookup_byte_array(PIP(cip), PORT_WWN_PROP, &bytes, 10738 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 10739 if (bytes) { 10740 (void) mdi_prop_free(bytes); 10741 } 10742 return (DDI_NOT_WELL_FORMED); 10743 } 10744 10745 words = 0; 10746 if (mdi_prop_lookup_int(PIP(cip), LUN_PROP, &words) != 10747 DDI_PROP_SUCCESS) { 10748 ASSERT(bytes != NULL); 10749 10750 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10751 fcp_trace, FCP_BUF_LEVEL_8, 0, 10752 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10753 " for %s (instance %d)", ddi_get_name(tgt_dip), 10754 ddi_get_instance(tgt_dip)); 10755 10756 (void) mdi_prop_free(bytes); 10757 return (DDI_NOT_WELL_FORMED); 10758 } 10759 10760 ASSERT(bytes != NULL); 10761 10762 mutex_enter(&pptr->port_mutex); 10763 if ((plun = fcp_lookup_lun(pptr, bytes, words)) == NULL) { 10764 mutex_exit(&pptr->port_mutex); 10765 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10766 fcp_trace, FCP_BUF_LEVEL_8, 0, 10767 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10768 " for %s (instance %d)", ddi_get_name(tgt_dip), 10769 ddi_get_instance(tgt_dip)); 10770 10771 (void) mdi_prop_free(bytes); 10772 (void) mdi_prop_free(&words); 10773 10774 return (DDI_FAILURE); 10775 } 10776 10777 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10778 FC_WWN_SIZE) == 0); 10779 ASSERT(plun->lun_num == (uint16_t)words); 10780 10781 (void) mdi_prop_free(bytes); 10782 (void) mdi_prop_free(&words); 10783 10784 ptgt = plun->lun_tgt; 10785 10786 mutex_enter(&ptgt->tgt_mutex); 10787 plun->lun_tgt_count++; 10788 hba_tran->tran_tgt_private = plun; 10789 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10790 plun->lun_tran = hba_tran; 10791 mutex_exit(&ptgt->tgt_mutex); 10792 mutex_exit(&pptr->port_mutex); 10793 10794 return (DDI_SUCCESS); 10795 } 10796 10797 10798 /* 10799 * called by the transport to do our own target initialization 10800 * 10801 * can acquire and release the global mutex 10802 */ 10803 /* ARGSUSED */ 10804 static int 10805 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10806 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10807 { 10808 struct fcp_port *pptr = (struct fcp_port *) 10809 hba_tran->tran_hba_private; 10810 int rval; 10811 10812 ASSERT(pptr != NULL); 10813 10814 /* 10815 * Child node is getting initialized. Look at the mpxio component 10816 * type on the child device to see if this device is mpxio managed 10817 * or not. 10818 */ 10819 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 10820 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10821 } else { 10822 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10823 } 10824 10825 return (rval); 10826 } 10827 10828 10829 /* ARGSUSED */ 10830 static void 10831 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10832 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10833 { 10834 struct fcp_lun *plun = hba_tran->tran_tgt_private; 10835 struct fcp_tgt *ptgt; 10836 10837 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 10838 fcp_trace, FCP_BUF_LEVEL_8, 0, 10839 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 10840 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 10841 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10842 10843 if (plun == NULL) { 10844 return; 10845 } 10846 ptgt = plun->lun_tgt; 10847 10848 ASSERT(ptgt != NULL); 10849 10850 mutex_enter(&ptgt->tgt_mutex); 10851 ASSERT(plun->lun_tgt_count > 0); 10852 10853 if (--plun->lun_tgt_count == 0) { 10854 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 10855 } 10856 plun->lun_tran = NULL; 10857 mutex_exit(&ptgt->tgt_mutex); 10858 } 10859 10860 /* 10861 * Function: fcp_scsi_start 10862 * 10863 * Description: This function is called by the target driver to request a 10864 * command to be sent. 10865 * 10866 * Argument: *ap SCSI address of the device. 10867 * *pkt SCSI packet containing the cmd to send. 10868 * 10869 * Return Value: TRAN_ACCEPT 10870 * TRAN_BUSY 10871 * TRAN_BADPKT 10872 * TRAN_FATAL_ERROR 10873 */ 10874 static int 10875 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 10876 { 10877 struct fcp_port *pptr = ADDR2FCP(ap); 10878 struct fcp_lun *plun = ADDR2LUN(ap); 10879 struct fcp_pkt *cmd = PKT2CMD(pkt); 10880 struct fcp_tgt *ptgt = plun->lun_tgt; 10881 int rval; 10882 10883 /* ensure command isn't already issued */ 10884 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 10885 10886 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10887 fcp_trace, FCP_BUF_LEVEL_9, 0, 10888 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 10889 10890 /* 10891 * It is strange that we enter the fcp_port mutex and the target 10892 * mutex to check the lun state (which has a mutex of its own). 10893 */ 10894 mutex_enter(&pptr->port_mutex); 10895 mutex_enter(&ptgt->tgt_mutex); 10896 10897 /* 10898 * If the device is offline and is not in the process of coming 10899 * online, fail the request. 10900 */ 10901 10902 if ((plun->lun_state & FCP_LUN_OFFLINE) && 10903 !(plun->lun_state & FCP_LUN_ONLINING)) { 10904 mutex_exit(&ptgt->tgt_mutex); 10905 mutex_exit(&pptr->port_mutex); 10906 10907 if (cmd->cmd_fp_pkt->pkt_pd == NULL) 10908 pkt->pkt_reason = CMD_DEV_GONE; 10909 10910 return (TRAN_FATAL_ERROR); 10911 } 10912 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 10913 10914 /* 10915 * If we are suspended, kernel is trying to dump, so don't 10916 * block, fail or defer requests - send them down right away. 10917 * NOTE: If we are in panic (i.e. trying to dump), we can't 10918 * assume we have been suspended. There is hardware such as 10919 * the v880 that doesn't do PM. Thus, the check for 10920 * ddi_in_panic. 10921 * 10922 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 10923 * of changing. So, if we can queue the packet, do it. Eventually, 10924 * either the device will have gone away or changed and we can fail 10925 * the request, or we can proceed if the device didn't change. 10926 * 10927 * If the pd in the target or the packet is NULL it's probably 10928 * because the device has gone away, we allow the request to be 10929 * put on the internal queue here in case the device comes back within 10930 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 10931 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 10932 * could be NULL because the device was disappearing during or since 10933 * packet initialization. 10934 */ 10935 10936 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 10937 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 10938 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 10939 (ptgt->tgt_pd_handle == NULL) || 10940 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 10941 /* 10942 * If ((LUN is busy AND 10943 * LUN not suspended AND 10944 * The system is not in panic state) OR 10945 * (The port is coming up)) 10946 * 10947 * We check to see if the any of the flags FLAG_NOINTR or 10948 * FLAG_NOQUEUE is set. If one of them is set the value 10949 * returned will be TRAN_BUSY. If not, the request is queued. 10950 */ 10951 mutex_exit(&ptgt->tgt_mutex); 10952 mutex_exit(&pptr->port_mutex); 10953 10954 /* see if using interrupts is allowed (so queueing'll work) */ 10955 if (pkt->pkt_flags & FLAG_NOINTR) { 10956 pkt->pkt_resid = 0; 10957 return (TRAN_BUSY); 10958 } 10959 if (pkt->pkt_flags & FLAG_NOQUEUE) { 10960 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10961 fcp_trace, FCP_BUF_LEVEL_9, 0, 10962 "fcp_scsi_start: lun busy for pkt %p", pkt); 10963 return (TRAN_BUSY); 10964 } 10965 #ifdef DEBUG 10966 mutex_enter(&pptr->port_pkt_mutex); 10967 pptr->port_npkts++; 10968 mutex_exit(&pptr->port_pkt_mutex); 10969 #endif /* DEBUG */ 10970 10971 /* got queue up the pkt for later */ 10972 fcp_queue_pkt(pptr, cmd); 10973 return (TRAN_ACCEPT); 10974 } 10975 cmd->cmd_state = FCP_PKT_ISSUED; 10976 10977 mutex_exit(&ptgt->tgt_mutex); 10978 mutex_exit(&pptr->port_mutex); 10979 10980 /* 10981 * Now that we released the mutexes, what was protected by them can 10982 * change. 10983 */ 10984 10985 /* 10986 * If there is a reconfiguration in progress, wait for it to complete. 10987 */ 10988 fcp_reconfig_wait(pptr); 10989 10990 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 10991 pkt->pkt_time : 0; 10992 10993 /* prepare the packet */ 10994 10995 fcp_prepare_pkt(pptr, cmd, plun); 10996 10997 if (cmd->cmd_pkt->pkt_time) { 10998 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 10999 } else { 11000 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11001 } 11002 11003 /* 11004 * if interrupts aren't allowed (e.g. at dump time) then we'll 11005 * have to do polled I/O 11006 */ 11007 if (pkt->pkt_flags & FLAG_NOINTR) { 11008 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11009 return (fcp_dopoll(pptr, cmd)); 11010 } 11011 11012 #ifdef DEBUG 11013 mutex_enter(&pptr->port_pkt_mutex); 11014 pptr->port_npkts++; 11015 mutex_exit(&pptr->port_pkt_mutex); 11016 #endif /* DEBUG */ 11017 11018 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11019 if (rval == FC_SUCCESS) { 11020 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11021 fcp_trace, FCP_BUF_LEVEL_9, 0, 11022 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11023 return (TRAN_ACCEPT); 11024 } 11025 11026 cmd->cmd_state = FCP_PKT_IDLE; 11027 11028 #ifdef DEBUG 11029 mutex_enter(&pptr->port_pkt_mutex); 11030 pptr->port_npkts--; 11031 mutex_exit(&pptr->port_pkt_mutex); 11032 #endif /* DEBUG */ 11033 11034 /* 11035 * For lack of clearer definitions, choose 11036 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11037 */ 11038 11039 if (rval == FC_TRAN_BUSY) { 11040 pkt->pkt_resid = 0; 11041 rval = TRAN_BUSY; 11042 } else { 11043 mutex_enter(&ptgt->tgt_mutex); 11044 if (plun->lun_state & FCP_LUN_OFFLINE) { 11045 child_info_t *cip; 11046 11047 mutex_enter(&plun->lun_mutex); 11048 cip = plun->lun_cip; 11049 mutex_exit(&plun->lun_mutex); 11050 11051 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11052 fcp_trace, FCP_BUF_LEVEL_6, 0, 11053 "fcp_transport failed 2 for %x: %x; dip=%p", 11054 plun->lun_tgt->tgt_d_id, rval, cip); 11055 11056 rval = TRAN_FATAL_ERROR; 11057 } else { 11058 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11059 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11060 fcp_trace, FCP_BUF_LEVEL_9, 0, 11061 "fcp_scsi_start: FC_BUSY for pkt %p", 11062 pkt); 11063 rval = TRAN_BUSY; 11064 } else { 11065 rval = TRAN_ACCEPT; 11066 fcp_queue_pkt(pptr, cmd); 11067 } 11068 } 11069 mutex_exit(&ptgt->tgt_mutex); 11070 } 11071 11072 return (rval); 11073 } 11074 11075 /* 11076 * called by the transport to abort a packet 11077 */ 11078 /*ARGSUSED*/ 11079 static int 11080 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11081 { 11082 int tgt_cnt; 11083 struct fcp_port *pptr = ADDR2FCP(ap); 11084 struct fcp_lun *plun = ADDR2LUN(ap); 11085 struct fcp_tgt *ptgt = plun->lun_tgt; 11086 11087 if (pkt == NULL) { 11088 if (ptgt) { 11089 mutex_enter(&ptgt->tgt_mutex); 11090 tgt_cnt = ptgt->tgt_change_cnt; 11091 mutex_exit(&ptgt->tgt_mutex); 11092 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11093 return (TRUE); 11094 } 11095 } 11096 return (FALSE); 11097 } 11098 11099 11100 /* 11101 * Perform reset 11102 */ 11103 int 11104 fcp_scsi_reset(struct scsi_address *ap, int level) 11105 { 11106 int rval = 0; 11107 struct fcp_port *pptr = ADDR2FCP(ap); 11108 struct fcp_lun *plun = ADDR2LUN(ap); 11109 struct fcp_tgt *ptgt = plun->lun_tgt; 11110 11111 if (level == RESET_ALL) { 11112 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11113 rval = 1; 11114 } 11115 } else if (level == RESET_TARGET || level == RESET_LUN) { 11116 /* 11117 * If we are in the middle of discovery, return 11118 * SUCCESS as this target will be rediscovered 11119 * anyway 11120 */ 11121 mutex_enter(&ptgt->tgt_mutex); 11122 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11123 mutex_exit(&ptgt->tgt_mutex); 11124 return (1); 11125 } 11126 mutex_exit(&ptgt->tgt_mutex); 11127 11128 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11129 rval = 1; 11130 } 11131 } 11132 return (rval); 11133 } 11134 11135 11136 /* 11137 * called by the framework to get a SCSI capability 11138 */ 11139 static int 11140 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11141 { 11142 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11143 } 11144 11145 11146 /* 11147 * called by the framework to set a SCSI capability 11148 */ 11149 static int 11150 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11151 { 11152 return (fcp_commoncap(ap, cap, value, whom, 1)); 11153 } 11154 11155 /* 11156 * Function: fcp_pkt_setup 11157 * 11158 * Description: This function sets up the scsi_pkt structure passed by the 11159 * caller. This function assumes fcp_pkt_constructor has been 11160 * called previously for the packet passed by the caller. If 11161 * successful this call will have the following results: 11162 * 11163 * - The resources needed that will be constant through out 11164 * the whole transaction are allocated. 11165 * - The fields that will be constant through out the whole 11166 * transaction are initialized. 11167 * - The scsi packet will be linked to the LUN structure 11168 * addressed by the transaction. 11169 * 11170 * Argument: 11171 * *pkt Pointer to a scsi_pkt structure. 11172 * callback 11173 * arg 11174 * 11175 * Return Value: 0 Success 11176 * !0 Failure 11177 * 11178 * Context: Kernel context or interrupt context 11179 */ 11180 /* ARGSUSED */ 11181 static int 11182 fcp_pkt_setup(struct scsi_pkt *pkt, 11183 int (*callback)(caddr_t arg), 11184 caddr_t arg) 11185 { 11186 struct fcp_pkt *cmd; 11187 struct fcp_port *pptr; 11188 struct fcp_lun *plun; 11189 struct fcp_tgt *ptgt; 11190 int kf; 11191 fc_packet_t *fpkt; 11192 fc_frame_hdr_t *hp; 11193 11194 pptr = ADDR2FCP(&pkt->pkt_address); 11195 plun = ADDR2LUN(&pkt->pkt_address); 11196 ptgt = plun->lun_tgt; 11197 11198 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11199 fpkt = cmd->cmd_fp_pkt; 11200 11201 /* 11202 * this request is for dma allocation only 11203 */ 11204 /* 11205 * First step of fcp_scsi_init_pkt: pkt allocation 11206 * We determine if the caller is willing to wait for the 11207 * resources. 11208 */ 11209 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11210 11211 /* 11212 * Selective zeroing of the pkt. 11213 */ 11214 cmd->cmd_back = NULL; 11215 cmd->cmd_next = NULL; 11216 11217 /* 11218 * Zero out fcp command 11219 */ 11220 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11221 11222 cmd->cmd_state = FCP_PKT_IDLE; 11223 11224 fpkt = cmd->cmd_fp_pkt; 11225 fpkt->pkt_data_acc = NULL; 11226 11227 mutex_enter(&ptgt->tgt_mutex); 11228 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11229 11230 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11231 != FC_SUCCESS) { 11232 mutex_exit(&ptgt->tgt_mutex); 11233 return (-1); 11234 } 11235 11236 mutex_exit(&ptgt->tgt_mutex); 11237 11238 /* Fill in the Fabric Channel Header */ 11239 hp = &fpkt->pkt_cmd_fhdr; 11240 hp->r_ctl = R_CTL_COMMAND; 11241 hp->rsvd = 0; 11242 hp->type = FC_TYPE_SCSI_FCP; 11243 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11244 hp->seq_id = 0; 11245 hp->df_ctl = 0; 11246 hp->seq_cnt = 0; 11247 hp->ox_id = 0xffff; 11248 hp->rx_id = 0xffff; 11249 hp->ro = 0; 11250 11251 /* 11252 * A doubly linked list (cmd_forw, cmd_back) is built 11253 * out of every allocated packet on a per-lun basis 11254 * 11255 * The packets are maintained in the list so as to satisfy 11256 * scsi_abort() requests. At present (which is unlikely to 11257 * change in the future) nobody performs a real scsi_abort 11258 * in the SCSI target drivers (as they don't keep the packets 11259 * after doing scsi_transport - so they don't know how to 11260 * abort a packet other than sending a NULL to abort all 11261 * outstanding packets) 11262 */ 11263 mutex_enter(&plun->lun_mutex); 11264 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11265 plun->lun_pkt_head->cmd_back = cmd; 11266 } else { 11267 plun->lun_pkt_tail = cmd; 11268 } 11269 plun->lun_pkt_head = cmd; 11270 mutex_exit(&plun->lun_mutex); 11271 return (0); 11272 } 11273 11274 /* 11275 * Function: fcp_pkt_teardown 11276 * 11277 * Description: This function releases a scsi_pkt structure and all the 11278 * resources attached to it. 11279 * 11280 * Argument: *pkt Pointer to a scsi_pkt structure. 11281 * 11282 * Return Value: None 11283 * 11284 * Context: User, Kernel or Interrupt context. 11285 */ 11286 static void 11287 fcp_pkt_teardown(struct scsi_pkt *pkt) 11288 { 11289 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11290 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11291 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11292 11293 /* 11294 * Remove the packet from the per-lun list 11295 */ 11296 mutex_enter(&plun->lun_mutex); 11297 if (cmd->cmd_back) { 11298 ASSERT(cmd != plun->lun_pkt_head); 11299 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11300 } else { 11301 ASSERT(cmd == plun->lun_pkt_head); 11302 plun->lun_pkt_head = cmd->cmd_forw; 11303 } 11304 11305 if (cmd->cmd_forw) { 11306 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11307 } else { 11308 ASSERT(cmd == plun->lun_pkt_tail); 11309 plun->lun_pkt_tail = cmd->cmd_back; 11310 } 11311 11312 mutex_exit(&plun->lun_mutex); 11313 11314 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11315 } 11316 11317 /* 11318 * Routine for reset notification setup, to register or cancel. 11319 * This function is called by SCSA 11320 */ 11321 /*ARGSUSED*/ 11322 static int 11323 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11324 void (*callback)(caddr_t), caddr_t arg) 11325 { 11326 struct fcp_port *pptr = ADDR2FCP(ap); 11327 11328 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11329 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11330 } 11331 11332 11333 static int 11334 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11335 ddi_eventcookie_t *event_cookiep) 11336 { 11337 struct fcp_port *pptr = fcp_dip2port(dip); 11338 11339 if (pptr == NULL) { 11340 return (DDI_FAILURE); 11341 } 11342 11343 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11344 event_cookiep, NDI_EVENT_NOPASS)); 11345 } 11346 11347 11348 static int 11349 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11350 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11351 ddi_callback_id_t *cb_id) 11352 { 11353 struct fcp_port *pptr = fcp_dip2port(dip); 11354 11355 if (pptr == NULL) { 11356 return (DDI_FAILURE); 11357 } 11358 11359 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11360 eventid, callback, arg, NDI_SLEEP, cb_id)); 11361 } 11362 11363 11364 static int 11365 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11366 { 11367 11368 struct fcp_port *pptr = fcp_dip2port(dip); 11369 11370 if (pptr == NULL) { 11371 return (DDI_FAILURE); 11372 } 11373 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11374 } 11375 11376 11377 /* 11378 * called by the transport to post an event 11379 */ 11380 static int 11381 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11382 ddi_eventcookie_t eventid, void *impldata) 11383 { 11384 struct fcp_port *pptr = fcp_dip2port(dip); 11385 11386 if (pptr == NULL) { 11387 return (DDI_FAILURE); 11388 } 11389 11390 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11391 eventid, impldata)); 11392 } 11393 11394 11395 /* 11396 * A target in in many cases in Fibre Channel has a one to one relation 11397 * with a port identifier (which is also known as D_ID and also as AL_PA 11398 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11399 * will most likely result in resetting all LUNs (which means a reset will 11400 * occur on all the SCSI devices connected at the other end of the bridge) 11401 * That is the latest favorite topic for discussion, for, one can debate as 11402 * hot as one likes and come up with arguably a best solution to one's 11403 * satisfaction 11404 * 11405 * To stay on track and not digress much, here are the problems stated 11406 * briefly: 11407 * 11408 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11409 * target drivers use RESET_TARGET even if their instance is on a 11410 * LUN. Doesn't that sound a bit broken ? 11411 * 11412 * FCP SCSI (the current spec) only defines RESET TARGET in the 11413 * control fields of an FCP_CMND structure. It should have been 11414 * fixed right there, giving flexibility to the initiators to 11415 * minimize havoc that could be caused by resetting a target. 11416 */ 11417 static int 11418 fcp_reset_target(struct scsi_address *ap, int level) 11419 { 11420 int rval = FC_FAILURE; 11421 char lun_id[25]; 11422 struct fcp_port *pptr = ADDR2FCP(ap); 11423 struct fcp_lun *plun = ADDR2LUN(ap); 11424 struct fcp_tgt *ptgt = plun->lun_tgt; 11425 struct scsi_pkt *pkt; 11426 struct fcp_pkt *cmd; 11427 struct fcp_rsp *rsp; 11428 uint32_t tgt_cnt; 11429 struct fcp_rsp_info *rsp_info; 11430 struct fcp_reset_elem *p; 11431 int bval; 11432 11433 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11434 KM_NOSLEEP)) == NULL) { 11435 return (rval); 11436 } 11437 11438 mutex_enter(&ptgt->tgt_mutex); 11439 if (level == RESET_TARGET) { 11440 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11441 mutex_exit(&ptgt->tgt_mutex); 11442 kmem_free(p, sizeof (struct fcp_reset_elem)); 11443 return (rval); 11444 } 11445 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11446 (void) strcpy(lun_id, " "); 11447 } else { 11448 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11449 mutex_exit(&ptgt->tgt_mutex); 11450 kmem_free(p, sizeof (struct fcp_reset_elem)); 11451 return (rval); 11452 } 11453 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11454 11455 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11456 } 11457 tgt_cnt = ptgt->tgt_change_cnt; 11458 11459 mutex_exit(&ptgt->tgt_mutex); 11460 11461 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11462 0, 0, NULL, 0)) == NULL) { 11463 kmem_free(p, sizeof (struct fcp_reset_elem)); 11464 mutex_enter(&ptgt->tgt_mutex); 11465 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11466 mutex_exit(&ptgt->tgt_mutex); 11467 return (rval); 11468 } 11469 pkt->pkt_time = FCP_POLL_TIMEOUT; 11470 11471 /* fill in cmd part of packet */ 11472 cmd = PKT2CMD(pkt); 11473 if (level == RESET_TARGET) { 11474 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11475 } else { 11476 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11477 } 11478 cmd->cmd_fp_pkt->pkt_comp = NULL; 11479 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11480 11481 /* prepare a packet for transport */ 11482 fcp_prepare_pkt(pptr, cmd, plun); 11483 11484 if (cmd->cmd_pkt->pkt_time) { 11485 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11486 } else { 11487 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11488 } 11489 11490 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11491 bval = fcp_dopoll(pptr, cmd); 11492 fc_ulp_idle_port(pptr->port_fp_handle); 11493 11494 /* submit the packet */ 11495 if (bval == TRAN_ACCEPT) { 11496 int error = 3; 11497 11498 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11499 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11500 sizeof (struct fcp_rsp)); 11501 11502 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11503 if (fcp_validate_fcp_response(rsp, pptr) == 11504 FC_SUCCESS) { 11505 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11506 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11507 sizeof (struct fcp_rsp), rsp_info, 11508 cmd->cmd_fp_pkt->pkt_resp_acc, 11509 sizeof (struct fcp_rsp_info)); 11510 } 11511 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11512 rval = FC_SUCCESS; 11513 error = 0; 11514 } else { 11515 error = 1; 11516 } 11517 } else { 11518 error = 2; 11519 } 11520 } 11521 11522 switch (error) { 11523 case 0: 11524 fcp_log(CE_WARN, pptr->port_dip, 11525 "!FCP: WWN 0x%08x%08x %s reset successfully", 11526 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11527 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11528 break; 11529 11530 case 1: 11531 fcp_log(CE_WARN, pptr->port_dip, 11532 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11533 " response code=%x", 11534 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11535 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11536 rsp_info->rsp_code); 11537 break; 11538 11539 case 2: 11540 fcp_log(CE_WARN, pptr->port_dip, 11541 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11542 " Bad FCP response values: rsvd1=%x," 11543 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11544 " rsplen=%x, senselen=%x", 11545 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11546 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11547 rsp->reserved_0, rsp->reserved_1, 11548 rsp->fcp_u.fcp_status.reserved_0, 11549 rsp->fcp_u.fcp_status.reserved_1, 11550 rsp->fcp_response_len, rsp->fcp_sense_len); 11551 break; 11552 11553 default: 11554 fcp_log(CE_WARN, pptr->port_dip, 11555 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11556 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11557 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11558 break; 11559 } 11560 } 11561 scsi_destroy_pkt(pkt); 11562 11563 if (rval == FC_FAILURE) { 11564 mutex_enter(&ptgt->tgt_mutex); 11565 if (level == RESET_TARGET) { 11566 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11567 } else { 11568 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11569 } 11570 mutex_exit(&ptgt->tgt_mutex); 11571 kmem_free(p, sizeof (struct fcp_reset_elem)); 11572 return (rval); 11573 } 11574 11575 mutex_enter(&pptr->port_mutex); 11576 if (level == RESET_TARGET) { 11577 p->tgt = ptgt; 11578 p->lun = NULL; 11579 } else { 11580 p->tgt = NULL; 11581 p->lun = plun; 11582 } 11583 p->tgt = ptgt; 11584 p->tgt_cnt = tgt_cnt; 11585 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11586 p->next = pptr->port_reset_list; 11587 pptr->port_reset_list = p; 11588 11589 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11590 fcp_trace, FCP_BUF_LEVEL_3, 0, 11591 "Notify ssd of the reset to reinstate the reservations"); 11592 11593 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11594 &pptr->port_reset_notify_listf); 11595 11596 mutex_exit(&pptr->port_mutex); 11597 11598 return (rval); 11599 } 11600 11601 11602 /* 11603 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11604 * SCSI capabilities 11605 */ 11606 /* ARGSUSED */ 11607 static int 11608 fcp_commoncap(struct scsi_address *ap, char *cap, 11609 int val, int tgtonly, int doset) 11610 { 11611 struct fcp_port *pptr = ADDR2FCP(ap); 11612 struct fcp_lun *plun = ADDR2LUN(ap); 11613 struct fcp_tgt *ptgt = plun->lun_tgt; 11614 int cidx; 11615 int rval = FALSE; 11616 11617 if (cap == (char *)0) { 11618 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11619 fcp_trace, FCP_BUF_LEVEL_3, 0, 11620 "fcp_commoncap: invalid arg"); 11621 return (rval); 11622 } 11623 11624 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11625 return (UNDEFINED); 11626 } 11627 11628 /* 11629 * Process setcap request. 11630 */ 11631 if (doset) { 11632 /* 11633 * At present, we can only set binary (0/1) values 11634 */ 11635 switch (cidx) { 11636 case SCSI_CAP_ARQ: 11637 if (val == 0) { 11638 rval = FALSE; 11639 } else { 11640 rval = TRUE; 11641 } 11642 break; 11643 11644 case SCSI_CAP_LUN_RESET: 11645 if (val) { 11646 plun->lun_cap |= FCP_LUN_CAP_RESET; 11647 } else { 11648 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11649 } 11650 rval = TRUE; 11651 break; 11652 11653 case SCSI_CAP_SECTOR_SIZE: 11654 rval = TRUE; 11655 break; 11656 default: 11657 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11658 fcp_trace, FCP_BUF_LEVEL_4, 0, 11659 "fcp_setcap: unsupported %d", cidx); 11660 rval = UNDEFINED; 11661 break; 11662 } 11663 11664 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11665 fcp_trace, FCP_BUF_LEVEL_5, 0, 11666 "set cap: cap=%s, val/tgtonly/doset/rval = " 11667 "0x%x/0x%x/0x%x/%d", 11668 cap, val, tgtonly, doset, rval); 11669 11670 } else { 11671 /* 11672 * Process getcap request. 11673 */ 11674 switch (cidx) { 11675 case SCSI_CAP_DMA_MAX: 11676 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11677 11678 /* 11679 * Need to make an adjustment qlc is uint_t 64 11680 * st is int, so we will make the adjustment here 11681 * being as nobody wants to touch this. 11682 * It still leaves the max single block length 11683 * of 2 gig. This should last . 11684 */ 11685 11686 if (rval == -1) { 11687 rval = MAX_INT_DMA; 11688 } 11689 11690 break; 11691 11692 case SCSI_CAP_INITIATOR_ID: 11693 rval = pptr->port_id; 11694 break; 11695 11696 case SCSI_CAP_ARQ: 11697 case SCSI_CAP_RESET_NOTIFICATION: 11698 case SCSI_CAP_TAGGED_QING: 11699 rval = TRUE; 11700 break; 11701 11702 case SCSI_CAP_SCSI_VERSION: 11703 rval = 3; 11704 break; 11705 11706 case SCSI_CAP_INTERCONNECT_TYPE: 11707 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11708 (ptgt->tgt_hard_addr == 0)) { 11709 rval = INTERCONNECT_FABRIC; 11710 } else { 11711 rval = INTERCONNECT_FIBRE; 11712 } 11713 break; 11714 11715 case SCSI_CAP_LUN_RESET: 11716 rval = plun->lun_cap; 11717 break; 11718 11719 default: 11720 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11721 fcp_trace, FCP_BUF_LEVEL_4, 0, 11722 "fcp_getcap: unsupported %d", cidx); 11723 rval = UNDEFINED; 11724 break; 11725 } 11726 11727 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11728 fcp_trace, FCP_BUF_LEVEL_8, 0, 11729 "get cap: cap=%s, val/tgtonly/doset/rval = " 11730 "0x%x/0x%x/0x%x/%d", 11731 cap, val, tgtonly, doset, rval); 11732 } 11733 11734 return (rval); 11735 } 11736 11737 /* 11738 * called by the transport to get the port-wwn and lun 11739 * properties of this device, and to create a "name" based on them 11740 * 11741 * these properties don't exist on sun4m 11742 * 11743 * return 1 for success else return 0 11744 */ 11745 /* ARGSUSED */ 11746 static int 11747 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11748 { 11749 int i; 11750 int *lun; 11751 int numChars; 11752 uint_t nlun; 11753 uint_t count; 11754 uint_t nbytes; 11755 uchar_t *bytes; 11756 uint16_t lun_num; 11757 uint32_t tgt_id; 11758 char **conf_wwn; 11759 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11760 uchar_t barray[FC_WWN_SIZE]; 11761 dev_info_t *tgt_dip; 11762 struct fcp_tgt *ptgt; 11763 struct fcp_port *pptr; 11764 struct fcp_lun *plun; 11765 11766 ASSERT(sd != NULL); 11767 ASSERT(name != NULL); 11768 11769 tgt_dip = sd->sd_dev; 11770 pptr = ddi_get_soft_state(fcp_softstate, 11771 ddi_get_instance(ddi_get_parent(tgt_dip))); 11772 if (pptr == NULL) { 11773 return (0); 11774 } 11775 11776 ASSERT(tgt_dip != NULL); 11777 11778 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11779 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11780 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11781 name[0] = '\0'; 11782 return (0); 11783 } 11784 11785 if (nlun == 0) { 11786 ddi_prop_free(lun); 11787 return (0); 11788 } 11789 11790 lun_num = lun[0]; 11791 ddi_prop_free(lun); 11792 11793 /* 11794 * Lookup for .conf WWN property 11795 */ 11796 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11797 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11798 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11799 ASSERT(count >= 1); 11800 11801 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11802 ddi_prop_free(conf_wwn); 11803 mutex_enter(&pptr->port_mutex); 11804 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11805 mutex_exit(&pptr->port_mutex); 11806 return (0); 11807 } 11808 ptgt = plun->lun_tgt; 11809 mutex_exit(&pptr->port_mutex); 11810 11811 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11812 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11813 11814 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11815 ptgt->tgt_hard_addr != 0) { 11816 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11817 ptgt->tgt_hard_addr]; 11818 } else { 11819 tgt_id = ptgt->tgt_d_id; 11820 } 11821 11822 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11823 TARGET_PROP, tgt_id); 11824 } 11825 11826 /* get the our port-wwn property */ 11827 bytes = NULL; 11828 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 11829 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 11830 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 11831 if (bytes != NULL) { 11832 ddi_prop_free(bytes); 11833 } 11834 return (0); 11835 } 11836 11837 for (i = 0; i < FC_WWN_SIZE; i++) { 11838 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 11839 } 11840 11841 /* Stick in the address of the form "wWWN,LUN" */ 11842 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 11843 11844 ASSERT(numChars < len); 11845 if (numChars >= len) { 11846 fcp_log(CE_WARN, pptr->port_dip, 11847 "!fcp_scsi_get_name: " 11848 "name parameter length too small, it needs to be %d", 11849 numChars+1); 11850 } 11851 11852 ddi_prop_free(bytes); 11853 11854 return (1); 11855 } 11856 11857 11858 /* 11859 * called by the transport to get the SCSI target id value, returning 11860 * it in "name" 11861 * 11862 * this isn't needed/used on sun4m 11863 * 11864 * return 1 for success else return 0 11865 */ 11866 /* ARGSUSED */ 11867 static int 11868 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 11869 { 11870 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 11871 struct fcp_tgt *ptgt; 11872 int numChars; 11873 11874 if (plun == NULL) { 11875 return (0); 11876 } 11877 11878 if ((ptgt = plun->lun_tgt) == NULL) { 11879 return (0); 11880 } 11881 11882 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 11883 11884 ASSERT(numChars < len); 11885 if (numChars >= len) { 11886 fcp_log(CE_WARN, NULL, 11887 "!fcp_scsi_get_bus_addr: " 11888 "name parameter length too small, it needs to be %d", 11889 numChars+1); 11890 } 11891 11892 return (1); 11893 } 11894 11895 11896 /* 11897 * called internally to reset the link where the specified port lives 11898 */ 11899 static int 11900 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 11901 { 11902 la_wwn_t wwn; 11903 struct fcp_lun *plun; 11904 struct fcp_tgt *ptgt; 11905 11906 /* disable restart of lip if we're suspended */ 11907 mutex_enter(&pptr->port_mutex); 11908 11909 if (pptr->port_state & (FCP_STATE_SUSPENDED | 11910 FCP_STATE_POWER_DOWN)) { 11911 mutex_exit(&pptr->port_mutex); 11912 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11913 fcp_trace, FCP_BUF_LEVEL_2, 0, 11914 "fcp_linkreset, fcp%d: link reset " 11915 "disabled due to DDI_SUSPEND", 11916 ddi_get_instance(pptr->port_dip)); 11917 return (FC_FAILURE); 11918 } 11919 11920 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 11921 mutex_exit(&pptr->port_mutex); 11922 return (FC_SUCCESS); 11923 } 11924 11925 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11926 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 11927 11928 /* 11929 * If ap == NULL assume local link reset. 11930 */ 11931 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 11932 plun = ADDR2LUN(ap); 11933 ptgt = plun->lun_tgt; 11934 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 11935 } else { 11936 bzero((caddr_t)&wwn, sizeof (wwn)); 11937 } 11938 mutex_exit(&pptr->port_mutex); 11939 11940 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 11941 } 11942 11943 11944 /* 11945 * called from fcp_port_attach() to resume a port 11946 * return DDI_* success/failure status 11947 * acquires and releases the global mutex 11948 * acquires and releases the port mutex 11949 */ 11950 /*ARGSUSED*/ 11951 11952 static int 11953 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 11954 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 11955 { 11956 int res = DDI_FAILURE; /* default result */ 11957 struct fcp_port *pptr; /* port state ptr */ 11958 uint32_t alloc_cnt; 11959 uint32_t max_cnt; 11960 fc_portmap_t *tmp_list = NULL; 11961 11962 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 11963 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 11964 instance); 11965 11966 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 11967 cmn_err(CE_WARN, "fcp: bad soft state"); 11968 return (res); 11969 } 11970 11971 mutex_enter(&pptr->port_mutex); 11972 switch (cmd) { 11973 case FC_CMD_RESUME: 11974 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 11975 pptr->port_state &= ~FCP_STATE_SUSPENDED; 11976 break; 11977 11978 case FC_CMD_POWER_UP: 11979 /* 11980 * If the port is DDI_SUSPENded, defer rediscovery 11981 * until DDI_RESUME occurs 11982 */ 11983 if (pptr->port_state & FCP_STATE_SUSPENDED) { 11984 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 11985 mutex_exit(&pptr->port_mutex); 11986 return (DDI_SUCCESS); 11987 } 11988 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 11989 } 11990 pptr->port_id = s_id; 11991 pptr->port_state = FCP_STATE_INIT; 11992 mutex_exit(&pptr->port_mutex); 11993 11994 /* 11995 * Make a copy of ulp_port_info as fctl allocates 11996 * a temp struct. 11997 */ 11998 (void) fcp_cp_pinfo(pptr, pinfo); 11999 12000 mutex_enter(&fcp_global_mutex); 12001 if (fcp_watchdog_init++ == 0) { 12002 fcp_watchdog_tick = fcp_watchdog_timeout * 12003 drv_usectohz(1000000); 12004 fcp_watchdog_id = timeout(fcp_watch, 12005 NULL, fcp_watchdog_tick); 12006 } 12007 mutex_exit(&fcp_global_mutex); 12008 12009 /* 12010 * Handle various topologies and link states. 12011 */ 12012 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12013 case FC_STATE_OFFLINE: 12014 /* 12015 * Wait for ONLINE, at which time a state 12016 * change will cause a statec_callback 12017 */ 12018 res = DDI_SUCCESS; 12019 break; 12020 12021 case FC_STATE_ONLINE: 12022 12023 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12024 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12025 res = DDI_SUCCESS; 12026 break; 12027 } 12028 12029 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12030 !fcp_enable_auto_configuration) { 12031 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12032 if (tmp_list == NULL) { 12033 if (!alloc_cnt) { 12034 res = DDI_SUCCESS; 12035 } 12036 break; 12037 } 12038 max_cnt = alloc_cnt; 12039 } else { 12040 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12041 12042 alloc_cnt = FCP_MAX_DEVICES; 12043 12044 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12045 (sizeof (fc_portmap_t)) * alloc_cnt, 12046 KM_NOSLEEP)) == NULL) { 12047 fcp_log(CE_WARN, pptr->port_dip, 12048 "!fcp%d: failed to allocate portmap", 12049 instance); 12050 break; 12051 } 12052 12053 max_cnt = alloc_cnt; 12054 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12055 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12056 FC_SUCCESS) { 12057 caddr_t msg; 12058 12059 (void) fc_ulp_error(res, &msg); 12060 12061 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12062 fcp_trace, FCP_BUF_LEVEL_2, 0, 12063 "resume failed getportmap: reason=0x%x", 12064 res); 12065 12066 fcp_log(CE_WARN, pptr->port_dip, 12067 "!failed to get port map : %s", msg); 12068 break; 12069 } 12070 if (max_cnt > alloc_cnt) { 12071 alloc_cnt = max_cnt; 12072 } 12073 } 12074 12075 /* 12076 * do the SCSI device discovery and create 12077 * the devinfos 12078 */ 12079 fcp_statec_callback(ulph, pptr->port_fp_handle, 12080 pptr->port_phys_state, pptr->port_topology, tmp_list, 12081 max_cnt, pptr->port_id); 12082 12083 res = DDI_SUCCESS; 12084 break; 12085 12086 default: 12087 fcp_log(CE_WARN, pptr->port_dip, 12088 "!fcp%d: invalid port state at attach=0x%x", 12089 instance, pptr->port_phys_state); 12090 12091 mutex_enter(&pptr->port_mutex); 12092 pptr->port_phys_state = FCP_STATE_OFFLINE; 12093 mutex_exit(&pptr->port_mutex); 12094 res = DDI_SUCCESS; 12095 12096 break; 12097 } 12098 12099 if (tmp_list != NULL) { 12100 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12101 } 12102 12103 return (res); 12104 } 12105 12106 12107 static void 12108 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12109 { 12110 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12111 pptr->port_dip = pinfo->port_dip; 12112 pptr->port_fp_handle = pinfo->port_handle; 12113 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12114 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12115 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12116 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12117 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12118 pptr->port_max_exch = pinfo->port_fca_max_exch; 12119 pptr->port_phys_state = pinfo->port_state; 12120 pptr->port_topology = pinfo->port_flags; 12121 pptr->port_reset_action = pinfo->port_reset_action; 12122 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12123 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12124 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12125 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12126 } 12127 12128 /* 12129 * If the elements wait field is set to 1 then 12130 * another thread is waiting for the operation to complete. Once 12131 * it is complete, the waiting thread is signaled and the element is 12132 * freed by the waiting thread. If the elements wait field is set to 0 12133 * the element is freed. 12134 */ 12135 static void 12136 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12137 { 12138 ASSERT(elem != NULL); 12139 mutex_enter(&elem->mutex); 12140 elem->result = result; 12141 if (elem->wait) { 12142 elem->wait = 0; 12143 cv_signal(&elem->cv); 12144 mutex_exit(&elem->mutex); 12145 } else { 12146 mutex_exit(&elem->mutex); 12147 cv_destroy(&elem->cv); 12148 mutex_destroy(&elem->mutex); 12149 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12150 } 12151 } 12152 12153 /* 12154 * This function is invoked from the taskq thread to allocate 12155 * devinfo nodes and to online/offline them. 12156 */ 12157 static void 12158 fcp_hp_task(void *arg) 12159 { 12160 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12161 struct fcp_lun *plun = elem->lun; 12162 struct fcp_port *pptr = elem->port; 12163 int result; 12164 12165 ASSERT(elem->what == FCP_ONLINE || 12166 elem->what == FCP_OFFLINE || 12167 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12168 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12169 12170 mutex_enter(&pptr->port_mutex); 12171 mutex_enter(&plun->lun_mutex); 12172 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12173 plun->lun_event_count != elem->event_cnt) || 12174 pptr->port_state & (FCP_STATE_SUSPENDED | 12175 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12176 mutex_exit(&plun->lun_mutex); 12177 mutex_exit(&pptr->port_mutex); 12178 fcp_process_elem(elem, NDI_FAILURE); 12179 return; 12180 } 12181 mutex_exit(&plun->lun_mutex); 12182 mutex_exit(&pptr->port_mutex); 12183 12184 result = fcp_trigger_lun(plun, elem->cip, elem->what, 12185 elem->link_cnt, elem->tgt_cnt, elem->flags); 12186 fcp_process_elem(elem, result); 12187 } 12188 12189 12190 static child_info_t * 12191 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12192 int tcount) 12193 { 12194 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12195 12196 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12197 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12198 12199 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12200 /* 12201 * Child has not been created yet. Create the child device 12202 * based on the per-Lun flags. 12203 */ 12204 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12205 plun->lun_cip = 12206 CIP(fcp_create_dip(plun, lcount, tcount)); 12207 plun->lun_mpxio = 0; 12208 } else { 12209 plun->lun_cip = 12210 CIP(fcp_create_pip(plun, lcount, tcount)); 12211 plun->lun_mpxio = 1; 12212 } 12213 } else { 12214 plun->lun_cip = cip; 12215 } 12216 12217 return (plun->lun_cip); 12218 } 12219 12220 12221 static int 12222 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12223 { 12224 int rval = FC_FAILURE; 12225 dev_info_t *pdip; 12226 struct dev_info *dip; 12227 int circular; 12228 12229 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12230 12231 pdip = plun->lun_tgt->tgt_port->port_dip; 12232 12233 if (plun->lun_cip == NULL) { 12234 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12235 fcp_trace, FCP_BUF_LEVEL_3, 0, 12236 "fcp_is_dip_present: plun->lun_cip is NULL: " 12237 "plun: %p lun state: %x num: %d target state: %x", 12238 plun, plun->lun_state, plun->lun_num, 12239 plun->lun_tgt->tgt_port->port_state); 12240 return (rval); 12241 } 12242 ndi_devi_enter(pdip, &circular); 12243 dip = DEVI(pdip)->devi_child; 12244 while (dip) { 12245 if (dip == DEVI(cdip)) { 12246 rval = FC_SUCCESS; 12247 break; 12248 } 12249 dip = dip->devi_sibling; 12250 } 12251 ndi_devi_exit(pdip, circular); 12252 return (rval); 12253 } 12254 12255 static int 12256 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12257 { 12258 int rval = FC_FAILURE; 12259 12260 ASSERT(plun != NULL); 12261 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12262 12263 if (plun->lun_mpxio == 0) { 12264 rval = fcp_is_dip_present(plun, DIP(cip)); 12265 } else { 12266 rval = fcp_is_pip_present(plun, PIP(cip)); 12267 } 12268 12269 return (rval); 12270 } 12271 12272 /* 12273 * Function: fcp_create_dip 12274 * 12275 * Description: Creates a dev_info_t structure for the LUN specified by the 12276 * caller. 12277 * 12278 * Argument: plun Lun structure 12279 * link_cnt Link state count. 12280 * tgt_cnt Target state change count. 12281 * 12282 * Return Value: NULL if it failed 12283 * dev_info_t structure address if it succeeded 12284 * 12285 * Context: Kernel context 12286 */ 12287 static dev_info_t * 12288 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12289 { 12290 int failure = 0; 12291 uint32_t tgt_id; 12292 uint64_t sam_lun; 12293 struct fcp_tgt *ptgt = plun->lun_tgt; 12294 struct fcp_port *pptr = ptgt->tgt_port; 12295 dev_info_t *pdip = pptr->port_dip; 12296 dev_info_t *cdip = NULL; 12297 dev_info_t *old_dip = DIP(plun->lun_cip); 12298 char *nname = NULL; 12299 char **compatible = NULL; 12300 int ncompatible; 12301 char *scsi_binding_set; 12302 char t_pwwn[17]; 12303 12304 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12305 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12306 12307 /* get the 'scsi-binding-set' property */ 12308 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12309 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12310 &scsi_binding_set) != DDI_PROP_SUCCESS) 12311 scsi_binding_set = NULL; 12312 12313 /* determine the node name and compatible */ 12314 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12315 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12316 if (scsi_binding_set) 12317 ddi_prop_free(scsi_binding_set); 12318 12319 if (nname == NULL) { 12320 #ifdef DEBUG 12321 cmn_err(CE_WARN, "%s%d: no driver for " 12322 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12323 " compatible: %s", 12324 ddi_driver_name(pdip), ddi_get_instance(pdip), 12325 ptgt->tgt_port_wwn.raw_wwn[0], 12326 ptgt->tgt_port_wwn.raw_wwn[1], 12327 ptgt->tgt_port_wwn.raw_wwn[2], 12328 ptgt->tgt_port_wwn.raw_wwn[3], 12329 ptgt->tgt_port_wwn.raw_wwn[4], 12330 ptgt->tgt_port_wwn.raw_wwn[5], 12331 ptgt->tgt_port_wwn.raw_wwn[6], 12332 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12333 *compatible); 12334 #endif /* DEBUG */ 12335 failure++; 12336 goto end_of_fcp_create_dip; 12337 } 12338 12339 cdip = fcp_find_existing_dip(plun, pdip, nname); 12340 12341 /* 12342 * if the old_dip does not match the cdip, that means there is 12343 * some property change. since we'll be using the cdip, we need 12344 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12345 * then the dtype for the device has been updated. Offline the 12346 * the old device and create a new device with the new device type 12347 * Refer to bug: 4764752 12348 */ 12349 if (old_dip && (cdip != old_dip || 12350 plun->lun_state & FCP_LUN_CHANGED)) { 12351 plun->lun_state &= ~(FCP_LUN_INIT); 12352 mutex_exit(&plun->lun_mutex); 12353 mutex_exit(&pptr->port_mutex); 12354 12355 mutex_enter(&ptgt->tgt_mutex); 12356 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12357 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12358 mutex_exit(&ptgt->tgt_mutex); 12359 12360 #ifdef DEBUG 12361 if (cdip != NULL) { 12362 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12363 fcp_trace, FCP_BUF_LEVEL_2, 0, 12364 "Old dip=%p; New dip=%p don't match", old_dip, 12365 cdip); 12366 } else { 12367 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12368 fcp_trace, FCP_BUF_LEVEL_2, 0, 12369 "Old dip=%p; New dip=NULL don't match", old_dip); 12370 } 12371 #endif 12372 12373 mutex_enter(&pptr->port_mutex); 12374 mutex_enter(&plun->lun_mutex); 12375 } 12376 12377 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12378 plun->lun_state &= ~(FCP_LUN_CHANGED); 12379 if (ndi_devi_alloc(pptr->port_dip, nname, 12380 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12381 failure++; 12382 goto end_of_fcp_create_dip; 12383 } 12384 } 12385 12386 /* 12387 * Previously all the properties for the devinfo were destroyed here 12388 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12389 * the devid property (and other properties established by the target 12390 * driver or framework) which the code does not always recreate, this 12391 * call was removed. 12392 * This opens a theoretical possibility that we may return with a 12393 * stale devid on the node if the scsi entity behind the fibre channel 12394 * lun has changed. 12395 */ 12396 12397 /* decorate the node with compatible */ 12398 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12399 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12400 failure++; 12401 goto end_of_fcp_create_dip; 12402 } 12403 12404 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12405 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12406 failure++; 12407 goto end_of_fcp_create_dip; 12408 } 12409 12410 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12411 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12412 failure++; 12413 goto end_of_fcp_create_dip; 12414 } 12415 12416 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12417 t_pwwn[16] = '\0'; 12418 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12419 != DDI_PROP_SUCCESS) { 12420 failure++; 12421 goto end_of_fcp_create_dip; 12422 } 12423 12424 /* 12425 * If there is no hard address - We might have to deal with 12426 * that by using WWN - Having said that it is important to 12427 * recognize this problem early so ssd can be informed of 12428 * the right interconnect type. 12429 */ 12430 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12431 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12432 } else { 12433 tgt_id = ptgt->tgt_d_id; 12434 } 12435 12436 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12437 tgt_id) != DDI_PROP_SUCCESS) { 12438 failure++; 12439 goto end_of_fcp_create_dip; 12440 } 12441 12442 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12443 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12444 failure++; 12445 goto end_of_fcp_create_dip; 12446 } 12447 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12448 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12449 sam_lun) != DDI_PROP_SUCCESS) { 12450 failure++; 12451 goto end_of_fcp_create_dip; 12452 } 12453 12454 end_of_fcp_create_dip: 12455 scsi_hba_nodename_compatible_free(nname, compatible); 12456 12457 if (cdip != NULL && failure) { 12458 (void) ndi_prop_remove_all(cdip); 12459 (void) ndi_devi_free(cdip); 12460 cdip = NULL; 12461 } 12462 12463 return (cdip); 12464 } 12465 12466 /* 12467 * Function: fcp_create_pip 12468 * 12469 * Description: Creates a Path Id for the LUN specified by the caller. 12470 * 12471 * Argument: plun Lun structure 12472 * link_cnt Link state count. 12473 * tgt_cnt Target state count. 12474 * 12475 * Return Value: NULL if it failed 12476 * mdi_pathinfo_t structure address if it succeeded 12477 * 12478 * Context: Kernel context 12479 */ 12480 static mdi_pathinfo_t * 12481 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12482 { 12483 int i; 12484 char buf[MAXNAMELEN]; 12485 char uaddr[MAXNAMELEN]; 12486 int failure = 0; 12487 uint32_t tgt_id; 12488 uint64_t sam_lun; 12489 struct fcp_tgt *ptgt = plun->lun_tgt; 12490 struct fcp_port *pptr = ptgt->tgt_port; 12491 dev_info_t *pdip = pptr->port_dip; 12492 mdi_pathinfo_t *pip = NULL; 12493 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12494 char *nname = NULL; 12495 char **compatible = NULL; 12496 int ncompatible; 12497 char *scsi_binding_set; 12498 char t_pwwn[17]; 12499 12500 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12501 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12502 12503 scsi_binding_set = "vhci"; 12504 12505 /* determine the node name and compatible */ 12506 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12507 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12508 12509 if (nname == NULL) { 12510 #ifdef DEBUG 12511 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12512 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12513 " compatible: %s", 12514 ddi_driver_name(pdip), ddi_get_instance(pdip), 12515 ptgt->tgt_port_wwn.raw_wwn[0], 12516 ptgt->tgt_port_wwn.raw_wwn[1], 12517 ptgt->tgt_port_wwn.raw_wwn[2], 12518 ptgt->tgt_port_wwn.raw_wwn[3], 12519 ptgt->tgt_port_wwn.raw_wwn[4], 12520 ptgt->tgt_port_wwn.raw_wwn[5], 12521 ptgt->tgt_port_wwn.raw_wwn[6], 12522 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12523 *compatible); 12524 #endif /* DEBUG */ 12525 failure++; 12526 goto end_of_fcp_create_pip; 12527 } 12528 12529 pip = fcp_find_existing_pip(plun, pdip); 12530 12531 /* 12532 * if the old_dip does not match the cdip, that means there is 12533 * some property change. since we'll be using the cdip, we need 12534 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12535 * then the dtype for the device has been updated. Offline the 12536 * the old device and create a new device with the new device type 12537 * Refer to bug: 4764752 12538 */ 12539 if (old_pip && (pip != old_pip || 12540 plun->lun_state & FCP_LUN_CHANGED)) { 12541 plun->lun_state &= ~(FCP_LUN_INIT); 12542 mutex_exit(&plun->lun_mutex); 12543 mutex_exit(&pptr->port_mutex); 12544 12545 mutex_enter(&ptgt->tgt_mutex); 12546 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12547 FCP_OFFLINE, lcount, tcount, 12548 NDI_DEVI_REMOVE, 0); 12549 mutex_exit(&ptgt->tgt_mutex); 12550 12551 if (pip != NULL) { 12552 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12553 fcp_trace, FCP_BUF_LEVEL_2, 0, 12554 "Old pip=%p; New pip=%p don't match", 12555 old_pip, pip); 12556 } else { 12557 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12558 fcp_trace, FCP_BUF_LEVEL_2, 0, 12559 "Old pip=%p; New pip=NULL don't match", 12560 old_pip); 12561 } 12562 12563 mutex_enter(&pptr->port_mutex); 12564 mutex_enter(&plun->lun_mutex); 12565 } 12566 12567 /* 12568 * Since FC_WWN_SIZE is 8 bytes and its not like the 12569 * lun_guid_size which is dependent on the target, I don't 12570 * believe the same trancation happens here UNLESS the standards 12571 * change the FC_WWN_SIZE value to something larger than 12572 * MAXNAMELEN(currently 255 bytes). 12573 */ 12574 12575 for (i = 0; i < FC_WWN_SIZE; i++) 12576 (void) sprintf(&buf[i << 1], "%02x", 12577 ptgt->tgt_port_wwn.raw_wwn[i]); 12578 12579 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12580 buf, plun->lun_num); 12581 12582 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12583 /* 12584 * Release the locks before calling into 12585 * mdi_pi_alloc_compatible() since this can result in a 12586 * callback into fcp which can result in a deadlock 12587 * (see bug # 4870272). 12588 * 12589 * Basically, what we are trying to avoid is the scenario where 12590 * one thread does ndi_devi_enter() and tries to grab 12591 * fcp_mutex and another does it the other way round. 12592 * 12593 * But before we do that, make sure that nobody releases the 12594 * port in the meantime. We can do this by setting a flag. 12595 */ 12596 plun->lun_state &= ~(FCP_LUN_CHANGED); 12597 pptr->port_state |= FCP_STATE_IN_MDI; 12598 mutex_exit(&plun->lun_mutex); 12599 mutex_exit(&pptr->port_mutex); 12600 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12601 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12602 fcp_log(CE_WARN, pptr->port_dip, 12603 "!path alloc failed:0x%x", plun); 12604 mutex_enter(&pptr->port_mutex); 12605 mutex_enter(&plun->lun_mutex); 12606 pptr->port_state &= ~FCP_STATE_IN_MDI; 12607 failure++; 12608 goto end_of_fcp_create_pip; 12609 } 12610 mutex_enter(&pptr->port_mutex); 12611 mutex_enter(&plun->lun_mutex); 12612 pptr->port_state &= ~FCP_STATE_IN_MDI; 12613 } else { 12614 (void) mdi_prop_remove(pip, NULL); 12615 } 12616 12617 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12618 12619 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12620 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12621 != DDI_PROP_SUCCESS) { 12622 failure++; 12623 goto end_of_fcp_create_pip; 12624 } 12625 12626 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12627 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12628 != DDI_PROP_SUCCESS) { 12629 failure++; 12630 goto end_of_fcp_create_pip; 12631 } 12632 12633 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12634 t_pwwn[16] = '\0'; 12635 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12636 != DDI_PROP_SUCCESS) { 12637 failure++; 12638 goto end_of_fcp_create_pip; 12639 } 12640 12641 /* 12642 * If there is no hard address - We might have to deal with 12643 * that by using WWN - Having said that it is important to 12644 * recognize this problem early so ssd can be informed of 12645 * the right interconnect type. 12646 */ 12647 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12648 ptgt->tgt_hard_addr != 0) { 12649 tgt_id = (uint32_t) 12650 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12651 } else { 12652 tgt_id = ptgt->tgt_d_id; 12653 } 12654 12655 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12656 != DDI_PROP_SUCCESS) { 12657 failure++; 12658 goto end_of_fcp_create_pip; 12659 } 12660 12661 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12662 != DDI_PROP_SUCCESS) { 12663 failure++; 12664 goto end_of_fcp_create_pip; 12665 } 12666 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12667 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12668 != DDI_PROP_SUCCESS) { 12669 failure++; 12670 goto end_of_fcp_create_pip; 12671 } 12672 12673 end_of_fcp_create_pip: 12674 scsi_hba_nodename_compatible_free(nname, compatible); 12675 12676 if (pip != NULL && failure) { 12677 (void) mdi_prop_remove(pip, NULL); 12678 mutex_exit(&plun->lun_mutex); 12679 mutex_exit(&pptr->port_mutex); 12680 (void) mdi_pi_free(pip, 0); 12681 mutex_enter(&pptr->port_mutex); 12682 mutex_enter(&plun->lun_mutex); 12683 pip = NULL; 12684 } 12685 12686 return (pip); 12687 } 12688 12689 static dev_info_t * 12690 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12691 { 12692 uint_t nbytes; 12693 uchar_t *bytes; 12694 uint_t nwords; 12695 uint32_t tgt_id; 12696 int *words; 12697 dev_info_t *cdip; 12698 dev_info_t *ndip; 12699 struct fcp_tgt *ptgt = plun->lun_tgt; 12700 struct fcp_port *pptr = ptgt->tgt_port; 12701 int circular; 12702 12703 ndi_devi_enter(pdip, &circular); 12704 12705 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12706 while ((cdip = ndip) != NULL) { 12707 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12708 12709 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12710 continue; 12711 } 12712 12713 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12714 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12715 &nbytes) != DDI_PROP_SUCCESS) { 12716 continue; 12717 } 12718 12719 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12720 if (bytes != NULL) { 12721 ddi_prop_free(bytes); 12722 } 12723 continue; 12724 } 12725 ASSERT(bytes != NULL); 12726 12727 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12728 ddi_prop_free(bytes); 12729 continue; 12730 } 12731 12732 ddi_prop_free(bytes); 12733 12734 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12735 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12736 &nbytes) != DDI_PROP_SUCCESS) { 12737 continue; 12738 } 12739 12740 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12741 if (bytes != NULL) { 12742 ddi_prop_free(bytes); 12743 } 12744 continue; 12745 } 12746 ASSERT(bytes != NULL); 12747 12748 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12749 ddi_prop_free(bytes); 12750 continue; 12751 } 12752 12753 ddi_prop_free(bytes); 12754 12755 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12756 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12757 &nwords) != DDI_PROP_SUCCESS) { 12758 continue; 12759 } 12760 12761 if (nwords != 1 || words == NULL) { 12762 if (words != NULL) { 12763 ddi_prop_free(words); 12764 } 12765 continue; 12766 } 12767 ASSERT(words != NULL); 12768 12769 /* 12770 * If there is no hard address - We might have to deal with 12771 * that by using WWN - Having said that it is important to 12772 * recognize this problem early so ssd can be informed of 12773 * the right interconnect type. 12774 */ 12775 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12776 ptgt->tgt_hard_addr != 0) { 12777 tgt_id = 12778 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12779 } else { 12780 tgt_id = ptgt->tgt_d_id; 12781 } 12782 12783 if (tgt_id != (uint32_t)*words) { 12784 ddi_prop_free(words); 12785 continue; 12786 } 12787 ddi_prop_free(words); 12788 12789 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12790 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12791 &nwords) != DDI_PROP_SUCCESS) { 12792 continue; 12793 } 12794 12795 if (nwords != 1 || words == NULL) { 12796 if (words != NULL) { 12797 ddi_prop_free(words); 12798 } 12799 continue; 12800 } 12801 ASSERT(words != NULL); 12802 12803 if (plun->lun_num == (uint16_t)*words) { 12804 ddi_prop_free(words); 12805 break; 12806 } 12807 ddi_prop_free(words); 12808 } 12809 ndi_devi_exit(pdip, circular); 12810 12811 return (cdip); 12812 } 12813 12814 12815 static int 12816 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 12817 { 12818 dev_info_t *pdip; 12819 char buf[MAXNAMELEN]; 12820 char uaddr[MAXNAMELEN]; 12821 int rval = FC_FAILURE; 12822 12823 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12824 12825 pdip = plun->lun_tgt->tgt_port->port_dip; 12826 12827 /* 12828 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 12829 * non-NULL even when the LUN is not there as in the case when a LUN is 12830 * configured and then deleted on the device end (for T3/T4 case). In 12831 * such cases, pip will be NULL. 12832 * 12833 * If the device generates an RSCN, it will end up getting offlined when 12834 * it disappeared and a new LUN will get created when it is rediscovered 12835 * on the device. If we check for lun_cip here, the LUN will not end 12836 * up getting onlined since this function will end up returning a 12837 * FC_SUCCESS. 12838 * 12839 * The behavior is different on other devices. For instance, on a HDS, 12840 * there was no RSCN generated by the device but the next I/O generated 12841 * a check condition and rediscovery got triggered that way. So, in 12842 * such cases, this path will not be exercised 12843 */ 12844 if (pip == NULL) { 12845 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12846 fcp_trace, FCP_BUF_LEVEL_4, 0, 12847 "fcp_is_pip_present: plun->lun_cip is NULL: " 12848 "plun: %p lun state: %x num: %d target state: %x", 12849 plun, plun->lun_state, plun->lun_num, 12850 plun->lun_tgt->tgt_port->port_state); 12851 return (rval); 12852 } 12853 12854 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 12855 12856 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12857 12858 if (plun->lun_old_guid) { 12859 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 12860 rval = FC_SUCCESS; 12861 } 12862 } else { 12863 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 12864 rval = FC_SUCCESS; 12865 } 12866 } 12867 return (rval); 12868 } 12869 12870 static mdi_pathinfo_t * 12871 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 12872 { 12873 char buf[MAXNAMELEN]; 12874 char uaddr[MAXNAMELEN]; 12875 mdi_pathinfo_t *pip; 12876 struct fcp_tgt *ptgt = plun->lun_tgt; 12877 struct fcp_port *pptr = ptgt->tgt_port; 12878 12879 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12880 12881 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 12882 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12883 12884 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 12885 12886 return (pip); 12887 } 12888 12889 12890 static int 12891 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 12892 int tcount, int flags, int *circ) 12893 { 12894 int rval; 12895 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12896 struct fcp_tgt *ptgt = plun->lun_tgt; 12897 dev_info_t *cdip = NULL; 12898 12899 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12900 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12901 12902 if (plun->lun_cip == NULL) { 12903 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12904 fcp_trace, FCP_BUF_LEVEL_3, 0, 12905 "fcp_online_child: plun->lun_cip is NULL: " 12906 "plun: %p state: %x num: %d target state: %x", 12907 plun, plun->lun_state, plun->lun_num, 12908 plun->lun_tgt->tgt_port->port_state); 12909 return (NDI_FAILURE); 12910 } 12911 again: 12912 if (plun->lun_mpxio == 0) { 12913 cdip = DIP(cip); 12914 mutex_exit(&plun->lun_mutex); 12915 mutex_exit(&pptr->port_mutex); 12916 12917 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12918 fcp_trace, FCP_BUF_LEVEL_3, 0, 12919 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 12920 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 12921 12922 /* 12923 * We could check for FCP_LUN_INIT here but chances 12924 * of getting here when it's already in FCP_LUN_INIT 12925 * is rare and a duplicate ndi_devi_online wouldn't 12926 * hurt either (as the node would already have been 12927 * in CF2) 12928 */ 12929 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) 12930 rval = ndi_devi_bind_driver(cdip, flags); 12931 else 12932 rval = ndi_devi_online(cdip, flags); 12933 /* 12934 * We log the message into trace buffer if the device 12935 * is "ses" and into syslog for any other device 12936 * type. This is to prevent the ndi_devi_online failure 12937 * message that appears for V880/A5K ses devices. 12938 */ 12939 if (rval == NDI_SUCCESS) { 12940 mutex_enter(&ptgt->tgt_mutex); 12941 plun->lun_state |= FCP_LUN_INIT; 12942 mutex_exit(&ptgt->tgt_mutex); 12943 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 12944 fcp_log(CE_NOTE, pptr->port_dip, 12945 "!ndi_devi_online:" 12946 " failed for %s: target=%x lun=%x %x", 12947 ddi_get_name(cdip), ptgt->tgt_d_id, 12948 plun->lun_num, rval); 12949 } else { 12950 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12951 fcp_trace, FCP_BUF_LEVEL_3, 0, 12952 " !ndi_devi_online:" 12953 " failed for %s: target=%x lun=%x %x", 12954 ddi_get_name(cdip), ptgt->tgt_d_id, 12955 plun->lun_num, rval); 12956 } 12957 } else { 12958 cdip = mdi_pi_get_client(PIP(cip)); 12959 mutex_exit(&plun->lun_mutex); 12960 mutex_exit(&pptr->port_mutex); 12961 12962 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12963 fcp_trace, FCP_BUF_LEVEL_3, 0, 12964 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 12965 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 12966 12967 /* 12968 * Hold path and exit phci to avoid deadlock with power 12969 * management code during mdi_pi_online. 12970 */ 12971 mdi_hold_path(PIP(cip)); 12972 mdi_devi_exit_phci(pptr->port_dip, *circ); 12973 12974 rval = mdi_pi_online(PIP(cip), flags); 12975 12976 mdi_devi_enter_phci(pptr->port_dip, circ); 12977 mdi_rele_path(PIP(cip)); 12978 12979 if (rval == MDI_SUCCESS) { 12980 mutex_enter(&ptgt->tgt_mutex); 12981 plun->lun_state |= FCP_LUN_INIT; 12982 mutex_exit(&ptgt->tgt_mutex); 12983 12984 /* 12985 * Clear MPxIO path permanent disable in case 12986 * fcp hotplug dropped the offline event. 12987 */ 12988 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 12989 12990 } else if (rval == MDI_NOT_SUPPORTED) { 12991 child_info_t *old_cip = cip; 12992 12993 /* 12994 * MPxIO does not support this device yet. 12995 * Enumerate in legacy mode. 12996 */ 12997 mutex_enter(&pptr->port_mutex); 12998 mutex_enter(&plun->lun_mutex); 12999 plun->lun_mpxio = 0; 13000 plun->lun_cip = NULL; 13001 cdip = fcp_create_dip(plun, lcount, tcount); 13002 plun->lun_cip = cip = CIP(cdip); 13003 if (cip == NULL) { 13004 fcp_log(CE_WARN, pptr->port_dip, 13005 "!fcp_online_child: " 13006 "Create devinfo failed for LU=%p", plun); 13007 mutex_exit(&plun->lun_mutex); 13008 13009 mutex_enter(&ptgt->tgt_mutex); 13010 plun->lun_state |= FCP_LUN_OFFLINE; 13011 mutex_exit(&ptgt->tgt_mutex); 13012 13013 mutex_exit(&pptr->port_mutex); 13014 13015 /* 13016 * free the mdi_pathinfo node 13017 */ 13018 (void) mdi_pi_free(PIP(old_cip), 0); 13019 } else { 13020 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13021 fcp_trace, FCP_BUF_LEVEL_3, 0, 13022 "fcp_online_child: creating devinfo " 13023 "node 0x%p for plun 0x%p", 13024 cip, plun); 13025 mutex_exit(&plun->lun_mutex); 13026 mutex_exit(&pptr->port_mutex); 13027 /* 13028 * free the mdi_pathinfo node 13029 */ 13030 (void) mdi_pi_free(PIP(old_cip), 0); 13031 mutex_enter(&pptr->port_mutex); 13032 mutex_enter(&plun->lun_mutex); 13033 goto again; 13034 } 13035 } else { 13036 if (cdip) { 13037 fcp_log(CE_NOTE, pptr->port_dip, 13038 "!fcp_online_child: mdi_pi_online:" 13039 " failed for %s: target=%x lun=%x %x", 13040 ddi_get_name(cdip), ptgt->tgt_d_id, 13041 plun->lun_num, rval); 13042 } 13043 } 13044 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13045 } 13046 13047 if (rval == NDI_SUCCESS) { 13048 if (cdip) { 13049 (void) ndi_event_retrieve_cookie( 13050 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13051 &fcp_insert_eid, NDI_EVENT_NOPASS); 13052 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13053 cdip, fcp_insert_eid, NULL); 13054 } 13055 } 13056 mutex_enter(&pptr->port_mutex); 13057 mutex_enter(&plun->lun_mutex); 13058 return (rval); 13059 } 13060 13061 /* ARGSUSED */ 13062 static int 13063 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13064 int tcount, int flags, int *circ) 13065 { 13066 int rval; 13067 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13068 struct fcp_tgt *ptgt = plun->lun_tgt; 13069 dev_info_t *cdip; 13070 13071 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13072 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13073 13074 if (plun->lun_cip == NULL) { 13075 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13076 fcp_trace, FCP_BUF_LEVEL_3, 0, 13077 "fcp_offline_child: plun->lun_cip is NULL: " 13078 "plun: %p lun state: %x num: %d target state: %x", 13079 plun, plun->lun_state, plun->lun_num, 13080 plun->lun_tgt->tgt_port->port_state); 13081 return (NDI_FAILURE); 13082 } 13083 13084 if (plun->lun_mpxio == 0) { 13085 cdip = DIP(cip); 13086 mutex_exit(&plun->lun_mutex); 13087 mutex_exit(&pptr->port_mutex); 13088 rval = ndi_devi_offline(DIP(cip), flags); 13089 if (rval != NDI_SUCCESS) { 13090 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13091 fcp_trace, FCP_BUF_LEVEL_3, 0, 13092 "fcp_offline_child: ndi_devi_offline failed " 13093 "rval=%x cip=%p", rval, cip); 13094 } 13095 } else { 13096 cdip = mdi_pi_get_client(PIP(cip)); 13097 mutex_exit(&plun->lun_mutex); 13098 mutex_exit(&pptr->port_mutex); 13099 13100 /* 13101 * Exit phci to avoid deadlock with power management code 13102 * during mdi_pi_offline 13103 */ 13104 mdi_hold_path(PIP(cip)); 13105 mdi_devi_exit_phci(pptr->port_dip, *circ); 13106 13107 rval = mdi_pi_offline(PIP(cip), flags); 13108 13109 mdi_devi_enter_phci(pptr->port_dip, circ); 13110 mdi_rele_path(PIP(cip)); 13111 13112 if (rval == MDI_SUCCESS) { 13113 /* 13114 * Clear MPxIO path permanent disable as the path is 13115 * already offlined. 13116 */ 13117 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13118 13119 if (flags & NDI_DEVI_REMOVE) { 13120 (void) mdi_pi_free(PIP(cip), 0); 13121 } 13122 } else { 13123 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13124 fcp_trace, FCP_BUF_LEVEL_3, 0, 13125 "fcp_offline_child: mdi_pi_offline failed " 13126 "rval=%x cip=%p", rval, cip); 13127 } 13128 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13129 } 13130 13131 mutex_enter(&ptgt->tgt_mutex); 13132 plun->lun_state &= ~FCP_LUN_INIT; 13133 mutex_exit(&ptgt->tgt_mutex); 13134 13135 mutex_enter(&pptr->port_mutex); 13136 mutex_enter(&plun->lun_mutex); 13137 13138 if (rval == NDI_SUCCESS) { 13139 cdip = NULL; 13140 if (flags & NDI_DEVI_REMOVE) { 13141 /* 13142 * If the guid of the LUN changes, lun_cip will not 13143 * equal to cip, and after offlining the LUN with the 13144 * old guid, we should keep lun_cip since it's the cip 13145 * of the LUN with the new guid. 13146 * Otherwise remove our reference to child node. 13147 */ 13148 if (plun->lun_cip == cip) 13149 plun->lun_cip = NULL; 13150 if (plun->lun_old_guid) { 13151 kmem_free(plun->lun_old_guid, 13152 plun->lun_old_guid_size); 13153 plun->lun_old_guid = NULL; 13154 plun->lun_old_guid_size = 0; 13155 } 13156 } 13157 } 13158 13159 if (cdip) { 13160 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13161 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13162 " target=%x lun=%x", "ndi_offline", 13163 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13164 } 13165 13166 return (rval); 13167 } 13168 13169 static void 13170 fcp_remove_child(struct fcp_lun *plun) 13171 { 13172 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13173 13174 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13175 if (plun->lun_mpxio == 0) { 13176 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13177 (void) ndi_devi_free(DIP(plun->lun_cip)); 13178 } else { 13179 mutex_exit(&plun->lun_mutex); 13180 mutex_exit(&plun->lun_tgt->tgt_mutex); 13181 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13182 FCP_TRACE(fcp_logq, 13183 plun->lun_tgt->tgt_port->port_instbuf, 13184 fcp_trace, FCP_BUF_LEVEL_3, 0, 13185 "lun=%p pip freed %p", plun, plun->lun_cip); 13186 (void) mdi_prop_remove(PIP(plun->lun_cip), NULL); 13187 (void) mdi_pi_free(PIP(plun->lun_cip), 0); 13188 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13189 mutex_enter(&plun->lun_tgt->tgt_mutex); 13190 mutex_enter(&plun->lun_mutex); 13191 } 13192 } 13193 13194 plun->lun_cip = NULL; 13195 } 13196 13197 /* 13198 * called when a timeout occurs 13199 * 13200 * can be scheduled during an attach or resume (if not already running) 13201 * 13202 * one timeout is set up for all ports 13203 * 13204 * acquires and releases the global mutex 13205 */ 13206 /*ARGSUSED*/ 13207 static void 13208 fcp_watch(void *arg) 13209 { 13210 struct fcp_port *pptr; 13211 struct fcp_ipkt *icmd; 13212 struct fcp_ipkt *nicmd; 13213 struct fcp_pkt *cmd; 13214 struct fcp_pkt *ncmd; 13215 struct fcp_pkt *tail; 13216 struct fcp_pkt *pcmd; 13217 struct fcp_pkt *save_head; 13218 struct fcp_port *save_port; 13219 13220 /* increment global watchdog time */ 13221 fcp_watchdog_time += fcp_watchdog_timeout; 13222 13223 mutex_enter(&fcp_global_mutex); 13224 13225 /* scan each port in our list */ 13226 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13227 save_port = fcp_port_head; 13228 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13229 mutex_exit(&fcp_global_mutex); 13230 13231 mutex_enter(&pptr->port_mutex); 13232 if (pptr->port_ipkt_list == NULL && 13233 (pptr->port_state & (FCP_STATE_SUSPENDED | 13234 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13235 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13236 mutex_exit(&pptr->port_mutex); 13237 mutex_enter(&fcp_global_mutex); 13238 goto end_of_watchdog; 13239 } 13240 13241 /* 13242 * We check if a list of targets need to be offlined. 13243 */ 13244 if (pptr->port_offline_tgts) { 13245 fcp_scan_offline_tgts(pptr); 13246 } 13247 13248 /* 13249 * We check if a list of luns need to be offlined. 13250 */ 13251 if (pptr->port_offline_luns) { 13252 fcp_scan_offline_luns(pptr); 13253 } 13254 13255 /* 13256 * We check if a list of targets or luns need to be reset. 13257 */ 13258 if (pptr->port_reset_list) { 13259 fcp_check_reset_delay(pptr); 13260 } 13261 13262 mutex_exit(&pptr->port_mutex); 13263 13264 /* 13265 * This is where the pending commands (pkt) are checked for 13266 * timeout. 13267 */ 13268 mutex_enter(&pptr->port_pkt_mutex); 13269 tail = pptr->port_pkt_tail; 13270 13271 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13272 cmd != NULL; cmd = ncmd) { 13273 ncmd = cmd->cmd_next; 13274 /* 13275 * If a command is in this queue the bit CFLAG_IN_QUEUE 13276 * must be set. 13277 */ 13278 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13279 /* 13280 * FCP_INVALID_TIMEOUT will be set for those 13281 * command that need to be failed. Mostly those 13282 * cmds that could not be queued down for the 13283 * "timeout" value. cmd->cmd_timeout is used 13284 * to try and requeue the command regularly. 13285 */ 13286 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13287 /* 13288 * This command hasn't timed out yet. Let's 13289 * go to the next one. 13290 */ 13291 pcmd = cmd; 13292 goto end_of_loop; 13293 } 13294 13295 if (cmd == pptr->port_pkt_head) { 13296 ASSERT(pcmd == NULL); 13297 pptr->port_pkt_head = cmd->cmd_next; 13298 } else { 13299 ASSERT(pcmd != NULL); 13300 pcmd->cmd_next = cmd->cmd_next; 13301 } 13302 13303 if (cmd == pptr->port_pkt_tail) { 13304 ASSERT(cmd->cmd_next == NULL); 13305 pptr->port_pkt_tail = pcmd; 13306 if (pcmd) 13307 pcmd->cmd_next = NULL; 13308 } 13309 cmd->cmd_next = NULL; 13310 13311 /* 13312 * save the current head before dropping the 13313 * mutex - If the head doesn't remain the 13314 * same after re acquiring the mutex, just 13315 * bail out and revisit on next tick. 13316 * 13317 * PS: The tail pointer can change as the commands 13318 * get requeued after failure to retransport 13319 */ 13320 save_head = pptr->port_pkt_head; 13321 mutex_exit(&pptr->port_pkt_mutex); 13322 13323 if (cmd->cmd_fp_pkt->pkt_timeout == 13324 FCP_INVALID_TIMEOUT) { 13325 struct scsi_pkt *pkt = cmd->cmd_pkt; 13326 struct fcp_lun *plun; 13327 struct fcp_tgt *ptgt; 13328 13329 plun = ADDR2LUN(&pkt->pkt_address); 13330 ptgt = plun->lun_tgt; 13331 13332 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13333 fcp_trace, FCP_BUF_LEVEL_2, 0, 13334 "SCSI cmd 0x%x to D_ID=%x timed out", 13335 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13336 13337 cmd->cmd_state == FCP_PKT_ABORTING ? 13338 fcp_fail_cmd(cmd, CMD_RESET, 13339 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13340 CMD_TIMEOUT, STAT_ABORTED); 13341 } else { 13342 fcp_retransport_cmd(pptr, cmd); 13343 } 13344 mutex_enter(&pptr->port_pkt_mutex); 13345 if (save_head && save_head != pptr->port_pkt_head) { 13346 /* 13347 * Looks like linked list got changed (mostly 13348 * happens when an an OFFLINE LUN code starts 13349 * returning overflow queue commands in 13350 * parallel. So bail out and revisit during 13351 * next tick 13352 */ 13353 break; 13354 } 13355 end_of_loop: 13356 /* 13357 * Scan only upto the previously known tail pointer 13358 * to avoid excessive processing - lots of new packets 13359 * could have been added to the tail or the old ones 13360 * re-queued. 13361 */ 13362 if (cmd == tail) { 13363 break; 13364 } 13365 } 13366 mutex_exit(&pptr->port_pkt_mutex); 13367 13368 mutex_enter(&pptr->port_mutex); 13369 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13370 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13371 13372 nicmd = icmd->ipkt_next; 13373 if ((icmd->ipkt_restart != 0) && 13374 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13375 /* packet has not timed out */ 13376 continue; 13377 } 13378 13379 /* time for packet re-transport */ 13380 if (icmd == pptr->port_ipkt_list) { 13381 pptr->port_ipkt_list = icmd->ipkt_next; 13382 if (pptr->port_ipkt_list) { 13383 pptr->port_ipkt_list->ipkt_prev = 13384 NULL; 13385 } 13386 } else { 13387 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13388 if (icmd->ipkt_next) { 13389 icmd->ipkt_next->ipkt_prev = 13390 icmd->ipkt_prev; 13391 } 13392 } 13393 icmd->ipkt_next = NULL; 13394 icmd->ipkt_prev = NULL; 13395 mutex_exit(&pptr->port_mutex); 13396 13397 if (fcp_is_retryable(icmd)) { 13398 fc_ulp_rscn_info_t *rscnp = 13399 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13400 pkt_ulp_rscn_infop; 13401 13402 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13403 fcp_trace, FCP_BUF_LEVEL_2, 0, 13404 "%x to D_ID=%x Retrying..", 13405 icmd->ipkt_opcode, 13406 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13407 13408 /* 13409 * Update the RSCN count in the packet 13410 * before resending. 13411 */ 13412 13413 if (rscnp != NULL) { 13414 rscnp->ulp_rscn_count = 13415 fc_ulp_get_rscn_count(pptr-> 13416 port_fp_handle); 13417 } 13418 13419 mutex_enter(&pptr->port_mutex); 13420 mutex_enter(&ptgt->tgt_mutex); 13421 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13422 mutex_exit(&ptgt->tgt_mutex); 13423 mutex_exit(&pptr->port_mutex); 13424 switch (icmd->ipkt_opcode) { 13425 int rval; 13426 case LA_ELS_PLOGI: 13427 if ((rval = fc_ulp_login( 13428 pptr->port_fp_handle, 13429 &icmd->ipkt_fpkt, 1)) == 13430 FC_SUCCESS) { 13431 mutex_enter( 13432 &pptr->port_mutex); 13433 continue; 13434 } 13435 if (fcp_handle_ipkt_errors( 13436 pptr, ptgt, icmd, rval, 13437 "PLOGI") == DDI_SUCCESS) { 13438 mutex_enter( 13439 &pptr->port_mutex); 13440 continue; 13441 } 13442 break; 13443 13444 case LA_ELS_PRLI: 13445 if ((rval = fc_ulp_issue_els( 13446 pptr->port_fp_handle, 13447 icmd->ipkt_fpkt)) == 13448 FC_SUCCESS) { 13449 mutex_enter( 13450 &pptr->port_mutex); 13451 continue; 13452 } 13453 if (fcp_handle_ipkt_errors( 13454 pptr, ptgt, icmd, rval, 13455 "PRLI") == DDI_SUCCESS) { 13456 mutex_enter( 13457 &pptr->port_mutex); 13458 continue; 13459 } 13460 break; 13461 13462 default: 13463 if ((rval = fcp_transport( 13464 pptr->port_fp_handle, 13465 icmd->ipkt_fpkt, 1)) == 13466 FC_SUCCESS) { 13467 mutex_enter( 13468 &pptr->port_mutex); 13469 continue; 13470 } 13471 if (fcp_handle_ipkt_errors( 13472 pptr, ptgt, icmd, rval, 13473 "PRLI") == DDI_SUCCESS) { 13474 mutex_enter( 13475 &pptr->port_mutex); 13476 continue; 13477 } 13478 break; 13479 } 13480 } else { 13481 mutex_exit(&ptgt->tgt_mutex); 13482 mutex_exit(&pptr->port_mutex); 13483 } 13484 } else { 13485 fcp_print_error(icmd->ipkt_fpkt); 13486 } 13487 13488 (void) fcp_call_finish_init(pptr, ptgt, 13489 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13490 icmd->ipkt_cause); 13491 fcp_icmd_free(pptr, icmd); 13492 mutex_enter(&pptr->port_mutex); 13493 } 13494 13495 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13496 mutex_exit(&pptr->port_mutex); 13497 mutex_enter(&fcp_global_mutex); 13498 13499 end_of_watchdog: 13500 /* 13501 * Bail out early before getting into trouble 13502 */ 13503 if (save_port != fcp_port_head) { 13504 break; 13505 } 13506 } 13507 13508 if (fcp_watchdog_init > 0) { 13509 /* reschedule timeout to go again */ 13510 fcp_watchdog_id = 13511 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13512 } 13513 mutex_exit(&fcp_global_mutex); 13514 } 13515 13516 13517 static void 13518 fcp_check_reset_delay(struct fcp_port *pptr) 13519 { 13520 uint32_t tgt_cnt; 13521 int level; 13522 struct fcp_tgt *ptgt; 13523 struct fcp_lun *plun; 13524 struct fcp_reset_elem *cur = NULL; 13525 struct fcp_reset_elem *next = NULL; 13526 struct fcp_reset_elem *prev = NULL; 13527 13528 ASSERT(mutex_owned(&pptr->port_mutex)); 13529 13530 next = pptr->port_reset_list; 13531 while ((cur = next) != NULL) { 13532 next = cur->next; 13533 13534 if (cur->timeout < fcp_watchdog_time) { 13535 prev = cur; 13536 continue; 13537 } 13538 13539 ptgt = cur->tgt; 13540 plun = cur->lun; 13541 tgt_cnt = cur->tgt_cnt; 13542 13543 if (ptgt) { 13544 level = RESET_TARGET; 13545 } else { 13546 ASSERT(plun != NULL); 13547 level = RESET_LUN; 13548 ptgt = plun->lun_tgt; 13549 } 13550 if (prev) { 13551 prev->next = next; 13552 } else { 13553 /* 13554 * Because we drop port mutex while doing aborts for 13555 * packets, we can't rely on reset_list pointing to 13556 * our head 13557 */ 13558 if (cur == pptr->port_reset_list) { 13559 pptr->port_reset_list = next; 13560 } else { 13561 struct fcp_reset_elem *which; 13562 13563 which = pptr->port_reset_list; 13564 while (which && which->next != cur) { 13565 which = which->next; 13566 } 13567 ASSERT(which != NULL); 13568 13569 which->next = next; 13570 prev = which; 13571 } 13572 } 13573 13574 kmem_free(cur, sizeof (*cur)); 13575 13576 if (tgt_cnt == ptgt->tgt_change_cnt) { 13577 mutex_enter(&ptgt->tgt_mutex); 13578 if (level == RESET_TARGET) { 13579 fcp_update_tgt_state(ptgt, 13580 FCP_RESET, FCP_LUN_BUSY); 13581 } else { 13582 fcp_update_lun_state(plun, 13583 FCP_RESET, FCP_LUN_BUSY); 13584 } 13585 mutex_exit(&ptgt->tgt_mutex); 13586 13587 mutex_exit(&pptr->port_mutex); 13588 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13589 mutex_enter(&pptr->port_mutex); 13590 } 13591 } 13592 } 13593 13594 13595 static void 13596 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13597 struct fcp_lun *rlun, int tgt_cnt) 13598 { 13599 int rval; 13600 struct fcp_lun *tlun, *nlun; 13601 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13602 *cmd = NULL, *head = NULL, 13603 *tail = NULL; 13604 13605 mutex_enter(&pptr->port_pkt_mutex); 13606 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13607 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13608 struct fcp_tgt *ptgt = plun->lun_tgt; 13609 13610 ncmd = cmd->cmd_next; 13611 13612 if (ptgt != ttgt && plun != rlun) { 13613 pcmd = cmd; 13614 continue; 13615 } 13616 13617 if (pcmd != NULL) { 13618 ASSERT(pptr->port_pkt_head != cmd); 13619 pcmd->cmd_next = ncmd; 13620 } else { 13621 ASSERT(cmd == pptr->port_pkt_head); 13622 pptr->port_pkt_head = ncmd; 13623 } 13624 if (pptr->port_pkt_tail == cmd) { 13625 ASSERT(cmd->cmd_next == NULL); 13626 pptr->port_pkt_tail = pcmd; 13627 if (pcmd != NULL) 13628 pcmd->cmd_next = NULL; 13629 } 13630 13631 if (head == NULL) { 13632 head = tail = cmd; 13633 } else { 13634 ASSERT(tail != NULL); 13635 tail->cmd_next = cmd; 13636 tail = cmd; 13637 } 13638 cmd->cmd_next = NULL; 13639 } 13640 mutex_exit(&pptr->port_pkt_mutex); 13641 13642 for (cmd = head; cmd != NULL; cmd = ncmd) { 13643 struct scsi_pkt *pkt = cmd->cmd_pkt; 13644 13645 ncmd = cmd->cmd_next; 13646 ASSERT(pkt != NULL); 13647 13648 mutex_enter(&pptr->port_mutex); 13649 if (ttgt->tgt_change_cnt == tgt_cnt) { 13650 mutex_exit(&pptr->port_mutex); 13651 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13652 pkt->pkt_reason = CMD_RESET; 13653 pkt->pkt_statistics |= STAT_DEV_RESET; 13654 cmd->cmd_state = FCP_PKT_IDLE; 13655 fcp_post_callback(cmd); 13656 } else { 13657 mutex_exit(&pptr->port_mutex); 13658 } 13659 } 13660 13661 /* 13662 * If the FCA will return all the commands in its queue then our 13663 * work is easy, just return. 13664 */ 13665 13666 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) 13667 return; 13668 13669 /* 13670 * For RESET_LUN get hold of target pointer 13671 */ 13672 if (ttgt == NULL) { 13673 ASSERT(rlun != NULL); 13674 13675 ttgt = rlun->lun_tgt; 13676 13677 ASSERT(ttgt != NULL); 13678 } 13679 13680 /* 13681 * There are some severe race conditions here. 13682 * While we are trying to abort the pkt, it might be completing 13683 * so mark it aborted and if the abort does not succeed then 13684 * handle it in the watch thread. 13685 */ 13686 mutex_enter(&ttgt->tgt_mutex); 13687 nlun = ttgt->tgt_lun; 13688 mutex_exit(&ttgt->tgt_mutex); 13689 while ((tlun = nlun) != NULL) { 13690 int restart = 0; 13691 if (rlun && rlun != tlun) { 13692 mutex_enter(&ttgt->tgt_mutex); 13693 nlun = tlun->lun_next; 13694 mutex_exit(&ttgt->tgt_mutex); 13695 continue; 13696 } 13697 mutex_enter(&tlun->lun_mutex); 13698 cmd = tlun->lun_pkt_head; 13699 while (cmd != NULL) { 13700 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13701 struct scsi_pkt *pkt; 13702 13703 restart = 1; 13704 cmd->cmd_state = FCP_PKT_ABORTING; 13705 mutex_exit(&tlun->lun_mutex); 13706 rval = fc_ulp_abort(pptr->port_fp_handle, 13707 cmd->cmd_fp_pkt, KM_SLEEP); 13708 if (rval == FC_SUCCESS) { 13709 pkt = cmd->cmd_pkt; 13710 pkt->pkt_reason = CMD_RESET; 13711 pkt->pkt_statistics |= STAT_DEV_RESET; 13712 cmd->cmd_state = FCP_PKT_IDLE; 13713 fcp_post_callback(cmd); 13714 } else { 13715 caddr_t msg; 13716 13717 (void) fc_ulp_error(rval, &msg); 13718 13719 /* 13720 * This part is tricky. The abort 13721 * failed and now the command could 13722 * be completing. The cmd_state == 13723 * FCP_PKT_ABORTING should save 13724 * us in fcp_cmd_callback. If we 13725 * are already aborting ignore the 13726 * command in fcp_cmd_callback. 13727 * Here we leave this packet for 20 13728 * sec to be aborted in the 13729 * fcp_watch thread. 13730 */ 13731 fcp_log(CE_WARN, pptr->port_dip, 13732 "!Abort failed after reset %s", 13733 msg); 13734 13735 cmd->cmd_timeout = 13736 fcp_watchdog_time + 13737 cmd->cmd_pkt->pkt_time + 13738 FCP_FAILED_DELAY; 13739 13740 cmd->cmd_fp_pkt->pkt_timeout = 13741 FCP_INVALID_TIMEOUT; 13742 /* 13743 * This is a hack, cmd is put in the 13744 * overflow queue so that it can be 13745 * timed out finally 13746 */ 13747 cmd->cmd_flags |= CFLAG_IN_QUEUE; 13748 13749 mutex_enter(&pptr->port_pkt_mutex); 13750 if (pptr->port_pkt_head) { 13751 ASSERT(pptr->port_pkt_tail 13752 != NULL); 13753 pptr->port_pkt_tail->cmd_next 13754 = cmd; 13755 pptr->port_pkt_tail = cmd; 13756 } else { 13757 ASSERT(pptr->port_pkt_tail 13758 == NULL); 13759 pptr->port_pkt_head = 13760 pptr->port_pkt_tail 13761 = cmd; 13762 } 13763 cmd->cmd_next = NULL; 13764 mutex_exit(&pptr->port_pkt_mutex); 13765 } 13766 mutex_enter(&tlun->lun_mutex); 13767 cmd = tlun->lun_pkt_head; 13768 } else { 13769 cmd = cmd->cmd_forw; 13770 } 13771 } 13772 mutex_exit(&tlun->lun_mutex); 13773 13774 mutex_enter(&ttgt->tgt_mutex); 13775 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 13776 mutex_exit(&ttgt->tgt_mutex); 13777 13778 mutex_enter(&pptr->port_mutex); 13779 if (tgt_cnt != ttgt->tgt_change_cnt) { 13780 mutex_exit(&pptr->port_mutex); 13781 return; 13782 } else { 13783 mutex_exit(&pptr->port_mutex); 13784 } 13785 } 13786 } 13787 13788 13789 /* 13790 * unlink the soft state, returning the soft state found (if any) 13791 * 13792 * acquires and releases the global mutex 13793 */ 13794 struct fcp_port * 13795 fcp_soft_state_unlink(struct fcp_port *pptr) 13796 { 13797 struct fcp_port *hptr; /* ptr index */ 13798 struct fcp_port *tptr; /* prev hptr */ 13799 13800 mutex_enter(&fcp_global_mutex); 13801 for (hptr = fcp_port_head, tptr = NULL; 13802 hptr != NULL; 13803 tptr = hptr, hptr = hptr->port_next) { 13804 if (hptr == pptr) { 13805 /* we found a match -- remove this item */ 13806 if (tptr == NULL) { 13807 /* we're at the head of the list */ 13808 fcp_port_head = hptr->port_next; 13809 } else { 13810 tptr->port_next = hptr->port_next; 13811 } 13812 break; /* success */ 13813 } 13814 } 13815 if (fcp_port_head == NULL) { 13816 fcp_cleanup_blacklist(&fcp_lun_blacklist); 13817 } 13818 mutex_exit(&fcp_global_mutex); 13819 return (hptr); 13820 } 13821 13822 13823 /* 13824 * called by fcp_scsi_hba_tgt_init to find a LUN given a 13825 * WWN and a LUN number 13826 */ 13827 /* ARGSUSED */ 13828 static struct fcp_lun * 13829 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 13830 { 13831 int hash; 13832 struct fcp_tgt *ptgt; 13833 struct fcp_lun *plun; 13834 13835 ASSERT(mutex_owned(&pptr->port_mutex)); 13836 13837 hash = FCP_HASH(wwn); 13838 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 13839 ptgt = ptgt->tgt_next) { 13840 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 13841 sizeof (ptgt->tgt_port_wwn)) == 0) { 13842 mutex_enter(&ptgt->tgt_mutex); 13843 for (plun = ptgt->tgt_lun; 13844 plun != NULL; 13845 plun = plun->lun_next) { 13846 if (plun->lun_num == lun) { 13847 mutex_exit(&ptgt->tgt_mutex); 13848 return (plun); 13849 } 13850 } 13851 mutex_exit(&ptgt->tgt_mutex); 13852 return (NULL); 13853 } 13854 } 13855 return (NULL); 13856 } 13857 13858 /* 13859 * Function: fcp_prepare_pkt 13860 * 13861 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 13862 * for fcp_start(). It binds the data or partially maps it. 13863 * Builds the FCP header and starts the initialization of the 13864 * Fibre Channel header. 13865 * 13866 * Argument: *pptr FCP port. 13867 * *cmd FCP packet. 13868 * *plun LUN the command will be sent to. 13869 * 13870 * Context: User, Kernel and Interrupt context. 13871 */ 13872 static void 13873 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 13874 struct fcp_lun *plun) 13875 { 13876 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 13877 struct fcp_tgt *ptgt = plun->lun_tgt; 13878 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 13879 13880 ASSERT(cmd->cmd_pkt->pkt_comp || 13881 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 13882 13883 if (cmd->cmd_pkt->pkt_numcookies) { 13884 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 13885 fcmd->fcp_cntl.cntl_read_data = 1; 13886 fcmd->fcp_cntl.cntl_write_data = 0; 13887 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 13888 } else { 13889 fcmd->fcp_cntl.cntl_read_data = 0; 13890 fcmd->fcp_cntl.cntl_write_data = 1; 13891 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 13892 } 13893 13894 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 13895 13896 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 13897 ASSERT(fpkt->pkt_data_cookie_cnt <= 13898 pptr->port_data_dma_attr.dma_attr_sgllen); 13899 13900 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 13901 13902 /* FCA needs pkt_datalen to be set */ 13903 fpkt->pkt_datalen = cmd->cmd_dmacount; 13904 fcmd->fcp_data_len = cmd->cmd_dmacount; 13905 } else { 13906 fcmd->fcp_cntl.cntl_read_data = 0; 13907 fcmd->fcp_cntl.cntl_write_data = 0; 13908 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 13909 fpkt->pkt_datalen = 0; 13910 fcmd->fcp_data_len = 0; 13911 } 13912 13913 /* set up the Tagged Queuing type */ 13914 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 13915 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 13916 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 13917 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 13918 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 13919 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 13920 } else { 13921 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 13922 } 13923 13924 fcmd->fcp_ent_addr = plun->lun_addr; 13925 13926 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 13927 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 13928 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 13929 } else { 13930 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 13931 } 13932 13933 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 13934 cmd->cmd_pkt->pkt_state = 0; 13935 cmd->cmd_pkt->pkt_statistics = 0; 13936 cmd->cmd_pkt->pkt_resid = 0; 13937 13938 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 13939 13940 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 13941 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 13942 fpkt->pkt_comp = NULL; 13943 } else { 13944 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 13945 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 13946 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 13947 } 13948 fpkt->pkt_comp = fcp_cmd_callback; 13949 } 13950 13951 mutex_enter(&pptr->port_mutex); 13952 if (pptr->port_state & FCP_STATE_SUSPENDED) { 13953 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 13954 } 13955 mutex_exit(&pptr->port_mutex); 13956 13957 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 13958 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 13959 13960 /* 13961 * Save a few kernel cycles here 13962 */ 13963 #ifndef __lock_lint 13964 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 13965 #endif /* __lock_lint */ 13966 } 13967 13968 static void 13969 fcp_post_callback(struct fcp_pkt *cmd) 13970 { 13971 if (cmd->cmd_pkt->pkt_comp) { 13972 (*cmd->cmd_pkt->pkt_comp) (cmd->cmd_pkt); 13973 } 13974 } 13975 13976 13977 /* 13978 * called to do polled I/O by fcp_start() 13979 * 13980 * return a transport status value, i.e. TRAN_ACCECPT for success 13981 */ 13982 static int 13983 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 13984 { 13985 int rval; 13986 13987 #ifdef DEBUG 13988 mutex_enter(&pptr->port_pkt_mutex); 13989 pptr->port_npkts++; 13990 mutex_exit(&pptr->port_pkt_mutex); 13991 #endif /* DEBUG */ 13992 13993 if (cmd->cmd_fp_pkt->pkt_timeout) { 13994 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 13995 } else { 13996 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 13997 } 13998 13999 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14000 14001 cmd->cmd_state = FCP_PKT_ISSUED; 14002 14003 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14004 14005 #ifdef DEBUG 14006 mutex_enter(&pptr->port_pkt_mutex); 14007 pptr->port_npkts--; 14008 mutex_exit(&pptr->port_pkt_mutex); 14009 #endif /* DEBUG */ 14010 14011 cmd->cmd_state = FCP_PKT_IDLE; 14012 14013 switch (rval) { 14014 case FC_SUCCESS: 14015 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14016 fcp_complete_pkt(cmd->cmd_fp_pkt); 14017 rval = TRAN_ACCEPT; 14018 } else { 14019 rval = TRAN_FATAL_ERROR; 14020 } 14021 break; 14022 14023 case FC_TRAN_BUSY: 14024 rval = TRAN_BUSY; 14025 cmd->cmd_pkt->pkt_resid = 0; 14026 break; 14027 14028 case FC_BADPACKET: 14029 rval = TRAN_BADPKT; 14030 break; 14031 14032 default: 14033 rval = TRAN_FATAL_ERROR; 14034 break; 14035 } 14036 14037 return (rval); 14038 } 14039 14040 14041 /* 14042 * called by some of the following transport-called routines to convert 14043 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14044 */ 14045 static struct fcp_port * 14046 fcp_dip2port(dev_info_t *dip) 14047 { 14048 int instance; 14049 14050 instance = ddi_get_instance(dip); 14051 return (ddi_get_soft_state(fcp_softstate, instance)); 14052 } 14053 14054 14055 /* 14056 * called internally to return a LUN given a dip 14057 */ 14058 struct fcp_lun * 14059 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14060 { 14061 struct fcp_tgt *ptgt; 14062 struct fcp_lun *plun; 14063 int i; 14064 14065 14066 ASSERT(mutex_owned(&pptr->port_mutex)); 14067 14068 for (i = 0; i < FCP_NUM_HASH; i++) { 14069 for (ptgt = pptr->port_tgt_hash_table[i]; 14070 ptgt != NULL; 14071 ptgt = ptgt->tgt_next) { 14072 mutex_enter(&ptgt->tgt_mutex); 14073 for (plun = ptgt->tgt_lun; plun != NULL; 14074 plun = plun->lun_next) { 14075 mutex_enter(&plun->lun_mutex); 14076 if (plun->lun_cip == cip) { 14077 mutex_exit(&plun->lun_mutex); 14078 mutex_exit(&ptgt->tgt_mutex); 14079 return (plun); /* match found */ 14080 } 14081 mutex_exit(&plun->lun_mutex); 14082 } 14083 mutex_exit(&ptgt->tgt_mutex); 14084 } 14085 } 14086 return (NULL); /* no LUN found */ 14087 } 14088 14089 /* 14090 * pass an element to the hotplug list, kick the hotplug thread 14091 * and wait for the element to get processed by the hotplug thread. 14092 * on return the element is freed. 14093 * 14094 * return zero success and non-zero on failure 14095 * 14096 * acquires/releases the target mutex 14097 * 14098 */ 14099 static int 14100 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14101 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14102 { 14103 struct fcp_hp_elem *elem; 14104 int rval; 14105 14106 mutex_enter(&plun->lun_tgt->tgt_mutex); 14107 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14108 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14109 mutex_exit(&plun->lun_tgt->tgt_mutex); 14110 fcp_log(CE_CONT, pptr->port_dip, 14111 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14112 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14113 return (NDI_FAILURE); 14114 } 14115 mutex_exit(&plun->lun_tgt->tgt_mutex); 14116 mutex_enter(&elem->mutex); 14117 if (elem->wait) { 14118 while (elem->wait) { 14119 cv_wait(&elem->cv, &elem->mutex); 14120 } 14121 } 14122 rval = (elem->result); 14123 mutex_exit(&elem->mutex); 14124 mutex_destroy(&elem->mutex); 14125 cv_destroy(&elem->cv); 14126 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14127 return (rval); 14128 } 14129 14130 /* 14131 * pass an element to the hotplug list, and then 14132 * kick the hotplug thread 14133 * 14134 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14135 * 14136 * acquires/releases the hotplug mutex 14137 * 14138 * called with the target mutex owned 14139 * 14140 * memory acquired in NOSLEEP mode 14141 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14142 * for the hp daemon to process the request and is responsible for 14143 * freeing the element 14144 */ 14145 static struct fcp_hp_elem * 14146 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14147 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14148 { 14149 struct fcp_hp_elem *elem; 14150 dev_info_t *pdip; 14151 14152 ASSERT(pptr != NULL); 14153 ASSERT(plun != NULL); 14154 ASSERT(plun->lun_tgt != NULL); 14155 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14156 14157 /* create space for a hotplug element */ 14158 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14159 == NULL) { 14160 fcp_log(CE_WARN, NULL, 14161 "!can't allocate memory for hotplug element"); 14162 return (NULL); 14163 } 14164 14165 /* fill in hotplug element */ 14166 elem->port = pptr; 14167 elem->lun = plun; 14168 elem->cip = cip; 14169 elem->what = what; 14170 elem->flags = flags; 14171 elem->link_cnt = link_cnt; 14172 elem->tgt_cnt = tgt_cnt; 14173 elem->wait = wait; 14174 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14175 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14176 14177 /* schedule the hotplug task */ 14178 pdip = pptr->port_dip; 14179 mutex_enter(&plun->lun_mutex); 14180 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14181 plun->lun_event_count++; 14182 elem->event_cnt = plun->lun_event_count; 14183 } 14184 mutex_exit(&plun->lun_mutex); 14185 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14186 (void *)elem, KM_NOSLEEP) == NULL) { 14187 mutex_enter(&plun->lun_mutex); 14188 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) 14189 plun->lun_event_count--; 14190 mutex_exit(&plun->lun_mutex); 14191 kmem_free(elem, sizeof (*elem)); 14192 return (0); 14193 } 14194 14195 return (elem); 14196 } 14197 14198 14199 static void 14200 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14201 { 14202 int rval; 14203 struct scsi_address *ap; 14204 struct fcp_lun *plun; 14205 struct fcp_tgt *ptgt; 14206 fc_packet_t *fpkt; 14207 14208 ap = &cmd->cmd_pkt->pkt_address; 14209 plun = ADDR2LUN(ap); 14210 ptgt = plun->lun_tgt; 14211 14212 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14213 14214 cmd->cmd_state = FCP_PKT_IDLE; 14215 14216 mutex_enter(&pptr->port_mutex); 14217 mutex_enter(&ptgt->tgt_mutex); 14218 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14219 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14220 fc_ulp_rscn_info_t *rscnp; 14221 14222 cmd->cmd_state = FCP_PKT_ISSUED; 14223 14224 /* 14225 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14226 * originally NULL, hence we try to set it to the pd pointed 14227 * to by the SCSI device we're trying to get to. 14228 */ 14229 14230 fpkt = cmd->cmd_fp_pkt; 14231 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14232 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14233 /* 14234 * We need to notify the transport that we now have a 14235 * reference to the remote port handle. 14236 */ 14237 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14238 } 14239 14240 mutex_exit(&ptgt->tgt_mutex); 14241 mutex_exit(&pptr->port_mutex); 14242 14243 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14244 14245 /* prepare the packet */ 14246 14247 fcp_prepare_pkt(pptr, cmd, plun); 14248 14249 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14250 pkt_ulp_rscn_infop; 14251 14252 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14253 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14254 14255 if (rscnp != NULL) { 14256 rscnp->ulp_rscn_count = 14257 fc_ulp_get_rscn_count(pptr-> 14258 port_fp_handle); 14259 } 14260 14261 rval = fcp_transport(pptr->port_fp_handle, 14262 cmd->cmd_fp_pkt, 0); 14263 14264 if (rval == FC_SUCCESS) { 14265 return; 14266 } 14267 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14268 } else { 14269 mutex_exit(&ptgt->tgt_mutex); 14270 mutex_exit(&pptr->port_mutex); 14271 } 14272 14273 fcp_queue_pkt(pptr, cmd); 14274 } 14275 14276 14277 static void 14278 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14279 { 14280 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14281 14282 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14283 cmd->cmd_state = FCP_PKT_IDLE; 14284 14285 cmd->cmd_pkt->pkt_reason = reason; 14286 cmd->cmd_pkt->pkt_state = 0; 14287 cmd->cmd_pkt->pkt_statistics = statistics; 14288 14289 fcp_post_callback(cmd); 14290 } 14291 14292 /* 14293 * Function: fcp_queue_pkt 14294 * 14295 * Description: This function queues the packet passed by the caller into 14296 * the list of packets of the FCP port. 14297 * 14298 * Argument: *pptr FCP port. 14299 * *cmd FCP packet to queue. 14300 * 14301 * Return Value: None 14302 * 14303 * Context: User, Kernel and Interrupt context. 14304 */ 14305 static void 14306 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14307 { 14308 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14309 14310 mutex_enter(&pptr->port_pkt_mutex); 14311 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14312 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14313 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14314 14315 /* 14316 * zero pkt_time means hang around for ever 14317 */ 14318 if (cmd->cmd_pkt->pkt_time) { 14319 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14320 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14321 } else { 14322 /* 14323 * Indicate the watch thread to fail the 14324 * command by setting it to highest value 14325 */ 14326 cmd->cmd_timeout = fcp_watchdog_time; 14327 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14328 } 14329 } 14330 14331 if (pptr->port_pkt_head) { 14332 ASSERT(pptr->port_pkt_tail != NULL); 14333 14334 pptr->port_pkt_tail->cmd_next = cmd; 14335 pptr->port_pkt_tail = cmd; 14336 } else { 14337 ASSERT(pptr->port_pkt_tail == NULL); 14338 14339 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14340 } 14341 cmd->cmd_next = NULL; 14342 mutex_exit(&pptr->port_pkt_mutex); 14343 } 14344 14345 /* 14346 * Function: fcp_update_targets 14347 * 14348 * Description: This function applies the specified change of state to all 14349 * the targets listed. The operation applied is 'set'. 14350 * 14351 * Argument: *pptr FCP port. 14352 * *dev_list Array of fc_portmap_t structures. 14353 * count Length of dev_list. 14354 * state State bits to update. 14355 * cause Reason for the update. 14356 * 14357 * Return Value: None 14358 * 14359 * Context: User, Kernel and Interrupt context. 14360 * The mutex pptr->port_mutex must be held. 14361 */ 14362 static void 14363 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14364 uint32_t count, uint32_t state, int cause) 14365 { 14366 fc_portmap_t *map_entry; 14367 struct fcp_tgt *ptgt; 14368 14369 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14370 14371 while (count--) { 14372 map_entry = &(dev_list[count]); 14373 ptgt = fcp_lookup_target(pptr, 14374 (uchar_t *)&(map_entry->map_pwwn)); 14375 if (ptgt == NULL) { 14376 continue; 14377 } 14378 14379 mutex_enter(&ptgt->tgt_mutex); 14380 ptgt->tgt_trace = 0; 14381 ptgt->tgt_change_cnt++; 14382 ptgt->tgt_statec_cause = cause; 14383 ptgt->tgt_tmp_cnt = 1; 14384 fcp_update_tgt_state(ptgt, FCP_SET, state); 14385 mutex_exit(&ptgt->tgt_mutex); 14386 } 14387 } 14388 14389 static int 14390 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14391 int lcount, int tcount, int cause) 14392 { 14393 int rval; 14394 14395 mutex_enter(&pptr->port_mutex); 14396 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14397 mutex_exit(&pptr->port_mutex); 14398 14399 return (rval); 14400 } 14401 14402 14403 static int 14404 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14405 int lcount, int tcount, int cause) 14406 { 14407 int finish_init = 0; 14408 int finish_tgt = 0; 14409 int do_finish_init = 0; 14410 int rval = FCP_NO_CHANGE; 14411 14412 if (cause == FCP_CAUSE_LINK_CHANGE || 14413 cause == FCP_CAUSE_LINK_DOWN) { 14414 do_finish_init = 1; 14415 } 14416 14417 if (ptgt != NULL) { 14418 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14419 FCP_BUF_LEVEL_2, 0, 14420 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14421 " cause = %d, d_id = 0x%x, tgt_done = %d", 14422 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14423 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14424 ptgt->tgt_d_id, ptgt->tgt_done); 14425 14426 mutex_enter(&ptgt->tgt_mutex); 14427 14428 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14429 rval = FCP_DEV_CHANGE; 14430 if (do_finish_init && ptgt->tgt_done == 0) { 14431 ptgt->tgt_done++; 14432 finish_init = 1; 14433 } 14434 } else { 14435 if (--ptgt->tgt_tmp_cnt <= 0) { 14436 ptgt->tgt_tmp_cnt = 0; 14437 finish_tgt = 1; 14438 14439 if (do_finish_init) { 14440 finish_init = 1; 14441 } 14442 } 14443 } 14444 mutex_exit(&ptgt->tgt_mutex); 14445 } else { 14446 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14447 FCP_BUF_LEVEL_2, 0, 14448 "Call Finish Init for NO target"); 14449 14450 if (do_finish_init) { 14451 finish_init = 1; 14452 } 14453 } 14454 14455 if (finish_tgt) { 14456 ASSERT(ptgt != NULL); 14457 14458 mutex_enter(&ptgt->tgt_mutex); 14459 #ifdef DEBUG 14460 bzero(ptgt->tgt_tmp_cnt_stack, 14461 sizeof (ptgt->tgt_tmp_cnt_stack)); 14462 14463 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14464 FCP_STACK_DEPTH); 14465 #endif /* DEBUG */ 14466 mutex_exit(&ptgt->tgt_mutex); 14467 14468 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14469 } 14470 14471 if (finish_init && lcount == pptr->port_link_cnt) { 14472 ASSERT(pptr->port_tmp_cnt > 0); 14473 if (--pptr->port_tmp_cnt == 0) { 14474 fcp_finish_init(pptr); 14475 } 14476 } else if (lcount != pptr->port_link_cnt) { 14477 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14478 fcp_trace, FCP_BUF_LEVEL_2, 0, 14479 "fcp_call_finish_init_held,1: state change occured" 14480 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14481 } 14482 14483 return (rval); 14484 } 14485 14486 14487 static void 14488 fcp_reconfigure_luns(void * tgt_handle) 14489 { 14490 uint32_t dev_cnt; 14491 fc_portmap_t *devlist; 14492 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14493 struct fcp_port *pptr = ptgt->tgt_port; 14494 14495 /* 14496 * If the timer that fires this off got canceled too late, the 14497 * target could have been destroyed. 14498 */ 14499 14500 if (ptgt->tgt_tid == NULL) { 14501 return; 14502 } 14503 14504 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14505 if (devlist == NULL) { 14506 fcp_log(CE_WARN, pptr->port_dip, 14507 "!fcp%d: failed to allocate for portmap", 14508 pptr->port_instance); 14509 return; 14510 } 14511 14512 dev_cnt = 1; 14513 devlist->map_pd = ptgt->tgt_pd_handle; 14514 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14515 devlist->map_did.port_id = ptgt->tgt_d_id; 14516 14517 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14518 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14519 14520 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14521 devlist->map_type = PORT_DEVICE_NEW; 14522 devlist->map_flags = 0; 14523 14524 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14525 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14526 14527 /* 14528 * Clear the tgt_tid after no more references to 14529 * the fcp_tgt 14530 */ 14531 mutex_enter(&ptgt->tgt_mutex); 14532 ptgt->tgt_tid = NULL; 14533 mutex_exit(&ptgt->tgt_mutex); 14534 14535 kmem_free(devlist, sizeof (*devlist)); 14536 } 14537 14538 14539 static void 14540 fcp_free_targets(struct fcp_port *pptr) 14541 { 14542 int i; 14543 struct fcp_tgt *ptgt; 14544 14545 mutex_enter(&pptr->port_mutex); 14546 for (i = 0; i < FCP_NUM_HASH; i++) { 14547 ptgt = pptr->port_tgt_hash_table[i]; 14548 while (ptgt != NULL) { 14549 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14550 14551 fcp_free_target(ptgt); 14552 ptgt = next_tgt; 14553 } 14554 } 14555 mutex_exit(&pptr->port_mutex); 14556 } 14557 14558 14559 static void 14560 fcp_free_target(struct fcp_tgt *ptgt) 14561 { 14562 struct fcp_lun *plun; 14563 timeout_id_t tid; 14564 14565 mutex_enter(&ptgt->tgt_mutex); 14566 tid = ptgt->tgt_tid; 14567 14568 /* 14569 * Cancel any pending timeouts for this target. 14570 */ 14571 14572 if (tid != NULL) { 14573 /* 14574 * Set tgt_tid to NULL first to avoid a race in the callback. 14575 * If tgt_tid is NULL, the callback will simply return. 14576 */ 14577 ptgt->tgt_tid = NULL; 14578 mutex_exit(&ptgt->tgt_mutex); 14579 (void) untimeout(tid); 14580 mutex_enter(&ptgt->tgt_mutex); 14581 } 14582 14583 plun = ptgt->tgt_lun; 14584 while (plun != NULL) { 14585 struct fcp_lun *next_lun = plun->lun_next; 14586 14587 fcp_dealloc_lun(plun); 14588 plun = next_lun; 14589 } 14590 14591 mutex_exit(&ptgt->tgt_mutex); 14592 fcp_dealloc_tgt(ptgt); 14593 } 14594 14595 /* 14596 * Function: fcp_is_retryable 14597 * 14598 * Description: Indicates if the internal packet is retryable. 14599 * 14600 * Argument: *icmd FCP internal packet. 14601 * 14602 * Return Value: 0 Not retryable 14603 * 1 Retryable 14604 * 14605 * Context: User, Kernel and Interrupt context 14606 */ 14607 static int 14608 fcp_is_retryable(struct fcp_ipkt *icmd) 14609 { 14610 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14611 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) 14612 return (0); 14613 14614 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14615 icmd->ipkt_port->port_deadline) ? 1 : 0); 14616 } 14617 14618 /* 14619 * Function: fcp_create_on_demand 14620 * 14621 * Argument: *pptr FCP port. 14622 * *pwwn Port WWN. 14623 * 14624 * Return Value: 0 Success 14625 * EIO 14626 * ENOMEM 14627 * EBUSY 14628 * EINVAL 14629 * 14630 * Context: User and Kernel context 14631 */ 14632 static int 14633 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14634 { 14635 int wait_ms; 14636 int tcount; 14637 int lcount; 14638 int ret; 14639 int error; 14640 int rval = EIO; 14641 int ntries; 14642 fc_portmap_t *devlist; 14643 opaque_t pd; 14644 struct fcp_lun *plun; 14645 struct fcp_tgt *ptgt; 14646 int old_manual = 0; 14647 14648 /* Allocates the fc_portmap_t structure. */ 14649 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14650 14651 /* 14652 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14653 * in the commented statement below: 14654 * 14655 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14656 * 14657 * Below, the deadline for the discovery process is set. 14658 */ 14659 mutex_enter(&pptr->port_mutex); 14660 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14661 mutex_exit(&pptr->port_mutex); 14662 14663 /* 14664 * We try to find the remote port based on the WWN provided by the 14665 * caller. We actually ask fp/fctl if it has it. 14666 */ 14667 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14668 (la_wwn_t *)pwwn, &error, 1); 14669 14670 if (pd == NULL) { 14671 kmem_free(devlist, sizeof (*devlist)); 14672 return (rval); 14673 } 14674 14675 /* 14676 * The remote port was found. We ask fp/fctl to update our 14677 * fc_portmap_t structure. 14678 */ 14679 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14680 (la_wwn_t *)pwwn, devlist); 14681 if (ret != FC_SUCCESS) { 14682 kmem_free(devlist, sizeof (*devlist)); 14683 return (rval); 14684 } 14685 14686 /* 14687 * The map flag field is set to indicates that the creation is being 14688 * done at the user request (Ioclt probably luxadm or cfgadm). 14689 */ 14690 devlist->map_type = PORT_DEVICE_USER_CREATE; 14691 14692 mutex_enter(&pptr->port_mutex); 14693 14694 /* 14695 * We check to see if fcp already has a target that describes the 14696 * device being created. If not it is created. 14697 */ 14698 ptgt = fcp_lookup_target(pptr, pwwn); 14699 if (ptgt == NULL) { 14700 lcount = pptr->port_link_cnt; 14701 mutex_exit(&pptr->port_mutex); 14702 14703 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14704 if (ptgt == NULL) { 14705 fcp_log(CE_WARN, pptr->port_dip, 14706 "!FC target allocation failed"); 14707 return (ENOMEM); 14708 } 14709 14710 mutex_enter(&pptr->port_mutex); 14711 } 14712 14713 mutex_enter(&ptgt->tgt_mutex); 14714 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14715 ptgt->tgt_tmp_cnt = 1; 14716 ptgt->tgt_device_created = 0; 14717 /* 14718 * If fabric and auto config is set but the target was 14719 * manually unconfigured then reset to the manual_config_only to 14720 * 0 so the device will get configured. 14721 */ 14722 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14723 fcp_enable_auto_configuration && 14724 ptgt->tgt_manual_config_only == 1) { 14725 old_manual = 1; 14726 ptgt->tgt_manual_config_only = 0; 14727 } 14728 mutex_exit(&ptgt->tgt_mutex); 14729 14730 fcp_update_targets(pptr, devlist, 1, 14731 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14732 14733 lcount = pptr->port_link_cnt; 14734 tcount = ptgt->tgt_change_cnt; 14735 14736 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14737 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14738 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14739 fcp_enable_auto_configuration && old_manual) { 14740 mutex_enter(&ptgt->tgt_mutex); 14741 ptgt->tgt_manual_config_only = 1; 14742 mutex_exit(&ptgt->tgt_mutex); 14743 } 14744 14745 if (pptr->port_link_cnt != lcount || 14746 ptgt->tgt_change_cnt != tcount) { 14747 rval = EBUSY; 14748 } 14749 mutex_exit(&pptr->port_mutex); 14750 14751 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14752 FCP_BUF_LEVEL_3, 0, 14753 "fcp_create_on_demand: mapflags ptgt=%x, " 14754 "lcount=%x::port_link_cnt=%x, " 14755 "tcount=%x: tgt_change_cnt=%x, rval=%x", 14756 ptgt, lcount, pptr->port_link_cnt, 14757 tcount, ptgt->tgt_change_cnt, rval); 14758 return (rval); 14759 } 14760 14761 /* 14762 * Due to lack of synchronization mechanisms, we perform 14763 * periodic monitoring of our request; Because requests 14764 * get dropped when another one supercedes (either because 14765 * of a link change or a target change), it is difficult to 14766 * provide a clean synchronization mechanism (such as a 14767 * semaphore or a conditional variable) without exhaustively 14768 * rewriting the mainline discovery code of this driver. 14769 */ 14770 wait_ms = 500; 14771 14772 ntries = fcp_max_target_retries; 14773 14774 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14775 FCP_BUF_LEVEL_3, 0, 14776 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 14777 "lcount=%x::port_link_cnt=%x, " 14778 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14779 "tgt_tmp_cnt =%x", 14780 ntries, ptgt, lcount, pptr->port_link_cnt, 14781 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14782 ptgt->tgt_tmp_cnt); 14783 14784 mutex_enter(&ptgt->tgt_mutex); 14785 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 14786 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 14787 mutex_exit(&ptgt->tgt_mutex); 14788 mutex_exit(&pptr->port_mutex); 14789 14790 delay(drv_usectohz(wait_ms * 1000)); 14791 14792 mutex_enter(&pptr->port_mutex); 14793 mutex_enter(&ptgt->tgt_mutex); 14794 } 14795 14796 14797 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 14798 rval = EBUSY; 14799 } else { 14800 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 14801 FCP_TGT_NODE_PRESENT) { 14802 rval = 0; 14803 } 14804 } 14805 14806 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14807 FCP_BUF_LEVEL_3, 0, 14808 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 14809 "lcount=%x::port_link_cnt=%x, " 14810 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14811 "tgt_tmp_cnt =%x", 14812 ntries, ptgt, lcount, pptr->port_link_cnt, 14813 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14814 ptgt->tgt_tmp_cnt); 14815 14816 if (rval) { 14817 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14818 fcp_enable_auto_configuration && old_manual) { 14819 ptgt->tgt_manual_config_only = 1; 14820 } 14821 mutex_exit(&ptgt->tgt_mutex); 14822 mutex_exit(&pptr->port_mutex); 14823 kmem_free(devlist, sizeof (*devlist)); 14824 14825 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14826 FCP_BUF_LEVEL_3, 0, 14827 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 14828 "lcount=%x::port_link_cnt=%x, " 14829 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 14830 "tgt_device_created=%x, tgt D_ID=%x", 14831 ntries, ptgt, lcount, pptr->port_link_cnt, 14832 tcount, ptgt->tgt_change_cnt, rval, 14833 ptgt->tgt_device_created, ptgt->tgt_d_id); 14834 return (rval); 14835 } 14836 14837 if ((plun = ptgt->tgt_lun) != NULL) { 14838 tcount = plun->lun_tgt->tgt_change_cnt; 14839 } else { 14840 rval = EINVAL; 14841 } 14842 lcount = pptr->port_link_cnt; 14843 14844 /* 14845 * Configuring the target with no LUNs will fail. We 14846 * should reset the node state so that it is not 14847 * automatically configured when the LUNs are added 14848 * to this target. 14849 */ 14850 if (ptgt->tgt_lun_cnt == 0) { 14851 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 14852 } 14853 mutex_exit(&ptgt->tgt_mutex); 14854 mutex_exit(&pptr->port_mutex); 14855 14856 while (plun) { 14857 child_info_t *cip; 14858 14859 mutex_enter(&plun->lun_mutex); 14860 cip = plun->lun_cip; 14861 mutex_exit(&plun->lun_mutex); 14862 14863 mutex_enter(&ptgt->tgt_mutex); 14864 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 14865 mutex_exit(&ptgt->tgt_mutex); 14866 14867 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 14868 FCP_ONLINE, lcount, tcount, 14869 NDI_ONLINE_ATTACH); 14870 if (rval != NDI_SUCCESS) { 14871 FCP_TRACE(fcp_logq, 14872 pptr->port_instbuf, fcp_trace, 14873 FCP_BUF_LEVEL_3, 0, 14874 "fcp_create_on_demand: " 14875 "pass_to_hp_and_wait failed " 14876 "rval=%x", rval); 14877 rval = EIO; 14878 } else { 14879 mutex_enter(&LUN_TGT->tgt_mutex); 14880 plun->lun_state &= ~(FCP_LUN_OFFLINE | 14881 FCP_LUN_BUSY); 14882 mutex_exit(&LUN_TGT->tgt_mutex); 14883 } 14884 mutex_enter(&ptgt->tgt_mutex); 14885 } 14886 14887 plun = plun->lun_next; 14888 mutex_exit(&ptgt->tgt_mutex); 14889 } 14890 14891 kmem_free(devlist, sizeof (*devlist)); 14892 14893 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14894 fcp_enable_auto_configuration && old_manual) { 14895 mutex_enter(&ptgt->tgt_mutex); 14896 /* if successful then set manual to 0 */ 14897 if (rval == 0) { 14898 ptgt->tgt_manual_config_only = 0; 14899 } else { 14900 /* reset to 1 so the user has to do the config */ 14901 ptgt->tgt_manual_config_only = 1; 14902 } 14903 mutex_exit(&ptgt->tgt_mutex); 14904 } 14905 14906 return (rval); 14907 } 14908 14909 14910 static void 14911 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 14912 { 14913 int count; 14914 uchar_t byte; 14915 14916 count = 0; 14917 while (*string) { 14918 byte = FCP_ATOB(*string); string++; 14919 byte = byte << 4 | FCP_ATOB(*string); string++; 14920 bytes[count++] = byte; 14921 14922 if (count >= byte_len) { 14923 break; 14924 } 14925 } 14926 } 14927 14928 static void 14929 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 14930 { 14931 int i; 14932 14933 for (i = 0; i < FC_WWN_SIZE; i++) { 14934 (void) sprintf(string + (i * 2), 14935 "%02x", wwn[i]); 14936 } 14937 14938 } 14939 14940 static void 14941 fcp_print_error(fc_packet_t *fpkt) 14942 { 14943 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 14944 fpkt->pkt_ulp_private; 14945 struct fcp_port *pptr; 14946 struct fcp_tgt *ptgt; 14947 struct fcp_lun *plun; 14948 caddr_t buf; 14949 int scsi_cmd = 0; 14950 14951 ptgt = icmd->ipkt_tgt; 14952 plun = icmd->ipkt_lun; 14953 pptr = ptgt->tgt_port; 14954 14955 buf = kmem_zalloc(256, KM_NOSLEEP); 14956 if (buf == NULL) { 14957 return; 14958 } 14959 14960 switch (icmd->ipkt_opcode) { 14961 case SCMD_REPORT_LUN: 14962 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 14963 " lun=0x%%x failed"); 14964 scsi_cmd++; 14965 break; 14966 14967 case SCMD_INQUIRY_PAGE83: 14968 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 14969 " lun=0x%%x failed"); 14970 scsi_cmd++; 14971 break; 14972 14973 case SCMD_INQUIRY: 14974 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 14975 " lun=0x%%x failed"); 14976 scsi_cmd++; 14977 break; 14978 14979 case LA_ELS_PLOGI: 14980 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 14981 break; 14982 14983 case LA_ELS_PRLI: 14984 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 14985 break; 14986 } 14987 14988 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 14989 struct fcp_rsp response, *rsp; 14990 uchar_t asc, ascq; 14991 caddr_t sense_key = NULL; 14992 struct fcp_rsp_info fcp_rsp_err, *bep; 14993 14994 if (icmd->ipkt_nodma) { 14995 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 14996 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 14997 sizeof (struct fcp_rsp)); 14998 } else { 14999 rsp = &response; 15000 bep = &fcp_rsp_err; 15001 15002 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15003 sizeof (struct fcp_rsp)); 15004 15005 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15006 bep, fpkt->pkt_resp_acc, 15007 sizeof (struct fcp_rsp_info)); 15008 } 15009 15010 15011 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15012 (void) sprintf(buf + strlen(buf), 15013 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15014 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15015 " senselen=%%x. Giving up"); 15016 15017 fcp_log(CE_WARN, pptr->port_dip, buf, 15018 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15019 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15020 rsp->fcp_u.fcp_status.reserved_1, 15021 rsp->fcp_response_len, rsp->fcp_sense_len); 15022 15023 kmem_free(buf, 256); 15024 return; 15025 } 15026 15027 if (rsp->fcp_u.fcp_status.rsp_len_set && 15028 bep->rsp_code != FCP_NO_FAILURE) { 15029 (void) sprintf(buf + strlen(buf), 15030 " FCP Response code = 0x%x", bep->rsp_code); 15031 } 15032 15033 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15034 struct scsi_extended_sense sense_info, *sense_ptr; 15035 15036 if (icmd->ipkt_nodma) { 15037 sense_ptr = (struct scsi_extended_sense *) 15038 ((caddr_t)fpkt->pkt_resp + 15039 sizeof (struct fcp_rsp) + 15040 rsp->fcp_response_len); 15041 } else { 15042 sense_ptr = &sense_info; 15043 15044 FCP_CP_IN(fpkt->pkt_resp + 15045 sizeof (struct fcp_rsp) + 15046 rsp->fcp_response_len, &sense_info, 15047 fpkt->pkt_resp_acc, 15048 sizeof (struct scsi_extended_sense)); 15049 } 15050 15051 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15052 NUM_IMPL_SENSE_KEYS) { 15053 sense_key = sense_keys[sense_ptr->es_key]; 15054 } else { 15055 sense_key = "Undefined"; 15056 } 15057 15058 asc = sense_ptr->es_add_code; 15059 ascq = sense_ptr->es_qual_code; 15060 15061 (void) sprintf(buf + strlen(buf), 15062 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15063 " Giving up"); 15064 15065 fcp_log(CE_WARN, pptr->port_dip, buf, 15066 ptgt->tgt_d_id, plun->lun_num, sense_key, 15067 asc, ascq); 15068 } else { 15069 (void) sprintf(buf + strlen(buf), 15070 " : SCSI status=%%x. Giving up"); 15071 15072 fcp_log(CE_WARN, pptr->port_dip, buf, 15073 ptgt->tgt_d_id, plun->lun_num, 15074 rsp->fcp_u.fcp_status.scsi_status); 15075 } 15076 } else { 15077 caddr_t state, reason, action, expln; 15078 15079 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15080 &action, &expln); 15081 15082 (void) sprintf(buf + strlen(buf), ": State:%%s," 15083 " Reason:%%s. Giving up"); 15084 15085 if (scsi_cmd) { 15086 fcp_log(CE_WARN, pptr->port_dip, buf, 15087 ptgt->tgt_d_id, plun->lun_num, state, reason); 15088 } else { 15089 fcp_log(CE_WARN, pptr->port_dip, buf, 15090 ptgt->tgt_d_id, state, reason); 15091 } 15092 } 15093 15094 kmem_free(buf, 256); 15095 } 15096 15097 15098 static int 15099 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15100 struct fcp_ipkt *icmd, int rval, caddr_t op) 15101 { 15102 int ret = DDI_FAILURE; 15103 char *error; 15104 15105 switch (rval) { 15106 case FC_DEVICE_BUSY_NEW_RSCN: 15107 /* 15108 * This means that there was a new RSCN that the transport 15109 * knows about (which the ULP *may* know about too) but the 15110 * pkt that was sent down was related to an older RSCN. So, we 15111 * are just going to reset the retry count and deadline and 15112 * continue to retry. The idea is that transport is currently 15113 * working on the new RSCN and will soon let the ULPs know 15114 * about it and when it does the existing logic will kick in 15115 * where it will change the tcount to indicate that something 15116 * changed on the target. So, rediscovery will start and there 15117 * will not be an infinite retry. 15118 * 15119 * For a full flow of how the RSCN info is transferred back and 15120 * forth, see fp.c 15121 */ 15122 icmd->ipkt_retries = 0; 15123 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15124 FCP_ICMD_DEADLINE; 15125 15126 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15127 FCP_BUF_LEVEL_3, 0, 15128 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15129 rval, ptgt->tgt_d_id); 15130 /* FALLTHROUGH */ 15131 15132 case FC_STATEC_BUSY: 15133 case FC_DEVICE_BUSY: 15134 case FC_PBUSY: 15135 case FC_FBUSY: 15136 case FC_TRAN_BUSY: 15137 case FC_OFFLINE: 15138 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15139 FCP_BUF_LEVEL_3, 0, 15140 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15141 rval, ptgt->tgt_d_id); 15142 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15143 fcp_is_retryable(icmd)) { 15144 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15145 ret = DDI_SUCCESS; 15146 } 15147 break; 15148 15149 case FC_LOGINREQ: 15150 /* 15151 * FC_LOGINREQ used to be handled just like all the cases 15152 * above. It has been changed to handled a PRLI that fails 15153 * with FC_LOGINREQ different than other ipkts that fail 15154 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15155 * a simple matter to turn it into a PLOGI instead, so that's 15156 * exactly what we do here. 15157 */ 15158 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15159 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15160 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15161 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15162 } else { 15163 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15164 FCP_BUF_LEVEL_3, 0, 15165 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15166 rval, ptgt->tgt_d_id); 15167 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15168 fcp_is_retryable(icmd)) { 15169 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15170 ret = DDI_SUCCESS; 15171 } 15172 } 15173 break; 15174 15175 default: 15176 mutex_enter(&pptr->port_mutex); 15177 mutex_enter(&ptgt->tgt_mutex); 15178 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15179 mutex_exit(&ptgt->tgt_mutex); 15180 mutex_exit(&pptr->port_mutex); 15181 15182 (void) fc_ulp_error(rval, &error); 15183 fcp_log(CE_WARN, pptr->port_dip, 15184 "!Failed to send %s to D_ID=%x error=%s", 15185 op, ptgt->tgt_d_id, error); 15186 } else { 15187 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15188 fcp_trace, FCP_BUF_LEVEL_2, 0, 15189 "fcp_handle_ipkt_errors,1: state change occured" 15190 " for D_ID=0x%x", ptgt->tgt_d_id); 15191 mutex_exit(&ptgt->tgt_mutex); 15192 mutex_exit(&pptr->port_mutex); 15193 } 15194 break; 15195 } 15196 15197 return (ret); 15198 } 15199 15200 15201 /* 15202 * Check of outstanding commands on any LUN for this target 15203 */ 15204 static int 15205 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15206 { 15207 struct fcp_lun *plun; 15208 struct fcp_pkt *cmd; 15209 15210 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15211 mutex_enter(&plun->lun_mutex); 15212 for (cmd = plun->lun_pkt_head; cmd != NULL; 15213 cmd = cmd->cmd_forw) { 15214 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15215 mutex_exit(&plun->lun_mutex); 15216 return (FC_SUCCESS); 15217 } 15218 } 15219 mutex_exit(&plun->lun_mutex); 15220 } 15221 15222 return (FC_FAILURE); 15223 } 15224 15225 static fc_portmap_t * 15226 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15227 { 15228 int i; 15229 fc_portmap_t *devlist; 15230 fc_portmap_t *devptr = NULL; 15231 struct fcp_tgt *ptgt; 15232 15233 mutex_enter(&pptr->port_mutex); 15234 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15235 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15236 ptgt = ptgt->tgt_next) { 15237 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15238 ++*dev_cnt; 15239 } 15240 } 15241 } 15242 15243 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15244 KM_NOSLEEP); 15245 if (devlist == NULL) { 15246 mutex_exit(&pptr->port_mutex); 15247 fcp_log(CE_WARN, pptr->port_dip, 15248 "!fcp%d: failed to allocate for portmap for construct map", 15249 pptr->port_instance); 15250 return (devptr); 15251 } 15252 15253 for (i = 0; i < FCP_NUM_HASH; i++) { 15254 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15255 ptgt = ptgt->tgt_next) { 15256 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15257 int ret; 15258 15259 ret = fc_ulp_pwwn_to_portmap( 15260 pptr->port_fp_handle, 15261 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15262 devlist); 15263 15264 if (ret == FC_SUCCESS) { 15265 devlist++; 15266 continue; 15267 } 15268 15269 devlist->map_pd = NULL; 15270 devlist->map_did.port_id = ptgt->tgt_d_id; 15271 devlist->map_hard_addr.hard_addr = 15272 ptgt->tgt_hard_addr; 15273 15274 devlist->map_state = PORT_DEVICE_INVALID; 15275 devlist->map_type = PORT_DEVICE_OLD; 15276 15277 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15278 &devlist->map_nwwn, FC_WWN_SIZE); 15279 15280 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15281 &devlist->map_pwwn, FC_WWN_SIZE); 15282 15283 devlist++; 15284 } 15285 } 15286 } 15287 15288 mutex_exit(&pptr->port_mutex); 15289 15290 return (devptr); 15291 } 15292 /* 15293 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15294 */ 15295 static void 15296 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15297 { 15298 int i; 15299 struct fcp_tgt *ptgt; 15300 struct fcp_lun *plun; 15301 15302 for (i = 0; i < FCP_NUM_HASH; i++) { 15303 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15304 ptgt = ptgt->tgt_next) { 15305 mutex_enter(&ptgt->tgt_mutex); 15306 for (plun = ptgt->tgt_lun; plun != NULL; 15307 plun = plun->lun_next) { 15308 if (plun->lun_mpxio && 15309 plun->lun_state & FCP_LUN_BUSY) { 15310 if (!fcp_pass_to_hp(pptr, plun, 15311 plun->lun_cip, 15312 FCP_MPXIO_PATH_SET_BUSY, 15313 pptr->port_link_cnt, 15314 ptgt->tgt_change_cnt, 0, 0)) { 15315 FCP_TRACE(fcp_logq, 15316 pptr->port_instbuf, 15317 fcp_trace, 15318 FCP_BUF_LEVEL_2, 0, 15319 "path_verifybusy: " 15320 "disable lun %p failed!", 15321 plun); 15322 } 15323 } 15324 } 15325 mutex_exit(&ptgt->tgt_mutex); 15326 } 15327 } 15328 } 15329 15330 static int 15331 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15332 { 15333 dev_info_t *cdip = NULL; 15334 dev_info_t *pdip = NULL; 15335 15336 ASSERT(plun); 15337 15338 mutex_enter(&plun->lun_mutex); 15339 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15340 mutex_exit(&plun->lun_mutex); 15341 return (NDI_FAILURE); 15342 } 15343 mutex_exit(&plun->lun_mutex); 15344 cdip = mdi_pi_get_client(PIP(cip)); 15345 pdip = mdi_pi_get_phci(PIP(cip)); 15346 15347 ASSERT(cdip != NULL); 15348 ASSERT(pdip != NULL); 15349 15350 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15351 /* LUN ready for IO */ 15352 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15353 } else { 15354 /* LUN busy to accept IO */ 15355 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15356 } 15357 return (NDI_SUCCESS); 15358 } 15359 15360 /* 15361 * Caller must free the returned string of MAXPATHLEN len 15362 * If the device is offline (-1 instance number) NULL 15363 * will be returned. 15364 */ 15365 static char * 15366 fcp_get_lun_path(struct fcp_lun *plun) { 15367 dev_info_t *dip = NULL; 15368 char *path = NULL; 15369 if (plun == NULL) { 15370 return (NULL); 15371 } 15372 if (plun->lun_mpxio == 0) { 15373 dip = DIP(plun->lun_cip); 15374 } else { 15375 dip = mdi_pi_get_client(PIP(plun->lun_cip)); 15376 } 15377 if (dip == NULL) { 15378 return (NULL); 15379 } 15380 if (ddi_get_instance(dip) < 0) { 15381 return (NULL); 15382 } 15383 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15384 if (path == NULL) { 15385 return (NULL); 15386 } 15387 15388 (void) ddi_pathname(dip, path); 15389 /* 15390 * In reality, the user wants a fully valid path (one they can open) 15391 * but this string is lacking the mount point, and the minor node. 15392 * It would be nice if we could "figure these out" somehow 15393 * and fill them in. Otherwise, the userland code has to understand 15394 * driver specific details of which minor node is the "best" or 15395 * "right" one to expose. (Ex: which slice is the whole disk, or 15396 * which tape doesn't rewind) 15397 */ 15398 return (path); 15399 } 15400 15401 static int 15402 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15403 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15404 { 15405 int64_t reset_delay; 15406 int rval, retry = 0; 15407 struct fcp_port *pptr = fcp_dip2port(parent); 15408 15409 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15410 (lbolt64 - pptr->port_attach_time); 15411 if (reset_delay < 0) 15412 reset_delay = 0; 15413 15414 if (fcp_bus_config_debug) 15415 flag |= NDI_DEVI_DEBUG; 15416 15417 switch (op) { 15418 case BUS_CONFIG_ONE: 15419 /* 15420 * Retry the command since we need to ensure 15421 * the fabric devices are available for root 15422 */ 15423 while (retry++ < fcp_max_bus_config_retries) { 15424 rval = (ndi_busop_bus_config(parent, 15425 flag | NDI_MDI_FALLBACK, op, 15426 arg, childp, (clock_t)reset_delay)); 15427 if (rval == 0) 15428 return (rval); 15429 } 15430 15431 /* 15432 * drain taskq to make sure nodes are created and then 15433 * try again. 15434 */ 15435 taskq_wait(DEVI(parent)->devi_taskq); 15436 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15437 op, arg, childp, 0)); 15438 15439 case BUS_CONFIG_DRIVER: 15440 case BUS_CONFIG_ALL: { 15441 /* 15442 * delay till all devices report in (port_tmp_cnt == 0) 15443 * or FCP_INIT_WAIT_TIMEOUT 15444 */ 15445 mutex_enter(&pptr->port_mutex); 15446 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15447 (void) cv_timedwait(&pptr->port_config_cv, 15448 &pptr->port_mutex, 15449 ddi_get_lbolt() + (clock_t)reset_delay); 15450 reset_delay = 15451 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15452 (lbolt64 - pptr->port_attach_time); 15453 } 15454 mutex_exit(&pptr->port_mutex); 15455 /* drain taskq to make sure nodes are created */ 15456 taskq_wait(DEVI(parent)->devi_taskq); 15457 return (ndi_busop_bus_config(parent, flag, op, 15458 arg, childp, 0)); 15459 } 15460 15461 default: 15462 return (NDI_FAILURE); 15463 } 15464 /*NOTREACHED*/ 15465 } 15466 15467 static int 15468 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15469 ddi_bus_config_op_t op, void *arg) 15470 { 15471 if (fcp_bus_config_debug) 15472 flag |= NDI_DEVI_DEBUG; 15473 15474 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15475 } 15476 15477 15478 /* 15479 * Routine to copy GUID into the lun structure. 15480 * returns 0 if copy was successful and 1 if encountered a 15481 * failure and did not copy the guid. 15482 */ 15483 static int 15484 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15485 { 15486 15487 int retval = 0; 15488 15489 /* add one for the null terminator */ 15490 const unsigned int len = strlen(guidp) + 1; 15491 15492 if ((guidp == NULL) || (plun == NULL)) { 15493 return (1); 15494 } 15495 15496 /* 15497 * if the plun->lun_guid already has been allocated, 15498 * then check the size. if the size is exact, reuse 15499 * it....if not free it an allocate the required size. 15500 * The reallocation should NOT typically happen 15501 * unless the GUIDs reported changes between passes. 15502 * We free up and alloc again even if the 15503 * size was more than required. This is due to the 15504 * fact that the field lun_guid_size - serves 15505 * dual role of indicating the size of the wwn 15506 * size and ALSO the allocation size. 15507 */ 15508 if (plun->lun_guid) { 15509 if (plun->lun_guid_size != len) { 15510 /* 15511 * free the allocated memory and 15512 * initialize the field 15513 * lun_guid_size to 0. 15514 */ 15515 kmem_free(plun->lun_guid, plun->lun_guid_size); 15516 plun->lun_guid = NULL; 15517 plun->lun_guid_size = 0; 15518 } 15519 } 15520 /* 15521 * alloc only if not already done. 15522 */ 15523 if (plun->lun_guid == NULL) { 15524 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15525 if (plun->lun_guid == NULL) { 15526 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15527 "Unable to allocate" 15528 "Memory for GUID!!! size %d", len); 15529 retval = 1; 15530 } else { 15531 plun->lun_guid_size = len; 15532 } 15533 } 15534 if (plun->lun_guid) { 15535 /* 15536 * now copy the GUID 15537 */ 15538 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15539 } 15540 return (retval); 15541 } 15542 15543 /* 15544 * fcp_reconfig_wait 15545 * 15546 * Wait for a rediscovery/reconfiguration to complete before continuing. 15547 */ 15548 15549 static void 15550 fcp_reconfig_wait(struct fcp_port *pptr) 15551 { 15552 clock_t reconfig_start, wait_timeout; 15553 15554 /* 15555 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15556 * reconfiguration in progress. 15557 */ 15558 15559 mutex_enter(&pptr->port_mutex); 15560 if (pptr->port_tmp_cnt == 0) { 15561 mutex_exit(&pptr->port_mutex); 15562 return; 15563 } 15564 mutex_exit(&pptr->port_mutex); 15565 15566 /* 15567 * If we cause a reconfig by raising power, delay until all devices 15568 * report in (port_tmp_cnt returns to 0) 15569 */ 15570 15571 reconfig_start = ddi_get_lbolt(); 15572 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15573 15574 mutex_enter(&pptr->port_mutex); 15575 15576 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15577 pptr->port_tmp_cnt) { 15578 15579 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15580 reconfig_start + wait_timeout); 15581 } 15582 15583 mutex_exit(&pptr->port_mutex); 15584 15585 /* 15586 * Even if fcp_tmp_count isn't 0, continue without error. The port 15587 * we want may still be ok. If not, it will error out later 15588 */ 15589 } 15590 15591 /* 15592 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15593 * We rely on the fcp_global_mutex to provide protection against changes to 15594 * the fcp_lun_blacklist. 15595 * 15596 * You can describe a list of target port WWNs and LUN numbers which will 15597 * not be configured. LUN numbers will be interpreted as decimal. White 15598 * spaces and ',' can be used in the list of LUN numbers. 15599 * 15600 * To prevent LUNs 1 and 2 from being configured for target 15601 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15602 * 15603 * pwwn-lun-blacklist= 15604 * "510000f010fd92a1,1,2", 15605 * "510000e012079df1,1,2"; 15606 */ 15607 static void 15608 fcp_read_blacklist(dev_info_t *dip, 15609 struct fcp_black_list_entry **pplun_blacklist) { 15610 char **prop_array = NULL; 15611 char *curr_pwwn = NULL; 15612 char *curr_lun = NULL; 15613 uint32_t prop_item = 0; 15614 int idx = 0; 15615 int len = 0; 15616 15617 ASSERT(mutex_owned(&fcp_global_mutex)); 15618 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15619 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15620 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15621 return; 15622 } 15623 15624 for (idx = 0; idx < prop_item; idx++) { 15625 15626 curr_pwwn = prop_array[idx]; 15627 while (*curr_pwwn == ' ') { 15628 curr_pwwn++; 15629 } 15630 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15631 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15632 ", please check.", curr_pwwn); 15633 continue; 15634 } 15635 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15636 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15637 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15638 ", please check.", curr_pwwn); 15639 continue; 15640 } 15641 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15642 if (isxdigit(curr_pwwn[len]) != TRUE) { 15643 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15644 "blacklist, please check.", curr_pwwn); 15645 break; 15646 } 15647 } 15648 if (len != sizeof (la_wwn_t) * 2) { 15649 continue; 15650 } 15651 15652 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15653 *(curr_lun - 1) = '\0'; 15654 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15655 } 15656 15657 ddi_prop_free(prop_array); 15658 } 15659 15660 /* 15661 * Get the masking info about one remote target port designated by wwn. 15662 * Lun ids could be separated by ',' or white spaces. 15663 */ 15664 static void 15665 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15666 struct fcp_black_list_entry **pplun_blacklist) { 15667 int idx = 0; 15668 uint32_t offset = 0; 15669 unsigned long lun_id = 0; 15670 char lunid_buf[16]; 15671 char *pend = NULL; 15672 int illegal_digit = 0; 15673 15674 while (offset < strlen(curr_lun)) { 15675 while ((curr_lun[offset + idx] != ',') && 15676 (curr_lun[offset + idx] != '\0') && 15677 (curr_lun[offset + idx] != ' ')) { 15678 if (isdigit(curr_lun[offset + idx]) == 0) { 15679 illegal_digit++; 15680 } 15681 idx++; 15682 } 15683 if (illegal_digit > 0) { 15684 offset += (idx+1); /* To the start of next lun */ 15685 idx = 0; 15686 illegal_digit = 0; 15687 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15688 "the blacklist, please check digits.", 15689 curr_lun, curr_pwwn); 15690 continue; 15691 } 15692 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15693 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15694 "the blacklist, please check the length of LUN#.", 15695 curr_lun, curr_pwwn); 15696 break; 15697 } 15698 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15699 offset++; 15700 continue; 15701 } 15702 15703 bcopy(curr_lun + offset, lunid_buf, idx); 15704 lunid_buf[idx] = '\0'; 15705 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15706 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15707 } else { 15708 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15709 "the blacklist, please check %s.", 15710 curr_lun, curr_pwwn, lunid_buf); 15711 } 15712 offset += (idx+1); /* To the start of next lun */ 15713 idx = 0; 15714 } 15715 } 15716 15717 /* 15718 * Add one masking record 15719 */ 15720 static void 15721 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 15722 struct fcp_black_list_entry **pplun_blacklist) { 15723 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15724 struct fcp_black_list_entry *new_entry = NULL; 15725 la_wwn_t wwn; 15726 15727 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 15728 while (tmp_entry) { 15729 if ((bcmp(&tmp_entry->wwn, &wwn, 15730 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 15731 return; 15732 } 15733 15734 tmp_entry = tmp_entry->next; 15735 } 15736 15737 /* add to black list */ 15738 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 15739 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 15740 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 15741 new_entry->lun = lun_id; 15742 new_entry->masked = 0; 15743 new_entry->next = *pplun_blacklist; 15744 *pplun_blacklist = new_entry; 15745 } 15746 15747 /* 15748 * Check if we should mask the specified lun of this fcp_tgt 15749 */ 15750 static int 15751 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 15752 struct fcp_black_list_entry *remote_port; 15753 15754 remote_port = fcp_lun_blacklist; 15755 while (remote_port != NULL) { 15756 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 15757 if (remote_port->lun == lun_id) { 15758 remote_port->masked++; 15759 if (remote_port->masked == 1) { 15760 fcp_log(CE_NOTE, NULL, "LUN %d of port " 15761 "%02x%02x%02x%02x%02x%02x%02x%02x is masked due to black listing.\n", 15762 lun_id, wwn->raw_wwn[0], wwn->raw_wwn[1], wwn->raw_wwn[2], 15763 wwn->raw_wwn[3], wwn->raw_wwn[4], wwn->raw_wwn[5], wwn->raw_wwn[6], 15764 wwn->raw_wwn[7]); 15765 } 15766 return (TRUE); 15767 } 15768 } 15769 remote_port = remote_port->next; 15770 } 15771 return (FALSE); 15772 } 15773 15774 /* 15775 * Release all allocated resources 15776 */ 15777 static void 15778 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 15779 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15780 struct fcp_black_list_entry *current_entry = NULL; 15781 15782 ASSERT(mutex_owned(&fcp_global_mutex)); 15783 /* 15784 * Traverse all luns 15785 */ 15786 while (tmp_entry) { 15787 current_entry = tmp_entry; 15788 tmp_entry = tmp_entry->next; 15789 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 15790 } 15791 *pplun_blacklist = NULL; 15792 } 15793