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 & FCP_LUN_CAP_RESET) != 0) ? 11717 TRUE : FALSE; 11718 break; 11719 11720 default: 11721 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11722 fcp_trace, FCP_BUF_LEVEL_4, 0, 11723 "fcp_getcap: unsupported %d", cidx); 11724 rval = UNDEFINED; 11725 break; 11726 } 11727 11728 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11729 fcp_trace, FCP_BUF_LEVEL_8, 0, 11730 "get cap: cap=%s, val/tgtonly/doset/rval = " 11731 "0x%x/0x%x/0x%x/%d", 11732 cap, val, tgtonly, doset, rval); 11733 } 11734 11735 return (rval); 11736 } 11737 11738 /* 11739 * called by the transport to get the port-wwn and lun 11740 * properties of this device, and to create a "name" based on them 11741 * 11742 * these properties don't exist on sun4m 11743 * 11744 * return 1 for success else return 0 11745 */ 11746 /* ARGSUSED */ 11747 static int 11748 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11749 { 11750 int i; 11751 int *lun; 11752 int numChars; 11753 uint_t nlun; 11754 uint_t count; 11755 uint_t nbytes; 11756 uchar_t *bytes; 11757 uint16_t lun_num; 11758 uint32_t tgt_id; 11759 char **conf_wwn; 11760 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11761 uchar_t barray[FC_WWN_SIZE]; 11762 dev_info_t *tgt_dip; 11763 struct fcp_tgt *ptgt; 11764 struct fcp_port *pptr; 11765 struct fcp_lun *plun; 11766 11767 ASSERT(sd != NULL); 11768 ASSERT(name != NULL); 11769 11770 tgt_dip = sd->sd_dev; 11771 pptr = ddi_get_soft_state(fcp_softstate, 11772 ddi_get_instance(ddi_get_parent(tgt_dip))); 11773 if (pptr == NULL) { 11774 return (0); 11775 } 11776 11777 ASSERT(tgt_dip != NULL); 11778 11779 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11780 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11781 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11782 name[0] = '\0'; 11783 return (0); 11784 } 11785 11786 if (nlun == 0) { 11787 ddi_prop_free(lun); 11788 return (0); 11789 } 11790 11791 lun_num = lun[0]; 11792 ddi_prop_free(lun); 11793 11794 /* 11795 * Lookup for .conf WWN property 11796 */ 11797 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11798 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11799 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11800 ASSERT(count >= 1); 11801 11802 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11803 ddi_prop_free(conf_wwn); 11804 mutex_enter(&pptr->port_mutex); 11805 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11806 mutex_exit(&pptr->port_mutex); 11807 return (0); 11808 } 11809 ptgt = plun->lun_tgt; 11810 mutex_exit(&pptr->port_mutex); 11811 11812 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11813 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11814 11815 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11816 ptgt->tgt_hard_addr != 0) { 11817 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11818 ptgt->tgt_hard_addr]; 11819 } else { 11820 tgt_id = ptgt->tgt_d_id; 11821 } 11822 11823 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11824 TARGET_PROP, tgt_id); 11825 } 11826 11827 /* get the our port-wwn property */ 11828 bytes = NULL; 11829 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 11830 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 11831 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 11832 if (bytes != NULL) { 11833 ddi_prop_free(bytes); 11834 } 11835 return (0); 11836 } 11837 11838 for (i = 0; i < FC_WWN_SIZE; i++) { 11839 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 11840 } 11841 11842 /* Stick in the address of the form "wWWN,LUN" */ 11843 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 11844 11845 ASSERT(numChars < len); 11846 if (numChars >= len) { 11847 fcp_log(CE_WARN, pptr->port_dip, 11848 "!fcp_scsi_get_name: " 11849 "name parameter length too small, it needs to be %d", 11850 numChars+1); 11851 } 11852 11853 ddi_prop_free(bytes); 11854 11855 return (1); 11856 } 11857 11858 11859 /* 11860 * called by the transport to get the SCSI target id value, returning 11861 * it in "name" 11862 * 11863 * this isn't needed/used on sun4m 11864 * 11865 * return 1 for success else return 0 11866 */ 11867 /* ARGSUSED */ 11868 static int 11869 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 11870 { 11871 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 11872 struct fcp_tgt *ptgt; 11873 int numChars; 11874 11875 if (plun == NULL) { 11876 return (0); 11877 } 11878 11879 if ((ptgt = plun->lun_tgt) == NULL) { 11880 return (0); 11881 } 11882 11883 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 11884 11885 ASSERT(numChars < len); 11886 if (numChars >= len) { 11887 fcp_log(CE_WARN, NULL, 11888 "!fcp_scsi_get_bus_addr: " 11889 "name parameter length too small, it needs to be %d", 11890 numChars+1); 11891 } 11892 11893 return (1); 11894 } 11895 11896 11897 /* 11898 * called internally to reset the link where the specified port lives 11899 */ 11900 static int 11901 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 11902 { 11903 la_wwn_t wwn; 11904 struct fcp_lun *plun; 11905 struct fcp_tgt *ptgt; 11906 11907 /* disable restart of lip if we're suspended */ 11908 mutex_enter(&pptr->port_mutex); 11909 11910 if (pptr->port_state & (FCP_STATE_SUSPENDED | 11911 FCP_STATE_POWER_DOWN)) { 11912 mutex_exit(&pptr->port_mutex); 11913 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11914 fcp_trace, FCP_BUF_LEVEL_2, 0, 11915 "fcp_linkreset, fcp%d: link reset " 11916 "disabled due to DDI_SUSPEND", 11917 ddi_get_instance(pptr->port_dip)); 11918 return (FC_FAILURE); 11919 } 11920 11921 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 11922 mutex_exit(&pptr->port_mutex); 11923 return (FC_SUCCESS); 11924 } 11925 11926 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11927 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 11928 11929 /* 11930 * If ap == NULL assume local link reset. 11931 */ 11932 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 11933 plun = ADDR2LUN(ap); 11934 ptgt = plun->lun_tgt; 11935 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 11936 } else { 11937 bzero((caddr_t)&wwn, sizeof (wwn)); 11938 } 11939 mutex_exit(&pptr->port_mutex); 11940 11941 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 11942 } 11943 11944 11945 /* 11946 * called from fcp_port_attach() to resume a port 11947 * return DDI_* success/failure status 11948 * acquires and releases the global mutex 11949 * acquires and releases the port mutex 11950 */ 11951 /*ARGSUSED*/ 11952 11953 static int 11954 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 11955 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 11956 { 11957 int res = DDI_FAILURE; /* default result */ 11958 struct fcp_port *pptr; /* port state ptr */ 11959 uint32_t alloc_cnt; 11960 uint32_t max_cnt; 11961 fc_portmap_t *tmp_list = NULL; 11962 11963 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 11964 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 11965 instance); 11966 11967 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 11968 cmn_err(CE_WARN, "fcp: bad soft state"); 11969 return (res); 11970 } 11971 11972 mutex_enter(&pptr->port_mutex); 11973 switch (cmd) { 11974 case FC_CMD_RESUME: 11975 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 11976 pptr->port_state &= ~FCP_STATE_SUSPENDED; 11977 break; 11978 11979 case FC_CMD_POWER_UP: 11980 /* 11981 * If the port is DDI_SUSPENded, defer rediscovery 11982 * until DDI_RESUME occurs 11983 */ 11984 if (pptr->port_state & FCP_STATE_SUSPENDED) { 11985 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 11986 mutex_exit(&pptr->port_mutex); 11987 return (DDI_SUCCESS); 11988 } 11989 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 11990 } 11991 pptr->port_id = s_id; 11992 pptr->port_state = FCP_STATE_INIT; 11993 mutex_exit(&pptr->port_mutex); 11994 11995 /* 11996 * Make a copy of ulp_port_info as fctl allocates 11997 * a temp struct. 11998 */ 11999 (void) fcp_cp_pinfo(pptr, pinfo); 12000 12001 mutex_enter(&fcp_global_mutex); 12002 if (fcp_watchdog_init++ == 0) { 12003 fcp_watchdog_tick = fcp_watchdog_timeout * 12004 drv_usectohz(1000000); 12005 fcp_watchdog_id = timeout(fcp_watch, 12006 NULL, fcp_watchdog_tick); 12007 } 12008 mutex_exit(&fcp_global_mutex); 12009 12010 /* 12011 * Handle various topologies and link states. 12012 */ 12013 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12014 case FC_STATE_OFFLINE: 12015 /* 12016 * Wait for ONLINE, at which time a state 12017 * change will cause a statec_callback 12018 */ 12019 res = DDI_SUCCESS; 12020 break; 12021 12022 case FC_STATE_ONLINE: 12023 12024 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12025 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12026 res = DDI_SUCCESS; 12027 break; 12028 } 12029 12030 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12031 !fcp_enable_auto_configuration) { 12032 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12033 if (tmp_list == NULL) { 12034 if (!alloc_cnt) { 12035 res = DDI_SUCCESS; 12036 } 12037 break; 12038 } 12039 max_cnt = alloc_cnt; 12040 } else { 12041 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12042 12043 alloc_cnt = FCP_MAX_DEVICES; 12044 12045 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12046 (sizeof (fc_portmap_t)) * alloc_cnt, 12047 KM_NOSLEEP)) == NULL) { 12048 fcp_log(CE_WARN, pptr->port_dip, 12049 "!fcp%d: failed to allocate portmap", 12050 instance); 12051 break; 12052 } 12053 12054 max_cnt = alloc_cnt; 12055 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12056 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12057 FC_SUCCESS) { 12058 caddr_t msg; 12059 12060 (void) fc_ulp_error(res, &msg); 12061 12062 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12063 fcp_trace, FCP_BUF_LEVEL_2, 0, 12064 "resume failed getportmap: reason=0x%x", 12065 res); 12066 12067 fcp_log(CE_WARN, pptr->port_dip, 12068 "!failed to get port map : %s", msg); 12069 break; 12070 } 12071 if (max_cnt > alloc_cnt) { 12072 alloc_cnt = max_cnt; 12073 } 12074 } 12075 12076 /* 12077 * do the SCSI device discovery and create 12078 * the devinfos 12079 */ 12080 fcp_statec_callback(ulph, pptr->port_fp_handle, 12081 pptr->port_phys_state, pptr->port_topology, tmp_list, 12082 max_cnt, pptr->port_id); 12083 12084 res = DDI_SUCCESS; 12085 break; 12086 12087 default: 12088 fcp_log(CE_WARN, pptr->port_dip, 12089 "!fcp%d: invalid port state at attach=0x%x", 12090 instance, pptr->port_phys_state); 12091 12092 mutex_enter(&pptr->port_mutex); 12093 pptr->port_phys_state = FCP_STATE_OFFLINE; 12094 mutex_exit(&pptr->port_mutex); 12095 res = DDI_SUCCESS; 12096 12097 break; 12098 } 12099 12100 if (tmp_list != NULL) { 12101 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12102 } 12103 12104 return (res); 12105 } 12106 12107 12108 static void 12109 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12110 { 12111 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12112 pptr->port_dip = pinfo->port_dip; 12113 pptr->port_fp_handle = pinfo->port_handle; 12114 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12115 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12116 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12117 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12118 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12119 pptr->port_max_exch = pinfo->port_fca_max_exch; 12120 pptr->port_phys_state = pinfo->port_state; 12121 pptr->port_topology = pinfo->port_flags; 12122 pptr->port_reset_action = pinfo->port_reset_action; 12123 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12124 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12125 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12126 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12127 } 12128 12129 /* 12130 * If the elements wait field is set to 1 then 12131 * another thread is waiting for the operation to complete. Once 12132 * it is complete, the waiting thread is signaled and the element is 12133 * freed by the waiting thread. If the elements wait field is set to 0 12134 * the element is freed. 12135 */ 12136 static void 12137 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12138 { 12139 ASSERT(elem != NULL); 12140 mutex_enter(&elem->mutex); 12141 elem->result = result; 12142 if (elem->wait) { 12143 elem->wait = 0; 12144 cv_signal(&elem->cv); 12145 mutex_exit(&elem->mutex); 12146 } else { 12147 mutex_exit(&elem->mutex); 12148 cv_destroy(&elem->cv); 12149 mutex_destroy(&elem->mutex); 12150 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12151 } 12152 } 12153 12154 /* 12155 * This function is invoked from the taskq thread to allocate 12156 * devinfo nodes and to online/offline them. 12157 */ 12158 static void 12159 fcp_hp_task(void *arg) 12160 { 12161 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12162 struct fcp_lun *plun = elem->lun; 12163 struct fcp_port *pptr = elem->port; 12164 int result; 12165 12166 ASSERT(elem->what == FCP_ONLINE || 12167 elem->what == FCP_OFFLINE || 12168 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12169 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12170 12171 mutex_enter(&pptr->port_mutex); 12172 mutex_enter(&plun->lun_mutex); 12173 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12174 plun->lun_event_count != elem->event_cnt) || 12175 pptr->port_state & (FCP_STATE_SUSPENDED | 12176 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12177 mutex_exit(&plun->lun_mutex); 12178 mutex_exit(&pptr->port_mutex); 12179 fcp_process_elem(elem, NDI_FAILURE); 12180 return; 12181 } 12182 mutex_exit(&plun->lun_mutex); 12183 mutex_exit(&pptr->port_mutex); 12184 12185 result = fcp_trigger_lun(plun, elem->cip, elem->what, 12186 elem->link_cnt, elem->tgt_cnt, elem->flags); 12187 fcp_process_elem(elem, result); 12188 } 12189 12190 12191 static child_info_t * 12192 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12193 int tcount) 12194 { 12195 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12196 12197 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12198 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12199 12200 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12201 /* 12202 * Child has not been created yet. Create the child device 12203 * based on the per-Lun flags. 12204 */ 12205 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12206 plun->lun_cip = 12207 CIP(fcp_create_dip(plun, lcount, tcount)); 12208 plun->lun_mpxio = 0; 12209 } else { 12210 plun->lun_cip = 12211 CIP(fcp_create_pip(plun, lcount, tcount)); 12212 plun->lun_mpxio = 1; 12213 } 12214 } else { 12215 plun->lun_cip = cip; 12216 } 12217 12218 return (plun->lun_cip); 12219 } 12220 12221 12222 static int 12223 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12224 { 12225 int rval = FC_FAILURE; 12226 dev_info_t *pdip; 12227 struct dev_info *dip; 12228 int circular; 12229 12230 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12231 12232 pdip = plun->lun_tgt->tgt_port->port_dip; 12233 12234 if (plun->lun_cip == NULL) { 12235 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12236 fcp_trace, FCP_BUF_LEVEL_3, 0, 12237 "fcp_is_dip_present: plun->lun_cip is NULL: " 12238 "plun: %p lun state: %x num: %d target state: %x", 12239 plun, plun->lun_state, plun->lun_num, 12240 plun->lun_tgt->tgt_port->port_state); 12241 return (rval); 12242 } 12243 ndi_devi_enter(pdip, &circular); 12244 dip = DEVI(pdip)->devi_child; 12245 while (dip) { 12246 if (dip == DEVI(cdip)) { 12247 rval = FC_SUCCESS; 12248 break; 12249 } 12250 dip = dip->devi_sibling; 12251 } 12252 ndi_devi_exit(pdip, circular); 12253 return (rval); 12254 } 12255 12256 static int 12257 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12258 { 12259 int rval = FC_FAILURE; 12260 12261 ASSERT(plun != NULL); 12262 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12263 12264 if (plun->lun_mpxio == 0) { 12265 rval = fcp_is_dip_present(plun, DIP(cip)); 12266 } else { 12267 rval = fcp_is_pip_present(plun, PIP(cip)); 12268 } 12269 12270 return (rval); 12271 } 12272 12273 /* 12274 * Function: fcp_create_dip 12275 * 12276 * Description: Creates a dev_info_t structure for the LUN specified by the 12277 * caller. 12278 * 12279 * Argument: plun Lun structure 12280 * link_cnt Link state count. 12281 * tgt_cnt Target state change count. 12282 * 12283 * Return Value: NULL if it failed 12284 * dev_info_t structure address if it succeeded 12285 * 12286 * Context: Kernel context 12287 */ 12288 static dev_info_t * 12289 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12290 { 12291 int failure = 0; 12292 uint32_t tgt_id; 12293 uint64_t sam_lun; 12294 struct fcp_tgt *ptgt = plun->lun_tgt; 12295 struct fcp_port *pptr = ptgt->tgt_port; 12296 dev_info_t *pdip = pptr->port_dip; 12297 dev_info_t *cdip = NULL; 12298 dev_info_t *old_dip = DIP(plun->lun_cip); 12299 char *nname = NULL; 12300 char **compatible = NULL; 12301 int ncompatible; 12302 char *scsi_binding_set; 12303 char t_pwwn[17]; 12304 12305 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12306 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12307 12308 /* get the 'scsi-binding-set' property */ 12309 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12310 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12311 &scsi_binding_set) != DDI_PROP_SUCCESS) 12312 scsi_binding_set = NULL; 12313 12314 /* determine the node name and compatible */ 12315 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12316 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12317 if (scsi_binding_set) 12318 ddi_prop_free(scsi_binding_set); 12319 12320 if (nname == NULL) { 12321 #ifdef DEBUG 12322 cmn_err(CE_WARN, "%s%d: no driver for " 12323 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12324 " compatible: %s", 12325 ddi_driver_name(pdip), ddi_get_instance(pdip), 12326 ptgt->tgt_port_wwn.raw_wwn[0], 12327 ptgt->tgt_port_wwn.raw_wwn[1], 12328 ptgt->tgt_port_wwn.raw_wwn[2], 12329 ptgt->tgt_port_wwn.raw_wwn[3], 12330 ptgt->tgt_port_wwn.raw_wwn[4], 12331 ptgt->tgt_port_wwn.raw_wwn[5], 12332 ptgt->tgt_port_wwn.raw_wwn[6], 12333 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12334 *compatible); 12335 #endif /* DEBUG */ 12336 failure++; 12337 goto end_of_fcp_create_dip; 12338 } 12339 12340 cdip = fcp_find_existing_dip(plun, pdip, nname); 12341 12342 /* 12343 * if the old_dip does not match the cdip, that means there is 12344 * some property change. since we'll be using the cdip, we need 12345 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12346 * then the dtype for the device has been updated. Offline the 12347 * the old device and create a new device with the new device type 12348 * Refer to bug: 4764752 12349 */ 12350 if (old_dip && (cdip != old_dip || 12351 plun->lun_state & FCP_LUN_CHANGED)) { 12352 plun->lun_state &= ~(FCP_LUN_INIT); 12353 mutex_exit(&plun->lun_mutex); 12354 mutex_exit(&pptr->port_mutex); 12355 12356 mutex_enter(&ptgt->tgt_mutex); 12357 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12358 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12359 mutex_exit(&ptgt->tgt_mutex); 12360 12361 #ifdef DEBUG 12362 if (cdip != NULL) { 12363 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12364 fcp_trace, FCP_BUF_LEVEL_2, 0, 12365 "Old dip=%p; New dip=%p don't match", old_dip, 12366 cdip); 12367 } else { 12368 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12369 fcp_trace, FCP_BUF_LEVEL_2, 0, 12370 "Old dip=%p; New dip=NULL don't match", old_dip); 12371 } 12372 #endif 12373 12374 mutex_enter(&pptr->port_mutex); 12375 mutex_enter(&plun->lun_mutex); 12376 } 12377 12378 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12379 plun->lun_state &= ~(FCP_LUN_CHANGED); 12380 if (ndi_devi_alloc(pptr->port_dip, nname, 12381 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12382 failure++; 12383 goto end_of_fcp_create_dip; 12384 } 12385 } 12386 12387 /* 12388 * Previously all the properties for the devinfo were destroyed here 12389 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12390 * the devid property (and other properties established by the target 12391 * driver or framework) which the code does not always recreate, this 12392 * call was removed. 12393 * This opens a theoretical possibility that we may return with a 12394 * stale devid on the node if the scsi entity behind the fibre channel 12395 * lun has changed. 12396 */ 12397 12398 /* decorate the node with compatible */ 12399 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12400 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12401 failure++; 12402 goto end_of_fcp_create_dip; 12403 } 12404 12405 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12406 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12407 failure++; 12408 goto end_of_fcp_create_dip; 12409 } 12410 12411 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12412 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12413 failure++; 12414 goto end_of_fcp_create_dip; 12415 } 12416 12417 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12418 t_pwwn[16] = '\0'; 12419 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12420 != DDI_PROP_SUCCESS) { 12421 failure++; 12422 goto end_of_fcp_create_dip; 12423 } 12424 12425 /* 12426 * If there is no hard address - We might have to deal with 12427 * that by using WWN - Having said that it is important to 12428 * recognize this problem early so ssd can be informed of 12429 * the right interconnect type. 12430 */ 12431 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12432 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12433 } else { 12434 tgt_id = ptgt->tgt_d_id; 12435 } 12436 12437 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12438 tgt_id) != DDI_PROP_SUCCESS) { 12439 failure++; 12440 goto end_of_fcp_create_dip; 12441 } 12442 12443 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12444 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12445 failure++; 12446 goto end_of_fcp_create_dip; 12447 } 12448 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12449 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12450 sam_lun) != DDI_PROP_SUCCESS) { 12451 failure++; 12452 goto end_of_fcp_create_dip; 12453 } 12454 12455 end_of_fcp_create_dip: 12456 scsi_hba_nodename_compatible_free(nname, compatible); 12457 12458 if (cdip != NULL && failure) { 12459 (void) ndi_prop_remove_all(cdip); 12460 (void) ndi_devi_free(cdip); 12461 cdip = NULL; 12462 } 12463 12464 return (cdip); 12465 } 12466 12467 /* 12468 * Function: fcp_create_pip 12469 * 12470 * Description: Creates a Path Id for the LUN specified by the caller. 12471 * 12472 * Argument: plun Lun structure 12473 * link_cnt Link state count. 12474 * tgt_cnt Target state count. 12475 * 12476 * Return Value: NULL if it failed 12477 * mdi_pathinfo_t structure address if it succeeded 12478 * 12479 * Context: Kernel context 12480 */ 12481 static mdi_pathinfo_t * 12482 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12483 { 12484 int i; 12485 char buf[MAXNAMELEN]; 12486 char uaddr[MAXNAMELEN]; 12487 int failure = 0; 12488 uint32_t tgt_id; 12489 uint64_t sam_lun; 12490 struct fcp_tgt *ptgt = plun->lun_tgt; 12491 struct fcp_port *pptr = ptgt->tgt_port; 12492 dev_info_t *pdip = pptr->port_dip; 12493 mdi_pathinfo_t *pip = NULL; 12494 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12495 char *nname = NULL; 12496 char **compatible = NULL; 12497 int ncompatible; 12498 char *scsi_binding_set; 12499 char t_pwwn[17]; 12500 12501 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12502 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12503 12504 scsi_binding_set = "vhci"; 12505 12506 /* determine the node name and compatible */ 12507 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12508 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12509 12510 if (nname == NULL) { 12511 #ifdef DEBUG 12512 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12513 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12514 " compatible: %s", 12515 ddi_driver_name(pdip), ddi_get_instance(pdip), 12516 ptgt->tgt_port_wwn.raw_wwn[0], 12517 ptgt->tgt_port_wwn.raw_wwn[1], 12518 ptgt->tgt_port_wwn.raw_wwn[2], 12519 ptgt->tgt_port_wwn.raw_wwn[3], 12520 ptgt->tgt_port_wwn.raw_wwn[4], 12521 ptgt->tgt_port_wwn.raw_wwn[5], 12522 ptgt->tgt_port_wwn.raw_wwn[6], 12523 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12524 *compatible); 12525 #endif /* DEBUG */ 12526 failure++; 12527 goto end_of_fcp_create_pip; 12528 } 12529 12530 pip = fcp_find_existing_pip(plun, pdip); 12531 12532 /* 12533 * if the old_dip does not match the cdip, that means there is 12534 * some property change. since we'll be using the cdip, we need 12535 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12536 * then the dtype for the device has been updated. Offline the 12537 * the old device and create a new device with the new device type 12538 * Refer to bug: 4764752 12539 */ 12540 if (old_pip && (pip != old_pip || 12541 plun->lun_state & FCP_LUN_CHANGED)) { 12542 plun->lun_state &= ~(FCP_LUN_INIT); 12543 mutex_exit(&plun->lun_mutex); 12544 mutex_exit(&pptr->port_mutex); 12545 12546 mutex_enter(&ptgt->tgt_mutex); 12547 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12548 FCP_OFFLINE, lcount, tcount, 12549 NDI_DEVI_REMOVE, 0); 12550 mutex_exit(&ptgt->tgt_mutex); 12551 12552 if (pip != NULL) { 12553 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12554 fcp_trace, FCP_BUF_LEVEL_2, 0, 12555 "Old pip=%p; New pip=%p don't match", 12556 old_pip, pip); 12557 } else { 12558 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12559 fcp_trace, FCP_BUF_LEVEL_2, 0, 12560 "Old pip=%p; New pip=NULL don't match", 12561 old_pip); 12562 } 12563 12564 mutex_enter(&pptr->port_mutex); 12565 mutex_enter(&plun->lun_mutex); 12566 } 12567 12568 /* 12569 * Since FC_WWN_SIZE is 8 bytes and its not like the 12570 * lun_guid_size which is dependent on the target, I don't 12571 * believe the same trancation happens here UNLESS the standards 12572 * change the FC_WWN_SIZE value to something larger than 12573 * MAXNAMELEN(currently 255 bytes). 12574 */ 12575 12576 for (i = 0; i < FC_WWN_SIZE; i++) 12577 (void) sprintf(&buf[i << 1], "%02x", 12578 ptgt->tgt_port_wwn.raw_wwn[i]); 12579 12580 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12581 buf, plun->lun_num); 12582 12583 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12584 /* 12585 * Release the locks before calling into 12586 * mdi_pi_alloc_compatible() since this can result in a 12587 * callback into fcp which can result in a deadlock 12588 * (see bug # 4870272). 12589 * 12590 * Basically, what we are trying to avoid is the scenario where 12591 * one thread does ndi_devi_enter() and tries to grab 12592 * fcp_mutex and another does it the other way round. 12593 * 12594 * But before we do that, make sure that nobody releases the 12595 * port in the meantime. We can do this by setting a flag. 12596 */ 12597 plun->lun_state &= ~(FCP_LUN_CHANGED); 12598 pptr->port_state |= FCP_STATE_IN_MDI; 12599 mutex_exit(&plun->lun_mutex); 12600 mutex_exit(&pptr->port_mutex); 12601 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12602 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12603 fcp_log(CE_WARN, pptr->port_dip, 12604 "!path alloc failed:0x%x", plun); 12605 mutex_enter(&pptr->port_mutex); 12606 mutex_enter(&plun->lun_mutex); 12607 pptr->port_state &= ~FCP_STATE_IN_MDI; 12608 failure++; 12609 goto end_of_fcp_create_pip; 12610 } 12611 mutex_enter(&pptr->port_mutex); 12612 mutex_enter(&plun->lun_mutex); 12613 pptr->port_state &= ~FCP_STATE_IN_MDI; 12614 } else { 12615 (void) mdi_prop_remove(pip, NULL); 12616 } 12617 12618 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12619 12620 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12621 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12622 != DDI_PROP_SUCCESS) { 12623 failure++; 12624 goto end_of_fcp_create_pip; 12625 } 12626 12627 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12628 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12629 != DDI_PROP_SUCCESS) { 12630 failure++; 12631 goto end_of_fcp_create_pip; 12632 } 12633 12634 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12635 t_pwwn[16] = '\0'; 12636 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12637 != DDI_PROP_SUCCESS) { 12638 failure++; 12639 goto end_of_fcp_create_pip; 12640 } 12641 12642 /* 12643 * If there is no hard address - We might have to deal with 12644 * that by using WWN - Having said that it is important to 12645 * recognize this problem early so ssd can be informed of 12646 * the right interconnect type. 12647 */ 12648 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12649 ptgt->tgt_hard_addr != 0) { 12650 tgt_id = (uint32_t) 12651 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12652 } else { 12653 tgt_id = ptgt->tgt_d_id; 12654 } 12655 12656 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12657 != DDI_PROP_SUCCESS) { 12658 failure++; 12659 goto end_of_fcp_create_pip; 12660 } 12661 12662 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12663 != DDI_PROP_SUCCESS) { 12664 failure++; 12665 goto end_of_fcp_create_pip; 12666 } 12667 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12668 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12669 != DDI_PROP_SUCCESS) { 12670 failure++; 12671 goto end_of_fcp_create_pip; 12672 } 12673 12674 end_of_fcp_create_pip: 12675 scsi_hba_nodename_compatible_free(nname, compatible); 12676 12677 if (pip != NULL && failure) { 12678 (void) mdi_prop_remove(pip, NULL); 12679 mutex_exit(&plun->lun_mutex); 12680 mutex_exit(&pptr->port_mutex); 12681 (void) mdi_pi_free(pip, 0); 12682 mutex_enter(&pptr->port_mutex); 12683 mutex_enter(&plun->lun_mutex); 12684 pip = NULL; 12685 } 12686 12687 return (pip); 12688 } 12689 12690 static dev_info_t * 12691 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12692 { 12693 uint_t nbytes; 12694 uchar_t *bytes; 12695 uint_t nwords; 12696 uint32_t tgt_id; 12697 int *words; 12698 dev_info_t *cdip; 12699 dev_info_t *ndip; 12700 struct fcp_tgt *ptgt = plun->lun_tgt; 12701 struct fcp_port *pptr = ptgt->tgt_port; 12702 int circular; 12703 12704 ndi_devi_enter(pdip, &circular); 12705 12706 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12707 while ((cdip = ndip) != NULL) { 12708 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12709 12710 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12711 continue; 12712 } 12713 12714 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12715 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12716 &nbytes) != DDI_PROP_SUCCESS) { 12717 continue; 12718 } 12719 12720 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12721 if (bytes != NULL) { 12722 ddi_prop_free(bytes); 12723 } 12724 continue; 12725 } 12726 ASSERT(bytes != NULL); 12727 12728 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12729 ddi_prop_free(bytes); 12730 continue; 12731 } 12732 12733 ddi_prop_free(bytes); 12734 12735 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12736 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12737 &nbytes) != DDI_PROP_SUCCESS) { 12738 continue; 12739 } 12740 12741 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12742 if (bytes != NULL) { 12743 ddi_prop_free(bytes); 12744 } 12745 continue; 12746 } 12747 ASSERT(bytes != NULL); 12748 12749 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12750 ddi_prop_free(bytes); 12751 continue; 12752 } 12753 12754 ddi_prop_free(bytes); 12755 12756 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12757 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12758 &nwords) != DDI_PROP_SUCCESS) { 12759 continue; 12760 } 12761 12762 if (nwords != 1 || words == NULL) { 12763 if (words != NULL) { 12764 ddi_prop_free(words); 12765 } 12766 continue; 12767 } 12768 ASSERT(words != NULL); 12769 12770 /* 12771 * If there is no hard address - We might have to deal with 12772 * that by using WWN - Having said that it is important to 12773 * recognize this problem early so ssd can be informed of 12774 * the right interconnect type. 12775 */ 12776 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12777 ptgt->tgt_hard_addr != 0) { 12778 tgt_id = 12779 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12780 } else { 12781 tgt_id = ptgt->tgt_d_id; 12782 } 12783 12784 if (tgt_id != (uint32_t)*words) { 12785 ddi_prop_free(words); 12786 continue; 12787 } 12788 ddi_prop_free(words); 12789 12790 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12791 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12792 &nwords) != DDI_PROP_SUCCESS) { 12793 continue; 12794 } 12795 12796 if (nwords != 1 || words == NULL) { 12797 if (words != NULL) { 12798 ddi_prop_free(words); 12799 } 12800 continue; 12801 } 12802 ASSERT(words != NULL); 12803 12804 if (plun->lun_num == (uint16_t)*words) { 12805 ddi_prop_free(words); 12806 break; 12807 } 12808 ddi_prop_free(words); 12809 } 12810 ndi_devi_exit(pdip, circular); 12811 12812 return (cdip); 12813 } 12814 12815 12816 static int 12817 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 12818 { 12819 dev_info_t *pdip; 12820 char buf[MAXNAMELEN]; 12821 char uaddr[MAXNAMELEN]; 12822 int rval = FC_FAILURE; 12823 12824 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12825 12826 pdip = plun->lun_tgt->tgt_port->port_dip; 12827 12828 /* 12829 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 12830 * non-NULL even when the LUN is not there as in the case when a LUN is 12831 * configured and then deleted on the device end (for T3/T4 case). In 12832 * such cases, pip will be NULL. 12833 * 12834 * If the device generates an RSCN, it will end up getting offlined when 12835 * it disappeared and a new LUN will get created when it is rediscovered 12836 * on the device. If we check for lun_cip here, the LUN will not end 12837 * up getting onlined since this function will end up returning a 12838 * FC_SUCCESS. 12839 * 12840 * The behavior is different on other devices. For instance, on a HDS, 12841 * there was no RSCN generated by the device but the next I/O generated 12842 * a check condition and rediscovery got triggered that way. So, in 12843 * such cases, this path will not be exercised 12844 */ 12845 if (pip == NULL) { 12846 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12847 fcp_trace, FCP_BUF_LEVEL_4, 0, 12848 "fcp_is_pip_present: plun->lun_cip is NULL: " 12849 "plun: %p lun state: %x num: %d target state: %x", 12850 plun, plun->lun_state, plun->lun_num, 12851 plun->lun_tgt->tgt_port->port_state); 12852 return (rval); 12853 } 12854 12855 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 12856 12857 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12858 12859 if (plun->lun_old_guid) { 12860 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 12861 rval = FC_SUCCESS; 12862 } 12863 } else { 12864 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 12865 rval = FC_SUCCESS; 12866 } 12867 } 12868 return (rval); 12869 } 12870 12871 static mdi_pathinfo_t * 12872 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 12873 { 12874 char buf[MAXNAMELEN]; 12875 char uaddr[MAXNAMELEN]; 12876 mdi_pathinfo_t *pip; 12877 struct fcp_tgt *ptgt = plun->lun_tgt; 12878 struct fcp_port *pptr = ptgt->tgt_port; 12879 12880 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12881 12882 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 12883 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12884 12885 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 12886 12887 return (pip); 12888 } 12889 12890 12891 static int 12892 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 12893 int tcount, int flags, int *circ) 12894 { 12895 int rval; 12896 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12897 struct fcp_tgt *ptgt = plun->lun_tgt; 12898 dev_info_t *cdip = NULL; 12899 12900 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12901 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12902 12903 if (plun->lun_cip == NULL) { 12904 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12905 fcp_trace, FCP_BUF_LEVEL_3, 0, 12906 "fcp_online_child: plun->lun_cip is NULL: " 12907 "plun: %p state: %x num: %d target state: %x", 12908 plun, plun->lun_state, plun->lun_num, 12909 plun->lun_tgt->tgt_port->port_state); 12910 return (NDI_FAILURE); 12911 } 12912 again: 12913 if (plun->lun_mpxio == 0) { 12914 cdip = DIP(cip); 12915 mutex_exit(&plun->lun_mutex); 12916 mutex_exit(&pptr->port_mutex); 12917 12918 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12919 fcp_trace, FCP_BUF_LEVEL_3, 0, 12920 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 12921 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 12922 12923 /* 12924 * We could check for FCP_LUN_INIT here but chances 12925 * of getting here when it's already in FCP_LUN_INIT 12926 * is rare and a duplicate ndi_devi_online wouldn't 12927 * hurt either (as the node would already have been 12928 * in CF2) 12929 */ 12930 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) 12931 rval = ndi_devi_bind_driver(cdip, flags); 12932 else 12933 rval = ndi_devi_online(cdip, flags); 12934 /* 12935 * We log the message into trace buffer if the device 12936 * is "ses" and into syslog for any other device 12937 * type. This is to prevent the ndi_devi_online failure 12938 * message that appears for V880/A5K ses devices. 12939 */ 12940 if (rval == NDI_SUCCESS) { 12941 mutex_enter(&ptgt->tgt_mutex); 12942 plun->lun_state |= FCP_LUN_INIT; 12943 mutex_exit(&ptgt->tgt_mutex); 12944 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 12945 fcp_log(CE_NOTE, pptr->port_dip, 12946 "!ndi_devi_online:" 12947 " failed for %s: target=%x lun=%x %x", 12948 ddi_get_name(cdip), ptgt->tgt_d_id, 12949 plun->lun_num, rval); 12950 } else { 12951 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12952 fcp_trace, FCP_BUF_LEVEL_3, 0, 12953 " !ndi_devi_online:" 12954 " failed for %s: target=%x lun=%x %x", 12955 ddi_get_name(cdip), ptgt->tgt_d_id, 12956 plun->lun_num, rval); 12957 } 12958 } else { 12959 cdip = mdi_pi_get_client(PIP(cip)); 12960 mutex_exit(&plun->lun_mutex); 12961 mutex_exit(&pptr->port_mutex); 12962 12963 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12964 fcp_trace, FCP_BUF_LEVEL_3, 0, 12965 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 12966 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 12967 12968 /* 12969 * Hold path and exit phci to avoid deadlock with power 12970 * management code during mdi_pi_online. 12971 */ 12972 mdi_hold_path(PIP(cip)); 12973 mdi_devi_exit_phci(pptr->port_dip, *circ); 12974 12975 rval = mdi_pi_online(PIP(cip), flags); 12976 12977 mdi_devi_enter_phci(pptr->port_dip, circ); 12978 mdi_rele_path(PIP(cip)); 12979 12980 if (rval == MDI_SUCCESS) { 12981 mutex_enter(&ptgt->tgt_mutex); 12982 plun->lun_state |= FCP_LUN_INIT; 12983 mutex_exit(&ptgt->tgt_mutex); 12984 12985 /* 12986 * Clear MPxIO path permanent disable in case 12987 * fcp hotplug dropped the offline event. 12988 */ 12989 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 12990 12991 } else if (rval == MDI_NOT_SUPPORTED) { 12992 child_info_t *old_cip = cip; 12993 12994 /* 12995 * MPxIO does not support this device yet. 12996 * Enumerate in legacy mode. 12997 */ 12998 mutex_enter(&pptr->port_mutex); 12999 mutex_enter(&plun->lun_mutex); 13000 plun->lun_mpxio = 0; 13001 plun->lun_cip = NULL; 13002 cdip = fcp_create_dip(plun, lcount, tcount); 13003 plun->lun_cip = cip = CIP(cdip); 13004 if (cip == NULL) { 13005 fcp_log(CE_WARN, pptr->port_dip, 13006 "!fcp_online_child: " 13007 "Create devinfo failed for LU=%p", plun); 13008 mutex_exit(&plun->lun_mutex); 13009 13010 mutex_enter(&ptgt->tgt_mutex); 13011 plun->lun_state |= FCP_LUN_OFFLINE; 13012 mutex_exit(&ptgt->tgt_mutex); 13013 13014 mutex_exit(&pptr->port_mutex); 13015 13016 /* 13017 * free the mdi_pathinfo node 13018 */ 13019 (void) mdi_pi_free(PIP(old_cip), 0); 13020 } else { 13021 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13022 fcp_trace, FCP_BUF_LEVEL_3, 0, 13023 "fcp_online_child: creating devinfo " 13024 "node 0x%p for plun 0x%p", 13025 cip, plun); 13026 mutex_exit(&plun->lun_mutex); 13027 mutex_exit(&pptr->port_mutex); 13028 /* 13029 * free the mdi_pathinfo node 13030 */ 13031 (void) mdi_pi_free(PIP(old_cip), 0); 13032 mutex_enter(&pptr->port_mutex); 13033 mutex_enter(&plun->lun_mutex); 13034 goto again; 13035 } 13036 } else { 13037 if (cdip) { 13038 fcp_log(CE_NOTE, pptr->port_dip, 13039 "!fcp_online_child: mdi_pi_online:" 13040 " failed for %s: target=%x lun=%x %x", 13041 ddi_get_name(cdip), ptgt->tgt_d_id, 13042 plun->lun_num, rval); 13043 } 13044 } 13045 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13046 } 13047 13048 if (rval == NDI_SUCCESS) { 13049 if (cdip) { 13050 (void) ndi_event_retrieve_cookie( 13051 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13052 &fcp_insert_eid, NDI_EVENT_NOPASS); 13053 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13054 cdip, fcp_insert_eid, NULL); 13055 } 13056 } 13057 mutex_enter(&pptr->port_mutex); 13058 mutex_enter(&plun->lun_mutex); 13059 return (rval); 13060 } 13061 13062 /* ARGSUSED */ 13063 static int 13064 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13065 int tcount, int flags, int *circ) 13066 { 13067 int rval; 13068 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13069 struct fcp_tgt *ptgt = plun->lun_tgt; 13070 dev_info_t *cdip; 13071 13072 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13073 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13074 13075 if (plun->lun_cip == NULL) { 13076 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13077 fcp_trace, FCP_BUF_LEVEL_3, 0, 13078 "fcp_offline_child: plun->lun_cip is NULL: " 13079 "plun: %p lun state: %x num: %d target state: %x", 13080 plun, plun->lun_state, plun->lun_num, 13081 plun->lun_tgt->tgt_port->port_state); 13082 return (NDI_FAILURE); 13083 } 13084 13085 if (plun->lun_mpxio == 0) { 13086 cdip = DIP(cip); 13087 mutex_exit(&plun->lun_mutex); 13088 mutex_exit(&pptr->port_mutex); 13089 rval = ndi_devi_offline(DIP(cip), flags); 13090 if (rval != NDI_SUCCESS) { 13091 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13092 fcp_trace, FCP_BUF_LEVEL_3, 0, 13093 "fcp_offline_child: ndi_devi_offline failed " 13094 "rval=%x cip=%p", rval, cip); 13095 } 13096 } else { 13097 cdip = mdi_pi_get_client(PIP(cip)); 13098 mutex_exit(&plun->lun_mutex); 13099 mutex_exit(&pptr->port_mutex); 13100 13101 /* 13102 * Exit phci to avoid deadlock with power management code 13103 * during mdi_pi_offline 13104 */ 13105 mdi_hold_path(PIP(cip)); 13106 mdi_devi_exit_phci(pptr->port_dip, *circ); 13107 13108 rval = mdi_pi_offline(PIP(cip), flags); 13109 13110 mdi_devi_enter_phci(pptr->port_dip, circ); 13111 mdi_rele_path(PIP(cip)); 13112 13113 if (rval == MDI_SUCCESS) { 13114 /* 13115 * Clear MPxIO path permanent disable as the path is 13116 * already offlined. 13117 */ 13118 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13119 13120 if (flags & NDI_DEVI_REMOVE) { 13121 (void) mdi_pi_free(PIP(cip), 0); 13122 } 13123 } else { 13124 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13125 fcp_trace, FCP_BUF_LEVEL_3, 0, 13126 "fcp_offline_child: mdi_pi_offline failed " 13127 "rval=%x cip=%p", rval, cip); 13128 } 13129 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13130 } 13131 13132 mutex_enter(&ptgt->tgt_mutex); 13133 plun->lun_state &= ~FCP_LUN_INIT; 13134 mutex_exit(&ptgt->tgt_mutex); 13135 13136 mutex_enter(&pptr->port_mutex); 13137 mutex_enter(&plun->lun_mutex); 13138 13139 if (rval == NDI_SUCCESS) { 13140 cdip = NULL; 13141 if (flags & NDI_DEVI_REMOVE) { 13142 /* 13143 * If the guid of the LUN changes, lun_cip will not 13144 * equal to cip, and after offlining the LUN with the 13145 * old guid, we should keep lun_cip since it's the cip 13146 * of the LUN with the new guid. 13147 * Otherwise remove our reference to child node. 13148 */ 13149 if (plun->lun_cip == cip) 13150 plun->lun_cip = NULL; 13151 if (plun->lun_old_guid) { 13152 kmem_free(plun->lun_old_guid, 13153 plun->lun_old_guid_size); 13154 plun->lun_old_guid = NULL; 13155 plun->lun_old_guid_size = 0; 13156 } 13157 } 13158 } 13159 13160 if (cdip) { 13161 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13162 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13163 " target=%x lun=%x", "ndi_offline", 13164 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13165 } 13166 13167 return (rval); 13168 } 13169 13170 static void 13171 fcp_remove_child(struct fcp_lun *plun) 13172 { 13173 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13174 13175 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13176 if (plun->lun_mpxio == 0) { 13177 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13178 (void) ndi_devi_free(DIP(plun->lun_cip)); 13179 } else { 13180 mutex_exit(&plun->lun_mutex); 13181 mutex_exit(&plun->lun_tgt->tgt_mutex); 13182 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13183 FCP_TRACE(fcp_logq, 13184 plun->lun_tgt->tgt_port->port_instbuf, 13185 fcp_trace, FCP_BUF_LEVEL_3, 0, 13186 "lun=%p pip freed %p", plun, plun->lun_cip); 13187 (void) mdi_prop_remove(PIP(plun->lun_cip), NULL); 13188 (void) mdi_pi_free(PIP(plun->lun_cip), 0); 13189 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13190 mutex_enter(&plun->lun_tgt->tgt_mutex); 13191 mutex_enter(&plun->lun_mutex); 13192 } 13193 } 13194 13195 plun->lun_cip = NULL; 13196 } 13197 13198 /* 13199 * called when a timeout occurs 13200 * 13201 * can be scheduled during an attach or resume (if not already running) 13202 * 13203 * one timeout is set up for all ports 13204 * 13205 * acquires and releases the global mutex 13206 */ 13207 /*ARGSUSED*/ 13208 static void 13209 fcp_watch(void *arg) 13210 { 13211 struct fcp_port *pptr; 13212 struct fcp_ipkt *icmd; 13213 struct fcp_ipkt *nicmd; 13214 struct fcp_pkt *cmd; 13215 struct fcp_pkt *ncmd; 13216 struct fcp_pkt *tail; 13217 struct fcp_pkt *pcmd; 13218 struct fcp_pkt *save_head; 13219 struct fcp_port *save_port; 13220 13221 /* increment global watchdog time */ 13222 fcp_watchdog_time += fcp_watchdog_timeout; 13223 13224 mutex_enter(&fcp_global_mutex); 13225 13226 /* scan each port in our list */ 13227 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13228 save_port = fcp_port_head; 13229 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13230 mutex_exit(&fcp_global_mutex); 13231 13232 mutex_enter(&pptr->port_mutex); 13233 if (pptr->port_ipkt_list == NULL && 13234 (pptr->port_state & (FCP_STATE_SUSPENDED | 13235 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13236 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13237 mutex_exit(&pptr->port_mutex); 13238 mutex_enter(&fcp_global_mutex); 13239 goto end_of_watchdog; 13240 } 13241 13242 /* 13243 * We check if a list of targets need to be offlined. 13244 */ 13245 if (pptr->port_offline_tgts) { 13246 fcp_scan_offline_tgts(pptr); 13247 } 13248 13249 /* 13250 * We check if a list of luns need to be offlined. 13251 */ 13252 if (pptr->port_offline_luns) { 13253 fcp_scan_offline_luns(pptr); 13254 } 13255 13256 /* 13257 * We check if a list of targets or luns need to be reset. 13258 */ 13259 if (pptr->port_reset_list) { 13260 fcp_check_reset_delay(pptr); 13261 } 13262 13263 mutex_exit(&pptr->port_mutex); 13264 13265 /* 13266 * This is where the pending commands (pkt) are checked for 13267 * timeout. 13268 */ 13269 mutex_enter(&pptr->port_pkt_mutex); 13270 tail = pptr->port_pkt_tail; 13271 13272 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13273 cmd != NULL; cmd = ncmd) { 13274 ncmd = cmd->cmd_next; 13275 /* 13276 * If a command is in this queue the bit CFLAG_IN_QUEUE 13277 * must be set. 13278 */ 13279 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13280 /* 13281 * FCP_INVALID_TIMEOUT will be set for those 13282 * command that need to be failed. Mostly those 13283 * cmds that could not be queued down for the 13284 * "timeout" value. cmd->cmd_timeout is used 13285 * to try and requeue the command regularly. 13286 */ 13287 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13288 /* 13289 * This command hasn't timed out yet. Let's 13290 * go to the next one. 13291 */ 13292 pcmd = cmd; 13293 goto end_of_loop; 13294 } 13295 13296 if (cmd == pptr->port_pkt_head) { 13297 ASSERT(pcmd == NULL); 13298 pptr->port_pkt_head = cmd->cmd_next; 13299 } else { 13300 ASSERT(pcmd != NULL); 13301 pcmd->cmd_next = cmd->cmd_next; 13302 } 13303 13304 if (cmd == pptr->port_pkt_tail) { 13305 ASSERT(cmd->cmd_next == NULL); 13306 pptr->port_pkt_tail = pcmd; 13307 if (pcmd) 13308 pcmd->cmd_next = NULL; 13309 } 13310 cmd->cmd_next = NULL; 13311 13312 /* 13313 * save the current head before dropping the 13314 * mutex - If the head doesn't remain the 13315 * same after re acquiring the mutex, just 13316 * bail out and revisit on next tick. 13317 * 13318 * PS: The tail pointer can change as the commands 13319 * get requeued after failure to retransport 13320 */ 13321 save_head = pptr->port_pkt_head; 13322 mutex_exit(&pptr->port_pkt_mutex); 13323 13324 if (cmd->cmd_fp_pkt->pkt_timeout == 13325 FCP_INVALID_TIMEOUT) { 13326 struct scsi_pkt *pkt = cmd->cmd_pkt; 13327 struct fcp_lun *plun; 13328 struct fcp_tgt *ptgt; 13329 13330 plun = ADDR2LUN(&pkt->pkt_address); 13331 ptgt = plun->lun_tgt; 13332 13333 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13334 fcp_trace, FCP_BUF_LEVEL_2, 0, 13335 "SCSI cmd 0x%x to D_ID=%x timed out", 13336 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13337 13338 cmd->cmd_state == FCP_PKT_ABORTING ? 13339 fcp_fail_cmd(cmd, CMD_RESET, 13340 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13341 CMD_TIMEOUT, STAT_ABORTED); 13342 } else { 13343 fcp_retransport_cmd(pptr, cmd); 13344 } 13345 mutex_enter(&pptr->port_pkt_mutex); 13346 if (save_head && save_head != pptr->port_pkt_head) { 13347 /* 13348 * Looks like linked list got changed (mostly 13349 * happens when an an OFFLINE LUN code starts 13350 * returning overflow queue commands in 13351 * parallel. So bail out and revisit during 13352 * next tick 13353 */ 13354 break; 13355 } 13356 end_of_loop: 13357 /* 13358 * Scan only upto the previously known tail pointer 13359 * to avoid excessive processing - lots of new packets 13360 * could have been added to the tail or the old ones 13361 * re-queued. 13362 */ 13363 if (cmd == tail) { 13364 break; 13365 } 13366 } 13367 mutex_exit(&pptr->port_pkt_mutex); 13368 13369 mutex_enter(&pptr->port_mutex); 13370 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13371 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13372 13373 nicmd = icmd->ipkt_next; 13374 if ((icmd->ipkt_restart != 0) && 13375 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13376 /* packet has not timed out */ 13377 continue; 13378 } 13379 13380 /* time for packet re-transport */ 13381 if (icmd == pptr->port_ipkt_list) { 13382 pptr->port_ipkt_list = icmd->ipkt_next; 13383 if (pptr->port_ipkt_list) { 13384 pptr->port_ipkt_list->ipkt_prev = 13385 NULL; 13386 } 13387 } else { 13388 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13389 if (icmd->ipkt_next) { 13390 icmd->ipkt_next->ipkt_prev = 13391 icmd->ipkt_prev; 13392 } 13393 } 13394 icmd->ipkt_next = NULL; 13395 icmd->ipkt_prev = NULL; 13396 mutex_exit(&pptr->port_mutex); 13397 13398 if (fcp_is_retryable(icmd)) { 13399 fc_ulp_rscn_info_t *rscnp = 13400 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13401 pkt_ulp_rscn_infop; 13402 13403 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13404 fcp_trace, FCP_BUF_LEVEL_2, 0, 13405 "%x to D_ID=%x Retrying..", 13406 icmd->ipkt_opcode, 13407 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13408 13409 /* 13410 * Update the RSCN count in the packet 13411 * before resending. 13412 */ 13413 13414 if (rscnp != NULL) { 13415 rscnp->ulp_rscn_count = 13416 fc_ulp_get_rscn_count(pptr-> 13417 port_fp_handle); 13418 } 13419 13420 mutex_enter(&pptr->port_mutex); 13421 mutex_enter(&ptgt->tgt_mutex); 13422 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13423 mutex_exit(&ptgt->tgt_mutex); 13424 mutex_exit(&pptr->port_mutex); 13425 switch (icmd->ipkt_opcode) { 13426 int rval; 13427 case LA_ELS_PLOGI: 13428 if ((rval = fc_ulp_login( 13429 pptr->port_fp_handle, 13430 &icmd->ipkt_fpkt, 1)) == 13431 FC_SUCCESS) { 13432 mutex_enter( 13433 &pptr->port_mutex); 13434 continue; 13435 } 13436 if (fcp_handle_ipkt_errors( 13437 pptr, ptgt, icmd, rval, 13438 "PLOGI") == DDI_SUCCESS) { 13439 mutex_enter( 13440 &pptr->port_mutex); 13441 continue; 13442 } 13443 break; 13444 13445 case LA_ELS_PRLI: 13446 if ((rval = fc_ulp_issue_els( 13447 pptr->port_fp_handle, 13448 icmd->ipkt_fpkt)) == 13449 FC_SUCCESS) { 13450 mutex_enter( 13451 &pptr->port_mutex); 13452 continue; 13453 } 13454 if (fcp_handle_ipkt_errors( 13455 pptr, ptgt, icmd, rval, 13456 "PRLI") == DDI_SUCCESS) { 13457 mutex_enter( 13458 &pptr->port_mutex); 13459 continue; 13460 } 13461 break; 13462 13463 default: 13464 if ((rval = fcp_transport( 13465 pptr->port_fp_handle, 13466 icmd->ipkt_fpkt, 1)) == 13467 FC_SUCCESS) { 13468 mutex_enter( 13469 &pptr->port_mutex); 13470 continue; 13471 } 13472 if (fcp_handle_ipkt_errors( 13473 pptr, ptgt, icmd, rval, 13474 "PRLI") == DDI_SUCCESS) { 13475 mutex_enter( 13476 &pptr->port_mutex); 13477 continue; 13478 } 13479 break; 13480 } 13481 } else { 13482 mutex_exit(&ptgt->tgt_mutex); 13483 mutex_exit(&pptr->port_mutex); 13484 } 13485 } else { 13486 fcp_print_error(icmd->ipkt_fpkt); 13487 } 13488 13489 (void) fcp_call_finish_init(pptr, ptgt, 13490 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13491 icmd->ipkt_cause); 13492 fcp_icmd_free(pptr, icmd); 13493 mutex_enter(&pptr->port_mutex); 13494 } 13495 13496 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13497 mutex_exit(&pptr->port_mutex); 13498 mutex_enter(&fcp_global_mutex); 13499 13500 end_of_watchdog: 13501 /* 13502 * Bail out early before getting into trouble 13503 */ 13504 if (save_port != fcp_port_head) { 13505 break; 13506 } 13507 } 13508 13509 if (fcp_watchdog_init > 0) { 13510 /* reschedule timeout to go again */ 13511 fcp_watchdog_id = 13512 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13513 } 13514 mutex_exit(&fcp_global_mutex); 13515 } 13516 13517 13518 static void 13519 fcp_check_reset_delay(struct fcp_port *pptr) 13520 { 13521 uint32_t tgt_cnt; 13522 int level; 13523 struct fcp_tgt *ptgt; 13524 struct fcp_lun *plun; 13525 struct fcp_reset_elem *cur = NULL; 13526 struct fcp_reset_elem *next = NULL; 13527 struct fcp_reset_elem *prev = NULL; 13528 13529 ASSERT(mutex_owned(&pptr->port_mutex)); 13530 13531 next = pptr->port_reset_list; 13532 while ((cur = next) != NULL) { 13533 next = cur->next; 13534 13535 if (cur->timeout < fcp_watchdog_time) { 13536 prev = cur; 13537 continue; 13538 } 13539 13540 ptgt = cur->tgt; 13541 plun = cur->lun; 13542 tgt_cnt = cur->tgt_cnt; 13543 13544 if (ptgt) { 13545 level = RESET_TARGET; 13546 } else { 13547 ASSERT(plun != NULL); 13548 level = RESET_LUN; 13549 ptgt = plun->lun_tgt; 13550 } 13551 if (prev) { 13552 prev->next = next; 13553 } else { 13554 /* 13555 * Because we drop port mutex while doing aborts for 13556 * packets, we can't rely on reset_list pointing to 13557 * our head 13558 */ 13559 if (cur == pptr->port_reset_list) { 13560 pptr->port_reset_list = next; 13561 } else { 13562 struct fcp_reset_elem *which; 13563 13564 which = pptr->port_reset_list; 13565 while (which && which->next != cur) { 13566 which = which->next; 13567 } 13568 ASSERT(which != NULL); 13569 13570 which->next = next; 13571 prev = which; 13572 } 13573 } 13574 13575 kmem_free(cur, sizeof (*cur)); 13576 13577 if (tgt_cnt == ptgt->tgt_change_cnt) { 13578 mutex_enter(&ptgt->tgt_mutex); 13579 if (level == RESET_TARGET) { 13580 fcp_update_tgt_state(ptgt, 13581 FCP_RESET, FCP_LUN_BUSY); 13582 } else { 13583 fcp_update_lun_state(plun, 13584 FCP_RESET, FCP_LUN_BUSY); 13585 } 13586 mutex_exit(&ptgt->tgt_mutex); 13587 13588 mutex_exit(&pptr->port_mutex); 13589 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13590 mutex_enter(&pptr->port_mutex); 13591 } 13592 } 13593 } 13594 13595 13596 static void 13597 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13598 struct fcp_lun *rlun, int tgt_cnt) 13599 { 13600 int rval; 13601 struct fcp_lun *tlun, *nlun; 13602 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13603 *cmd = NULL, *head = NULL, 13604 *tail = NULL; 13605 13606 mutex_enter(&pptr->port_pkt_mutex); 13607 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13608 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13609 struct fcp_tgt *ptgt = plun->lun_tgt; 13610 13611 ncmd = cmd->cmd_next; 13612 13613 if (ptgt != ttgt && plun != rlun) { 13614 pcmd = cmd; 13615 continue; 13616 } 13617 13618 if (pcmd != NULL) { 13619 ASSERT(pptr->port_pkt_head != cmd); 13620 pcmd->cmd_next = ncmd; 13621 } else { 13622 ASSERT(cmd == pptr->port_pkt_head); 13623 pptr->port_pkt_head = ncmd; 13624 } 13625 if (pptr->port_pkt_tail == cmd) { 13626 ASSERT(cmd->cmd_next == NULL); 13627 pptr->port_pkt_tail = pcmd; 13628 if (pcmd != NULL) 13629 pcmd->cmd_next = NULL; 13630 } 13631 13632 if (head == NULL) { 13633 head = tail = cmd; 13634 } else { 13635 ASSERT(tail != NULL); 13636 tail->cmd_next = cmd; 13637 tail = cmd; 13638 } 13639 cmd->cmd_next = NULL; 13640 } 13641 mutex_exit(&pptr->port_pkt_mutex); 13642 13643 for (cmd = head; cmd != NULL; cmd = ncmd) { 13644 struct scsi_pkt *pkt = cmd->cmd_pkt; 13645 13646 ncmd = cmd->cmd_next; 13647 ASSERT(pkt != NULL); 13648 13649 mutex_enter(&pptr->port_mutex); 13650 if (ttgt->tgt_change_cnt == tgt_cnt) { 13651 mutex_exit(&pptr->port_mutex); 13652 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13653 pkt->pkt_reason = CMD_RESET; 13654 pkt->pkt_statistics |= STAT_DEV_RESET; 13655 cmd->cmd_state = FCP_PKT_IDLE; 13656 fcp_post_callback(cmd); 13657 } else { 13658 mutex_exit(&pptr->port_mutex); 13659 } 13660 } 13661 13662 /* 13663 * If the FCA will return all the commands in its queue then our 13664 * work is easy, just return. 13665 */ 13666 13667 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) 13668 return; 13669 13670 /* 13671 * For RESET_LUN get hold of target pointer 13672 */ 13673 if (ttgt == NULL) { 13674 ASSERT(rlun != NULL); 13675 13676 ttgt = rlun->lun_tgt; 13677 13678 ASSERT(ttgt != NULL); 13679 } 13680 13681 /* 13682 * There are some severe race conditions here. 13683 * While we are trying to abort the pkt, it might be completing 13684 * so mark it aborted and if the abort does not succeed then 13685 * handle it in the watch thread. 13686 */ 13687 mutex_enter(&ttgt->tgt_mutex); 13688 nlun = ttgt->tgt_lun; 13689 mutex_exit(&ttgt->tgt_mutex); 13690 while ((tlun = nlun) != NULL) { 13691 int restart = 0; 13692 if (rlun && rlun != tlun) { 13693 mutex_enter(&ttgt->tgt_mutex); 13694 nlun = tlun->lun_next; 13695 mutex_exit(&ttgt->tgt_mutex); 13696 continue; 13697 } 13698 mutex_enter(&tlun->lun_mutex); 13699 cmd = tlun->lun_pkt_head; 13700 while (cmd != NULL) { 13701 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13702 struct scsi_pkt *pkt; 13703 13704 restart = 1; 13705 cmd->cmd_state = FCP_PKT_ABORTING; 13706 mutex_exit(&tlun->lun_mutex); 13707 rval = fc_ulp_abort(pptr->port_fp_handle, 13708 cmd->cmd_fp_pkt, KM_SLEEP); 13709 if (rval == FC_SUCCESS) { 13710 pkt = cmd->cmd_pkt; 13711 pkt->pkt_reason = CMD_RESET; 13712 pkt->pkt_statistics |= STAT_DEV_RESET; 13713 cmd->cmd_state = FCP_PKT_IDLE; 13714 fcp_post_callback(cmd); 13715 } else { 13716 caddr_t msg; 13717 13718 (void) fc_ulp_error(rval, &msg); 13719 13720 /* 13721 * This part is tricky. The abort 13722 * failed and now the command could 13723 * be completing. The cmd_state == 13724 * FCP_PKT_ABORTING should save 13725 * us in fcp_cmd_callback. If we 13726 * are already aborting ignore the 13727 * command in fcp_cmd_callback. 13728 * Here we leave this packet for 20 13729 * sec to be aborted in the 13730 * fcp_watch thread. 13731 */ 13732 fcp_log(CE_WARN, pptr->port_dip, 13733 "!Abort failed after reset %s", 13734 msg); 13735 13736 cmd->cmd_timeout = 13737 fcp_watchdog_time + 13738 cmd->cmd_pkt->pkt_time + 13739 FCP_FAILED_DELAY; 13740 13741 cmd->cmd_fp_pkt->pkt_timeout = 13742 FCP_INVALID_TIMEOUT; 13743 /* 13744 * This is a hack, cmd is put in the 13745 * overflow queue so that it can be 13746 * timed out finally 13747 */ 13748 cmd->cmd_flags |= CFLAG_IN_QUEUE; 13749 13750 mutex_enter(&pptr->port_pkt_mutex); 13751 if (pptr->port_pkt_head) { 13752 ASSERT(pptr->port_pkt_tail 13753 != NULL); 13754 pptr->port_pkt_tail->cmd_next 13755 = cmd; 13756 pptr->port_pkt_tail = cmd; 13757 } else { 13758 ASSERT(pptr->port_pkt_tail 13759 == NULL); 13760 pptr->port_pkt_head = 13761 pptr->port_pkt_tail 13762 = cmd; 13763 } 13764 cmd->cmd_next = NULL; 13765 mutex_exit(&pptr->port_pkt_mutex); 13766 } 13767 mutex_enter(&tlun->lun_mutex); 13768 cmd = tlun->lun_pkt_head; 13769 } else { 13770 cmd = cmd->cmd_forw; 13771 } 13772 } 13773 mutex_exit(&tlun->lun_mutex); 13774 13775 mutex_enter(&ttgt->tgt_mutex); 13776 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 13777 mutex_exit(&ttgt->tgt_mutex); 13778 13779 mutex_enter(&pptr->port_mutex); 13780 if (tgt_cnt != ttgt->tgt_change_cnt) { 13781 mutex_exit(&pptr->port_mutex); 13782 return; 13783 } else { 13784 mutex_exit(&pptr->port_mutex); 13785 } 13786 } 13787 } 13788 13789 13790 /* 13791 * unlink the soft state, returning the soft state found (if any) 13792 * 13793 * acquires and releases the global mutex 13794 */ 13795 struct fcp_port * 13796 fcp_soft_state_unlink(struct fcp_port *pptr) 13797 { 13798 struct fcp_port *hptr; /* ptr index */ 13799 struct fcp_port *tptr; /* prev hptr */ 13800 13801 mutex_enter(&fcp_global_mutex); 13802 for (hptr = fcp_port_head, tptr = NULL; 13803 hptr != NULL; 13804 tptr = hptr, hptr = hptr->port_next) { 13805 if (hptr == pptr) { 13806 /* we found a match -- remove this item */ 13807 if (tptr == NULL) { 13808 /* we're at the head of the list */ 13809 fcp_port_head = hptr->port_next; 13810 } else { 13811 tptr->port_next = hptr->port_next; 13812 } 13813 break; /* success */ 13814 } 13815 } 13816 if (fcp_port_head == NULL) { 13817 fcp_cleanup_blacklist(&fcp_lun_blacklist); 13818 } 13819 mutex_exit(&fcp_global_mutex); 13820 return (hptr); 13821 } 13822 13823 13824 /* 13825 * called by fcp_scsi_hba_tgt_init to find a LUN given a 13826 * WWN and a LUN number 13827 */ 13828 /* ARGSUSED */ 13829 static struct fcp_lun * 13830 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 13831 { 13832 int hash; 13833 struct fcp_tgt *ptgt; 13834 struct fcp_lun *plun; 13835 13836 ASSERT(mutex_owned(&pptr->port_mutex)); 13837 13838 hash = FCP_HASH(wwn); 13839 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 13840 ptgt = ptgt->tgt_next) { 13841 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 13842 sizeof (ptgt->tgt_port_wwn)) == 0) { 13843 mutex_enter(&ptgt->tgt_mutex); 13844 for (plun = ptgt->tgt_lun; 13845 plun != NULL; 13846 plun = plun->lun_next) { 13847 if (plun->lun_num == lun) { 13848 mutex_exit(&ptgt->tgt_mutex); 13849 return (plun); 13850 } 13851 } 13852 mutex_exit(&ptgt->tgt_mutex); 13853 return (NULL); 13854 } 13855 } 13856 return (NULL); 13857 } 13858 13859 /* 13860 * Function: fcp_prepare_pkt 13861 * 13862 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 13863 * for fcp_start(). It binds the data or partially maps it. 13864 * Builds the FCP header and starts the initialization of the 13865 * Fibre Channel header. 13866 * 13867 * Argument: *pptr FCP port. 13868 * *cmd FCP packet. 13869 * *plun LUN the command will be sent to. 13870 * 13871 * Context: User, Kernel and Interrupt context. 13872 */ 13873 static void 13874 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 13875 struct fcp_lun *plun) 13876 { 13877 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 13878 struct fcp_tgt *ptgt = plun->lun_tgt; 13879 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 13880 13881 ASSERT(cmd->cmd_pkt->pkt_comp || 13882 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 13883 13884 if (cmd->cmd_pkt->pkt_numcookies) { 13885 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 13886 fcmd->fcp_cntl.cntl_read_data = 1; 13887 fcmd->fcp_cntl.cntl_write_data = 0; 13888 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 13889 } else { 13890 fcmd->fcp_cntl.cntl_read_data = 0; 13891 fcmd->fcp_cntl.cntl_write_data = 1; 13892 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 13893 } 13894 13895 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 13896 13897 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 13898 ASSERT(fpkt->pkt_data_cookie_cnt <= 13899 pptr->port_data_dma_attr.dma_attr_sgllen); 13900 13901 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 13902 13903 /* FCA needs pkt_datalen to be set */ 13904 fpkt->pkt_datalen = cmd->cmd_dmacount; 13905 fcmd->fcp_data_len = cmd->cmd_dmacount; 13906 } else { 13907 fcmd->fcp_cntl.cntl_read_data = 0; 13908 fcmd->fcp_cntl.cntl_write_data = 0; 13909 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 13910 fpkt->pkt_datalen = 0; 13911 fcmd->fcp_data_len = 0; 13912 } 13913 13914 /* set up the Tagged Queuing type */ 13915 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 13916 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 13917 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 13918 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 13919 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 13920 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 13921 } else { 13922 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 13923 } 13924 13925 fcmd->fcp_ent_addr = plun->lun_addr; 13926 13927 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 13928 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 13929 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 13930 } else { 13931 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 13932 } 13933 13934 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 13935 cmd->cmd_pkt->pkt_state = 0; 13936 cmd->cmd_pkt->pkt_statistics = 0; 13937 cmd->cmd_pkt->pkt_resid = 0; 13938 13939 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 13940 13941 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 13942 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 13943 fpkt->pkt_comp = NULL; 13944 } else { 13945 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 13946 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 13947 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 13948 } 13949 fpkt->pkt_comp = fcp_cmd_callback; 13950 } 13951 13952 mutex_enter(&pptr->port_mutex); 13953 if (pptr->port_state & FCP_STATE_SUSPENDED) { 13954 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 13955 } 13956 mutex_exit(&pptr->port_mutex); 13957 13958 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 13959 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 13960 13961 /* 13962 * Save a few kernel cycles here 13963 */ 13964 #ifndef __lock_lint 13965 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 13966 #endif /* __lock_lint */ 13967 } 13968 13969 static void 13970 fcp_post_callback(struct fcp_pkt *cmd) 13971 { 13972 if (cmd->cmd_pkt->pkt_comp) { 13973 (*cmd->cmd_pkt->pkt_comp) (cmd->cmd_pkt); 13974 } 13975 } 13976 13977 13978 /* 13979 * called to do polled I/O by fcp_start() 13980 * 13981 * return a transport status value, i.e. TRAN_ACCECPT for success 13982 */ 13983 static int 13984 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 13985 { 13986 int rval; 13987 13988 #ifdef DEBUG 13989 mutex_enter(&pptr->port_pkt_mutex); 13990 pptr->port_npkts++; 13991 mutex_exit(&pptr->port_pkt_mutex); 13992 #endif /* DEBUG */ 13993 13994 if (cmd->cmd_fp_pkt->pkt_timeout) { 13995 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 13996 } else { 13997 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 13998 } 13999 14000 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14001 14002 cmd->cmd_state = FCP_PKT_ISSUED; 14003 14004 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14005 14006 #ifdef DEBUG 14007 mutex_enter(&pptr->port_pkt_mutex); 14008 pptr->port_npkts--; 14009 mutex_exit(&pptr->port_pkt_mutex); 14010 #endif /* DEBUG */ 14011 14012 cmd->cmd_state = FCP_PKT_IDLE; 14013 14014 switch (rval) { 14015 case FC_SUCCESS: 14016 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14017 fcp_complete_pkt(cmd->cmd_fp_pkt); 14018 rval = TRAN_ACCEPT; 14019 } else { 14020 rval = TRAN_FATAL_ERROR; 14021 } 14022 break; 14023 14024 case FC_TRAN_BUSY: 14025 rval = TRAN_BUSY; 14026 cmd->cmd_pkt->pkt_resid = 0; 14027 break; 14028 14029 case FC_BADPACKET: 14030 rval = TRAN_BADPKT; 14031 break; 14032 14033 default: 14034 rval = TRAN_FATAL_ERROR; 14035 break; 14036 } 14037 14038 return (rval); 14039 } 14040 14041 14042 /* 14043 * called by some of the following transport-called routines to convert 14044 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14045 */ 14046 static struct fcp_port * 14047 fcp_dip2port(dev_info_t *dip) 14048 { 14049 int instance; 14050 14051 instance = ddi_get_instance(dip); 14052 return (ddi_get_soft_state(fcp_softstate, instance)); 14053 } 14054 14055 14056 /* 14057 * called internally to return a LUN given a dip 14058 */ 14059 struct fcp_lun * 14060 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14061 { 14062 struct fcp_tgt *ptgt; 14063 struct fcp_lun *plun; 14064 int i; 14065 14066 14067 ASSERT(mutex_owned(&pptr->port_mutex)); 14068 14069 for (i = 0; i < FCP_NUM_HASH; i++) { 14070 for (ptgt = pptr->port_tgt_hash_table[i]; 14071 ptgt != NULL; 14072 ptgt = ptgt->tgt_next) { 14073 mutex_enter(&ptgt->tgt_mutex); 14074 for (plun = ptgt->tgt_lun; plun != NULL; 14075 plun = plun->lun_next) { 14076 mutex_enter(&plun->lun_mutex); 14077 if (plun->lun_cip == cip) { 14078 mutex_exit(&plun->lun_mutex); 14079 mutex_exit(&ptgt->tgt_mutex); 14080 return (plun); /* match found */ 14081 } 14082 mutex_exit(&plun->lun_mutex); 14083 } 14084 mutex_exit(&ptgt->tgt_mutex); 14085 } 14086 } 14087 return (NULL); /* no LUN found */ 14088 } 14089 14090 /* 14091 * pass an element to the hotplug list, kick the hotplug thread 14092 * and wait for the element to get processed by the hotplug thread. 14093 * on return the element is freed. 14094 * 14095 * return zero success and non-zero on failure 14096 * 14097 * acquires/releases the target mutex 14098 * 14099 */ 14100 static int 14101 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14102 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14103 { 14104 struct fcp_hp_elem *elem; 14105 int rval; 14106 14107 mutex_enter(&plun->lun_tgt->tgt_mutex); 14108 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14109 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14110 mutex_exit(&plun->lun_tgt->tgt_mutex); 14111 fcp_log(CE_CONT, pptr->port_dip, 14112 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14113 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14114 return (NDI_FAILURE); 14115 } 14116 mutex_exit(&plun->lun_tgt->tgt_mutex); 14117 mutex_enter(&elem->mutex); 14118 if (elem->wait) { 14119 while (elem->wait) { 14120 cv_wait(&elem->cv, &elem->mutex); 14121 } 14122 } 14123 rval = (elem->result); 14124 mutex_exit(&elem->mutex); 14125 mutex_destroy(&elem->mutex); 14126 cv_destroy(&elem->cv); 14127 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14128 return (rval); 14129 } 14130 14131 /* 14132 * pass an element to the hotplug list, and then 14133 * kick the hotplug thread 14134 * 14135 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14136 * 14137 * acquires/releases the hotplug mutex 14138 * 14139 * called with the target mutex owned 14140 * 14141 * memory acquired in NOSLEEP mode 14142 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14143 * for the hp daemon to process the request and is responsible for 14144 * freeing the element 14145 */ 14146 static struct fcp_hp_elem * 14147 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14148 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14149 { 14150 struct fcp_hp_elem *elem; 14151 dev_info_t *pdip; 14152 14153 ASSERT(pptr != NULL); 14154 ASSERT(plun != NULL); 14155 ASSERT(plun->lun_tgt != NULL); 14156 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14157 14158 /* create space for a hotplug element */ 14159 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14160 == NULL) { 14161 fcp_log(CE_WARN, NULL, 14162 "!can't allocate memory for hotplug element"); 14163 return (NULL); 14164 } 14165 14166 /* fill in hotplug element */ 14167 elem->port = pptr; 14168 elem->lun = plun; 14169 elem->cip = cip; 14170 elem->what = what; 14171 elem->flags = flags; 14172 elem->link_cnt = link_cnt; 14173 elem->tgt_cnt = tgt_cnt; 14174 elem->wait = wait; 14175 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14176 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14177 14178 /* schedule the hotplug task */ 14179 pdip = pptr->port_dip; 14180 mutex_enter(&plun->lun_mutex); 14181 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14182 plun->lun_event_count++; 14183 elem->event_cnt = plun->lun_event_count; 14184 } 14185 mutex_exit(&plun->lun_mutex); 14186 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14187 (void *)elem, KM_NOSLEEP) == NULL) { 14188 mutex_enter(&plun->lun_mutex); 14189 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) 14190 plun->lun_event_count--; 14191 mutex_exit(&plun->lun_mutex); 14192 kmem_free(elem, sizeof (*elem)); 14193 return (0); 14194 } 14195 14196 return (elem); 14197 } 14198 14199 14200 static void 14201 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14202 { 14203 int rval; 14204 struct scsi_address *ap; 14205 struct fcp_lun *plun; 14206 struct fcp_tgt *ptgt; 14207 fc_packet_t *fpkt; 14208 14209 ap = &cmd->cmd_pkt->pkt_address; 14210 plun = ADDR2LUN(ap); 14211 ptgt = plun->lun_tgt; 14212 14213 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14214 14215 cmd->cmd_state = FCP_PKT_IDLE; 14216 14217 mutex_enter(&pptr->port_mutex); 14218 mutex_enter(&ptgt->tgt_mutex); 14219 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14220 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14221 fc_ulp_rscn_info_t *rscnp; 14222 14223 cmd->cmd_state = FCP_PKT_ISSUED; 14224 14225 /* 14226 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14227 * originally NULL, hence we try to set it to the pd pointed 14228 * to by the SCSI device we're trying to get to. 14229 */ 14230 14231 fpkt = cmd->cmd_fp_pkt; 14232 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14233 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14234 /* 14235 * We need to notify the transport that we now have a 14236 * reference to the remote port handle. 14237 */ 14238 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14239 } 14240 14241 mutex_exit(&ptgt->tgt_mutex); 14242 mutex_exit(&pptr->port_mutex); 14243 14244 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14245 14246 /* prepare the packet */ 14247 14248 fcp_prepare_pkt(pptr, cmd, plun); 14249 14250 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14251 pkt_ulp_rscn_infop; 14252 14253 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14254 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14255 14256 if (rscnp != NULL) { 14257 rscnp->ulp_rscn_count = 14258 fc_ulp_get_rscn_count(pptr-> 14259 port_fp_handle); 14260 } 14261 14262 rval = fcp_transport(pptr->port_fp_handle, 14263 cmd->cmd_fp_pkt, 0); 14264 14265 if (rval == FC_SUCCESS) { 14266 return; 14267 } 14268 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14269 } else { 14270 mutex_exit(&ptgt->tgt_mutex); 14271 mutex_exit(&pptr->port_mutex); 14272 } 14273 14274 fcp_queue_pkt(pptr, cmd); 14275 } 14276 14277 14278 static void 14279 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14280 { 14281 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14282 14283 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14284 cmd->cmd_state = FCP_PKT_IDLE; 14285 14286 cmd->cmd_pkt->pkt_reason = reason; 14287 cmd->cmd_pkt->pkt_state = 0; 14288 cmd->cmd_pkt->pkt_statistics = statistics; 14289 14290 fcp_post_callback(cmd); 14291 } 14292 14293 /* 14294 * Function: fcp_queue_pkt 14295 * 14296 * Description: This function queues the packet passed by the caller into 14297 * the list of packets of the FCP port. 14298 * 14299 * Argument: *pptr FCP port. 14300 * *cmd FCP packet to queue. 14301 * 14302 * Return Value: None 14303 * 14304 * Context: User, Kernel and Interrupt context. 14305 */ 14306 static void 14307 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14308 { 14309 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14310 14311 mutex_enter(&pptr->port_pkt_mutex); 14312 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14313 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14314 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14315 14316 /* 14317 * zero pkt_time means hang around for ever 14318 */ 14319 if (cmd->cmd_pkt->pkt_time) { 14320 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14321 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14322 } else { 14323 /* 14324 * Indicate the watch thread to fail the 14325 * command by setting it to highest value 14326 */ 14327 cmd->cmd_timeout = fcp_watchdog_time; 14328 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14329 } 14330 } 14331 14332 if (pptr->port_pkt_head) { 14333 ASSERT(pptr->port_pkt_tail != NULL); 14334 14335 pptr->port_pkt_tail->cmd_next = cmd; 14336 pptr->port_pkt_tail = cmd; 14337 } else { 14338 ASSERT(pptr->port_pkt_tail == NULL); 14339 14340 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14341 } 14342 cmd->cmd_next = NULL; 14343 mutex_exit(&pptr->port_pkt_mutex); 14344 } 14345 14346 /* 14347 * Function: fcp_update_targets 14348 * 14349 * Description: This function applies the specified change of state to all 14350 * the targets listed. The operation applied is 'set'. 14351 * 14352 * Argument: *pptr FCP port. 14353 * *dev_list Array of fc_portmap_t structures. 14354 * count Length of dev_list. 14355 * state State bits to update. 14356 * cause Reason for the update. 14357 * 14358 * Return Value: None 14359 * 14360 * Context: User, Kernel and Interrupt context. 14361 * The mutex pptr->port_mutex must be held. 14362 */ 14363 static void 14364 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14365 uint32_t count, uint32_t state, int cause) 14366 { 14367 fc_portmap_t *map_entry; 14368 struct fcp_tgt *ptgt; 14369 14370 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14371 14372 while (count--) { 14373 map_entry = &(dev_list[count]); 14374 ptgt = fcp_lookup_target(pptr, 14375 (uchar_t *)&(map_entry->map_pwwn)); 14376 if (ptgt == NULL) { 14377 continue; 14378 } 14379 14380 mutex_enter(&ptgt->tgt_mutex); 14381 ptgt->tgt_trace = 0; 14382 ptgt->tgt_change_cnt++; 14383 ptgt->tgt_statec_cause = cause; 14384 ptgt->tgt_tmp_cnt = 1; 14385 fcp_update_tgt_state(ptgt, FCP_SET, state); 14386 mutex_exit(&ptgt->tgt_mutex); 14387 } 14388 } 14389 14390 static int 14391 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14392 int lcount, int tcount, int cause) 14393 { 14394 int rval; 14395 14396 mutex_enter(&pptr->port_mutex); 14397 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14398 mutex_exit(&pptr->port_mutex); 14399 14400 return (rval); 14401 } 14402 14403 14404 static int 14405 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14406 int lcount, int tcount, int cause) 14407 { 14408 int finish_init = 0; 14409 int finish_tgt = 0; 14410 int do_finish_init = 0; 14411 int rval = FCP_NO_CHANGE; 14412 14413 if (cause == FCP_CAUSE_LINK_CHANGE || 14414 cause == FCP_CAUSE_LINK_DOWN) { 14415 do_finish_init = 1; 14416 } 14417 14418 if (ptgt != NULL) { 14419 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14420 FCP_BUF_LEVEL_2, 0, 14421 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14422 " cause = %d, d_id = 0x%x, tgt_done = %d", 14423 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14424 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14425 ptgt->tgt_d_id, ptgt->tgt_done); 14426 14427 mutex_enter(&ptgt->tgt_mutex); 14428 14429 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14430 rval = FCP_DEV_CHANGE; 14431 if (do_finish_init && ptgt->tgt_done == 0) { 14432 ptgt->tgt_done++; 14433 finish_init = 1; 14434 } 14435 } else { 14436 if (--ptgt->tgt_tmp_cnt <= 0) { 14437 ptgt->tgt_tmp_cnt = 0; 14438 finish_tgt = 1; 14439 14440 if (do_finish_init) { 14441 finish_init = 1; 14442 } 14443 } 14444 } 14445 mutex_exit(&ptgt->tgt_mutex); 14446 } else { 14447 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14448 FCP_BUF_LEVEL_2, 0, 14449 "Call Finish Init for NO target"); 14450 14451 if (do_finish_init) { 14452 finish_init = 1; 14453 } 14454 } 14455 14456 if (finish_tgt) { 14457 ASSERT(ptgt != NULL); 14458 14459 mutex_enter(&ptgt->tgt_mutex); 14460 #ifdef DEBUG 14461 bzero(ptgt->tgt_tmp_cnt_stack, 14462 sizeof (ptgt->tgt_tmp_cnt_stack)); 14463 14464 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14465 FCP_STACK_DEPTH); 14466 #endif /* DEBUG */ 14467 mutex_exit(&ptgt->tgt_mutex); 14468 14469 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14470 } 14471 14472 if (finish_init && lcount == pptr->port_link_cnt) { 14473 ASSERT(pptr->port_tmp_cnt > 0); 14474 if (--pptr->port_tmp_cnt == 0) { 14475 fcp_finish_init(pptr); 14476 } 14477 } else if (lcount != pptr->port_link_cnt) { 14478 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14479 fcp_trace, FCP_BUF_LEVEL_2, 0, 14480 "fcp_call_finish_init_held,1: state change occured" 14481 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14482 } 14483 14484 return (rval); 14485 } 14486 14487 14488 static void 14489 fcp_reconfigure_luns(void * tgt_handle) 14490 { 14491 uint32_t dev_cnt; 14492 fc_portmap_t *devlist; 14493 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14494 struct fcp_port *pptr = ptgt->tgt_port; 14495 14496 /* 14497 * If the timer that fires this off got canceled too late, the 14498 * target could have been destroyed. 14499 */ 14500 14501 if (ptgt->tgt_tid == NULL) { 14502 return; 14503 } 14504 14505 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14506 if (devlist == NULL) { 14507 fcp_log(CE_WARN, pptr->port_dip, 14508 "!fcp%d: failed to allocate for portmap", 14509 pptr->port_instance); 14510 return; 14511 } 14512 14513 dev_cnt = 1; 14514 devlist->map_pd = ptgt->tgt_pd_handle; 14515 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14516 devlist->map_did.port_id = ptgt->tgt_d_id; 14517 14518 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14519 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14520 14521 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14522 devlist->map_type = PORT_DEVICE_NEW; 14523 devlist->map_flags = 0; 14524 14525 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14526 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14527 14528 /* 14529 * Clear the tgt_tid after no more references to 14530 * the fcp_tgt 14531 */ 14532 mutex_enter(&ptgt->tgt_mutex); 14533 ptgt->tgt_tid = NULL; 14534 mutex_exit(&ptgt->tgt_mutex); 14535 14536 kmem_free(devlist, sizeof (*devlist)); 14537 } 14538 14539 14540 static void 14541 fcp_free_targets(struct fcp_port *pptr) 14542 { 14543 int i; 14544 struct fcp_tgt *ptgt; 14545 14546 mutex_enter(&pptr->port_mutex); 14547 for (i = 0; i < FCP_NUM_HASH; i++) { 14548 ptgt = pptr->port_tgt_hash_table[i]; 14549 while (ptgt != NULL) { 14550 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14551 14552 fcp_free_target(ptgt); 14553 ptgt = next_tgt; 14554 } 14555 } 14556 mutex_exit(&pptr->port_mutex); 14557 } 14558 14559 14560 static void 14561 fcp_free_target(struct fcp_tgt *ptgt) 14562 { 14563 struct fcp_lun *plun; 14564 timeout_id_t tid; 14565 14566 mutex_enter(&ptgt->tgt_mutex); 14567 tid = ptgt->tgt_tid; 14568 14569 /* 14570 * Cancel any pending timeouts for this target. 14571 */ 14572 14573 if (tid != NULL) { 14574 /* 14575 * Set tgt_tid to NULL first to avoid a race in the callback. 14576 * If tgt_tid is NULL, the callback will simply return. 14577 */ 14578 ptgt->tgt_tid = NULL; 14579 mutex_exit(&ptgt->tgt_mutex); 14580 (void) untimeout(tid); 14581 mutex_enter(&ptgt->tgt_mutex); 14582 } 14583 14584 plun = ptgt->tgt_lun; 14585 while (plun != NULL) { 14586 struct fcp_lun *next_lun = plun->lun_next; 14587 14588 fcp_dealloc_lun(plun); 14589 plun = next_lun; 14590 } 14591 14592 mutex_exit(&ptgt->tgt_mutex); 14593 fcp_dealloc_tgt(ptgt); 14594 } 14595 14596 /* 14597 * Function: fcp_is_retryable 14598 * 14599 * Description: Indicates if the internal packet is retryable. 14600 * 14601 * Argument: *icmd FCP internal packet. 14602 * 14603 * Return Value: 0 Not retryable 14604 * 1 Retryable 14605 * 14606 * Context: User, Kernel and Interrupt context 14607 */ 14608 static int 14609 fcp_is_retryable(struct fcp_ipkt *icmd) 14610 { 14611 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14612 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) 14613 return (0); 14614 14615 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14616 icmd->ipkt_port->port_deadline) ? 1 : 0); 14617 } 14618 14619 /* 14620 * Function: fcp_create_on_demand 14621 * 14622 * Argument: *pptr FCP port. 14623 * *pwwn Port WWN. 14624 * 14625 * Return Value: 0 Success 14626 * EIO 14627 * ENOMEM 14628 * EBUSY 14629 * EINVAL 14630 * 14631 * Context: User and Kernel context 14632 */ 14633 static int 14634 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14635 { 14636 int wait_ms; 14637 int tcount; 14638 int lcount; 14639 int ret; 14640 int error; 14641 int rval = EIO; 14642 int ntries; 14643 fc_portmap_t *devlist; 14644 opaque_t pd; 14645 struct fcp_lun *plun; 14646 struct fcp_tgt *ptgt; 14647 int old_manual = 0; 14648 14649 /* Allocates the fc_portmap_t structure. */ 14650 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14651 14652 /* 14653 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14654 * in the commented statement below: 14655 * 14656 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14657 * 14658 * Below, the deadline for the discovery process is set. 14659 */ 14660 mutex_enter(&pptr->port_mutex); 14661 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14662 mutex_exit(&pptr->port_mutex); 14663 14664 /* 14665 * We try to find the remote port based on the WWN provided by the 14666 * caller. We actually ask fp/fctl if it has it. 14667 */ 14668 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14669 (la_wwn_t *)pwwn, &error, 1); 14670 14671 if (pd == NULL) { 14672 kmem_free(devlist, sizeof (*devlist)); 14673 return (rval); 14674 } 14675 14676 /* 14677 * The remote port was found. We ask fp/fctl to update our 14678 * fc_portmap_t structure. 14679 */ 14680 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14681 (la_wwn_t *)pwwn, devlist); 14682 if (ret != FC_SUCCESS) { 14683 kmem_free(devlist, sizeof (*devlist)); 14684 return (rval); 14685 } 14686 14687 /* 14688 * The map flag field is set to indicates that the creation is being 14689 * done at the user request (Ioclt probably luxadm or cfgadm). 14690 */ 14691 devlist->map_type = PORT_DEVICE_USER_CREATE; 14692 14693 mutex_enter(&pptr->port_mutex); 14694 14695 /* 14696 * We check to see if fcp already has a target that describes the 14697 * device being created. If not it is created. 14698 */ 14699 ptgt = fcp_lookup_target(pptr, pwwn); 14700 if (ptgt == NULL) { 14701 lcount = pptr->port_link_cnt; 14702 mutex_exit(&pptr->port_mutex); 14703 14704 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14705 if (ptgt == NULL) { 14706 fcp_log(CE_WARN, pptr->port_dip, 14707 "!FC target allocation failed"); 14708 return (ENOMEM); 14709 } 14710 14711 mutex_enter(&pptr->port_mutex); 14712 } 14713 14714 mutex_enter(&ptgt->tgt_mutex); 14715 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14716 ptgt->tgt_tmp_cnt = 1; 14717 ptgt->tgt_device_created = 0; 14718 /* 14719 * If fabric and auto config is set but the target was 14720 * manually unconfigured then reset to the manual_config_only to 14721 * 0 so the device will get configured. 14722 */ 14723 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14724 fcp_enable_auto_configuration && 14725 ptgt->tgt_manual_config_only == 1) { 14726 old_manual = 1; 14727 ptgt->tgt_manual_config_only = 0; 14728 } 14729 mutex_exit(&ptgt->tgt_mutex); 14730 14731 fcp_update_targets(pptr, devlist, 1, 14732 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14733 14734 lcount = pptr->port_link_cnt; 14735 tcount = ptgt->tgt_change_cnt; 14736 14737 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14738 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14739 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14740 fcp_enable_auto_configuration && old_manual) { 14741 mutex_enter(&ptgt->tgt_mutex); 14742 ptgt->tgt_manual_config_only = 1; 14743 mutex_exit(&ptgt->tgt_mutex); 14744 } 14745 14746 if (pptr->port_link_cnt != lcount || 14747 ptgt->tgt_change_cnt != tcount) { 14748 rval = EBUSY; 14749 } 14750 mutex_exit(&pptr->port_mutex); 14751 14752 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14753 FCP_BUF_LEVEL_3, 0, 14754 "fcp_create_on_demand: mapflags ptgt=%x, " 14755 "lcount=%x::port_link_cnt=%x, " 14756 "tcount=%x: tgt_change_cnt=%x, rval=%x", 14757 ptgt, lcount, pptr->port_link_cnt, 14758 tcount, ptgt->tgt_change_cnt, rval); 14759 return (rval); 14760 } 14761 14762 /* 14763 * Due to lack of synchronization mechanisms, we perform 14764 * periodic monitoring of our request; Because requests 14765 * get dropped when another one supercedes (either because 14766 * of a link change or a target change), it is difficult to 14767 * provide a clean synchronization mechanism (such as a 14768 * semaphore or a conditional variable) without exhaustively 14769 * rewriting the mainline discovery code of this driver. 14770 */ 14771 wait_ms = 500; 14772 14773 ntries = fcp_max_target_retries; 14774 14775 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14776 FCP_BUF_LEVEL_3, 0, 14777 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 14778 "lcount=%x::port_link_cnt=%x, " 14779 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14780 "tgt_tmp_cnt =%x", 14781 ntries, ptgt, lcount, pptr->port_link_cnt, 14782 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14783 ptgt->tgt_tmp_cnt); 14784 14785 mutex_enter(&ptgt->tgt_mutex); 14786 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 14787 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 14788 mutex_exit(&ptgt->tgt_mutex); 14789 mutex_exit(&pptr->port_mutex); 14790 14791 delay(drv_usectohz(wait_ms * 1000)); 14792 14793 mutex_enter(&pptr->port_mutex); 14794 mutex_enter(&ptgt->tgt_mutex); 14795 } 14796 14797 14798 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 14799 rval = EBUSY; 14800 } else { 14801 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 14802 FCP_TGT_NODE_PRESENT) { 14803 rval = 0; 14804 } 14805 } 14806 14807 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14808 FCP_BUF_LEVEL_3, 0, 14809 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 14810 "lcount=%x::port_link_cnt=%x, " 14811 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14812 "tgt_tmp_cnt =%x", 14813 ntries, ptgt, lcount, pptr->port_link_cnt, 14814 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14815 ptgt->tgt_tmp_cnt); 14816 14817 if (rval) { 14818 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14819 fcp_enable_auto_configuration && old_manual) { 14820 ptgt->tgt_manual_config_only = 1; 14821 } 14822 mutex_exit(&ptgt->tgt_mutex); 14823 mutex_exit(&pptr->port_mutex); 14824 kmem_free(devlist, sizeof (*devlist)); 14825 14826 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14827 FCP_BUF_LEVEL_3, 0, 14828 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 14829 "lcount=%x::port_link_cnt=%x, " 14830 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 14831 "tgt_device_created=%x, tgt D_ID=%x", 14832 ntries, ptgt, lcount, pptr->port_link_cnt, 14833 tcount, ptgt->tgt_change_cnt, rval, 14834 ptgt->tgt_device_created, ptgt->tgt_d_id); 14835 return (rval); 14836 } 14837 14838 if ((plun = ptgt->tgt_lun) != NULL) { 14839 tcount = plun->lun_tgt->tgt_change_cnt; 14840 } else { 14841 rval = EINVAL; 14842 } 14843 lcount = pptr->port_link_cnt; 14844 14845 /* 14846 * Configuring the target with no LUNs will fail. We 14847 * should reset the node state so that it is not 14848 * automatically configured when the LUNs are added 14849 * to this target. 14850 */ 14851 if (ptgt->tgt_lun_cnt == 0) { 14852 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 14853 } 14854 mutex_exit(&ptgt->tgt_mutex); 14855 mutex_exit(&pptr->port_mutex); 14856 14857 while (plun) { 14858 child_info_t *cip; 14859 14860 mutex_enter(&plun->lun_mutex); 14861 cip = plun->lun_cip; 14862 mutex_exit(&plun->lun_mutex); 14863 14864 mutex_enter(&ptgt->tgt_mutex); 14865 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 14866 mutex_exit(&ptgt->tgt_mutex); 14867 14868 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 14869 FCP_ONLINE, lcount, tcount, 14870 NDI_ONLINE_ATTACH); 14871 if (rval != NDI_SUCCESS) { 14872 FCP_TRACE(fcp_logq, 14873 pptr->port_instbuf, fcp_trace, 14874 FCP_BUF_LEVEL_3, 0, 14875 "fcp_create_on_demand: " 14876 "pass_to_hp_and_wait failed " 14877 "rval=%x", rval); 14878 rval = EIO; 14879 } else { 14880 mutex_enter(&LUN_TGT->tgt_mutex); 14881 plun->lun_state &= ~(FCP_LUN_OFFLINE | 14882 FCP_LUN_BUSY); 14883 mutex_exit(&LUN_TGT->tgt_mutex); 14884 } 14885 mutex_enter(&ptgt->tgt_mutex); 14886 } 14887 14888 plun = plun->lun_next; 14889 mutex_exit(&ptgt->tgt_mutex); 14890 } 14891 14892 kmem_free(devlist, sizeof (*devlist)); 14893 14894 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14895 fcp_enable_auto_configuration && old_manual) { 14896 mutex_enter(&ptgt->tgt_mutex); 14897 /* if successful then set manual to 0 */ 14898 if (rval == 0) { 14899 ptgt->tgt_manual_config_only = 0; 14900 } else { 14901 /* reset to 1 so the user has to do the config */ 14902 ptgt->tgt_manual_config_only = 1; 14903 } 14904 mutex_exit(&ptgt->tgt_mutex); 14905 } 14906 14907 return (rval); 14908 } 14909 14910 14911 static void 14912 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 14913 { 14914 int count; 14915 uchar_t byte; 14916 14917 count = 0; 14918 while (*string) { 14919 byte = FCP_ATOB(*string); string++; 14920 byte = byte << 4 | FCP_ATOB(*string); string++; 14921 bytes[count++] = byte; 14922 14923 if (count >= byte_len) { 14924 break; 14925 } 14926 } 14927 } 14928 14929 static void 14930 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 14931 { 14932 int i; 14933 14934 for (i = 0; i < FC_WWN_SIZE; i++) { 14935 (void) sprintf(string + (i * 2), 14936 "%02x", wwn[i]); 14937 } 14938 14939 } 14940 14941 static void 14942 fcp_print_error(fc_packet_t *fpkt) 14943 { 14944 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 14945 fpkt->pkt_ulp_private; 14946 struct fcp_port *pptr; 14947 struct fcp_tgt *ptgt; 14948 struct fcp_lun *plun; 14949 caddr_t buf; 14950 int scsi_cmd = 0; 14951 14952 ptgt = icmd->ipkt_tgt; 14953 plun = icmd->ipkt_lun; 14954 pptr = ptgt->tgt_port; 14955 14956 buf = kmem_zalloc(256, KM_NOSLEEP); 14957 if (buf == NULL) { 14958 return; 14959 } 14960 14961 switch (icmd->ipkt_opcode) { 14962 case SCMD_REPORT_LUN: 14963 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 14964 " lun=0x%%x failed"); 14965 scsi_cmd++; 14966 break; 14967 14968 case SCMD_INQUIRY_PAGE83: 14969 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 14970 " lun=0x%%x failed"); 14971 scsi_cmd++; 14972 break; 14973 14974 case SCMD_INQUIRY: 14975 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 14976 " lun=0x%%x failed"); 14977 scsi_cmd++; 14978 break; 14979 14980 case LA_ELS_PLOGI: 14981 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 14982 break; 14983 14984 case LA_ELS_PRLI: 14985 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 14986 break; 14987 } 14988 14989 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 14990 struct fcp_rsp response, *rsp; 14991 uchar_t asc, ascq; 14992 caddr_t sense_key = NULL; 14993 struct fcp_rsp_info fcp_rsp_err, *bep; 14994 14995 if (icmd->ipkt_nodma) { 14996 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 14997 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 14998 sizeof (struct fcp_rsp)); 14999 } else { 15000 rsp = &response; 15001 bep = &fcp_rsp_err; 15002 15003 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15004 sizeof (struct fcp_rsp)); 15005 15006 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15007 bep, fpkt->pkt_resp_acc, 15008 sizeof (struct fcp_rsp_info)); 15009 } 15010 15011 15012 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15013 (void) sprintf(buf + strlen(buf), 15014 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15015 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15016 " senselen=%%x. Giving up"); 15017 15018 fcp_log(CE_WARN, pptr->port_dip, buf, 15019 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15020 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15021 rsp->fcp_u.fcp_status.reserved_1, 15022 rsp->fcp_response_len, rsp->fcp_sense_len); 15023 15024 kmem_free(buf, 256); 15025 return; 15026 } 15027 15028 if (rsp->fcp_u.fcp_status.rsp_len_set && 15029 bep->rsp_code != FCP_NO_FAILURE) { 15030 (void) sprintf(buf + strlen(buf), 15031 " FCP Response code = 0x%x", bep->rsp_code); 15032 } 15033 15034 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15035 struct scsi_extended_sense sense_info, *sense_ptr; 15036 15037 if (icmd->ipkt_nodma) { 15038 sense_ptr = (struct scsi_extended_sense *) 15039 ((caddr_t)fpkt->pkt_resp + 15040 sizeof (struct fcp_rsp) + 15041 rsp->fcp_response_len); 15042 } else { 15043 sense_ptr = &sense_info; 15044 15045 FCP_CP_IN(fpkt->pkt_resp + 15046 sizeof (struct fcp_rsp) + 15047 rsp->fcp_response_len, &sense_info, 15048 fpkt->pkt_resp_acc, 15049 sizeof (struct scsi_extended_sense)); 15050 } 15051 15052 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15053 NUM_IMPL_SENSE_KEYS) { 15054 sense_key = sense_keys[sense_ptr->es_key]; 15055 } else { 15056 sense_key = "Undefined"; 15057 } 15058 15059 asc = sense_ptr->es_add_code; 15060 ascq = sense_ptr->es_qual_code; 15061 15062 (void) sprintf(buf + strlen(buf), 15063 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15064 " Giving up"); 15065 15066 fcp_log(CE_WARN, pptr->port_dip, buf, 15067 ptgt->tgt_d_id, plun->lun_num, sense_key, 15068 asc, ascq); 15069 } else { 15070 (void) sprintf(buf + strlen(buf), 15071 " : SCSI status=%%x. Giving up"); 15072 15073 fcp_log(CE_WARN, pptr->port_dip, buf, 15074 ptgt->tgt_d_id, plun->lun_num, 15075 rsp->fcp_u.fcp_status.scsi_status); 15076 } 15077 } else { 15078 caddr_t state, reason, action, expln; 15079 15080 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15081 &action, &expln); 15082 15083 (void) sprintf(buf + strlen(buf), ": State:%%s," 15084 " Reason:%%s. Giving up"); 15085 15086 if (scsi_cmd) { 15087 fcp_log(CE_WARN, pptr->port_dip, buf, 15088 ptgt->tgt_d_id, plun->lun_num, state, reason); 15089 } else { 15090 fcp_log(CE_WARN, pptr->port_dip, buf, 15091 ptgt->tgt_d_id, state, reason); 15092 } 15093 } 15094 15095 kmem_free(buf, 256); 15096 } 15097 15098 15099 static int 15100 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15101 struct fcp_ipkt *icmd, int rval, caddr_t op) 15102 { 15103 int ret = DDI_FAILURE; 15104 char *error; 15105 15106 switch (rval) { 15107 case FC_DEVICE_BUSY_NEW_RSCN: 15108 /* 15109 * This means that there was a new RSCN that the transport 15110 * knows about (which the ULP *may* know about too) but the 15111 * pkt that was sent down was related to an older RSCN. So, we 15112 * are just going to reset the retry count and deadline and 15113 * continue to retry. The idea is that transport is currently 15114 * working on the new RSCN and will soon let the ULPs know 15115 * about it and when it does the existing logic will kick in 15116 * where it will change the tcount to indicate that something 15117 * changed on the target. So, rediscovery will start and there 15118 * will not be an infinite retry. 15119 * 15120 * For a full flow of how the RSCN info is transferred back and 15121 * forth, see fp.c 15122 */ 15123 icmd->ipkt_retries = 0; 15124 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15125 FCP_ICMD_DEADLINE; 15126 15127 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15128 FCP_BUF_LEVEL_3, 0, 15129 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15130 rval, ptgt->tgt_d_id); 15131 /* FALLTHROUGH */ 15132 15133 case FC_STATEC_BUSY: 15134 case FC_DEVICE_BUSY: 15135 case FC_PBUSY: 15136 case FC_FBUSY: 15137 case FC_TRAN_BUSY: 15138 case FC_OFFLINE: 15139 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15140 FCP_BUF_LEVEL_3, 0, 15141 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15142 rval, ptgt->tgt_d_id); 15143 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15144 fcp_is_retryable(icmd)) { 15145 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15146 ret = DDI_SUCCESS; 15147 } 15148 break; 15149 15150 case FC_LOGINREQ: 15151 /* 15152 * FC_LOGINREQ used to be handled just like all the cases 15153 * above. It has been changed to handled a PRLI that fails 15154 * with FC_LOGINREQ different than other ipkts that fail 15155 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15156 * a simple matter to turn it into a PLOGI instead, so that's 15157 * exactly what we do here. 15158 */ 15159 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15160 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15161 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15162 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15163 } else { 15164 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15165 FCP_BUF_LEVEL_3, 0, 15166 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15167 rval, ptgt->tgt_d_id); 15168 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15169 fcp_is_retryable(icmd)) { 15170 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15171 ret = DDI_SUCCESS; 15172 } 15173 } 15174 break; 15175 15176 default: 15177 mutex_enter(&pptr->port_mutex); 15178 mutex_enter(&ptgt->tgt_mutex); 15179 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15180 mutex_exit(&ptgt->tgt_mutex); 15181 mutex_exit(&pptr->port_mutex); 15182 15183 (void) fc_ulp_error(rval, &error); 15184 fcp_log(CE_WARN, pptr->port_dip, 15185 "!Failed to send %s to D_ID=%x error=%s", 15186 op, ptgt->tgt_d_id, error); 15187 } else { 15188 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15189 fcp_trace, FCP_BUF_LEVEL_2, 0, 15190 "fcp_handle_ipkt_errors,1: state change occured" 15191 " for D_ID=0x%x", ptgt->tgt_d_id); 15192 mutex_exit(&ptgt->tgt_mutex); 15193 mutex_exit(&pptr->port_mutex); 15194 } 15195 break; 15196 } 15197 15198 return (ret); 15199 } 15200 15201 15202 /* 15203 * Check of outstanding commands on any LUN for this target 15204 */ 15205 static int 15206 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15207 { 15208 struct fcp_lun *plun; 15209 struct fcp_pkt *cmd; 15210 15211 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15212 mutex_enter(&plun->lun_mutex); 15213 for (cmd = plun->lun_pkt_head; cmd != NULL; 15214 cmd = cmd->cmd_forw) { 15215 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15216 mutex_exit(&plun->lun_mutex); 15217 return (FC_SUCCESS); 15218 } 15219 } 15220 mutex_exit(&plun->lun_mutex); 15221 } 15222 15223 return (FC_FAILURE); 15224 } 15225 15226 static fc_portmap_t * 15227 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15228 { 15229 int i; 15230 fc_portmap_t *devlist; 15231 fc_portmap_t *devptr = NULL; 15232 struct fcp_tgt *ptgt; 15233 15234 mutex_enter(&pptr->port_mutex); 15235 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15236 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15237 ptgt = ptgt->tgt_next) { 15238 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15239 ++*dev_cnt; 15240 } 15241 } 15242 } 15243 15244 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15245 KM_NOSLEEP); 15246 if (devlist == NULL) { 15247 mutex_exit(&pptr->port_mutex); 15248 fcp_log(CE_WARN, pptr->port_dip, 15249 "!fcp%d: failed to allocate for portmap for construct map", 15250 pptr->port_instance); 15251 return (devptr); 15252 } 15253 15254 for (i = 0; i < FCP_NUM_HASH; i++) { 15255 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15256 ptgt = ptgt->tgt_next) { 15257 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15258 int ret; 15259 15260 ret = fc_ulp_pwwn_to_portmap( 15261 pptr->port_fp_handle, 15262 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15263 devlist); 15264 15265 if (ret == FC_SUCCESS) { 15266 devlist++; 15267 continue; 15268 } 15269 15270 devlist->map_pd = NULL; 15271 devlist->map_did.port_id = ptgt->tgt_d_id; 15272 devlist->map_hard_addr.hard_addr = 15273 ptgt->tgt_hard_addr; 15274 15275 devlist->map_state = PORT_DEVICE_INVALID; 15276 devlist->map_type = PORT_DEVICE_OLD; 15277 15278 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15279 &devlist->map_nwwn, FC_WWN_SIZE); 15280 15281 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15282 &devlist->map_pwwn, FC_WWN_SIZE); 15283 15284 devlist++; 15285 } 15286 } 15287 } 15288 15289 mutex_exit(&pptr->port_mutex); 15290 15291 return (devptr); 15292 } 15293 /* 15294 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15295 */ 15296 static void 15297 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15298 { 15299 int i; 15300 struct fcp_tgt *ptgt; 15301 struct fcp_lun *plun; 15302 15303 for (i = 0; i < FCP_NUM_HASH; i++) { 15304 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15305 ptgt = ptgt->tgt_next) { 15306 mutex_enter(&ptgt->tgt_mutex); 15307 for (plun = ptgt->tgt_lun; plun != NULL; 15308 plun = plun->lun_next) { 15309 if (plun->lun_mpxio && 15310 plun->lun_state & FCP_LUN_BUSY) { 15311 if (!fcp_pass_to_hp(pptr, plun, 15312 plun->lun_cip, 15313 FCP_MPXIO_PATH_SET_BUSY, 15314 pptr->port_link_cnt, 15315 ptgt->tgt_change_cnt, 0, 0)) { 15316 FCP_TRACE(fcp_logq, 15317 pptr->port_instbuf, 15318 fcp_trace, 15319 FCP_BUF_LEVEL_2, 0, 15320 "path_verifybusy: " 15321 "disable lun %p failed!", 15322 plun); 15323 } 15324 } 15325 } 15326 mutex_exit(&ptgt->tgt_mutex); 15327 } 15328 } 15329 } 15330 15331 static int 15332 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15333 { 15334 dev_info_t *cdip = NULL; 15335 dev_info_t *pdip = NULL; 15336 15337 ASSERT(plun); 15338 15339 mutex_enter(&plun->lun_mutex); 15340 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15341 mutex_exit(&plun->lun_mutex); 15342 return (NDI_FAILURE); 15343 } 15344 mutex_exit(&plun->lun_mutex); 15345 cdip = mdi_pi_get_client(PIP(cip)); 15346 pdip = mdi_pi_get_phci(PIP(cip)); 15347 15348 ASSERT(cdip != NULL); 15349 ASSERT(pdip != NULL); 15350 15351 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15352 /* LUN ready for IO */ 15353 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15354 } else { 15355 /* LUN busy to accept IO */ 15356 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15357 } 15358 return (NDI_SUCCESS); 15359 } 15360 15361 /* 15362 * Caller must free the returned string of MAXPATHLEN len 15363 * If the device is offline (-1 instance number) NULL 15364 * will be returned. 15365 */ 15366 static char * 15367 fcp_get_lun_path(struct fcp_lun *plun) { 15368 dev_info_t *dip = NULL; 15369 char *path = NULL; 15370 if (plun == NULL) { 15371 return (NULL); 15372 } 15373 if (plun->lun_mpxio == 0) { 15374 dip = DIP(plun->lun_cip); 15375 } else { 15376 dip = mdi_pi_get_client(PIP(plun->lun_cip)); 15377 } 15378 if (dip == NULL) { 15379 return (NULL); 15380 } 15381 if (ddi_get_instance(dip) < 0) { 15382 return (NULL); 15383 } 15384 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15385 if (path == NULL) { 15386 return (NULL); 15387 } 15388 15389 (void) ddi_pathname(dip, path); 15390 /* 15391 * In reality, the user wants a fully valid path (one they can open) 15392 * but this string is lacking the mount point, and the minor node. 15393 * It would be nice if we could "figure these out" somehow 15394 * and fill them in. Otherwise, the userland code has to understand 15395 * driver specific details of which minor node is the "best" or 15396 * "right" one to expose. (Ex: which slice is the whole disk, or 15397 * which tape doesn't rewind) 15398 */ 15399 return (path); 15400 } 15401 15402 static int 15403 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15404 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15405 { 15406 int64_t reset_delay; 15407 int rval, retry = 0; 15408 struct fcp_port *pptr = fcp_dip2port(parent); 15409 15410 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15411 (lbolt64 - pptr->port_attach_time); 15412 if (reset_delay < 0) 15413 reset_delay = 0; 15414 15415 if (fcp_bus_config_debug) 15416 flag |= NDI_DEVI_DEBUG; 15417 15418 switch (op) { 15419 case BUS_CONFIG_ONE: 15420 /* 15421 * Retry the command since we need to ensure 15422 * the fabric devices are available for root 15423 */ 15424 while (retry++ < fcp_max_bus_config_retries) { 15425 rval = (ndi_busop_bus_config(parent, 15426 flag | NDI_MDI_FALLBACK, op, 15427 arg, childp, (clock_t)reset_delay)); 15428 if (rval == 0) 15429 return (rval); 15430 } 15431 15432 /* 15433 * drain taskq to make sure nodes are created and then 15434 * try again. 15435 */ 15436 taskq_wait(DEVI(parent)->devi_taskq); 15437 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15438 op, arg, childp, 0)); 15439 15440 case BUS_CONFIG_DRIVER: 15441 case BUS_CONFIG_ALL: { 15442 /* 15443 * delay till all devices report in (port_tmp_cnt == 0) 15444 * or FCP_INIT_WAIT_TIMEOUT 15445 */ 15446 mutex_enter(&pptr->port_mutex); 15447 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15448 (void) cv_timedwait(&pptr->port_config_cv, 15449 &pptr->port_mutex, 15450 ddi_get_lbolt() + (clock_t)reset_delay); 15451 reset_delay = 15452 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15453 (lbolt64 - pptr->port_attach_time); 15454 } 15455 mutex_exit(&pptr->port_mutex); 15456 /* drain taskq to make sure nodes are created */ 15457 taskq_wait(DEVI(parent)->devi_taskq); 15458 return (ndi_busop_bus_config(parent, flag, op, 15459 arg, childp, 0)); 15460 } 15461 15462 default: 15463 return (NDI_FAILURE); 15464 } 15465 /*NOTREACHED*/ 15466 } 15467 15468 static int 15469 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15470 ddi_bus_config_op_t op, void *arg) 15471 { 15472 if (fcp_bus_config_debug) 15473 flag |= NDI_DEVI_DEBUG; 15474 15475 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15476 } 15477 15478 15479 /* 15480 * Routine to copy GUID into the lun structure. 15481 * returns 0 if copy was successful and 1 if encountered a 15482 * failure and did not copy the guid. 15483 */ 15484 static int 15485 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15486 { 15487 15488 int retval = 0; 15489 15490 /* add one for the null terminator */ 15491 const unsigned int len = strlen(guidp) + 1; 15492 15493 if ((guidp == NULL) || (plun == NULL)) { 15494 return (1); 15495 } 15496 15497 /* 15498 * if the plun->lun_guid already has been allocated, 15499 * then check the size. if the size is exact, reuse 15500 * it....if not free it an allocate the required size. 15501 * The reallocation should NOT typically happen 15502 * unless the GUIDs reported changes between passes. 15503 * We free up and alloc again even if the 15504 * size was more than required. This is due to the 15505 * fact that the field lun_guid_size - serves 15506 * dual role of indicating the size of the wwn 15507 * size and ALSO the allocation size. 15508 */ 15509 if (plun->lun_guid) { 15510 if (plun->lun_guid_size != len) { 15511 /* 15512 * free the allocated memory and 15513 * initialize the field 15514 * lun_guid_size to 0. 15515 */ 15516 kmem_free(plun->lun_guid, plun->lun_guid_size); 15517 plun->lun_guid = NULL; 15518 plun->lun_guid_size = 0; 15519 } 15520 } 15521 /* 15522 * alloc only if not already done. 15523 */ 15524 if (plun->lun_guid == NULL) { 15525 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15526 if (plun->lun_guid == NULL) { 15527 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15528 "Unable to allocate" 15529 "Memory for GUID!!! size %d", len); 15530 retval = 1; 15531 } else { 15532 plun->lun_guid_size = len; 15533 } 15534 } 15535 if (plun->lun_guid) { 15536 /* 15537 * now copy the GUID 15538 */ 15539 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15540 } 15541 return (retval); 15542 } 15543 15544 /* 15545 * fcp_reconfig_wait 15546 * 15547 * Wait for a rediscovery/reconfiguration to complete before continuing. 15548 */ 15549 15550 static void 15551 fcp_reconfig_wait(struct fcp_port *pptr) 15552 { 15553 clock_t reconfig_start, wait_timeout; 15554 15555 /* 15556 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15557 * reconfiguration in progress. 15558 */ 15559 15560 mutex_enter(&pptr->port_mutex); 15561 if (pptr->port_tmp_cnt == 0) { 15562 mutex_exit(&pptr->port_mutex); 15563 return; 15564 } 15565 mutex_exit(&pptr->port_mutex); 15566 15567 /* 15568 * If we cause a reconfig by raising power, delay until all devices 15569 * report in (port_tmp_cnt returns to 0) 15570 */ 15571 15572 reconfig_start = ddi_get_lbolt(); 15573 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15574 15575 mutex_enter(&pptr->port_mutex); 15576 15577 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15578 pptr->port_tmp_cnt) { 15579 15580 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15581 reconfig_start + wait_timeout); 15582 } 15583 15584 mutex_exit(&pptr->port_mutex); 15585 15586 /* 15587 * Even if fcp_tmp_count isn't 0, continue without error. The port 15588 * we want may still be ok. If not, it will error out later 15589 */ 15590 } 15591 15592 /* 15593 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15594 * We rely on the fcp_global_mutex to provide protection against changes to 15595 * the fcp_lun_blacklist. 15596 * 15597 * You can describe a list of target port WWNs and LUN numbers which will 15598 * not be configured. LUN numbers will be interpreted as decimal. White 15599 * spaces and ',' can be used in the list of LUN numbers. 15600 * 15601 * To prevent LUNs 1 and 2 from being configured for target 15602 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15603 * 15604 * pwwn-lun-blacklist= 15605 * "510000f010fd92a1,1,2", 15606 * "510000e012079df1,1,2"; 15607 */ 15608 static void 15609 fcp_read_blacklist(dev_info_t *dip, 15610 struct fcp_black_list_entry **pplun_blacklist) { 15611 char **prop_array = NULL; 15612 char *curr_pwwn = NULL; 15613 char *curr_lun = NULL; 15614 uint32_t prop_item = 0; 15615 int idx = 0; 15616 int len = 0; 15617 15618 ASSERT(mutex_owned(&fcp_global_mutex)); 15619 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15620 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15621 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15622 return; 15623 } 15624 15625 for (idx = 0; idx < prop_item; idx++) { 15626 15627 curr_pwwn = prop_array[idx]; 15628 while (*curr_pwwn == ' ') { 15629 curr_pwwn++; 15630 } 15631 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15632 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15633 ", please check.", curr_pwwn); 15634 continue; 15635 } 15636 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15637 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15638 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15639 ", please check.", curr_pwwn); 15640 continue; 15641 } 15642 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15643 if (isxdigit(curr_pwwn[len]) != TRUE) { 15644 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15645 "blacklist, please check.", curr_pwwn); 15646 break; 15647 } 15648 } 15649 if (len != sizeof (la_wwn_t) * 2) { 15650 continue; 15651 } 15652 15653 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15654 *(curr_lun - 1) = '\0'; 15655 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15656 } 15657 15658 ddi_prop_free(prop_array); 15659 } 15660 15661 /* 15662 * Get the masking info about one remote target port designated by wwn. 15663 * Lun ids could be separated by ',' or white spaces. 15664 */ 15665 static void 15666 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15667 struct fcp_black_list_entry **pplun_blacklist) { 15668 int idx = 0; 15669 uint32_t offset = 0; 15670 unsigned long lun_id = 0; 15671 char lunid_buf[16]; 15672 char *pend = NULL; 15673 int illegal_digit = 0; 15674 15675 while (offset < strlen(curr_lun)) { 15676 while ((curr_lun[offset + idx] != ',') && 15677 (curr_lun[offset + idx] != '\0') && 15678 (curr_lun[offset + idx] != ' ')) { 15679 if (isdigit(curr_lun[offset + idx]) == 0) { 15680 illegal_digit++; 15681 } 15682 idx++; 15683 } 15684 if (illegal_digit > 0) { 15685 offset += (idx+1); /* To the start of next lun */ 15686 idx = 0; 15687 illegal_digit = 0; 15688 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15689 "the blacklist, please check digits.", 15690 curr_lun, curr_pwwn); 15691 continue; 15692 } 15693 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15694 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15695 "the blacklist, please check the length of LUN#.", 15696 curr_lun, curr_pwwn); 15697 break; 15698 } 15699 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15700 offset++; 15701 continue; 15702 } 15703 15704 bcopy(curr_lun + offset, lunid_buf, idx); 15705 lunid_buf[idx] = '\0'; 15706 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15707 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15708 } else { 15709 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15710 "the blacklist, please check %s.", 15711 curr_lun, curr_pwwn, lunid_buf); 15712 } 15713 offset += (idx+1); /* To the start of next lun */ 15714 idx = 0; 15715 } 15716 } 15717 15718 /* 15719 * Add one masking record 15720 */ 15721 static void 15722 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 15723 struct fcp_black_list_entry **pplun_blacklist) { 15724 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15725 struct fcp_black_list_entry *new_entry = NULL; 15726 la_wwn_t wwn; 15727 15728 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 15729 while (tmp_entry) { 15730 if ((bcmp(&tmp_entry->wwn, &wwn, 15731 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 15732 return; 15733 } 15734 15735 tmp_entry = tmp_entry->next; 15736 } 15737 15738 /* add to black list */ 15739 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 15740 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 15741 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 15742 new_entry->lun = lun_id; 15743 new_entry->masked = 0; 15744 new_entry->next = *pplun_blacklist; 15745 *pplun_blacklist = new_entry; 15746 } 15747 15748 /* 15749 * Check if we should mask the specified lun of this fcp_tgt 15750 */ 15751 static int 15752 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 15753 struct fcp_black_list_entry *remote_port; 15754 15755 remote_port = fcp_lun_blacklist; 15756 while (remote_port != NULL) { 15757 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 15758 if (remote_port->lun == lun_id) { 15759 remote_port->masked++; 15760 if (remote_port->masked == 1) { 15761 fcp_log(CE_NOTE, NULL, "LUN %d of port " 15762 "%02x%02x%02x%02x%02x%02x%02x%02x is masked due to black listing.\n", 15763 lun_id, wwn->raw_wwn[0], wwn->raw_wwn[1], wwn->raw_wwn[2], 15764 wwn->raw_wwn[3], wwn->raw_wwn[4], wwn->raw_wwn[5], wwn->raw_wwn[6], 15765 wwn->raw_wwn[7]); 15766 } 15767 return (TRUE); 15768 } 15769 } 15770 remote_port = remote_port->next; 15771 } 15772 return (FALSE); 15773 } 15774 15775 /* 15776 * Release all allocated resources 15777 */ 15778 static void 15779 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 15780 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15781 struct fcp_black_list_entry *current_entry = NULL; 15782 15783 ASSERT(mutex_owned(&fcp_global_mutex)); 15784 /* 15785 * Traverse all luns 15786 */ 15787 while (tmp_entry) { 15788 current_entry = tmp_entry; 15789 tmp_entry = tmp_entry->next; 15790 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 15791 } 15792 *pplun_blacklist = NULL; 15793 } 15794