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 2010 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_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause); 431 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 432 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 433 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 434 int cause); 435 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 436 uint32_t state); 437 static struct fcp_port *fcp_get_port(opaque_t port_handle); 438 static void fcp_unsol_callback(fc_packet_t *fpkt); 439 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 440 uchar_t r_ctl, uchar_t type); 441 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 442 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 443 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 444 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 445 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 446 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 447 int nodma, int flags); 448 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 449 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 450 uchar_t *wwn); 451 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 452 uint32_t d_id); 453 static void fcp_icmd_callback(fc_packet_t *fpkt); 454 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 455 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 456 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 457 static void fcp_scsi_callback(fc_packet_t *fpkt); 458 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 459 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 460 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 461 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 462 uint16_t lun_num); 463 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 464 int link_cnt, int tgt_cnt, int cause); 465 static void fcp_finish_init(struct fcp_port *pptr); 466 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 467 int tgt_cnt, int cause); 468 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 469 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 470 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 471 int link_cnt, int tgt_cnt, int nowait, int flags); 472 static void fcp_offline_target_now(struct fcp_port *pptr, 473 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 474 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 475 int tgt_cnt, int flags); 476 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 477 int nowait, int flags); 478 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 479 int tgt_cnt); 480 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 481 int tgt_cnt, int flags); 482 static void fcp_scan_offline_luns(struct fcp_port *pptr); 483 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 484 static void fcp_update_offline_flags(struct fcp_lun *plun); 485 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 486 static void fcp_abort_commands(struct fcp_pkt *head, struct 487 fcp_port *pptr); 488 static void fcp_cmd_callback(fc_packet_t *fpkt); 489 static void fcp_complete_pkt(fc_packet_t *fpkt); 490 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 491 struct fcp_port *pptr); 492 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 493 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 494 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 495 static void fcp_dealloc_lun(struct fcp_lun *plun); 496 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 497 fc_portmap_t *map_entry, int link_cnt); 498 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 499 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 500 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 501 int internal); 502 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 503 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 504 uint32_t s_id, int instance); 505 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 506 int instance); 507 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 508 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 509 int); 510 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 511 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 512 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 513 int flags); 514 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 515 static int fcp_reset_target(struct scsi_address *ap, int level); 516 static int fcp_commoncap(struct scsi_address *ap, char *cap, 517 int val, int tgtonly, int doset); 518 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 519 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 520 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 521 int sleep); 522 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 523 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 524 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 525 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 526 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 527 int lcount, int tcount); 528 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 529 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 530 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 531 int tgt_cnt); 532 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 533 dev_info_t *pdip, caddr_t name); 534 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 535 int lcount, int tcount, int flags, int *circ); 536 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 537 int lcount, int tcount, int flags, int *circ); 538 static void fcp_remove_child(struct fcp_lun *plun); 539 static void fcp_watch(void *arg); 540 static void fcp_check_reset_delay(struct fcp_port *pptr); 541 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 542 struct fcp_lun *rlun, int tgt_cnt); 543 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 544 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 545 uchar_t *wwn, uint16_t lun); 546 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 547 struct fcp_lun *plun); 548 static void fcp_post_callback(struct fcp_pkt *cmd); 549 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 550 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 551 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 552 child_info_t *cip); 553 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 554 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 555 int tgt_cnt, int flags); 556 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 557 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 558 int tgt_cnt, int flags, int wait); 559 static void fcp_retransport_cmd(struct fcp_port *pptr, 560 struct fcp_pkt *cmd); 561 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 562 uint_t statistics); 563 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 564 static void fcp_update_targets(struct fcp_port *pptr, 565 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 566 static int fcp_call_finish_init(struct fcp_port *pptr, 567 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 568 static int fcp_call_finish_init_held(struct fcp_port *pptr, 569 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 570 static void fcp_reconfigure_luns(void * tgt_handle); 571 static void fcp_free_targets(struct fcp_port *pptr); 572 static void fcp_free_target(struct fcp_tgt *ptgt); 573 static int fcp_is_retryable(struct fcp_ipkt *icmd); 574 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 575 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 576 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 577 static void fcp_print_error(fc_packet_t *fpkt); 578 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 579 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 580 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 581 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 582 uint32_t *dev_cnt); 583 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 584 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 585 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 586 struct fcp_ioctl *, struct fcp_port **); 587 static char *fcp_get_lun_path(struct fcp_lun *plun); 588 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 589 int *rval); 590 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 591 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 592 static char *fcp_get_lun_path(struct fcp_lun *plun); 593 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 594 int *rval); 595 static void fcp_reconfig_wait(struct fcp_port *pptr); 596 597 /* 598 * New functions added for mpxio support 599 */ 600 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 601 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 602 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 603 int tcount); 604 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 605 dev_info_t *pdip); 606 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 607 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 608 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 609 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 610 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 611 int what); 612 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 613 fc_packet_t *fpkt); 614 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 615 616 /* 617 * New functions added for lun masking support 618 */ 619 static void fcp_read_blacklist(dev_info_t *dip, 620 struct fcp_black_list_entry **pplun_blacklist); 621 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 622 struct fcp_black_list_entry **pplun_blacklist); 623 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 624 struct fcp_black_list_entry **pplun_blacklist); 625 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 626 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 627 628 /* 629 * New functions to support software FCA (like fcoei) 630 */ 631 static struct scsi_pkt *fcp_pseudo_init_pkt( 632 struct scsi_address *ap, struct scsi_pkt *pkt, 633 struct buf *bp, int cmdlen, int statuslen, 634 int tgtlen, int flags, int (*callback)(), caddr_t arg); 635 static void fcp_pseudo_destroy_pkt( 636 struct scsi_address *ap, struct scsi_pkt *pkt); 637 static void fcp_pseudo_sync_pkt( 638 struct scsi_address *ap, struct scsi_pkt *pkt); 639 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt); 640 static void fcp_pseudo_dmafree( 641 struct scsi_address *ap, struct scsi_pkt *pkt); 642 643 extern struct mod_ops mod_driverops; 644 /* 645 * This variable is defined in modctl.c and set to '1' after the root driver 646 * and fs are loaded. It serves as an indication that the root filesystem can 647 * be used. 648 */ 649 extern int modrootloaded; 650 /* 651 * This table contains strings associated with the SCSI sense key codes. It 652 * is used by FCP to print a clear explanation of the code returned in the 653 * sense information by a device. 654 */ 655 extern char *sense_keys[]; 656 /* 657 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 658 * under this device that the paths to a physical device are created when 659 * MPxIO is used. 660 */ 661 extern dev_info_t *scsi_vhci_dip; 662 663 /* 664 * Report lun processing 665 */ 666 #define FCP_LUN_ADDRESSING 0x80 667 #define FCP_PD_ADDRESSING 0x00 668 #define FCP_VOLUME_ADDRESSING 0x40 669 670 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 671 #define MAX_INT_DMA 0x7fffffff 672 /* 673 * Property definitions 674 */ 675 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 676 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 677 #define TARGET_PROP (char *)fcp_target_prop 678 #define LUN_PROP (char *)fcp_lun_prop 679 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 680 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 681 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 682 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 683 #define INIT_PORT_PROP (char *)fcp_init_port_prop 684 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 685 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 686 /* 687 * Short hand macros. 688 */ 689 #define LUN_PORT (plun->lun_tgt->tgt_port) 690 #define LUN_TGT (plun->lun_tgt) 691 692 /* 693 * Driver private macros 694 */ 695 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 696 ((x) >= 'a' && (x) <= 'f') ? \ 697 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 698 699 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 700 701 #define FCP_N_NDI_EVENTS \ 702 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 703 704 #define FCP_LINK_STATE_CHANGED(p, c) \ 705 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 706 707 #define FCP_TGT_STATE_CHANGED(t, c) \ 708 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 709 710 #define FCP_STATE_CHANGED(p, t, c) \ 711 (FCP_TGT_STATE_CHANGED(t, c)) 712 713 #define FCP_MUST_RETRY(fpkt) \ 714 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 715 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 716 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 717 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 718 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 719 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 720 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 721 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 722 723 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 724 ((es)->es_key == KEY_UNIT_ATTENTION && \ 725 (es)->es_add_code == 0x3f && \ 726 (es)->es_qual_code == 0x0e) 727 728 #define FCP_SENSE_NO_LUN(es) \ 729 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 730 (es)->es_add_code == 0x25 && \ 731 (es)->es_qual_code == 0x0) 732 733 #define FCP_VERSION "20091208-1.192" 734 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 735 736 #define FCP_NUM_ELEMENTS(array) \ 737 (sizeof (array) / sizeof ((array)[0])) 738 739 /* 740 * Debugging, Error reporting, and tracing 741 */ 742 #define FCP_LOG_SIZE 1024 * 1024 743 744 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 745 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 746 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 747 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 748 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 749 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 750 #define FCP_LEVEL_7 0x00040 751 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 752 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 753 754 755 756 /* 757 * Log contents to system messages file 758 */ 759 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 760 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 761 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 762 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 763 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 764 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 765 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 766 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 767 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 768 769 770 /* 771 * Log contents to trace buffer 772 */ 773 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 774 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 775 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 776 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 777 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 778 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 779 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 780 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 781 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 782 783 784 /* 785 * Log contents to both system messages file and trace buffer 786 */ 787 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 788 FC_TRACE_LOG_MSG) 789 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 790 FC_TRACE_LOG_MSG) 791 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 792 FC_TRACE_LOG_MSG) 793 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 794 FC_TRACE_LOG_MSG) 795 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 796 FC_TRACE_LOG_MSG) 797 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 798 FC_TRACE_LOG_MSG) 799 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 800 FC_TRACE_LOG_MSG) 801 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 802 FC_TRACE_LOG_MSG) 803 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 804 FC_TRACE_LOG_MSG) 805 #ifdef DEBUG 806 #define FCP_DTRACE fc_trace_debug 807 #else 808 #define FCP_DTRACE 809 #endif 810 811 #define FCP_TRACE fc_trace_debug 812 813 static struct cb_ops fcp_cb_ops = { 814 fcp_open, /* open */ 815 fcp_close, /* close */ 816 nodev, /* strategy */ 817 nodev, /* print */ 818 nodev, /* dump */ 819 nodev, /* read */ 820 nodev, /* write */ 821 fcp_ioctl, /* ioctl */ 822 nodev, /* devmap */ 823 nodev, /* mmap */ 824 nodev, /* segmap */ 825 nochpoll, /* chpoll */ 826 ddi_prop_op, /* cb_prop_op */ 827 0, /* streamtab */ 828 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 829 CB_REV, /* rev */ 830 nodev, /* aread */ 831 nodev /* awrite */ 832 }; 833 834 835 static struct dev_ops fcp_ops = { 836 DEVO_REV, 837 0, 838 ddi_getinfo_1to1, 839 nulldev, /* identify */ 840 nulldev, /* probe */ 841 fcp_attach, /* attach and detach are mandatory */ 842 fcp_detach, 843 nodev, /* reset */ 844 &fcp_cb_ops, /* cb_ops */ 845 NULL, /* bus_ops */ 846 NULL, /* power */ 847 }; 848 849 850 char *fcp_version = FCP_NAME_VERSION; 851 852 static struct modldrv modldrv = { 853 &mod_driverops, 854 FCP_NAME_VERSION, 855 &fcp_ops 856 }; 857 858 859 static struct modlinkage modlinkage = { 860 MODREV_1, 861 &modldrv, 862 NULL 863 }; 864 865 866 static fc_ulp_modinfo_t fcp_modinfo = { 867 &fcp_modinfo, /* ulp_handle */ 868 FCTL_ULP_MODREV_4, /* ulp_rev */ 869 FC4_SCSI_FCP, /* ulp_type */ 870 "fcp", /* ulp_name */ 871 FCP_STATEC_MASK, /* ulp_statec_mask */ 872 fcp_port_attach, /* ulp_port_attach */ 873 fcp_port_detach, /* ulp_port_detach */ 874 fcp_port_ioctl, /* ulp_port_ioctl */ 875 fcp_els_callback, /* ulp_els_callback */ 876 fcp_data_callback, /* ulp_data_callback */ 877 fcp_statec_callback /* ulp_statec_callback */ 878 }; 879 880 #ifdef DEBUG 881 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 882 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 883 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 884 FCP_LEVEL_6 | FCP_LEVEL_7) 885 #else 886 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 887 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 888 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 889 FCP_LEVEL_6 | FCP_LEVEL_7) 890 #endif 891 892 /* FCP global variables */ 893 int fcp_bus_config_debug = 0; 894 static int fcp_log_size = FCP_LOG_SIZE; 895 static int fcp_trace = FCP_TRACE_DEFAULT; 896 static fc_trace_logq_t *fcp_logq = NULL; 897 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 898 /* 899 * The auto-configuration is set by default. The only way of disabling it is 900 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 901 */ 902 static int fcp_enable_auto_configuration = 1; 903 static int fcp_max_bus_config_retries = 4; 904 static int fcp_lun_ready_retry = 300; 905 /* 906 * The value assigned to the following variable has changed several times due 907 * to a problem with the data underruns reporting of some firmware(s). The 908 * current value of 50 gives a timeout value of 25 seconds for a max number 909 * of 256 LUNs. 910 */ 911 static int fcp_max_target_retries = 50; 912 /* 913 * Watchdog variables 914 * ------------------ 915 * 916 * fcp_watchdog_init 917 * 918 * Indicates if the watchdog timer is running or not. This is actually 919 * a counter of the number of Fibre Channel ports that attached. When 920 * the first port attaches the watchdog is started. When the last port 921 * detaches the watchdog timer is stopped. 922 * 923 * fcp_watchdog_time 924 * 925 * This is the watchdog clock counter. It is incremented by 926 * fcp_watchdog_time each time the watchdog timer expires. 927 * 928 * fcp_watchdog_timeout 929 * 930 * Increment value of the variable fcp_watchdog_time as well as the 931 * the timeout value of the watchdog timer. The unit is 1 second. It 932 * is strange that this is not a #define but a variable since the code 933 * never changes this value. The reason why it can be said that the 934 * unit is 1 second is because the number of ticks for the watchdog 935 * timer is determined like this: 936 * 937 * fcp_watchdog_tick = fcp_watchdog_timeout * 938 * drv_usectohz(1000000); 939 * 940 * The value 1000000 is hard coded in the code. 941 * 942 * fcp_watchdog_tick 943 * 944 * Watchdog timer value in ticks. 945 */ 946 static int fcp_watchdog_init = 0; 947 static int fcp_watchdog_time = 0; 948 static int fcp_watchdog_timeout = 1; 949 static int fcp_watchdog_tick; 950 951 /* 952 * fcp_offline_delay is a global variable to enable customisation of 953 * the timeout on link offlines or RSCNs. The default value is set 954 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 955 * specified in FCP4 Chapter 11 (see www.t10.org). 956 * 957 * The variable fcp_offline_delay is specified in SECONDS. 958 * 959 * If we made this a static var then the user would not be able to 960 * change it. This variable is set in fcp_attach(). 961 */ 962 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 963 964 static void *fcp_softstate = NULL; /* for soft state */ 965 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 966 static kmutex_t fcp_global_mutex; 967 static kmutex_t fcp_ioctl_mutex; 968 static dev_info_t *fcp_global_dip = NULL; 969 static timeout_id_t fcp_watchdog_id; 970 const char *fcp_lun_prop = "lun"; 971 const char *fcp_sam_lun_prop = "sam-lun"; 972 const char *fcp_target_prop = "target"; 973 /* 974 * NOTE: consumers of "node-wwn" property include stmsboot in ON 975 * consolidation. 976 */ 977 const char *fcp_node_wwn_prop = "node-wwn"; 978 const char *fcp_port_wwn_prop = "port-wwn"; 979 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 980 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 981 const char *fcp_manual_config_only = "manual_configuration_only"; 982 const char *fcp_init_port_prop = "initiator-port"; 983 const char *fcp_tgt_port_prop = "target-port"; 984 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 985 986 static struct fcp_port *fcp_port_head = NULL; 987 static ddi_eventcookie_t fcp_insert_eid; 988 static ddi_eventcookie_t fcp_remove_eid; 989 990 static ndi_event_definition_t fcp_ndi_event_defs[] = { 991 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 992 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 993 }; 994 995 /* 996 * List of valid commands for the scsi_ioctl call 997 */ 998 static uint8_t scsi_ioctl_list[] = { 999 SCMD_INQUIRY, 1000 SCMD_REPORT_LUN, 1001 SCMD_READ_CAPACITY 1002 }; 1003 1004 /* 1005 * this is used to dummy up a report lun response for cases 1006 * where the target doesn't support it 1007 */ 1008 static uchar_t fcp_dummy_lun[] = { 1009 0x00, /* MSB length (length = no of luns * 8) */ 1010 0x00, 1011 0x00, 1012 0x08, /* LSB length */ 1013 0x00, /* MSB reserved */ 1014 0x00, 1015 0x00, 1016 0x00, /* LSB reserved */ 1017 FCP_PD_ADDRESSING, 1018 0x00, /* LUN is ZERO at the first level */ 1019 0x00, 1020 0x00, /* second level is zero */ 1021 0x00, 1022 0x00, /* third level is zero */ 1023 0x00, 1024 0x00 /* fourth level is zero */ 1025 }; 1026 1027 static uchar_t fcp_alpa_to_switch[] = { 1028 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1029 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1030 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1031 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1032 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1033 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1034 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1035 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1036 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1037 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1038 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1039 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1040 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1041 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1042 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1043 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1044 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1045 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1046 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1047 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1048 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1049 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1050 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1051 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1052 }; 1053 1054 static caddr_t pid = "SESS01 "; 1055 1056 #if !defined(lint) 1057 1058 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1059 fcp_port::fcp_next fcp_watchdog_id)) 1060 1061 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1062 1063 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1064 fcp_insert_eid 1065 fcp_remove_eid 1066 fcp_watchdog_time)) 1067 1068 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1069 fcp_cb_ops 1070 fcp_ops 1071 callb_cpr)) 1072 1073 #endif /* lint */ 1074 1075 /* 1076 * This table is used to determine whether or not it's safe to copy in 1077 * the target node name for a lun. Since all luns behind the same target 1078 * have the same wwnn, only tagets that do not support multiple luns are 1079 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1080 */ 1081 1082 char *fcp_symmetric_disk_table[] = { 1083 "SEAGATE ST", 1084 "IBM DDYFT", 1085 "SUNW SUNWGS", /* Daktari enclosure */ 1086 "SUN SENA", /* SES device */ 1087 "SUN SESS01" /* VICOM SVE box */ 1088 }; 1089 1090 int fcp_symmetric_disk_table_size = 1091 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1092 1093 /* 1094 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1095 * will panic if you don't pass this in to the routine, this information. 1096 * Need to determine what the actual impact to the system is by providing 1097 * this information if any. Since dma allocation is done in pkt_init it may 1098 * not have any impact. These values are straight from the Writing Device 1099 * Driver manual. 1100 */ 1101 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1102 DMA_ATTR_V0, /* ddi_dma_attr version */ 1103 0, /* low address */ 1104 0xffffffff, /* high address */ 1105 0x00ffffff, /* counter upper bound */ 1106 1, /* alignment requirements */ 1107 0x3f, /* burst sizes */ 1108 1, /* minimum DMA access */ 1109 0xffffffff, /* maximum DMA access */ 1110 (1 << 24) - 1, /* segment boundary restrictions */ 1111 1, /* scater/gather list length */ 1112 512, /* device granularity */ 1113 0 /* DMA flags */ 1114 }; 1115 1116 /* 1117 * The _init(9e) return value should be that of mod_install(9f). Under 1118 * some circumstances, a failure may not be related mod_install(9f) and 1119 * one would then require a return value to indicate the failure. Looking 1120 * at mod_install(9f), it is expected to return 0 for success and non-zero 1121 * for failure. mod_install(9f) for device drivers, further goes down the 1122 * calling chain and ends up in ddi_installdrv(), whose return values are 1123 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1124 * calling chain of mod_install(9f) which return values like EINVAL and 1125 * in some even return -1. 1126 * 1127 * To work around the vagaries of the mod_install() calling chain, return 1128 * either 0 or ENODEV depending on the success or failure of mod_install() 1129 */ 1130 int 1131 _init(void) 1132 { 1133 int rval; 1134 1135 /* 1136 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1137 * before registering with the transport first. 1138 */ 1139 if (ddi_soft_state_init(&fcp_softstate, 1140 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1141 return (EINVAL); 1142 } 1143 1144 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1145 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1146 1147 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1148 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1149 mutex_destroy(&fcp_global_mutex); 1150 mutex_destroy(&fcp_ioctl_mutex); 1151 ddi_soft_state_fini(&fcp_softstate); 1152 return (ENODEV); 1153 } 1154 1155 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1156 1157 if ((rval = mod_install(&modlinkage)) != 0) { 1158 fc_trace_free_logq(fcp_logq); 1159 (void) fc_ulp_remove(&fcp_modinfo); 1160 mutex_destroy(&fcp_global_mutex); 1161 mutex_destroy(&fcp_ioctl_mutex); 1162 ddi_soft_state_fini(&fcp_softstate); 1163 rval = ENODEV; 1164 } 1165 1166 return (rval); 1167 } 1168 1169 1170 /* 1171 * the system is done with us as a driver, so clean up 1172 */ 1173 int 1174 _fini(void) 1175 { 1176 int rval; 1177 1178 /* 1179 * don't start cleaning up until we know that the module remove 1180 * has worked -- if this works, then we know that each instance 1181 * has successfully been DDI_DETACHed 1182 */ 1183 if ((rval = mod_remove(&modlinkage)) != 0) { 1184 return (rval); 1185 } 1186 1187 (void) fc_ulp_remove(&fcp_modinfo); 1188 1189 ddi_soft_state_fini(&fcp_softstate); 1190 mutex_destroy(&fcp_global_mutex); 1191 mutex_destroy(&fcp_ioctl_mutex); 1192 fc_trace_free_logq(fcp_logq); 1193 1194 return (rval); 1195 } 1196 1197 1198 int 1199 _info(struct modinfo *modinfop) 1200 { 1201 return (mod_info(&modlinkage, modinfop)); 1202 } 1203 1204 1205 /* 1206 * attach the module 1207 */ 1208 static int 1209 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1210 { 1211 int rval = DDI_SUCCESS; 1212 1213 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1214 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1215 1216 if (cmd == DDI_ATTACH) { 1217 /* The FCP pseudo device is created here. */ 1218 mutex_enter(&fcp_global_mutex); 1219 fcp_global_dip = devi; 1220 mutex_exit(&fcp_global_mutex); 1221 1222 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1223 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1224 ddi_report_dev(fcp_global_dip); 1225 } else { 1226 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1227 mutex_enter(&fcp_global_mutex); 1228 fcp_global_dip = NULL; 1229 mutex_exit(&fcp_global_mutex); 1230 1231 rval = DDI_FAILURE; 1232 } 1233 /* 1234 * We check the fcp_offline_delay property at this 1235 * point. This variable is global for the driver, 1236 * not specific to an instance. 1237 * 1238 * We do not recommend setting the value to less 1239 * than 10 seconds (RA_TOV_els), or greater than 1240 * 60 seconds. 1241 */ 1242 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1243 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1244 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1245 if ((fcp_offline_delay < 10) || 1246 (fcp_offline_delay > 60)) { 1247 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1248 "to %d second(s). This is outside the " 1249 "recommended range of 10..60 seconds.", 1250 fcp_offline_delay); 1251 } 1252 } 1253 1254 return (rval); 1255 } 1256 1257 1258 /*ARGSUSED*/ 1259 static int 1260 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1261 { 1262 int res = DDI_SUCCESS; 1263 1264 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1265 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1266 1267 if (cmd == DDI_DETACH) { 1268 /* 1269 * Check if there are active ports/threads. If there 1270 * are any, we will fail, else we will succeed (there 1271 * should not be much to clean up) 1272 */ 1273 mutex_enter(&fcp_global_mutex); 1274 FCP_DTRACE(fcp_logq, "fcp", 1275 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1276 (void *) fcp_port_head); 1277 1278 if (fcp_port_head == NULL) { 1279 ddi_remove_minor_node(fcp_global_dip, NULL); 1280 fcp_global_dip = NULL; 1281 mutex_exit(&fcp_global_mutex); 1282 } else { 1283 mutex_exit(&fcp_global_mutex); 1284 res = DDI_FAILURE; 1285 } 1286 } 1287 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1288 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1289 1290 return (res); 1291 } 1292 1293 1294 /* ARGSUSED */ 1295 static int 1296 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1297 { 1298 if (otype != OTYP_CHR) { 1299 return (EINVAL); 1300 } 1301 1302 /* 1303 * Allow only root to talk; 1304 */ 1305 if (drv_priv(credp)) { 1306 return (EPERM); 1307 } 1308 1309 mutex_enter(&fcp_global_mutex); 1310 if (fcp_oflag & FCP_EXCL) { 1311 mutex_exit(&fcp_global_mutex); 1312 return (EBUSY); 1313 } 1314 1315 if (flag & FEXCL) { 1316 if (fcp_oflag & FCP_OPEN) { 1317 mutex_exit(&fcp_global_mutex); 1318 return (EBUSY); 1319 } 1320 fcp_oflag |= FCP_EXCL; 1321 } 1322 fcp_oflag |= FCP_OPEN; 1323 mutex_exit(&fcp_global_mutex); 1324 1325 return (0); 1326 } 1327 1328 1329 /* ARGSUSED */ 1330 static int 1331 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1332 { 1333 if (otype != OTYP_CHR) { 1334 return (EINVAL); 1335 } 1336 1337 mutex_enter(&fcp_global_mutex); 1338 if (!(fcp_oflag & FCP_OPEN)) { 1339 mutex_exit(&fcp_global_mutex); 1340 return (ENODEV); 1341 } 1342 fcp_oflag = FCP_IDLE; 1343 mutex_exit(&fcp_global_mutex); 1344 1345 return (0); 1346 } 1347 1348 1349 /* 1350 * fcp_ioctl 1351 * Entry point for the FCP ioctls 1352 * 1353 * Input: 1354 * See ioctl(9E) 1355 * 1356 * Output: 1357 * See ioctl(9E) 1358 * 1359 * Returns: 1360 * See ioctl(9E) 1361 * 1362 * Context: 1363 * Kernel context. 1364 */ 1365 /* ARGSUSED */ 1366 static int 1367 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1368 int *rval) 1369 { 1370 int ret = 0; 1371 1372 mutex_enter(&fcp_global_mutex); 1373 if (!(fcp_oflag & FCP_OPEN)) { 1374 mutex_exit(&fcp_global_mutex); 1375 return (ENXIO); 1376 } 1377 mutex_exit(&fcp_global_mutex); 1378 1379 switch (cmd) { 1380 case FCP_TGT_INQUIRY: 1381 case FCP_TGT_CREATE: 1382 case FCP_TGT_DELETE: 1383 ret = fcp_setup_device_data_ioctl(cmd, 1384 (struct fcp_ioctl *)data, mode, rval); 1385 break; 1386 1387 case FCP_TGT_SEND_SCSI: 1388 mutex_enter(&fcp_ioctl_mutex); 1389 ret = fcp_setup_scsi_ioctl( 1390 (struct fcp_scsi_cmd *)data, mode, rval); 1391 mutex_exit(&fcp_ioctl_mutex); 1392 break; 1393 1394 case FCP_STATE_COUNT: 1395 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1396 mode, rval); 1397 break; 1398 case FCP_GET_TARGET_MAPPINGS: 1399 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1400 mode, rval); 1401 break; 1402 default: 1403 fcp_log(CE_WARN, NULL, 1404 "!Invalid ioctl opcode = 0x%x", cmd); 1405 ret = EINVAL; 1406 } 1407 1408 return (ret); 1409 } 1410 1411 1412 /* 1413 * fcp_setup_device_data_ioctl 1414 * Setup handler for the "device data" style of 1415 * ioctl for FCP. See "fcp_util.h" for data structure 1416 * definition. 1417 * 1418 * Input: 1419 * cmd = FCP ioctl command 1420 * data = ioctl data 1421 * mode = See ioctl(9E) 1422 * 1423 * Output: 1424 * data = ioctl data 1425 * rval = return value - see ioctl(9E) 1426 * 1427 * Returns: 1428 * See ioctl(9E) 1429 * 1430 * Context: 1431 * Kernel context. 1432 */ 1433 /* ARGSUSED */ 1434 static int 1435 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1436 int *rval) 1437 { 1438 struct fcp_port *pptr; 1439 struct device_data *dev_data; 1440 uint32_t link_cnt; 1441 la_wwn_t *wwn_ptr = NULL; 1442 struct fcp_tgt *ptgt = NULL; 1443 struct fcp_lun *plun = NULL; 1444 int i, error; 1445 struct fcp_ioctl fioctl; 1446 1447 #ifdef _MULTI_DATAMODEL 1448 switch (ddi_model_convert_from(mode & FMODELS)) { 1449 case DDI_MODEL_ILP32: { 1450 struct fcp32_ioctl f32_ioctl; 1451 1452 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1453 sizeof (struct fcp32_ioctl), mode)) { 1454 return (EFAULT); 1455 } 1456 fioctl.fp_minor = f32_ioctl.fp_minor; 1457 fioctl.listlen = f32_ioctl.listlen; 1458 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1459 break; 1460 } 1461 case DDI_MODEL_NONE: 1462 if (ddi_copyin((void *)data, (void *)&fioctl, 1463 sizeof (struct fcp_ioctl), mode)) { 1464 return (EFAULT); 1465 } 1466 break; 1467 } 1468 1469 #else /* _MULTI_DATAMODEL */ 1470 if (ddi_copyin((void *)data, (void *)&fioctl, 1471 sizeof (struct fcp_ioctl), mode)) { 1472 return (EFAULT); 1473 } 1474 #endif /* _MULTI_DATAMODEL */ 1475 1476 /* 1477 * Right now we can assume that the minor number matches with 1478 * this instance of fp. If this changes we will need to 1479 * revisit this logic. 1480 */ 1481 mutex_enter(&fcp_global_mutex); 1482 pptr = fcp_port_head; 1483 while (pptr) { 1484 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1485 break; 1486 } else { 1487 pptr = pptr->port_next; 1488 } 1489 } 1490 mutex_exit(&fcp_global_mutex); 1491 if (pptr == NULL) { 1492 return (ENXIO); 1493 } 1494 mutex_enter(&pptr->port_mutex); 1495 1496 1497 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1498 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1499 mutex_exit(&pptr->port_mutex); 1500 return (ENOMEM); 1501 } 1502 1503 if (ddi_copyin(fioctl.list, dev_data, 1504 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1505 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1506 mutex_exit(&pptr->port_mutex); 1507 return (EFAULT); 1508 } 1509 link_cnt = pptr->port_link_cnt; 1510 1511 if (cmd == FCP_TGT_INQUIRY) { 1512 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1513 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1514 sizeof (wwn_ptr->raw_wwn)) == 0) { 1515 /* This ioctl is requesting INQ info of local HBA */ 1516 mutex_exit(&pptr->port_mutex); 1517 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1518 dev_data[0].dev_status = 0; 1519 if (ddi_copyout(dev_data, fioctl.list, 1520 (sizeof (struct device_data)) * fioctl.listlen, 1521 mode)) { 1522 kmem_free(dev_data, 1523 sizeof (*dev_data) * fioctl.listlen); 1524 return (EFAULT); 1525 } 1526 kmem_free(dev_data, 1527 sizeof (*dev_data) * fioctl.listlen); 1528 #ifdef _MULTI_DATAMODEL 1529 switch (ddi_model_convert_from(mode & FMODELS)) { 1530 case DDI_MODEL_ILP32: { 1531 struct fcp32_ioctl f32_ioctl; 1532 f32_ioctl.fp_minor = fioctl.fp_minor; 1533 f32_ioctl.listlen = fioctl.listlen; 1534 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1535 if (ddi_copyout((void *)&f32_ioctl, 1536 (void *)data, 1537 sizeof (struct fcp32_ioctl), mode)) { 1538 return (EFAULT); 1539 } 1540 break; 1541 } 1542 case DDI_MODEL_NONE: 1543 if (ddi_copyout((void *)&fioctl, (void *)data, 1544 sizeof (struct fcp_ioctl), mode)) { 1545 return (EFAULT); 1546 } 1547 break; 1548 } 1549 #else /* _MULTI_DATAMODEL */ 1550 if (ddi_copyout((void *)&fioctl, (void *)data, 1551 sizeof (struct fcp_ioctl), mode)) { 1552 return (EFAULT); 1553 } 1554 #endif /* _MULTI_DATAMODEL */ 1555 return (0); 1556 } 1557 } 1558 1559 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1560 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1561 mutex_exit(&pptr->port_mutex); 1562 return (ENXIO); 1563 } 1564 1565 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1566 i++) { 1567 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1568 1569 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1570 1571 1572 dev_data[i].dev_status = ENXIO; 1573 1574 if ((ptgt = fcp_lookup_target(pptr, 1575 (uchar_t *)wwn_ptr)) == NULL) { 1576 mutex_exit(&pptr->port_mutex); 1577 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1578 wwn_ptr, &error, 0) == NULL) { 1579 dev_data[i].dev_status = ENODEV; 1580 mutex_enter(&pptr->port_mutex); 1581 continue; 1582 } else { 1583 1584 dev_data[i].dev_status = EAGAIN; 1585 1586 mutex_enter(&pptr->port_mutex); 1587 continue; 1588 } 1589 } else { 1590 mutex_enter(&ptgt->tgt_mutex); 1591 if (ptgt->tgt_state & (FCP_TGT_MARK | 1592 FCP_TGT_BUSY)) { 1593 dev_data[i].dev_status = EAGAIN; 1594 mutex_exit(&ptgt->tgt_mutex); 1595 continue; 1596 } 1597 1598 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1599 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1600 dev_data[i].dev_status = ENOTSUP; 1601 } else { 1602 dev_data[i].dev_status = ENXIO; 1603 } 1604 mutex_exit(&ptgt->tgt_mutex); 1605 continue; 1606 } 1607 1608 switch (cmd) { 1609 case FCP_TGT_INQUIRY: 1610 /* 1611 * The reason we give device type of 1612 * lun 0 only even though in some 1613 * cases(like maxstrat) lun 0 device 1614 * type may be 0x3f(invalid) is that 1615 * for bridge boxes target will appear 1616 * as luns and the first lun could be 1617 * a device that utility may not care 1618 * about (like a tape device). 1619 */ 1620 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1621 dev_data[i].dev_status = 0; 1622 mutex_exit(&ptgt->tgt_mutex); 1623 1624 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1625 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1626 } else { 1627 dev_data[i].dev0_type = plun->lun_type; 1628 } 1629 mutex_enter(&ptgt->tgt_mutex); 1630 break; 1631 1632 case FCP_TGT_CREATE: 1633 mutex_exit(&ptgt->tgt_mutex); 1634 mutex_exit(&pptr->port_mutex); 1635 1636 /* 1637 * serialize state change call backs. 1638 * only one call back will be handled 1639 * at a time. 1640 */ 1641 mutex_enter(&fcp_global_mutex); 1642 if (fcp_oflag & FCP_BUSY) { 1643 mutex_exit(&fcp_global_mutex); 1644 if (dev_data) { 1645 kmem_free(dev_data, 1646 sizeof (*dev_data) * 1647 fioctl.listlen); 1648 } 1649 return (EBUSY); 1650 } 1651 fcp_oflag |= FCP_BUSY; 1652 mutex_exit(&fcp_global_mutex); 1653 1654 dev_data[i].dev_status = 1655 fcp_create_on_demand(pptr, 1656 wwn_ptr->raw_wwn); 1657 1658 if (dev_data[i].dev_status != 0) { 1659 char buf[25]; 1660 1661 for (i = 0; i < FC_WWN_SIZE; i++) { 1662 (void) sprintf(&buf[i << 1], 1663 "%02x", 1664 wwn_ptr->raw_wwn[i]); 1665 } 1666 1667 fcp_log(CE_WARN, pptr->port_dip, 1668 "!Failed to create nodes for" 1669 " pwwn=%s; error=%x", buf, 1670 dev_data[i].dev_status); 1671 } 1672 1673 /* allow state change call backs again */ 1674 mutex_enter(&fcp_global_mutex); 1675 fcp_oflag &= ~FCP_BUSY; 1676 mutex_exit(&fcp_global_mutex); 1677 1678 mutex_enter(&pptr->port_mutex); 1679 mutex_enter(&ptgt->tgt_mutex); 1680 1681 break; 1682 1683 case FCP_TGT_DELETE: 1684 break; 1685 1686 default: 1687 fcp_log(CE_WARN, pptr->port_dip, 1688 "!Invalid device data ioctl " 1689 "opcode = 0x%x", cmd); 1690 } 1691 mutex_exit(&ptgt->tgt_mutex); 1692 } 1693 } 1694 mutex_exit(&pptr->port_mutex); 1695 1696 if (ddi_copyout(dev_data, fioctl.list, 1697 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1698 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1699 return (EFAULT); 1700 } 1701 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1702 1703 #ifdef _MULTI_DATAMODEL 1704 switch (ddi_model_convert_from(mode & FMODELS)) { 1705 case DDI_MODEL_ILP32: { 1706 struct fcp32_ioctl f32_ioctl; 1707 1708 f32_ioctl.fp_minor = fioctl.fp_minor; 1709 f32_ioctl.listlen = fioctl.listlen; 1710 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1711 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1712 sizeof (struct fcp32_ioctl), mode)) { 1713 return (EFAULT); 1714 } 1715 break; 1716 } 1717 case DDI_MODEL_NONE: 1718 if (ddi_copyout((void *)&fioctl, (void *)data, 1719 sizeof (struct fcp_ioctl), mode)) { 1720 return (EFAULT); 1721 } 1722 break; 1723 } 1724 #else /* _MULTI_DATAMODEL */ 1725 1726 if (ddi_copyout((void *)&fioctl, (void *)data, 1727 sizeof (struct fcp_ioctl), mode)) { 1728 return (EFAULT); 1729 } 1730 #endif /* _MULTI_DATAMODEL */ 1731 1732 return (0); 1733 } 1734 1735 /* 1736 * Fetch the target mappings (path, etc.) for all LUNs 1737 * on this port. 1738 */ 1739 /* ARGSUSED */ 1740 static int 1741 fcp_get_target_mappings(struct fcp_ioctl *data, 1742 int mode, int *rval) 1743 { 1744 struct fcp_port *pptr; 1745 fc_hba_target_mappings_t *mappings; 1746 fc_hba_mapping_entry_t *map; 1747 struct fcp_tgt *ptgt = NULL; 1748 struct fcp_lun *plun = NULL; 1749 int i, mapIndex, mappingSize; 1750 int listlen; 1751 struct fcp_ioctl fioctl; 1752 char *path; 1753 fcp_ent_addr_t sam_lun_addr; 1754 1755 #ifdef _MULTI_DATAMODEL 1756 switch (ddi_model_convert_from(mode & FMODELS)) { 1757 case DDI_MODEL_ILP32: { 1758 struct fcp32_ioctl f32_ioctl; 1759 1760 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1761 sizeof (struct fcp32_ioctl), mode)) { 1762 return (EFAULT); 1763 } 1764 fioctl.fp_minor = f32_ioctl.fp_minor; 1765 fioctl.listlen = f32_ioctl.listlen; 1766 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1767 break; 1768 } 1769 case DDI_MODEL_NONE: 1770 if (ddi_copyin((void *)data, (void *)&fioctl, 1771 sizeof (struct fcp_ioctl), mode)) { 1772 return (EFAULT); 1773 } 1774 break; 1775 } 1776 1777 #else /* _MULTI_DATAMODEL */ 1778 if (ddi_copyin((void *)data, (void *)&fioctl, 1779 sizeof (struct fcp_ioctl), mode)) { 1780 return (EFAULT); 1781 } 1782 #endif /* _MULTI_DATAMODEL */ 1783 1784 /* 1785 * Right now we can assume that the minor number matches with 1786 * this instance of fp. If this changes we will need to 1787 * revisit this logic. 1788 */ 1789 mutex_enter(&fcp_global_mutex); 1790 pptr = fcp_port_head; 1791 while (pptr) { 1792 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1793 break; 1794 } else { 1795 pptr = pptr->port_next; 1796 } 1797 } 1798 mutex_exit(&fcp_global_mutex); 1799 if (pptr == NULL) { 1800 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1801 fioctl.fp_minor); 1802 return (ENXIO); 1803 } 1804 1805 1806 /* We use listlen to show the total buffer size */ 1807 mappingSize = fioctl.listlen; 1808 1809 /* Now calculate how many mapping entries will fit */ 1810 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1811 - sizeof (fc_hba_target_mappings_t); 1812 if (listlen <= 0) { 1813 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1814 return (ENXIO); 1815 } 1816 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1817 1818 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1819 return (ENOMEM); 1820 } 1821 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1822 1823 /* Now get to work */ 1824 mapIndex = 0; 1825 1826 mutex_enter(&pptr->port_mutex); 1827 /* Loop through all targets on this port */ 1828 for (i = 0; i < FCP_NUM_HASH; i++) { 1829 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1830 ptgt = ptgt->tgt_next) { 1831 1832 mutex_enter(&ptgt->tgt_mutex); 1833 1834 /* Loop through all LUNs on this target */ 1835 for (plun = ptgt->tgt_lun; plun != NULL; 1836 plun = plun->lun_next) { 1837 if (plun->lun_state & FCP_LUN_OFFLINE) { 1838 continue; 1839 } 1840 1841 path = fcp_get_lun_path(plun); 1842 if (path == NULL) { 1843 continue; 1844 } 1845 1846 if (mapIndex >= listlen) { 1847 mapIndex ++; 1848 kmem_free(path, MAXPATHLEN); 1849 continue; 1850 } 1851 map = &mappings->entries[mapIndex++]; 1852 bcopy(path, map->targetDriver, 1853 sizeof (map->targetDriver)); 1854 map->d_id = ptgt->tgt_d_id; 1855 map->busNumber = 0; 1856 map->targetNumber = ptgt->tgt_d_id; 1857 map->osLUN = plun->lun_num; 1858 1859 /* 1860 * We had swapped lun when we stored it in 1861 * lun_addr. We need to swap it back before 1862 * returning it to user land 1863 */ 1864 1865 sam_lun_addr.ent_addr_0 = 1866 BE_16(plun->lun_addr.ent_addr_0); 1867 sam_lun_addr.ent_addr_1 = 1868 BE_16(plun->lun_addr.ent_addr_1); 1869 sam_lun_addr.ent_addr_2 = 1870 BE_16(plun->lun_addr.ent_addr_2); 1871 sam_lun_addr.ent_addr_3 = 1872 BE_16(plun->lun_addr.ent_addr_3); 1873 1874 bcopy(&sam_lun_addr, &map->samLUN, 1875 FCP_LUN_SIZE); 1876 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1877 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1878 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1879 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1880 1881 if (plun->lun_guid) { 1882 1883 /* convert ascii wwn to bytes */ 1884 fcp_ascii_to_wwn(plun->lun_guid, 1885 map->guid, sizeof (map->guid)); 1886 1887 if ((sizeof (map->guid)) < 1888 plun->lun_guid_size / 2) { 1889 cmn_err(CE_WARN, 1890 "fcp_get_target_mappings:" 1891 "guid copy space " 1892 "insufficient." 1893 "Copy Truncation - " 1894 "available %d; need %d", 1895 (int)sizeof (map->guid), 1896 (int) 1897 plun->lun_guid_size / 2); 1898 } 1899 } 1900 kmem_free(path, MAXPATHLEN); 1901 } 1902 mutex_exit(&ptgt->tgt_mutex); 1903 } 1904 } 1905 mutex_exit(&pptr->port_mutex); 1906 mappings->numLuns = mapIndex; 1907 1908 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1909 kmem_free(mappings, mappingSize); 1910 return (EFAULT); 1911 } 1912 kmem_free(mappings, mappingSize); 1913 1914 #ifdef _MULTI_DATAMODEL 1915 switch (ddi_model_convert_from(mode & FMODELS)) { 1916 case DDI_MODEL_ILP32: { 1917 struct fcp32_ioctl f32_ioctl; 1918 1919 f32_ioctl.fp_minor = fioctl.fp_minor; 1920 f32_ioctl.listlen = fioctl.listlen; 1921 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1922 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1923 sizeof (struct fcp32_ioctl), mode)) { 1924 return (EFAULT); 1925 } 1926 break; 1927 } 1928 case DDI_MODEL_NONE: 1929 if (ddi_copyout((void *)&fioctl, (void *)data, 1930 sizeof (struct fcp_ioctl), mode)) { 1931 return (EFAULT); 1932 } 1933 break; 1934 } 1935 #else /* _MULTI_DATAMODEL */ 1936 1937 if (ddi_copyout((void *)&fioctl, (void *)data, 1938 sizeof (struct fcp_ioctl), mode)) { 1939 return (EFAULT); 1940 } 1941 #endif /* _MULTI_DATAMODEL */ 1942 1943 return (0); 1944 } 1945 1946 /* 1947 * fcp_setup_scsi_ioctl 1948 * Setup handler for the "scsi passthru" style of 1949 * ioctl for FCP. See "fcp_util.h" for data structure 1950 * definition. 1951 * 1952 * Input: 1953 * u_fscsi = ioctl data (user address space) 1954 * mode = See ioctl(9E) 1955 * 1956 * Output: 1957 * u_fscsi = ioctl data (user address space) 1958 * rval = return value - see ioctl(9E) 1959 * 1960 * Returns: 1961 * 0 = OK 1962 * EAGAIN = See errno.h 1963 * EBUSY = See errno.h 1964 * EFAULT = See errno.h 1965 * EINTR = See errno.h 1966 * EINVAL = See errno.h 1967 * EIO = See errno.h 1968 * ENOMEM = See errno.h 1969 * ENXIO = See errno.h 1970 * 1971 * Context: 1972 * Kernel context. 1973 */ 1974 /* ARGSUSED */ 1975 static int 1976 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1977 int mode, int *rval) 1978 { 1979 int ret = 0; 1980 int temp_ret; 1981 caddr_t k_cdbbufaddr = NULL; 1982 caddr_t k_bufaddr = NULL; 1983 caddr_t k_rqbufaddr = NULL; 1984 caddr_t u_cdbbufaddr; 1985 caddr_t u_bufaddr; 1986 caddr_t u_rqbufaddr; 1987 struct fcp_scsi_cmd k_fscsi; 1988 1989 /* 1990 * Get fcp_scsi_cmd array element from user address space 1991 */ 1992 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1993 != 0) { 1994 return (ret); 1995 } 1996 1997 1998 /* 1999 * Even though kmem_alloc() checks the validity of the 2000 * buffer length, this check is needed when the 2001 * kmem_flags set and the zero buffer length is passed. 2002 */ 2003 if ((k_fscsi.scsi_cdblen <= 0) || 2004 (k_fscsi.scsi_buflen <= 0) || 2005 (k_fscsi.scsi_rqlen <= 0)) { 2006 return (EINVAL); 2007 } 2008 2009 /* 2010 * Allocate data for fcp_scsi_cmd pointer fields 2011 */ 2012 if (ret == 0) { 2013 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 2014 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 2015 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 2016 2017 if (k_cdbbufaddr == NULL || 2018 k_bufaddr == NULL || 2019 k_rqbufaddr == NULL) { 2020 ret = ENOMEM; 2021 } 2022 } 2023 2024 /* 2025 * Get fcp_scsi_cmd pointer fields from user 2026 * address space 2027 */ 2028 if (ret == 0) { 2029 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2030 u_bufaddr = k_fscsi.scsi_bufaddr; 2031 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2032 2033 if (ddi_copyin(u_cdbbufaddr, 2034 k_cdbbufaddr, 2035 k_fscsi.scsi_cdblen, 2036 mode)) { 2037 ret = EFAULT; 2038 } else if (ddi_copyin(u_bufaddr, 2039 k_bufaddr, 2040 k_fscsi.scsi_buflen, 2041 mode)) { 2042 ret = EFAULT; 2043 } else if (ddi_copyin(u_rqbufaddr, 2044 k_rqbufaddr, 2045 k_fscsi.scsi_rqlen, 2046 mode)) { 2047 ret = EFAULT; 2048 } 2049 } 2050 2051 /* 2052 * Send scsi command (blocking) 2053 */ 2054 if (ret == 0) { 2055 /* 2056 * Prior to sending the scsi command, the 2057 * fcp_scsi_cmd data structure must contain kernel, 2058 * not user, addresses. 2059 */ 2060 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2061 k_fscsi.scsi_bufaddr = k_bufaddr; 2062 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2063 2064 ret = fcp_send_scsi_ioctl(&k_fscsi); 2065 2066 /* 2067 * After sending the scsi command, the 2068 * fcp_scsi_cmd data structure must contain user, 2069 * not kernel, addresses. 2070 */ 2071 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2072 k_fscsi.scsi_bufaddr = u_bufaddr; 2073 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2074 } 2075 2076 /* 2077 * Put fcp_scsi_cmd pointer fields to user address space 2078 */ 2079 if (ret == 0) { 2080 if (ddi_copyout(k_cdbbufaddr, 2081 u_cdbbufaddr, 2082 k_fscsi.scsi_cdblen, 2083 mode)) { 2084 ret = EFAULT; 2085 } else if (ddi_copyout(k_bufaddr, 2086 u_bufaddr, 2087 k_fscsi.scsi_buflen, 2088 mode)) { 2089 ret = EFAULT; 2090 } else if (ddi_copyout(k_rqbufaddr, 2091 u_rqbufaddr, 2092 k_fscsi.scsi_rqlen, 2093 mode)) { 2094 ret = EFAULT; 2095 } 2096 } 2097 2098 /* 2099 * Free data for fcp_scsi_cmd pointer fields 2100 */ 2101 if (k_cdbbufaddr != NULL) { 2102 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2103 } 2104 if (k_bufaddr != NULL) { 2105 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2106 } 2107 if (k_rqbufaddr != NULL) { 2108 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2109 } 2110 2111 /* 2112 * Put fcp_scsi_cmd array element to user address space 2113 */ 2114 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2115 if (temp_ret != 0) { 2116 ret = temp_ret; 2117 } 2118 2119 /* 2120 * Return status 2121 */ 2122 return (ret); 2123 } 2124 2125 2126 /* 2127 * fcp_copyin_scsi_cmd 2128 * Copy in fcp_scsi_cmd data structure from user address space. 2129 * The data may be in 32 bit or 64 bit modes. 2130 * 2131 * Input: 2132 * base_addr = from address (user address space) 2133 * mode = See ioctl(9E) and ddi_copyin(9F) 2134 * 2135 * Output: 2136 * fscsi = to address (kernel address space) 2137 * 2138 * Returns: 2139 * 0 = OK 2140 * EFAULT = Error 2141 * 2142 * Context: 2143 * Kernel context. 2144 */ 2145 static int 2146 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2147 { 2148 #ifdef _MULTI_DATAMODEL 2149 struct fcp32_scsi_cmd f32scsi; 2150 2151 switch (ddi_model_convert_from(mode & FMODELS)) { 2152 case DDI_MODEL_ILP32: 2153 /* 2154 * Copy data from user address space 2155 */ 2156 if (ddi_copyin((void *)base_addr, 2157 &f32scsi, 2158 sizeof (struct fcp32_scsi_cmd), 2159 mode)) { 2160 return (EFAULT); 2161 } 2162 /* 2163 * Convert from 32 bit to 64 bit 2164 */ 2165 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2166 break; 2167 case DDI_MODEL_NONE: 2168 /* 2169 * Copy data from user address space 2170 */ 2171 if (ddi_copyin((void *)base_addr, 2172 fscsi, 2173 sizeof (struct fcp_scsi_cmd), 2174 mode)) { 2175 return (EFAULT); 2176 } 2177 break; 2178 } 2179 #else /* _MULTI_DATAMODEL */ 2180 /* 2181 * Copy data from user address space 2182 */ 2183 if (ddi_copyin((void *)base_addr, 2184 fscsi, 2185 sizeof (struct fcp_scsi_cmd), 2186 mode)) { 2187 return (EFAULT); 2188 } 2189 #endif /* _MULTI_DATAMODEL */ 2190 2191 return (0); 2192 } 2193 2194 2195 /* 2196 * fcp_copyout_scsi_cmd 2197 * Copy out fcp_scsi_cmd data structure to user address space. 2198 * The data may be in 32 bit or 64 bit modes. 2199 * 2200 * Input: 2201 * fscsi = to address (kernel address space) 2202 * mode = See ioctl(9E) and ddi_copyin(9F) 2203 * 2204 * Output: 2205 * base_addr = from address (user address space) 2206 * 2207 * Returns: 2208 * 0 = OK 2209 * EFAULT = Error 2210 * 2211 * Context: 2212 * Kernel context. 2213 */ 2214 static int 2215 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2216 { 2217 #ifdef _MULTI_DATAMODEL 2218 struct fcp32_scsi_cmd f32scsi; 2219 2220 switch (ddi_model_convert_from(mode & FMODELS)) { 2221 case DDI_MODEL_ILP32: 2222 /* 2223 * Convert from 64 bit to 32 bit 2224 */ 2225 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2226 /* 2227 * Copy data to user address space 2228 */ 2229 if (ddi_copyout(&f32scsi, 2230 (void *)base_addr, 2231 sizeof (struct fcp32_scsi_cmd), 2232 mode)) { 2233 return (EFAULT); 2234 } 2235 break; 2236 case DDI_MODEL_NONE: 2237 /* 2238 * Copy data to user address space 2239 */ 2240 if (ddi_copyout(fscsi, 2241 (void *)base_addr, 2242 sizeof (struct fcp_scsi_cmd), 2243 mode)) { 2244 return (EFAULT); 2245 } 2246 break; 2247 } 2248 #else /* _MULTI_DATAMODEL */ 2249 /* 2250 * Copy data to user address space 2251 */ 2252 if (ddi_copyout(fscsi, 2253 (void *)base_addr, 2254 sizeof (struct fcp_scsi_cmd), 2255 mode)) { 2256 return (EFAULT); 2257 } 2258 #endif /* _MULTI_DATAMODEL */ 2259 2260 return (0); 2261 } 2262 2263 2264 /* 2265 * fcp_send_scsi_ioctl 2266 * Sends the SCSI command in blocking mode. 2267 * 2268 * Input: 2269 * fscsi = SCSI command data structure 2270 * 2271 * Output: 2272 * fscsi = SCSI command data structure 2273 * 2274 * Returns: 2275 * 0 = OK 2276 * EAGAIN = See errno.h 2277 * EBUSY = See errno.h 2278 * EINTR = See errno.h 2279 * EINVAL = See errno.h 2280 * EIO = See errno.h 2281 * ENOMEM = See errno.h 2282 * ENXIO = See errno.h 2283 * 2284 * Context: 2285 * Kernel context. 2286 */ 2287 static int 2288 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2289 { 2290 struct fcp_lun *plun = NULL; 2291 struct fcp_port *pptr = NULL; 2292 struct fcp_tgt *ptgt = NULL; 2293 fc_packet_t *fpkt = NULL; 2294 struct fcp_ipkt *icmd = NULL; 2295 int target_created = FALSE; 2296 fc_frame_hdr_t *hp; 2297 struct fcp_cmd fcp_cmd; 2298 struct fcp_cmd *fcmd; 2299 union scsi_cdb *scsi_cdb; 2300 la_wwn_t *wwn_ptr; 2301 int nodma; 2302 struct fcp_rsp *rsp; 2303 struct fcp_rsp_info *rsp_info; 2304 caddr_t rsp_sense; 2305 int buf_len; 2306 int info_len; 2307 int sense_len; 2308 struct scsi_extended_sense *sense_to = NULL; 2309 timeout_id_t tid; 2310 uint8_t reconfig_lun = FALSE; 2311 uint8_t reconfig_pending = FALSE; 2312 uint8_t scsi_cmd; 2313 int rsp_len; 2314 int cmd_index; 2315 int fc_status; 2316 int pkt_state; 2317 int pkt_action; 2318 int pkt_reason; 2319 int ret, xport_retval = ~FC_SUCCESS; 2320 int lcount; 2321 int tcount; 2322 int reconfig_status; 2323 int port_busy = FALSE; 2324 uchar_t *lun_string; 2325 2326 /* 2327 * Check valid SCSI command 2328 */ 2329 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2330 ret = EINVAL; 2331 for (cmd_index = 0; 2332 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2333 ret != 0; 2334 cmd_index++) { 2335 /* 2336 * First byte of CDB is the SCSI command 2337 */ 2338 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2339 ret = 0; 2340 } 2341 } 2342 2343 /* 2344 * Check inputs 2345 */ 2346 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2347 ret = EINVAL; 2348 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2349 /* no larger than */ 2350 ret = EINVAL; 2351 } 2352 2353 2354 /* 2355 * Find FC port 2356 */ 2357 if (ret == 0) { 2358 /* 2359 * Acquire global mutex 2360 */ 2361 mutex_enter(&fcp_global_mutex); 2362 2363 pptr = fcp_port_head; 2364 while (pptr) { 2365 if (pptr->port_instance == 2366 (uint32_t)fscsi->scsi_fc_port_num) { 2367 break; 2368 } else { 2369 pptr = pptr->port_next; 2370 } 2371 } 2372 2373 if (pptr == NULL) { 2374 ret = ENXIO; 2375 } else { 2376 /* 2377 * fc_ulp_busy_port can raise power 2378 * so, we must not hold any mutexes involved in PM 2379 */ 2380 mutex_exit(&fcp_global_mutex); 2381 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2382 } 2383 2384 if (ret == 0) { 2385 2386 /* remember port is busy, so we will release later */ 2387 port_busy = TRUE; 2388 2389 /* 2390 * If there is a reconfiguration in progress, wait 2391 * for it to complete. 2392 */ 2393 2394 fcp_reconfig_wait(pptr); 2395 2396 /* reacquire mutexes in order */ 2397 mutex_enter(&fcp_global_mutex); 2398 mutex_enter(&pptr->port_mutex); 2399 2400 /* 2401 * Will port accept DMA? 2402 */ 2403 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2404 ? 1 : 0; 2405 2406 /* 2407 * If init or offline, device not known 2408 * 2409 * If we are discovering (onlining), we can 2410 * NOT obviously provide reliable data about 2411 * devices until it is complete 2412 */ 2413 if (pptr->port_state & (FCP_STATE_INIT | 2414 FCP_STATE_OFFLINE)) { 2415 ret = ENXIO; 2416 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2417 ret = EBUSY; 2418 } else { 2419 /* 2420 * Find target from pwwn 2421 * 2422 * The wwn must be put into a local 2423 * variable to ensure alignment. 2424 */ 2425 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2426 ptgt = fcp_lookup_target(pptr, 2427 (uchar_t *)wwn_ptr); 2428 2429 /* 2430 * If target not found, 2431 */ 2432 if (ptgt == NULL) { 2433 /* 2434 * Note: Still have global & 2435 * port mutexes 2436 */ 2437 mutex_exit(&pptr->port_mutex); 2438 ptgt = fcp_port_create_tgt(pptr, 2439 wwn_ptr, &ret, &fc_status, 2440 &pkt_state, &pkt_action, 2441 &pkt_reason); 2442 mutex_enter(&pptr->port_mutex); 2443 2444 fscsi->scsi_fc_status = fc_status; 2445 fscsi->scsi_pkt_state = 2446 (uchar_t)pkt_state; 2447 fscsi->scsi_pkt_reason = pkt_reason; 2448 fscsi->scsi_pkt_action = 2449 (uchar_t)pkt_action; 2450 2451 if (ptgt != NULL) { 2452 target_created = TRUE; 2453 } else if (ret == 0) { 2454 ret = ENOMEM; 2455 } 2456 } 2457 2458 if (ret == 0) { 2459 /* 2460 * Acquire target 2461 */ 2462 mutex_enter(&ptgt->tgt_mutex); 2463 2464 /* 2465 * If target is mark or busy, 2466 * then target can not be used 2467 */ 2468 if (ptgt->tgt_state & 2469 (FCP_TGT_MARK | 2470 FCP_TGT_BUSY)) { 2471 ret = EBUSY; 2472 } else { 2473 /* 2474 * Mark target as busy 2475 */ 2476 ptgt->tgt_state |= 2477 FCP_TGT_BUSY; 2478 } 2479 2480 /* 2481 * Release target 2482 */ 2483 lcount = pptr->port_link_cnt; 2484 tcount = ptgt->tgt_change_cnt; 2485 mutex_exit(&ptgt->tgt_mutex); 2486 } 2487 } 2488 2489 /* 2490 * Release port 2491 */ 2492 mutex_exit(&pptr->port_mutex); 2493 } 2494 2495 /* 2496 * Release global mutex 2497 */ 2498 mutex_exit(&fcp_global_mutex); 2499 } 2500 2501 if (ret == 0) { 2502 uint64_t belun = BE_64(fscsi->scsi_lun); 2503 2504 /* 2505 * If it's a target device, find lun from pwwn 2506 * The wwn must be put into a local 2507 * variable to ensure alignment. 2508 */ 2509 mutex_enter(&pptr->port_mutex); 2510 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2511 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2512 /* this is not a target */ 2513 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2514 ret = ENXIO; 2515 } else if ((belun << 16) != 0) { 2516 /* 2517 * Since fcp only support PD and LU addressing method 2518 * so far, the last 6 bytes of a valid LUN are expected 2519 * to be filled with 00h. 2520 */ 2521 fscsi->scsi_fc_status = FC_INVALID_LUN; 2522 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2523 " method 0x%02x with LUN number 0x%016" PRIx64, 2524 (uint8_t)(belun >> 62), belun); 2525 ret = ENXIO; 2526 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2527 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2528 /* 2529 * This is a SCSI target, but no LUN at this 2530 * address. 2531 * 2532 * In the future, we may want to send this to 2533 * the target, and let it respond 2534 * appropriately 2535 */ 2536 ret = ENXIO; 2537 } 2538 mutex_exit(&pptr->port_mutex); 2539 } 2540 2541 /* 2542 * Finished grabbing external resources 2543 * Allocate internal packet (icmd) 2544 */ 2545 if (ret == 0) { 2546 /* 2547 * Calc rsp len assuming rsp info included 2548 */ 2549 rsp_len = sizeof (struct fcp_rsp) + 2550 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2551 2552 icmd = fcp_icmd_alloc(pptr, ptgt, 2553 sizeof (struct fcp_cmd), 2554 rsp_len, 2555 fscsi->scsi_buflen, 2556 nodma, 2557 lcount, /* ipkt_link_cnt */ 2558 tcount, /* ipkt_change_cnt */ 2559 0, /* cause */ 2560 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2561 2562 if (icmd == NULL) { 2563 ret = ENOMEM; 2564 } else { 2565 /* 2566 * Setup internal packet as sema sync 2567 */ 2568 fcp_ipkt_sema_init(icmd); 2569 } 2570 } 2571 2572 if (ret == 0) { 2573 /* 2574 * Init fpkt pointer for use. 2575 */ 2576 2577 fpkt = icmd->ipkt_fpkt; 2578 2579 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2580 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2581 fpkt->pkt_timeout = fscsi->scsi_timeout; 2582 2583 /* 2584 * Init fcmd pointer for use by SCSI command 2585 */ 2586 2587 if (nodma) { 2588 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2589 } else { 2590 fcmd = &fcp_cmd; 2591 } 2592 bzero(fcmd, sizeof (struct fcp_cmd)); 2593 ptgt = plun->lun_tgt; 2594 2595 lun_string = (uchar_t *)&fscsi->scsi_lun; 2596 2597 fcmd->fcp_ent_addr.ent_addr_0 = 2598 BE_16(*(uint16_t *)&(lun_string[0])); 2599 fcmd->fcp_ent_addr.ent_addr_1 = 2600 BE_16(*(uint16_t *)&(lun_string[2])); 2601 fcmd->fcp_ent_addr.ent_addr_2 = 2602 BE_16(*(uint16_t *)&(lun_string[4])); 2603 fcmd->fcp_ent_addr.ent_addr_3 = 2604 BE_16(*(uint16_t *)&(lun_string[6])); 2605 2606 /* 2607 * Setup internal packet(icmd) 2608 */ 2609 icmd->ipkt_lun = plun; 2610 icmd->ipkt_restart = 0; 2611 icmd->ipkt_retries = 0; 2612 icmd->ipkt_opcode = 0; 2613 2614 /* 2615 * Init the frame HEADER Pointer for use 2616 */ 2617 hp = &fpkt->pkt_cmd_fhdr; 2618 2619 hp->s_id = pptr->port_id; 2620 hp->d_id = ptgt->tgt_d_id; 2621 hp->r_ctl = R_CTL_COMMAND; 2622 hp->type = FC_TYPE_SCSI_FCP; 2623 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2624 hp->rsvd = 0; 2625 hp->seq_id = 0; 2626 hp->seq_cnt = 0; 2627 hp->ox_id = 0xffff; 2628 hp->rx_id = 0xffff; 2629 hp->ro = 0; 2630 2631 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2632 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2633 fcmd->fcp_cntl.cntl_write_data = 0; 2634 fcmd->fcp_data_len = fscsi->scsi_buflen; 2635 2636 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2637 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2638 fscsi->scsi_cdblen); 2639 2640 if (!nodma) { 2641 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2642 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2643 } 2644 2645 /* 2646 * Send SCSI command to FC transport 2647 */ 2648 2649 if (ret == 0) { 2650 mutex_enter(&ptgt->tgt_mutex); 2651 2652 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2653 mutex_exit(&ptgt->tgt_mutex); 2654 fscsi->scsi_fc_status = xport_retval = 2655 fc_ulp_transport(pptr->port_fp_handle, 2656 fpkt); 2657 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2658 ret = EIO; 2659 } 2660 } else { 2661 mutex_exit(&ptgt->tgt_mutex); 2662 ret = EBUSY; 2663 } 2664 } 2665 } 2666 2667 /* 2668 * Wait for completion only if fc_ulp_transport was called and it 2669 * returned a success. This is the only time callback will happen. 2670 * Otherwise, there is no point in waiting 2671 */ 2672 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2673 ret = fcp_ipkt_sema_wait(icmd); 2674 } 2675 2676 /* 2677 * Copy data to IOCTL data structures 2678 */ 2679 rsp = NULL; 2680 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2681 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2682 2683 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2684 fcp_log(CE_WARN, pptr->port_dip, 2685 "!SCSI command to d_id=0x%x lun=0x%x" 2686 " failed, Bad FCP response values:" 2687 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2688 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2689 ptgt->tgt_d_id, plun->lun_num, 2690 rsp->reserved_0, rsp->reserved_1, 2691 rsp->fcp_u.fcp_status.reserved_0, 2692 rsp->fcp_u.fcp_status.reserved_1, 2693 rsp->fcp_response_len, rsp->fcp_sense_len); 2694 2695 ret = EIO; 2696 } 2697 } 2698 2699 if ((ret == 0) && (rsp != NULL)) { 2700 /* 2701 * Calc response lengths 2702 */ 2703 sense_len = 0; 2704 info_len = 0; 2705 2706 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2707 info_len = rsp->fcp_response_len; 2708 } 2709 2710 rsp_info = (struct fcp_rsp_info *) 2711 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2712 2713 /* 2714 * Get SCSI status 2715 */ 2716 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2717 /* 2718 * If a lun was just added or removed and the next command 2719 * comes through this interface, we need to capture the check 2720 * condition so we can discover the new topology. 2721 */ 2722 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2723 rsp->fcp_u.fcp_status.sense_len_set) { 2724 sense_len = rsp->fcp_sense_len; 2725 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2726 sense_to = (struct scsi_extended_sense *)rsp_sense; 2727 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2728 (FCP_SENSE_NO_LUN(sense_to))) { 2729 reconfig_lun = TRUE; 2730 } 2731 } 2732 2733 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2734 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2735 if (reconfig_lun == FALSE) { 2736 reconfig_status = 2737 fcp_is_reconfig_needed(ptgt, fpkt); 2738 } 2739 2740 if ((reconfig_lun == TRUE) || 2741 (reconfig_status == TRUE)) { 2742 mutex_enter(&ptgt->tgt_mutex); 2743 if (ptgt->tgt_tid == NULL) { 2744 /* 2745 * Either we've been notified the 2746 * REPORT_LUN data has changed, or 2747 * we've determined on our own that 2748 * we're out of date. Kick off 2749 * rediscovery. 2750 */ 2751 tid = timeout(fcp_reconfigure_luns, 2752 (caddr_t)ptgt, drv_usectohz(1)); 2753 2754 ptgt->tgt_tid = tid; 2755 ptgt->tgt_state |= FCP_TGT_BUSY; 2756 ret = EBUSY; 2757 reconfig_pending = TRUE; 2758 } 2759 mutex_exit(&ptgt->tgt_mutex); 2760 } 2761 } 2762 2763 /* 2764 * Calc residuals and buffer lengths 2765 */ 2766 2767 if (ret == 0) { 2768 buf_len = fscsi->scsi_buflen; 2769 fscsi->scsi_bufresid = 0; 2770 if (rsp->fcp_u.fcp_status.resid_under) { 2771 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2772 fscsi->scsi_bufresid = rsp->fcp_resid; 2773 } else { 2774 cmn_err(CE_WARN, "fcp: bad residue %x " 2775 "for txfer len %x", rsp->fcp_resid, 2776 fscsi->scsi_buflen); 2777 fscsi->scsi_bufresid = 2778 fscsi->scsi_buflen; 2779 } 2780 buf_len -= fscsi->scsi_bufresid; 2781 } 2782 if (rsp->fcp_u.fcp_status.resid_over) { 2783 fscsi->scsi_bufresid = -rsp->fcp_resid; 2784 } 2785 2786 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2787 if (fscsi->scsi_rqlen < sense_len) { 2788 sense_len = fscsi->scsi_rqlen; 2789 } 2790 2791 fscsi->scsi_fc_rspcode = 0; 2792 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2793 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2794 } 2795 fscsi->scsi_pkt_state = fpkt->pkt_state; 2796 fscsi->scsi_pkt_action = fpkt->pkt_action; 2797 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2798 2799 /* 2800 * Copy data and request sense 2801 * 2802 * Data must be copied by using the FCP_CP_IN macro. 2803 * This will ensure the proper byte order since the data 2804 * is being copied directly from the memory mapped 2805 * device register. 2806 * 2807 * The response (and request sense) will be in the 2808 * correct byte order. No special copy is necessary. 2809 */ 2810 2811 if (buf_len) { 2812 FCP_CP_IN(fpkt->pkt_data, 2813 fscsi->scsi_bufaddr, 2814 fpkt->pkt_data_acc, 2815 buf_len); 2816 } 2817 bcopy((void *)rsp_sense, 2818 (void *)fscsi->scsi_rqbufaddr, 2819 sense_len); 2820 } 2821 } 2822 2823 /* 2824 * Cleanup transport data structures if icmd was alloc-ed 2825 * So, cleanup happens in the same thread that icmd was alloc-ed 2826 */ 2827 if (icmd != NULL) { 2828 fcp_ipkt_sema_cleanup(icmd); 2829 } 2830 2831 /* restore pm busy/idle status */ 2832 if (port_busy) { 2833 fc_ulp_idle_port(pptr->port_fp_handle); 2834 } 2835 2836 /* 2837 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2838 * flag, it'll be cleared when the reconfig is complete. 2839 */ 2840 if ((ptgt != NULL) && !reconfig_pending) { 2841 /* 2842 * If target was created, 2843 */ 2844 if (target_created) { 2845 mutex_enter(&ptgt->tgt_mutex); 2846 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2847 mutex_exit(&ptgt->tgt_mutex); 2848 } else { 2849 /* 2850 * De-mark target as busy 2851 */ 2852 mutex_enter(&ptgt->tgt_mutex); 2853 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2854 mutex_exit(&ptgt->tgt_mutex); 2855 } 2856 } 2857 return (ret); 2858 } 2859 2860 2861 static int 2862 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2863 fc_packet_t *fpkt) 2864 { 2865 uchar_t *lun_string; 2866 uint16_t lun_num, i; 2867 int num_luns; 2868 int actual_luns; 2869 int num_masked_luns; 2870 int lun_buflen; 2871 struct fcp_lun *plun = NULL; 2872 struct fcp_reportlun_resp *report_lun; 2873 uint8_t reconfig_needed = FALSE; 2874 uint8_t lun_exists = FALSE; 2875 fcp_port_t *pptr = ptgt->tgt_port; 2876 2877 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2878 2879 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2880 fpkt->pkt_datalen); 2881 2882 /* get number of luns (which is supplied as LUNS * 8) */ 2883 num_luns = BE_32(report_lun->num_lun) >> 3; 2884 2885 /* 2886 * Figure out exactly how many lun strings our response buffer 2887 * can hold. 2888 */ 2889 lun_buflen = (fpkt->pkt_datalen - 2890 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2891 2892 /* 2893 * Is our response buffer full or not? We don't want to 2894 * potentially walk beyond the number of luns we have. 2895 */ 2896 if (num_luns <= lun_buflen) { 2897 actual_luns = num_luns; 2898 } else { 2899 actual_luns = lun_buflen; 2900 } 2901 2902 mutex_enter(&ptgt->tgt_mutex); 2903 2904 /* Scan each lun to see if we have masked it. */ 2905 num_masked_luns = 0; 2906 if (fcp_lun_blacklist != NULL) { 2907 for (i = 0; i < actual_luns; i++) { 2908 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2909 switch (lun_string[0] & 0xC0) { 2910 case FCP_LUN_ADDRESSING: 2911 case FCP_PD_ADDRESSING: 2912 case FCP_VOLUME_ADDRESSING: 2913 lun_num = ((lun_string[0] & 0x3F) << 8) 2914 | lun_string[1]; 2915 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2916 lun_num) == TRUE) { 2917 num_masked_luns++; 2918 } 2919 break; 2920 default: 2921 break; 2922 } 2923 } 2924 } 2925 2926 /* 2927 * The quick and easy check. If the number of LUNs reported 2928 * doesn't match the number we currently know about, we need 2929 * to reconfigure. 2930 */ 2931 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2932 mutex_exit(&ptgt->tgt_mutex); 2933 kmem_free(report_lun, fpkt->pkt_datalen); 2934 return (TRUE); 2935 } 2936 2937 /* 2938 * If the quick and easy check doesn't turn up anything, we walk 2939 * the list of luns from the REPORT_LUN response and look for 2940 * any luns we don't know about. If we find one, we know we need 2941 * to reconfigure. We will skip LUNs that are masked because of the 2942 * blacklist. 2943 */ 2944 for (i = 0; i < actual_luns; i++) { 2945 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2946 lun_exists = FALSE; 2947 switch (lun_string[0] & 0xC0) { 2948 case FCP_LUN_ADDRESSING: 2949 case FCP_PD_ADDRESSING: 2950 case FCP_VOLUME_ADDRESSING: 2951 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2952 2953 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2954 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2955 lun_exists = TRUE; 2956 break; 2957 } 2958 2959 for (plun = ptgt->tgt_lun; plun; 2960 plun = plun->lun_next) { 2961 if (plun->lun_num == lun_num) { 2962 lun_exists = TRUE; 2963 break; 2964 } 2965 } 2966 break; 2967 default: 2968 break; 2969 } 2970 2971 if (lun_exists == FALSE) { 2972 reconfig_needed = TRUE; 2973 break; 2974 } 2975 } 2976 2977 mutex_exit(&ptgt->tgt_mutex); 2978 kmem_free(report_lun, fpkt->pkt_datalen); 2979 2980 return (reconfig_needed); 2981 } 2982 2983 /* 2984 * This function is called by fcp_handle_page83 and uses inquiry response data 2985 * stored in plun->lun_inq to determine whether or not a device is a member of 2986 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2987 * otherwise 1. 2988 */ 2989 static int 2990 fcp_symmetric_device_probe(struct fcp_lun *plun) 2991 { 2992 struct scsi_inquiry *stdinq = &plun->lun_inq; 2993 char *devidptr; 2994 int i, len; 2995 2996 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2997 devidptr = fcp_symmetric_disk_table[i]; 2998 len = (int)strlen(devidptr); 2999 3000 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 3001 return (0); 3002 } 3003 } 3004 return (1); 3005 } 3006 3007 3008 /* 3009 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 3010 * It basically returns the current count of # of state change callbacks 3011 * i.e the value of tgt_change_cnt. 3012 * 3013 * INPUT: 3014 * fcp_ioctl.fp_minor -> The minor # of the fp port 3015 * fcp_ioctl.listlen -> 1 3016 * fcp_ioctl.list -> Pointer to a 32 bit integer 3017 */ 3018 /*ARGSUSED2*/ 3019 static int 3020 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3021 { 3022 int ret; 3023 uint32_t link_cnt; 3024 struct fcp_ioctl fioctl; 3025 struct fcp_port *pptr = NULL; 3026 3027 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3028 &pptr)) != 0) { 3029 return (ret); 3030 } 3031 3032 ASSERT(pptr != NULL); 3033 3034 if (fioctl.listlen != 1) { 3035 return (EINVAL); 3036 } 3037 3038 mutex_enter(&pptr->port_mutex); 3039 if (pptr->port_state & FCP_STATE_OFFLINE) { 3040 mutex_exit(&pptr->port_mutex); 3041 return (ENXIO); 3042 } 3043 3044 /* 3045 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3046 * When the fcp initially attaches to the port and there are nothing 3047 * hanging out of the port or if there was a repeat offline state change 3048 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3049 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3050 * will differentiate the 2 cases. 3051 */ 3052 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3053 mutex_exit(&pptr->port_mutex); 3054 return (ENXIO); 3055 } 3056 3057 link_cnt = pptr->port_link_cnt; 3058 mutex_exit(&pptr->port_mutex); 3059 3060 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3061 return (EFAULT); 3062 } 3063 3064 #ifdef _MULTI_DATAMODEL 3065 switch (ddi_model_convert_from(mode & FMODELS)) { 3066 case DDI_MODEL_ILP32: { 3067 struct fcp32_ioctl f32_ioctl; 3068 3069 f32_ioctl.fp_minor = fioctl.fp_minor; 3070 f32_ioctl.listlen = fioctl.listlen; 3071 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3072 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3073 sizeof (struct fcp32_ioctl), mode)) { 3074 return (EFAULT); 3075 } 3076 break; 3077 } 3078 case DDI_MODEL_NONE: 3079 if (ddi_copyout((void *)&fioctl, (void *)data, 3080 sizeof (struct fcp_ioctl), mode)) { 3081 return (EFAULT); 3082 } 3083 break; 3084 } 3085 #else /* _MULTI_DATAMODEL */ 3086 3087 if (ddi_copyout((void *)&fioctl, (void *)data, 3088 sizeof (struct fcp_ioctl), mode)) { 3089 return (EFAULT); 3090 } 3091 #endif /* _MULTI_DATAMODEL */ 3092 3093 return (0); 3094 } 3095 3096 /* 3097 * This function copies the fcp_ioctl structure passed in from user land 3098 * into kernel land. Handles 32 bit applications. 3099 */ 3100 /*ARGSUSED*/ 3101 static int 3102 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3103 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3104 { 3105 struct fcp_port *t_pptr; 3106 3107 #ifdef _MULTI_DATAMODEL 3108 switch (ddi_model_convert_from(mode & FMODELS)) { 3109 case DDI_MODEL_ILP32: { 3110 struct fcp32_ioctl f32_ioctl; 3111 3112 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3113 sizeof (struct fcp32_ioctl), mode)) { 3114 return (EFAULT); 3115 } 3116 fioctl->fp_minor = f32_ioctl.fp_minor; 3117 fioctl->listlen = f32_ioctl.listlen; 3118 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3119 break; 3120 } 3121 case DDI_MODEL_NONE: 3122 if (ddi_copyin((void *)data, (void *)fioctl, 3123 sizeof (struct fcp_ioctl), mode)) { 3124 return (EFAULT); 3125 } 3126 break; 3127 } 3128 3129 #else /* _MULTI_DATAMODEL */ 3130 if (ddi_copyin((void *)data, (void *)fioctl, 3131 sizeof (struct fcp_ioctl), mode)) { 3132 return (EFAULT); 3133 } 3134 #endif /* _MULTI_DATAMODEL */ 3135 3136 /* 3137 * Right now we can assume that the minor number matches with 3138 * this instance of fp. If this changes we will need to 3139 * revisit this logic. 3140 */ 3141 mutex_enter(&fcp_global_mutex); 3142 t_pptr = fcp_port_head; 3143 while (t_pptr) { 3144 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3145 break; 3146 } else { 3147 t_pptr = t_pptr->port_next; 3148 } 3149 } 3150 *pptr = t_pptr; 3151 mutex_exit(&fcp_global_mutex); 3152 if (t_pptr == NULL) { 3153 return (ENXIO); 3154 } 3155 3156 return (0); 3157 } 3158 3159 /* 3160 * Function: fcp_port_create_tgt 3161 * 3162 * Description: As the name suggest this function creates the target context 3163 * specified by the the WWN provided by the caller. If the 3164 * creation goes well and the target is known by fp/fctl a PLOGI 3165 * followed by a PRLI are issued. 3166 * 3167 * Argument: pptr fcp port structure 3168 * pwwn WWN of the target 3169 * ret_val Address of the return code. It could be: 3170 * EIO, ENOMEM or 0. 3171 * fc_status PLOGI or PRLI status completion 3172 * fc_pkt_state PLOGI or PRLI state completion 3173 * fc_pkt_reason PLOGI or PRLI reason completion 3174 * fc_pkt_action PLOGI or PRLI action completion 3175 * 3176 * Return Value: NULL if it failed 3177 * Target structure address if it succeeds 3178 */ 3179 static struct fcp_tgt * 3180 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3181 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3182 { 3183 struct fcp_tgt *ptgt = NULL; 3184 fc_portmap_t devlist; 3185 int lcount; 3186 int error; 3187 3188 *ret_val = 0; 3189 3190 /* 3191 * Check FC port device & get port map 3192 */ 3193 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3194 &error, 1) == NULL) { 3195 *ret_val = EIO; 3196 } else { 3197 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3198 &devlist) != FC_SUCCESS) { 3199 *ret_val = EIO; 3200 } 3201 } 3202 3203 /* Set port map flags */ 3204 devlist.map_type = PORT_DEVICE_USER_CREATE; 3205 3206 /* Allocate target */ 3207 if (*ret_val == 0) { 3208 lcount = pptr->port_link_cnt; 3209 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3210 if (ptgt == NULL) { 3211 fcp_log(CE_WARN, pptr->port_dip, 3212 "!FC target allocation failed"); 3213 *ret_val = ENOMEM; 3214 } else { 3215 /* Setup target */ 3216 mutex_enter(&ptgt->tgt_mutex); 3217 3218 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3219 ptgt->tgt_tmp_cnt = 1; 3220 ptgt->tgt_d_id = devlist.map_did.port_id; 3221 ptgt->tgt_hard_addr = 3222 devlist.map_hard_addr.hard_addr; 3223 ptgt->tgt_pd_handle = devlist.map_pd; 3224 ptgt->tgt_fca_dev = NULL; 3225 3226 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3227 FC_WWN_SIZE); 3228 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3229 FC_WWN_SIZE); 3230 3231 mutex_exit(&ptgt->tgt_mutex); 3232 } 3233 } 3234 3235 /* Release global mutex for PLOGI and PRLI */ 3236 mutex_exit(&fcp_global_mutex); 3237 3238 /* Send PLOGI (If necessary) */ 3239 if (*ret_val == 0) { 3240 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3241 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3242 } 3243 3244 /* Send PRLI (If necessary) */ 3245 if (*ret_val == 0) { 3246 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3247 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3248 } 3249 3250 mutex_enter(&fcp_global_mutex); 3251 3252 return (ptgt); 3253 } 3254 3255 /* 3256 * Function: fcp_tgt_send_plogi 3257 * 3258 * Description: This function sends a PLOGI to the target specified by the 3259 * caller and waits till it completes. 3260 * 3261 * Argument: ptgt Target to send the plogi to. 3262 * fc_status Status returned by fp/fctl in the PLOGI request. 3263 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3264 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3265 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3266 * 3267 * Return Value: 0 3268 * ENOMEM 3269 * EIO 3270 * 3271 * Context: User context. 3272 */ 3273 static int 3274 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3275 int *fc_pkt_reason, int *fc_pkt_action) 3276 { 3277 struct fcp_port *pptr; 3278 struct fcp_ipkt *icmd; 3279 struct fc_packet *fpkt; 3280 fc_frame_hdr_t *hp; 3281 struct la_els_logi logi; 3282 int tcount; 3283 int lcount; 3284 int ret, login_retval = ~FC_SUCCESS; 3285 3286 ret = 0; 3287 3288 pptr = ptgt->tgt_port; 3289 3290 lcount = pptr->port_link_cnt; 3291 tcount = ptgt->tgt_change_cnt; 3292 3293 /* Alloc internal packet */ 3294 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3295 sizeof (la_els_logi_t), 0, 3296 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3297 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3298 3299 if (icmd == NULL) { 3300 ret = ENOMEM; 3301 } else { 3302 /* 3303 * Setup internal packet as sema sync 3304 */ 3305 fcp_ipkt_sema_init(icmd); 3306 3307 /* 3308 * Setup internal packet (icmd) 3309 */ 3310 icmd->ipkt_lun = NULL; 3311 icmd->ipkt_restart = 0; 3312 icmd->ipkt_retries = 0; 3313 icmd->ipkt_opcode = LA_ELS_PLOGI; 3314 3315 /* 3316 * Setup fc_packet 3317 */ 3318 fpkt = icmd->ipkt_fpkt; 3319 3320 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3321 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3322 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3323 3324 /* 3325 * Setup FC frame header 3326 */ 3327 hp = &fpkt->pkt_cmd_fhdr; 3328 3329 hp->s_id = pptr->port_id; /* source ID */ 3330 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3331 hp->r_ctl = R_CTL_ELS_REQ; 3332 hp->type = FC_TYPE_EXTENDED_LS; 3333 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3334 hp->seq_id = 0; 3335 hp->rsvd = 0; 3336 hp->df_ctl = 0; 3337 hp->seq_cnt = 0; 3338 hp->ox_id = 0xffff; /* i.e. none */ 3339 hp->rx_id = 0xffff; /* i.e. none */ 3340 hp->ro = 0; 3341 3342 /* 3343 * Setup PLOGI 3344 */ 3345 bzero(&logi, sizeof (struct la_els_logi)); 3346 logi.ls_code.ls_code = LA_ELS_PLOGI; 3347 3348 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3349 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3350 3351 /* 3352 * Send PLOGI 3353 */ 3354 *fc_status = login_retval = 3355 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3356 if (*fc_status != FC_SUCCESS) { 3357 ret = EIO; 3358 } 3359 } 3360 3361 /* 3362 * Wait for completion 3363 */ 3364 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3365 ret = fcp_ipkt_sema_wait(icmd); 3366 3367 *fc_pkt_state = fpkt->pkt_state; 3368 *fc_pkt_reason = fpkt->pkt_reason; 3369 *fc_pkt_action = fpkt->pkt_action; 3370 } 3371 3372 /* 3373 * Cleanup transport data structures if icmd was alloc-ed AND if there 3374 * is going to be no callback (i.e if fc_ulp_login() failed). 3375 * Otherwise, cleanup happens in callback routine. 3376 */ 3377 if (icmd != NULL) { 3378 fcp_ipkt_sema_cleanup(icmd); 3379 } 3380 3381 return (ret); 3382 } 3383 3384 /* 3385 * Function: fcp_tgt_send_prli 3386 * 3387 * Description: Does nothing as of today. 3388 * 3389 * Argument: ptgt Target to send the prli to. 3390 * fc_status Status returned by fp/fctl in the PRLI request. 3391 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3392 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3393 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3394 * 3395 * Return Value: 0 3396 */ 3397 /*ARGSUSED*/ 3398 static int 3399 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3400 int *fc_pkt_reason, int *fc_pkt_action) 3401 { 3402 return (0); 3403 } 3404 3405 /* 3406 * Function: fcp_ipkt_sema_init 3407 * 3408 * Description: Initializes the semaphore contained in the internal packet. 3409 * 3410 * Argument: icmd Internal packet the semaphore of which must be 3411 * initialized. 3412 * 3413 * Return Value: None 3414 * 3415 * Context: User context only. 3416 */ 3417 static void 3418 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3419 { 3420 struct fc_packet *fpkt; 3421 3422 fpkt = icmd->ipkt_fpkt; 3423 3424 /* Create semaphore for sync */ 3425 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3426 3427 /* Setup the completion callback */ 3428 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3429 } 3430 3431 /* 3432 * Function: fcp_ipkt_sema_wait 3433 * 3434 * Description: Wait on the semaphore embedded in the internal packet. The 3435 * semaphore is released in the callback. 3436 * 3437 * Argument: icmd Internal packet to wait on for completion. 3438 * 3439 * Return Value: 0 3440 * EIO 3441 * EBUSY 3442 * EAGAIN 3443 * 3444 * Context: User context only. 3445 * 3446 * This function does a conversion between the field pkt_state of the fc_packet 3447 * embedded in the internal packet (icmd) and the code it returns. 3448 */ 3449 static int 3450 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3451 { 3452 struct fc_packet *fpkt; 3453 int ret; 3454 3455 ret = EIO; 3456 fpkt = icmd->ipkt_fpkt; 3457 3458 /* 3459 * Wait on semaphore 3460 */ 3461 sema_p(&(icmd->ipkt_sema)); 3462 3463 /* 3464 * Check the status of the FC packet 3465 */ 3466 switch (fpkt->pkt_state) { 3467 case FC_PKT_SUCCESS: 3468 ret = 0; 3469 break; 3470 case FC_PKT_LOCAL_RJT: 3471 switch (fpkt->pkt_reason) { 3472 case FC_REASON_SEQ_TIMEOUT: 3473 case FC_REASON_RX_BUF_TIMEOUT: 3474 ret = EAGAIN; 3475 break; 3476 case FC_REASON_PKT_BUSY: 3477 ret = EBUSY; 3478 break; 3479 } 3480 break; 3481 case FC_PKT_TIMEOUT: 3482 ret = EAGAIN; 3483 break; 3484 case FC_PKT_LOCAL_BSY: 3485 case FC_PKT_TRAN_BSY: 3486 case FC_PKT_NPORT_BSY: 3487 case FC_PKT_FABRIC_BSY: 3488 ret = EBUSY; 3489 break; 3490 case FC_PKT_LS_RJT: 3491 case FC_PKT_BA_RJT: 3492 switch (fpkt->pkt_reason) { 3493 case FC_REASON_LOGICAL_BSY: 3494 ret = EBUSY; 3495 break; 3496 } 3497 break; 3498 case FC_PKT_FS_RJT: 3499 switch (fpkt->pkt_reason) { 3500 case FC_REASON_FS_LOGICAL_BUSY: 3501 ret = EBUSY; 3502 break; 3503 } 3504 break; 3505 } 3506 3507 return (ret); 3508 } 3509 3510 /* 3511 * Function: fcp_ipkt_sema_callback 3512 * 3513 * Description: Registered as the completion callback function for the FC 3514 * transport when the ipkt semaphore is used for sync. This will 3515 * cleanup the used data structures, if necessary and wake up 3516 * the user thread to complete the transaction. 3517 * 3518 * Argument: fpkt FC packet (points to the icmd) 3519 * 3520 * Return Value: None 3521 * 3522 * Context: User context only 3523 */ 3524 static void 3525 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3526 { 3527 struct fcp_ipkt *icmd; 3528 3529 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3530 3531 /* 3532 * Wake up user thread 3533 */ 3534 sema_v(&(icmd->ipkt_sema)); 3535 } 3536 3537 /* 3538 * Function: fcp_ipkt_sema_cleanup 3539 * 3540 * Description: Called to cleanup (if necessary) the data structures used 3541 * when ipkt sema is used for sync. This function will detect 3542 * whether the caller is the last thread (via counter) and 3543 * cleanup only if necessary. 3544 * 3545 * Argument: icmd Internal command packet 3546 * 3547 * Return Value: None 3548 * 3549 * Context: User context only 3550 */ 3551 static void 3552 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3553 { 3554 struct fcp_tgt *ptgt; 3555 struct fcp_port *pptr; 3556 3557 ptgt = icmd->ipkt_tgt; 3558 pptr = icmd->ipkt_port; 3559 3560 /* 3561 * Acquire data structure 3562 */ 3563 mutex_enter(&ptgt->tgt_mutex); 3564 3565 /* 3566 * Destroy semaphore 3567 */ 3568 sema_destroy(&(icmd->ipkt_sema)); 3569 3570 /* 3571 * Cleanup internal packet 3572 */ 3573 mutex_exit(&ptgt->tgt_mutex); 3574 fcp_icmd_free(pptr, icmd); 3575 } 3576 3577 /* 3578 * Function: fcp_port_attach 3579 * 3580 * Description: Called by the transport framework to resume, suspend or 3581 * attach a new port. 3582 * 3583 * Argument: ulph Port handle 3584 * *pinfo Port information 3585 * cmd Command 3586 * s_id Port ID 3587 * 3588 * Return Value: FC_FAILURE or FC_SUCCESS 3589 */ 3590 /*ARGSUSED*/ 3591 static int 3592 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3593 fc_attach_cmd_t cmd, uint32_t s_id) 3594 { 3595 int instance; 3596 int res = FC_FAILURE; /* default result */ 3597 3598 ASSERT(pinfo != NULL); 3599 3600 instance = ddi_get_instance(pinfo->port_dip); 3601 3602 switch (cmd) { 3603 case FC_CMD_ATTACH: 3604 /* 3605 * this port instance attaching for the first time (or after 3606 * being detached before) 3607 */ 3608 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3609 instance) == DDI_SUCCESS) { 3610 res = FC_SUCCESS; 3611 } else { 3612 ASSERT(ddi_get_soft_state(fcp_softstate, 3613 instance) == NULL); 3614 } 3615 break; 3616 3617 case FC_CMD_RESUME: 3618 case FC_CMD_POWER_UP: 3619 /* 3620 * this port instance was attached and the suspended and 3621 * will now be resumed 3622 */ 3623 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3624 instance) == DDI_SUCCESS) { 3625 res = FC_SUCCESS; 3626 } 3627 break; 3628 3629 default: 3630 /* shouldn't happen */ 3631 FCP_TRACE(fcp_logq, "fcp", 3632 fcp_trace, FCP_BUF_LEVEL_2, 0, 3633 "port_attach: unknown cmdcommand: %d", cmd); 3634 break; 3635 } 3636 3637 /* return result */ 3638 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3639 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3640 3641 return (res); 3642 } 3643 3644 3645 /* 3646 * detach or suspend this port instance 3647 * 3648 * acquires and releases the global mutex 3649 * 3650 * acquires and releases the mutex for this port 3651 * 3652 * acquires and releases the hotplug mutex for this port 3653 */ 3654 /*ARGSUSED*/ 3655 static int 3656 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3657 fc_detach_cmd_t cmd) 3658 { 3659 int flag; 3660 int instance; 3661 struct fcp_port *pptr; 3662 3663 instance = ddi_get_instance(info->port_dip); 3664 pptr = ddi_get_soft_state(fcp_softstate, instance); 3665 3666 switch (cmd) { 3667 case FC_CMD_SUSPEND: 3668 FCP_DTRACE(fcp_logq, "fcp", 3669 fcp_trace, FCP_BUF_LEVEL_8, 0, 3670 "port suspend called for port %d", instance); 3671 flag = FCP_STATE_SUSPENDED; 3672 break; 3673 3674 case FC_CMD_POWER_DOWN: 3675 FCP_DTRACE(fcp_logq, "fcp", 3676 fcp_trace, FCP_BUF_LEVEL_8, 0, 3677 "port power down called for port %d", instance); 3678 flag = FCP_STATE_POWER_DOWN; 3679 break; 3680 3681 case FC_CMD_DETACH: 3682 FCP_DTRACE(fcp_logq, "fcp", 3683 fcp_trace, FCP_BUF_LEVEL_8, 0, 3684 "port detach called for port %d", instance); 3685 flag = FCP_STATE_DETACHING; 3686 break; 3687 3688 default: 3689 /* shouldn't happen */ 3690 return (FC_FAILURE); 3691 } 3692 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3693 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3694 3695 return (fcp_handle_port_detach(pptr, flag, instance)); 3696 } 3697 3698 3699 /* 3700 * called for ioctls on the transport's devctl interface, and the transport 3701 * has passed it to us 3702 * 3703 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3704 * 3705 * return FC_SUCCESS if we decide to claim the ioctl, 3706 * else return FC_UNCLAIMED 3707 * 3708 * *rval is set iff we decide to claim the ioctl 3709 */ 3710 /*ARGSUSED*/ 3711 static int 3712 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3713 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3714 { 3715 int retval = FC_UNCLAIMED; /* return value */ 3716 struct fcp_port *pptr = NULL; /* our soft state */ 3717 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3718 dev_info_t *cdip; 3719 mdi_pathinfo_t *pip = NULL; 3720 char *ndi_nm; /* NDI name */ 3721 char *ndi_addr; /* NDI addr */ 3722 int is_mpxio, circ; 3723 int devi_entered = 0; 3724 time_t end_time; 3725 3726 ASSERT(rval != NULL); 3727 3728 FCP_DTRACE(fcp_logq, "fcp", 3729 fcp_trace, FCP_BUF_LEVEL_8, 0, 3730 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3731 3732 /* if already claimed then forget it */ 3733 if (claimed) { 3734 /* 3735 * for now, if this ioctl has already been claimed, then 3736 * we just ignore it 3737 */ 3738 return (retval); 3739 } 3740 3741 /* get our port info */ 3742 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3743 fcp_log(CE_WARN, NULL, 3744 "!fcp:Invalid port handle handle in ioctl"); 3745 *rval = ENXIO; 3746 return (retval); 3747 } 3748 is_mpxio = pptr->port_mpxio; 3749 3750 switch (cmd) { 3751 case DEVCTL_BUS_GETSTATE: 3752 case DEVCTL_BUS_QUIESCE: 3753 case DEVCTL_BUS_UNQUIESCE: 3754 case DEVCTL_BUS_RESET: 3755 case DEVCTL_BUS_RESETALL: 3756 3757 case DEVCTL_BUS_DEV_CREATE: 3758 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3759 return (retval); 3760 } 3761 break; 3762 3763 case DEVCTL_DEVICE_GETSTATE: 3764 case DEVCTL_DEVICE_OFFLINE: 3765 case DEVCTL_DEVICE_ONLINE: 3766 case DEVCTL_DEVICE_REMOVE: 3767 case DEVCTL_DEVICE_RESET: 3768 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3769 return (retval); 3770 } 3771 3772 ASSERT(dcp != NULL); 3773 3774 /* ensure we have a name and address */ 3775 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3776 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3777 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3778 fcp_trace, FCP_BUF_LEVEL_2, 0, 3779 "ioctl: can't get name (%s) or addr (%s)", 3780 ndi_nm ? ndi_nm : "<null ptr>", 3781 ndi_addr ? ndi_addr : "<null ptr>"); 3782 ndi_dc_freehdl(dcp); 3783 return (retval); 3784 } 3785 3786 3787 /* get our child's DIP */ 3788 ASSERT(pptr != NULL); 3789 if (is_mpxio) { 3790 mdi_devi_enter(pptr->port_dip, &circ); 3791 } else { 3792 ndi_devi_enter(pptr->port_dip, &circ); 3793 } 3794 devi_entered = 1; 3795 3796 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3797 ndi_addr)) == NULL) { 3798 /* Look for virtually enumerated devices. */ 3799 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3800 if (pip == NULL || 3801 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3802 *rval = ENXIO; 3803 goto out; 3804 } 3805 } 3806 break; 3807 3808 default: 3809 *rval = ENOTTY; 3810 return (retval); 3811 } 3812 3813 /* this ioctl is ours -- process it */ 3814 3815 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3816 3817 /* we assume it will be a success; else we'll set error value */ 3818 *rval = 0; 3819 3820 3821 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3822 fcp_trace, FCP_BUF_LEVEL_8, 0, 3823 "ioctl: claiming this one"); 3824 3825 /* handle ioctls now */ 3826 switch (cmd) { 3827 case DEVCTL_DEVICE_GETSTATE: 3828 ASSERT(cdip != NULL); 3829 ASSERT(dcp != NULL); 3830 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3831 *rval = EFAULT; 3832 } 3833 break; 3834 3835 case DEVCTL_DEVICE_REMOVE: 3836 case DEVCTL_DEVICE_OFFLINE: { 3837 int flag = 0; 3838 int lcount; 3839 int tcount; 3840 struct fcp_pkt *head = NULL; 3841 struct fcp_lun *plun; 3842 child_info_t *cip = CIP(cdip); 3843 int all = 1; 3844 struct fcp_lun *tplun; 3845 struct fcp_tgt *ptgt; 3846 3847 ASSERT(pptr != NULL); 3848 ASSERT(cdip != NULL); 3849 3850 mutex_enter(&pptr->port_mutex); 3851 if (pip != NULL) { 3852 cip = CIP(pip); 3853 } 3854 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3855 mutex_exit(&pptr->port_mutex); 3856 *rval = ENXIO; 3857 break; 3858 } 3859 3860 head = fcp_scan_commands(plun); 3861 if (head != NULL) { 3862 fcp_abort_commands(head, LUN_PORT); 3863 } 3864 lcount = pptr->port_link_cnt; 3865 tcount = plun->lun_tgt->tgt_change_cnt; 3866 mutex_exit(&pptr->port_mutex); 3867 3868 if (cmd == DEVCTL_DEVICE_REMOVE) { 3869 flag = NDI_DEVI_REMOVE; 3870 } 3871 3872 if (is_mpxio) { 3873 mdi_devi_exit(pptr->port_dip, circ); 3874 } else { 3875 ndi_devi_exit(pptr->port_dip, circ); 3876 } 3877 devi_entered = 0; 3878 3879 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3880 FCP_OFFLINE, lcount, tcount, flag); 3881 3882 if (*rval != NDI_SUCCESS) { 3883 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3884 break; 3885 } 3886 3887 fcp_update_offline_flags(plun); 3888 3889 ptgt = plun->lun_tgt; 3890 mutex_enter(&ptgt->tgt_mutex); 3891 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3892 tplun->lun_next) { 3893 mutex_enter(&tplun->lun_mutex); 3894 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3895 all = 0; 3896 } 3897 mutex_exit(&tplun->lun_mutex); 3898 } 3899 3900 if (all) { 3901 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3902 /* 3903 * The user is unconfiguring/offlining the device. 3904 * If fabric and the auto configuration is set 3905 * then make sure the user is the only one who 3906 * can reconfigure the device. 3907 */ 3908 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3909 fcp_enable_auto_configuration) { 3910 ptgt->tgt_manual_config_only = 1; 3911 } 3912 } 3913 mutex_exit(&ptgt->tgt_mutex); 3914 break; 3915 } 3916 3917 case DEVCTL_DEVICE_ONLINE: { 3918 int lcount; 3919 int tcount; 3920 struct fcp_lun *plun; 3921 child_info_t *cip = CIP(cdip); 3922 3923 ASSERT(cdip != NULL); 3924 ASSERT(pptr != NULL); 3925 3926 mutex_enter(&pptr->port_mutex); 3927 if (pip != NULL) { 3928 cip = CIP(pip); 3929 } 3930 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3931 mutex_exit(&pptr->port_mutex); 3932 *rval = ENXIO; 3933 break; 3934 } 3935 lcount = pptr->port_link_cnt; 3936 tcount = plun->lun_tgt->tgt_change_cnt; 3937 mutex_exit(&pptr->port_mutex); 3938 3939 /* 3940 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3941 * to allow the device attach to occur when the device is 3942 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3943 * from the scsi_probe()). 3944 */ 3945 mutex_enter(&LUN_TGT->tgt_mutex); 3946 plun->lun_state |= FCP_LUN_ONLINING; 3947 mutex_exit(&LUN_TGT->tgt_mutex); 3948 3949 if (is_mpxio) { 3950 mdi_devi_exit(pptr->port_dip, circ); 3951 } else { 3952 ndi_devi_exit(pptr->port_dip, circ); 3953 } 3954 devi_entered = 0; 3955 3956 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3957 FCP_ONLINE, lcount, tcount, 0); 3958 3959 if (*rval != NDI_SUCCESS) { 3960 /* Reset the FCP_LUN_ONLINING bit */ 3961 mutex_enter(&LUN_TGT->tgt_mutex); 3962 plun->lun_state &= ~FCP_LUN_ONLINING; 3963 mutex_exit(&LUN_TGT->tgt_mutex); 3964 *rval = EIO; 3965 break; 3966 } 3967 mutex_enter(&LUN_TGT->tgt_mutex); 3968 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3969 FCP_LUN_ONLINING); 3970 mutex_exit(&LUN_TGT->tgt_mutex); 3971 break; 3972 } 3973 3974 case DEVCTL_BUS_DEV_CREATE: { 3975 uchar_t *bytes = NULL; 3976 uint_t nbytes; 3977 struct fcp_tgt *ptgt = NULL; 3978 struct fcp_lun *plun = NULL; 3979 dev_info_t *useless_dip = NULL; 3980 3981 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3982 DEVCTL_CONSTRUCT, &useless_dip); 3983 if (*rval != 0 || useless_dip == NULL) { 3984 break; 3985 } 3986 3987 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3988 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3989 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3990 *rval = EINVAL; 3991 (void) ndi_devi_free(useless_dip); 3992 if (bytes != NULL) { 3993 ddi_prop_free(bytes); 3994 } 3995 break; 3996 } 3997 3998 *rval = fcp_create_on_demand(pptr, bytes); 3999 if (*rval == 0) { 4000 mutex_enter(&pptr->port_mutex); 4001 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 4002 if (ptgt) { 4003 /* 4004 * We now have a pointer to the target that 4005 * was created. Lets point to the first LUN on 4006 * this new target. 4007 */ 4008 mutex_enter(&ptgt->tgt_mutex); 4009 4010 plun = ptgt->tgt_lun; 4011 /* 4012 * There may be stale/offline LUN entries on 4013 * this list (this is by design) and so we have 4014 * to make sure we point to the first online 4015 * LUN 4016 */ 4017 while (plun && 4018 plun->lun_state & FCP_LUN_OFFLINE) { 4019 plun = plun->lun_next; 4020 } 4021 4022 mutex_exit(&ptgt->tgt_mutex); 4023 } 4024 mutex_exit(&pptr->port_mutex); 4025 } 4026 4027 if (*rval == 0 && ptgt && plun) { 4028 mutex_enter(&plun->lun_mutex); 4029 /* 4030 * Allow up to fcp_lun_ready_retry seconds to 4031 * configure all the luns behind the target. 4032 * 4033 * The intent here is to allow targets with long 4034 * reboot/reset-recovery times to become available 4035 * while limiting the maximum wait time for an 4036 * unresponsive target. 4037 */ 4038 end_time = ddi_get_lbolt() + 4039 SEC_TO_TICK(fcp_lun_ready_retry); 4040 4041 while (ddi_get_lbolt() < end_time) { 4042 retval = FC_SUCCESS; 4043 4044 /* 4045 * The new ndi interfaces for on-demand creation 4046 * are inflexible, Do some more work to pass on 4047 * a path name of some LUN (design is broken !) 4048 */ 4049 if (plun->lun_cip) { 4050 if (plun->lun_mpxio == 0) { 4051 cdip = DIP(plun->lun_cip); 4052 } else { 4053 cdip = mdi_pi_get_client( 4054 PIP(plun->lun_cip)); 4055 } 4056 if (cdip == NULL) { 4057 *rval = ENXIO; 4058 break; 4059 } 4060 4061 if (!i_ddi_devi_attached(cdip)) { 4062 mutex_exit(&plun->lun_mutex); 4063 delay(drv_usectohz(1000000)); 4064 mutex_enter(&plun->lun_mutex); 4065 } else { 4066 /* 4067 * This Lun is ready, lets 4068 * check the next one. 4069 */ 4070 mutex_exit(&plun->lun_mutex); 4071 plun = plun->lun_next; 4072 while (plun && (plun->lun_state 4073 & FCP_LUN_OFFLINE)) { 4074 plun = plun->lun_next; 4075 } 4076 if (!plun) { 4077 break; 4078 } 4079 mutex_enter(&plun->lun_mutex); 4080 } 4081 } else { 4082 /* 4083 * lun_cip field for a valid lun 4084 * should never be NULL. Fail the 4085 * command. 4086 */ 4087 *rval = ENXIO; 4088 break; 4089 } 4090 } 4091 if (plun) { 4092 mutex_exit(&plun->lun_mutex); 4093 } else { 4094 char devnm[MAXNAMELEN]; 4095 int nmlen; 4096 4097 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4098 ddi_node_name(cdip), 4099 ddi_get_name_addr(cdip)); 4100 4101 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4102 0) { 4103 *rval = EFAULT; 4104 } 4105 } 4106 } else { 4107 int i; 4108 char buf[25]; 4109 4110 for (i = 0; i < FC_WWN_SIZE; i++) { 4111 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4112 } 4113 4114 fcp_log(CE_WARN, pptr->port_dip, 4115 "!Failed to create nodes for pwwn=%s; error=%x", 4116 buf, *rval); 4117 } 4118 4119 (void) ndi_devi_free(useless_dip); 4120 ddi_prop_free(bytes); 4121 break; 4122 } 4123 4124 case DEVCTL_DEVICE_RESET: { 4125 struct fcp_lun *plun; 4126 child_info_t *cip = CIP(cdip); 4127 4128 ASSERT(cdip != NULL); 4129 ASSERT(pptr != NULL); 4130 mutex_enter(&pptr->port_mutex); 4131 if (pip != NULL) { 4132 cip = CIP(pip); 4133 } 4134 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4135 mutex_exit(&pptr->port_mutex); 4136 *rval = ENXIO; 4137 break; 4138 } 4139 mutex_exit(&pptr->port_mutex); 4140 4141 mutex_enter(&plun->lun_tgt->tgt_mutex); 4142 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4143 mutex_exit(&plun->lun_tgt->tgt_mutex); 4144 4145 *rval = ENXIO; 4146 break; 4147 } 4148 4149 if (plun->lun_sd == NULL) { 4150 mutex_exit(&plun->lun_tgt->tgt_mutex); 4151 4152 *rval = ENXIO; 4153 break; 4154 } 4155 mutex_exit(&plun->lun_tgt->tgt_mutex); 4156 4157 /* 4158 * set up ap so that fcp_reset can figure out 4159 * which target to reset 4160 */ 4161 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4162 RESET_TARGET) == FALSE) { 4163 *rval = EIO; 4164 } 4165 break; 4166 } 4167 4168 case DEVCTL_BUS_GETSTATE: 4169 ASSERT(dcp != NULL); 4170 ASSERT(pptr != NULL); 4171 ASSERT(pptr->port_dip != NULL); 4172 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4173 NDI_SUCCESS) { 4174 *rval = EFAULT; 4175 } 4176 break; 4177 4178 case DEVCTL_BUS_QUIESCE: 4179 case DEVCTL_BUS_UNQUIESCE: 4180 *rval = ENOTSUP; 4181 break; 4182 4183 case DEVCTL_BUS_RESET: 4184 case DEVCTL_BUS_RESETALL: 4185 ASSERT(pptr != NULL); 4186 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4187 break; 4188 4189 default: 4190 ASSERT(dcp != NULL); 4191 *rval = ENOTTY; 4192 break; 4193 } 4194 4195 /* all done -- clean up and return */ 4196 out: if (devi_entered) { 4197 if (is_mpxio) { 4198 mdi_devi_exit(pptr->port_dip, circ); 4199 } else { 4200 ndi_devi_exit(pptr->port_dip, circ); 4201 } 4202 } 4203 4204 if (dcp != NULL) { 4205 ndi_dc_freehdl(dcp); 4206 } 4207 4208 return (retval); 4209 } 4210 4211 4212 /*ARGSUSED*/ 4213 static int 4214 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4215 uint32_t claimed) 4216 { 4217 uchar_t r_ctl; 4218 uchar_t ls_code; 4219 struct fcp_port *pptr; 4220 4221 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4222 return (FC_UNCLAIMED); 4223 } 4224 4225 mutex_enter(&pptr->port_mutex); 4226 if (pptr->port_state & (FCP_STATE_DETACHING | 4227 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4228 mutex_exit(&pptr->port_mutex); 4229 return (FC_UNCLAIMED); 4230 } 4231 mutex_exit(&pptr->port_mutex); 4232 4233 r_ctl = buf->ub_frame.r_ctl; 4234 4235 switch (r_ctl & R_CTL_ROUTING) { 4236 case R_CTL_EXTENDED_SVC: 4237 if (r_ctl == R_CTL_ELS_REQ) { 4238 ls_code = buf->ub_buffer[0]; 4239 4240 switch (ls_code) { 4241 case LA_ELS_PRLI: 4242 /* 4243 * We really don't care if something fails. 4244 * If the PRLI was not sent out, then the 4245 * other end will time it out. 4246 */ 4247 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4248 return (FC_SUCCESS); 4249 } 4250 return (FC_UNCLAIMED); 4251 /* NOTREACHED */ 4252 4253 default: 4254 break; 4255 } 4256 } 4257 /* FALLTHROUGH */ 4258 4259 default: 4260 return (FC_UNCLAIMED); 4261 } 4262 } 4263 4264 4265 /*ARGSUSED*/ 4266 static int 4267 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4268 uint32_t claimed) 4269 { 4270 return (FC_UNCLAIMED); 4271 } 4272 4273 /* 4274 * Function: fcp_statec_callback 4275 * 4276 * Description: The purpose of this function is to handle a port state change. 4277 * It is called from fp/fctl and, in a few instances, internally. 4278 * 4279 * Argument: ulph fp/fctl port handle 4280 * port_handle fcp_port structure 4281 * port_state Physical state of the port 4282 * port_top Topology 4283 * *devlist Pointer to the first entry of a table 4284 * containing the remote ports that can be 4285 * reached. 4286 * dev_cnt Number of entries pointed by devlist. 4287 * port_sid Port ID of the local port. 4288 * 4289 * Return Value: None 4290 */ 4291 /*ARGSUSED*/ 4292 static void 4293 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4294 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4295 uint32_t dev_cnt, uint32_t port_sid) 4296 { 4297 uint32_t link_count; 4298 int map_len = 0; 4299 struct fcp_port *pptr; 4300 fcp_map_tag_t *map_tag = NULL; 4301 4302 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4303 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4304 return; /* nothing to work with! */ 4305 } 4306 4307 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4308 fcp_trace, FCP_BUF_LEVEL_2, 0, 4309 "fcp_statec_callback: port state/dev_cnt/top =" 4310 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4311 dev_cnt, port_top); 4312 4313 mutex_enter(&pptr->port_mutex); 4314 4315 /* 4316 * If a thread is in detach, don't do anything. 4317 */ 4318 if (pptr->port_state & (FCP_STATE_DETACHING | 4319 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4320 mutex_exit(&pptr->port_mutex); 4321 return; 4322 } 4323 4324 /* 4325 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4326 * init_pkt is called, it knows whether or not the target's status 4327 * (or pd) might be changing. 4328 */ 4329 4330 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4331 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4332 } 4333 4334 /* 4335 * the transport doesn't allocate or probe unless being 4336 * asked to by either the applications or ULPs 4337 * 4338 * in cases where the port is OFFLINE at the time of port 4339 * attach callback and the link comes ONLINE later, for 4340 * easier automatic node creation (i.e. without you having to 4341 * go out and run the utility to perform LOGINs) the 4342 * following conditional is helpful 4343 */ 4344 pptr->port_phys_state = port_state; 4345 4346 if (dev_cnt) { 4347 mutex_exit(&pptr->port_mutex); 4348 4349 map_len = sizeof (*map_tag) * dev_cnt; 4350 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4351 if (map_tag == NULL) { 4352 fcp_log(CE_WARN, pptr->port_dip, 4353 "!fcp%d: failed to allocate for map tags; " 4354 " state change will not be processed", 4355 pptr->port_instance); 4356 4357 mutex_enter(&pptr->port_mutex); 4358 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4359 mutex_exit(&pptr->port_mutex); 4360 4361 return; 4362 } 4363 4364 mutex_enter(&pptr->port_mutex); 4365 } 4366 4367 if (pptr->port_id != port_sid) { 4368 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4369 fcp_trace, FCP_BUF_LEVEL_3, 0, 4370 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4371 port_sid); 4372 /* 4373 * The local port changed ID. It is the first time a port ID 4374 * is assigned or something drastic happened. We might have 4375 * been unplugged and replugged on another loop or fabric port 4376 * or somebody grabbed the AL_PA we had or somebody rezoned 4377 * the fabric we were plugged into. 4378 */ 4379 pptr->port_id = port_sid; 4380 } 4381 4382 switch (FC_PORT_STATE_MASK(port_state)) { 4383 case FC_STATE_OFFLINE: 4384 case FC_STATE_RESET_REQUESTED: 4385 /* 4386 * link has gone from online to offline -- just update the 4387 * state of this port to BUSY and MARKed to go offline 4388 */ 4389 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4390 fcp_trace, FCP_BUF_LEVEL_3, 0, 4391 "link went offline"); 4392 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4393 /* 4394 * We were offline a while ago and this one 4395 * seems to indicate that the loop has gone 4396 * dead forever. 4397 */ 4398 pptr->port_tmp_cnt += dev_cnt; 4399 pptr->port_state &= ~FCP_STATE_OFFLINE; 4400 pptr->port_state |= FCP_STATE_INIT; 4401 link_count = pptr->port_link_cnt; 4402 fcp_handle_devices(pptr, devlist, dev_cnt, 4403 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4404 } else { 4405 pptr->port_link_cnt++; 4406 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4407 fcp_update_state(pptr, (FCP_LUN_BUSY | 4408 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4409 if (pptr->port_mpxio) { 4410 fcp_update_mpxio_path_verifybusy(pptr); 4411 } 4412 pptr->port_state |= FCP_STATE_OFFLINE; 4413 pptr->port_state &= 4414 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4415 pptr->port_tmp_cnt = 0; 4416 } 4417 mutex_exit(&pptr->port_mutex); 4418 break; 4419 4420 case FC_STATE_ONLINE: 4421 case FC_STATE_LIP: 4422 case FC_STATE_LIP_LBIT_SET: 4423 /* 4424 * link has gone from offline to online 4425 */ 4426 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4427 fcp_trace, FCP_BUF_LEVEL_3, 0, 4428 "link went online"); 4429 4430 pptr->port_link_cnt++; 4431 4432 while (pptr->port_ipkt_cnt) { 4433 mutex_exit(&pptr->port_mutex); 4434 delay(drv_usectohz(1000000)); 4435 mutex_enter(&pptr->port_mutex); 4436 } 4437 4438 pptr->port_topology = port_top; 4439 4440 /* 4441 * The state of the targets and luns accessible through this 4442 * port is updated. 4443 */ 4444 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4445 FCP_CAUSE_LINK_CHANGE); 4446 4447 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4448 pptr->port_state |= FCP_STATE_ONLINING; 4449 pptr->port_tmp_cnt = dev_cnt; 4450 link_count = pptr->port_link_cnt; 4451 4452 pptr->port_deadline = fcp_watchdog_time + 4453 FCP_ICMD_DEADLINE; 4454 4455 if (!dev_cnt) { 4456 /* 4457 * We go directly to the online state if no remote 4458 * ports were discovered. 4459 */ 4460 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4461 fcp_trace, FCP_BUF_LEVEL_3, 0, 4462 "No remote ports discovered"); 4463 4464 pptr->port_state &= ~FCP_STATE_ONLINING; 4465 pptr->port_state |= FCP_STATE_ONLINE; 4466 } 4467 4468 switch (port_top) { 4469 case FC_TOP_FABRIC: 4470 case FC_TOP_PUBLIC_LOOP: 4471 case FC_TOP_PRIVATE_LOOP: 4472 case FC_TOP_PT_PT: 4473 4474 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4475 fcp_retry_ns_registry(pptr, port_sid); 4476 } 4477 4478 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4479 map_tag, FCP_CAUSE_LINK_CHANGE); 4480 break; 4481 4482 default: 4483 /* 4484 * We got here because we were provided with an unknown 4485 * topology. 4486 */ 4487 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4488 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4489 } 4490 4491 pptr->port_tmp_cnt -= dev_cnt; 4492 fcp_log(CE_WARN, pptr->port_dip, 4493 "!unknown/unsupported topology (0x%x)", port_top); 4494 break; 4495 } 4496 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4497 fcp_trace, FCP_BUF_LEVEL_3, 0, 4498 "Notify ssd of the reset to reinstate the reservations"); 4499 4500 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4501 &pptr->port_reset_notify_listf); 4502 4503 mutex_exit(&pptr->port_mutex); 4504 4505 break; 4506 4507 case FC_STATE_RESET: 4508 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4509 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4510 fcp_trace, FCP_BUF_LEVEL_3, 0, 4511 "RESET state, waiting for Offline/Online state_cb"); 4512 mutex_exit(&pptr->port_mutex); 4513 break; 4514 4515 case FC_STATE_DEVICE_CHANGE: 4516 /* 4517 * We come here when an application has requested 4518 * Dynamic node creation/deletion in Fabric connectivity. 4519 */ 4520 if (pptr->port_state & (FCP_STATE_OFFLINE | 4521 FCP_STATE_INIT)) { 4522 /* 4523 * This case can happen when the FCTL is in the 4524 * process of giving us on online and the host on 4525 * the other side issues a PLOGI/PLOGO. Ideally 4526 * the state changes should be serialized unless 4527 * they are opposite (online-offline). 4528 * The transport will give us a final state change 4529 * so we can ignore this for the time being. 4530 */ 4531 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4532 mutex_exit(&pptr->port_mutex); 4533 break; 4534 } 4535 4536 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4537 fcp_retry_ns_registry(pptr, port_sid); 4538 } 4539 4540 /* 4541 * Extend the deadline under steady state conditions 4542 * to provide more time for the device-change-commands 4543 */ 4544 if (!pptr->port_ipkt_cnt) { 4545 pptr->port_deadline = fcp_watchdog_time + 4546 FCP_ICMD_DEADLINE; 4547 } 4548 4549 /* 4550 * There is another race condition here, where if we were 4551 * in ONLINEING state and a devices in the map logs out, 4552 * fp will give another state change as DEVICE_CHANGE 4553 * and OLD. This will result in that target being offlined. 4554 * The pd_handle is freed. If from the first statec callback 4555 * we were going to fire a PLOGI/PRLI, the system will 4556 * panic in fc_ulp_transport with invalid pd_handle. 4557 * The fix is to check for the link_cnt before issuing 4558 * any command down. 4559 */ 4560 fcp_update_targets(pptr, devlist, dev_cnt, 4561 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4562 4563 link_count = pptr->port_link_cnt; 4564 4565 fcp_handle_devices(pptr, devlist, dev_cnt, 4566 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4567 4568 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4569 4570 mutex_exit(&pptr->port_mutex); 4571 break; 4572 4573 case FC_STATE_TARGET_PORT_RESET: 4574 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4575 fcp_retry_ns_registry(pptr, port_sid); 4576 } 4577 4578 /* Do nothing else */ 4579 mutex_exit(&pptr->port_mutex); 4580 break; 4581 4582 default: 4583 fcp_log(CE_WARN, pptr->port_dip, 4584 "!Invalid state change=0x%x", port_state); 4585 mutex_exit(&pptr->port_mutex); 4586 break; 4587 } 4588 4589 if (map_tag) { 4590 kmem_free(map_tag, map_len); 4591 } 4592 } 4593 4594 /* 4595 * Function: fcp_handle_devices 4596 * 4597 * Description: This function updates the devices currently known by 4598 * walking the list provided by the caller. The list passed 4599 * by the caller is supposed to be the list of reachable 4600 * devices. 4601 * 4602 * Argument: *pptr Fcp port structure. 4603 * *devlist Pointer to the first entry of a table 4604 * containing the remote ports that can be 4605 * reached. 4606 * dev_cnt Number of entries pointed by devlist. 4607 * link_cnt Link state count. 4608 * *map_tag Array of fcp_map_tag_t structures. 4609 * cause What caused this function to be called. 4610 * 4611 * Return Value: None 4612 * 4613 * Notes: The pptr->port_mutex must be held. 4614 */ 4615 static void 4616 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4617 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4618 { 4619 int i; 4620 int check_finish_init = 0; 4621 fc_portmap_t *map_entry; 4622 struct fcp_tgt *ptgt = NULL; 4623 4624 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4625 fcp_trace, FCP_BUF_LEVEL_3, 0, 4626 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4627 4628 if (dev_cnt) { 4629 ASSERT(map_tag != NULL); 4630 } 4631 4632 /* 4633 * The following code goes through the list of remote ports that are 4634 * accessible through this (pptr) local port (The list walked is the 4635 * one provided by the caller which is the list of the remote ports 4636 * currently reachable). It checks if any of them was already 4637 * known by looking for the corresponding target structure based on 4638 * the world wide name. If a target is part of the list it is tagged 4639 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4640 * 4641 * Old comment 4642 * ----------- 4643 * Before we drop port mutex; we MUST get the tags updated; This 4644 * two step process is somewhat slow, but more reliable. 4645 */ 4646 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4647 map_entry = &(devlist[i]); 4648 4649 /* 4650 * get ptr to this map entry in our port's 4651 * list (if any) 4652 */ 4653 ptgt = fcp_lookup_target(pptr, 4654 (uchar_t *)&(map_entry->map_pwwn)); 4655 4656 if (ptgt) { 4657 map_tag[i] = ptgt->tgt_change_cnt; 4658 if (cause == FCP_CAUSE_LINK_CHANGE) { 4659 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4660 } 4661 } 4662 } 4663 4664 /* 4665 * At this point we know which devices of the new list were already 4666 * known (The field tgt_aux_state of the target structure has been 4667 * set to FCP_TGT_TAGGED). 4668 * 4669 * The following code goes through the list of targets currently known 4670 * by the local port (the list is actually a hashing table). If a 4671 * target is found and is not tagged, it means the target cannot 4672 * be reached anymore through the local port (pptr). It is offlined. 4673 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4674 */ 4675 for (i = 0; i < FCP_NUM_HASH; i++) { 4676 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4677 ptgt = ptgt->tgt_next) { 4678 mutex_enter(&ptgt->tgt_mutex); 4679 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4680 (cause == FCP_CAUSE_LINK_CHANGE) && 4681 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4682 fcp_offline_target_now(pptr, ptgt, 4683 link_cnt, ptgt->tgt_change_cnt, 0); 4684 } 4685 mutex_exit(&ptgt->tgt_mutex); 4686 } 4687 } 4688 4689 /* 4690 * At this point, the devices that were known but cannot be reached 4691 * anymore, have most likely been offlined. 4692 * 4693 * The following section of code seems to go through the list of 4694 * remote ports that can now be reached. For every single one it 4695 * checks if it is already known or if it is a new port. 4696 */ 4697 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4698 4699 if (check_finish_init) { 4700 ASSERT(i > 0); 4701 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4702 map_tag[i - 1], cause); 4703 check_finish_init = 0; 4704 } 4705 4706 /* get a pointer to this map entry */ 4707 map_entry = &(devlist[i]); 4708 4709 /* 4710 * Check for the duplicate map entry flag. If we have marked 4711 * this entry as a duplicate we skip it since the correct 4712 * (perhaps even same) state change will be encountered 4713 * later in the list. 4714 */ 4715 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4716 continue; 4717 } 4718 4719 /* get ptr to this map entry in our port's list (if any) */ 4720 ptgt = fcp_lookup_target(pptr, 4721 (uchar_t *)&(map_entry->map_pwwn)); 4722 4723 if (ptgt) { 4724 /* 4725 * This device was already known. The field 4726 * tgt_aux_state is reset (was probably set to 4727 * FCP_TGT_TAGGED previously in this routine). 4728 */ 4729 ptgt->tgt_aux_state = 0; 4730 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4731 fcp_trace, FCP_BUF_LEVEL_3, 0, 4732 "handle_devices: map did/state/type/flags = " 4733 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4734 "tgt_state=%d", 4735 map_entry->map_did.port_id, map_entry->map_state, 4736 map_entry->map_type, map_entry->map_flags, 4737 ptgt->tgt_d_id, ptgt->tgt_state); 4738 } 4739 4740 if (map_entry->map_type == PORT_DEVICE_OLD || 4741 map_entry->map_type == PORT_DEVICE_NEW || 4742 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4743 map_entry->map_type == PORT_DEVICE_CHANGED) { 4744 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4745 fcp_trace, FCP_BUF_LEVEL_2, 0, 4746 "map_type=%x, did = %x", 4747 map_entry->map_type, 4748 map_entry->map_did.port_id); 4749 } 4750 4751 switch (map_entry->map_type) { 4752 case PORT_DEVICE_NOCHANGE: 4753 case PORT_DEVICE_USER_CREATE: 4754 case PORT_DEVICE_USER_LOGIN: 4755 case PORT_DEVICE_NEW: 4756 case PORT_DEVICE_REPORTLUN_CHANGED: 4757 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4758 4759 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4760 link_cnt, (ptgt) ? map_tag[i] : 0, 4761 cause) == TRUE) { 4762 4763 FCP_TGT_TRACE(ptgt, map_tag[i], 4764 FCP_TGT_TRACE_2); 4765 check_finish_init++; 4766 } 4767 break; 4768 4769 case PORT_DEVICE_OLD: 4770 if (ptgt != NULL) { 4771 FCP_TGT_TRACE(ptgt, map_tag[i], 4772 FCP_TGT_TRACE_3); 4773 4774 mutex_enter(&ptgt->tgt_mutex); 4775 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4776 /* 4777 * Must do an in-line wait for I/Os 4778 * to get drained 4779 */ 4780 mutex_exit(&ptgt->tgt_mutex); 4781 mutex_exit(&pptr->port_mutex); 4782 4783 mutex_enter(&ptgt->tgt_mutex); 4784 while (ptgt->tgt_ipkt_cnt || 4785 fcp_outstanding_lun_cmds(ptgt) 4786 == FC_SUCCESS) { 4787 mutex_exit(&ptgt->tgt_mutex); 4788 delay(drv_usectohz(1000000)); 4789 mutex_enter(&ptgt->tgt_mutex); 4790 } 4791 mutex_exit(&ptgt->tgt_mutex); 4792 4793 mutex_enter(&pptr->port_mutex); 4794 mutex_enter(&ptgt->tgt_mutex); 4795 4796 (void) fcp_offline_target(pptr, ptgt, 4797 link_cnt, map_tag[i], 0, 0); 4798 } 4799 mutex_exit(&ptgt->tgt_mutex); 4800 } 4801 check_finish_init++; 4802 break; 4803 4804 case PORT_DEVICE_USER_DELETE: 4805 case PORT_DEVICE_USER_LOGOUT: 4806 if (ptgt != NULL) { 4807 FCP_TGT_TRACE(ptgt, map_tag[i], 4808 FCP_TGT_TRACE_4); 4809 4810 mutex_enter(&ptgt->tgt_mutex); 4811 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4812 (void) fcp_offline_target(pptr, ptgt, 4813 link_cnt, map_tag[i], 1, 0); 4814 } 4815 mutex_exit(&ptgt->tgt_mutex); 4816 } 4817 check_finish_init++; 4818 break; 4819 4820 case PORT_DEVICE_CHANGED: 4821 if (ptgt != NULL) { 4822 FCP_TGT_TRACE(ptgt, map_tag[i], 4823 FCP_TGT_TRACE_5); 4824 4825 if (fcp_device_changed(pptr, ptgt, 4826 map_entry, link_cnt, map_tag[i], 4827 cause) == TRUE) { 4828 check_finish_init++; 4829 } 4830 } else { 4831 if (fcp_handle_mapflags(pptr, ptgt, 4832 map_entry, link_cnt, 0, cause) == TRUE) { 4833 check_finish_init++; 4834 } 4835 } 4836 break; 4837 4838 default: 4839 fcp_log(CE_WARN, pptr->port_dip, 4840 "!Invalid map_type=0x%x", map_entry->map_type); 4841 check_finish_init++; 4842 break; 4843 } 4844 } 4845 4846 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4847 ASSERT(i > 0); 4848 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4849 map_tag[i-1], cause); 4850 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4851 fcp_offline_all(pptr, link_cnt, cause); 4852 } 4853 } 4854 4855 static int 4856 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4857 { 4858 struct fcp_lun *plun; 4859 struct fcp_port *pptr; 4860 int rscn_count; 4861 int lun0_newalloc; 4862 int ret = TRUE; 4863 4864 ASSERT(ptgt); 4865 pptr = ptgt->tgt_port; 4866 lun0_newalloc = 0; 4867 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4868 /* 4869 * no LUN struct for LUN 0 yet exists, 4870 * so create one 4871 */ 4872 plun = fcp_alloc_lun(ptgt); 4873 if (plun == NULL) { 4874 fcp_log(CE_WARN, pptr->port_dip, 4875 "!Failed to allocate lun 0 for" 4876 " D_ID=%x", ptgt->tgt_d_id); 4877 return (ret); 4878 } 4879 lun0_newalloc = 1; 4880 } 4881 4882 mutex_enter(&ptgt->tgt_mutex); 4883 /* 4884 * consider lun 0 as device not connected if it is 4885 * offlined or newly allocated 4886 */ 4887 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4888 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4889 } 4890 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4891 plun->lun_state &= ~FCP_LUN_OFFLINE; 4892 ptgt->tgt_lun_cnt = 1; 4893 ptgt->tgt_report_lun_cnt = 0; 4894 mutex_exit(&ptgt->tgt_mutex); 4895 4896 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4897 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4898 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4899 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4900 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4901 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4902 "to D_ID=%x", ptgt->tgt_d_id); 4903 } else { 4904 ret = FALSE; 4905 } 4906 4907 return (ret); 4908 } 4909 4910 /* 4911 * Function: fcp_handle_mapflags 4912 * 4913 * Description: This function creates a target structure if the ptgt passed 4914 * is NULL. It also kicks off the PLOGI if we are not logged 4915 * into the target yet or the PRLI if we are logged into the 4916 * target already. The rest of the treatment is done in the 4917 * callbacks of the PLOGI or PRLI. 4918 * 4919 * Argument: *pptr FCP Port structure. 4920 * *ptgt Target structure. 4921 * *map_entry Array of fc_portmap_t structures. 4922 * link_cnt Link state count. 4923 * tgt_cnt Target state count. 4924 * cause What caused this function to be called. 4925 * 4926 * Return Value: TRUE Failed 4927 * FALSE Succeeded 4928 * 4929 * Notes: pptr->port_mutex must be owned. 4930 */ 4931 static int 4932 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4933 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4934 { 4935 int lcount; 4936 int tcount; 4937 int ret = TRUE; 4938 int alloc; 4939 struct fcp_ipkt *icmd; 4940 struct fcp_lun *pseq_lun = NULL; 4941 uchar_t opcode; 4942 int valid_ptgt_was_passed = FALSE; 4943 4944 ASSERT(mutex_owned(&pptr->port_mutex)); 4945 4946 /* 4947 * This case is possible where the FCTL has come up and done discovery 4948 * before FCP was loaded and attached. FCTL would have discovered the 4949 * devices and later the ULP came online. In this case ULP's would get 4950 * PORT_DEVICE_NOCHANGE but target would be NULL. 4951 */ 4952 if (ptgt == NULL) { 4953 /* don't already have a target */ 4954 mutex_exit(&pptr->port_mutex); 4955 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4956 mutex_enter(&pptr->port_mutex); 4957 4958 if (ptgt == NULL) { 4959 fcp_log(CE_WARN, pptr->port_dip, 4960 "!FC target allocation failed"); 4961 return (ret); 4962 } 4963 mutex_enter(&ptgt->tgt_mutex); 4964 ptgt->tgt_statec_cause = cause; 4965 ptgt->tgt_tmp_cnt = 1; 4966 mutex_exit(&ptgt->tgt_mutex); 4967 } else { 4968 valid_ptgt_was_passed = TRUE; 4969 } 4970 4971 /* 4972 * Copy in the target parameters 4973 */ 4974 mutex_enter(&ptgt->tgt_mutex); 4975 ptgt->tgt_d_id = map_entry->map_did.port_id; 4976 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4977 ptgt->tgt_pd_handle = map_entry->map_pd; 4978 ptgt->tgt_fca_dev = NULL; 4979 4980 /* Copy port and node WWNs */ 4981 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4982 FC_WWN_SIZE); 4983 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4984 FC_WWN_SIZE); 4985 4986 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4987 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4988 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4989 valid_ptgt_was_passed) { 4990 /* 4991 * determine if there are any tape LUNs on this target 4992 */ 4993 for (pseq_lun = ptgt->tgt_lun; 4994 pseq_lun != NULL; 4995 pseq_lun = pseq_lun->lun_next) { 4996 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4997 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4998 fcp_update_tgt_state(ptgt, FCP_RESET, 4999 FCP_LUN_MARK); 5000 mutex_exit(&ptgt->tgt_mutex); 5001 return (ret); 5002 } 5003 } 5004 } 5005 5006 /* 5007 * if UA'REPORT_LUN_CHANGED received, 5008 * send out REPORT LUN promptly, skip PLOGI/PRLI process 5009 */ 5010 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 5011 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 5012 mutex_exit(&ptgt->tgt_mutex); 5013 mutex_exit(&pptr->port_mutex); 5014 5015 ret = fcp_handle_reportlun_changed(ptgt, cause); 5016 5017 mutex_enter(&pptr->port_mutex); 5018 return (ret); 5019 } 5020 5021 /* 5022 * If ptgt was NULL when this function was entered, then tgt_node_state 5023 * was never specifically initialized but zeroed out which means 5024 * FCP_TGT_NODE_NONE. 5025 */ 5026 switch (ptgt->tgt_node_state) { 5027 case FCP_TGT_NODE_NONE: 5028 case FCP_TGT_NODE_ON_DEMAND: 5029 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5030 !fcp_enable_auto_configuration && 5031 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5032 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5033 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5034 fcp_enable_auto_configuration && 5035 (ptgt->tgt_manual_config_only == 1) && 5036 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5037 /* 5038 * If auto configuration is set and 5039 * the tgt_manual_config_only flag is set then 5040 * we only want the user to be able to change 5041 * the state through create_on_demand. 5042 */ 5043 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5044 } else { 5045 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5046 } 5047 break; 5048 5049 case FCP_TGT_NODE_PRESENT: 5050 break; 5051 } 5052 /* 5053 * If we are booting from a fabric device, make sure we 5054 * mark the node state appropriately for this target to be 5055 * enumerated 5056 */ 5057 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5058 if (bcmp((caddr_t)pptr->port_boot_wwn, 5059 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5060 sizeof (ptgt->tgt_port_wwn)) == 0) { 5061 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5062 } 5063 } 5064 mutex_exit(&ptgt->tgt_mutex); 5065 5066 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5067 fcp_trace, FCP_BUF_LEVEL_3, 0, 5068 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5069 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5070 map_entry->map_rscn_info.ulp_rscn_count); 5071 5072 mutex_enter(&ptgt->tgt_mutex); 5073 5074 /* 5075 * Reset target OFFLINE state and mark the target BUSY 5076 */ 5077 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5078 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5079 5080 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5081 lcount = link_cnt; 5082 5083 mutex_exit(&ptgt->tgt_mutex); 5084 mutex_exit(&pptr->port_mutex); 5085 5086 /* 5087 * if we are already logged in, then we do a PRLI, else 5088 * we do a PLOGI first (to get logged in) 5089 * 5090 * We will not check if we are the PLOGI initiator 5091 */ 5092 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5093 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5094 5095 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5096 5097 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5098 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5099 cause, map_entry->map_rscn_info.ulp_rscn_count); 5100 5101 if (icmd == NULL) { 5102 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5103 /* 5104 * We've exited port_mutex before calling fcp_icmd_alloc, 5105 * we need to make sure we reacquire it before returning. 5106 */ 5107 mutex_enter(&pptr->port_mutex); 5108 return (FALSE); 5109 } 5110 5111 /* TRUE is only returned while target is intended skipped */ 5112 ret = FALSE; 5113 /* discover info about this target */ 5114 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5115 lcount, tcount, cause)) == DDI_SUCCESS) { 5116 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5117 } else { 5118 fcp_icmd_free(pptr, icmd); 5119 ret = TRUE; 5120 } 5121 mutex_enter(&pptr->port_mutex); 5122 5123 return (ret); 5124 } 5125 5126 /* 5127 * Function: fcp_send_els 5128 * 5129 * Description: Sends an ELS to the target specified by the caller. Supports 5130 * PLOGI and PRLI. 5131 * 5132 * Argument: *pptr Fcp port. 5133 * *ptgt Target to send the ELS to. 5134 * *icmd Internal packet 5135 * opcode ELS opcode 5136 * lcount Link state change counter 5137 * tcount Target state change counter 5138 * cause What caused the call 5139 * 5140 * Return Value: DDI_SUCCESS 5141 * Others 5142 */ 5143 static int 5144 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5145 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5146 { 5147 fc_packet_t *fpkt; 5148 fc_frame_hdr_t *hp; 5149 int internal = 0; 5150 int alloc; 5151 int cmd_len; 5152 int resp_len; 5153 int res = DDI_FAILURE; /* default result */ 5154 int rval = DDI_FAILURE; 5155 5156 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5157 ASSERT(ptgt->tgt_port == pptr); 5158 5159 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5160 fcp_trace, FCP_BUF_LEVEL_5, 0, 5161 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5162 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5163 5164 if (opcode == LA_ELS_PLOGI) { 5165 cmd_len = sizeof (la_els_logi_t); 5166 resp_len = sizeof (la_els_logi_t); 5167 } else { 5168 ASSERT(opcode == LA_ELS_PRLI); 5169 cmd_len = sizeof (la_els_prli_t); 5170 resp_len = sizeof (la_els_prli_t); 5171 } 5172 5173 if (icmd == NULL) { 5174 alloc = FCP_MAX(sizeof (la_els_logi_t), 5175 sizeof (la_els_prli_t)); 5176 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5177 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5178 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5179 if (icmd == NULL) { 5180 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5181 return (res); 5182 } 5183 internal++; 5184 } 5185 fpkt = icmd->ipkt_fpkt; 5186 5187 fpkt->pkt_cmdlen = cmd_len; 5188 fpkt->pkt_rsplen = resp_len; 5189 fpkt->pkt_datalen = 0; 5190 icmd->ipkt_retries = 0; 5191 5192 /* fill in fpkt info */ 5193 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5194 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5195 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5196 5197 /* get ptr to frame hdr in fpkt */ 5198 hp = &fpkt->pkt_cmd_fhdr; 5199 5200 /* 5201 * fill in frame hdr 5202 */ 5203 hp->r_ctl = R_CTL_ELS_REQ; 5204 hp->s_id = pptr->port_id; /* source ID */ 5205 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5206 hp->type = FC_TYPE_EXTENDED_LS; 5207 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5208 hp->seq_id = 0; 5209 hp->rsvd = 0; 5210 hp->df_ctl = 0; 5211 hp->seq_cnt = 0; 5212 hp->ox_id = 0xffff; /* i.e. none */ 5213 hp->rx_id = 0xffff; /* i.e. none */ 5214 hp->ro = 0; 5215 5216 /* 5217 * at this point we have a filled in cmd pkt 5218 * 5219 * fill in the respective info, then use the transport to send 5220 * the packet 5221 * 5222 * for a PLOGI call fc_ulp_login(), and 5223 * for a PRLI call fc_ulp_issue_els() 5224 */ 5225 switch (opcode) { 5226 case LA_ELS_PLOGI: { 5227 struct la_els_logi logi; 5228 5229 bzero(&logi, sizeof (struct la_els_logi)); 5230 5231 hp = &fpkt->pkt_cmd_fhdr; 5232 hp->r_ctl = R_CTL_ELS_REQ; 5233 logi.ls_code.ls_code = LA_ELS_PLOGI; 5234 logi.ls_code.mbz = 0; 5235 5236 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5237 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5238 5239 icmd->ipkt_opcode = LA_ELS_PLOGI; 5240 5241 mutex_enter(&pptr->port_mutex); 5242 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5243 5244 mutex_exit(&pptr->port_mutex); 5245 5246 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5247 if (rval == FC_SUCCESS) { 5248 res = DDI_SUCCESS; 5249 break; 5250 } 5251 5252 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5253 5254 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5255 rval, "PLOGI"); 5256 } else { 5257 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5258 fcp_trace, FCP_BUF_LEVEL_5, 0, 5259 "fcp_send_els1: state change occured" 5260 " for D_ID=0x%x", ptgt->tgt_d_id); 5261 mutex_exit(&pptr->port_mutex); 5262 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5263 } 5264 break; 5265 } 5266 5267 case LA_ELS_PRLI: { 5268 struct la_els_prli prli; 5269 struct fcp_prli *fprli; 5270 5271 bzero(&prli, sizeof (struct la_els_prli)); 5272 5273 hp = &fpkt->pkt_cmd_fhdr; 5274 hp->r_ctl = R_CTL_ELS_REQ; 5275 5276 /* fill in PRLI cmd ELS fields */ 5277 prli.ls_code = LA_ELS_PRLI; 5278 prli.page_length = 0x10; /* huh? */ 5279 prli.payload_length = sizeof (struct la_els_prli); 5280 5281 icmd->ipkt_opcode = LA_ELS_PRLI; 5282 5283 /* get ptr to PRLI service params */ 5284 fprli = (struct fcp_prli *)prli.service_params; 5285 5286 /* fill in service params */ 5287 fprli->type = 0x08; 5288 fprli->resvd1 = 0; 5289 fprli->orig_process_assoc_valid = 0; 5290 fprli->resp_process_assoc_valid = 0; 5291 fprli->establish_image_pair = 1; 5292 fprli->resvd2 = 0; 5293 fprli->resvd3 = 0; 5294 fprli->obsolete_1 = 0; 5295 fprli->obsolete_2 = 0; 5296 fprli->data_overlay_allowed = 0; 5297 fprli->initiator_fn = 1; 5298 fprli->confirmed_compl_allowed = 1; 5299 5300 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5301 fprli->target_fn = 1; 5302 } else { 5303 fprli->target_fn = 0; 5304 } 5305 5306 fprli->retry = 1; 5307 fprli->read_xfer_rdy_disabled = 1; 5308 fprli->write_xfer_rdy_disabled = 0; 5309 5310 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5311 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5312 5313 /* issue the PRLI request */ 5314 5315 mutex_enter(&pptr->port_mutex); 5316 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5317 5318 mutex_exit(&pptr->port_mutex); 5319 5320 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5321 if (rval == FC_SUCCESS) { 5322 res = DDI_SUCCESS; 5323 break; 5324 } 5325 5326 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5327 5328 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5329 rval, "PRLI"); 5330 } else { 5331 mutex_exit(&pptr->port_mutex); 5332 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5333 } 5334 break; 5335 } 5336 5337 default: 5338 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5339 break; 5340 } 5341 5342 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5343 fcp_trace, FCP_BUF_LEVEL_5, 0, 5344 "fcp_send_els: returning %d", res); 5345 5346 if (res != DDI_SUCCESS) { 5347 if (internal) { 5348 fcp_icmd_free(pptr, icmd); 5349 } 5350 } 5351 5352 return (res); 5353 } 5354 5355 5356 /* 5357 * called internally update the state of all of the tgts and each LUN 5358 * for this port (i.e. each target known to be attached to this port) 5359 * if they are not already offline 5360 * 5361 * must be called with the port mutex owned 5362 * 5363 * acquires and releases the target mutexes for each target attached 5364 * to this port 5365 */ 5366 void 5367 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5368 { 5369 int i; 5370 struct fcp_tgt *ptgt; 5371 5372 ASSERT(mutex_owned(&pptr->port_mutex)); 5373 5374 for (i = 0; i < FCP_NUM_HASH; i++) { 5375 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5376 ptgt = ptgt->tgt_next) { 5377 mutex_enter(&ptgt->tgt_mutex); 5378 fcp_update_tgt_state(ptgt, FCP_SET, state); 5379 ptgt->tgt_change_cnt++; 5380 ptgt->tgt_statec_cause = cause; 5381 ptgt->tgt_tmp_cnt = 1; 5382 ptgt->tgt_done = 0; 5383 mutex_exit(&ptgt->tgt_mutex); 5384 } 5385 } 5386 } 5387 5388 5389 static void 5390 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5391 { 5392 int i; 5393 int ndevs; 5394 struct fcp_tgt *ptgt; 5395 5396 ASSERT(mutex_owned(&pptr->port_mutex)); 5397 5398 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5399 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5400 ptgt = ptgt->tgt_next) { 5401 ndevs++; 5402 } 5403 } 5404 5405 if (ndevs == 0) { 5406 return; 5407 } 5408 pptr->port_tmp_cnt = ndevs; 5409 5410 for (i = 0; i < FCP_NUM_HASH; i++) { 5411 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5412 ptgt = ptgt->tgt_next) { 5413 (void) fcp_call_finish_init_held(pptr, ptgt, 5414 lcount, ptgt->tgt_change_cnt, cause); 5415 } 5416 } 5417 } 5418 5419 /* 5420 * Function: fcp_update_tgt_state 5421 * 5422 * Description: This function updates the field tgt_state of a target. That 5423 * field is a bitmap and which bit can be set or reset 5424 * individually. The action applied to the target state is also 5425 * applied to all the LUNs belonging to the target (provided the 5426 * LUN is not offline). A side effect of applying the state 5427 * modification to the target and the LUNs is the field tgt_trace 5428 * of the target and lun_trace of the LUNs is set to zero. 5429 * 5430 * 5431 * Argument: *ptgt Target structure. 5432 * flag Flag indication what action to apply (set/reset). 5433 * state State bits to update. 5434 * 5435 * Return Value: None 5436 * 5437 * Context: Interrupt, Kernel or User context. 5438 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5439 * calling this function. 5440 */ 5441 void 5442 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5443 { 5444 struct fcp_lun *plun; 5445 5446 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5447 5448 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5449 /* The target is not offline. */ 5450 if (flag == FCP_SET) { 5451 ptgt->tgt_state |= state; 5452 ptgt->tgt_trace = 0; 5453 } else { 5454 ptgt->tgt_state &= ~state; 5455 } 5456 5457 for (plun = ptgt->tgt_lun; plun != NULL; 5458 plun = plun->lun_next) { 5459 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5460 /* The LUN is not offline. */ 5461 if (flag == FCP_SET) { 5462 plun->lun_state |= state; 5463 plun->lun_trace = 0; 5464 } else { 5465 plun->lun_state &= ~state; 5466 } 5467 } 5468 } 5469 } 5470 } 5471 5472 /* 5473 * Function: fcp_update_tgt_state 5474 * 5475 * Description: This function updates the field lun_state of a LUN. That 5476 * field is a bitmap and which bit can be set or reset 5477 * individually. 5478 * 5479 * Argument: *plun LUN structure. 5480 * flag Flag indication what action to apply (set/reset). 5481 * state State bits to update. 5482 * 5483 * Return Value: None 5484 * 5485 * Context: Interrupt, Kernel or User context. 5486 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5487 * calling this function. 5488 */ 5489 void 5490 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5491 { 5492 struct fcp_tgt *ptgt = plun->lun_tgt; 5493 5494 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5495 5496 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5497 if (flag == FCP_SET) { 5498 plun->lun_state |= state; 5499 } else { 5500 plun->lun_state &= ~state; 5501 } 5502 } 5503 } 5504 5505 /* 5506 * Function: fcp_get_port 5507 * 5508 * Description: This function returns the fcp_port structure from the opaque 5509 * handle passed by the caller. That opaque handle is the handle 5510 * used by fp/fctl to identify a particular local port. That 5511 * handle has been stored in the corresponding fcp_port 5512 * structure. This function is going to walk the global list of 5513 * fcp_port structures till one has a port_fp_handle that matches 5514 * the handle passed by the caller. This function enters the 5515 * mutex fcp_global_mutex while walking the global list and then 5516 * releases it. 5517 * 5518 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5519 * particular port. 5520 * 5521 * Return Value: NULL Not found. 5522 * Not NULL Pointer to the fcp_port structure. 5523 * 5524 * Context: Interrupt, Kernel or User context. 5525 */ 5526 static struct fcp_port * 5527 fcp_get_port(opaque_t port_handle) 5528 { 5529 struct fcp_port *pptr; 5530 5531 ASSERT(port_handle != NULL); 5532 5533 mutex_enter(&fcp_global_mutex); 5534 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5535 if (pptr->port_fp_handle == port_handle) { 5536 break; 5537 } 5538 } 5539 mutex_exit(&fcp_global_mutex); 5540 5541 return (pptr); 5542 } 5543 5544 5545 static void 5546 fcp_unsol_callback(fc_packet_t *fpkt) 5547 { 5548 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5549 struct fcp_port *pptr = icmd->ipkt_port; 5550 5551 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5552 caddr_t state, reason, action, expln; 5553 5554 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5555 &action, &expln); 5556 5557 fcp_log(CE_WARN, pptr->port_dip, 5558 "!couldn't post response to unsolicited request: " 5559 " state=%s reason=%s rx_id=%x ox_id=%x", 5560 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5561 fpkt->pkt_cmd_fhdr.rx_id); 5562 } 5563 fcp_icmd_free(pptr, icmd); 5564 } 5565 5566 5567 /* 5568 * Perform general purpose preparation of a response to an unsolicited request 5569 */ 5570 static void 5571 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5572 uchar_t r_ctl, uchar_t type) 5573 { 5574 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5575 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5576 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5577 pkt->pkt_cmd_fhdr.type = type; 5578 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5579 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5580 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5581 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5582 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5583 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5584 pkt->pkt_cmd_fhdr.ro = 0; 5585 pkt->pkt_cmd_fhdr.rsvd = 0; 5586 pkt->pkt_comp = fcp_unsol_callback; 5587 pkt->pkt_pd = NULL; 5588 pkt->pkt_ub_resp_token = (opaque_t)buf; 5589 } 5590 5591 5592 /*ARGSUSED*/ 5593 static int 5594 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5595 { 5596 fc_packet_t *fpkt; 5597 struct la_els_prli prli; 5598 struct fcp_prli *fprli; 5599 struct fcp_ipkt *icmd; 5600 struct la_els_prli *from; 5601 struct fcp_prli *orig; 5602 struct fcp_tgt *ptgt; 5603 int tcount = 0; 5604 int lcount; 5605 5606 from = (struct la_els_prli *)buf->ub_buffer; 5607 orig = (struct fcp_prli *)from->service_params; 5608 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5609 NULL) { 5610 mutex_enter(&ptgt->tgt_mutex); 5611 tcount = ptgt->tgt_change_cnt; 5612 mutex_exit(&ptgt->tgt_mutex); 5613 } 5614 5615 mutex_enter(&pptr->port_mutex); 5616 lcount = pptr->port_link_cnt; 5617 mutex_exit(&pptr->port_mutex); 5618 5619 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5620 sizeof (la_els_prli_t), 0, 5621 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5622 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5623 return (FC_FAILURE); 5624 } 5625 5626 fpkt = icmd->ipkt_fpkt; 5627 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5628 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5629 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5630 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5631 fpkt->pkt_rsplen = 0; 5632 fpkt->pkt_datalen = 0; 5633 5634 icmd->ipkt_opcode = LA_ELS_PRLI; 5635 5636 bzero(&prli, sizeof (struct la_els_prli)); 5637 fprli = (struct fcp_prli *)prli.service_params; 5638 prli.ls_code = LA_ELS_ACC; 5639 prli.page_length = 0x10; 5640 prli.payload_length = sizeof (struct la_els_prli); 5641 5642 /* fill in service params */ 5643 fprli->type = 0x08; 5644 fprli->resvd1 = 0; 5645 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5646 fprli->orig_process_associator = orig->orig_process_associator; 5647 fprli->resp_process_assoc_valid = 0; 5648 fprli->establish_image_pair = 1; 5649 fprli->resvd2 = 0; 5650 fprli->resvd3 = 0; 5651 fprli->obsolete_1 = 0; 5652 fprli->obsolete_2 = 0; 5653 fprli->data_overlay_allowed = 0; 5654 fprli->initiator_fn = 1; 5655 fprli->confirmed_compl_allowed = 1; 5656 5657 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5658 fprli->target_fn = 1; 5659 } else { 5660 fprli->target_fn = 0; 5661 } 5662 5663 fprli->retry = 1; 5664 fprli->read_xfer_rdy_disabled = 1; 5665 fprli->write_xfer_rdy_disabled = 0; 5666 5667 /* save the unsol prli payload first */ 5668 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5669 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5670 5671 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5672 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5673 5674 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5675 5676 mutex_enter(&pptr->port_mutex); 5677 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5678 int rval; 5679 mutex_exit(&pptr->port_mutex); 5680 5681 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5682 FC_SUCCESS) { 5683 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5684 ptgt != NULL) { 5685 fcp_queue_ipkt(pptr, fpkt); 5686 return (FC_SUCCESS); 5687 } 5688 /* Let it timeout */ 5689 fcp_icmd_free(pptr, icmd); 5690 return (FC_FAILURE); 5691 } 5692 } else { 5693 mutex_exit(&pptr->port_mutex); 5694 fcp_icmd_free(pptr, icmd); 5695 return (FC_FAILURE); 5696 } 5697 5698 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5699 5700 return (FC_SUCCESS); 5701 } 5702 5703 /* 5704 * Function: fcp_icmd_alloc 5705 * 5706 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5707 * field is initialized to fcp_icmd_callback. Sometimes it is 5708 * modified by the caller (such as fcp_send_scsi). The 5709 * structure is also tied to the state of the line and of the 5710 * target at a particular time. That link is established by 5711 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5712 * and tcount which came respectively from pptr->link_cnt and 5713 * ptgt->tgt_change_cnt. 5714 * 5715 * Argument: *pptr Fcp port. 5716 * *ptgt Target (destination of the command). 5717 * cmd_len Length of the command. 5718 * resp_len Length of the expected response. 5719 * data_len Length of the data. 5720 * nodma Indicates weither the command and response. 5721 * will be transfer through DMA or not. 5722 * lcount Link state change counter. 5723 * tcount Target state change counter. 5724 * cause Reason that lead to this call. 5725 * 5726 * Return Value: NULL Failed. 5727 * Not NULL Internal packet address. 5728 */ 5729 static struct fcp_ipkt * 5730 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5731 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5732 uint32_t rscn_count) 5733 { 5734 int dma_setup = 0; 5735 fc_packet_t *fpkt; 5736 struct fcp_ipkt *icmd = NULL; 5737 5738 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5739 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5740 KM_NOSLEEP); 5741 if (icmd == NULL) { 5742 fcp_log(CE_WARN, pptr->port_dip, 5743 "!internal packet allocation failed"); 5744 return (NULL); 5745 } 5746 5747 /* 5748 * initialize the allocated packet 5749 */ 5750 icmd->ipkt_nodma = nodma; 5751 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5752 icmd->ipkt_lun = NULL; 5753 5754 icmd->ipkt_link_cnt = lcount; 5755 icmd->ipkt_change_cnt = tcount; 5756 icmd->ipkt_cause = cause; 5757 5758 mutex_enter(&pptr->port_mutex); 5759 icmd->ipkt_port = pptr; 5760 mutex_exit(&pptr->port_mutex); 5761 5762 /* keep track of amt of data to be sent in pkt */ 5763 icmd->ipkt_cmdlen = cmd_len; 5764 icmd->ipkt_resplen = resp_len; 5765 icmd->ipkt_datalen = data_len; 5766 5767 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5768 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5769 5770 /* set pkt's private ptr to point to cmd pkt */ 5771 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5772 5773 /* set FCA private ptr to memory just beyond */ 5774 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5775 ((char *)icmd + sizeof (struct fcp_ipkt) + 5776 pptr->port_dmacookie_sz); 5777 5778 /* get ptr to fpkt substruct and fill it in */ 5779 fpkt = icmd->ipkt_fpkt; 5780 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5781 sizeof (struct fcp_ipkt)); 5782 5783 if (ptgt != NULL) { 5784 icmd->ipkt_tgt = ptgt; 5785 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5786 } 5787 5788 fpkt->pkt_comp = fcp_icmd_callback; 5789 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5790 fpkt->pkt_cmdlen = cmd_len; 5791 fpkt->pkt_rsplen = resp_len; 5792 fpkt->pkt_datalen = data_len; 5793 5794 /* 5795 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5796 * rscn_count as fcp knows down to the transport. If a valid count was 5797 * passed into this function, we allocate memory to actually pass down 5798 * this info. 5799 * 5800 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5801 * basically mean that fcp will not be able to help transport 5802 * distinguish if a new RSCN has come after fcp was last informed about 5803 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5804 * 5068068 where the device might end up going offline in case of RSCN 5805 * storms. 5806 */ 5807 fpkt->pkt_ulp_rscn_infop = NULL; 5808 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5809 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5810 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5811 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5812 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5813 fcp_trace, FCP_BUF_LEVEL_6, 0, 5814 "Failed to alloc memory to pass rscn info"); 5815 } 5816 } 5817 5818 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5819 fc_ulp_rscn_info_t *rscnp; 5820 5821 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5822 rscnp->ulp_rscn_count = rscn_count; 5823 } 5824 5825 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5826 goto fail; 5827 } 5828 dma_setup++; 5829 5830 /* 5831 * Must hold target mutex across setting of pkt_pd and call to 5832 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5833 * away while we're not looking. 5834 */ 5835 if (ptgt != NULL) { 5836 mutex_enter(&ptgt->tgt_mutex); 5837 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5838 5839 /* ask transport to do its initialization on this pkt */ 5840 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5841 != FC_SUCCESS) { 5842 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5843 fcp_trace, FCP_BUF_LEVEL_6, 0, 5844 "fc_ulp_init_packet failed"); 5845 mutex_exit(&ptgt->tgt_mutex); 5846 goto fail; 5847 } 5848 mutex_exit(&ptgt->tgt_mutex); 5849 } else { 5850 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5851 != FC_SUCCESS) { 5852 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5853 fcp_trace, FCP_BUF_LEVEL_6, 0, 5854 "fc_ulp_init_packet failed"); 5855 goto fail; 5856 } 5857 } 5858 5859 mutex_enter(&pptr->port_mutex); 5860 if (pptr->port_state & (FCP_STATE_DETACHING | 5861 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5862 int rval; 5863 5864 mutex_exit(&pptr->port_mutex); 5865 5866 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5867 ASSERT(rval == FC_SUCCESS); 5868 5869 goto fail; 5870 } 5871 5872 if (ptgt != NULL) { 5873 mutex_enter(&ptgt->tgt_mutex); 5874 ptgt->tgt_ipkt_cnt++; 5875 mutex_exit(&ptgt->tgt_mutex); 5876 } 5877 5878 pptr->port_ipkt_cnt++; 5879 5880 mutex_exit(&pptr->port_mutex); 5881 5882 return (icmd); 5883 5884 fail: 5885 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5886 kmem_free(fpkt->pkt_ulp_rscn_infop, 5887 sizeof (fc_ulp_rscn_info_t)); 5888 fpkt->pkt_ulp_rscn_infop = NULL; 5889 } 5890 5891 if (dma_setup) { 5892 fcp_free_dma(pptr, icmd); 5893 } 5894 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5895 (size_t)pptr->port_dmacookie_sz); 5896 5897 return (NULL); 5898 } 5899 5900 /* 5901 * Function: fcp_icmd_free 5902 * 5903 * Description: Frees the internal command passed by the caller. 5904 * 5905 * Argument: *pptr Fcp port. 5906 * *icmd Internal packet to free. 5907 * 5908 * Return Value: None 5909 */ 5910 static void 5911 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5912 { 5913 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5914 5915 /* Let the underlying layers do their cleanup. */ 5916 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5917 icmd->ipkt_fpkt); 5918 5919 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5920 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5921 sizeof (fc_ulp_rscn_info_t)); 5922 } 5923 5924 fcp_free_dma(pptr, icmd); 5925 5926 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5927 (size_t)pptr->port_dmacookie_sz); 5928 5929 mutex_enter(&pptr->port_mutex); 5930 5931 if (ptgt) { 5932 mutex_enter(&ptgt->tgt_mutex); 5933 ptgt->tgt_ipkt_cnt--; 5934 mutex_exit(&ptgt->tgt_mutex); 5935 } 5936 5937 pptr->port_ipkt_cnt--; 5938 mutex_exit(&pptr->port_mutex); 5939 } 5940 5941 /* 5942 * Function: fcp_alloc_dma 5943 * 5944 * Description: Allocated the DMA resources required for the internal 5945 * packet. 5946 * 5947 * Argument: *pptr FCP port. 5948 * *icmd Internal FCP packet. 5949 * nodma Indicates if the Cmd and Resp will be DMAed. 5950 * flags Allocation flags (Sleep or NoSleep). 5951 * 5952 * Return Value: FC_SUCCESS 5953 * FC_NOMEM 5954 */ 5955 static int 5956 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5957 int nodma, int flags) 5958 { 5959 int rval; 5960 size_t real_size; 5961 uint_t ccount; 5962 int bound = 0; 5963 int cmd_resp = 0; 5964 fc_packet_t *fpkt; 5965 ddi_dma_cookie_t pkt_data_cookie; 5966 ddi_dma_cookie_t *cp; 5967 uint32_t cnt; 5968 5969 fpkt = &icmd->ipkt_fc_packet; 5970 5971 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5972 fpkt->pkt_resp_dma == NULL); 5973 5974 icmd->ipkt_nodma = nodma; 5975 5976 if (nodma) { 5977 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5978 if (fpkt->pkt_cmd == NULL) { 5979 goto fail; 5980 } 5981 5982 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5983 if (fpkt->pkt_resp == NULL) { 5984 goto fail; 5985 } 5986 } else { 5987 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5988 5989 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5990 if (rval == FC_FAILURE) { 5991 ASSERT(fpkt->pkt_cmd_dma == NULL && 5992 fpkt->pkt_resp_dma == NULL); 5993 goto fail; 5994 } 5995 cmd_resp++; 5996 } 5997 5998 if ((fpkt->pkt_datalen != 0) && 5999 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 6000 /* 6001 * set up DMA handle and memory for the data in this packet 6002 */ 6003 if (ddi_dma_alloc_handle(pptr->port_dip, 6004 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 6005 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 6006 goto fail; 6007 } 6008 6009 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 6010 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 6011 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 6012 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 6013 goto fail; 6014 } 6015 6016 /* was DMA mem size gotten < size asked for/needed ?? */ 6017 if (real_size < fpkt->pkt_datalen) { 6018 goto fail; 6019 } 6020 6021 /* bind DMA address and handle together */ 6022 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6023 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6024 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6025 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6026 goto fail; 6027 } 6028 bound++; 6029 6030 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6031 goto fail; 6032 } 6033 6034 fpkt->pkt_data_cookie_cnt = ccount; 6035 6036 cp = fpkt->pkt_data_cookie; 6037 *cp = pkt_data_cookie; 6038 cp++; 6039 6040 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6041 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6042 &pkt_data_cookie); 6043 *cp = pkt_data_cookie; 6044 } 6045 6046 } else if (fpkt->pkt_datalen != 0) { 6047 /* 6048 * If it's a pseudo FCA, then it can't support DMA even in 6049 * SCSI data phase. 6050 */ 6051 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6052 if (fpkt->pkt_data == NULL) { 6053 goto fail; 6054 } 6055 6056 } 6057 6058 return (FC_SUCCESS); 6059 6060 fail: 6061 if (bound) { 6062 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6063 } 6064 6065 if (fpkt->pkt_data_dma) { 6066 if (fpkt->pkt_data) { 6067 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6068 } 6069 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6070 } else { 6071 if (fpkt->pkt_data) { 6072 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6073 } 6074 } 6075 6076 if (nodma) { 6077 if (fpkt->pkt_cmd) { 6078 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6079 } 6080 if (fpkt->pkt_resp) { 6081 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6082 } 6083 } else { 6084 if (cmd_resp) { 6085 fcp_free_cmd_resp(pptr, fpkt); 6086 } 6087 } 6088 6089 return (FC_NOMEM); 6090 } 6091 6092 6093 static void 6094 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6095 { 6096 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6097 6098 if (fpkt->pkt_data_dma) { 6099 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6100 if (fpkt->pkt_data) { 6101 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6102 } 6103 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6104 } else { 6105 if (fpkt->pkt_data) { 6106 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6107 } 6108 /* 6109 * Need we reset pkt_* to zero??? 6110 */ 6111 } 6112 6113 if (icmd->ipkt_nodma) { 6114 if (fpkt->pkt_cmd) { 6115 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6116 } 6117 if (fpkt->pkt_resp) { 6118 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6119 } 6120 } else { 6121 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6122 6123 fcp_free_cmd_resp(pptr, fpkt); 6124 } 6125 } 6126 6127 /* 6128 * Function: fcp_lookup_target 6129 * 6130 * Description: Finds a target given a WWN. 6131 * 6132 * Argument: *pptr FCP port. 6133 * *wwn World Wide Name of the device to look for. 6134 * 6135 * Return Value: NULL No target found 6136 * Not NULL Target structure 6137 * 6138 * Context: Interrupt context. 6139 * The mutex pptr->port_mutex must be owned. 6140 */ 6141 /* ARGSUSED */ 6142 static struct fcp_tgt * 6143 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6144 { 6145 int hash; 6146 struct fcp_tgt *ptgt; 6147 6148 ASSERT(mutex_owned(&pptr->port_mutex)); 6149 6150 hash = FCP_HASH(wwn); 6151 6152 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6153 ptgt = ptgt->tgt_next) { 6154 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6155 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6156 sizeof (ptgt->tgt_port_wwn)) == 0) { 6157 break; 6158 } 6159 } 6160 6161 return (ptgt); 6162 } 6163 6164 6165 /* 6166 * Find target structure given a port identifier 6167 */ 6168 static struct fcp_tgt * 6169 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6170 { 6171 fc_portid_t port_id; 6172 la_wwn_t pwwn; 6173 struct fcp_tgt *ptgt = NULL; 6174 6175 port_id.priv_lilp_posit = 0; 6176 port_id.port_id = d_id; 6177 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6178 &pwwn) == FC_SUCCESS) { 6179 mutex_enter(&pptr->port_mutex); 6180 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6181 mutex_exit(&pptr->port_mutex); 6182 } 6183 6184 return (ptgt); 6185 } 6186 6187 6188 /* 6189 * the packet completion callback routine for info cmd pkts 6190 * 6191 * this means fpkt pts to a response to either a PLOGI or a PRLI 6192 * 6193 * if there is an error an attempt is made to call a routine to resend 6194 * the command that failed 6195 */ 6196 static void 6197 fcp_icmd_callback(fc_packet_t *fpkt) 6198 { 6199 struct fcp_ipkt *icmd; 6200 struct fcp_port *pptr; 6201 struct fcp_tgt *ptgt; 6202 struct la_els_prli *prli; 6203 struct la_els_prli prli_s; 6204 struct fcp_prli *fprli; 6205 struct fcp_lun *plun; 6206 int free_pkt = 1; 6207 int rval; 6208 ls_code_t resp; 6209 uchar_t prli_acc = 0; 6210 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6211 int lun0_newalloc; 6212 6213 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6214 6215 /* get ptrs to the port and target structs for the cmd */ 6216 pptr = icmd->ipkt_port; 6217 ptgt = icmd->ipkt_tgt; 6218 6219 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6220 6221 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6222 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6223 sizeof (prli_s)); 6224 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6225 } 6226 6227 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6228 fcp_trace, FCP_BUF_LEVEL_2, 0, 6229 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6230 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6231 ptgt->tgt_d_id); 6232 6233 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6234 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6235 6236 mutex_enter(&ptgt->tgt_mutex); 6237 if (ptgt->tgt_pd_handle == NULL) { 6238 /* 6239 * in a fabric environment the port device handles 6240 * get created only after successful LOGIN into the 6241 * transport, so the transport makes this port 6242 * device (pd) handle available in this packet, so 6243 * save it now 6244 */ 6245 ASSERT(fpkt->pkt_pd != NULL); 6246 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6247 } 6248 mutex_exit(&ptgt->tgt_mutex); 6249 6250 /* which ELS cmd is this response for ?? */ 6251 switch (icmd->ipkt_opcode) { 6252 case LA_ELS_PLOGI: 6253 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6254 fcp_trace, FCP_BUF_LEVEL_5, 0, 6255 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6256 ptgt->tgt_d_id, 6257 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6258 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6259 6260 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6261 FCP_TGT_TRACE_15); 6262 6263 /* Note that we are not allocating a new icmd */ 6264 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6265 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6266 icmd->ipkt_cause) != DDI_SUCCESS) { 6267 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6268 FCP_TGT_TRACE_16); 6269 goto fail; 6270 } 6271 break; 6272 6273 case LA_ELS_PRLI: 6274 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6275 fcp_trace, FCP_BUF_LEVEL_5, 0, 6276 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6277 6278 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6279 FCP_TGT_TRACE_17); 6280 6281 prli = &prli_s; 6282 6283 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6284 sizeof (prli_s)); 6285 6286 fprli = (struct fcp_prli *)prli->service_params; 6287 6288 mutex_enter(&ptgt->tgt_mutex); 6289 ptgt->tgt_icap = fprli->initiator_fn; 6290 ptgt->tgt_tcap = fprli->target_fn; 6291 mutex_exit(&ptgt->tgt_mutex); 6292 6293 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6294 /* 6295 * this FCP device does not support target mode 6296 */ 6297 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6298 FCP_TGT_TRACE_18); 6299 goto fail; 6300 } 6301 if (fprli->retry == 1) { 6302 fc_ulp_disable_relogin(pptr->port_fp_handle, 6303 &ptgt->tgt_port_wwn); 6304 } 6305 6306 /* target is no longer offline */ 6307 mutex_enter(&pptr->port_mutex); 6308 mutex_enter(&ptgt->tgt_mutex); 6309 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6310 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6311 FCP_TGT_MARK); 6312 } else { 6313 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6314 fcp_trace, FCP_BUF_LEVEL_2, 0, 6315 "fcp_icmd_callback,1: state change " 6316 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6317 mutex_exit(&ptgt->tgt_mutex); 6318 mutex_exit(&pptr->port_mutex); 6319 goto fail; 6320 } 6321 mutex_exit(&ptgt->tgt_mutex); 6322 mutex_exit(&pptr->port_mutex); 6323 6324 /* 6325 * lun 0 should always respond to inquiry, so 6326 * get the LUN struct for LUN 0 6327 * 6328 * Currently we deal with first level of addressing. 6329 * If / when we start supporting 0x device types 6330 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6331 * this logic will need revisiting. 6332 */ 6333 lun0_newalloc = 0; 6334 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6335 /* 6336 * no LUN struct for LUN 0 yet exists, 6337 * so create one 6338 */ 6339 plun = fcp_alloc_lun(ptgt); 6340 if (plun == NULL) { 6341 fcp_log(CE_WARN, pptr->port_dip, 6342 "!Failed to allocate lun 0 for" 6343 " D_ID=%x", ptgt->tgt_d_id); 6344 goto fail; 6345 } 6346 lun0_newalloc = 1; 6347 } 6348 6349 /* fill in LUN info */ 6350 mutex_enter(&ptgt->tgt_mutex); 6351 /* 6352 * consider lun 0 as device not connected if it is 6353 * offlined or newly allocated 6354 */ 6355 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6356 lun0_newalloc) { 6357 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6358 } 6359 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6360 plun->lun_state &= ~FCP_LUN_OFFLINE; 6361 ptgt->tgt_lun_cnt = 1; 6362 ptgt->tgt_report_lun_cnt = 0; 6363 mutex_exit(&ptgt->tgt_mutex); 6364 6365 /* Retrieve the rscn count (if a valid one exists) */ 6366 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6367 rscn_count = ((fc_ulp_rscn_info_t *) 6368 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6369 ->ulp_rscn_count; 6370 } else { 6371 rscn_count = FC_INVALID_RSCN_COUNT; 6372 } 6373 6374 /* send Report Lun request to target */ 6375 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6376 sizeof (struct fcp_reportlun_resp), 6377 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6378 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6379 mutex_enter(&pptr->port_mutex); 6380 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6381 fcp_log(CE_WARN, pptr->port_dip, 6382 "!Failed to send REPORT LUN to" 6383 " D_ID=%x", ptgt->tgt_d_id); 6384 } else { 6385 FCP_TRACE(fcp_logq, 6386 pptr->port_instbuf, fcp_trace, 6387 FCP_BUF_LEVEL_5, 0, 6388 "fcp_icmd_callback,2:state change" 6389 " occured for D_ID=0x%x", 6390 ptgt->tgt_d_id); 6391 } 6392 mutex_exit(&pptr->port_mutex); 6393 6394 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6395 FCP_TGT_TRACE_19); 6396 6397 goto fail; 6398 } else { 6399 free_pkt = 0; 6400 fcp_icmd_free(pptr, icmd); 6401 } 6402 break; 6403 6404 default: 6405 fcp_log(CE_WARN, pptr->port_dip, 6406 "!fcp_icmd_callback Invalid opcode"); 6407 goto fail; 6408 } 6409 6410 return; 6411 } 6412 6413 6414 /* 6415 * Other PLOGI failures are not retried as the 6416 * transport does it already 6417 */ 6418 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6419 if (fcp_is_retryable(icmd) && 6420 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6421 6422 if (FCP_MUST_RETRY(fpkt)) { 6423 fcp_queue_ipkt(pptr, fpkt); 6424 return; 6425 } 6426 6427 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6428 fcp_trace, FCP_BUF_LEVEL_2, 0, 6429 "ELS PRLI is retried for d_id=0x%x, state=%x," 6430 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6431 fpkt->pkt_reason); 6432 6433 /* 6434 * Retry by recalling the routine that 6435 * originally queued this packet 6436 */ 6437 mutex_enter(&pptr->port_mutex); 6438 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6439 caddr_t msg; 6440 6441 mutex_exit(&pptr->port_mutex); 6442 6443 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6444 6445 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6446 fpkt->pkt_timeout += 6447 FCP_TIMEOUT_DELTA; 6448 } 6449 6450 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6451 fpkt); 6452 if (rval == FC_SUCCESS) { 6453 return; 6454 } 6455 6456 if (rval == FC_STATEC_BUSY || 6457 rval == FC_OFFLINE) { 6458 fcp_queue_ipkt(pptr, fpkt); 6459 return; 6460 } 6461 (void) fc_ulp_error(rval, &msg); 6462 6463 fcp_log(CE_NOTE, pptr->port_dip, 6464 "!ELS 0x%x failed to d_id=0x%x;" 6465 " %s", icmd->ipkt_opcode, 6466 ptgt->tgt_d_id, msg); 6467 } else { 6468 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6469 fcp_trace, FCP_BUF_LEVEL_2, 0, 6470 "fcp_icmd_callback,3: state change " 6471 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6472 mutex_exit(&pptr->port_mutex); 6473 } 6474 } 6475 } else { 6476 if (fcp_is_retryable(icmd) && 6477 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6478 if (FCP_MUST_RETRY(fpkt)) { 6479 fcp_queue_ipkt(pptr, fpkt); 6480 return; 6481 } 6482 } 6483 mutex_enter(&pptr->port_mutex); 6484 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6485 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6486 mutex_exit(&pptr->port_mutex); 6487 fcp_print_error(fpkt); 6488 } else { 6489 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6490 fcp_trace, FCP_BUF_LEVEL_2, 0, 6491 "fcp_icmd_callback,4: state change occured" 6492 " for D_ID=0x%x", ptgt->tgt_d_id); 6493 mutex_exit(&pptr->port_mutex); 6494 } 6495 } 6496 6497 fail: 6498 if (free_pkt) { 6499 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6500 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6501 fcp_icmd_free(pptr, icmd); 6502 } 6503 } 6504 6505 6506 /* 6507 * called internally to send an info cmd using the transport 6508 * 6509 * sends either an INQ or a REPORT_LUN 6510 * 6511 * when the packet is completed fcp_scsi_callback is called 6512 */ 6513 static int 6514 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6515 int lcount, int tcount, int cause, uint32_t rscn_count) 6516 { 6517 int nodma; 6518 struct fcp_ipkt *icmd; 6519 struct fcp_tgt *ptgt; 6520 struct fcp_port *pptr; 6521 fc_frame_hdr_t *hp; 6522 fc_packet_t *fpkt; 6523 struct fcp_cmd fcp_cmd; 6524 struct fcp_cmd *fcmd; 6525 union scsi_cdb *scsi_cdb; 6526 6527 ASSERT(plun != NULL); 6528 6529 ptgt = plun->lun_tgt; 6530 ASSERT(ptgt != NULL); 6531 6532 pptr = ptgt->tgt_port; 6533 ASSERT(pptr != NULL); 6534 6535 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6536 fcp_trace, FCP_BUF_LEVEL_5, 0, 6537 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6538 6539 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6540 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6541 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6542 rscn_count); 6543 6544 if (icmd == NULL) { 6545 return (DDI_FAILURE); 6546 } 6547 6548 fpkt = icmd->ipkt_fpkt; 6549 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6550 icmd->ipkt_retries = 0; 6551 icmd->ipkt_opcode = opcode; 6552 icmd->ipkt_lun = plun; 6553 6554 if (nodma) { 6555 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6556 } else { 6557 fcmd = &fcp_cmd; 6558 } 6559 bzero(fcmd, sizeof (struct fcp_cmd)); 6560 6561 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6562 6563 hp = &fpkt->pkt_cmd_fhdr; 6564 6565 hp->s_id = pptr->port_id; 6566 hp->d_id = ptgt->tgt_d_id; 6567 hp->r_ctl = R_CTL_COMMAND; 6568 hp->type = FC_TYPE_SCSI_FCP; 6569 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6570 hp->rsvd = 0; 6571 hp->seq_id = 0; 6572 hp->seq_cnt = 0; 6573 hp->ox_id = 0xffff; 6574 hp->rx_id = 0xffff; 6575 hp->ro = 0; 6576 6577 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6578 6579 /* 6580 * Request SCSI target for expedited processing 6581 */ 6582 6583 /* 6584 * Set up for untagged queuing because we do not 6585 * know if the fibre device supports queuing. 6586 */ 6587 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6588 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6589 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6590 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6591 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6592 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6593 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6594 6595 switch (opcode) { 6596 case SCMD_INQUIRY_PAGE83: 6597 /* 6598 * Prepare to get the Inquiry VPD page 83 information 6599 */ 6600 fcmd->fcp_cntl.cntl_read_data = 1; 6601 fcmd->fcp_cntl.cntl_write_data = 0; 6602 fcmd->fcp_data_len = alloc_len; 6603 6604 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6605 fpkt->pkt_comp = fcp_scsi_callback; 6606 6607 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6608 scsi_cdb->g0_addr2 = 0x01; 6609 scsi_cdb->g0_addr1 = 0x83; 6610 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6611 break; 6612 6613 case SCMD_INQUIRY: 6614 fcmd->fcp_cntl.cntl_read_data = 1; 6615 fcmd->fcp_cntl.cntl_write_data = 0; 6616 fcmd->fcp_data_len = alloc_len; 6617 6618 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6619 fpkt->pkt_comp = fcp_scsi_callback; 6620 6621 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6622 scsi_cdb->g0_count0 = SUN_INQSIZE; 6623 break; 6624 6625 case SCMD_REPORT_LUN: { 6626 fc_portid_t d_id; 6627 opaque_t fca_dev; 6628 6629 ASSERT(alloc_len >= 16); 6630 6631 d_id.priv_lilp_posit = 0; 6632 d_id.port_id = ptgt->tgt_d_id; 6633 6634 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6635 6636 mutex_enter(&ptgt->tgt_mutex); 6637 ptgt->tgt_fca_dev = fca_dev; 6638 mutex_exit(&ptgt->tgt_mutex); 6639 6640 fcmd->fcp_cntl.cntl_read_data = 1; 6641 fcmd->fcp_cntl.cntl_write_data = 0; 6642 fcmd->fcp_data_len = alloc_len; 6643 6644 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6645 fpkt->pkt_comp = fcp_scsi_callback; 6646 6647 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6648 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6649 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6650 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6651 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6652 break; 6653 } 6654 6655 default: 6656 fcp_log(CE_WARN, pptr->port_dip, 6657 "!fcp_send_scsi Invalid opcode"); 6658 break; 6659 } 6660 6661 if (!nodma) { 6662 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6663 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6664 } 6665 6666 mutex_enter(&pptr->port_mutex); 6667 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6668 6669 mutex_exit(&pptr->port_mutex); 6670 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6671 FC_SUCCESS) { 6672 fcp_icmd_free(pptr, icmd); 6673 return (DDI_FAILURE); 6674 } 6675 return (DDI_SUCCESS); 6676 } else { 6677 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6678 fcp_trace, FCP_BUF_LEVEL_2, 0, 6679 "fcp_send_scsi,1: state change occured" 6680 " for D_ID=0x%x", ptgt->tgt_d_id); 6681 mutex_exit(&pptr->port_mutex); 6682 fcp_icmd_free(pptr, icmd); 6683 return (DDI_FAILURE); 6684 } 6685 } 6686 6687 6688 /* 6689 * called by fcp_scsi_callback to check to handle the case where 6690 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6691 */ 6692 static int 6693 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6694 { 6695 uchar_t rqlen; 6696 int rval = DDI_FAILURE; 6697 struct scsi_extended_sense sense_info, *sense; 6698 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6699 fpkt->pkt_ulp_private; 6700 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6701 struct fcp_port *pptr = ptgt->tgt_port; 6702 6703 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6704 6705 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6706 /* 6707 * SCSI-II Reserve Release support. Some older FC drives return 6708 * Reservation conflict for Report Luns command. 6709 */ 6710 if (icmd->ipkt_nodma) { 6711 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6712 rsp->fcp_u.fcp_status.sense_len_set = 0; 6713 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6714 } else { 6715 fcp_rsp_t new_resp; 6716 6717 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6718 fpkt->pkt_resp_acc, sizeof (new_resp)); 6719 6720 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6721 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6722 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6723 6724 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6725 fpkt->pkt_resp_acc, sizeof (new_resp)); 6726 } 6727 6728 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6729 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6730 6731 return (DDI_SUCCESS); 6732 } 6733 6734 sense = &sense_info; 6735 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6736 /* no need to continue if sense length is not set */ 6737 return (rval); 6738 } 6739 6740 /* casting 64-bit integer to 8-bit */ 6741 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6742 sizeof (struct scsi_extended_sense)); 6743 6744 if (rqlen < 14) { 6745 /* no need to continue if request length isn't long enough */ 6746 return (rval); 6747 } 6748 6749 if (icmd->ipkt_nodma) { 6750 /* 6751 * We can safely use fcp_response_len here since the 6752 * only path that calls fcp_check_reportlun, 6753 * fcp_scsi_callback, has already called 6754 * fcp_validate_fcp_response. 6755 */ 6756 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6757 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6758 } else { 6759 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6760 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6761 sizeof (struct scsi_extended_sense)); 6762 } 6763 6764 if (!FCP_SENSE_NO_LUN(sense)) { 6765 mutex_enter(&ptgt->tgt_mutex); 6766 /* clear the flag if any */ 6767 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6768 mutex_exit(&ptgt->tgt_mutex); 6769 } 6770 6771 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6772 (sense->es_add_code == 0x20)) { 6773 if (icmd->ipkt_nodma) { 6774 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6775 rsp->fcp_u.fcp_status.sense_len_set = 0; 6776 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6777 } else { 6778 fcp_rsp_t new_resp; 6779 6780 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6781 fpkt->pkt_resp_acc, sizeof (new_resp)); 6782 6783 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6784 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6785 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6786 6787 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6788 fpkt->pkt_resp_acc, sizeof (new_resp)); 6789 } 6790 6791 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6792 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6793 6794 return (DDI_SUCCESS); 6795 } 6796 6797 /* 6798 * This is for the STK library which returns a check condition, 6799 * to indicate device is not ready, manual assistance needed. 6800 * This is to a report lun command when the door is open. 6801 */ 6802 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6803 if (icmd->ipkt_nodma) { 6804 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6805 rsp->fcp_u.fcp_status.sense_len_set = 0; 6806 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6807 } else { 6808 fcp_rsp_t new_resp; 6809 6810 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6811 fpkt->pkt_resp_acc, sizeof (new_resp)); 6812 6813 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6814 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6815 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6816 6817 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6818 fpkt->pkt_resp_acc, sizeof (new_resp)); 6819 } 6820 6821 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6822 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6823 6824 return (DDI_SUCCESS); 6825 } 6826 6827 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6828 (FCP_SENSE_NO_LUN(sense))) { 6829 mutex_enter(&ptgt->tgt_mutex); 6830 if ((FCP_SENSE_NO_LUN(sense)) && 6831 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6832 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6833 mutex_exit(&ptgt->tgt_mutex); 6834 /* 6835 * reconfig was triggred by ILLEGAL REQUEST but 6836 * got ILLEGAL REQUEST again 6837 */ 6838 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6839 fcp_trace, FCP_BUF_LEVEL_3, 0, 6840 "!FCP: Unable to obtain Report Lun data" 6841 " target=%x", ptgt->tgt_d_id); 6842 } else { 6843 if (ptgt->tgt_tid == NULL) { 6844 timeout_id_t tid; 6845 /* 6846 * REPORT LUN data has changed. Kick off 6847 * rediscovery 6848 */ 6849 tid = timeout(fcp_reconfigure_luns, 6850 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6851 6852 ptgt->tgt_tid = tid; 6853 ptgt->tgt_state |= FCP_TGT_BUSY; 6854 } 6855 if (FCP_SENSE_NO_LUN(sense)) { 6856 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6857 } 6858 mutex_exit(&ptgt->tgt_mutex); 6859 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6860 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6861 fcp_trace, FCP_BUF_LEVEL_3, 0, 6862 "!FCP:Report Lun Has Changed" 6863 " target=%x", ptgt->tgt_d_id); 6864 } else if (FCP_SENSE_NO_LUN(sense)) { 6865 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6866 fcp_trace, FCP_BUF_LEVEL_3, 0, 6867 "!FCP:LU Not Supported" 6868 " target=%x", ptgt->tgt_d_id); 6869 } 6870 } 6871 rval = DDI_SUCCESS; 6872 } 6873 6874 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6875 fcp_trace, FCP_BUF_LEVEL_5, 0, 6876 "D_ID=%x, sense=%x, status=%x", 6877 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6878 rsp->fcp_u.fcp_status.scsi_status); 6879 6880 return (rval); 6881 } 6882 6883 /* 6884 * Function: fcp_scsi_callback 6885 * 6886 * Description: This is the callback routine set by fcp_send_scsi() after 6887 * it calls fcp_icmd_alloc(). The SCSI command completed here 6888 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6889 * INQUIRY_PAGE83. 6890 * 6891 * Argument: *fpkt FC packet used to convey the command 6892 * 6893 * Return Value: None 6894 */ 6895 static void 6896 fcp_scsi_callback(fc_packet_t *fpkt) 6897 { 6898 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6899 fpkt->pkt_ulp_private; 6900 struct fcp_rsp_info fcp_rsp_err, *bep; 6901 struct fcp_port *pptr; 6902 struct fcp_tgt *ptgt; 6903 struct fcp_lun *plun; 6904 struct fcp_rsp response, *rsp; 6905 6906 ptgt = icmd->ipkt_tgt; 6907 pptr = ptgt->tgt_port; 6908 plun = icmd->ipkt_lun; 6909 6910 if (icmd->ipkt_nodma) { 6911 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6912 } else { 6913 rsp = &response; 6914 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6915 sizeof (struct fcp_rsp)); 6916 } 6917 6918 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6919 fcp_trace, FCP_BUF_LEVEL_2, 0, 6920 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6921 "status=%x, lun num=%x", 6922 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6923 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6924 6925 /* 6926 * Pre-init LUN GUID with NWWN if it is not a device that 6927 * supports multiple luns and we know it's not page83 6928 * compliant. Although using a NWWN is not lun unique, 6929 * we will be fine since there is only one lun behind the taget 6930 * in this case. 6931 */ 6932 if ((plun->lun_guid_size == 0) && 6933 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6934 (fcp_symmetric_device_probe(plun) == 0)) { 6935 6936 char ascii_wwn[FC_WWN_SIZE*2+1]; 6937 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6938 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6939 } 6940 6941 /* 6942 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6943 * when thay have more data than what is asked in CDB. An overrun 6944 * is really when FCP_DL is smaller than the data length in CDB. 6945 * In the case here we know that REPORT LUN command we formed within 6946 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6947 * behavior. In reality this is FC_SUCCESS. 6948 */ 6949 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6950 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6951 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6952 fpkt->pkt_state = FC_PKT_SUCCESS; 6953 } 6954 6955 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6956 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6957 fcp_trace, FCP_BUF_LEVEL_2, 0, 6958 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6959 ptgt->tgt_d_id); 6960 6961 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6962 /* 6963 * Inquiry VPD page command on A5K SES devices would 6964 * result in data CRC errors. 6965 */ 6966 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6967 (void) fcp_handle_page83(fpkt, icmd, 1); 6968 return; 6969 } 6970 } 6971 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6972 FCP_MUST_RETRY(fpkt)) { 6973 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6974 fcp_retry_scsi_cmd(fpkt); 6975 return; 6976 } 6977 6978 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6979 FCP_TGT_TRACE_20); 6980 6981 mutex_enter(&pptr->port_mutex); 6982 mutex_enter(&ptgt->tgt_mutex); 6983 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6984 mutex_exit(&ptgt->tgt_mutex); 6985 mutex_exit(&pptr->port_mutex); 6986 fcp_print_error(fpkt); 6987 } else { 6988 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6989 fcp_trace, FCP_BUF_LEVEL_2, 0, 6990 "fcp_scsi_callback,1: state change occured" 6991 " for D_ID=0x%x", ptgt->tgt_d_id); 6992 mutex_exit(&ptgt->tgt_mutex); 6993 mutex_exit(&pptr->port_mutex); 6994 } 6995 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6996 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6997 fcp_icmd_free(pptr, icmd); 6998 return; 6999 } 7000 7001 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 7002 7003 mutex_enter(&pptr->port_mutex); 7004 mutex_enter(&ptgt->tgt_mutex); 7005 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7006 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7007 fcp_trace, FCP_BUF_LEVEL_2, 0, 7008 "fcp_scsi_callback,2: state change occured" 7009 " for D_ID=0x%x", ptgt->tgt_d_id); 7010 mutex_exit(&ptgt->tgt_mutex); 7011 mutex_exit(&pptr->port_mutex); 7012 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7013 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7014 fcp_icmd_free(pptr, icmd); 7015 return; 7016 } 7017 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7018 7019 mutex_exit(&ptgt->tgt_mutex); 7020 mutex_exit(&pptr->port_mutex); 7021 7022 if (icmd->ipkt_nodma) { 7023 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7024 sizeof (struct fcp_rsp)); 7025 } else { 7026 bep = &fcp_rsp_err; 7027 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7028 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7029 } 7030 7031 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7032 fcp_retry_scsi_cmd(fpkt); 7033 return; 7034 } 7035 7036 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7037 FCP_NO_FAILURE) { 7038 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7039 fcp_trace, FCP_BUF_LEVEL_2, 0, 7040 "rsp_code=0x%x, rsp_len_set=0x%x", 7041 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7042 fcp_retry_scsi_cmd(fpkt); 7043 return; 7044 } 7045 7046 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7047 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7048 fcp_queue_ipkt(pptr, fpkt); 7049 return; 7050 } 7051 7052 /* 7053 * Devices that do not support INQUIRY_PAGE83, return check condition 7054 * with illegal request as per SCSI spec. 7055 * Crossbridge is one such device and Daktari's SES node is another. 7056 * We want to ideally enumerate these devices as a non-mpxio devices. 7057 * SES nodes (Daktari only currently) are an exception to this. 7058 */ 7059 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7060 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7061 7062 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7063 fcp_trace, FCP_BUF_LEVEL_3, 0, 7064 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7065 "check condition. May enumerate as non-mpxio device", 7066 ptgt->tgt_d_id, plun->lun_type); 7067 7068 /* 7069 * If we let Daktari's SES be enumerated as a non-mpxio 7070 * device, there will be a discrepency in that the other 7071 * internal FC disks will get enumerated as mpxio devices. 7072 * Applications like luxadm expect this to be consistent. 7073 * 7074 * So, we put in a hack here to check if this is an SES device 7075 * and handle it here. 7076 */ 7077 if (plun->lun_type == DTYPE_ESI) { 7078 /* 7079 * Since, pkt_state is actually FC_PKT_SUCCESS 7080 * at this stage, we fake a failure here so that 7081 * fcp_handle_page83 will create a device path using 7082 * the WWN instead of the GUID which is not there anyway 7083 */ 7084 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7085 (void) fcp_handle_page83(fpkt, icmd, 1); 7086 return; 7087 } 7088 7089 mutex_enter(&ptgt->tgt_mutex); 7090 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7091 FCP_LUN_MARK | FCP_LUN_BUSY); 7092 mutex_exit(&ptgt->tgt_mutex); 7093 7094 (void) fcp_call_finish_init(pptr, ptgt, 7095 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7096 icmd->ipkt_cause); 7097 fcp_icmd_free(pptr, icmd); 7098 return; 7099 } 7100 7101 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7102 int rval = DDI_FAILURE; 7103 7104 /* 7105 * handle cases where report lun isn't supported 7106 * by faking up our own REPORT_LUN response or 7107 * UNIT ATTENTION 7108 */ 7109 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7110 rval = fcp_check_reportlun(rsp, fpkt); 7111 7112 /* 7113 * fcp_check_reportlun might have modified the 7114 * FCP response. Copy it in again to get an updated 7115 * FCP response 7116 */ 7117 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7118 rsp = &response; 7119 7120 FCP_CP_IN(fpkt->pkt_resp, rsp, 7121 fpkt->pkt_resp_acc, 7122 sizeof (struct fcp_rsp)); 7123 } 7124 } 7125 7126 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7127 if (rval == DDI_SUCCESS) { 7128 (void) fcp_call_finish_init(pptr, ptgt, 7129 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7130 icmd->ipkt_cause); 7131 fcp_icmd_free(pptr, icmd); 7132 } else { 7133 fcp_retry_scsi_cmd(fpkt); 7134 } 7135 7136 return; 7137 } 7138 } else { 7139 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7140 mutex_enter(&ptgt->tgt_mutex); 7141 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7142 mutex_exit(&ptgt->tgt_mutex); 7143 } 7144 } 7145 7146 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7147 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7148 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7149 DDI_DMA_SYNC_FORCPU); 7150 } 7151 7152 switch (icmd->ipkt_opcode) { 7153 case SCMD_INQUIRY: 7154 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7155 fcp_handle_inquiry(fpkt, icmd); 7156 break; 7157 7158 case SCMD_REPORT_LUN: 7159 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7160 FCP_TGT_TRACE_22); 7161 fcp_handle_reportlun(fpkt, icmd); 7162 break; 7163 7164 case SCMD_INQUIRY_PAGE83: 7165 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7166 (void) fcp_handle_page83(fpkt, icmd, 0); 7167 break; 7168 7169 default: 7170 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7171 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7172 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7173 fcp_icmd_free(pptr, icmd); 7174 break; 7175 } 7176 } 7177 7178 7179 static void 7180 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7181 { 7182 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7183 fpkt->pkt_ulp_private; 7184 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7185 struct fcp_port *pptr = ptgt->tgt_port; 7186 7187 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7188 fcp_is_retryable(icmd)) { 7189 mutex_enter(&pptr->port_mutex); 7190 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7191 mutex_exit(&pptr->port_mutex); 7192 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7193 fcp_trace, FCP_BUF_LEVEL_3, 0, 7194 "Retrying %s to %x; state=%x, reason=%x", 7195 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7196 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7197 fpkt->pkt_state, fpkt->pkt_reason); 7198 7199 fcp_queue_ipkt(pptr, fpkt); 7200 } else { 7201 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7202 fcp_trace, FCP_BUF_LEVEL_3, 0, 7203 "fcp_retry_scsi_cmd,1: state change occured" 7204 " for D_ID=0x%x", ptgt->tgt_d_id); 7205 mutex_exit(&pptr->port_mutex); 7206 (void) fcp_call_finish_init(pptr, ptgt, 7207 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7208 icmd->ipkt_cause); 7209 fcp_icmd_free(pptr, icmd); 7210 } 7211 } else { 7212 fcp_print_error(fpkt); 7213 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7214 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7215 fcp_icmd_free(pptr, icmd); 7216 } 7217 } 7218 7219 /* 7220 * Function: fcp_handle_page83 7221 * 7222 * Description: Treats the response to INQUIRY_PAGE83. 7223 * 7224 * Argument: *fpkt FC packet used to convey the command. 7225 * *icmd Original fcp_ipkt structure. 7226 * ignore_page83_data 7227 * if it's 1, that means it's a special devices's 7228 * page83 response, it should be enumerated under mpxio 7229 * 7230 * Return Value: None 7231 */ 7232 static void 7233 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7234 int ignore_page83_data) 7235 { 7236 struct fcp_port *pptr; 7237 struct fcp_lun *plun; 7238 struct fcp_tgt *ptgt; 7239 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7240 int fail = 0; 7241 ddi_devid_t devid; 7242 char *guid = NULL; 7243 int ret; 7244 7245 ASSERT(icmd != NULL && fpkt != NULL); 7246 7247 pptr = icmd->ipkt_port; 7248 ptgt = icmd->ipkt_tgt; 7249 plun = icmd->ipkt_lun; 7250 7251 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7252 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7253 7254 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7255 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7256 7257 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7258 fcp_trace, FCP_BUF_LEVEL_5, 0, 7259 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7260 "dtype=0x%x, lun num=%x", 7261 pptr->port_instance, ptgt->tgt_d_id, 7262 dev_id_page[0], plun->lun_num); 7263 7264 ret = ddi_devid_scsi_encode( 7265 DEVID_SCSI_ENCODE_VERSION_LATEST, 7266 NULL, /* driver name */ 7267 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7268 sizeof (plun->lun_inq), /* size of standard inquiry */ 7269 NULL, /* page 80 data */ 7270 0, /* page 80 len */ 7271 dev_id_page, /* page 83 data */ 7272 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7273 &devid); 7274 7275 if (ret == DDI_SUCCESS) { 7276 7277 guid = ddi_devid_to_guid(devid); 7278 7279 if (guid) { 7280 /* 7281 * Check our current guid. If it's non null 7282 * and it has changed, we need to copy it into 7283 * lun_old_guid since we might still need it. 7284 */ 7285 if (plun->lun_guid && 7286 strcmp(guid, plun->lun_guid)) { 7287 unsigned int len; 7288 7289 /* 7290 * If the guid of the LUN changes, 7291 * reconfiguration should be triggered 7292 * to reflect the changes. 7293 * i.e. we should offline the LUN with 7294 * the old guid, and online the LUN with 7295 * the new guid. 7296 */ 7297 plun->lun_state |= FCP_LUN_CHANGED; 7298 7299 if (plun->lun_old_guid) { 7300 kmem_free(plun->lun_old_guid, 7301 plun->lun_old_guid_size); 7302 } 7303 7304 len = plun->lun_guid_size; 7305 plun->lun_old_guid_size = len; 7306 7307 plun->lun_old_guid = kmem_zalloc(len, 7308 KM_NOSLEEP); 7309 7310 if (plun->lun_old_guid) { 7311 /* 7312 * The alloc was successful then 7313 * let's do the copy. 7314 */ 7315 bcopy(plun->lun_guid, 7316 plun->lun_old_guid, len); 7317 } else { 7318 fail = 1; 7319 plun->lun_old_guid_size = 0; 7320 } 7321 } 7322 if (!fail) { 7323 if (fcp_copy_guid_2_lun_block( 7324 plun, guid)) { 7325 fail = 1; 7326 } 7327 } 7328 ddi_devid_free_guid(guid); 7329 7330 } else { 7331 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7332 fcp_trace, FCP_BUF_LEVEL_2, 0, 7333 "fcp_handle_page83: unable to create " 7334 "GUID"); 7335 7336 /* couldn't create good guid from devid */ 7337 fail = 1; 7338 } 7339 ddi_devid_free(devid); 7340 7341 } else if (ret == DDI_NOT_WELL_FORMED) { 7342 /* NULL filled data for page 83 */ 7343 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7344 fcp_trace, FCP_BUF_LEVEL_2, 0, 7345 "fcp_handle_page83: retry GUID"); 7346 7347 icmd->ipkt_retries = 0; 7348 fcp_retry_scsi_cmd(fpkt); 7349 return; 7350 } else { 7351 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7352 fcp_trace, FCP_BUF_LEVEL_2, 0, 7353 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7354 ret); 7355 /* 7356 * Since the page83 validation 7357 * introduced late, we are being 7358 * tolerant to the existing devices 7359 * that already found to be working 7360 * under mpxio, like A5200's SES device, 7361 * its page83 response will not be standard-compliant, 7362 * but we still want it to be enumerated under mpxio. 7363 */ 7364 if (fcp_symmetric_device_probe(plun) != 0) { 7365 fail = 1; 7366 } 7367 } 7368 7369 } else { 7370 /* bad packet state */ 7371 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7372 7373 /* 7374 * For some special devices (A5K SES and Daktari's SES devices), 7375 * they should be enumerated under mpxio 7376 * or "luxadm dis" will fail 7377 */ 7378 if (ignore_page83_data) { 7379 fail = 0; 7380 } else { 7381 fail = 1; 7382 } 7383 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7384 fcp_trace, FCP_BUF_LEVEL_2, 0, 7385 "!Devid page cmd failed. " 7386 "fpkt_state: %x fpkt_reason: %x", 7387 "ignore_page83: %d", 7388 fpkt->pkt_state, fpkt->pkt_reason, 7389 ignore_page83_data); 7390 } 7391 7392 mutex_enter(&pptr->port_mutex); 7393 mutex_enter(&plun->lun_mutex); 7394 /* 7395 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7396 * mismatch between lun_cip and lun_mpxio. 7397 */ 7398 if (plun->lun_cip == NULL) { 7399 /* 7400 * If we don't have a guid for this lun it's because we were 7401 * unable to glean one from the page 83 response. Set the 7402 * control flag to 0 here to make sure that we don't attempt to 7403 * enumerate it under mpxio. 7404 */ 7405 if (fail || pptr->port_mpxio == 0) { 7406 plun->lun_mpxio = 0; 7407 } else { 7408 plun->lun_mpxio = 1; 7409 } 7410 } 7411 mutex_exit(&plun->lun_mutex); 7412 mutex_exit(&pptr->port_mutex); 7413 7414 mutex_enter(&ptgt->tgt_mutex); 7415 plun->lun_state &= 7416 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7417 mutex_exit(&ptgt->tgt_mutex); 7418 7419 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7420 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7421 7422 fcp_icmd_free(pptr, icmd); 7423 } 7424 7425 /* 7426 * Function: fcp_handle_inquiry 7427 * 7428 * Description: Called by fcp_scsi_callback to handle the response to an 7429 * INQUIRY request. 7430 * 7431 * Argument: *fpkt FC packet used to convey the command. 7432 * *icmd Original fcp_ipkt structure. 7433 * 7434 * Return Value: None 7435 */ 7436 static void 7437 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7438 { 7439 struct fcp_port *pptr; 7440 struct fcp_lun *plun; 7441 struct fcp_tgt *ptgt; 7442 uchar_t dtype; 7443 uchar_t pqual; 7444 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7445 7446 ASSERT(icmd != NULL && fpkt != NULL); 7447 7448 pptr = icmd->ipkt_port; 7449 ptgt = icmd->ipkt_tgt; 7450 plun = icmd->ipkt_lun; 7451 7452 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7453 sizeof (struct scsi_inquiry)); 7454 7455 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7456 pqual = plun->lun_inq.inq_dtype >> 5; 7457 7458 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7459 fcp_trace, FCP_BUF_LEVEL_5, 0, 7460 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7461 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7462 plun->lun_num, dtype, pqual); 7463 7464 if (pqual != 0) { 7465 /* 7466 * Non-zero peripheral qualifier 7467 */ 7468 fcp_log(CE_CONT, pptr->port_dip, 7469 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7470 "Device type=0x%x Peripheral qual=0x%x\n", 7471 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7472 7473 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7474 fcp_trace, FCP_BUF_LEVEL_5, 0, 7475 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7476 "Device type=0x%x Peripheral qual=0x%x\n", 7477 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7478 7479 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7480 7481 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7482 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7483 fcp_icmd_free(pptr, icmd); 7484 return; 7485 } 7486 7487 /* 7488 * If the device is already initialized, check the dtype 7489 * for a change. If it has changed then update the flags 7490 * so the create_luns will offline the old device and 7491 * create the new device. Refer to bug: 4764752 7492 */ 7493 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7494 plun->lun_state |= FCP_LUN_CHANGED; 7495 } 7496 plun->lun_type = plun->lun_inq.inq_dtype; 7497 7498 /* 7499 * This code is setting/initializing the throttling in the FCA 7500 * driver. 7501 */ 7502 mutex_enter(&pptr->port_mutex); 7503 if (!pptr->port_notify) { 7504 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7505 uint32_t cmd = 0; 7506 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7507 ((cmd & 0xFFFFFF00 >> 8) | 7508 FCP_SVE_THROTTLE << 8)); 7509 pptr->port_notify = 1; 7510 mutex_exit(&pptr->port_mutex); 7511 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7512 mutex_enter(&pptr->port_mutex); 7513 } 7514 } 7515 7516 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7517 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7518 fcp_trace, FCP_BUF_LEVEL_2, 0, 7519 "fcp_handle_inquiry,1:state change occured" 7520 " for D_ID=0x%x", ptgt->tgt_d_id); 7521 mutex_exit(&pptr->port_mutex); 7522 7523 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7524 (void) fcp_call_finish_init(pptr, ptgt, 7525 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7526 icmd->ipkt_cause); 7527 fcp_icmd_free(pptr, icmd); 7528 return; 7529 } 7530 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7531 mutex_exit(&pptr->port_mutex); 7532 7533 /* Retrieve the rscn count (if a valid one exists) */ 7534 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7535 rscn_count = ((fc_ulp_rscn_info_t *) 7536 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7537 } else { 7538 rscn_count = FC_INVALID_RSCN_COUNT; 7539 } 7540 7541 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7542 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7543 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7544 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7545 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7546 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7547 (void) fcp_call_finish_init(pptr, ptgt, 7548 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7549 icmd->ipkt_cause); 7550 } 7551 7552 /* 7553 * Read Inquiry VPD Page 0x83 to uniquely 7554 * identify this logical unit. 7555 */ 7556 fcp_icmd_free(pptr, icmd); 7557 } 7558 7559 /* 7560 * Function: fcp_handle_reportlun 7561 * 7562 * Description: Called by fcp_scsi_callback to handle the response to a 7563 * REPORT_LUN request. 7564 * 7565 * Argument: *fpkt FC packet used to convey the command. 7566 * *icmd Original fcp_ipkt structure. 7567 * 7568 * Return Value: None 7569 */ 7570 static void 7571 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7572 { 7573 int i; 7574 int nluns_claimed; 7575 int nluns_bufmax; 7576 int len; 7577 uint16_t lun_num; 7578 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7579 struct fcp_port *pptr; 7580 struct fcp_tgt *ptgt; 7581 struct fcp_lun *plun; 7582 struct fcp_reportlun_resp *report_lun; 7583 7584 pptr = icmd->ipkt_port; 7585 ptgt = icmd->ipkt_tgt; 7586 len = fpkt->pkt_datalen; 7587 7588 if ((len < FCP_LUN_HEADER) || 7589 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7590 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7591 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7592 fcp_icmd_free(pptr, icmd); 7593 return; 7594 } 7595 7596 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7597 fpkt->pkt_datalen); 7598 7599 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7600 fcp_trace, FCP_BUF_LEVEL_5, 0, 7601 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7602 pptr->port_instance, ptgt->tgt_d_id); 7603 7604 /* 7605 * Get the number of luns (which is supplied as LUNS * 8) the 7606 * device claims it has. 7607 */ 7608 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7609 7610 /* 7611 * Get the maximum number of luns the buffer submitted can hold. 7612 */ 7613 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7614 7615 /* 7616 * Due to limitations of certain hardware, we support only 16 bit LUNs 7617 */ 7618 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7619 kmem_free(report_lun, len); 7620 7621 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7622 " 0x%x number of LUNs for target=%x", nluns_claimed, 7623 ptgt->tgt_d_id); 7624 7625 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7626 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7627 fcp_icmd_free(pptr, icmd); 7628 return; 7629 } 7630 7631 /* 7632 * If there are more LUNs than we have allocated memory for, 7633 * allocate more space and send down yet another report lun if 7634 * the maximum number of attempts hasn't been reached. 7635 */ 7636 mutex_enter(&ptgt->tgt_mutex); 7637 7638 if ((nluns_claimed > nluns_bufmax) && 7639 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7640 7641 struct fcp_lun *plun; 7642 7643 ptgt->tgt_report_lun_cnt++; 7644 plun = ptgt->tgt_lun; 7645 ASSERT(plun != NULL); 7646 mutex_exit(&ptgt->tgt_mutex); 7647 7648 kmem_free(report_lun, len); 7649 7650 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7651 fcp_trace, FCP_BUF_LEVEL_5, 0, 7652 "!Dynamically discovered %d LUNs for D_ID=%x", 7653 nluns_claimed, ptgt->tgt_d_id); 7654 7655 /* Retrieve the rscn count (if a valid one exists) */ 7656 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7657 rscn_count = ((fc_ulp_rscn_info_t *) 7658 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7659 ulp_rscn_count; 7660 } else { 7661 rscn_count = FC_INVALID_RSCN_COUNT; 7662 } 7663 7664 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7665 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7666 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7667 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7668 (void) fcp_call_finish_init(pptr, ptgt, 7669 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7670 icmd->ipkt_cause); 7671 } 7672 7673 fcp_icmd_free(pptr, icmd); 7674 return; 7675 } 7676 7677 if (nluns_claimed > nluns_bufmax) { 7678 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7679 fcp_trace, FCP_BUF_LEVEL_5, 0, 7680 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7681 " Number of LUNs lost=%x", 7682 ptgt->tgt_port_wwn.raw_wwn[0], 7683 ptgt->tgt_port_wwn.raw_wwn[1], 7684 ptgt->tgt_port_wwn.raw_wwn[2], 7685 ptgt->tgt_port_wwn.raw_wwn[3], 7686 ptgt->tgt_port_wwn.raw_wwn[4], 7687 ptgt->tgt_port_wwn.raw_wwn[5], 7688 ptgt->tgt_port_wwn.raw_wwn[6], 7689 ptgt->tgt_port_wwn.raw_wwn[7], 7690 nluns_claimed - nluns_bufmax); 7691 7692 nluns_claimed = nluns_bufmax; 7693 } 7694 ptgt->tgt_lun_cnt = nluns_claimed; 7695 7696 /* 7697 * Identify missing LUNs and print warning messages 7698 */ 7699 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7700 int offline; 7701 int exists = 0; 7702 7703 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7704 7705 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7706 uchar_t *lun_string; 7707 7708 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7709 7710 switch (lun_string[0] & 0xC0) { 7711 case FCP_LUN_ADDRESSING: 7712 case FCP_PD_ADDRESSING: 7713 case FCP_VOLUME_ADDRESSING: 7714 lun_num = ((lun_string[0] & 0x3F) << 8) | 7715 lun_string[1]; 7716 if (plun->lun_num == lun_num) { 7717 exists++; 7718 break; 7719 } 7720 break; 7721 7722 default: 7723 break; 7724 } 7725 } 7726 7727 if (!exists && !offline) { 7728 mutex_exit(&ptgt->tgt_mutex); 7729 7730 mutex_enter(&pptr->port_mutex); 7731 mutex_enter(&ptgt->tgt_mutex); 7732 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7733 /* 7734 * set disappear flag when device was connected 7735 */ 7736 if (!(plun->lun_state & 7737 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7738 plun->lun_state |= FCP_LUN_DISAPPEARED; 7739 } 7740 mutex_exit(&ptgt->tgt_mutex); 7741 mutex_exit(&pptr->port_mutex); 7742 if (!(plun->lun_state & 7743 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7744 fcp_log(CE_NOTE, pptr->port_dip, 7745 "!Lun=%x for target=%x disappeared", 7746 plun->lun_num, ptgt->tgt_d_id); 7747 } 7748 mutex_enter(&ptgt->tgt_mutex); 7749 } else { 7750 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7751 fcp_trace, FCP_BUF_LEVEL_5, 0, 7752 "fcp_handle_reportlun,1: state change" 7753 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7754 mutex_exit(&ptgt->tgt_mutex); 7755 mutex_exit(&pptr->port_mutex); 7756 kmem_free(report_lun, len); 7757 (void) fcp_call_finish_init(pptr, ptgt, 7758 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7759 icmd->ipkt_cause); 7760 fcp_icmd_free(pptr, icmd); 7761 return; 7762 } 7763 } else if (exists) { 7764 /* 7765 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7766 * actually exists in REPORT_LUN response 7767 */ 7768 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7769 plun->lun_state &= 7770 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7771 } 7772 if (offline || plun->lun_num == 0) { 7773 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7774 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7775 mutex_exit(&ptgt->tgt_mutex); 7776 fcp_log(CE_NOTE, pptr->port_dip, 7777 "!Lun=%x for target=%x reappeared", 7778 plun->lun_num, ptgt->tgt_d_id); 7779 mutex_enter(&ptgt->tgt_mutex); 7780 } 7781 } 7782 } 7783 } 7784 7785 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7786 mutex_exit(&ptgt->tgt_mutex); 7787 7788 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7789 fcp_trace, FCP_BUF_LEVEL_5, 0, 7790 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7791 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7792 7793 /* scan each lun */ 7794 for (i = 0; i < nluns_claimed; i++) { 7795 uchar_t *lun_string; 7796 7797 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7798 7799 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7800 fcp_trace, FCP_BUF_LEVEL_5, 0, 7801 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7802 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7803 lun_string[0]); 7804 7805 switch (lun_string[0] & 0xC0) { 7806 case FCP_LUN_ADDRESSING: 7807 case FCP_PD_ADDRESSING: 7808 case FCP_VOLUME_ADDRESSING: 7809 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7810 7811 /* We will skip masked LUNs because of the blacklist. */ 7812 if (fcp_lun_blacklist != NULL) { 7813 mutex_enter(&ptgt->tgt_mutex); 7814 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7815 lun_num) == TRUE) { 7816 ptgt->tgt_lun_cnt--; 7817 mutex_exit(&ptgt->tgt_mutex); 7818 break; 7819 } 7820 mutex_exit(&ptgt->tgt_mutex); 7821 } 7822 7823 /* see if this LUN is already allocated */ 7824 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7825 plun = fcp_alloc_lun(ptgt); 7826 if (plun == NULL) { 7827 fcp_log(CE_NOTE, pptr->port_dip, 7828 "!Lun allocation failed" 7829 " target=%x lun=%x", 7830 ptgt->tgt_d_id, lun_num); 7831 break; 7832 } 7833 } 7834 7835 mutex_enter(&plun->lun_tgt->tgt_mutex); 7836 /* convert to LUN */ 7837 plun->lun_addr.ent_addr_0 = 7838 BE_16(*(uint16_t *)&(lun_string[0])); 7839 plun->lun_addr.ent_addr_1 = 7840 BE_16(*(uint16_t *)&(lun_string[2])); 7841 plun->lun_addr.ent_addr_2 = 7842 BE_16(*(uint16_t *)&(lun_string[4])); 7843 plun->lun_addr.ent_addr_3 = 7844 BE_16(*(uint16_t *)&(lun_string[6])); 7845 7846 plun->lun_num = lun_num; 7847 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7848 plun->lun_state &= ~FCP_LUN_OFFLINE; 7849 mutex_exit(&plun->lun_tgt->tgt_mutex); 7850 7851 /* Retrieve the rscn count (if a valid one exists) */ 7852 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7853 rscn_count = ((fc_ulp_rscn_info_t *) 7854 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7855 ulp_rscn_count; 7856 } else { 7857 rscn_count = FC_INVALID_RSCN_COUNT; 7858 } 7859 7860 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7861 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7862 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7863 mutex_enter(&pptr->port_mutex); 7864 mutex_enter(&plun->lun_tgt->tgt_mutex); 7865 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7866 fcp_log(CE_NOTE, pptr->port_dip, 7867 "!failed to send INQUIRY" 7868 " target=%x lun=%x", 7869 ptgt->tgt_d_id, plun->lun_num); 7870 } else { 7871 FCP_TRACE(fcp_logq, 7872 pptr->port_instbuf, fcp_trace, 7873 FCP_BUF_LEVEL_5, 0, 7874 "fcp_handle_reportlun,2: state" 7875 " change occured for D_ID=0x%x", 7876 ptgt->tgt_d_id); 7877 } 7878 mutex_exit(&plun->lun_tgt->tgt_mutex); 7879 mutex_exit(&pptr->port_mutex); 7880 } else { 7881 continue; 7882 } 7883 break; 7884 7885 default: 7886 fcp_log(CE_WARN, NULL, 7887 "!Unsupported LUN Addressing method %x " 7888 "in response to REPORT_LUN", lun_string[0]); 7889 break; 7890 } 7891 7892 /* 7893 * each time through this loop we should decrement 7894 * the tmp_cnt by one -- since we go through this loop 7895 * one time for each LUN, the tmp_cnt should never be <=0 7896 */ 7897 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7898 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7899 } 7900 7901 if (i == 0) { 7902 fcp_log(CE_WARN, pptr->port_dip, 7903 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7904 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7905 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7906 } 7907 7908 kmem_free(report_lun, len); 7909 fcp_icmd_free(pptr, icmd); 7910 } 7911 7912 7913 /* 7914 * called internally to return a LUN given a target and a LUN number 7915 */ 7916 static struct fcp_lun * 7917 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7918 { 7919 struct fcp_lun *plun; 7920 7921 mutex_enter(&ptgt->tgt_mutex); 7922 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7923 if (plun->lun_num == lun_num) { 7924 mutex_exit(&ptgt->tgt_mutex); 7925 return (plun); 7926 } 7927 } 7928 mutex_exit(&ptgt->tgt_mutex); 7929 7930 return (NULL); 7931 } 7932 7933 7934 /* 7935 * handle finishing one target for fcp_finish_init 7936 * 7937 * return true (non-zero) if we want finish_init to continue with the 7938 * next target 7939 * 7940 * called with the port mutex held 7941 */ 7942 /*ARGSUSED*/ 7943 static int 7944 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7945 int link_cnt, int tgt_cnt, int cause) 7946 { 7947 int rval = 1; 7948 ASSERT(pptr != NULL); 7949 ASSERT(ptgt != NULL); 7950 7951 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7952 fcp_trace, FCP_BUF_LEVEL_5, 0, 7953 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7954 ptgt->tgt_state); 7955 7956 ASSERT(mutex_owned(&pptr->port_mutex)); 7957 7958 if ((pptr->port_link_cnt != link_cnt) || 7959 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7960 /* 7961 * oh oh -- another link reset or target change 7962 * must have occurred while we are in here 7963 */ 7964 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7965 7966 return (0); 7967 } else { 7968 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7969 } 7970 7971 mutex_enter(&ptgt->tgt_mutex); 7972 7973 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7974 /* 7975 * tgt is not offline -- is it marked (i.e. needs 7976 * to be offlined) ?? 7977 */ 7978 if (ptgt->tgt_state & FCP_TGT_MARK) { 7979 /* 7980 * this target not offline *and* 7981 * marked 7982 */ 7983 ptgt->tgt_state &= ~FCP_TGT_MARK; 7984 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7985 tgt_cnt, 0, 0); 7986 } else { 7987 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7988 7989 /* create the LUNs */ 7990 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7991 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7992 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7993 cause); 7994 ptgt->tgt_device_created = 1; 7995 } else { 7996 fcp_update_tgt_state(ptgt, FCP_RESET, 7997 FCP_LUN_BUSY); 7998 } 7999 } 8000 } 8001 8002 mutex_exit(&ptgt->tgt_mutex); 8003 8004 return (rval); 8005 } 8006 8007 8008 /* 8009 * this routine is called to finish port initialization 8010 * 8011 * Each port has a "temp" counter -- when a state change happens (e.g. 8012 * port online), the temp count is set to the number of devices in the map. 8013 * Then, as each device gets "discovered", the temp counter is decremented 8014 * by one. When this count reaches zero we know that all of the devices 8015 * in the map have been discovered (or an error has occurred), so we can 8016 * then finish initialization -- which is done by this routine (well, this 8017 * and fcp-finish_tgt()) 8018 * 8019 * acquires and releases the global mutex 8020 * 8021 * called with the port mutex owned 8022 */ 8023 static void 8024 fcp_finish_init(struct fcp_port *pptr) 8025 { 8026 #ifdef DEBUG 8027 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8028 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8029 FCP_STACK_DEPTH); 8030 #endif /* DEBUG */ 8031 8032 ASSERT(mutex_owned(&pptr->port_mutex)); 8033 8034 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8035 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8036 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8037 8038 if ((pptr->port_state & FCP_STATE_ONLINING) && 8039 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8040 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8041 pptr->port_state &= ~FCP_STATE_ONLINING; 8042 pptr->port_state |= FCP_STATE_ONLINE; 8043 } 8044 8045 /* Wake up threads waiting on config done */ 8046 cv_broadcast(&pptr->port_config_cv); 8047 } 8048 8049 8050 /* 8051 * called from fcp_finish_init to create the LUNs for a target 8052 * 8053 * called with the port mutex owned 8054 */ 8055 static void 8056 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8057 { 8058 struct fcp_lun *plun; 8059 struct fcp_port *pptr; 8060 child_info_t *cip = NULL; 8061 8062 ASSERT(ptgt != NULL); 8063 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8064 8065 pptr = ptgt->tgt_port; 8066 8067 ASSERT(pptr != NULL); 8068 8069 /* scan all LUNs for this target */ 8070 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8071 if (plun->lun_state & FCP_LUN_OFFLINE) { 8072 continue; 8073 } 8074 8075 if (plun->lun_state & FCP_LUN_MARK) { 8076 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8077 fcp_trace, FCP_BUF_LEVEL_2, 0, 8078 "fcp_create_luns: offlining marked LUN!"); 8079 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8080 continue; 8081 } 8082 8083 plun->lun_state &= ~FCP_LUN_BUSY; 8084 8085 /* 8086 * There are conditions in which FCP_LUN_INIT flag is cleared 8087 * but we have a valid plun->lun_cip. To cover this case also 8088 * CLEAR_BUSY whenever we have a valid lun_cip. 8089 */ 8090 if (plun->lun_mpxio && plun->lun_cip && 8091 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8092 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8093 0, 0))) { 8094 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8095 fcp_trace, FCP_BUF_LEVEL_2, 0, 8096 "fcp_create_luns: enable lun %p failed!", 8097 plun); 8098 } 8099 8100 if (plun->lun_state & FCP_LUN_INIT && 8101 !(plun->lun_state & FCP_LUN_CHANGED)) { 8102 continue; 8103 } 8104 8105 if (cause == FCP_CAUSE_USER_CREATE) { 8106 continue; 8107 } 8108 8109 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8110 fcp_trace, FCP_BUF_LEVEL_6, 0, 8111 "create_luns: passing ONLINE elem to HP thread"); 8112 8113 /* 8114 * If lun has changed, prepare for offlining the old path. 8115 * Do not offline the old path right now, since it may be 8116 * still opened. 8117 */ 8118 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8119 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8120 } 8121 8122 /* pass an ONLINE element to the hotplug thread */ 8123 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8124 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8125 8126 /* 8127 * We can not synchronous attach (i.e pass 8128 * NDI_ONLINE_ATTACH) here as we might be 8129 * coming from an interrupt or callback 8130 * thread. 8131 */ 8132 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8133 link_cnt, tgt_cnt, 0, 0)) { 8134 fcp_log(CE_CONT, pptr->port_dip, 8135 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8136 plun->lun_tgt->tgt_d_id, plun->lun_num); 8137 } 8138 } 8139 } 8140 } 8141 8142 8143 /* 8144 * function to online/offline devices 8145 */ 8146 static int 8147 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8148 int online, int lcount, int tcount, int flags) 8149 { 8150 int rval = NDI_FAILURE; 8151 int circ; 8152 child_info_t *ccip; 8153 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8154 int is_mpxio = pptr->port_mpxio; 8155 dev_info_t *cdip, *pdip; 8156 char *devname; 8157 8158 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8159 /* 8160 * When this event gets serviced, lun_cip and lun_mpxio 8161 * has changed, so it should be invalidated now. 8162 */ 8163 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8164 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8165 "plun: %p, cip: %p, what:%d", plun, cip, online); 8166 return (rval); 8167 } 8168 8169 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8170 fcp_trace, FCP_BUF_LEVEL_2, 0, 8171 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8172 "flags=%x mpxio=%x\n", 8173 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8174 plun->lun_mpxio); 8175 8176 /* 8177 * lun_mpxio needs checking here because we can end up in a race 8178 * condition where this task has been dispatched while lun_mpxio is 8179 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8180 * enable MPXIO for the LUN, but was unable to, and hence cleared 8181 * the flag. We rely on the serialization of the tasks here. We return 8182 * NDI_SUCCESS so any callers continue without reporting spurious 8183 * errors, and the still think we're an MPXIO LUN. 8184 */ 8185 8186 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8187 online == FCP_MPXIO_PATH_SET_BUSY) { 8188 if (plun->lun_mpxio) { 8189 rval = fcp_update_mpxio_path(plun, cip, online); 8190 } else { 8191 rval = NDI_SUCCESS; 8192 } 8193 return (rval); 8194 } 8195 8196 /* 8197 * Explicit devfs_clean() due to ndi_devi_offline() not 8198 * executing devfs_clean() if parent lock is held. 8199 */ 8200 ASSERT(!servicing_interrupt()); 8201 if (online == FCP_OFFLINE) { 8202 if (plun->lun_mpxio == 0) { 8203 if (plun->lun_cip == cip) { 8204 cdip = DIP(plun->lun_cip); 8205 } else { 8206 cdip = DIP(cip); 8207 } 8208 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8209 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8210 } else if ((plun->lun_cip != cip) && cip) { 8211 /* 8212 * This means a DTYPE/GUID change, we shall get the 8213 * dip of the old cip instead of the current lun_cip. 8214 */ 8215 cdip = mdi_pi_get_client(PIP(cip)); 8216 } 8217 if (cdip) { 8218 if (i_ddi_devi_attached(cdip)) { 8219 pdip = ddi_get_parent(cdip); 8220 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8221 ndi_devi_enter(pdip, &circ); 8222 (void) ddi_deviname(cdip, devname); 8223 ndi_devi_exit(pdip, circ); 8224 /* 8225 * Release parent lock before calling 8226 * devfs_clean(). 8227 */ 8228 rval = devfs_clean(pdip, devname + 1, 8229 DV_CLEAN_FORCE); 8230 kmem_free(devname, MAXNAMELEN + 1); 8231 /* 8232 * Return if devfs_clean() fails for 8233 * non-MPXIO case. 8234 * For MPXIO case, another path could be 8235 * offlined. 8236 */ 8237 if (rval && plun->lun_mpxio == 0) { 8238 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8239 fcp_trace, FCP_BUF_LEVEL_3, 0, 8240 "fcp_trigger_lun: devfs_clean " 8241 "failed rval=%x dip=%p", 8242 rval, pdip); 8243 return (NDI_FAILURE); 8244 } 8245 } 8246 } 8247 } 8248 8249 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8250 return (NDI_FAILURE); 8251 } 8252 8253 if (is_mpxio) { 8254 mdi_devi_enter(pptr->port_dip, &circ); 8255 } else { 8256 ndi_devi_enter(pptr->port_dip, &circ); 8257 } 8258 8259 mutex_enter(&pptr->port_mutex); 8260 mutex_enter(&plun->lun_mutex); 8261 8262 if (online == FCP_ONLINE) { 8263 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8264 if (ccip == NULL) { 8265 goto fail; 8266 } 8267 } else { 8268 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8269 goto fail; 8270 } 8271 ccip = cip; 8272 } 8273 8274 if (online == FCP_ONLINE) { 8275 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8276 &circ); 8277 fc_ulp_log_device_event(pptr->port_fp_handle, 8278 FC_ULP_DEVICE_ONLINE); 8279 } else { 8280 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8281 &circ); 8282 fc_ulp_log_device_event(pptr->port_fp_handle, 8283 FC_ULP_DEVICE_OFFLINE); 8284 } 8285 8286 fail: mutex_exit(&plun->lun_mutex); 8287 mutex_exit(&pptr->port_mutex); 8288 8289 if (is_mpxio) { 8290 mdi_devi_exit(pptr->port_dip, circ); 8291 } else { 8292 ndi_devi_exit(pptr->port_dip, circ); 8293 } 8294 8295 fc_ulp_idle_port(pptr->port_fp_handle); 8296 8297 return (rval); 8298 } 8299 8300 8301 /* 8302 * take a target offline by taking all of its LUNs offline 8303 */ 8304 /*ARGSUSED*/ 8305 static int 8306 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8307 int link_cnt, int tgt_cnt, int nowait, int flags) 8308 { 8309 struct fcp_tgt_elem *elem; 8310 8311 ASSERT(mutex_owned(&pptr->port_mutex)); 8312 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8313 8314 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8315 8316 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8317 ptgt->tgt_change_cnt)) { 8318 mutex_exit(&ptgt->tgt_mutex); 8319 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8320 mutex_enter(&ptgt->tgt_mutex); 8321 8322 return (0); 8323 } 8324 8325 ptgt->tgt_pd_handle = NULL; 8326 mutex_exit(&ptgt->tgt_mutex); 8327 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8328 mutex_enter(&ptgt->tgt_mutex); 8329 8330 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8331 8332 if (ptgt->tgt_tcap && 8333 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8334 elem->flags = flags; 8335 elem->time = fcp_watchdog_time; 8336 if (nowait == 0) { 8337 elem->time += fcp_offline_delay; 8338 } 8339 elem->ptgt = ptgt; 8340 elem->link_cnt = link_cnt; 8341 elem->tgt_cnt = tgt_cnt; 8342 elem->next = pptr->port_offline_tgts; 8343 pptr->port_offline_tgts = elem; 8344 } else { 8345 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8346 } 8347 8348 return (1); 8349 } 8350 8351 8352 static void 8353 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8354 int link_cnt, int tgt_cnt, int flags) 8355 { 8356 ASSERT(mutex_owned(&pptr->port_mutex)); 8357 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8358 8359 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8360 ptgt->tgt_state = FCP_TGT_OFFLINE; 8361 ptgt->tgt_pd_handle = NULL; 8362 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8363 } 8364 8365 8366 static void 8367 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8368 int flags) 8369 { 8370 struct fcp_lun *plun; 8371 8372 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8373 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8374 8375 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8376 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8377 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8378 } 8379 } 8380 } 8381 8382 8383 /* 8384 * take a LUN offline 8385 * 8386 * enters and leaves with the target mutex held, releasing it in the process 8387 * 8388 * allocates memory in non-sleep mode 8389 */ 8390 static void 8391 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8392 int nowait, int flags) 8393 { 8394 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8395 struct fcp_lun_elem *elem; 8396 8397 ASSERT(plun != NULL); 8398 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8399 8400 if (nowait) { 8401 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8402 return; 8403 } 8404 8405 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8406 elem->flags = flags; 8407 elem->time = fcp_watchdog_time; 8408 if (nowait == 0) { 8409 elem->time += fcp_offline_delay; 8410 } 8411 elem->plun = plun; 8412 elem->link_cnt = link_cnt; 8413 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8414 elem->next = pptr->port_offline_luns; 8415 pptr->port_offline_luns = elem; 8416 } else { 8417 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8418 } 8419 } 8420 8421 8422 static void 8423 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8424 { 8425 struct fcp_pkt *head = NULL; 8426 8427 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8428 8429 mutex_exit(&LUN_TGT->tgt_mutex); 8430 8431 head = fcp_scan_commands(plun); 8432 if (head != NULL) { 8433 fcp_abort_commands(head, LUN_PORT); 8434 } 8435 8436 mutex_enter(&LUN_TGT->tgt_mutex); 8437 8438 if (plun->lun_cip && plun->lun_mpxio) { 8439 /* 8440 * Intimate MPxIO lun busy is cleared 8441 */ 8442 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8443 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8444 0, 0)) { 8445 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8446 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8447 LUN_TGT->tgt_d_id, plun->lun_num); 8448 } 8449 /* 8450 * Intimate MPxIO that the lun is now marked for offline 8451 */ 8452 mutex_exit(&LUN_TGT->tgt_mutex); 8453 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8454 mutex_enter(&LUN_TGT->tgt_mutex); 8455 } 8456 } 8457 8458 static void 8459 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8460 int flags) 8461 { 8462 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8463 8464 mutex_exit(&LUN_TGT->tgt_mutex); 8465 fcp_update_offline_flags(plun); 8466 mutex_enter(&LUN_TGT->tgt_mutex); 8467 8468 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8469 8470 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8471 fcp_trace, FCP_BUF_LEVEL_4, 0, 8472 "offline_lun: passing OFFLINE elem to HP thread"); 8473 8474 if (plun->lun_cip) { 8475 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8476 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8477 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8478 LUN_TGT->tgt_trace); 8479 8480 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8481 link_cnt, tgt_cnt, flags, 0)) { 8482 fcp_log(CE_CONT, LUN_PORT->port_dip, 8483 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8484 LUN_TGT->tgt_d_id, plun->lun_num); 8485 } 8486 } 8487 } 8488 8489 static void 8490 fcp_scan_offline_luns(struct fcp_port *pptr) 8491 { 8492 struct fcp_lun_elem *elem; 8493 struct fcp_lun_elem *prev; 8494 struct fcp_lun_elem *next; 8495 8496 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8497 8498 prev = NULL; 8499 elem = pptr->port_offline_luns; 8500 while (elem) { 8501 next = elem->next; 8502 if (elem->time <= fcp_watchdog_time) { 8503 int changed = 1; 8504 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8505 8506 mutex_enter(&ptgt->tgt_mutex); 8507 if (pptr->port_link_cnt == elem->link_cnt && 8508 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8509 changed = 0; 8510 } 8511 8512 if (!changed && 8513 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8514 fcp_offline_lun_now(elem->plun, 8515 elem->link_cnt, elem->tgt_cnt, elem->flags); 8516 } 8517 mutex_exit(&ptgt->tgt_mutex); 8518 8519 kmem_free(elem, sizeof (*elem)); 8520 8521 if (prev) { 8522 prev->next = next; 8523 } else { 8524 pptr->port_offline_luns = next; 8525 } 8526 } else { 8527 prev = elem; 8528 } 8529 elem = next; 8530 } 8531 } 8532 8533 8534 static void 8535 fcp_scan_offline_tgts(struct fcp_port *pptr) 8536 { 8537 struct fcp_tgt_elem *elem; 8538 struct fcp_tgt_elem *prev; 8539 struct fcp_tgt_elem *next; 8540 8541 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8542 8543 prev = NULL; 8544 elem = pptr->port_offline_tgts; 8545 while (elem) { 8546 next = elem->next; 8547 if (elem->time <= fcp_watchdog_time) { 8548 int outdated = 1; 8549 struct fcp_tgt *ptgt = elem->ptgt; 8550 8551 mutex_enter(&ptgt->tgt_mutex); 8552 8553 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8554 /* No change on tgt since elem was created. */ 8555 outdated = 0; 8556 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8557 pptr->port_link_cnt == elem->link_cnt + 1 && 8558 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8559 /* 8560 * Exactly one thing happened to the target 8561 * inbetween: the local port went offline. 8562 * For fp the remote port is already gone so 8563 * it will not tell us again to offline the 8564 * target. We must offline it now. 8565 */ 8566 outdated = 0; 8567 } 8568 8569 if (!outdated && !(ptgt->tgt_state & 8570 FCP_TGT_OFFLINE)) { 8571 fcp_offline_target_now(pptr, 8572 ptgt, elem->link_cnt, elem->tgt_cnt, 8573 elem->flags); 8574 } 8575 8576 mutex_exit(&ptgt->tgt_mutex); 8577 8578 kmem_free(elem, sizeof (*elem)); 8579 8580 if (prev) { 8581 prev->next = next; 8582 } else { 8583 pptr->port_offline_tgts = next; 8584 } 8585 } else { 8586 prev = elem; 8587 } 8588 elem = next; 8589 } 8590 } 8591 8592 8593 static void 8594 fcp_update_offline_flags(struct fcp_lun *plun) 8595 { 8596 struct fcp_port *pptr = LUN_PORT; 8597 ASSERT(plun != NULL); 8598 8599 mutex_enter(&LUN_TGT->tgt_mutex); 8600 plun->lun_state |= FCP_LUN_OFFLINE; 8601 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8602 8603 mutex_enter(&plun->lun_mutex); 8604 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8605 dev_info_t *cdip = NULL; 8606 8607 mutex_exit(&LUN_TGT->tgt_mutex); 8608 8609 if (plun->lun_mpxio == 0) { 8610 cdip = DIP(plun->lun_cip); 8611 } else if (plun->lun_cip) { 8612 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8613 } 8614 8615 mutex_exit(&plun->lun_mutex); 8616 if (cdip) { 8617 (void) ndi_event_retrieve_cookie( 8618 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8619 &fcp_remove_eid, NDI_EVENT_NOPASS); 8620 (void) ndi_event_run_callbacks( 8621 pptr->port_ndi_event_hdl, cdip, 8622 fcp_remove_eid, NULL); 8623 } 8624 } else { 8625 mutex_exit(&plun->lun_mutex); 8626 mutex_exit(&LUN_TGT->tgt_mutex); 8627 } 8628 } 8629 8630 8631 /* 8632 * Scan all of the command pkts for this port, moving pkts that 8633 * match our LUN onto our own list (headed by "head") 8634 */ 8635 static struct fcp_pkt * 8636 fcp_scan_commands(struct fcp_lun *plun) 8637 { 8638 struct fcp_port *pptr = LUN_PORT; 8639 8640 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8641 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8642 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8643 8644 struct fcp_pkt *head = NULL; /* head of our list */ 8645 struct fcp_pkt *tail = NULL; /* tail of our list */ 8646 8647 int cmds_found = 0; 8648 8649 mutex_enter(&pptr->port_pkt_mutex); 8650 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8651 struct fcp_lun *tlun = 8652 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8653 8654 ncmd = cmd->cmd_next; /* set next command */ 8655 8656 /* 8657 * if this pkt is for a different LUN or the 8658 * command is sent down, skip it. 8659 */ 8660 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8661 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8662 pcmd = cmd; 8663 continue; 8664 } 8665 cmds_found++; 8666 if (pcmd != NULL) { 8667 ASSERT(pptr->port_pkt_head != cmd); 8668 pcmd->cmd_next = cmd->cmd_next; 8669 } else { 8670 ASSERT(cmd == pptr->port_pkt_head); 8671 pptr->port_pkt_head = cmd->cmd_next; 8672 } 8673 8674 if (cmd == pptr->port_pkt_tail) { 8675 pptr->port_pkt_tail = pcmd; 8676 if (pcmd) { 8677 pcmd->cmd_next = NULL; 8678 } 8679 } 8680 8681 if (head == NULL) { 8682 head = tail = cmd; 8683 } else { 8684 ASSERT(tail != NULL); 8685 8686 tail->cmd_next = cmd; 8687 tail = cmd; 8688 } 8689 cmd->cmd_next = NULL; 8690 } 8691 mutex_exit(&pptr->port_pkt_mutex); 8692 8693 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8694 fcp_trace, FCP_BUF_LEVEL_8, 0, 8695 "scan commands: %d cmd(s) found", cmds_found); 8696 8697 return (head); 8698 } 8699 8700 8701 /* 8702 * Abort all the commands in the command queue 8703 */ 8704 static void 8705 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8706 { 8707 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8708 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8709 8710 ASSERT(mutex_owned(&pptr->port_mutex)); 8711 8712 /* scan through the pkts and invalid them */ 8713 for (cmd = head; cmd != NULL; cmd = ncmd) { 8714 struct scsi_pkt *pkt = cmd->cmd_pkt; 8715 8716 ncmd = cmd->cmd_next; 8717 ASSERT(pkt != NULL); 8718 8719 /* 8720 * The lun is going to be marked offline. Indicate 8721 * the target driver not to requeue or retry this command 8722 * as the device is going to be offlined pretty soon. 8723 */ 8724 pkt->pkt_reason = CMD_DEV_GONE; 8725 pkt->pkt_statistics = 0; 8726 pkt->pkt_state = 0; 8727 8728 /* reset cmd flags/state */ 8729 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8730 cmd->cmd_state = FCP_PKT_IDLE; 8731 8732 /* 8733 * ensure we have a packet completion routine, 8734 * then call it. 8735 */ 8736 ASSERT(pkt->pkt_comp != NULL); 8737 8738 mutex_exit(&pptr->port_mutex); 8739 fcp_post_callback(cmd); 8740 mutex_enter(&pptr->port_mutex); 8741 } 8742 } 8743 8744 8745 /* 8746 * the pkt_comp callback for command packets 8747 */ 8748 static void 8749 fcp_cmd_callback(fc_packet_t *fpkt) 8750 { 8751 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8752 struct scsi_pkt *pkt = cmd->cmd_pkt; 8753 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8754 8755 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8756 8757 if (cmd->cmd_state == FCP_PKT_IDLE) { 8758 cmn_err(CE_PANIC, "Packet already completed %p", 8759 (void *)cmd); 8760 } 8761 8762 /* 8763 * Watch thread should be freeing the packet, ignore the pkt. 8764 */ 8765 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8766 fcp_log(CE_CONT, pptr->port_dip, 8767 "!FCP: Pkt completed while aborting\n"); 8768 return; 8769 } 8770 cmd->cmd_state = FCP_PKT_IDLE; 8771 8772 fcp_complete_pkt(fpkt); 8773 8774 #ifdef DEBUG 8775 mutex_enter(&pptr->port_pkt_mutex); 8776 pptr->port_npkts--; 8777 mutex_exit(&pptr->port_pkt_mutex); 8778 #endif /* DEBUG */ 8779 8780 fcp_post_callback(cmd); 8781 } 8782 8783 8784 static void 8785 fcp_complete_pkt(fc_packet_t *fpkt) 8786 { 8787 int error = 0; 8788 struct fcp_pkt *cmd = (struct fcp_pkt *) 8789 fpkt->pkt_ulp_private; 8790 struct scsi_pkt *pkt = cmd->cmd_pkt; 8791 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8792 struct fcp_lun *plun; 8793 struct fcp_tgt *ptgt; 8794 struct fcp_rsp *rsp; 8795 struct scsi_address save; 8796 8797 #ifdef DEBUG 8798 save = pkt->pkt_address; 8799 #endif /* DEBUG */ 8800 8801 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8802 8803 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8804 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8805 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8806 sizeof (struct fcp_rsp)); 8807 } 8808 8809 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8810 STATE_SENT_CMD | STATE_GOT_STATUS; 8811 8812 pkt->pkt_resid = 0; 8813 8814 if (fpkt->pkt_datalen) { 8815 pkt->pkt_state |= STATE_XFERRED_DATA; 8816 if (fpkt->pkt_data_resid) { 8817 error++; 8818 } 8819 } 8820 8821 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8822 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8823 /* 8824 * The next two checks make sure that if there 8825 * is no sense data or a valid response and 8826 * the command came back with check condition, 8827 * the command should be retried. 8828 */ 8829 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8830 !rsp->fcp_u.fcp_status.sense_len_set) { 8831 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8832 pkt->pkt_resid = cmd->cmd_dmacount; 8833 } 8834 } 8835 8836 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8837 return; 8838 } 8839 8840 plun = ADDR2LUN(&pkt->pkt_address); 8841 ptgt = plun->lun_tgt; 8842 ASSERT(ptgt != NULL); 8843 8844 /* 8845 * Update the transfer resid, if appropriate 8846 */ 8847 if (rsp->fcp_u.fcp_status.resid_over || 8848 rsp->fcp_u.fcp_status.resid_under) { 8849 pkt->pkt_resid = rsp->fcp_resid; 8850 } 8851 8852 /* 8853 * First see if we got a FCP protocol error. 8854 */ 8855 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8856 struct fcp_rsp_info *bep; 8857 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8858 sizeof (struct fcp_rsp)); 8859 8860 if (fcp_validate_fcp_response(rsp, pptr) != 8861 FC_SUCCESS) { 8862 pkt->pkt_reason = CMD_CMPLT; 8863 *(pkt->pkt_scbp) = STATUS_CHECK; 8864 8865 fcp_log(CE_WARN, pptr->port_dip, 8866 "!SCSI command to d_id=0x%x lun=0x%x" 8867 " failed, Bad FCP response values:" 8868 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8869 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8870 ptgt->tgt_d_id, plun->lun_num, 8871 rsp->reserved_0, rsp->reserved_1, 8872 rsp->fcp_u.fcp_status.reserved_0, 8873 rsp->fcp_u.fcp_status.reserved_1, 8874 rsp->fcp_response_len, rsp->fcp_sense_len); 8875 8876 return; 8877 } 8878 8879 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8880 FCP_CP_IN(fpkt->pkt_resp + 8881 sizeof (struct fcp_rsp), bep, 8882 fpkt->pkt_resp_acc, 8883 sizeof (struct fcp_rsp_info)); 8884 } 8885 8886 if (bep->rsp_code != FCP_NO_FAILURE) { 8887 child_info_t *cip; 8888 8889 pkt->pkt_reason = CMD_TRAN_ERR; 8890 8891 mutex_enter(&plun->lun_mutex); 8892 cip = plun->lun_cip; 8893 mutex_exit(&plun->lun_mutex); 8894 8895 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8896 fcp_trace, FCP_BUF_LEVEL_2, 0, 8897 "FCP response error on cmd=%p" 8898 " target=0x%x, cip=%p", cmd, 8899 ptgt->tgt_d_id, cip); 8900 } 8901 } 8902 8903 /* 8904 * See if we got a SCSI error with sense data 8905 */ 8906 if (rsp->fcp_u.fcp_status.sense_len_set) { 8907 uchar_t rqlen; 8908 caddr_t sense_from; 8909 child_info_t *cip; 8910 timeout_id_t tid; 8911 struct scsi_arq_status *arq; 8912 struct scsi_extended_sense *sense_to; 8913 8914 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8915 sense_to = &arq->sts_sensedata; 8916 8917 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8918 sizeof (struct scsi_extended_sense)); 8919 8920 sense_from = (caddr_t)fpkt->pkt_resp + 8921 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8922 8923 if (fcp_validate_fcp_response(rsp, pptr) != 8924 FC_SUCCESS) { 8925 pkt->pkt_reason = CMD_CMPLT; 8926 *(pkt->pkt_scbp) = STATUS_CHECK; 8927 8928 fcp_log(CE_WARN, pptr->port_dip, 8929 "!SCSI command to d_id=0x%x lun=0x%x" 8930 " failed, Bad FCP response values:" 8931 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8932 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8933 ptgt->tgt_d_id, plun->lun_num, 8934 rsp->reserved_0, rsp->reserved_1, 8935 rsp->fcp_u.fcp_status.reserved_0, 8936 rsp->fcp_u.fcp_status.reserved_1, 8937 rsp->fcp_response_len, rsp->fcp_sense_len); 8938 8939 return; 8940 } 8941 8942 /* 8943 * copy in sense information 8944 */ 8945 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8946 FCP_CP_IN(sense_from, sense_to, 8947 fpkt->pkt_resp_acc, rqlen); 8948 } else { 8949 bcopy(sense_from, sense_to, rqlen); 8950 } 8951 8952 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8953 (FCP_SENSE_NO_LUN(sense_to))) { 8954 mutex_enter(&ptgt->tgt_mutex); 8955 if (ptgt->tgt_tid == NULL) { 8956 /* 8957 * Kick off rediscovery 8958 */ 8959 tid = timeout(fcp_reconfigure_luns, 8960 (caddr_t)ptgt, drv_usectohz(1)); 8961 8962 ptgt->tgt_tid = tid; 8963 ptgt->tgt_state |= FCP_TGT_BUSY; 8964 } 8965 mutex_exit(&ptgt->tgt_mutex); 8966 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8967 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8968 fcp_trace, FCP_BUF_LEVEL_3, 0, 8969 "!FCP: Report Lun Has Changed" 8970 " target=%x", ptgt->tgt_d_id); 8971 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8972 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8973 fcp_trace, FCP_BUF_LEVEL_3, 0, 8974 "!FCP: LU Not Supported" 8975 " target=%x", ptgt->tgt_d_id); 8976 } 8977 } 8978 ASSERT(pkt->pkt_scbp != NULL); 8979 8980 pkt->pkt_state |= STATE_ARQ_DONE; 8981 8982 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8983 8984 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8985 arq->sts_rqpkt_reason = 0; 8986 arq->sts_rqpkt_statistics = 0; 8987 8988 arq->sts_rqpkt_state = STATE_GOT_BUS | 8989 STATE_GOT_TARGET | STATE_SENT_CMD | 8990 STATE_GOT_STATUS | STATE_ARQ_DONE | 8991 STATE_XFERRED_DATA; 8992 8993 mutex_enter(&plun->lun_mutex); 8994 cip = plun->lun_cip; 8995 mutex_exit(&plun->lun_mutex); 8996 8997 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8998 fcp_trace, FCP_BUF_LEVEL_8, 0, 8999 "SCSI Check condition on cmd=%p target=0x%x" 9000 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 9001 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 9002 cmd->cmd_fcp_cmd.fcp_cdb[0], 9003 rsp->fcp_u.fcp_status.scsi_status, 9004 sense_to->es_key, sense_to->es_add_code, 9005 sense_to->es_qual_code); 9006 } 9007 } else { 9008 plun = ADDR2LUN(&pkt->pkt_address); 9009 ptgt = plun->lun_tgt; 9010 ASSERT(ptgt != NULL); 9011 9012 /* 9013 * Work harder to translate errors into target driver 9014 * understandable ones. Note with despair that the target 9015 * drivers don't decode pkt_state and pkt_reason exhaustively 9016 * They resort to using the big hammer most often, which 9017 * may not get fixed in the life time of this driver. 9018 */ 9019 pkt->pkt_state = 0; 9020 pkt->pkt_statistics = 0; 9021 9022 switch (fpkt->pkt_state) { 9023 case FC_PKT_TRAN_ERROR: 9024 switch (fpkt->pkt_reason) { 9025 case FC_REASON_OVERRUN: 9026 pkt->pkt_reason = CMD_CMD_OVR; 9027 pkt->pkt_statistics |= STAT_ABORTED; 9028 break; 9029 9030 case FC_REASON_XCHG_BSY: { 9031 caddr_t ptr; 9032 9033 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9034 9035 ptr = (caddr_t)pkt->pkt_scbp; 9036 if (ptr) { 9037 *ptr = STATUS_BUSY; 9038 } 9039 break; 9040 } 9041 9042 case FC_REASON_ABORTED: 9043 pkt->pkt_reason = CMD_TRAN_ERR; 9044 pkt->pkt_statistics |= STAT_ABORTED; 9045 break; 9046 9047 case FC_REASON_ABORT_FAILED: 9048 pkt->pkt_reason = CMD_ABORT_FAIL; 9049 break; 9050 9051 case FC_REASON_NO_SEQ_INIT: 9052 case FC_REASON_CRC_ERROR: 9053 pkt->pkt_reason = CMD_TRAN_ERR; 9054 pkt->pkt_statistics |= STAT_ABORTED; 9055 break; 9056 default: 9057 pkt->pkt_reason = CMD_TRAN_ERR; 9058 break; 9059 } 9060 break; 9061 9062 case FC_PKT_PORT_OFFLINE: { 9063 dev_info_t *cdip = NULL; 9064 caddr_t ptr; 9065 9066 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9067 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9068 fcp_trace, FCP_BUF_LEVEL_8, 0, 9069 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9070 ptgt->tgt_d_id); 9071 } 9072 9073 mutex_enter(&plun->lun_mutex); 9074 if (plun->lun_mpxio == 0) { 9075 cdip = DIP(plun->lun_cip); 9076 } else if (plun->lun_cip) { 9077 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9078 } 9079 9080 mutex_exit(&plun->lun_mutex); 9081 9082 if (cdip) { 9083 (void) ndi_event_retrieve_cookie( 9084 pptr->port_ndi_event_hdl, cdip, 9085 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9086 NDI_EVENT_NOPASS); 9087 (void) ndi_event_run_callbacks( 9088 pptr->port_ndi_event_hdl, cdip, 9089 fcp_remove_eid, NULL); 9090 } 9091 9092 /* 9093 * If the link goes off-line for a lip, 9094 * this will cause a error to the ST SG 9095 * SGEN drivers. By setting BUSY we will 9096 * give the drivers the chance to retry 9097 * before it blows of the job. ST will 9098 * remember how many times it has retried. 9099 */ 9100 9101 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9102 (plun->lun_type == DTYPE_CHANGER)) { 9103 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9104 ptr = (caddr_t)pkt->pkt_scbp; 9105 if (ptr) { 9106 *ptr = STATUS_BUSY; 9107 } 9108 } else { 9109 pkt->pkt_reason = CMD_TRAN_ERR; 9110 pkt->pkt_statistics |= STAT_BUS_RESET; 9111 } 9112 break; 9113 } 9114 9115 case FC_PKT_TRAN_BSY: 9116 /* 9117 * Use the ssd Qfull handling here. 9118 */ 9119 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9120 pkt->pkt_state = STATE_GOT_BUS; 9121 break; 9122 9123 case FC_PKT_TIMEOUT: 9124 pkt->pkt_reason = CMD_TIMEOUT; 9125 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9126 pkt->pkt_statistics |= STAT_TIMEOUT; 9127 } else { 9128 pkt->pkt_statistics |= STAT_ABORTED; 9129 } 9130 break; 9131 9132 case FC_PKT_LOCAL_RJT: 9133 switch (fpkt->pkt_reason) { 9134 case FC_REASON_OFFLINE: { 9135 dev_info_t *cdip = NULL; 9136 9137 mutex_enter(&plun->lun_mutex); 9138 if (plun->lun_mpxio == 0) { 9139 cdip = DIP(plun->lun_cip); 9140 } else if (plun->lun_cip) { 9141 cdip = mdi_pi_get_client( 9142 PIP(plun->lun_cip)); 9143 } 9144 mutex_exit(&plun->lun_mutex); 9145 9146 if (cdip) { 9147 (void) ndi_event_retrieve_cookie( 9148 pptr->port_ndi_event_hdl, cdip, 9149 FCAL_REMOVE_EVENT, 9150 &fcp_remove_eid, 9151 NDI_EVENT_NOPASS); 9152 (void) ndi_event_run_callbacks( 9153 pptr->port_ndi_event_hdl, 9154 cdip, fcp_remove_eid, NULL); 9155 } 9156 9157 pkt->pkt_reason = CMD_TRAN_ERR; 9158 pkt->pkt_statistics |= STAT_BUS_RESET; 9159 9160 break; 9161 } 9162 9163 case FC_REASON_NOMEM: 9164 case FC_REASON_QFULL: { 9165 caddr_t ptr; 9166 9167 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9168 ptr = (caddr_t)pkt->pkt_scbp; 9169 if (ptr) { 9170 *ptr = STATUS_BUSY; 9171 } 9172 break; 9173 } 9174 9175 case FC_REASON_DMA_ERROR: 9176 pkt->pkt_reason = CMD_DMA_DERR; 9177 pkt->pkt_statistics |= STAT_ABORTED; 9178 break; 9179 9180 case FC_REASON_CRC_ERROR: 9181 case FC_REASON_UNDERRUN: { 9182 uchar_t status; 9183 /* 9184 * Work around for Bugid: 4240945. 9185 * IB on A5k doesn't set the Underrun bit 9186 * in the fcp status, when it is transferring 9187 * less than requested amount of data. Work 9188 * around the ses problem to keep luxadm 9189 * happy till ibfirmware is fixed. 9190 */ 9191 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9192 FCP_CP_IN(fpkt->pkt_resp, rsp, 9193 fpkt->pkt_resp_acc, 9194 sizeof (struct fcp_rsp)); 9195 } 9196 status = rsp->fcp_u.fcp_status.scsi_status; 9197 if (((plun->lun_type & DTYPE_MASK) == 9198 DTYPE_ESI) && (status == STATUS_GOOD)) { 9199 pkt->pkt_reason = CMD_CMPLT; 9200 *pkt->pkt_scbp = status; 9201 pkt->pkt_resid = 0; 9202 } else { 9203 pkt->pkt_reason = CMD_TRAN_ERR; 9204 pkt->pkt_statistics |= STAT_ABORTED; 9205 } 9206 break; 9207 } 9208 9209 case FC_REASON_NO_CONNECTION: 9210 case FC_REASON_UNSUPPORTED: 9211 case FC_REASON_ILLEGAL_REQ: 9212 case FC_REASON_BAD_SID: 9213 case FC_REASON_DIAG_BUSY: 9214 case FC_REASON_FCAL_OPN_FAIL: 9215 case FC_REASON_BAD_XID: 9216 default: 9217 pkt->pkt_reason = CMD_TRAN_ERR; 9218 pkt->pkt_statistics |= STAT_ABORTED; 9219 break; 9220 9221 } 9222 break; 9223 9224 case FC_PKT_NPORT_RJT: 9225 case FC_PKT_FABRIC_RJT: 9226 case FC_PKT_NPORT_BSY: 9227 case FC_PKT_FABRIC_BSY: 9228 default: 9229 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9230 fcp_trace, FCP_BUF_LEVEL_8, 0, 9231 "FC Status 0x%x, reason 0x%x", 9232 fpkt->pkt_state, fpkt->pkt_reason); 9233 pkt->pkt_reason = CMD_TRAN_ERR; 9234 pkt->pkt_statistics |= STAT_ABORTED; 9235 break; 9236 } 9237 9238 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9239 fcp_trace, FCP_BUF_LEVEL_9, 0, 9240 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9241 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9242 fpkt->pkt_reason); 9243 } 9244 9245 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9246 } 9247 9248 9249 static int 9250 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9251 { 9252 if (rsp->reserved_0 || rsp->reserved_1 || 9253 rsp->fcp_u.fcp_status.reserved_0 || 9254 rsp->fcp_u.fcp_status.reserved_1) { 9255 /* 9256 * These reserved fields should ideally be zero. FCP-2 does say 9257 * that the recipient need not check for reserved fields to be 9258 * zero. If they are not zero, we will not make a fuss about it 9259 * - just log it (in debug to both trace buffer and messages 9260 * file and to trace buffer only in non-debug) and move on. 9261 * 9262 * Non-zero reserved fields were seen with minnows. 9263 * 9264 * qlc takes care of some of this but we cannot assume that all 9265 * FCAs will do so. 9266 */ 9267 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9268 FCP_BUF_LEVEL_5, 0, 9269 "Got fcp response packet with non-zero reserved fields " 9270 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9271 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9272 rsp->reserved_0, rsp->reserved_1, 9273 rsp->fcp_u.fcp_status.reserved_0, 9274 rsp->fcp_u.fcp_status.reserved_1); 9275 } 9276 9277 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9278 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9279 return (FC_FAILURE); 9280 } 9281 9282 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9283 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9284 sizeof (struct fcp_rsp))) { 9285 return (FC_FAILURE); 9286 } 9287 9288 return (FC_SUCCESS); 9289 } 9290 9291 9292 /* 9293 * This is called when there is a change the in device state. The case we're 9294 * handling here is, if the d_id s does not match, offline this tgt and online 9295 * a new tgt with the new d_id. called from fcp_handle_devices with 9296 * port_mutex held. 9297 */ 9298 static int 9299 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9300 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9301 { 9302 ASSERT(mutex_owned(&pptr->port_mutex)); 9303 9304 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9305 fcp_trace, FCP_BUF_LEVEL_3, 0, 9306 "Starting fcp_device_changed..."); 9307 9308 /* 9309 * The two cases where the port_device_changed is called is 9310 * either it changes it's d_id or it's hard address. 9311 */ 9312 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9313 (FC_TOP_EXTERNAL(pptr->port_topology) && 9314 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9315 9316 /* offline this target */ 9317 mutex_enter(&ptgt->tgt_mutex); 9318 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9319 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9320 0, 1, NDI_DEVI_REMOVE); 9321 } 9322 mutex_exit(&ptgt->tgt_mutex); 9323 9324 fcp_log(CE_NOTE, pptr->port_dip, 9325 "Change in target properties: Old D_ID=%x New D_ID=%x" 9326 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9327 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9328 map_entry->map_hard_addr.hard_addr); 9329 } 9330 9331 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9332 link_cnt, tgt_cnt, cause)); 9333 } 9334 9335 /* 9336 * Function: fcp_alloc_lun 9337 * 9338 * Description: Creates a new lun structure and adds it to the list 9339 * of luns of the target. 9340 * 9341 * Argument: ptgt Target the lun will belong to. 9342 * 9343 * Return Value: NULL Failed 9344 * Not NULL Succeeded 9345 * 9346 * Context: Kernel context 9347 */ 9348 static struct fcp_lun * 9349 fcp_alloc_lun(struct fcp_tgt *ptgt) 9350 { 9351 struct fcp_lun *plun; 9352 9353 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9354 if (plun != NULL) { 9355 /* 9356 * Initialize the mutex before putting in the target list 9357 * especially before releasing the target mutex. 9358 */ 9359 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9360 plun->lun_tgt = ptgt; 9361 9362 mutex_enter(&ptgt->tgt_mutex); 9363 plun->lun_next = ptgt->tgt_lun; 9364 ptgt->tgt_lun = plun; 9365 plun->lun_old_guid = NULL; 9366 plun->lun_old_guid_size = 0; 9367 mutex_exit(&ptgt->tgt_mutex); 9368 } 9369 9370 return (plun); 9371 } 9372 9373 /* 9374 * Function: fcp_dealloc_lun 9375 * 9376 * Description: Frees the LUN structure passed by the caller. 9377 * 9378 * Argument: plun LUN structure to free. 9379 * 9380 * Return Value: None 9381 * 9382 * Context: Kernel context. 9383 */ 9384 static void 9385 fcp_dealloc_lun(struct fcp_lun *plun) 9386 { 9387 mutex_enter(&plun->lun_mutex); 9388 if (plun->lun_cip) { 9389 fcp_remove_child(plun); 9390 } 9391 mutex_exit(&plun->lun_mutex); 9392 9393 mutex_destroy(&plun->lun_mutex); 9394 if (plun->lun_guid) { 9395 kmem_free(plun->lun_guid, plun->lun_guid_size); 9396 } 9397 if (plun->lun_old_guid) { 9398 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9399 } 9400 kmem_free(plun, sizeof (*plun)); 9401 } 9402 9403 /* 9404 * Function: fcp_alloc_tgt 9405 * 9406 * Description: Creates a new target structure and adds it to the port 9407 * hash list. 9408 * 9409 * Argument: pptr fcp port structure 9410 * *map_entry entry describing the target to create 9411 * link_cnt Link state change counter 9412 * 9413 * Return Value: NULL Failed 9414 * Not NULL Succeeded 9415 * 9416 * Context: Kernel context. 9417 */ 9418 static struct fcp_tgt * 9419 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9420 { 9421 int hash; 9422 uchar_t *wwn; 9423 struct fcp_tgt *ptgt; 9424 9425 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9426 if (ptgt != NULL) { 9427 mutex_enter(&pptr->port_mutex); 9428 if (link_cnt != pptr->port_link_cnt) { 9429 /* 9430 * oh oh -- another link reset 9431 * in progress -- give up 9432 */ 9433 mutex_exit(&pptr->port_mutex); 9434 kmem_free(ptgt, sizeof (*ptgt)); 9435 ptgt = NULL; 9436 } else { 9437 /* 9438 * initialize the mutex before putting in the port 9439 * wwn list, especially before releasing the port 9440 * mutex. 9441 */ 9442 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9443 9444 /* add new target entry to the port's hash list */ 9445 wwn = (uchar_t *)&map_entry->map_pwwn; 9446 hash = FCP_HASH(wwn); 9447 9448 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9449 pptr->port_tgt_hash_table[hash] = ptgt; 9450 9451 /* save cross-ptr */ 9452 ptgt->tgt_port = pptr; 9453 9454 ptgt->tgt_change_cnt = 1; 9455 9456 /* initialize the target manual_config_only flag */ 9457 if (fcp_enable_auto_configuration) { 9458 ptgt->tgt_manual_config_only = 0; 9459 } else { 9460 ptgt->tgt_manual_config_only = 1; 9461 } 9462 9463 mutex_exit(&pptr->port_mutex); 9464 } 9465 } 9466 9467 return (ptgt); 9468 } 9469 9470 /* 9471 * Function: fcp_dealloc_tgt 9472 * 9473 * Description: Frees the target structure passed by the caller. 9474 * 9475 * Argument: ptgt Target structure to free. 9476 * 9477 * Return Value: None 9478 * 9479 * Context: Kernel context. 9480 */ 9481 static void 9482 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9483 { 9484 mutex_destroy(&ptgt->tgt_mutex); 9485 kmem_free(ptgt, sizeof (*ptgt)); 9486 } 9487 9488 9489 /* 9490 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9491 * 9492 * Device discovery commands will not be retried for-ever as 9493 * this will have repercussions on other devices that need to 9494 * be submitted to the hotplug thread. After a quick glance 9495 * at the SCSI-3 spec, it was found that the spec doesn't 9496 * mandate a forever retry, rather recommends a delayed retry. 9497 * 9498 * Since Photon IB is single threaded, STATUS_BUSY is common 9499 * in a 4+initiator environment. Make sure the total time 9500 * spent on retries (including command timeout) does not 9501 * 60 seconds 9502 */ 9503 static void 9504 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9505 { 9506 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9507 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9508 9509 mutex_enter(&pptr->port_mutex); 9510 mutex_enter(&ptgt->tgt_mutex); 9511 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9512 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9513 fcp_trace, FCP_BUF_LEVEL_2, 0, 9514 "fcp_queue_ipkt,1:state change occured" 9515 " for D_ID=0x%x", ptgt->tgt_d_id); 9516 mutex_exit(&ptgt->tgt_mutex); 9517 mutex_exit(&pptr->port_mutex); 9518 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9519 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9520 fcp_icmd_free(pptr, icmd); 9521 return; 9522 } 9523 mutex_exit(&ptgt->tgt_mutex); 9524 9525 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9526 9527 if (pptr->port_ipkt_list != NULL) { 9528 /* add pkt to front of doubly-linked list */ 9529 pptr->port_ipkt_list->ipkt_prev = icmd; 9530 icmd->ipkt_next = pptr->port_ipkt_list; 9531 pptr->port_ipkt_list = icmd; 9532 icmd->ipkt_prev = NULL; 9533 } else { 9534 /* this is the first/only pkt on the list */ 9535 pptr->port_ipkt_list = icmd; 9536 icmd->ipkt_next = NULL; 9537 icmd->ipkt_prev = NULL; 9538 } 9539 mutex_exit(&pptr->port_mutex); 9540 } 9541 9542 /* 9543 * Function: fcp_transport 9544 * 9545 * Description: This function submits the Fibre Channel packet to the transort 9546 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9547 * fails the submission, the treatment depends on the value of 9548 * the variable internal. 9549 * 9550 * Argument: port_handle fp/fctl port handle. 9551 * *fpkt Packet to submit to the transport layer. 9552 * internal Not zero when it's an internal packet. 9553 * 9554 * Return Value: FC_TRAN_BUSY 9555 * FC_STATEC_BUSY 9556 * FC_OFFLINE 9557 * FC_LOGINREQ 9558 * FC_DEVICE_BUSY 9559 * FC_SUCCESS 9560 */ 9561 static int 9562 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9563 { 9564 int rval; 9565 9566 rval = fc_ulp_transport(port_handle, fpkt); 9567 if (rval == FC_SUCCESS) { 9568 return (rval); 9569 } 9570 9571 /* 9572 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9573 * a command, if the underlying modules see that there is a state 9574 * change, or if a port is OFFLINE, that means, that state change 9575 * hasn't reached FCP yet, so re-queue the command for deferred 9576 * submission. 9577 */ 9578 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9579 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9580 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9581 /* 9582 * Defer packet re-submission. Life hang is possible on 9583 * internal commands if the port driver sends FC_STATEC_BUSY 9584 * for ever, but that shouldn't happen in a good environment. 9585 * Limiting re-transport for internal commands is probably a 9586 * good idea.. 9587 * A race condition can happen when a port sees barrage of 9588 * link transitions offline to online. If the FCTL has 9589 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9590 * internal commands should be queued to do the discovery. 9591 * The race condition is when an online comes and FCP starts 9592 * its internal discovery and the link goes offline. It is 9593 * possible that the statec_callback has not reached FCP 9594 * and FCP is carrying on with its internal discovery. 9595 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9596 * that the link has gone offline. At this point FCP should 9597 * drop all the internal commands and wait for the 9598 * statec_callback. It will be facilitated by incrementing 9599 * port_link_cnt. 9600 * 9601 * For external commands, the (FC)pkt_timeout is decremented 9602 * by the QUEUE Delay added by our driver, Care is taken to 9603 * ensure that it doesn't become zero (zero means no timeout) 9604 * If the time expires right inside driver queue itself, 9605 * the watch thread will return it to the original caller 9606 * indicating that the command has timed-out. 9607 */ 9608 if (internal) { 9609 char *op; 9610 struct fcp_ipkt *icmd; 9611 9612 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9613 switch (icmd->ipkt_opcode) { 9614 case SCMD_REPORT_LUN: 9615 op = "REPORT LUN"; 9616 break; 9617 9618 case SCMD_INQUIRY: 9619 op = "INQUIRY"; 9620 break; 9621 9622 case SCMD_INQUIRY_PAGE83: 9623 op = "INQUIRY-83"; 9624 break; 9625 9626 default: 9627 op = "Internal SCSI COMMAND"; 9628 break; 9629 } 9630 9631 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9632 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9633 rval = FC_SUCCESS; 9634 } 9635 } else { 9636 struct fcp_pkt *cmd; 9637 struct fcp_port *pptr; 9638 9639 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9640 cmd->cmd_state = FCP_PKT_IDLE; 9641 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9642 9643 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9644 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9645 fcp_trace, FCP_BUF_LEVEL_9, 0, 9646 "fcp_transport: xport busy for pkt %p", 9647 cmd->cmd_pkt); 9648 rval = FC_TRAN_BUSY; 9649 } else { 9650 fcp_queue_pkt(pptr, cmd); 9651 rval = FC_SUCCESS; 9652 } 9653 } 9654 } 9655 9656 return (rval); 9657 } 9658 9659 /*VARARGS3*/ 9660 static void 9661 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9662 { 9663 char buf[256]; 9664 va_list ap; 9665 9666 if (dip == NULL) { 9667 dip = fcp_global_dip; 9668 } 9669 9670 va_start(ap, fmt); 9671 (void) vsprintf(buf, fmt, ap); 9672 va_end(ap); 9673 9674 scsi_log(dip, "fcp", level, buf); 9675 } 9676 9677 /* 9678 * This function retries NS registry of FC4 type. 9679 * It assumes that fcp_mutex is held. 9680 * The function does nothing if topology is not fabric 9681 * So, the topology has to be set before this function can be called 9682 */ 9683 static void 9684 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9685 { 9686 int rval; 9687 9688 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9689 9690 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9691 ((pptr->port_topology != FC_TOP_FABRIC) && 9692 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9693 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9694 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9695 } 9696 return; 9697 } 9698 mutex_exit(&pptr->port_mutex); 9699 rval = fcp_do_ns_registry(pptr, s_id); 9700 mutex_enter(&pptr->port_mutex); 9701 9702 if (rval == 0) { 9703 /* Registry successful. Reset flag */ 9704 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9705 } 9706 } 9707 9708 /* 9709 * This function registers the ULP with the switch by calling transport i/f 9710 */ 9711 static int 9712 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9713 { 9714 fc_ns_cmd_t ns_cmd; 9715 ns_rfc_type_t rfc; 9716 uint32_t types[8]; 9717 9718 /* 9719 * Prepare the Name server structure to 9720 * register with the transport in case of 9721 * Fabric configuration. 9722 */ 9723 bzero(&rfc, sizeof (rfc)); 9724 bzero(types, sizeof (types)); 9725 9726 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9727 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9728 9729 rfc.rfc_port_id.port_id = s_id; 9730 bcopy(types, rfc.rfc_types, sizeof (types)); 9731 9732 ns_cmd.ns_flags = 0; 9733 ns_cmd.ns_cmd = NS_RFT_ID; 9734 ns_cmd.ns_req_len = sizeof (rfc); 9735 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9736 ns_cmd.ns_resp_len = 0; 9737 ns_cmd.ns_resp_payload = NULL; 9738 9739 /* 9740 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9741 */ 9742 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9743 fcp_log(CE_WARN, pptr->port_dip, 9744 "!ns_registry: failed name server registration"); 9745 return (1); 9746 } 9747 9748 return (0); 9749 } 9750 9751 /* 9752 * Function: fcp_handle_port_attach 9753 * 9754 * Description: This function is called from fcp_port_attach() to attach a 9755 * new port. This routine does the following: 9756 * 9757 * 1) Allocates an fcp_port structure and initializes it. 9758 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9759 * server. 9760 * 3) Kicks off the enumeration of the targets/luns visible 9761 * through this new port. That is done by calling 9762 * fcp_statec_callback() if the port is online. 9763 * 9764 * Argument: ulph fp/fctl port handle. 9765 * *pinfo Port information. 9766 * s_id Port ID. 9767 * instance Device instance number for the local port 9768 * (returned by ddi_get_instance()). 9769 * 9770 * Return Value: DDI_SUCCESS 9771 * DDI_FAILURE 9772 * 9773 * Context: User and Kernel context. 9774 */ 9775 /*ARGSUSED*/ 9776 int 9777 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9778 uint32_t s_id, int instance) 9779 { 9780 int res = DDI_FAILURE; 9781 scsi_hba_tran_t *tran; 9782 int mutex_initted = FALSE; 9783 int hba_attached = FALSE; 9784 int soft_state_linked = FALSE; 9785 int event_bind = FALSE; 9786 struct fcp_port *pptr; 9787 fc_portmap_t *tmp_list = NULL; 9788 uint32_t max_cnt, alloc_cnt; 9789 uchar_t *boot_wwn = NULL; 9790 uint_t nbytes; 9791 int manual_cfg; 9792 9793 /* 9794 * this port instance attaching for the first time (or after 9795 * being detached before) 9796 */ 9797 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9798 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9799 9800 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9801 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9802 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9803 instance); 9804 return (res); 9805 } 9806 9807 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9808 /* this shouldn't happen */ 9809 ddi_soft_state_free(fcp_softstate, instance); 9810 cmn_err(CE_WARN, "fcp: bad soft state"); 9811 return (res); 9812 } 9813 9814 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9815 9816 /* 9817 * Make a copy of ulp_port_info as fctl allocates 9818 * a temp struct. 9819 */ 9820 (void) fcp_cp_pinfo(pptr, pinfo); 9821 9822 /* 9823 * Check for manual_configuration_only property. 9824 * Enable manual configurtion if the property is 9825 * set to 1, otherwise disable manual configuration. 9826 */ 9827 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9828 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9829 MANUAL_CFG_ONLY, 9830 -1)) != -1) { 9831 if (manual_cfg == 1) { 9832 char *pathname; 9833 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9834 (void) ddi_pathname(pptr->port_dip, pathname); 9835 cmn_err(CE_NOTE, 9836 "%s (%s%d) %s is enabled via %s.conf.", 9837 pathname, 9838 ddi_driver_name(pptr->port_dip), 9839 ddi_get_instance(pptr->port_dip), 9840 MANUAL_CFG_ONLY, 9841 ddi_driver_name(pptr->port_dip)); 9842 fcp_enable_auto_configuration = 0; 9843 kmem_free(pathname, MAXPATHLEN); 9844 } 9845 } 9846 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9847 pptr->port_link_cnt = 1; 9848 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9849 pptr->port_id = s_id; 9850 pptr->port_instance = instance; 9851 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9852 pptr->port_state = FCP_STATE_INIT; 9853 if (pinfo->port_acc_attr == NULL) { 9854 /* 9855 * The corresponding FCA doesn't support DMA at all 9856 */ 9857 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9858 } 9859 9860 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9861 9862 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9863 /* 9864 * If FCA supports DMA in SCSI data phase, we need preallocate 9865 * dma cookie, so stash the cookie size 9866 */ 9867 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9868 pptr->port_data_dma_attr.dma_attr_sgllen; 9869 } 9870 9871 /* 9872 * The two mutexes of fcp_port are initialized. The variable 9873 * mutex_initted is incremented to remember that fact. That variable 9874 * is checked when the routine fails and the mutexes have to be 9875 * destroyed. 9876 */ 9877 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9878 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9879 mutex_initted++; 9880 9881 /* 9882 * The SCSI tran structure is allocate and initialized now. 9883 */ 9884 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9885 fcp_log(CE_WARN, pptr->port_dip, 9886 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9887 goto fail; 9888 } 9889 9890 /* link in the transport structure then fill it in */ 9891 pptr->port_tran = tran; 9892 tran->tran_hba_private = pptr; 9893 tran->tran_tgt_init = fcp_scsi_tgt_init; 9894 tran->tran_tgt_probe = NULL; 9895 tran->tran_tgt_free = fcp_scsi_tgt_free; 9896 tran->tran_start = fcp_scsi_start; 9897 tran->tran_reset = fcp_scsi_reset; 9898 tran->tran_abort = fcp_scsi_abort; 9899 tran->tran_getcap = fcp_scsi_getcap; 9900 tran->tran_setcap = fcp_scsi_setcap; 9901 tran->tran_init_pkt = NULL; 9902 tran->tran_destroy_pkt = NULL; 9903 tran->tran_dmafree = NULL; 9904 tran->tran_sync_pkt = NULL; 9905 tran->tran_reset_notify = fcp_scsi_reset_notify; 9906 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9907 tran->tran_get_name = fcp_scsi_get_name; 9908 tran->tran_clear_aca = NULL; 9909 tran->tran_clear_task_set = NULL; 9910 tran->tran_terminate_task = NULL; 9911 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9912 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9913 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9914 tran->tran_post_event = fcp_scsi_bus_post_event; 9915 tran->tran_quiesce = NULL; 9916 tran->tran_unquiesce = NULL; 9917 tran->tran_bus_reset = NULL; 9918 tran->tran_bus_config = fcp_scsi_bus_config; 9919 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9920 tran->tran_bus_power = NULL; 9921 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9922 9923 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9924 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9925 tran->tran_setup_pkt = fcp_pkt_setup; 9926 tran->tran_teardown_pkt = fcp_pkt_teardown; 9927 tran->tran_hba_len = pptr->port_priv_pkt_len + 9928 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9929 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9930 /* 9931 * If FCA don't support DMA, then we use different vectors to 9932 * minimize the effects on DMA code flow path 9933 */ 9934 tran->tran_start = fcp_pseudo_start; 9935 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9936 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9937 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9938 tran->tran_dmafree = fcp_pseudo_dmafree; 9939 tran->tran_setup_pkt = NULL; 9940 tran->tran_teardown_pkt = NULL; 9941 tran->tran_pkt_constructor = NULL; 9942 tran->tran_pkt_destructor = NULL; 9943 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9944 } 9945 9946 /* 9947 * Allocate an ndi event handle 9948 */ 9949 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9950 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9951 9952 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9953 sizeof (fcp_ndi_event_defs)); 9954 9955 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9956 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9957 9958 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9959 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9960 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9961 9962 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9963 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9964 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9965 goto fail; 9966 } 9967 event_bind++; /* Checked in fail case */ 9968 9969 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9970 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9971 != DDI_SUCCESS) { 9972 fcp_log(CE_WARN, pptr->port_dip, 9973 "!fcp%d: scsi_hba_attach_setup failed", instance); 9974 goto fail; 9975 } 9976 hba_attached++; /* Checked in fail case */ 9977 9978 pptr->port_mpxio = 0; 9979 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9980 MDI_SUCCESS) { 9981 pptr->port_mpxio++; 9982 } 9983 9984 /* 9985 * The following code is putting the new port structure in the global 9986 * list of ports and, if it is the first port to attach, it start the 9987 * fcp_watchdog_tick. 9988 * 9989 * Why put this new port in the global before we are done attaching it? 9990 * We are actually making the structure globally known before we are 9991 * done attaching it. The reason for that is: because of the code that 9992 * follows. At this point the resources to handle the port are 9993 * allocated. This function is now going to do the following: 9994 * 9995 * 1) It is going to try to register with the name server advertizing 9996 * the new FCP capability of the port. 9997 * 2) It is going to play the role of the fp/fctl layer by building 9998 * a list of worlwide names reachable through this port and call 9999 * itself on fcp_statec_callback(). That requires the port to 10000 * be part of the global list. 10001 */ 10002 mutex_enter(&fcp_global_mutex); 10003 if (fcp_port_head == NULL) { 10004 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 10005 } 10006 pptr->port_next = fcp_port_head; 10007 fcp_port_head = pptr; 10008 soft_state_linked++; 10009 10010 if (fcp_watchdog_init++ == 0) { 10011 fcp_watchdog_tick = fcp_watchdog_timeout * 10012 drv_usectohz(1000000); 10013 fcp_watchdog_id = timeout(fcp_watch, NULL, 10014 fcp_watchdog_tick); 10015 } 10016 mutex_exit(&fcp_global_mutex); 10017 10018 /* 10019 * Here an attempt is made to register with the name server, the new 10020 * FCP capability. That is done using an RTF_ID to the name server. 10021 * It is done synchronously. The function fcp_do_ns_registry() 10022 * doesn't return till the name server responded. 10023 * On failures, just ignore it for now and it will get retried during 10024 * state change callbacks. We'll set a flag to show this failure 10025 */ 10026 if (fcp_do_ns_registry(pptr, s_id)) { 10027 mutex_enter(&pptr->port_mutex); 10028 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 10029 mutex_exit(&pptr->port_mutex); 10030 } else { 10031 mutex_enter(&pptr->port_mutex); 10032 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 10033 mutex_exit(&pptr->port_mutex); 10034 } 10035 10036 /* 10037 * Lookup for boot WWN property 10038 */ 10039 if (modrootloaded != 1) { 10040 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 10041 ddi_get_parent(pinfo->port_dip), 10042 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 10043 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 10044 (nbytes == FC_WWN_SIZE)) { 10045 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 10046 } 10047 if (boot_wwn) { 10048 ddi_prop_free(boot_wwn); 10049 } 10050 } 10051 10052 /* 10053 * Handle various topologies and link states. 10054 */ 10055 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10056 case FC_STATE_OFFLINE: 10057 10058 /* 10059 * we're attaching a port where the link is offline 10060 * 10061 * Wait for ONLINE, at which time a state 10062 * change will cause a statec_callback 10063 * 10064 * in the mean time, do not do anything 10065 */ 10066 res = DDI_SUCCESS; 10067 pptr->port_state |= FCP_STATE_OFFLINE; 10068 break; 10069 10070 case FC_STATE_ONLINE: { 10071 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10072 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10073 res = DDI_SUCCESS; 10074 break; 10075 } 10076 /* 10077 * discover devices and create nodes (a private 10078 * loop or point-to-point) 10079 */ 10080 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10081 10082 /* 10083 * At this point we are going to build a list of all the ports 10084 * that can be reached through this local port. It looks like 10085 * we cannot handle more than FCP_MAX_DEVICES per local port 10086 * (128). 10087 */ 10088 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10089 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10090 KM_NOSLEEP)) == NULL) { 10091 fcp_log(CE_WARN, pptr->port_dip, 10092 "!fcp%d: failed to allocate portmap", 10093 instance); 10094 goto fail; 10095 } 10096 10097 /* 10098 * fc_ulp_getportmap() is going to provide us with the list of 10099 * remote ports in the buffer we just allocated. The way the 10100 * list is going to be retrieved depends on the topology. 10101 * However, if we are connected to a Fabric, a name server 10102 * request may be sent to get the list of FCP capable ports. 10103 * It should be noted that is the case the request is 10104 * synchronous. This means we are stuck here till the name 10105 * server replies. A lot of things can change during that time 10106 * and including, may be, being called on 10107 * fcp_statec_callback() for different reasons. I'm not sure 10108 * the code can handle that. 10109 */ 10110 max_cnt = FCP_MAX_DEVICES; 10111 alloc_cnt = FCP_MAX_DEVICES; 10112 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10113 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10114 FC_SUCCESS) { 10115 caddr_t msg; 10116 10117 (void) fc_ulp_error(res, &msg); 10118 10119 /* 10120 * this just means the transport is 10121 * busy perhaps building a portmap so, 10122 * for now, succeed this port attach 10123 * when the transport has a new map, 10124 * it'll send us a state change then 10125 */ 10126 fcp_log(CE_WARN, pptr->port_dip, 10127 "!failed to get port map : %s", msg); 10128 10129 res = DDI_SUCCESS; 10130 break; /* go return result */ 10131 } 10132 if (max_cnt > alloc_cnt) { 10133 alloc_cnt = max_cnt; 10134 } 10135 10136 /* 10137 * We are now going to call fcp_statec_callback() ourselves. 10138 * By issuing this call we are trying to kick off the enumera- 10139 * tion process. 10140 */ 10141 /* 10142 * let the state change callback do the SCSI device 10143 * discovery and create the devinfos 10144 */ 10145 fcp_statec_callback(ulph, pptr->port_fp_handle, 10146 pptr->port_phys_state, pptr->port_topology, tmp_list, 10147 max_cnt, pptr->port_id); 10148 10149 res = DDI_SUCCESS; 10150 break; 10151 } 10152 10153 default: 10154 /* unknown port state */ 10155 fcp_log(CE_WARN, pptr->port_dip, 10156 "!fcp%d: invalid port state at attach=0x%x", 10157 instance, pptr->port_phys_state); 10158 10159 mutex_enter(&pptr->port_mutex); 10160 pptr->port_phys_state = FCP_STATE_OFFLINE; 10161 mutex_exit(&pptr->port_mutex); 10162 10163 res = DDI_SUCCESS; 10164 break; 10165 } 10166 10167 /* free temp list if used */ 10168 if (tmp_list != NULL) { 10169 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10170 } 10171 10172 /* note the attach time */ 10173 pptr->port_attach_time = ddi_get_lbolt64(); 10174 10175 /* all done */ 10176 return (res); 10177 10178 /* a failure we have to clean up after */ 10179 fail: 10180 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10181 10182 if (soft_state_linked) { 10183 /* remove this fcp_port from the linked list */ 10184 (void) fcp_soft_state_unlink(pptr); 10185 } 10186 10187 /* unbind and free event set */ 10188 if (pptr->port_ndi_event_hdl) { 10189 if (event_bind) { 10190 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10191 &pptr->port_ndi_events, NDI_SLEEP); 10192 } 10193 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10194 } 10195 10196 if (pptr->port_ndi_event_defs) { 10197 (void) kmem_free(pptr->port_ndi_event_defs, 10198 sizeof (fcp_ndi_event_defs)); 10199 } 10200 10201 /* 10202 * Clean up mpxio stuff 10203 */ 10204 if (pptr->port_mpxio) { 10205 (void) mdi_phci_unregister(pptr->port_dip, 0); 10206 pptr->port_mpxio--; 10207 } 10208 10209 /* undo SCSI HBA setup */ 10210 if (hba_attached) { 10211 (void) scsi_hba_detach(pptr->port_dip); 10212 } 10213 if (pptr->port_tran != NULL) { 10214 scsi_hba_tran_free(pptr->port_tran); 10215 } 10216 10217 mutex_enter(&fcp_global_mutex); 10218 10219 /* 10220 * We check soft_state_linked, because it is incremented right before 10221 * we call increment fcp_watchdog_init. Therefore, we know if 10222 * soft_state_linked is still FALSE, we do not want to decrement 10223 * fcp_watchdog_init or possibly call untimeout. 10224 */ 10225 10226 if (soft_state_linked) { 10227 if (--fcp_watchdog_init == 0) { 10228 timeout_id_t tid = fcp_watchdog_id; 10229 10230 mutex_exit(&fcp_global_mutex); 10231 (void) untimeout(tid); 10232 } else { 10233 mutex_exit(&fcp_global_mutex); 10234 } 10235 } else { 10236 mutex_exit(&fcp_global_mutex); 10237 } 10238 10239 if (mutex_initted) { 10240 mutex_destroy(&pptr->port_mutex); 10241 mutex_destroy(&pptr->port_pkt_mutex); 10242 } 10243 10244 if (tmp_list != NULL) { 10245 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10246 } 10247 10248 /* this makes pptr invalid */ 10249 ddi_soft_state_free(fcp_softstate, instance); 10250 10251 return (DDI_FAILURE); 10252 } 10253 10254 10255 static int 10256 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10257 { 10258 int count = 0; 10259 10260 mutex_enter(&pptr->port_mutex); 10261 10262 /* 10263 * if the port is powered down or suspended, nothing else 10264 * to do; just return. 10265 */ 10266 if (flag != FCP_STATE_DETACHING) { 10267 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10268 FCP_STATE_SUSPENDED)) { 10269 pptr->port_state |= flag; 10270 mutex_exit(&pptr->port_mutex); 10271 return (FC_SUCCESS); 10272 } 10273 } 10274 10275 if (pptr->port_state & FCP_STATE_IN_MDI) { 10276 mutex_exit(&pptr->port_mutex); 10277 return (FC_FAILURE); 10278 } 10279 10280 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10281 fcp_trace, FCP_BUF_LEVEL_2, 0, 10282 "fcp_handle_port_detach: port is detaching"); 10283 10284 pptr->port_state |= flag; 10285 10286 /* 10287 * Wait for any ongoing reconfig/ipkt to complete, that 10288 * ensures the freeing to targets/luns is safe. 10289 * No more ref to this port should happen from statec/ioctl 10290 * after that as it was removed from the global port list. 10291 */ 10292 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10293 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10294 /* 10295 * Let's give sufficient time for reconfig/ipkt 10296 * to complete. 10297 */ 10298 if (count++ >= FCP_ICMD_DEADLINE) { 10299 break; 10300 } 10301 mutex_exit(&pptr->port_mutex); 10302 delay(drv_usectohz(1000000)); 10303 mutex_enter(&pptr->port_mutex); 10304 } 10305 10306 /* 10307 * if the driver is still busy then fail to 10308 * suspend/power down. 10309 */ 10310 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10311 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10312 pptr->port_state &= ~flag; 10313 mutex_exit(&pptr->port_mutex); 10314 return (FC_FAILURE); 10315 } 10316 10317 if (flag == FCP_STATE_DETACHING) { 10318 pptr = fcp_soft_state_unlink(pptr); 10319 ASSERT(pptr != NULL); 10320 } 10321 10322 pptr->port_link_cnt++; 10323 pptr->port_state |= FCP_STATE_OFFLINE; 10324 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10325 10326 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10327 FCP_CAUSE_LINK_DOWN); 10328 mutex_exit(&pptr->port_mutex); 10329 10330 /* kill watch dog timer if we're the last */ 10331 mutex_enter(&fcp_global_mutex); 10332 if (--fcp_watchdog_init == 0) { 10333 timeout_id_t tid = fcp_watchdog_id; 10334 mutex_exit(&fcp_global_mutex); 10335 (void) untimeout(tid); 10336 } else { 10337 mutex_exit(&fcp_global_mutex); 10338 } 10339 10340 /* clean up the port structures */ 10341 if (flag == FCP_STATE_DETACHING) { 10342 fcp_cleanup_port(pptr, instance); 10343 } 10344 10345 return (FC_SUCCESS); 10346 } 10347 10348 10349 static void 10350 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10351 { 10352 ASSERT(pptr != NULL); 10353 10354 /* unbind and free event set */ 10355 if (pptr->port_ndi_event_hdl) { 10356 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10357 &pptr->port_ndi_events, NDI_SLEEP); 10358 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10359 } 10360 10361 if (pptr->port_ndi_event_defs) { 10362 (void) kmem_free(pptr->port_ndi_event_defs, 10363 sizeof (fcp_ndi_event_defs)); 10364 } 10365 10366 /* free the lun/target structures and devinfos */ 10367 fcp_free_targets(pptr); 10368 10369 /* 10370 * Clean up mpxio stuff 10371 */ 10372 if (pptr->port_mpxio) { 10373 (void) mdi_phci_unregister(pptr->port_dip, 0); 10374 pptr->port_mpxio--; 10375 } 10376 10377 /* clean up SCSA stuff */ 10378 (void) scsi_hba_detach(pptr->port_dip); 10379 if (pptr->port_tran != NULL) { 10380 scsi_hba_tran_free(pptr->port_tran); 10381 } 10382 10383 #ifdef KSTATS_CODE 10384 /* clean up kstats */ 10385 if (pptr->fcp_ksp != NULL) { 10386 kstat_delete(pptr->fcp_ksp); 10387 } 10388 #endif 10389 10390 /* clean up soft state mutexes/condition variables */ 10391 mutex_destroy(&pptr->port_mutex); 10392 mutex_destroy(&pptr->port_pkt_mutex); 10393 10394 /* all done with soft state */ 10395 ddi_soft_state_free(fcp_softstate, instance); 10396 } 10397 10398 /* 10399 * Function: fcp_kmem_cache_constructor 10400 * 10401 * Description: This function allocates and initializes the resources required 10402 * to build a scsi_pkt structure the target driver. The result 10403 * of the allocation and initialization will be cached in the 10404 * memory cache. As DMA resources may be allocated here, that 10405 * means DMA resources will be tied up in the cache manager. 10406 * This is a tradeoff that has been made for performance reasons. 10407 * 10408 * Argument: *buf Memory to preinitialize. 10409 * *arg FCP port structure (fcp_port). 10410 * kmflags Value passed to kmem_cache_alloc() and 10411 * propagated to the constructor. 10412 * 10413 * Return Value: 0 Allocation/Initialization was successful. 10414 * -1 Allocation or Initialization failed. 10415 * 10416 * 10417 * If the returned value is 0, the buffer is initialized like this: 10418 * 10419 * +================================+ 10420 * +----> | struct scsi_pkt | 10421 * | | | 10422 * | +--- | pkt_ha_private | 10423 * | | | | 10424 * | | +================================+ 10425 * | | 10426 * | | +================================+ 10427 * | +--> | struct fcp_pkt | <---------+ 10428 * | | | | 10429 * +----- | cmd_pkt | | 10430 * | cmd_fp_pkt | ---+ | 10431 * +-------->| cmd_fcp_rsp[] | | | 10432 * | +--->| cmd_fcp_cmd[] | | | 10433 * | | |--------------------------------| | | 10434 * | | | struct fc_packet | <--+ | 10435 * | | | | | 10436 * | | | pkt_ulp_private | ----------+ 10437 * | | | pkt_fca_private | -----+ 10438 * | | | pkt_data_cookie | ---+ | 10439 * | | | pkt_cmdlen | | | 10440 * | |(a) | pkt_rsplen | | | 10441 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10442 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10443 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10444 * | pkt_resp_cookie | ---|-|--+ | | | 10445 * | pkt_cmd_dma | | | | | | | 10446 * | pkt_cmd_acc | | | | | | | 10447 * +================================+ | | | | | | 10448 * | dma_cookies | <--+ | | | | | 10449 * | | | | | | | 10450 * +================================+ | | | | | 10451 * | fca_private | <----+ | | | | 10452 * | | | | | | 10453 * +================================+ | | | | 10454 * | | | | 10455 * | | | | 10456 * +================================+ (d) | | | | 10457 * | fcp_resp cookies | <-------+ | | | 10458 * | | | | | 10459 * +================================+ | | | 10460 * | | | 10461 * +================================+ (d) | | | 10462 * | fcp_resp | <-----------+ | | 10463 * | (DMA resources associated) | | | 10464 * +================================+ | | 10465 * | | 10466 * | | 10467 * | | 10468 * +================================+ (c) | | 10469 * | fcp_cmd cookies | <---------------+ | 10470 * | | | 10471 * +================================+ | 10472 * | 10473 * +================================+ (c) | 10474 * | fcp_cmd | <--------------------+ 10475 * | (DMA resources associated) | 10476 * +================================+ 10477 * 10478 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10479 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10480 * (c) Only if DMA is used for the FCP_CMD buffer. 10481 * (d) Only if DMA is used for the FCP_RESP buffer 10482 */ 10483 static int 10484 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10485 int kmflags) 10486 { 10487 struct fcp_pkt *cmd; 10488 struct fcp_port *pptr; 10489 fc_packet_t *fpkt; 10490 10491 pptr = (struct fcp_port *)tran->tran_hba_private; 10492 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10493 bzero(cmd, tran->tran_hba_len); 10494 10495 cmd->cmd_pkt = pkt; 10496 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10497 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10498 cmd->cmd_fp_pkt = fpkt; 10499 10500 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10501 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10502 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10503 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10504 10505 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10506 sizeof (struct fcp_pkt)); 10507 10508 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10509 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10510 10511 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10512 /* 10513 * The underlying HBA doesn't want to DMA the fcp_cmd or 10514 * fcp_resp. The transfer of information will be done by 10515 * bcopy. 10516 * The naming of the flags (that is actually a value) is 10517 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10518 * DMA" but instead "NO DMA". 10519 */ 10520 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10521 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10522 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10523 } else { 10524 /* 10525 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10526 * buffer. A buffer is allocated for each one the ddi_dma_* 10527 * interfaces. 10528 */ 10529 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10530 return (-1); 10531 } 10532 } 10533 10534 return (0); 10535 } 10536 10537 /* 10538 * Function: fcp_kmem_cache_destructor 10539 * 10540 * Description: Called by the destructor of the cache managed by SCSA. 10541 * All the resources pre-allocated in fcp_pkt_constructor 10542 * and the data also pre-initialized in fcp_pkt_constructor 10543 * are freed and uninitialized here. 10544 * 10545 * Argument: *buf Memory to uninitialize. 10546 * *arg FCP port structure (fcp_port). 10547 * 10548 * Return Value: None 10549 * 10550 * Context: kernel 10551 */ 10552 static void 10553 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10554 { 10555 struct fcp_pkt *cmd; 10556 struct fcp_port *pptr; 10557 10558 pptr = (struct fcp_port *)(tran->tran_hba_private); 10559 cmd = pkt->pkt_ha_private; 10560 10561 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10562 /* 10563 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10564 * buffer and DMA resources allocated to do so are released. 10565 */ 10566 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10567 } 10568 } 10569 10570 /* 10571 * Function: fcp_alloc_cmd_resp 10572 * 10573 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10574 * will be DMAed by the HBA. The buffer is allocated applying 10575 * the DMA requirements for the HBA. The buffers allocated will 10576 * also be bound. DMA resources are allocated in the process. 10577 * They will be released by fcp_free_cmd_resp(). 10578 * 10579 * Argument: *pptr FCP port. 10580 * *fpkt fc packet for which the cmd and resp packet should be 10581 * allocated. 10582 * flags Allocation flags. 10583 * 10584 * Return Value: FC_FAILURE 10585 * FC_SUCCESS 10586 * 10587 * Context: User or Kernel context only if flags == KM_SLEEP. 10588 * Interrupt context if the KM_SLEEP is not specified. 10589 */ 10590 static int 10591 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10592 { 10593 int rval; 10594 int cmd_len; 10595 int resp_len; 10596 ulong_t real_len; 10597 int (*cb) (caddr_t); 10598 ddi_dma_cookie_t pkt_cookie; 10599 ddi_dma_cookie_t *cp; 10600 uint32_t cnt; 10601 10602 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10603 10604 cmd_len = fpkt->pkt_cmdlen; 10605 resp_len = fpkt->pkt_rsplen; 10606 10607 ASSERT(fpkt->pkt_cmd_dma == NULL); 10608 10609 /* Allocation of a DMA handle used in subsequent calls. */ 10610 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10611 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10612 return (FC_FAILURE); 10613 } 10614 10615 /* A buffer is allocated that satisfies the DMA requirements. */ 10616 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10617 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10618 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10619 10620 if (rval != DDI_SUCCESS) { 10621 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10622 return (FC_FAILURE); 10623 } 10624 10625 if (real_len < cmd_len) { 10626 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10627 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10628 return (FC_FAILURE); 10629 } 10630 10631 /* The buffer allocated is DMA bound. */ 10632 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10633 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10634 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10635 10636 if (rval != DDI_DMA_MAPPED) { 10637 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10638 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10639 return (FC_FAILURE); 10640 } 10641 10642 if (fpkt->pkt_cmd_cookie_cnt > 10643 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10644 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10645 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10646 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10647 return (FC_FAILURE); 10648 } 10649 10650 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10651 10652 /* 10653 * The buffer where the scatter/gather list is going to be built is 10654 * allocated. 10655 */ 10656 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10657 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10658 KM_NOSLEEP); 10659 10660 if (cp == NULL) { 10661 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10662 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10663 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10664 return (FC_FAILURE); 10665 } 10666 10667 /* 10668 * The scatter/gather list for the buffer we just allocated is built 10669 * here. 10670 */ 10671 *cp = pkt_cookie; 10672 cp++; 10673 10674 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10675 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10676 &pkt_cookie); 10677 *cp = pkt_cookie; 10678 } 10679 10680 ASSERT(fpkt->pkt_resp_dma == NULL); 10681 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10682 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10683 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10684 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10685 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10686 return (FC_FAILURE); 10687 } 10688 10689 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10690 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10691 (caddr_t *)&fpkt->pkt_resp, &real_len, 10692 &fpkt->pkt_resp_acc); 10693 10694 if (rval != DDI_SUCCESS) { 10695 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10696 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10697 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10698 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10699 kmem_free(fpkt->pkt_cmd_cookie, 10700 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10701 return (FC_FAILURE); 10702 } 10703 10704 if (real_len < resp_len) { 10705 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10706 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10707 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10708 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10709 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10710 kmem_free(fpkt->pkt_cmd_cookie, 10711 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10712 return (FC_FAILURE); 10713 } 10714 10715 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10716 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10717 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10718 10719 if (rval != DDI_DMA_MAPPED) { 10720 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10721 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10722 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10723 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10724 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10725 kmem_free(fpkt->pkt_cmd_cookie, 10726 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10727 return (FC_FAILURE); 10728 } 10729 10730 if (fpkt->pkt_resp_cookie_cnt > 10731 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10732 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10733 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10734 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10735 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10736 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10737 kmem_free(fpkt->pkt_cmd_cookie, 10738 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10739 return (FC_FAILURE); 10740 } 10741 10742 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10743 10744 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10745 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10746 KM_NOSLEEP); 10747 10748 if (cp == NULL) { 10749 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10750 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10751 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10752 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10753 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10754 kmem_free(fpkt->pkt_cmd_cookie, 10755 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10756 return (FC_FAILURE); 10757 } 10758 10759 *cp = pkt_cookie; 10760 cp++; 10761 10762 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10763 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10764 &pkt_cookie); 10765 *cp = pkt_cookie; 10766 } 10767 10768 return (FC_SUCCESS); 10769 } 10770 10771 /* 10772 * Function: fcp_free_cmd_resp 10773 * 10774 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10775 * allocated by fcp_alloc_cmd_resp() and all the resources 10776 * associated with them. That includes the DMA resources and the 10777 * buffer allocated for the cookies of each one of them. 10778 * 10779 * Argument: *pptr FCP port context. 10780 * *fpkt fc packet containing the cmd and resp packet 10781 * to be released. 10782 * 10783 * Return Value: None 10784 * 10785 * Context: Interrupt, User and Kernel context. 10786 */ 10787 /* ARGSUSED */ 10788 static void 10789 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10790 { 10791 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10792 10793 if (fpkt->pkt_resp_dma) { 10794 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10795 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10796 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10797 } 10798 10799 if (fpkt->pkt_resp_cookie) { 10800 kmem_free(fpkt->pkt_resp_cookie, 10801 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10802 fpkt->pkt_resp_cookie = NULL; 10803 } 10804 10805 if (fpkt->pkt_cmd_dma) { 10806 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10807 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10808 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10809 } 10810 10811 if (fpkt->pkt_cmd_cookie) { 10812 kmem_free(fpkt->pkt_cmd_cookie, 10813 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10814 fpkt->pkt_cmd_cookie = NULL; 10815 } 10816 } 10817 10818 10819 /* 10820 * called by the transport to do our own target initialization 10821 * 10822 * can acquire and release the global mutex 10823 */ 10824 /* ARGSUSED */ 10825 static int 10826 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10827 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10828 { 10829 uchar_t *bytes; 10830 uint_t nbytes; 10831 uint16_t lun_num; 10832 struct fcp_tgt *ptgt; 10833 struct fcp_lun *plun; 10834 struct fcp_port *pptr = (struct fcp_port *) 10835 hba_tran->tran_hba_private; 10836 10837 ASSERT(pptr != NULL); 10838 10839 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10840 FCP_BUF_LEVEL_8, 0, 10841 "fcp_phys_tgt_init: called for %s (instance %d)", 10842 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10843 10844 /* get our port WWN property */ 10845 bytes = NULL; 10846 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10847 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10848 (nbytes != FC_WWN_SIZE)) { 10849 /* no port WWN property */ 10850 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10851 FCP_BUF_LEVEL_8, 0, 10852 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10853 " for %s (instance %d): bytes=%p nbytes=%x", 10854 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10855 nbytes); 10856 10857 if (bytes != NULL) { 10858 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10859 } 10860 10861 return (DDI_NOT_WELL_FORMED); 10862 } 10863 ASSERT(bytes != NULL); 10864 10865 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10866 LUN_PROP, 0xFFFF); 10867 if (lun_num == 0xFFFF) { 10868 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10869 FCP_BUF_LEVEL_8, 0, 10870 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10871 " for %s (instance %d)", ddi_get_name(tgt_dip), 10872 ddi_get_instance(tgt_dip)); 10873 10874 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10875 return (DDI_NOT_WELL_FORMED); 10876 } 10877 10878 mutex_enter(&pptr->port_mutex); 10879 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10880 mutex_exit(&pptr->port_mutex); 10881 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10882 FCP_BUF_LEVEL_8, 0, 10883 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10884 " for %s (instance %d)", ddi_get_name(tgt_dip), 10885 ddi_get_instance(tgt_dip)); 10886 10887 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10888 return (DDI_FAILURE); 10889 } 10890 10891 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10892 FC_WWN_SIZE) == 0); 10893 ASSERT(plun->lun_num == lun_num); 10894 10895 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10896 10897 ptgt = plun->lun_tgt; 10898 10899 mutex_enter(&ptgt->tgt_mutex); 10900 plun->lun_tgt_count++; 10901 scsi_device_hba_private_set(sd, plun); 10902 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10903 plun->lun_sd = sd; 10904 mutex_exit(&ptgt->tgt_mutex); 10905 mutex_exit(&pptr->port_mutex); 10906 10907 return (DDI_SUCCESS); 10908 } 10909 10910 /*ARGSUSED*/ 10911 static int 10912 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10913 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10914 { 10915 uchar_t *bytes; 10916 uint_t nbytes; 10917 uint16_t lun_num; 10918 struct fcp_tgt *ptgt; 10919 struct fcp_lun *plun; 10920 struct fcp_port *pptr = (struct fcp_port *) 10921 hba_tran->tran_hba_private; 10922 child_info_t *cip; 10923 10924 ASSERT(pptr != NULL); 10925 10926 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10927 fcp_trace, FCP_BUF_LEVEL_8, 0, 10928 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10929 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10930 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10931 10932 cip = (child_info_t *)sd->sd_pathinfo; 10933 if (cip == NULL) { 10934 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10935 fcp_trace, FCP_BUF_LEVEL_8, 0, 10936 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10937 " for %s (instance %d)", ddi_get_name(tgt_dip), 10938 ddi_get_instance(tgt_dip)); 10939 10940 return (DDI_NOT_WELL_FORMED); 10941 } 10942 10943 /* get our port WWN property */ 10944 bytes = NULL; 10945 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10946 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10947 (nbytes != FC_WWN_SIZE)) { 10948 if (bytes) { 10949 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10950 } 10951 return (DDI_NOT_WELL_FORMED); 10952 } 10953 10954 ASSERT(bytes != NULL); 10955 10956 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10957 LUN_PROP, 0xFFFF); 10958 if (lun_num == 0xFFFF) { 10959 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10960 fcp_trace, FCP_BUF_LEVEL_8, 0, 10961 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10962 " for %s (instance %d)", ddi_get_name(tgt_dip), 10963 ddi_get_instance(tgt_dip)); 10964 10965 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10966 return (DDI_NOT_WELL_FORMED); 10967 } 10968 10969 mutex_enter(&pptr->port_mutex); 10970 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10971 mutex_exit(&pptr->port_mutex); 10972 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10973 fcp_trace, FCP_BUF_LEVEL_8, 0, 10974 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10975 " for %s (instance %d)", ddi_get_name(tgt_dip), 10976 ddi_get_instance(tgt_dip)); 10977 10978 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10979 return (DDI_FAILURE); 10980 } 10981 10982 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10983 FC_WWN_SIZE) == 0); 10984 ASSERT(plun->lun_num == lun_num); 10985 10986 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10987 10988 ptgt = plun->lun_tgt; 10989 10990 mutex_enter(&ptgt->tgt_mutex); 10991 plun->lun_tgt_count++; 10992 scsi_device_hba_private_set(sd, plun); 10993 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10994 plun->lun_sd = sd; 10995 mutex_exit(&ptgt->tgt_mutex); 10996 mutex_exit(&pptr->port_mutex); 10997 10998 return (DDI_SUCCESS); 10999 } 11000 11001 11002 /* 11003 * called by the transport to do our own target initialization 11004 * 11005 * can acquire and release the global mutex 11006 */ 11007 /* ARGSUSED */ 11008 static int 11009 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11010 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11011 { 11012 struct fcp_port *pptr = (struct fcp_port *) 11013 hba_tran->tran_hba_private; 11014 int rval; 11015 11016 ASSERT(pptr != NULL); 11017 11018 /* 11019 * Child node is getting initialized. Look at the mpxio component 11020 * type on the child device to see if this device is mpxio managed 11021 * or not. 11022 */ 11023 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 11024 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11025 } else { 11026 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11027 } 11028 11029 return (rval); 11030 } 11031 11032 11033 /* ARGSUSED */ 11034 static void 11035 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11036 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11037 { 11038 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 11039 struct fcp_tgt *ptgt; 11040 11041 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 11042 fcp_trace, FCP_BUF_LEVEL_8, 0, 11043 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 11044 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 11045 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 11046 11047 if (plun == NULL) { 11048 return; 11049 } 11050 ptgt = plun->lun_tgt; 11051 11052 ASSERT(ptgt != NULL); 11053 11054 mutex_enter(&ptgt->tgt_mutex); 11055 ASSERT(plun->lun_tgt_count > 0); 11056 11057 if (--plun->lun_tgt_count == 0) { 11058 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11059 } 11060 plun->lun_sd = NULL; 11061 mutex_exit(&ptgt->tgt_mutex); 11062 } 11063 11064 /* 11065 * Function: fcp_scsi_start 11066 * 11067 * Description: This function is called by the target driver to request a 11068 * command to be sent. 11069 * 11070 * Argument: *ap SCSI address of the device. 11071 * *pkt SCSI packet containing the cmd to send. 11072 * 11073 * Return Value: TRAN_ACCEPT 11074 * TRAN_BUSY 11075 * TRAN_BADPKT 11076 * TRAN_FATAL_ERROR 11077 */ 11078 static int 11079 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11080 { 11081 struct fcp_port *pptr = ADDR2FCP(ap); 11082 struct fcp_lun *plun = ADDR2LUN(ap); 11083 struct fcp_pkt *cmd = PKT2CMD(pkt); 11084 struct fcp_tgt *ptgt = plun->lun_tgt; 11085 int rval; 11086 11087 /* ensure command isn't already issued */ 11088 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11089 11090 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11091 fcp_trace, FCP_BUF_LEVEL_9, 0, 11092 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11093 11094 /* 11095 * It is strange that we enter the fcp_port mutex and the target 11096 * mutex to check the lun state (which has a mutex of its own). 11097 */ 11098 mutex_enter(&pptr->port_mutex); 11099 mutex_enter(&ptgt->tgt_mutex); 11100 11101 /* 11102 * If the device is offline and is not in the process of coming 11103 * online, fail the request. 11104 */ 11105 11106 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11107 !(plun->lun_state & FCP_LUN_ONLINING)) { 11108 mutex_exit(&ptgt->tgt_mutex); 11109 mutex_exit(&pptr->port_mutex); 11110 11111 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11112 pkt->pkt_reason = CMD_DEV_GONE; 11113 } 11114 11115 return (TRAN_FATAL_ERROR); 11116 } 11117 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11118 11119 /* 11120 * If we are suspended, kernel is trying to dump, so don't 11121 * block, fail or defer requests - send them down right away. 11122 * NOTE: If we are in panic (i.e. trying to dump), we can't 11123 * assume we have been suspended. There is hardware such as 11124 * the v880 that doesn't do PM. Thus, the check for 11125 * ddi_in_panic. 11126 * 11127 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11128 * of changing. So, if we can queue the packet, do it. Eventually, 11129 * either the device will have gone away or changed and we can fail 11130 * the request, or we can proceed if the device didn't change. 11131 * 11132 * If the pd in the target or the packet is NULL it's probably 11133 * because the device has gone away, we allow the request to be 11134 * put on the internal queue here in case the device comes back within 11135 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11136 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11137 * could be NULL because the device was disappearing during or since 11138 * packet initialization. 11139 */ 11140 11141 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11142 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11143 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11144 (ptgt->tgt_pd_handle == NULL) || 11145 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11146 /* 11147 * If ((LUN is busy AND 11148 * LUN not suspended AND 11149 * The system is not in panic state) OR 11150 * (The port is coming up)) 11151 * 11152 * We check to see if the any of the flags FLAG_NOINTR or 11153 * FLAG_NOQUEUE is set. If one of them is set the value 11154 * returned will be TRAN_BUSY. If not, the request is queued. 11155 */ 11156 mutex_exit(&ptgt->tgt_mutex); 11157 mutex_exit(&pptr->port_mutex); 11158 11159 /* see if using interrupts is allowed (so queueing'll work) */ 11160 if (pkt->pkt_flags & FLAG_NOINTR) { 11161 pkt->pkt_resid = 0; 11162 return (TRAN_BUSY); 11163 } 11164 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11165 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11166 fcp_trace, FCP_BUF_LEVEL_9, 0, 11167 "fcp_scsi_start: lun busy for pkt %p", pkt); 11168 return (TRAN_BUSY); 11169 } 11170 #ifdef DEBUG 11171 mutex_enter(&pptr->port_pkt_mutex); 11172 pptr->port_npkts++; 11173 mutex_exit(&pptr->port_pkt_mutex); 11174 #endif /* DEBUG */ 11175 11176 /* got queue up the pkt for later */ 11177 fcp_queue_pkt(pptr, cmd); 11178 return (TRAN_ACCEPT); 11179 } 11180 cmd->cmd_state = FCP_PKT_ISSUED; 11181 11182 mutex_exit(&ptgt->tgt_mutex); 11183 mutex_exit(&pptr->port_mutex); 11184 11185 /* 11186 * Now that we released the mutexes, what was protected by them can 11187 * change. 11188 */ 11189 11190 /* 11191 * If there is a reconfiguration in progress, wait for it to complete. 11192 */ 11193 fcp_reconfig_wait(pptr); 11194 11195 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11196 pkt->pkt_time : 0; 11197 11198 /* prepare the packet */ 11199 11200 fcp_prepare_pkt(pptr, cmd, plun); 11201 11202 if (cmd->cmd_pkt->pkt_time) { 11203 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11204 } else { 11205 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11206 } 11207 11208 /* 11209 * if interrupts aren't allowed (e.g. at dump time) then we'll 11210 * have to do polled I/O 11211 */ 11212 if (pkt->pkt_flags & FLAG_NOINTR) { 11213 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11214 return (fcp_dopoll(pptr, cmd)); 11215 } 11216 11217 #ifdef DEBUG 11218 mutex_enter(&pptr->port_pkt_mutex); 11219 pptr->port_npkts++; 11220 mutex_exit(&pptr->port_pkt_mutex); 11221 #endif /* DEBUG */ 11222 11223 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11224 if (rval == FC_SUCCESS) { 11225 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11226 fcp_trace, FCP_BUF_LEVEL_9, 0, 11227 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11228 return (TRAN_ACCEPT); 11229 } 11230 11231 cmd->cmd_state = FCP_PKT_IDLE; 11232 11233 #ifdef DEBUG 11234 mutex_enter(&pptr->port_pkt_mutex); 11235 pptr->port_npkts--; 11236 mutex_exit(&pptr->port_pkt_mutex); 11237 #endif /* DEBUG */ 11238 11239 /* 11240 * For lack of clearer definitions, choose 11241 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11242 */ 11243 11244 if (rval == FC_TRAN_BUSY) { 11245 pkt->pkt_resid = 0; 11246 rval = TRAN_BUSY; 11247 } else { 11248 mutex_enter(&ptgt->tgt_mutex); 11249 if (plun->lun_state & FCP_LUN_OFFLINE) { 11250 child_info_t *cip; 11251 11252 mutex_enter(&plun->lun_mutex); 11253 cip = plun->lun_cip; 11254 mutex_exit(&plun->lun_mutex); 11255 11256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11257 fcp_trace, FCP_BUF_LEVEL_6, 0, 11258 "fcp_transport failed 2 for %x: %x; dip=%p", 11259 plun->lun_tgt->tgt_d_id, rval, cip); 11260 11261 rval = TRAN_FATAL_ERROR; 11262 } else { 11263 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11264 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11265 fcp_trace, FCP_BUF_LEVEL_9, 0, 11266 "fcp_scsi_start: FC_BUSY for pkt %p", 11267 pkt); 11268 rval = TRAN_BUSY; 11269 } else { 11270 rval = TRAN_ACCEPT; 11271 fcp_queue_pkt(pptr, cmd); 11272 } 11273 } 11274 mutex_exit(&ptgt->tgt_mutex); 11275 } 11276 11277 return (rval); 11278 } 11279 11280 /* 11281 * called by the transport to abort a packet 11282 */ 11283 /*ARGSUSED*/ 11284 static int 11285 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11286 { 11287 int tgt_cnt; 11288 struct fcp_port *pptr = ADDR2FCP(ap); 11289 struct fcp_lun *plun = ADDR2LUN(ap); 11290 struct fcp_tgt *ptgt = plun->lun_tgt; 11291 11292 if (pkt == NULL) { 11293 if (ptgt) { 11294 mutex_enter(&ptgt->tgt_mutex); 11295 tgt_cnt = ptgt->tgt_change_cnt; 11296 mutex_exit(&ptgt->tgt_mutex); 11297 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11298 return (TRUE); 11299 } 11300 } 11301 return (FALSE); 11302 } 11303 11304 11305 /* 11306 * Perform reset 11307 */ 11308 int 11309 fcp_scsi_reset(struct scsi_address *ap, int level) 11310 { 11311 int rval = 0; 11312 struct fcp_port *pptr = ADDR2FCP(ap); 11313 struct fcp_lun *plun = ADDR2LUN(ap); 11314 struct fcp_tgt *ptgt = plun->lun_tgt; 11315 11316 if (level == RESET_ALL) { 11317 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11318 rval = 1; 11319 } 11320 } else if (level == RESET_TARGET || level == RESET_LUN) { 11321 /* 11322 * If we are in the middle of discovery, return 11323 * SUCCESS as this target will be rediscovered 11324 * anyway 11325 */ 11326 mutex_enter(&ptgt->tgt_mutex); 11327 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11328 mutex_exit(&ptgt->tgt_mutex); 11329 return (1); 11330 } 11331 mutex_exit(&ptgt->tgt_mutex); 11332 11333 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11334 rval = 1; 11335 } 11336 } 11337 return (rval); 11338 } 11339 11340 11341 /* 11342 * called by the framework to get a SCSI capability 11343 */ 11344 static int 11345 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11346 { 11347 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11348 } 11349 11350 11351 /* 11352 * called by the framework to set a SCSI capability 11353 */ 11354 static int 11355 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11356 { 11357 return (fcp_commoncap(ap, cap, value, whom, 1)); 11358 } 11359 11360 /* 11361 * Function: fcp_pkt_setup 11362 * 11363 * Description: This function sets up the scsi_pkt structure passed by the 11364 * caller. This function assumes fcp_pkt_constructor has been 11365 * called previously for the packet passed by the caller. If 11366 * successful this call will have the following results: 11367 * 11368 * - The resources needed that will be constant through out 11369 * the whole transaction are allocated. 11370 * - The fields that will be constant through out the whole 11371 * transaction are initialized. 11372 * - The scsi packet will be linked to the LUN structure 11373 * addressed by the transaction. 11374 * 11375 * Argument: 11376 * *pkt Pointer to a scsi_pkt structure. 11377 * callback 11378 * arg 11379 * 11380 * Return Value: 0 Success 11381 * !0 Failure 11382 * 11383 * Context: Kernel context or interrupt context 11384 */ 11385 /* ARGSUSED */ 11386 static int 11387 fcp_pkt_setup(struct scsi_pkt *pkt, 11388 int (*callback)(caddr_t arg), 11389 caddr_t arg) 11390 { 11391 struct fcp_pkt *cmd; 11392 struct fcp_port *pptr; 11393 struct fcp_lun *plun; 11394 struct fcp_tgt *ptgt; 11395 int kf; 11396 fc_packet_t *fpkt; 11397 fc_frame_hdr_t *hp; 11398 11399 pptr = ADDR2FCP(&pkt->pkt_address); 11400 plun = ADDR2LUN(&pkt->pkt_address); 11401 ptgt = plun->lun_tgt; 11402 11403 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11404 fpkt = cmd->cmd_fp_pkt; 11405 11406 /* 11407 * this request is for dma allocation only 11408 */ 11409 /* 11410 * First step of fcp_scsi_init_pkt: pkt allocation 11411 * We determine if the caller is willing to wait for the 11412 * resources. 11413 */ 11414 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11415 11416 /* 11417 * Selective zeroing of the pkt. 11418 */ 11419 cmd->cmd_back = NULL; 11420 cmd->cmd_next = NULL; 11421 11422 /* 11423 * Zero out fcp command 11424 */ 11425 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11426 11427 cmd->cmd_state = FCP_PKT_IDLE; 11428 11429 fpkt = cmd->cmd_fp_pkt; 11430 fpkt->pkt_data_acc = NULL; 11431 11432 /* 11433 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11434 * could be destroyed. We need fail pkt_setup. 11435 */ 11436 if (pptr->port_state & FCP_STATE_OFFLINE) { 11437 return (-1); 11438 } 11439 11440 mutex_enter(&ptgt->tgt_mutex); 11441 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11442 11443 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11444 != FC_SUCCESS) { 11445 mutex_exit(&ptgt->tgt_mutex); 11446 return (-1); 11447 } 11448 11449 mutex_exit(&ptgt->tgt_mutex); 11450 11451 /* Fill in the Fabric Channel Header */ 11452 hp = &fpkt->pkt_cmd_fhdr; 11453 hp->r_ctl = R_CTL_COMMAND; 11454 hp->rsvd = 0; 11455 hp->type = FC_TYPE_SCSI_FCP; 11456 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11457 hp->seq_id = 0; 11458 hp->df_ctl = 0; 11459 hp->seq_cnt = 0; 11460 hp->ox_id = 0xffff; 11461 hp->rx_id = 0xffff; 11462 hp->ro = 0; 11463 11464 /* 11465 * A doubly linked list (cmd_forw, cmd_back) is built 11466 * out of every allocated packet on a per-lun basis 11467 * 11468 * The packets are maintained in the list so as to satisfy 11469 * scsi_abort() requests. At present (which is unlikely to 11470 * change in the future) nobody performs a real scsi_abort 11471 * in the SCSI target drivers (as they don't keep the packets 11472 * after doing scsi_transport - so they don't know how to 11473 * abort a packet other than sending a NULL to abort all 11474 * outstanding packets) 11475 */ 11476 mutex_enter(&plun->lun_mutex); 11477 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11478 plun->lun_pkt_head->cmd_back = cmd; 11479 } else { 11480 plun->lun_pkt_tail = cmd; 11481 } 11482 plun->lun_pkt_head = cmd; 11483 mutex_exit(&plun->lun_mutex); 11484 return (0); 11485 } 11486 11487 /* 11488 * Function: fcp_pkt_teardown 11489 * 11490 * Description: This function releases a scsi_pkt structure and all the 11491 * resources attached to it. 11492 * 11493 * Argument: *pkt Pointer to a scsi_pkt structure. 11494 * 11495 * Return Value: None 11496 * 11497 * Context: User, Kernel or Interrupt context. 11498 */ 11499 static void 11500 fcp_pkt_teardown(struct scsi_pkt *pkt) 11501 { 11502 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11503 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11504 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11505 11506 /* 11507 * Remove the packet from the per-lun list 11508 */ 11509 mutex_enter(&plun->lun_mutex); 11510 if (cmd->cmd_back) { 11511 ASSERT(cmd != plun->lun_pkt_head); 11512 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11513 } else { 11514 ASSERT(cmd == plun->lun_pkt_head); 11515 plun->lun_pkt_head = cmd->cmd_forw; 11516 } 11517 11518 if (cmd->cmd_forw) { 11519 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11520 } else { 11521 ASSERT(cmd == plun->lun_pkt_tail); 11522 plun->lun_pkt_tail = cmd->cmd_back; 11523 } 11524 11525 mutex_exit(&plun->lun_mutex); 11526 11527 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11528 } 11529 11530 /* 11531 * Routine for reset notification setup, to register or cancel. 11532 * This function is called by SCSA 11533 */ 11534 /*ARGSUSED*/ 11535 static int 11536 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11537 void (*callback)(caddr_t), caddr_t arg) 11538 { 11539 struct fcp_port *pptr = ADDR2FCP(ap); 11540 11541 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11542 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11543 } 11544 11545 11546 static int 11547 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11548 ddi_eventcookie_t *event_cookiep) 11549 { 11550 struct fcp_port *pptr = fcp_dip2port(dip); 11551 11552 if (pptr == NULL) { 11553 return (DDI_FAILURE); 11554 } 11555 11556 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11557 event_cookiep, NDI_EVENT_NOPASS)); 11558 } 11559 11560 11561 static int 11562 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11563 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11564 ddi_callback_id_t *cb_id) 11565 { 11566 struct fcp_port *pptr = fcp_dip2port(dip); 11567 11568 if (pptr == NULL) { 11569 return (DDI_FAILURE); 11570 } 11571 11572 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11573 eventid, callback, arg, NDI_SLEEP, cb_id)); 11574 } 11575 11576 11577 static int 11578 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11579 { 11580 11581 struct fcp_port *pptr = fcp_dip2port(dip); 11582 11583 if (pptr == NULL) { 11584 return (DDI_FAILURE); 11585 } 11586 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11587 } 11588 11589 11590 /* 11591 * called by the transport to post an event 11592 */ 11593 static int 11594 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11595 ddi_eventcookie_t eventid, void *impldata) 11596 { 11597 struct fcp_port *pptr = fcp_dip2port(dip); 11598 11599 if (pptr == NULL) { 11600 return (DDI_FAILURE); 11601 } 11602 11603 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11604 eventid, impldata)); 11605 } 11606 11607 11608 /* 11609 * A target in in many cases in Fibre Channel has a one to one relation 11610 * with a port identifier (which is also known as D_ID and also as AL_PA 11611 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11612 * will most likely result in resetting all LUNs (which means a reset will 11613 * occur on all the SCSI devices connected at the other end of the bridge) 11614 * That is the latest favorite topic for discussion, for, one can debate as 11615 * hot as one likes and come up with arguably a best solution to one's 11616 * satisfaction 11617 * 11618 * To stay on track and not digress much, here are the problems stated 11619 * briefly: 11620 * 11621 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11622 * target drivers use RESET_TARGET even if their instance is on a 11623 * LUN. Doesn't that sound a bit broken ? 11624 * 11625 * FCP SCSI (the current spec) only defines RESET TARGET in the 11626 * control fields of an FCP_CMND structure. It should have been 11627 * fixed right there, giving flexibility to the initiators to 11628 * minimize havoc that could be caused by resetting a target. 11629 */ 11630 static int 11631 fcp_reset_target(struct scsi_address *ap, int level) 11632 { 11633 int rval = FC_FAILURE; 11634 char lun_id[25]; 11635 struct fcp_port *pptr = ADDR2FCP(ap); 11636 struct fcp_lun *plun = ADDR2LUN(ap); 11637 struct fcp_tgt *ptgt = plun->lun_tgt; 11638 struct scsi_pkt *pkt; 11639 struct fcp_pkt *cmd; 11640 struct fcp_rsp *rsp; 11641 uint32_t tgt_cnt; 11642 struct fcp_rsp_info *rsp_info; 11643 struct fcp_reset_elem *p; 11644 int bval; 11645 11646 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11647 KM_NOSLEEP)) == NULL) { 11648 return (rval); 11649 } 11650 11651 mutex_enter(&ptgt->tgt_mutex); 11652 if (level == RESET_TARGET) { 11653 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11654 mutex_exit(&ptgt->tgt_mutex); 11655 kmem_free(p, sizeof (struct fcp_reset_elem)); 11656 return (rval); 11657 } 11658 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11659 (void) strcpy(lun_id, " "); 11660 } else { 11661 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11662 mutex_exit(&ptgt->tgt_mutex); 11663 kmem_free(p, sizeof (struct fcp_reset_elem)); 11664 return (rval); 11665 } 11666 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11667 11668 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11669 } 11670 tgt_cnt = ptgt->tgt_change_cnt; 11671 11672 mutex_exit(&ptgt->tgt_mutex); 11673 11674 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11675 0, 0, NULL, 0)) == NULL) { 11676 kmem_free(p, sizeof (struct fcp_reset_elem)); 11677 mutex_enter(&ptgt->tgt_mutex); 11678 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11679 mutex_exit(&ptgt->tgt_mutex); 11680 return (rval); 11681 } 11682 pkt->pkt_time = FCP_POLL_TIMEOUT; 11683 11684 /* fill in cmd part of packet */ 11685 cmd = PKT2CMD(pkt); 11686 if (level == RESET_TARGET) { 11687 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11688 } else { 11689 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11690 } 11691 cmd->cmd_fp_pkt->pkt_comp = NULL; 11692 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11693 11694 /* prepare a packet for transport */ 11695 fcp_prepare_pkt(pptr, cmd, plun); 11696 11697 if (cmd->cmd_pkt->pkt_time) { 11698 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11699 } else { 11700 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11701 } 11702 11703 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11704 bval = fcp_dopoll(pptr, cmd); 11705 fc_ulp_idle_port(pptr->port_fp_handle); 11706 11707 /* submit the packet */ 11708 if (bval == TRAN_ACCEPT) { 11709 int error = 3; 11710 11711 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11712 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11713 sizeof (struct fcp_rsp)); 11714 11715 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11716 if (fcp_validate_fcp_response(rsp, pptr) == 11717 FC_SUCCESS) { 11718 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11719 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11720 sizeof (struct fcp_rsp), rsp_info, 11721 cmd->cmd_fp_pkt->pkt_resp_acc, 11722 sizeof (struct fcp_rsp_info)); 11723 } 11724 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11725 rval = FC_SUCCESS; 11726 error = 0; 11727 } else { 11728 error = 1; 11729 } 11730 } else { 11731 error = 2; 11732 } 11733 } 11734 11735 switch (error) { 11736 case 0: 11737 fcp_log(CE_WARN, pptr->port_dip, 11738 "!FCP: WWN 0x%08x%08x %s reset successfully", 11739 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11740 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11741 break; 11742 11743 case 1: 11744 fcp_log(CE_WARN, pptr->port_dip, 11745 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11746 " response code=%x", 11747 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11748 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11749 rsp_info->rsp_code); 11750 break; 11751 11752 case 2: 11753 fcp_log(CE_WARN, pptr->port_dip, 11754 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11755 " Bad FCP response values: rsvd1=%x," 11756 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11757 " rsplen=%x, senselen=%x", 11758 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11759 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11760 rsp->reserved_0, rsp->reserved_1, 11761 rsp->fcp_u.fcp_status.reserved_0, 11762 rsp->fcp_u.fcp_status.reserved_1, 11763 rsp->fcp_response_len, rsp->fcp_sense_len); 11764 break; 11765 11766 default: 11767 fcp_log(CE_WARN, pptr->port_dip, 11768 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11769 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11770 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11771 break; 11772 } 11773 } 11774 scsi_destroy_pkt(pkt); 11775 11776 if (rval == FC_FAILURE) { 11777 mutex_enter(&ptgt->tgt_mutex); 11778 if (level == RESET_TARGET) { 11779 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11780 } else { 11781 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11782 } 11783 mutex_exit(&ptgt->tgt_mutex); 11784 kmem_free(p, sizeof (struct fcp_reset_elem)); 11785 return (rval); 11786 } 11787 11788 mutex_enter(&pptr->port_mutex); 11789 if (level == RESET_TARGET) { 11790 p->tgt = ptgt; 11791 p->lun = NULL; 11792 } else { 11793 p->tgt = NULL; 11794 p->lun = plun; 11795 } 11796 p->tgt = ptgt; 11797 p->tgt_cnt = tgt_cnt; 11798 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11799 p->next = pptr->port_reset_list; 11800 pptr->port_reset_list = p; 11801 11802 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11803 fcp_trace, FCP_BUF_LEVEL_3, 0, 11804 "Notify ssd of the reset to reinstate the reservations"); 11805 11806 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11807 &pptr->port_reset_notify_listf); 11808 11809 mutex_exit(&pptr->port_mutex); 11810 11811 return (rval); 11812 } 11813 11814 11815 /* 11816 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11817 * SCSI capabilities 11818 */ 11819 /* ARGSUSED */ 11820 static int 11821 fcp_commoncap(struct scsi_address *ap, char *cap, 11822 int val, int tgtonly, int doset) 11823 { 11824 struct fcp_port *pptr = ADDR2FCP(ap); 11825 struct fcp_lun *plun = ADDR2LUN(ap); 11826 struct fcp_tgt *ptgt = plun->lun_tgt; 11827 int cidx; 11828 int rval = FALSE; 11829 11830 if (cap == (char *)0) { 11831 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11832 fcp_trace, FCP_BUF_LEVEL_3, 0, 11833 "fcp_commoncap: invalid arg"); 11834 return (rval); 11835 } 11836 11837 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11838 return (UNDEFINED); 11839 } 11840 11841 /* 11842 * Process setcap request. 11843 */ 11844 if (doset) { 11845 /* 11846 * At present, we can only set binary (0/1) values 11847 */ 11848 switch (cidx) { 11849 case SCSI_CAP_ARQ: 11850 if (val == 0) { 11851 rval = FALSE; 11852 } else { 11853 rval = TRUE; 11854 } 11855 break; 11856 11857 case SCSI_CAP_LUN_RESET: 11858 if (val) { 11859 plun->lun_cap |= FCP_LUN_CAP_RESET; 11860 } else { 11861 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11862 } 11863 rval = TRUE; 11864 break; 11865 11866 case SCSI_CAP_SECTOR_SIZE: 11867 rval = TRUE; 11868 break; 11869 default: 11870 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11871 fcp_trace, FCP_BUF_LEVEL_4, 0, 11872 "fcp_setcap: unsupported %d", cidx); 11873 rval = UNDEFINED; 11874 break; 11875 } 11876 11877 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11878 fcp_trace, FCP_BUF_LEVEL_5, 0, 11879 "set cap: cap=%s, val/tgtonly/doset/rval = " 11880 "0x%x/0x%x/0x%x/%d", 11881 cap, val, tgtonly, doset, rval); 11882 11883 } else { 11884 /* 11885 * Process getcap request. 11886 */ 11887 switch (cidx) { 11888 case SCSI_CAP_DMA_MAX: 11889 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11890 11891 /* 11892 * Need to make an adjustment qlc is uint_t 64 11893 * st is int, so we will make the adjustment here 11894 * being as nobody wants to touch this. 11895 * It still leaves the max single block length 11896 * of 2 gig. This should last . 11897 */ 11898 11899 if (rval == -1) { 11900 rval = MAX_INT_DMA; 11901 } 11902 11903 break; 11904 11905 case SCSI_CAP_INITIATOR_ID: 11906 rval = pptr->port_id; 11907 break; 11908 11909 case SCSI_CAP_ARQ: 11910 case SCSI_CAP_RESET_NOTIFICATION: 11911 case SCSI_CAP_TAGGED_QING: 11912 rval = TRUE; 11913 break; 11914 11915 case SCSI_CAP_SCSI_VERSION: 11916 rval = 3; 11917 break; 11918 11919 case SCSI_CAP_INTERCONNECT_TYPE: 11920 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11921 (ptgt->tgt_hard_addr == 0)) { 11922 rval = INTERCONNECT_FABRIC; 11923 } else { 11924 rval = INTERCONNECT_FIBRE; 11925 } 11926 break; 11927 11928 case SCSI_CAP_LUN_RESET: 11929 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11930 TRUE : FALSE; 11931 break; 11932 11933 default: 11934 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11935 fcp_trace, FCP_BUF_LEVEL_4, 0, 11936 "fcp_getcap: unsupported %d", cidx); 11937 rval = UNDEFINED; 11938 break; 11939 } 11940 11941 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11942 fcp_trace, FCP_BUF_LEVEL_8, 0, 11943 "get cap: cap=%s, val/tgtonly/doset/rval = " 11944 "0x%x/0x%x/0x%x/%d", 11945 cap, val, tgtonly, doset, rval); 11946 } 11947 11948 return (rval); 11949 } 11950 11951 /* 11952 * called by the transport to get the port-wwn and lun 11953 * properties of this device, and to create a "name" based on them 11954 * 11955 * these properties don't exist on sun4m 11956 * 11957 * return 1 for success else return 0 11958 */ 11959 /* ARGSUSED */ 11960 static int 11961 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11962 { 11963 int i; 11964 int *lun; 11965 int numChars; 11966 uint_t nlun; 11967 uint_t count; 11968 uint_t nbytes; 11969 uchar_t *bytes; 11970 uint16_t lun_num; 11971 uint32_t tgt_id; 11972 char **conf_wwn; 11973 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11974 uchar_t barray[FC_WWN_SIZE]; 11975 dev_info_t *tgt_dip; 11976 struct fcp_tgt *ptgt; 11977 struct fcp_port *pptr; 11978 struct fcp_lun *plun; 11979 11980 ASSERT(sd != NULL); 11981 ASSERT(name != NULL); 11982 11983 tgt_dip = sd->sd_dev; 11984 pptr = ddi_get_soft_state(fcp_softstate, 11985 ddi_get_instance(ddi_get_parent(tgt_dip))); 11986 if (pptr == NULL) { 11987 return (0); 11988 } 11989 11990 ASSERT(tgt_dip != NULL); 11991 11992 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11993 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11994 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11995 name[0] = '\0'; 11996 return (0); 11997 } 11998 11999 if (nlun == 0) { 12000 ddi_prop_free(lun); 12001 return (0); 12002 } 12003 12004 lun_num = lun[0]; 12005 ddi_prop_free(lun); 12006 12007 /* 12008 * Lookup for .conf WWN property 12009 */ 12010 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 12011 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 12012 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 12013 ASSERT(count >= 1); 12014 12015 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 12016 ddi_prop_free(conf_wwn); 12017 mutex_enter(&pptr->port_mutex); 12018 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 12019 mutex_exit(&pptr->port_mutex); 12020 return (0); 12021 } 12022 ptgt = plun->lun_tgt; 12023 mutex_exit(&pptr->port_mutex); 12024 12025 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 12026 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 12027 12028 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12029 ptgt->tgt_hard_addr != 0) { 12030 tgt_id = (uint32_t)fcp_alpa_to_switch[ 12031 ptgt->tgt_hard_addr]; 12032 } else { 12033 tgt_id = ptgt->tgt_d_id; 12034 } 12035 12036 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 12037 TARGET_PROP, tgt_id); 12038 } 12039 12040 /* get the our port-wwn property */ 12041 bytes = NULL; 12042 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 12043 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12044 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 12045 if (bytes != NULL) { 12046 ddi_prop_free(bytes); 12047 } 12048 return (0); 12049 } 12050 12051 for (i = 0; i < FC_WWN_SIZE; i++) { 12052 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12053 } 12054 12055 /* Stick in the address of the form "wWWN,LUN" */ 12056 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12057 12058 ASSERT(numChars < len); 12059 if (numChars >= len) { 12060 fcp_log(CE_WARN, pptr->port_dip, 12061 "!fcp_scsi_get_name: " 12062 "name parameter length too small, it needs to be %d", 12063 numChars+1); 12064 } 12065 12066 ddi_prop_free(bytes); 12067 12068 return (1); 12069 } 12070 12071 12072 /* 12073 * called by the transport to get the SCSI target id value, returning 12074 * it in "name" 12075 * 12076 * this isn't needed/used on sun4m 12077 * 12078 * return 1 for success else return 0 12079 */ 12080 /* ARGSUSED */ 12081 static int 12082 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12083 { 12084 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12085 struct fcp_tgt *ptgt; 12086 int numChars; 12087 12088 if (plun == NULL) { 12089 return (0); 12090 } 12091 12092 if ((ptgt = plun->lun_tgt) == NULL) { 12093 return (0); 12094 } 12095 12096 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12097 12098 ASSERT(numChars < len); 12099 if (numChars >= len) { 12100 fcp_log(CE_WARN, NULL, 12101 "!fcp_scsi_get_bus_addr: " 12102 "name parameter length too small, it needs to be %d", 12103 numChars+1); 12104 } 12105 12106 return (1); 12107 } 12108 12109 12110 /* 12111 * called internally to reset the link where the specified port lives 12112 */ 12113 static int 12114 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12115 { 12116 la_wwn_t wwn; 12117 struct fcp_lun *plun; 12118 struct fcp_tgt *ptgt; 12119 12120 /* disable restart of lip if we're suspended */ 12121 mutex_enter(&pptr->port_mutex); 12122 12123 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12124 FCP_STATE_POWER_DOWN)) { 12125 mutex_exit(&pptr->port_mutex); 12126 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12127 fcp_trace, FCP_BUF_LEVEL_2, 0, 12128 "fcp_linkreset, fcp%d: link reset " 12129 "disabled due to DDI_SUSPEND", 12130 ddi_get_instance(pptr->port_dip)); 12131 return (FC_FAILURE); 12132 } 12133 12134 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12135 mutex_exit(&pptr->port_mutex); 12136 return (FC_SUCCESS); 12137 } 12138 12139 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12140 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12141 12142 /* 12143 * If ap == NULL assume local link reset. 12144 */ 12145 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12146 plun = ADDR2LUN(ap); 12147 ptgt = plun->lun_tgt; 12148 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12149 } else { 12150 bzero((caddr_t)&wwn, sizeof (wwn)); 12151 } 12152 mutex_exit(&pptr->port_mutex); 12153 12154 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12155 } 12156 12157 12158 /* 12159 * called from fcp_port_attach() to resume a port 12160 * return DDI_* success/failure status 12161 * acquires and releases the global mutex 12162 * acquires and releases the port mutex 12163 */ 12164 /*ARGSUSED*/ 12165 12166 static int 12167 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12168 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12169 { 12170 int res = DDI_FAILURE; /* default result */ 12171 struct fcp_port *pptr; /* port state ptr */ 12172 uint32_t alloc_cnt; 12173 uint32_t max_cnt; 12174 fc_portmap_t *tmp_list = NULL; 12175 12176 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12177 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12178 instance); 12179 12180 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12181 cmn_err(CE_WARN, "fcp: bad soft state"); 12182 return (res); 12183 } 12184 12185 mutex_enter(&pptr->port_mutex); 12186 switch (cmd) { 12187 case FC_CMD_RESUME: 12188 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12189 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12190 break; 12191 12192 case FC_CMD_POWER_UP: 12193 /* 12194 * If the port is DDI_SUSPENded, defer rediscovery 12195 * until DDI_RESUME occurs 12196 */ 12197 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12198 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12199 mutex_exit(&pptr->port_mutex); 12200 return (DDI_SUCCESS); 12201 } 12202 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12203 } 12204 pptr->port_id = s_id; 12205 pptr->port_state = FCP_STATE_INIT; 12206 mutex_exit(&pptr->port_mutex); 12207 12208 /* 12209 * Make a copy of ulp_port_info as fctl allocates 12210 * a temp struct. 12211 */ 12212 (void) fcp_cp_pinfo(pptr, pinfo); 12213 12214 mutex_enter(&fcp_global_mutex); 12215 if (fcp_watchdog_init++ == 0) { 12216 fcp_watchdog_tick = fcp_watchdog_timeout * 12217 drv_usectohz(1000000); 12218 fcp_watchdog_id = timeout(fcp_watch, 12219 NULL, fcp_watchdog_tick); 12220 } 12221 mutex_exit(&fcp_global_mutex); 12222 12223 /* 12224 * Handle various topologies and link states. 12225 */ 12226 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12227 case FC_STATE_OFFLINE: 12228 /* 12229 * Wait for ONLINE, at which time a state 12230 * change will cause a statec_callback 12231 */ 12232 res = DDI_SUCCESS; 12233 break; 12234 12235 case FC_STATE_ONLINE: 12236 12237 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12238 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12239 res = DDI_SUCCESS; 12240 break; 12241 } 12242 12243 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12244 !fcp_enable_auto_configuration) { 12245 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12246 if (tmp_list == NULL) { 12247 if (!alloc_cnt) { 12248 res = DDI_SUCCESS; 12249 } 12250 break; 12251 } 12252 max_cnt = alloc_cnt; 12253 } else { 12254 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12255 12256 alloc_cnt = FCP_MAX_DEVICES; 12257 12258 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12259 (sizeof (fc_portmap_t)) * alloc_cnt, 12260 KM_NOSLEEP)) == NULL) { 12261 fcp_log(CE_WARN, pptr->port_dip, 12262 "!fcp%d: failed to allocate portmap", 12263 instance); 12264 break; 12265 } 12266 12267 max_cnt = alloc_cnt; 12268 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12269 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12270 FC_SUCCESS) { 12271 caddr_t msg; 12272 12273 (void) fc_ulp_error(res, &msg); 12274 12275 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12276 fcp_trace, FCP_BUF_LEVEL_2, 0, 12277 "resume failed getportmap: reason=0x%x", 12278 res); 12279 12280 fcp_log(CE_WARN, pptr->port_dip, 12281 "!failed to get port map : %s", msg); 12282 break; 12283 } 12284 if (max_cnt > alloc_cnt) { 12285 alloc_cnt = max_cnt; 12286 } 12287 } 12288 12289 /* 12290 * do the SCSI device discovery and create 12291 * the devinfos 12292 */ 12293 fcp_statec_callback(ulph, pptr->port_fp_handle, 12294 pptr->port_phys_state, pptr->port_topology, tmp_list, 12295 max_cnt, pptr->port_id); 12296 12297 res = DDI_SUCCESS; 12298 break; 12299 12300 default: 12301 fcp_log(CE_WARN, pptr->port_dip, 12302 "!fcp%d: invalid port state at attach=0x%x", 12303 instance, pptr->port_phys_state); 12304 12305 mutex_enter(&pptr->port_mutex); 12306 pptr->port_phys_state = FCP_STATE_OFFLINE; 12307 mutex_exit(&pptr->port_mutex); 12308 res = DDI_SUCCESS; 12309 12310 break; 12311 } 12312 12313 if (tmp_list != NULL) { 12314 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12315 } 12316 12317 return (res); 12318 } 12319 12320 12321 static void 12322 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12323 { 12324 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12325 pptr->port_dip = pinfo->port_dip; 12326 pptr->port_fp_handle = pinfo->port_handle; 12327 if (pinfo->port_acc_attr != NULL) { 12328 /* 12329 * FCA supports DMA 12330 */ 12331 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12332 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12333 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12334 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12335 } 12336 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12337 pptr->port_max_exch = pinfo->port_fca_max_exch; 12338 pptr->port_phys_state = pinfo->port_state; 12339 pptr->port_topology = pinfo->port_flags; 12340 pptr->port_reset_action = pinfo->port_reset_action; 12341 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12342 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12343 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12344 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12345 12346 /* Clear FMA caps to avoid fm-capability ereport */ 12347 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12348 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12349 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12350 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12351 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12352 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12353 } 12354 12355 /* 12356 * If the elements wait field is set to 1 then 12357 * another thread is waiting for the operation to complete. Once 12358 * it is complete, the waiting thread is signaled and the element is 12359 * freed by the waiting thread. If the elements wait field is set to 0 12360 * the element is freed. 12361 */ 12362 static void 12363 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12364 { 12365 ASSERT(elem != NULL); 12366 mutex_enter(&elem->mutex); 12367 elem->result = result; 12368 if (elem->wait) { 12369 elem->wait = 0; 12370 cv_signal(&elem->cv); 12371 mutex_exit(&elem->mutex); 12372 } else { 12373 mutex_exit(&elem->mutex); 12374 cv_destroy(&elem->cv); 12375 mutex_destroy(&elem->mutex); 12376 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12377 } 12378 } 12379 12380 /* 12381 * This function is invoked from the taskq thread to allocate 12382 * devinfo nodes and to online/offline them. 12383 */ 12384 static void 12385 fcp_hp_task(void *arg) 12386 { 12387 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12388 struct fcp_lun *plun = elem->lun; 12389 struct fcp_port *pptr = elem->port; 12390 int result; 12391 12392 ASSERT(elem->what == FCP_ONLINE || 12393 elem->what == FCP_OFFLINE || 12394 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12395 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12396 12397 mutex_enter(&pptr->port_mutex); 12398 mutex_enter(&plun->lun_mutex); 12399 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12400 plun->lun_event_count != elem->event_cnt) || 12401 pptr->port_state & (FCP_STATE_SUSPENDED | 12402 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12403 mutex_exit(&plun->lun_mutex); 12404 mutex_exit(&pptr->port_mutex); 12405 fcp_process_elem(elem, NDI_FAILURE); 12406 return; 12407 } 12408 mutex_exit(&plun->lun_mutex); 12409 mutex_exit(&pptr->port_mutex); 12410 12411 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12412 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12413 fcp_process_elem(elem, result); 12414 } 12415 12416 12417 static child_info_t * 12418 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12419 int tcount) 12420 { 12421 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12422 12423 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12424 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12425 12426 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12427 /* 12428 * Child has not been created yet. Create the child device 12429 * based on the per-Lun flags. 12430 */ 12431 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12432 plun->lun_cip = 12433 CIP(fcp_create_dip(plun, lcount, tcount)); 12434 plun->lun_mpxio = 0; 12435 } else { 12436 plun->lun_cip = 12437 CIP(fcp_create_pip(plun, lcount, tcount)); 12438 plun->lun_mpxio = 1; 12439 } 12440 } else { 12441 plun->lun_cip = cip; 12442 } 12443 12444 return (plun->lun_cip); 12445 } 12446 12447 12448 static int 12449 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12450 { 12451 int rval = FC_FAILURE; 12452 dev_info_t *pdip; 12453 struct dev_info *dip; 12454 int circular; 12455 12456 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12457 12458 pdip = plun->lun_tgt->tgt_port->port_dip; 12459 12460 if (plun->lun_cip == NULL) { 12461 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12462 fcp_trace, FCP_BUF_LEVEL_3, 0, 12463 "fcp_is_dip_present: plun->lun_cip is NULL: " 12464 "plun: %p lun state: %x num: %d target state: %x", 12465 plun, plun->lun_state, plun->lun_num, 12466 plun->lun_tgt->tgt_port->port_state); 12467 return (rval); 12468 } 12469 ndi_devi_enter(pdip, &circular); 12470 dip = DEVI(pdip)->devi_child; 12471 while (dip) { 12472 if (dip == DEVI(cdip)) { 12473 rval = FC_SUCCESS; 12474 break; 12475 } 12476 dip = dip->devi_sibling; 12477 } 12478 ndi_devi_exit(pdip, circular); 12479 return (rval); 12480 } 12481 12482 static int 12483 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12484 { 12485 int rval = FC_FAILURE; 12486 12487 ASSERT(plun != NULL); 12488 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12489 12490 if (plun->lun_mpxio == 0) { 12491 rval = fcp_is_dip_present(plun, DIP(cip)); 12492 } else { 12493 rval = fcp_is_pip_present(plun, PIP(cip)); 12494 } 12495 12496 return (rval); 12497 } 12498 12499 /* 12500 * Function: fcp_create_dip 12501 * 12502 * Description: Creates a dev_info_t structure for the LUN specified by the 12503 * caller. 12504 * 12505 * Argument: plun Lun structure 12506 * link_cnt Link state count. 12507 * tgt_cnt Target state change count. 12508 * 12509 * Return Value: NULL if it failed 12510 * dev_info_t structure address if it succeeded 12511 * 12512 * Context: Kernel context 12513 */ 12514 static dev_info_t * 12515 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12516 { 12517 int failure = 0; 12518 uint32_t tgt_id; 12519 uint64_t sam_lun; 12520 struct fcp_tgt *ptgt = plun->lun_tgt; 12521 struct fcp_port *pptr = ptgt->tgt_port; 12522 dev_info_t *pdip = pptr->port_dip; 12523 dev_info_t *cdip = NULL; 12524 dev_info_t *old_dip = DIP(plun->lun_cip); 12525 char *nname = NULL; 12526 char **compatible = NULL; 12527 int ncompatible; 12528 char *scsi_binding_set; 12529 char t_pwwn[17]; 12530 12531 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12532 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12533 12534 /* get the 'scsi-binding-set' property */ 12535 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12536 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12537 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12538 scsi_binding_set = NULL; 12539 } 12540 12541 /* determine the node name and compatible */ 12542 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12543 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12544 if (scsi_binding_set) { 12545 ddi_prop_free(scsi_binding_set); 12546 } 12547 12548 if (nname == NULL) { 12549 #ifdef DEBUG 12550 cmn_err(CE_WARN, "%s%d: no driver for " 12551 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12552 " compatible: %s", 12553 ddi_driver_name(pdip), ddi_get_instance(pdip), 12554 ptgt->tgt_port_wwn.raw_wwn[0], 12555 ptgt->tgt_port_wwn.raw_wwn[1], 12556 ptgt->tgt_port_wwn.raw_wwn[2], 12557 ptgt->tgt_port_wwn.raw_wwn[3], 12558 ptgt->tgt_port_wwn.raw_wwn[4], 12559 ptgt->tgt_port_wwn.raw_wwn[5], 12560 ptgt->tgt_port_wwn.raw_wwn[6], 12561 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12562 *compatible); 12563 #endif /* DEBUG */ 12564 failure++; 12565 goto end_of_fcp_create_dip; 12566 } 12567 12568 cdip = fcp_find_existing_dip(plun, pdip, nname); 12569 12570 /* 12571 * if the old_dip does not match the cdip, that means there is 12572 * some property change. since we'll be using the cdip, we need 12573 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12574 * then the dtype for the device has been updated. Offline the 12575 * the old device and create a new device with the new device type 12576 * Refer to bug: 4764752 12577 */ 12578 if (old_dip && (cdip != old_dip || 12579 plun->lun_state & FCP_LUN_CHANGED)) { 12580 plun->lun_state &= ~(FCP_LUN_INIT); 12581 mutex_exit(&plun->lun_mutex); 12582 mutex_exit(&pptr->port_mutex); 12583 12584 mutex_enter(&ptgt->tgt_mutex); 12585 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12586 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12587 mutex_exit(&ptgt->tgt_mutex); 12588 12589 #ifdef DEBUG 12590 if (cdip != NULL) { 12591 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12592 fcp_trace, FCP_BUF_LEVEL_2, 0, 12593 "Old dip=%p; New dip=%p don't match", old_dip, 12594 cdip); 12595 } else { 12596 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12597 fcp_trace, FCP_BUF_LEVEL_2, 0, 12598 "Old dip=%p; New dip=NULL don't match", old_dip); 12599 } 12600 #endif 12601 12602 mutex_enter(&pptr->port_mutex); 12603 mutex_enter(&plun->lun_mutex); 12604 } 12605 12606 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12607 plun->lun_state &= ~(FCP_LUN_CHANGED); 12608 if (ndi_devi_alloc(pptr->port_dip, nname, 12609 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12610 failure++; 12611 goto end_of_fcp_create_dip; 12612 } 12613 } 12614 12615 /* 12616 * Previously all the properties for the devinfo were destroyed here 12617 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12618 * the devid property (and other properties established by the target 12619 * driver or framework) which the code does not always recreate, this 12620 * call was removed. 12621 * This opens a theoretical possibility that we may return with a 12622 * stale devid on the node if the scsi entity behind the fibre channel 12623 * lun has changed. 12624 */ 12625 12626 /* decorate the node with compatible */ 12627 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12628 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12629 failure++; 12630 goto end_of_fcp_create_dip; 12631 } 12632 12633 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12634 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12635 failure++; 12636 goto end_of_fcp_create_dip; 12637 } 12638 12639 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12640 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12641 failure++; 12642 goto end_of_fcp_create_dip; 12643 } 12644 12645 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12646 t_pwwn[16] = '\0'; 12647 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12648 != DDI_PROP_SUCCESS) { 12649 failure++; 12650 goto end_of_fcp_create_dip; 12651 } 12652 12653 /* 12654 * If there is no hard address - We might have to deal with 12655 * that by using WWN - Having said that it is important to 12656 * recognize this problem early so ssd can be informed of 12657 * the right interconnect type. 12658 */ 12659 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12660 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12661 } else { 12662 tgt_id = ptgt->tgt_d_id; 12663 } 12664 12665 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12666 tgt_id) != DDI_PROP_SUCCESS) { 12667 failure++; 12668 goto end_of_fcp_create_dip; 12669 } 12670 12671 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12672 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12673 failure++; 12674 goto end_of_fcp_create_dip; 12675 } 12676 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12677 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12678 sam_lun) != DDI_PROP_SUCCESS) { 12679 failure++; 12680 goto end_of_fcp_create_dip; 12681 } 12682 12683 end_of_fcp_create_dip: 12684 scsi_hba_nodename_compatible_free(nname, compatible); 12685 12686 if (cdip != NULL && failure) { 12687 (void) ndi_prop_remove_all(cdip); 12688 (void) ndi_devi_free(cdip); 12689 cdip = NULL; 12690 } 12691 12692 return (cdip); 12693 } 12694 12695 /* 12696 * Function: fcp_create_pip 12697 * 12698 * Description: Creates a Path Id for the LUN specified by the caller. 12699 * 12700 * Argument: plun Lun structure 12701 * link_cnt Link state count. 12702 * tgt_cnt Target state count. 12703 * 12704 * Return Value: NULL if it failed 12705 * mdi_pathinfo_t structure address if it succeeded 12706 * 12707 * Context: Kernel context 12708 */ 12709 static mdi_pathinfo_t * 12710 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12711 { 12712 int i; 12713 char buf[MAXNAMELEN]; 12714 char uaddr[MAXNAMELEN]; 12715 int failure = 0; 12716 uint32_t tgt_id; 12717 uint64_t sam_lun; 12718 struct fcp_tgt *ptgt = plun->lun_tgt; 12719 struct fcp_port *pptr = ptgt->tgt_port; 12720 dev_info_t *pdip = pptr->port_dip; 12721 mdi_pathinfo_t *pip = NULL; 12722 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12723 char *nname = NULL; 12724 char **compatible = NULL; 12725 int ncompatible; 12726 char *scsi_binding_set; 12727 char t_pwwn[17]; 12728 12729 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12730 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12731 12732 scsi_binding_set = "vhci"; 12733 12734 /* determine the node name and compatible */ 12735 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12736 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12737 12738 if (nname == NULL) { 12739 #ifdef DEBUG 12740 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12741 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12742 " compatible: %s", 12743 ddi_driver_name(pdip), ddi_get_instance(pdip), 12744 ptgt->tgt_port_wwn.raw_wwn[0], 12745 ptgt->tgt_port_wwn.raw_wwn[1], 12746 ptgt->tgt_port_wwn.raw_wwn[2], 12747 ptgt->tgt_port_wwn.raw_wwn[3], 12748 ptgt->tgt_port_wwn.raw_wwn[4], 12749 ptgt->tgt_port_wwn.raw_wwn[5], 12750 ptgt->tgt_port_wwn.raw_wwn[6], 12751 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12752 *compatible); 12753 #endif /* DEBUG */ 12754 failure++; 12755 goto end_of_fcp_create_pip; 12756 } 12757 12758 pip = fcp_find_existing_pip(plun, pdip); 12759 12760 /* 12761 * if the old_dip does not match the cdip, that means there is 12762 * some property change. since we'll be using the cdip, we need 12763 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12764 * then the dtype for the device has been updated. Offline the 12765 * the old device and create a new device with the new device type 12766 * Refer to bug: 4764752 12767 */ 12768 if (old_pip && (pip != old_pip || 12769 plun->lun_state & FCP_LUN_CHANGED)) { 12770 plun->lun_state &= ~(FCP_LUN_INIT); 12771 mutex_exit(&plun->lun_mutex); 12772 mutex_exit(&pptr->port_mutex); 12773 12774 mutex_enter(&ptgt->tgt_mutex); 12775 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12776 FCP_OFFLINE, lcount, tcount, 12777 NDI_DEVI_REMOVE, 0); 12778 mutex_exit(&ptgt->tgt_mutex); 12779 12780 if (pip != NULL) { 12781 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12782 fcp_trace, FCP_BUF_LEVEL_2, 0, 12783 "Old pip=%p; New pip=%p don't match", 12784 old_pip, pip); 12785 } else { 12786 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12787 fcp_trace, FCP_BUF_LEVEL_2, 0, 12788 "Old pip=%p; New pip=NULL don't match", 12789 old_pip); 12790 } 12791 12792 mutex_enter(&pptr->port_mutex); 12793 mutex_enter(&plun->lun_mutex); 12794 } 12795 12796 /* 12797 * Since FC_WWN_SIZE is 8 bytes and its not like the 12798 * lun_guid_size which is dependent on the target, I don't 12799 * believe the same trancation happens here UNLESS the standards 12800 * change the FC_WWN_SIZE value to something larger than 12801 * MAXNAMELEN(currently 255 bytes). 12802 */ 12803 12804 for (i = 0; i < FC_WWN_SIZE; i++) { 12805 (void) sprintf(&buf[i << 1], "%02x", 12806 ptgt->tgt_port_wwn.raw_wwn[i]); 12807 } 12808 12809 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12810 buf, plun->lun_num); 12811 12812 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12813 /* 12814 * Release the locks before calling into 12815 * mdi_pi_alloc_compatible() since this can result in a 12816 * callback into fcp which can result in a deadlock 12817 * (see bug # 4870272). 12818 * 12819 * Basically, what we are trying to avoid is the scenario where 12820 * one thread does ndi_devi_enter() and tries to grab 12821 * fcp_mutex and another does it the other way round. 12822 * 12823 * But before we do that, make sure that nobody releases the 12824 * port in the meantime. We can do this by setting a flag. 12825 */ 12826 plun->lun_state &= ~(FCP_LUN_CHANGED); 12827 pptr->port_state |= FCP_STATE_IN_MDI; 12828 mutex_exit(&plun->lun_mutex); 12829 mutex_exit(&pptr->port_mutex); 12830 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12831 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12832 fcp_log(CE_WARN, pptr->port_dip, 12833 "!path alloc failed:0x%x", plun); 12834 mutex_enter(&pptr->port_mutex); 12835 mutex_enter(&plun->lun_mutex); 12836 pptr->port_state &= ~FCP_STATE_IN_MDI; 12837 failure++; 12838 goto end_of_fcp_create_pip; 12839 } 12840 mutex_enter(&pptr->port_mutex); 12841 mutex_enter(&plun->lun_mutex); 12842 pptr->port_state &= ~FCP_STATE_IN_MDI; 12843 } else { 12844 (void) mdi_prop_remove(pip, NULL); 12845 } 12846 12847 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12848 12849 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12850 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12851 != DDI_PROP_SUCCESS) { 12852 failure++; 12853 goto end_of_fcp_create_pip; 12854 } 12855 12856 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12857 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12858 != DDI_PROP_SUCCESS) { 12859 failure++; 12860 goto end_of_fcp_create_pip; 12861 } 12862 12863 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12864 t_pwwn[16] = '\0'; 12865 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12866 != DDI_PROP_SUCCESS) { 12867 failure++; 12868 goto end_of_fcp_create_pip; 12869 } 12870 12871 /* 12872 * If there is no hard address - We might have to deal with 12873 * that by using WWN - Having said that it is important to 12874 * recognize this problem early so ssd can be informed of 12875 * the right interconnect type. 12876 */ 12877 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12878 ptgt->tgt_hard_addr != 0) { 12879 tgt_id = (uint32_t) 12880 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12881 } else { 12882 tgt_id = ptgt->tgt_d_id; 12883 } 12884 12885 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12886 != DDI_PROP_SUCCESS) { 12887 failure++; 12888 goto end_of_fcp_create_pip; 12889 } 12890 12891 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12892 != DDI_PROP_SUCCESS) { 12893 failure++; 12894 goto end_of_fcp_create_pip; 12895 } 12896 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12897 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12898 != DDI_PROP_SUCCESS) { 12899 failure++; 12900 goto end_of_fcp_create_pip; 12901 } 12902 12903 end_of_fcp_create_pip: 12904 scsi_hba_nodename_compatible_free(nname, compatible); 12905 12906 if (pip != NULL && failure) { 12907 (void) mdi_prop_remove(pip, NULL); 12908 mutex_exit(&plun->lun_mutex); 12909 mutex_exit(&pptr->port_mutex); 12910 (void) mdi_pi_free(pip, 0); 12911 mutex_enter(&pptr->port_mutex); 12912 mutex_enter(&plun->lun_mutex); 12913 pip = NULL; 12914 } 12915 12916 return (pip); 12917 } 12918 12919 static dev_info_t * 12920 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12921 { 12922 uint_t nbytes; 12923 uchar_t *bytes; 12924 uint_t nwords; 12925 uint32_t tgt_id; 12926 int *words; 12927 dev_info_t *cdip; 12928 dev_info_t *ndip; 12929 struct fcp_tgt *ptgt = plun->lun_tgt; 12930 struct fcp_port *pptr = ptgt->tgt_port; 12931 int circular; 12932 12933 ndi_devi_enter(pdip, &circular); 12934 12935 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12936 while ((cdip = ndip) != NULL) { 12937 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12938 12939 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12940 continue; 12941 } 12942 12943 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12944 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12945 &nbytes) != DDI_PROP_SUCCESS) { 12946 continue; 12947 } 12948 12949 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12950 if (bytes != NULL) { 12951 ddi_prop_free(bytes); 12952 } 12953 continue; 12954 } 12955 ASSERT(bytes != NULL); 12956 12957 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12958 ddi_prop_free(bytes); 12959 continue; 12960 } 12961 12962 ddi_prop_free(bytes); 12963 12964 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12965 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12966 &nbytes) != DDI_PROP_SUCCESS) { 12967 continue; 12968 } 12969 12970 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12971 if (bytes != NULL) { 12972 ddi_prop_free(bytes); 12973 } 12974 continue; 12975 } 12976 ASSERT(bytes != NULL); 12977 12978 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12979 ddi_prop_free(bytes); 12980 continue; 12981 } 12982 12983 ddi_prop_free(bytes); 12984 12985 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12986 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12987 &nwords) != DDI_PROP_SUCCESS) { 12988 continue; 12989 } 12990 12991 if (nwords != 1 || words == NULL) { 12992 if (words != NULL) { 12993 ddi_prop_free(words); 12994 } 12995 continue; 12996 } 12997 ASSERT(words != NULL); 12998 12999 /* 13000 * If there is no hard address - We might have to deal with 13001 * that by using WWN - Having said that it is important to 13002 * recognize this problem early so ssd can be informed of 13003 * the right interconnect type. 13004 */ 13005 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 13006 ptgt->tgt_hard_addr != 0) { 13007 tgt_id = 13008 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 13009 } else { 13010 tgt_id = ptgt->tgt_d_id; 13011 } 13012 13013 if (tgt_id != (uint32_t)*words) { 13014 ddi_prop_free(words); 13015 continue; 13016 } 13017 ddi_prop_free(words); 13018 13019 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 13020 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 13021 &nwords) != DDI_PROP_SUCCESS) { 13022 continue; 13023 } 13024 13025 if (nwords != 1 || words == NULL) { 13026 if (words != NULL) { 13027 ddi_prop_free(words); 13028 } 13029 continue; 13030 } 13031 ASSERT(words != NULL); 13032 13033 if (plun->lun_num == (uint16_t)*words) { 13034 ddi_prop_free(words); 13035 break; 13036 } 13037 ddi_prop_free(words); 13038 } 13039 ndi_devi_exit(pdip, circular); 13040 13041 return (cdip); 13042 } 13043 13044 13045 static int 13046 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 13047 { 13048 dev_info_t *pdip; 13049 char buf[MAXNAMELEN]; 13050 char uaddr[MAXNAMELEN]; 13051 int rval = FC_FAILURE; 13052 13053 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13054 13055 pdip = plun->lun_tgt->tgt_port->port_dip; 13056 13057 /* 13058 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13059 * non-NULL even when the LUN is not there as in the case when a LUN is 13060 * configured and then deleted on the device end (for T3/T4 case). In 13061 * such cases, pip will be NULL. 13062 * 13063 * If the device generates an RSCN, it will end up getting offlined when 13064 * it disappeared and a new LUN will get created when it is rediscovered 13065 * on the device. If we check for lun_cip here, the LUN will not end 13066 * up getting onlined since this function will end up returning a 13067 * FC_SUCCESS. 13068 * 13069 * The behavior is different on other devices. For instance, on a HDS, 13070 * there was no RSCN generated by the device but the next I/O generated 13071 * a check condition and rediscovery got triggered that way. So, in 13072 * such cases, this path will not be exercised 13073 */ 13074 if (pip == NULL) { 13075 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13076 fcp_trace, FCP_BUF_LEVEL_4, 0, 13077 "fcp_is_pip_present: plun->lun_cip is NULL: " 13078 "plun: %p lun state: %x num: %d target state: %x", 13079 plun, plun->lun_state, plun->lun_num, 13080 plun->lun_tgt->tgt_port->port_state); 13081 return (rval); 13082 } 13083 13084 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13085 13086 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13087 13088 if (plun->lun_old_guid) { 13089 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 13090 rval = FC_SUCCESS; 13091 } 13092 } else { 13093 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 13094 rval = FC_SUCCESS; 13095 } 13096 } 13097 return (rval); 13098 } 13099 13100 static mdi_pathinfo_t * 13101 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13102 { 13103 char buf[MAXNAMELEN]; 13104 char uaddr[MAXNAMELEN]; 13105 mdi_pathinfo_t *pip; 13106 struct fcp_tgt *ptgt = plun->lun_tgt; 13107 struct fcp_port *pptr = ptgt->tgt_port; 13108 13109 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13110 13111 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13112 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13113 13114 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13115 13116 return (pip); 13117 } 13118 13119 13120 static int 13121 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13122 int tcount, int flags, int *circ) 13123 { 13124 int rval; 13125 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13126 struct fcp_tgt *ptgt = plun->lun_tgt; 13127 dev_info_t *cdip = NULL; 13128 13129 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13130 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13131 13132 if (plun->lun_cip == NULL) { 13133 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13134 fcp_trace, FCP_BUF_LEVEL_3, 0, 13135 "fcp_online_child: plun->lun_cip is NULL: " 13136 "plun: %p state: %x num: %d target state: %x", 13137 plun, plun->lun_state, plun->lun_num, 13138 plun->lun_tgt->tgt_port->port_state); 13139 return (NDI_FAILURE); 13140 } 13141 again: 13142 if (plun->lun_mpxio == 0) { 13143 cdip = DIP(cip); 13144 mutex_exit(&plun->lun_mutex); 13145 mutex_exit(&pptr->port_mutex); 13146 13147 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13148 fcp_trace, FCP_BUF_LEVEL_3, 0, 13149 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13150 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13151 13152 /* 13153 * We could check for FCP_LUN_INIT here but chances 13154 * of getting here when it's already in FCP_LUN_INIT 13155 * is rare and a duplicate ndi_devi_online wouldn't 13156 * hurt either (as the node would already have been 13157 * in CF2) 13158 */ 13159 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13160 rval = ndi_devi_bind_driver(cdip, flags); 13161 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13162 fcp_trace, FCP_BUF_LEVEL_3, 0, 13163 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13164 } else { 13165 rval = ndi_devi_online(cdip, flags); 13166 } 13167 13168 /* 13169 * We log the message into trace buffer if the device 13170 * is "ses" and into syslog for any other device 13171 * type. This is to prevent the ndi_devi_online failure 13172 * message that appears for V880/A5K ses devices. 13173 */ 13174 if (rval == NDI_SUCCESS) { 13175 mutex_enter(&ptgt->tgt_mutex); 13176 plun->lun_state |= FCP_LUN_INIT; 13177 mutex_exit(&ptgt->tgt_mutex); 13178 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13179 fcp_log(CE_NOTE, pptr->port_dip, 13180 "!ndi_devi_online:" 13181 " failed for %s: target=%x lun=%x %x", 13182 ddi_get_name(cdip), ptgt->tgt_d_id, 13183 plun->lun_num, rval); 13184 } else { 13185 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13186 fcp_trace, FCP_BUF_LEVEL_3, 0, 13187 " !ndi_devi_online:" 13188 " failed for %s: target=%x lun=%x %x", 13189 ddi_get_name(cdip), ptgt->tgt_d_id, 13190 plun->lun_num, rval); 13191 } 13192 } else { 13193 cdip = mdi_pi_get_client(PIP(cip)); 13194 mutex_exit(&plun->lun_mutex); 13195 mutex_exit(&pptr->port_mutex); 13196 13197 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13198 fcp_trace, FCP_BUF_LEVEL_3, 0, 13199 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13200 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13201 13202 /* 13203 * Hold path and exit phci to avoid deadlock with power 13204 * management code during mdi_pi_online. 13205 */ 13206 mdi_hold_path(PIP(cip)); 13207 mdi_devi_exit_phci(pptr->port_dip, *circ); 13208 13209 rval = mdi_pi_online(PIP(cip), flags); 13210 13211 mdi_devi_enter_phci(pptr->port_dip, circ); 13212 mdi_rele_path(PIP(cip)); 13213 13214 if (rval == MDI_SUCCESS) { 13215 mutex_enter(&ptgt->tgt_mutex); 13216 plun->lun_state |= FCP_LUN_INIT; 13217 mutex_exit(&ptgt->tgt_mutex); 13218 13219 /* 13220 * Clear MPxIO path permanent disable in case 13221 * fcp hotplug dropped the offline event. 13222 */ 13223 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13224 13225 } else if (rval == MDI_NOT_SUPPORTED) { 13226 child_info_t *old_cip = cip; 13227 13228 /* 13229 * MPxIO does not support this device yet. 13230 * Enumerate in legacy mode. 13231 */ 13232 mutex_enter(&pptr->port_mutex); 13233 mutex_enter(&plun->lun_mutex); 13234 plun->lun_mpxio = 0; 13235 plun->lun_cip = NULL; 13236 cdip = fcp_create_dip(plun, lcount, tcount); 13237 plun->lun_cip = cip = CIP(cdip); 13238 if (cip == NULL) { 13239 fcp_log(CE_WARN, pptr->port_dip, 13240 "!fcp_online_child: " 13241 "Create devinfo failed for LU=%p", plun); 13242 mutex_exit(&plun->lun_mutex); 13243 13244 mutex_enter(&ptgt->tgt_mutex); 13245 plun->lun_state |= FCP_LUN_OFFLINE; 13246 mutex_exit(&ptgt->tgt_mutex); 13247 13248 mutex_exit(&pptr->port_mutex); 13249 13250 /* 13251 * free the mdi_pathinfo node 13252 */ 13253 (void) mdi_pi_free(PIP(old_cip), 0); 13254 } else { 13255 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13256 fcp_trace, FCP_BUF_LEVEL_3, 0, 13257 "fcp_online_child: creating devinfo " 13258 "node 0x%p for plun 0x%p", 13259 cip, plun); 13260 mutex_exit(&plun->lun_mutex); 13261 mutex_exit(&pptr->port_mutex); 13262 /* 13263 * free the mdi_pathinfo node 13264 */ 13265 (void) mdi_pi_free(PIP(old_cip), 0); 13266 mutex_enter(&pptr->port_mutex); 13267 mutex_enter(&plun->lun_mutex); 13268 goto again; 13269 } 13270 } else { 13271 if (cdip) { 13272 fcp_log(CE_NOTE, pptr->port_dip, 13273 "!fcp_online_child: mdi_pi_online:" 13274 " failed for %s: target=%x lun=%x %x", 13275 ddi_get_name(cdip), ptgt->tgt_d_id, 13276 plun->lun_num, rval); 13277 } 13278 } 13279 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13280 } 13281 13282 if (rval == NDI_SUCCESS) { 13283 if (cdip) { 13284 (void) ndi_event_retrieve_cookie( 13285 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13286 &fcp_insert_eid, NDI_EVENT_NOPASS); 13287 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13288 cdip, fcp_insert_eid, NULL); 13289 } 13290 } 13291 mutex_enter(&pptr->port_mutex); 13292 mutex_enter(&plun->lun_mutex); 13293 return (rval); 13294 } 13295 13296 /* ARGSUSED */ 13297 static int 13298 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13299 int tcount, int flags, int *circ) 13300 { 13301 int rval; 13302 int lun_mpxio; 13303 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13304 struct fcp_tgt *ptgt = plun->lun_tgt; 13305 dev_info_t *cdip; 13306 13307 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13308 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13309 13310 if (plun->lun_cip == NULL) { 13311 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13312 fcp_trace, FCP_BUF_LEVEL_3, 0, 13313 "fcp_offline_child: plun->lun_cip is NULL: " 13314 "plun: %p lun state: %x num: %d target state: %x", 13315 plun, plun->lun_state, plun->lun_num, 13316 plun->lun_tgt->tgt_port->port_state); 13317 return (NDI_FAILURE); 13318 } 13319 13320 /* 13321 * We will use this value twice. Make a copy to be sure we use 13322 * the same value in both places. 13323 */ 13324 lun_mpxio = plun->lun_mpxio; 13325 13326 if (lun_mpxio == 0) { 13327 cdip = DIP(cip); 13328 mutex_exit(&plun->lun_mutex); 13329 mutex_exit(&pptr->port_mutex); 13330 rval = ndi_devi_offline(DIP(cip), flags); 13331 if (rval != NDI_SUCCESS) { 13332 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13333 fcp_trace, FCP_BUF_LEVEL_3, 0, 13334 "fcp_offline_child: ndi_devi_offline failed " 13335 "rval=%x cip=%p", rval, cip); 13336 } 13337 } else { 13338 cdip = mdi_pi_get_client(PIP(cip)); 13339 mutex_exit(&plun->lun_mutex); 13340 mutex_exit(&pptr->port_mutex); 13341 13342 /* 13343 * Exit phci to avoid deadlock with power management code 13344 * during mdi_pi_offline 13345 */ 13346 mdi_hold_path(PIP(cip)); 13347 mdi_devi_exit_phci(pptr->port_dip, *circ); 13348 13349 rval = mdi_pi_offline(PIP(cip), flags); 13350 13351 mdi_devi_enter_phci(pptr->port_dip, circ); 13352 mdi_rele_path(PIP(cip)); 13353 13354 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13355 } 13356 13357 mutex_enter(&ptgt->tgt_mutex); 13358 plun->lun_state &= ~FCP_LUN_INIT; 13359 mutex_exit(&ptgt->tgt_mutex); 13360 13361 if (rval == NDI_SUCCESS) { 13362 cdip = NULL; 13363 if (flags & NDI_DEVI_REMOVE) { 13364 mutex_enter(&plun->lun_mutex); 13365 /* 13366 * If the guid of the LUN changes, lun_cip will not 13367 * equal to cip, and after offlining the LUN with the 13368 * old guid, we should keep lun_cip since it's the cip 13369 * of the LUN with the new guid. 13370 * Otherwise remove our reference to child node. 13371 * 13372 * This must be done before the child node is freed, 13373 * otherwise other threads could see a stale lun_cip 13374 * pointer. 13375 */ 13376 if (plun->lun_cip == cip) { 13377 plun->lun_cip = NULL; 13378 } 13379 if (plun->lun_old_guid) { 13380 kmem_free(plun->lun_old_guid, 13381 plun->lun_old_guid_size); 13382 plun->lun_old_guid = NULL; 13383 plun->lun_old_guid_size = 0; 13384 } 13385 mutex_exit(&plun->lun_mutex); 13386 } 13387 } 13388 13389 if (lun_mpxio != 0) { 13390 if (rval == NDI_SUCCESS) { 13391 /* 13392 * Clear MPxIO path permanent disable as the path is 13393 * already offlined. 13394 */ 13395 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13396 13397 if (flags & NDI_DEVI_REMOVE) { 13398 (void) mdi_pi_free(PIP(cip), 0); 13399 } 13400 } else { 13401 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13402 fcp_trace, FCP_BUF_LEVEL_3, 0, 13403 "fcp_offline_child: mdi_pi_offline failed " 13404 "rval=%x cip=%p", rval, cip); 13405 } 13406 } 13407 13408 mutex_enter(&pptr->port_mutex); 13409 mutex_enter(&plun->lun_mutex); 13410 13411 if (cdip) { 13412 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13413 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13414 " target=%x lun=%x", "ndi_offline", 13415 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13416 } 13417 13418 return (rval); 13419 } 13420 13421 static void 13422 fcp_remove_child(struct fcp_lun *plun) 13423 { 13424 child_info_t *cip; 13425 int circ; 13426 13427 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13428 13429 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13430 if (plun->lun_mpxio == 0) { 13431 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13432 (void) ndi_devi_free(DIP(plun->lun_cip)); 13433 plun->lun_cip = NULL; 13434 } else { 13435 /* 13436 * Clear reference to the child node in the lun. 13437 * This must be done before freeing it with mdi_pi_free 13438 * and with lun_mutex held so that other threads always 13439 * see either valid lun_cip or NULL when holding 13440 * lun_mutex. We keep a copy in cip. 13441 */ 13442 cip = plun->lun_cip; 13443 plun->lun_cip = NULL; 13444 13445 mutex_exit(&plun->lun_mutex); 13446 mutex_exit(&plun->lun_tgt->tgt_mutex); 13447 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13448 13449 mdi_devi_enter( 13450 plun->lun_tgt->tgt_port->port_dip, &circ); 13451 13452 /* 13453 * Exit phci to avoid deadlock with power management 13454 * code during mdi_pi_offline 13455 */ 13456 mdi_hold_path(PIP(cip)); 13457 mdi_devi_exit_phci( 13458 plun->lun_tgt->tgt_port->port_dip, circ); 13459 (void) mdi_pi_offline(PIP(cip), 13460 NDI_DEVI_REMOVE); 13461 mdi_devi_enter_phci( 13462 plun->lun_tgt->tgt_port->port_dip, &circ); 13463 mdi_rele_path(PIP(cip)); 13464 13465 mdi_devi_exit( 13466 plun->lun_tgt->tgt_port->port_dip, circ); 13467 13468 FCP_TRACE(fcp_logq, 13469 plun->lun_tgt->tgt_port->port_instbuf, 13470 fcp_trace, FCP_BUF_LEVEL_3, 0, 13471 "lun=%p pip freed %p", plun, cip); 13472 13473 (void) mdi_prop_remove(PIP(cip), NULL); 13474 (void) mdi_pi_free(PIP(cip), 0); 13475 13476 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13477 mutex_enter(&plun->lun_tgt->tgt_mutex); 13478 mutex_enter(&plun->lun_mutex); 13479 } 13480 } else { 13481 plun->lun_cip = NULL; 13482 } 13483 } 13484 13485 /* 13486 * called when a timeout occurs 13487 * 13488 * can be scheduled during an attach or resume (if not already running) 13489 * 13490 * one timeout is set up for all ports 13491 * 13492 * acquires and releases the global mutex 13493 */ 13494 /*ARGSUSED*/ 13495 static void 13496 fcp_watch(void *arg) 13497 { 13498 struct fcp_port *pptr; 13499 struct fcp_ipkt *icmd; 13500 struct fcp_ipkt *nicmd; 13501 struct fcp_pkt *cmd; 13502 struct fcp_pkt *ncmd; 13503 struct fcp_pkt *tail; 13504 struct fcp_pkt *pcmd; 13505 struct fcp_pkt *save_head; 13506 struct fcp_port *save_port; 13507 13508 /* increment global watchdog time */ 13509 fcp_watchdog_time += fcp_watchdog_timeout; 13510 13511 mutex_enter(&fcp_global_mutex); 13512 13513 /* scan each port in our list */ 13514 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13515 save_port = fcp_port_head; 13516 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13517 mutex_exit(&fcp_global_mutex); 13518 13519 mutex_enter(&pptr->port_mutex); 13520 if (pptr->port_ipkt_list == NULL && 13521 (pptr->port_state & (FCP_STATE_SUSPENDED | 13522 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13523 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13524 mutex_exit(&pptr->port_mutex); 13525 mutex_enter(&fcp_global_mutex); 13526 goto end_of_watchdog; 13527 } 13528 13529 /* 13530 * We check if a list of targets need to be offlined. 13531 */ 13532 if (pptr->port_offline_tgts) { 13533 fcp_scan_offline_tgts(pptr); 13534 } 13535 13536 /* 13537 * We check if a list of luns need to be offlined. 13538 */ 13539 if (pptr->port_offline_luns) { 13540 fcp_scan_offline_luns(pptr); 13541 } 13542 13543 /* 13544 * We check if a list of targets or luns need to be reset. 13545 */ 13546 if (pptr->port_reset_list) { 13547 fcp_check_reset_delay(pptr); 13548 } 13549 13550 mutex_exit(&pptr->port_mutex); 13551 13552 /* 13553 * This is where the pending commands (pkt) are checked for 13554 * timeout. 13555 */ 13556 mutex_enter(&pptr->port_pkt_mutex); 13557 tail = pptr->port_pkt_tail; 13558 13559 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13560 cmd != NULL; cmd = ncmd) { 13561 ncmd = cmd->cmd_next; 13562 /* 13563 * If a command is in this queue the bit CFLAG_IN_QUEUE 13564 * must be set. 13565 */ 13566 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13567 /* 13568 * FCP_INVALID_TIMEOUT will be set for those 13569 * command that need to be failed. Mostly those 13570 * cmds that could not be queued down for the 13571 * "timeout" value. cmd->cmd_timeout is used 13572 * to try and requeue the command regularly. 13573 */ 13574 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13575 /* 13576 * This command hasn't timed out yet. Let's 13577 * go to the next one. 13578 */ 13579 pcmd = cmd; 13580 goto end_of_loop; 13581 } 13582 13583 if (cmd == pptr->port_pkt_head) { 13584 ASSERT(pcmd == NULL); 13585 pptr->port_pkt_head = cmd->cmd_next; 13586 } else { 13587 ASSERT(pcmd != NULL); 13588 pcmd->cmd_next = cmd->cmd_next; 13589 } 13590 13591 if (cmd == pptr->port_pkt_tail) { 13592 ASSERT(cmd->cmd_next == NULL); 13593 pptr->port_pkt_tail = pcmd; 13594 if (pcmd) { 13595 pcmd->cmd_next = NULL; 13596 } 13597 } 13598 cmd->cmd_next = NULL; 13599 13600 /* 13601 * save the current head before dropping the 13602 * mutex - If the head doesn't remain the 13603 * same after re acquiring the mutex, just 13604 * bail out and revisit on next tick. 13605 * 13606 * PS: The tail pointer can change as the commands 13607 * get requeued after failure to retransport 13608 */ 13609 save_head = pptr->port_pkt_head; 13610 mutex_exit(&pptr->port_pkt_mutex); 13611 13612 if (cmd->cmd_fp_pkt->pkt_timeout == 13613 FCP_INVALID_TIMEOUT) { 13614 struct scsi_pkt *pkt = cmd->cmd_pkt; 13615 struct fcp_lun *plun; 13616 struct fcp_tgt *ptgt; 13617 13618 plun = ADDR2LUN(&pkt->pkt_address); 13619 ptgt = plun->lun_tgt; 13620 13621 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13622 fcp_trace, FCP_BUF_LEVEL_2, 0, 13623 "SCSI cmd 0x%x to D_ID=%x timed out", 13624 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13625 13626 cmd->cmd_state == FCP_PKT_ABORTING ? 13627 fcp_fail_cmd(cmd, CMD_RESET, 13628 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13629 CMD_TIMEOUT, STAT_ABORTED); 13630 } else { 13631 fcp_retransport_cmd(pptr, cmd); 13632 } 13633 mutex_enter(&pptr->port_pkt_mutex); 13634 if (save_head && save_head != pptr->port_pkt_head) { 13635 /* 13636 * Looks like linked list got changed (mostly 13637 * happens when an an OFFLINE LUN code starts 13638 * returning overflow queue commands in 13639 * parallel. So bail out and revisit during 13640 * next tick 13641 */ 13642 break; 13643 } 13644 end_of_loop: 13645 /* 13646 * Scan only upto the previously known tail pointer 13647 * to avoid excessive processing - lots of new packets 13648 * could have been added to the tail or the old ones 13649 * re-queued. 13650 */ 13651 if (cmd == tail) { 13652 break; 13653 } 13654 } 13655 mutex_exit(&pptr->port_pkt_mutex); 13656 13657 mutex_enter(&pptr->port_mutex); 13658 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13659 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13660 13661 nicmd = icmd->ipkt_next; 13662 if ((icmd->ipkt_restart != 0) && 13663 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13664 /* packet has not timed out */ 13665 continue; 13666 } 13667 13668 /* time for packet re-transport */ 13669 if (icmd == pptr->port_ipkt_list) { 13670 pptr->port_ipkt_list = icmd->ipkt_next; 13671 if (pptr->port_ipkt_list) { 13672 pptr->port_ipkt_list->ipkt_prev = 13673 NULL; 13674 } 13675 } else { 13676 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13677 if (icmd->ipkt_next) { 13678 icmd->ipkt_next->ipkt_prev = 13679 icmd->ipkt_prev; 13680 } 13681 } 13682 icmd->ipkt_next = NULL; 13683 icmd->ipkt_prev = NULL; 13684 mutex_exit(&pptr->port_mutex); 13685 13686 if (fcp_is_retryable(icmd)) { 13687 fc_ulp_rscn_info_t *rscnp = 13688 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13689 pkt_ulp_rscn_infop; 13690 13691 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13692 fcp_trace, FCP_BUF_LEVEL_2, 0, 13693 "%x to D_ID=%x Retrying..", 13694 icmd->ipkt_opcode, 13695 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13696 13697 /* 13698 * Update the RSCN count in the packet 13699 * before resending. 13700 */ 13701 13702 if (rscnp != NULL) { 13703 rscnp->ulp_rscn_count = 13704 fc_ulp_get_rscn_count(pptr-> 13705 port_fp_handle); 13706 } 13707 13708 mutex_enter(&pptr->port_mutex); 13709 mutex_enter(&ptgt->tgt_mutex); 13710 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13711 mutex_exit(&ptgt->tgt_mutex); 13712 mutex_exit(&pptr->port_mutex); 13713 switch (icmd->ipkt_opcode) { 13714 int rval; 13715 case LA_ELS_PLOGI: 13716 if ((rval = fc_ulp_login( 13717 pptr->port_fp_handle, 13718 &icmd->ipkt_fpkt, 1)) == 13719 FC_SUCCESS) { 13720 mutex_enter( 13721 &pptr->port_mutex); 13722 continue; 13723 } 13724 if (fcp_handle_ipkt_errors( 13725 pptr, ptgt, icmd, rval, 13726 "PLOGI") == DDI_SUCCESS) { 13727 mutex_enter( 13728 &pptr->port_mutex); 13729 continue; 13730 } 13731 break; 13732 13733 case LA_ELS_PRLI: 13734 if ((rval = fc_ulp_issue_els( 13735 pptr->port_fp_handle, 13736 icmd->ipkt_fpkt)) == 13737 FC_SUCCESS) { 13738 mutex_enter( 13739 &pptr->port_mutex); 13740 continue; 13741 } 13742 if (fcp_handle_ipkt_errors( 13743 pptr, ptgt, icmd, rval, 13744 "PRLI") == DDI_SUCCESS) { 13745 mutex_enter( 13746 &pptr->port_mutex); 13747 continue; 13748 } 13749 break; 13750 13751 default: 13752 if ((rval = fcp_transport( 13753 pptr->port_fp_handle, 13754 icmd->ipkt_fpkt, 1)) == 13755 FC_SUCCESS) { 13756 mutex_enter( 13757 &pptr->port_mutex); 13758 continue; 13759 } 13760 if (fcp_handle_ipkt_errors( 13761 pptr, ptgt, icmd, rval, 13762 "PRLI") == DDI_SUCCESS) { 13763 mutex_enter( 13764 &pptr->port_mutex); 13765 continue; 13766 } 13767 break; 13768 } 13769 } else { 13770 mutex_exit(&ptgt->tgt_mutex); 13771 mutex_exit(&pptr->port_mutex); 13772 } 13773 } else { 13774 fcp_print_error(icmd->ipkt_fpkt); 13775 } 13776 13777 (void) fcp_call_finish_init(pptr, ptgt, 13778 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13779 icmd->ipkt_cause); 13780 fcp_icmd_free(pptr, icmd); 13781 mutex_enter(&pptr->port_mutex); 13782 } 13783 13784 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13785 mutex_exit(&pptr->port_mutex); 13786 mutex_enter(&fcp_global_mutex); 13787 13788 end_of_watchdog: 13789 /* 13790 * Bail out early before getting into trouble 13791 */ 13792 if (save_port != fcp_port_head) { 13793 break; 13794 } 13795 } 13796 13797 if (fcp_watchdog_init > 0) { 13798 /* reschedule timeout to go again */ 13799 fcp_watchdog_id = 13800 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13801 } 13802 mutex_exit(&fcp_global_mutex); 13803 } 13804 13805 13806 static void 13807 fcp_check_reset_delay(struct fcp_port *pptr) 13808 { 13809 uint32_t tgt_cnt; 13810 int level; 13811 struct fcp_tgt *ptgt; 13812 struct fcp_lun *plun; 13813 struct fcp_reset_elem *cur = NULL; 13814 struct fcp_reset_elem *next = NULL; 13815 struct fcp_reset_elem *prev = NULL; 13816 13817 ASSERT(mutex_owned(&pptr->port_mutex)); 13818 13819 next = pptr->port_reset_list; 13820 while ((cur = next) != NULL) { 13821 next = cur->next; 13822 13823 if (cur->timeout < fcp_watchdog_time) { 13824 prev = cur; 13825 continue; 13826 } 13827 13828 ptgt = cur->tgt; 13829 plun = cur->lun; 13830 tgt_cnt = cur->tgt_cnt; 13831 13832 if (ptgt) { 13833 level = RESET_TARGET; 13834 } else { 13835 ASSERT(plun != NULL); 13836 level = RESET_LUN; 13837 ptgt = plun->lun_tgt; 13838 } 13839 if (prev) { 13840 prev->next = next; 13841 } else { 13842 /* 13843 * Because we drop port mutex while doing aborts for 13844 * packets, we can't rely on reset_list pointing to 13845 * our head 13846 */ 13847 if (cur == pptr->port_reset_list) { 13848 pptr->port_reset_list = next; 13849 } else { 13850 struct fcp_reset_elem *which; 13851 13852 which = pptr->port_reset_list; 13853 while (which && which->next != cur) { 13854 which = which->next; 13855 } 13856 ASSERT(which != NULL); 13857 13858 which->next = next; 13859 prev = which; 13860 } 13861 } 13862 13863 kmem_free(cur, sizeof (*cur)); 13864 13865 if (tgt_cnt == ptgt->tgt_change_cnt) { 13866 mutex_enter(&ptgt->tgt_mutex); 13867 if (level == RESET_TARGET) { 13868 fcp_update_tgt_state(ptgt, 13869 FCP_RESET, FCP_LUN_BUSY); 13870 } else { 13871 fcp_update_lun_state(plun, 13872 FCP_RESET, FCP_LUN_BUSY); 13873 } 13874 mutex_exit(&ptgt->tgt_mutex); 13875 13876 mutex_exit(&pptr->port_mutex); 13877 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13878 mutex_enter(&pptr->port_mutex); 13879 } 13880 } 13881 } 13882 13883 13884 static void 13885 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13886 struct fcp_lun *rlun, int tgt_cnt) 13887 { 13888 int rval; 13889 struct fcp_lun *tlun, *nlun; 13890 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13891 *cmd = NULL, *head = NULL, 13892 *tail = NULL; 13893 13894 mutex_enter(&pptr->port_pkt_mutex); 13895 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13896 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13897 struct fcp_tgt *ptgt = plun->lun_tgt; 13898 13899 ncmd = cmd->cmd_next; 13900 13901 if (ptgt != ttgt && plun != rlun) { 13902 pcmd = cmd; 13903 continue; 13904 } 13905 13906 if (pcmd != NULL) { 13907 ASSERT(pptr->port_pkt_head != cmd); 13908 pcmd->cmd_next = ncmd; 13909 } else { 13910 ASSERT(cmd == pptr->port_pkt_head); 13911 pptr->port_pkt_head = ncmd; 13912 } 13913 if (pptr->port_pkt_tail == cmd) { 13914 ASSERT(cmd->cmd_next == NULL); 13915 pptr->port_pkt_tail = pcmd; 13916 if (pcmd != NULL) { 13917 pcmd->cmd_next = NULL; 13918 } 13919 } 13920 13921 if (head == NULL) { 13922 head = tail = cmd; 13923 } else { 13924 ASSERT(tail != NULL); 13925 tail->cmd_next = cmd; 13926 tail = cmd; 13927 } 13928 cmd->cmd_next = NULL; 13929 } 13930 mutex_exit(&pptr->port_pkt_mutex); 13931 13932 for (cmd = head; cmd != NULL; cmd = ncmd) { 13933 struct scsi_pkt *pkt = cmd->cmd_pkt; 13934 13935 ncmd = cmd->cmd_next; 13936 ASSERT(pkt != NULL); 13937 13938 mutex_enter(&pptr->port_mutex); 13939 if (ttgt->tgt_change_cnt == tgt_cnt) { 13940 mutex_exit(&pptr->port_mutex); 13941 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13942 pkt->pkt_reason = CMD_RESET; 13943 pkt->pkt_statistics |= STAT_DEV_RESET; 13944 cmd->cmd_state = FCP_PKT_IDLE; 13945 fcp_post_callback(cmd); 13946 } else { 13947 mutex_exit(&pptr->port_mutex); 13948 } 13949 } 13950 13951 /* 13952 * If the FCA will return all the commands in its queue then our 13953 * work is easy, just return. 13954 */ 13955 13956 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13957 return; 13958 } 13959 13960 /* 13961 * For RESET_LUN get hold of target pointer 13962 */ 13963 if (ttgt == NULL) { 13964 ASSERT(rlun != NULL); 13965 13966 ttgt = rlun->lun_tgt; 13967 13968 ASSERT(ttgt != NULL); 13969 } 13970 13971 /* 13972 * There are some severe race conditions here. 13973 * While we are trying to abort the pkt, it might be completing 13974 * so mark it aborted and if the abort does not succeed then 13975 * handle it in the watch thread. 13976 */ 13977 mutex_enter(&ttgt->tgt_mutex); 13978 nlun = ttgt->tgt_lun; 13979 mutex_exit(&ttgt->tgt_mutex); 13980 while ((tlun = nlun) != NULL) { 13981 int restart = 0; 13982 if (rlun && rlun != tlun) { 13983 mutex_enter(&ttgt->tgt_mutex); 13984 nlun = tlun->lun_next; 13985 mutex_exit(&ttgt->tgt_mutex); 13986 continue; 13987 } 13988 mutex_enter(&tlun->lun_mutex); 13989 cmd = tlun->lun_pkt_head; 13990 while (cmd != NULL) { 13991 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13992 struct scsi_pkt *pkt; 13993 13994 restart = 1; 13995 cmd->cmd_state = FCP_PKT_ABORTING; 13996 mutex_exit(&tlun->lun_mutex); 13997 rval = fc_ulp_abort(pptr->port_fp_handle, 13998 cmd->cmd_fp_pkt, KM_SLEEP); 13999 if (rval == FC_SUCCESS) { 14000 pkt = cmd->cmd_pkt; 14001 pkt->pkt_reason = CMD_RESET; 14002 pkt->pkt_statistics |= STAT_DEV_RESET; 14003 cmd->cmd_state = FCP_PKT_IDLE; 14004 fcp_post_callback(cmd); 14005 } else { 14006 caddr_t msg; 14007 14008 (void) fc_ulp_error(rval, &msg); 14009 14010 /* 14011 * This part is tricky. The abort 14012 * failed and now the command could 14013 * be completing. The cmd_state == 14014 * FCP_PKT_ABORTING should save 14015 * us in fcp_cmd_callback. If we 14016 * are already aborting ignore the 14017 * command in fcp_cmd_callback. 14018 * Here we leave this packet for 20 14019 * sec to be aborted in the 14020 * fcp_watch thread. 14021 */ 14022 fcp_log(CE_WARN, pptr->port_dip, 14023 "!Abort failed after reset %s", 14024 msg); 14025 14026 cmd->cmd_timeout = 14027 fcp_watchdog_time + 14028 cmd->cmd_pkt->pkt_time + 14029 FCP_FAILED_DELAY; 14030 14031 cmd->cmd_fp_pkt->pkt_timeout = 14032 FCP_INVALID_TIMEOUT; 14033 /* 14034 * This is a hack, cmd is put in the 14035 * overflow queue so that it can be 14036 * timed out finally 14037 */ 14038 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14039 14040 mutex_enter(&pptr->port_pkt_mutex); 14041 if (pptr->port_pkt_head) { 14042 ASSERT(pptr->port_pkt_tail 14043 != NULL); 14044 pptr->port_pkt_tail->cmd_next 14045 = cmd; 14046 pptr->port_pkt_tail = cmd; 14047 } else { 14048 ASSERT(pptr->port_pkt_tail 14049 == NULL); 14050 pptr->port_pkt_head = 14051 pptr->port_pkt_tail 14052 = cmd; 14053 } 14054 cmd->cmd_next = NULL; 14055 mutex_exit(&pptr->port_pkt_mutex); 14056 } 14057 mutex_enter(&tlun->lun_mutex); 14058 cmd = tlun->lun_pkt_head; 14059 } else { 14060 cmd = cmd->cmd_forw; 14061 } 14062 } 14063 mutex_exit(&tlun->lun_mutex); 14064 14065 mutex_enter(&ttgt->tgt_mutex); 14066 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14067 mutex_exit(&ttgt->tgt_mutex); 14068 14069 mutex_enter(&pptr->port_mutex); 14070 if (tgt_cnt != ttgt->tgt_change_cnt) { 14071 mutex_exit(&pptr->port_mutex); 14072 return; 14073 } else { 14074 mutex_exit(&pptr->port_mutex); 14075 } 14076 } 14077 } 14078 14079 14080 /* 14081 * unlink the soft state, returning the soft state found (if any) 14082 * 14083 * acquires and releases the global mutex 14084 */ 14085 struct fcp_port * 14086 fcp_soft_state_unlink(struct fcp_port *pptr) 14087 { 14088 struct fcp_port *hptr; /* ptr index */ 14089 struct fcp_port *tptr; /* prev hptr */ 14090 14091 mutex_enter(&fcp_global_mutex); 14092 for (hptr = fcp_port_head, tptr = NULL; 14093 hptr != NULL; 14094 tptr = hptr, hptr = hptr->port_next) { 14095 if (hptr == pptr) { 14096 /* we found a match -- remove this item */ 14097 if (tptr == NULL) { 14098 /* we're at the head of the list */ 14099 fcp_port_head = hptr->port_next; 14100 } else { 14101 tptr->port_next = hptr->port_next; 14102 } 14103 break; /* success */ 14104 } 14105 } 14106 if (fcp_port_head == NULL) { 14107 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14108 } 14109 mutex_exit(&fcp_global_mutex); 14110 return (hptr); 14111 } 14112 14113 14114 /* 14115 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14116 * WWN and a LUN number 14117 */ 14118 /* ARGSUSED */ 14119 static struct fcp_lun * 14120 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14121 { 14122 int hash; 14123 struct fcp_tgt *ptgt; 14124 struct fcp_lun *plun; 14125 14126 ASSERT(mutex_owned(&pptr->port_mutex)); 14127 14128 hash = FCP_HASH(wwn); 14129 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14130 ptgt = ptgt->tgt_next) { 14131 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14132 sizeof (ptgt->tgt_port_wwn)) == 0) { 14133 mutex_enter(&ptgt->tgt_mutex); 14134 for (plun = ptgt->tgt_lun; 14135 plun != NULL; 14136 plun = plun->lun_next) { 14137 if (plun->lun_num == lun) { 14138 mutex_exit(&ptgt->tgt_mutex); 14139 return (plun); 14140 } 14141 } 14142 mutex_exit(&ptgt->tgt_mutex); 14143 return (NULL); 14144 } 14145 } 14146 return (NULL); 14147 } 14148 14149 /* 14150 * Function: fcp_prepare_pkt 14151 * 14152 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14153 * for fcp_start(). It binds the data or partially maps it. 14154 * Builds the FCP header and starts the initialization of the 14155 * Fibre Channel header. 14156 * 14157 * Argument: *pptr FCP port. 14158 * *cmd FCP packet. 14159 * *plun LUN the command will be sent to. 14160 * 14161 * Context: User, Kernel and Interrupt context. 14162 */ 14163 static void 14164 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14165 struct fcp_lun *plun) 14166 { 14167 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14168 struct fcp_tgt *ptgt = plun->lun_tgt; 14169 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14170 14171 ASSERT(cmd->cmd_pkt->pkt_comp || 14172 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14173 14174 if (cmd->cmd_pkt->pkt_numcookies) { 14175 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14176 fcmd->fcp_cntl.cntl_read_data = 1; 14177 fcmd->fcp_cntl.cntl_write_data = 0; 14178 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14179 } else { 14180 fcmd->fcp_cntl.cntl_read_data = 0; 14181 fcmd->fcp_cntl.cntl_write_data = 1; 14182 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14183 } 14184 14185 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14186 14187 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14188 ASSERT(fpkt->pkt_data_cookie_cnt <= 14189 pptr->port_data_dma_attr.dma_attr_sgllen); 14190 14191 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14192 14193 /* FCA needs pkt_datalen to be set */ 14194 fpkt->pkt_datalen = cmd->cmd_dmacount; 14195 fcmd->fcp_data_len = cmd->cmd_dmacount; 14196 } else { 14197 fcmd->fcp_cntl.cntl_read_data = 0; 14198 fcmd->fcp_cntl.cntl_write_data = 0; 14199 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14200 fpkt->pkt_datalen = 0; 14201 fcmd->fcp_data_len = 0; 14202 } 14203 14204 /* set up the Tagged Queuing type */ 14205 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14206 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14207 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14208 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14209 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14210 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14211 } else { 14212 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14213 } 14214 14215 fcmd->fcp_ent_addr = plun->lun_addr; 14216 14217 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14218 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14219 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14220 } else { 14221 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14222 } 14223 14224 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14225 cmd->cmd_pkt->pkt_state = 0; 14226 cmd->cmd_pkt->pkt_statistics = 0; 14227 cmd->cmd_pkt->pkt_resid = 0; 14228 14229 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14230 14231 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14232 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14233 fpkt->pkt_comp = NULL; 14234 } else { 14235 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14236 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14237 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14238 } 14239 fpkt->pkt_comp = fcp_cmd_callback; 14240 } 14241 14242 mutex_enter(&pptr->port_mutex); 14243 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14244 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14245 } 14246 mutex_exit(&pptr->port_mutex); 14247 14248 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14249 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14250 14251 /* 14252 * Save a few kernel cycles here 14253 */ 14254 #ifndef __lock_lint 14255 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14256 #endif /* __lock_lint */ 14257 } 14258 14259 static void 14260 fcp_post_callback(struct fcp_pkt *cmd) 14261 { 14262 scsi_hba_pkt_comp(cmd->cmd_pkt); 14263 } 14264 14265 14266 /* 14267 * called to do polled I/O by fcp_start() 14268 * 14269 * return a transport status value, i.e. TRAN_ACCECPT for success 14270 */ 14271 static int 14272 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14273 { 14274 int rval; 14275 14276 #ifdef DEBUG 14277 mutex_enter(&pptr->port_pkt_mutex); 14278 pptr->port_npkts++; 14279 mutex_exit(&pptr->port_pkt_mutex); 14280 #endif /* DEBUG */ 14281 14282 if (cmd->cmd_fp_pkt->pkt_timeout) { 14283 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14284 } else { 14285 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14286 } 14287 14288 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14289 14290 cmd->cmd_state = FCP_PKT_ISSUED; 14291 14292 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14293 14294 #ifdef DEBUG 14295 mutex_enter(&pptr->port_pkt_mutex); 14296 pptr->port_npkts--; 14297 mutex_exit(&pptr->port_pkt_mutex); 14298 #endif /* DEBUG */ 14299 14300 cmd->cmd_state = FCP_PKT_IDLE; 14301 14302 switch (rval) { 14303 case FC_SUCCESS: 14304 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14305 fcp_complete_pkt(cmd->cmd_fp_pkt); 14306 rval = TRAN_ACCEPT; 14307 } else { 14308 rval = TRAN_FATAL_ERROR; 14309 } 14310 break; 14311 14312 case FC_TRAN_BUSY: 14313 rval = TRAN_BUSY; 14314 cmd->cmd_pkt->pkt_resid = 0; 14315 break; 14316 14317 case FC_BADPACKET: 14318 rval = TRAN_BADPKT; 14319 break; 14320 14321 default: 14322 rval = TRAN_FATAL_ERROR; 14323 break; 14324 } 14325 14326 return (rval); 14327 } 14328 14329 14330 /* 14331 * called by some of the following transport-called routines to convert 14332 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14333 */ 14334 static struct fcp_port * 14335 fcp_dip2port(dev_info_t *dip) 14336 { 14337 int instance; 14338 14339 instance = ddi_get_instance(dip); 14340 return (ddi_get_soft_state(fcp_softstate, instance)); 14341 } 14342 14343 14344 /* 14345 * called internally to return a LUN given a dip 14346 */ 14347 struct fcp_lun * 14348 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14349 { 14350 struct fcp_tgt *ptgt; 14351 struct fcp_lun *plun; 14352 int i; 14353 14354 14355 ASSERT(mutex_owned(&pptr->port_mutex)); 14356 14357 for (i = 0; i < FCP_NUM_HASH; i++) { 14358 for (ptgt = pptr->port_tgt_hash_table[i]; 14359 ptgt != NULL; 14360 ptgt = ptgt->tgt_next) { 14361 mutex_enter(&ptgt->tgt_mutex); 14362 for (plun = ptgt->tgt_lun; plun != NULL; 14363 plun = plun->lun_next) { 14364 mutex_enter(&plun->lun_mutex); 14365 if (plun->lun_cip == cip) { 14366 mutex_exit(&plun->lun_mutex); 14367 mutex_exit(&ptgt->tgt_mutex); 14368 return (plun); /* match found */ 14369 } 14370 mutex_exit(&plun->lun_mutex); 14371 } 14372 mutex_exit(&ptgt->tgt_mutex); 14373 } 14374 } 14375 return (NULL); /* no LUN found */ 14376 } 14377 14378 /* 14379 * pass an element to the hotplug list, kick the hotplug thread 14380 * and wait for the element to get processed by the hotplug thread. 14381 * on return the element is freed. 14382 * 14383 * return zero success and non-zero on failure 14384 * 14385 * acquires/releases the target mutex 14386 * 14387 */ 14388 static int 14389 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14390 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14391 { 14392 struct fcp_hp_elem *elem; 14393 int rval; 14394 14395 mutex_enter(&plun->lun_tgt->tgt_mutex); 14396 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14397 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14398 mutex_exit(&plun->lun_tgt->tgt_mutex); 14399 fcp_log(CE_CONT, pptr->port_dip, 14400 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14401 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14402 return (NDI_FAILURE); 14403 } 14404 mutex_exit(&plun->lun_tgt->tgt_mutex); 14405 mutex_enter(&elem->mutex); 14406 if (elem->wait) { 14407 while (elem->wait) { 14408 cv_wait(&elem->cv, &elem->mutex); 14409 } 14410 } 14411 rval = (elem->result); 14412 mutex_exit(&elem->mutex); 14413 mutex_destroy(&elem->mutex); 14414 cv_destroy(&elem->cv); 14415 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14416 return (rval); 14417 } 14418 14419 /* 14420 * pass an element to the hotplug list, and then 14421 * kick the hotplug thread 14422 * 14423 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14424 * 14425 * acquires/releases the hotplug mutex 14426 * 14427 * called with the target mutex owned 14428 * 14429 * memory acquired in NOSLEEP mode 14430 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14431 * for the hp daemon to process the request and is responsible for 14432 * freeing the element 14433 */ 14434 static struct fcp_hp_elem * 14435 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14436 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14437 { 14438 struct fcp_hp_elem *elem; 14439 dev_info_t *pdip; 14440 14441 ASSERT(pptr != NULL); 14442 ASSERT(plun != NULL); 14443 ASSERT(plun->lun_tgt != NULL); 14444 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14445 14446 /* create space for a hotplug element */ 14447 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14448 == NULL) { 14449 fcp_log(CE_WARN, NULL, 14450 "!can't allocate memory for hotplug element"); 14451 return (NULL); 14452 } 14453 14454 /* fill in hotplug element */ 14455 elem->port = pptr; 14456 elem->lun = plun; 14457 elem->cip = cip; 14458 elem->old_lun_mpxio = plun->lun_mpxio; 14459 elem->what = what; 14460 elem->flags = flags; 14461 elem->link_cnt = link_cnt; 14462 elem->tgt_cnt = tgt_cnt; 14463 elem->wait = wait; 14464 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14465 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14466 14467 /* schedule the hotplug task */ 14468 pdip = pptr->port_dip; 14469 mutex_enter(&plun->lun_mutex); 14470 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14471 plun->lun_event_count++; 14472 elem->event_cnt = plun->lun_event_count; 14473 } 14474 mutex_exit(&plun->lun_mutex); 14475 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14476 (void *)elem, KM_NOSLEEP) == NULL) { 14477 mutex_enter(&plun->lun_mutex); 14478 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14479 plun->lun_event_count--; 14480 } 14481 mutex_exit(&plun->lun_mutex); 14482 kmem_free(elem, sizeof (*elem)); 14483 return (0); 14484 } 14485 14486 return (elem); 14487 } 14488 14489 14490 static void 14491 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14492 { 14493 int rval; 14494 struct scsi_address *ap; 14495 struct fcp_lun *plun; 14496 struct fcp_tgt *ptgt; 14497 fc_packet_t *fpkt; 14498 14499 ap = &cmd->cmd_pkt->pkt_address; 14500 plun = ADDR2LUN(ap); 14501 ptgt = plun->lun_tgt; 14502 14503 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14504 14505 cmd->cmd_state = FCP_PKT_IDLE; 14506 14507 mutex_enter(&pptr->port_mutex); 14508 mutex_enter(&ptgt->tgt_mutex); 14509 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14510 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14511 fc_ulp_rscn_info_t *rscnp; 14512 14513 cmd->cmd_state = FCP_PKT_ISSUED; 14514 14515 /* 14516 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14517 * originally NULL, hence we try to set it to the pd pointed 14518 * to by the SCSI device we're trying to get to. 14519 */ 14520 14521 fpkt = cmd->cmd_fp_pkt; 14522 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14523 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14524 /* 14525 * We need to notify the transport that we now have a 14526 * reference to the remote port handle. 14527 */ 14528 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14529 } 14530 14531 mutex_exit(&ptgt->tgt_mutex); 14532 mutex_exit(&pptr->port_mutex); 14533 14534 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14535 14536 /* prepare the packet */ 14537 14538 fcp_prepare_pkt(pptr, cmd, plun); 14539 14540 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14541 pkt_ulp_rscn_infop; 14542 14543 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14544 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14545 14546 if (rscnp != NULL) { 14547 rscnp->ulp_rscn_count = 14548 fc_ulp_get_rscn_count(pptr-> 14549 port_fp_handle); 14550 } 14551 14552 rval = fcp_transport(pptr->port_fp_handle, 14553 cmd->cmd_fp_pkt, 0); 14554 14555 if (rval == FC_SUCCESS) { 14556 return; 14557 } 14558 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14559 } else { 14560 mutex_exit(&ptgt->tgt_mutex); 14561 mutex_exit(&pptr->port_mutex); 14562 } 14563 14564 fcp_queue_pkt(pptr, cmd); 14565 } 14566 14567 14568 static void 14569 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14570 { 14571 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14572 14573 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14574 cmd->cmd_state = FCP_PKT_IDLE; 14575 14576 cmd->cmd_pkt->pkt_reason = reason; 14577 cmd->cmd_pkt->pkt_state = 0; 14578 cmd->cmd_pkt->pkt_statistics = statistics; 14579 14580 fcp_post_callback(cmd); 14581 } 14582 14583 /* 14584 * Function: fcp_queue_pkt 14585 * 14586 * Description: This function queues the packet passed by the caller into 14587 * the list of packets of the FCP port. 14588 * 14589 * Argument: *pptr FCP port. 14590 * *cmd FCP packet to queue. 14591 * 14592 * Return Value: None 14593 * 14594 * Context: User, Kernel and Interrupt context. 14595 */ 14596 static void 14597 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14598 { 14599 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14600 14601 mutex_enter(&pptr->port_pkt_mutex); 14602 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14603 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14604 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14605 14606 /* 14607 * zero pkt_time means hang around for ever 14608 */ 14609 if (cmd->cmd_pkt->pkt_time) { 14610 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14611 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14612 } else { 14613 /* 14614 * Indicate the watch thread to fail the 14615 * command by setting it to highest value 14616 */ 14617 cmd->cmd_timeout = fcp_watchdog_time; 14618 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14619 } 14620 } 14621 14622 if (pptr->port_pkt_head) { 14623 ASSERT(pptr->port_pkt_tail != NULL); 14624 14625 pptr->port_pkt_tail->cmd_next = cmd; 14626 pptr->port_pkt_tail = cmd; 14627 } else { 14628 ASSERT(pptr->port_pkt_tail == NULL); 14629 14630 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14631 } 14632 cmd->cmd_next = NULL; 14633 mutex_exit(&pptr->port_pkt_mutex); 14634 } 14635 14636 /* 14637 * Function: fcp_update_targets 14638 * 14639 * Description: This function applies the specified change of state to all 14640 * the targets listed. The operation applied is 'set'. 14641 * 14642 * Argument: *pptr FCP port. 14643 * *dev_list Array of fc_portmap_t structures. 14644 * count Length of dev_list. 14645 * state State bits to update. 14646 * cause Reason for the update. 14647 * 14648 * Return Value: None 14649 * 14650 * Context: User, Kernel and Interrupt context. 14651 * The mutex pptr->port_mutex must be held. 14652 */ 14653 static void 14654 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14655 uint32_t count, uint32_t state, int cause) 14656 { 14657 fc_portmap_t *map_entry; 14658 struct fcp_tgt *ptgt; 14659 14660 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14661 14662 while (count--) { 14663 map_entry = &(dev_list[count]); 14664 ptgt = fcp_lookup_target(pptr, 14665 (uchar_t *)&(map_entry->map_pwwn)); 14666 if (ptgt == NULL) { 14667 continue; 14668 } 14669 14670 mutex_enter(&ptgt->tgt_mutex); 14671 ptgt->tgt_trace = 0; 14672 ptgt->tgt_change_cnt++; 14673 ptgt->tgt_statec_cause = cause; 14674 ptgt->tgt_tmp_cnt = 1; 14675 fcp_update_tgt_state(ptgt, FCP_SET, state); 14676 mutex_exit(&ptgt->tgt_mutex); 14677 } 14678 } 14679 14680 static int 14681 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14682 int lcount, int tcount, int cause) 14683 { 14684 int rval; 14685 14686 mutex_enter(&pptr->port_mutex); 14687 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14688 mutex_exit(&pptr->port_mutex); 14689 14690 return (rval); 14691 } 14692 14693 14694 static int 14695 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14696 int lcount, int tcount, int cause) 14697 { 14698 int finish_init = 0; 14699 int finish_tgt = 0; 14700 int do_finish_init = 0; 14701 int rval = FCP_NO_CHANGE; 14702 14703 if (cause == FCP_CAUSE_LINK_CHANGE || 14704 cause == FCP_CAUSE_LINK_DOWN) { 14705 do_finish_init = 1; 14706 } 14707 14708 if (ptgt != NULL) { 14709 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14710 FCP_BUF_LEVEL_2, 0, 14711 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14712 " cause = %d, d_id = 0x%x, tgt_done = %d", 14713 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14714 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14715 ptgt->tgt_d_id, ptgt->tgt_done); 14716 14717 mutex_enter(&ptgt->tgt_mutex); 14718 14719 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14720 rval = FCP_DEV_CHANGE; 14721 if (do_finish_init && ptgt->tgt_done == 0) { 14722 ptgt->tgt_done++; 14723 finish_init = 1; 14724 } 14725 } else { 14726 if (--ptgt->tgt_tmp_cnt <= 0) { 14727 ptgt->tgt_tmp_cnt = 0; 14728 finish_tgt = 1; 14729 14730 if (do_finish_init) { 14731 finish_init = 1; 14732 } 14733 } 14734 } 14735 mutex_exit(&ptgt->tgt_mutex); 14736 } else { 14737 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14738 FCP_BUF_LEVEL_2, 0, 14739 "Call Finish Init for NO target"); 14740 14741 if (do_finish_init) { 14742 finish_init = 1; 14743 } 14744 } 14745 14746 if (finish_tgt) { 14747 ASSERT(ptgt != NULL); 14748 14749 mutex_enter(&ptgt->tgt_mutex); 14750 #ifdef DEBUG 14751 bzero(ptgt->tgt_tmp_cnt_stack, 14752 sizeof (ptgt->tgt_tmp_cnt_stack)); 14753 14754 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14755 FCP_STACK_DEPTH); 14756 #endif /* DEBUG */ 14757 mutex_exit(&ptgt->tgt_mutex); 14758 14759 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14760 } 14761 14762 if (finish_init && lcount == pptr->port_link_cnt) { 14763 ASSERT(pptr->port_tmp_cnt > 0); 14764 if (--pptr->port_tmp_cnt == 0) { 14765 fcp_finish_init(pptr); 14766 } 14767 } else if (lcount != pptr->port_link_cnt) { 14768 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14769 fcp_trace, FCP_BUF_LEVEL_2, 0, 14770 "fcp_call_finish_init_held,1: state change occured" 14771 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14772 } 14773 14774 return (rval); 14775 } 14776 14777 static void 14778 fcp_reconfigure_luns(void * tgt_handle) 14779 { 14780 uint32_t dev_cnt; 14781 fc_portmap_t *devlist; 14782 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14783 struct fcp_port *pptr = ptgt->tgt_port; 14784 14785 /* 14786 * If the timer that fires this off got canceled too late, the 14787 * target could have been destroyed. 14788 */ 14789 14790 if (ptgt->tgt_tid == NULL) { 14791 return; 14792 } 14793 14794 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14795 if (devlist == NULL) { 14796 fcp_log(CE_WARN, pptr->port_dip, 14797 "!fcp%d: failed to allocate for portmap", 14798 pptr->port_instance); 14799 return; 14800 } 14801 14802 dev_cnt = 1; 14803 devlist->map_pd = ptgt->tgt_pd_handle; 14804 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14805 devlist->map_did.port_id = ptgt->tgt_d_id; 14806 14807 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14808 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14809 14810 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14811 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14812 devlist->map_flags = 0; 14813 14814 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14815 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14816 14817 /* 14818 * Clear the tgt_tid after no more references to 14819 * the fcp_tgt 14820 */ 14821 mutex_enter(&ptgt->tgt_mutex); 14822 ptgt->tgt_tid = NULL; 14823 mutex_exit(&ptgt->tgt_mutex); 14824 14825 kmem_free(devlist, sizeof (*devlist)); 14826 } 14827 14828 14829 static void 14830 fcp_free_targets(struct fcp_port *pptr) 14831 { 14832 int i; 14833 struct fcp_tgt *ptgt; 14834 14835 mutex_enter(&pptr->port_mutex); 14836 for (i = 0; i < FCP_NUM_HASH; i++) { 14837 ptgt = pptr->port_tgt_hash_table[i]; 14838 while (ptgt != NULL) { 14839 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14840 14841 fcp_free_target(ptgt); 14842 ptgt = next_tgt; 14843 } 14844 } 14845 mutex_exit(&pptr->port_mutex); 14846 } 14847 14848 14849 static void 14850 fcp_free_target(struct fcp_tgt *ptgt) 14851 { 14852 struct fcp_lun *plun; 14853 timeout_id_t tid; 14854 14855 mutex_enter(&ptgt->tgt_mutex); 14856 tid = ptgt->tgt_tid; 14857 14858 /* 14859 * Cancel any pending timeouts for this target. 14860 */ 14861 14862 if (tid != NULL) { 14863 /* 14864 * Set tgt_tid to NULL first to avoid a race in the callback. 14865 * If tgt_tid is NULL, the callback will simply return. 14866 */ 14867 ptgt->tgt_tid = NULL; 14868 mutex_exit(&ptgt->tgt_mutex); 14869 (void) untimeout(tid); 14870 mutex_enter(&ptgt->tgt_mutex); 14871 } 14872 14873 plun = ptgt->tgt_lun; 14874 while (plun != NULL) { 14875 struct fcp_lun *next_lun = plun->lun_next; 14876 14877 fcp_dealloc_lun(plun); 14878 plun = next_lun; 14879 } 14880 14881 mutex_exit(&ptgt->tgt_mutex); 14882 fcp_dealloc_tgt(ptgt); 14883 } 14884 14885 /* 14886 * Function: fcp_is_retryable 14887 * 14888 * Description: Indicates if the internal packet is retryable. 14889 * 14890 * Argument: *icmd FCP internal packet. 14891 * 14892 * Return Value: 0 Not retryable 14893 * 1 Retryable 14894 * 14895 * Context: User, Kernel and Interrupt context 14896 */ 14897 static int 14898 fcp_is_retryable(struct fcp_ipkt *icmd) 14899 { 14900 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14901 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14902 return (0); 14903 } 14904 14905 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14906 icmd->ipkt_port->port_deadline) ? 1 : 0); 14907 } 14908 14909 /* 14910 * Function: fcp_create_on_demand 14911 * 14912 * Argument: *pptr FCP port. 14913 * *pwwn Port WWN. 14914 * 14915 * Return Value: 0 Success 14916 * EIO 14917 * ENOMEM 14918 * EBUSY 14919 * EINVAL 14920 * 14921 * Context: User and Kernel context 14922 */ 14923 static int 14924 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14925 { 14926 int wait_ms; 14927 int tcount; 14928 int lcount; 14929 int ret; 14930 int error; 14931 int rval = EIO; 14932 int ntries; 14933 fc_portmap_t *devlist; 14934 opaque_t pd; 14935 struct fcp_lun *plun; 14936 struct fcp_tgt *ptgt; 14937 int old_manual = 0; 14938 14939 /* Allocates the fc_portmap_t structure. */ 14940 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14941 14942 /* 14943 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14944 * in the commented statement below: 14945 * 14946 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14947 * 14948 * Below, the deadline for the discovery process is set. 14949 */ 14950 mutex_enter(&pptr->port_mutex); 14951 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14952 mutex_exit(&pptr->port_mutex); 14953 14954 /* 14955 * We try to find the remote port based on the WWN provided by the 14956 * caller. We actually ask fp/fctl if it has it. 14957 */ 14958 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14959 (la_wwn_t *)pwwn, &error, 1); 14960 14961 if (pd == NULL) { 14962 kmem_free(devlist, sizeof (*devlist)); 14963 return (rval); 14964 } 14965 14966 /* 14967 * The remote port was found. We ask fp/fctl to update our 14968 * fc_portmap_t structure. 14969 */ 14970 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14971 (la_wwn_t *)pwwn, devlist); 14972 if (ret != FC_SUCCESS) { 14973 kmem_free(devlist, sizeof (*devlist)); 14974 return (rval); 14975 } 14976 14977 /* 14978 * The map flag field is set to indicates that the creation is being 14979 * done at the user request (Ioclt probably luxadm or cfgadm). 14980 */ 14981 devlist->map_type = PORT_DEVICE_USER_CREATE; 14982 14983 mutex_enter(&pptr->port_mutex); 14984 14985 /* 14986 * We check to see if fcp already has a target that describes the 14987 * device being created. If not it is created. 14988 */ 14989 ptgt = fcp_lookup_target(pptr, pwwn); 14990 if (ptgt == NULL) { 14991 lcount = pptr->port_link_cnt; 14992 mutex_exit(&pptr->port_mutex); 14993 14994 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14995 if (ptgt == NULL) { 14996 fcp_log(CE_WARN, pptr->port_dip, 14997 "!FC target allocation failed"); 14998 return (ENOMEM); 14999 } 15000 15001 mutex_enter(&pptr->port_mutex); 15002 } 15003 15004 mutex_enter(&ptgt->tgt_mutex); 15005 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 15006 ptgt->tgt_tmp_cnt = 1; 15007 ptgt->tgt_device_created = 0; 15008 /* 15009 * If fabric and auto config is set but the target was 15010 * manually unconfigured then reset to the manual_config_only to 15011 * 0 so the device will get configured. 15012 */ 15013 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15014 fcp_enable_auto_configuration && 15015 ptgt->tgt_manual_config_only == 1) { 15016 old_manual = 1; 15017 ptgt->tgt_manual_config_only = 0; 15018 } 15019 mutex_exit(&ptgt->tgt_mutex); 15020 15021 fcp_update_targets(pptr, devlist, 1, 15022 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 15023 15024 lcount = pptr->port_link_cnt; 15025 tcount = ptgt->tgt_change_cnt; 15026 15027 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 15028 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 15029 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15030 fcp_enable_auto_configuration && old_manual) { 15031 mutex_enter(&ptgt->tgt_mutex); 15032 ptgt->tgt_manual_config_only = 1; 15033 mutex_exit(&ptgt->tgt_mutex); 15034 } 15035 15036 if (pptr->port_link_cnt != lcount || 15037 ptgt->tgt_change_cnt != tcount) { 15038 rval = EBUSY; 15039 } 15040 mutex_exit(&pptr->port_mutex); 15041 15042 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15043 FCP_BUF_LEVEL_3, 0, 15044 "fcp_create_on_demand: mapflags ptgt=%x, " 15045 "lcount=%x::port_link_cnt=%x, " 15046 "tcount=%x: tgt_change_cnt=%x, rval=%x", 15047 ptgt, lcount, pptr->port_link_cnt, 15048 tcount, ptgt->tgt_change_cnt, rval); 15049 return (rval); 15050 } 15051 15052 /* 15053 * Due to lack of synchronization mechanisms, we perform 15054 * periodic monitoring of our request; Because requests 15055 * get dropped when another one supercedes (either because 15056 * of a link change or a target change), it is difficult to 15057 * provide a clean synchronization mechanism (such as a 15058 * semaphore or a conditional variable) without exhaustively 15059 * rewriting the mainline discovery code of this driver. 15060 */ 15061 wait_ms = 500; 15062 15063 ntries = fcp_max_target_retries; 15064 15065 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15066 FCP_BUF_LEVEL_3, 0, 15067 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15068 "lcount=%x::port_link_cnt=%x, " 15069 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15070 "tgt_tmp_cnt =%x", 15071 ntries, ptgt, lcount, pptr->port_link_cnt, 15072 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15073 ptgt->tgt_tmp_cnt); 15074 15075 mutex_enter(&ptgt->tgt_mutex); 15076 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15077 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15078 mutex_exit(&ptgt->tgt_mutex); 15079 mutex_exit(&pptr->port_mutex); 15080 15081 delay(drv_usectohz(wait_ms * 1000)); 15082 15083 mutex_enter(&pptr->port_mutex); 15084 mutex_enter(&ptgt->tgt_mutex); 15085 } 15086 15087 15088 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15089 rval = EBUSY; 15090 } else { 15091 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15092 FCP_TGT_NODE_PRESENT) { 15093 rval = 0; 15094 } 15095 } 15096 15097 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15098 FCP_BUF_LEVEL_3, 0, 15099 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15100 "lcount=%x::port_link_cnt=%x, " 15101 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15102 "tgt_tmp_cnt =%x", 15103 ntries, ptgt, lcount, pptr->port_link_cnt, 15104 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15105 ptgt->tgt_tmp_cnt); 15106 15107 if (rval) { 15108 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15109 fcp_enable_auto_configuration && old_manual) { 15110 ptgt->tgt_manual_config_only = 1; 15111 } 15112 mutex_exit(&ptgt->tgt_mutex); 15113 mutex_exit(&pptr->port_mutex); 15114 kmem_free(devlist, sizeof (*devlist)); 15115 15116 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15117 FCP_BUF_LEVEL_3, 0, 15118 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15119 "lcount=%x::port_link_cnt=%x, " 15120 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15121 "tgt_device_created=%x, tgt D_ID=%x", 15122 ntries, ptgt, lcount, pptr->port_link_cnt, 15123 tcount, ptgt->tgt_change_cnt, rval, 15124 ptgt->tgt_device_created, ptgt->tgt_d_id); 15125 return (rval); 15126 } 15127 15128 if ((plun = ptgt->tgt_lun) != NULL) { 15129 tcount = plun->lun_tgt->tgt_change_cnt; 15130 } else { 15131 rval = EINVAL; 15132 } 15133 lcount = pptr->port_link_cnt; 15134 15135 /* 15136 * Configuring the target with no LUNs will fail. We 15137 * should reset the node state so that it is not 15138 * automatically configured when the LUNs are added 15139 * to this target. 15140 */ 15141 if (ptgt->tgt_lun_cnt == 0) { 15142 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15143 } 15144 mutex_exit(&ptgt->tgt_mutex); 15145 mutex_exit(&pptr->port_mutex); 15146 15147 while (plun) { 15148 child_info_t *cip; 15149 15150 mutex_enter(&plun->lun_mutex); 15151 cip = plun->lun_cip; 15152 mutex_exit(&plun->lun_mutex); 15153 15154 mutex_enter(&ptgt->tgt_mutex); 15155 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15156 mutex_exit(&ptgt->tgt_mutex); 15157 15158 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15159 FCP_ONLINE, lcount, tcount, 15160 NDI_ONLINE_ATTACH); 15161 if (rval != NDI_SUCCESS) { 15162 FCP_TRACE(fcp_logq, 15163 pptr->port_instbuf, fcp_trace, 15164 FCP_BUF_LEVEL_3, 0, 15165 "fcp_create_on_demand: " 15166 "pass_to_hp_and_wait failed " 15167 "rval=%x", rval); 15168 rval = EIO; 15169 } else { 15170 mutex_enter(&LUN_TGT->tgt_mutex); 15171 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15172 FCP_LUN_BUSY); 15173 mutex_exit(&LUN_TGT->tgt_mutex); 15174 } 15175 mutex_enter(&ptgt->tgt_mutex); 15176 } 15177 15178 plun = plun->lun_next; 15179 mutex_exit(&ptgt->tgt_mutex); 15180 } 15181 15182 kmem_free(devlist, sizeof (*devlist)); 15183 15184 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15185 fcp_enable_auto_configuration && old_manual) { 15186 mutex_enter(&ptgt->tgt_mutex); 15187 /* if successful then set manual to 0 */ 15188 if (rval == 0) { 15189 ptgt->tgt_manual_config_only = 0; 15190 } else { 15191 /* reset to 1 so the user has to do the config */ 15192 ptgt->tgt_manual_config_only = 1; 15193 } 15194 mutex_exit(&ptgt->tgt_mutex); 15195 } 15196 15197 return (rval); 15198 } 15199 15200 15201 static void 15202 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15203 { 15204 int count; 15205 uchar_t byte; 15206 15207 count = 0; 15208 while (*string) { 15209 byte = FCP_ATOB(*string); string++; 15210 byte = byte << 4 | FCP_ATOB(*string); string++; 15211 bytes[count++] = byte; 15212 15213 if (count >= byte_len) { 15214 break; 15215 } 15216 } 15217 } 15218 15219 static void 15220 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15221 { 15222 int i; 15223 15224 for (i = 0; i < FC_WWN_SIZE; i++) { 15225 (void) sprintf(string + (i * 2), 15226 "%02x", wwn[i]); 15227 } 15228 15229 } 15230 15231 static void 15232 fcp_print_error(fc_packet_t *fpkt) 15233 { 15234 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15235 fpkt->pkt_ulp_private; 15236 struct fcp_port *pptr; 15237 struct fcp_tgt *ptgt; 15238 struct fcp_lun *plun; 15239 caddr_t buf; 15240 int scsi_cmd = 0; 15241 15242 ptgt = icmd->ipkt_tgt; 15243 plun = icmd->ipkt_lun; 15244 pptr = ptgt->tgt_port; 15245 15246 buf = kmem_zalloc(256, KM_NOSLEEP); 15247 if (buf == NULL) { 15248 return; 15249 } 15250 15251 switch (icmd->ipkt_opcode) { 15252 case SCMD_REPORT_LUN: 15253 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15254 " lun=0x%%x failed"); 15255 scsi_cmd++; 15256 break; 15257 15258 case SCMD_INQUIRY_PAGE83: 15259 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15260 " lun=0x%%x failed"); 15261 scsi_cmd++; 15262 break; 15263 15264 case SCMD_INQUIRY: 15265 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15266 " lun=0x%%x failed"); 15267 scsi_cmd++; 15268 break; 15269 15270 case LA_ELS_PLOGI: 15271 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15272 break; 15273 15274 case LA_ELS_PRLI: 15275 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15276 break; 15277 } 15278 15279 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15280 struct fcp_rsp response, *rsp; 15281 uchar_t asc, ascq; 15282 caddr_t sense_key = NULL; 15283 struct fcp_rsp_info fcp_rsp_err, *bep; 15284 15285 if (icmd->ipkt_nodma) { 15286 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15287 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15288 sizeof (struct fcp_rsp)); 15289 } else { 15290 rsp = &response; 15291 bep = &fcp_rsp_err; 15292 15293 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15294 sizeof (struct fcp_rsp)); 15295 15296 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15297 bep, fpkt->pkt_resp_acc, 15298 sizeof (struct fcp_rsp_info)); 15299 } 15300 15301 15302 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15303 (void) sprintf(buf + strlen(buf), 15304 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15305 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15306 " senselen=%%x. Giving up"); 15307 15308 fcp_log(CE_WARN, pptr->port_dip, buf, 15309 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15310 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15311 rsp->fcp_u.fcp_status.reserved_1, 15312 rsp->fcp_response_len, rsp->fcp_sense_len); 15313 15314 kmem_free(buf, 256); 15315 return; 15316 } 15317 15318 if (rsp->fcp_u.fcp_status.rsp_len_set && 15319 bep->rsp_code != FCP_NO_FAILURE) { 15320 (void) sprintf(buf + strlen(buf), 15321 " FCP Response code = 0x%x", bep->rsp_code); 15322 } 15323 15324 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15325 struct scsi_extended_sense sense_info, *sense_ptr; 15326 15327 if (icmd->ipkt_nodma) { 15328 sense_ptr = (struct scsi_extended_sense *) 15329 ((caddr_t)fpkt->pkt_resp + 15330 sizeof (struct fcp_rsp) + 15331 rsp->fcp_response_len); 15332 } else { 15333 sense_ptr = &sense_info; 15334 15335 FCP_CP_IN(fpkt->pkt_resp + 15336 sizeof (struct fcp_rsp) + 15337 rsp->fcp_response_len, &sense_info, 15338 fpkt->pkt_resp_acc, 15339 sizeof (struct scsi_extended_sense)); 15340 } 15341 15342 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15343 NUM_IMPL_SENSE_KEYS) { 15344 sense_key = sense_keys[sense_ptr->es_key]; 15345 } else { 15346 sense_key = "Undefined"; 15347 } 15348 15349 asc = sense_ptr->es_add_code; 15350 ascq = sense_ptr->es_qual_code; 15351 15352 (void) sprintf(buf + strlen(buf), 15353 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15354 " Giving up"); 15355 15356 fcp_log(CE_WARN, pptr->port_dip, buf, 15357 ptgt->tgt_d_id, plun->lun_num, sense_key, 15358 asc, ascq); 15359 } else { 15360 (void) sprintf(buf + strlen(buf), 15361 " : SCSI status=%%x. Giving up"); 15362 15363 fcp_log(CE_WARN, pptr->port_dip, buf, 15364 ptgt->tgt_d_id, plun->lun_num, 15365 rsp->fcp_u.fcp_status.scsi_status); 15366 } 15367 } else { 15368 caddr_t state, reason, action, expln; 15369 15370 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15371 &action, &expln); 15372 15373 (void) sprintf(buf + strlen(buf), ": State:%%s," 15374 " Reason:%%s. Giving up"); 15375 15376 if (scsi_cmd) { 15377 fcp_log(CE_WARN, pptr->port_dip, buf, 15378 ptgt->tgt_d_id, plun->lun_num, state, reason); 15379 } else { 15380 fcp_log(CE_WARN, pptr->port_dip, buf, 15381 ptgt->tgt_d_id, state, reason); 15382 } 15383 } 15384 15385 kmem_free(buf, 256); 15386 } 15387 15388 15389 static int 15390 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15391 struct fcp_ipkt *icmd, int rval, caddr_t op) 15392 { 15393 int ret = DDI_FAILURE; 15394 char *error; 15395 15396 switch (rval) { 15397 case FC_DEVICE_BUSY_NEW_RSCN: 15398 /* 15399 * This means that there was a new RSCN that the transport 15400 * knows about (which the ULP *may* know about too) but the 15401 * pkt that was sent down was related to an older RSCN. So, we 15402 * are just going to reset the retry count and deadline and 15403 * continue to retry. The idea is that transport is currently 15404 * working on the new RSCN and will soon let the ULPs know 15405 * about it and when it does the existing logic will kick in 15406 * where it will change the tcount to indicate that something 15407 * changed on the target. So, rediscovery will start and there 15408 * will not be an infinite retry. 15409 * 15410 * For a full flow of how the RSCN info is transferred back and 15411 * forth, see fp.c 15412 */ 15413 icmd->ipkt_retries = 0; 15414 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15415 FCP_ICMD_DEADLINE; 15416 15417 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15418 FCP_BUF_LEVEL_3, 0, 15419 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15420 rval, ptgt->tgt_d_id); 15421 /* FALLTHROUGH */ 15422 15423 case FC_STATEC_BUSY: 15424 case FC_DEVICE_BUSY: 15425 case FC_PBUSY: 15426 case FC_FBUSY: 15427 case FC_TRAN_BUSY: 15428 case FC_OFFLINE: 15429 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15430 FCP_BUF_LEVEL_3, 0, 15431 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15432 rval, ptgt->tgt_d_id); 15433 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15434 fcp_is_retryable(icmd)) { 15435 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15436 ret = DDI_SUCCESS; 15437 } 15438 break; 15439 15440 case FC_LOGINREQ: 15441 /* 15442 * FC_LOGINREQ used to be handled just like all the cases 15443 * above. It has been changed to handled a PRLI that fails 15444 * with FC_LOGINREQ different than other ipkts that fail 15445 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15446 * a simple matter to turn it into a PLOGI instead, so that's 15447 * exactly what we do here. 15448 */ 15449 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15450 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15451 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15452 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15453 } else { 15454 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15455 FCP_BUF_LEVEL_3, 0, 15456 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15457 rval, ptgt->tgt_d_id); 15458 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15459 fcp_is_retryable(icmd)) { 15460 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15461 ret = DDI_SUCCESS; 15462 } 15463 } 15464 break; 15465 15466 default: 15467 mutex_enter(&pptr->port_mutex); 15468 mutex_enter(&ptgt->tgt_mutex); 15469 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15470 mutex_exit(&ptgt->tgt_mutex); 15471 mutex_exit(&pptr->port_mutex); 15472 15473 (void) fc_ulp_error(rval, &error); 15474 fcp_log(CE_WARN, pptr->port_dip, 15475 "!Failed to send %s to D_ID=%x error=%s", 15476 op, ptgt->tgt_d_id, error); 15477 } else { 15478 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15479 fcp_trace, FCP_BUF_LEVEL_2, 0, 15480 "fcp_handle_ipkt_errors,1: state change occured" 15481 " for D_ID=0x%x", ptgt->tgt_d_id); 15482 mutex_exit(&ptgt->tgt_mutex); 15483 mutex_exit(&pptr->port_mutex); 15484 } 15485 break; 15486 } 15487 15488 return (ret); 15489 } 15490 15491 15492 /* 15493 * Check of outstanding commands on any LUN for this target 15494 */ 15495 static int 15496 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15497 { 15498 struct fcp_lun *plun; 15499 struct fcp_pkt *cmd; 15500 15501 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15502 mutex_enter(&plun->lun_mutex); 15503 for (cmd = plun->lun_pkt_head; cmd != NULL; 15504 cmd = cmd->cmd_forw) { 15505 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15506 mutex_exit(&plun->lun_mutex); 15507 return (FC_SUCCESS); 15508 } 15509 } 15510 mutex_exit(&plun->lun_mutex); 15511 } 15512 15513 return (FC_FAILURE); 15514 } 15515 15516 static fc_portmap_t * 15517 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15518 { 15519 int i; 15520 fc_portmap_t *devlist; 15521 fc_portmap_t *devptr = NULL; 15522 struct fcp_tgt *ptgt; 15523 15524 mutex_enter(&pptr->port_mutex); 15525 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15526 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15527 ptgt = ptgt->tgt_next) { 15528 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15529 ++*dev_cnt; 15530 } 15531 } 15532 } 15533 15534 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15535 KM_NOSLEEP); 15536 if (devlist == NULL) { 15537 mutex_exit(&pptr->port_mutex); 15538 fcp_log(CE_WARN, pptr->port_dip, 15539 "!fcp%d: failed to allocate for portmap for construct map", 15540 pptr->port_instance); 15541 return (devptr); 15542 } 15543 15544 for (i = 0; i < FCP_NUM_HASH; i++) { 15545 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15546 ptgt = ptgt->tgt_next) { 15547 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15548 int ret; 15549 15550 ret = fc_ulp_pwwn_to_portmap( 15551 pptr->port_fp_handle, 15552 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15553 devlist); 15554 15555 if (ret == FC_SUCCESS) { 15556 devlist++; 15557 continue; 15558 } 15559 15560 devlist->map_pd = NULL; 15561 devlist->map_did.port_id = ptgt->tgt_d_id; 15562 devlist->map_hard_addr.hard_addr = 15563 ptgt->tgt_hard_addr; 15564 15565 devlist->map_state = PORT_DEVICE_INVALID; 15566 devlist->map_type = PORT_DEVICE_OLD; 15567 15568 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15569 &devlist->map_nwwn, FC_WWN_SIZE); 15570 15571 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15572 &devlist->map_pwwn, FC_WWN_SIZE); 15573 15574 devlist++; 15575 } 15576 } 15577 } 15578 15579 mutex_exit(&pptr->port_mutex); 15580 15581 return (devptr); 15582 } 15583 /* 15584 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15585 */ 15586 static void 15587 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15588 { 15589 int i; 15590 struct fcp_tgt *ptgt; 15591 struct fcp_lun *plun; 15592 15593 for (i = 0; i < FCP_NUM_HASH; i++) { 15594 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15595 ptgt = ptgt->tgt_next) { 15596 mutex_enter(&ptgt->tgt_mutex); 15597 for (plun = ptgt->tgt_lun; plun != NULL; 15598 plun = plun->lun_next) { 15599 if (plun->lun_mpxio && 15600 plun->lun_state & FCP_LUN_BUSY) { 15601 if (!fcp_pass_to_hp(pptr, plun, 15602 plun->lun_cip, 15603 FCP_MPXIO_PATH_SET_BUSY, 15604 pptr->port_link_cnt, 15605 ptgt->tgt_change_cnt, 0, 0)) { 15606 FCP_TRACE(fcp_logq, 15607 pptr->port_instbuf, 15608 fcp_trace, 15609 FCP_BUF_LEVEL_2, 0, 15610 "path_verifybusy: " 15611 "disable lun %p failed!", 15612 plun); 15613 } 15614 } 15615 } 15616 mutex_exit(&ptgt->tgt_mutex); 15617 } 15618 } 15619 } 15620 15621 static int 15622 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15623 { 15624 dev_info_t *cdip = NULL; 15625 dev_info_t *pdip = NULL; 15626 15627 ASSERT(plun); 15628 15629 mutex_enter(&plun->lun_mutex); 15630 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15631 mutex_exit(&plun->lun_mutex); 15632 return (NDI_FAILURE); 15633 } 15634 mutex_exit(&plun->lun_mutex); 15635 cdip = mdi_pi_get_client(PIP(cip)); 15636 pdip = mdi_pi_get_phci(PIP(cip)); 15637 15638 ASSERT(cdip != NULL); 15639 ASSERT(pdip != NULL); 15640 15641 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15642 /* LUN ready for IO */ 15643 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15644 } else { 15645 /* LUN busy to accept IO */ 15646 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15647 } 15648 return (NDI_SUCCESS); 15649 } 15650 15651 /* 15652 * Caller must free the returned string of MAXPATHLEN len 15653 * If the device is offline (-1 instance number) NULL 15654 * will be returned. 15655 */ 15656 static char * 15657 fcp_get_lun_path(struct fcp_lun *plun) { 15658 dev_info_t *dip = NULL; 15659 char *path = NULL; 15660 mdi_pathinfo_t *pip = NULL; 15661 15662 if (plun == NULL) { 15663 return (NULL); 15664 } 15665 15666 mutex_enter(&plun->lun_mutex); 15667 if (plun->lun_mpxio == 0) { 15668 dip = DIP(plun->lun_cip); 15669 mutex_exit(&plun->lun_mutex); 15670 } else { 15671 /* 15672 * lun_cip must be accessed with lun_mutex held. Here 15673 * plun->lun_cip either points to a valid node or it is NULL. 15674 * Make a copy so that we can release lun_mutex. 15675 */ 15676 pip = PIP(plun->lun_cip); 15677 15678 /* 15679 * Increase ref count on the path so that we can release 15680 * lun_mutex and still be sure that the pathinfo node (and thus 15681 * also the client) is not deallocated. If pip is NULL, this 15682 * has no effect. 15683 */ 15684 mdi_hold_path(pip); 15685 15686 mutex_exit(&plun->lun_mutex); 15687 15688 /* Get the client. If pip is NULL, we get NULL. */ 15689 dip = mdi_pi_get_client(pip); 15690 } 15691 15692 if (dip == NULL) 15693 goto out; 15694 if (ddi_get_instance(dip) < 0) 15695 goto out; 15696 15697 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15698 if (path == NULL) 15699 goto out; 15700 15701 (void) ddi_pathname(dip, path); 15702 15703 /* Clean up. */ 15704 out: 15705 if (pip != NULL) 15706 mdi_rele_path(pip); 15707 15708 /* 15709 * In reality, the user wants a fully valid path (one they can open) 15710 * but this string is lacking the mount point, and the minor node. 15711 * It would be nice if we could "figure these out" somehow 15712 * and fill them in. Otherwise, the userland code has to understand 15713 * driver specific details of which minor node is the "best" or 15714 * "right" one to expose. (Ex: which slice is the whole disk, or 15715 * which tape doesn't rewind) 15716 */ 15717 return (path); 15718 } 15719 15720 static int 15721 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15722 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15723 { 15724 int64_t reset_delay; 15725 int rval, retry = 0; 15726 struct fcp_port *pptr = fcp_dip2port(parent); 15727 15728 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15729 (ddi_get_lbolt64() - pptr->port_attach_time); 15730 if (reset_delay < 0) { 15731 reset_delay = 0; 15732 } 15733 15734 if (fcp_bus_config_debug) { 15735 flag |= NDI_DEVI_DEBUG; 15736 } 15737 15738 switch (op) { 15739 case BUS_CONFIG_ONE: 15740 /* 15741 * Retry the command since we need to ensure 15742 * the fabric devices are available for root 15743 */ 15744 while (retry++ < fcp_max_bus_config_retries) { 15745 rval = (ndi_busop_bus_config(parent, 15746 flag | NDI_MDI_FALLBACK, op, 15747 arg, childp, (clock_t)reset_delay)); 15748 if (rval == 0) { 15749 return (rval); 15750 } 15751 } 15752 15753 /* 15754 * drain taskq to make sure nodes are created and then 15755 * try again. 15756 */ 15757 taskq_wait(DEVI(parent)->devi_taskq); 15758 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15759 op, arg, childp, 0)); 15760 15761 case BUS_CONFIG_DRIVER: 15762 case BUS_CONFIG_ALL: { 15763 /* 15764 * delay till all devices report in (port_tmp_cnt == 0) 15765 * or FCP_INIT_WAIT_TIMEOUT 15766 */ 15767 mutex_enter(&pptr->port_mutex); 15768 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15769 (void) cv_timedwait(&pptr->port_config_cv, 15770 &pptr->port_mutex, 15771 ddi_get_lbolt() + (clock_t)reset_delay); 15772 reset_delay = 15773 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15774 (ddi_get_lbolt64() - pptr->port_attach_time); 15775 } 15776 mutex_exit(&pptr->port_mutex); 15777 /* drain taskq to make sure nodes are created */ 15778 taskq_wait(DEVI(parent)->devi_taskq); 15779 return (ndi_busop_bus_config(parent, flag, op, 15780 arg, childp, 0)); 15781 } 15782 15783 default: 15784 return (NDI_FAILURE); 15785 } 15786 /*NOTREACHED*/ 15787 } 15788 15789 static int 15790 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15791 ddi_bus_config_op_t op, void *arg) 15792 { 15793 if (fcp_bus_config_debug) { 15794 flag |= NDI_DEVI_DEBUG; 15795 } 15796 15797 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15798 } 15799 15800 15801 /* 15802 * Routine to copy GUID into the lun structure. 15803 * returns 0 if copy was successful and 1 if encountered a 15804 * failure and did not copy the guid. 15805 */ 15806 static int 15807 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15808 { 15809 15810 int retval = 0; 15811 15812 /* add one for the null terminator */ 15813 const unsigned int len = strlen(guidp) + 1; 15814 15815 if ((guidp == NULL) || (plun == NULL)) { 15816 return (1); 15817 } 15818 15819 /* 15820 * if the plun->lun_guid already has been allocated, 15821 * then check the size. if the size is exact, reuse 15822 * it....if not free it an allocate the required size. 15823 * The reallocation should NOT typically happen 15824 * unless the GUIDs reported changes between passes. 15825 * We free up and alloc again even if the 15826 * size was more than required. This is due to the 15827 * fact that the field lun_guid_size - serves 15828 * dual role of indicating the size of the wwn 15829 * size and ALSO the allocation size. 15830 */ 15831 if (plun->lun_guid) { 15832 if (plun->lun_guid_size != len) { 15833 /* 15834 * free the allocated memory and 15835 * initialize the field 15836 * lun_guid_size to 0. 15837 */ 15838 kmem_free(plun->lun_guid, plun->lun_guid_size); 15839 plun->lun_guid = NULL; 15840 plun->lun_guid_size = 0; 15841 } 15842 } 15843 /* 15844 * alloc only if not already done. 15845 */ 15846 if (plun->lun_guid == NULL) { 15847 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15848 if (plun->lun_guid == NULL) { 15849 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15850 "Unable to allocate" 15851 "Memory for GUID!!! size %d", len); 15852 retval = 1; 15853 } else { 15854 plun->lun_guid_size = len; 15855 } 15856 } 15857 if (plun->lun_guid) { 15858 /* 15859 * now copy the GUID 15860 */ 15861 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15862 } 15863 return (retval); 15864 } 15865 15866 /* 15867 * fcp_reconfig_wait 15868 * 15869 * Wait for a rediscovery/reconfiguration to complete before continuing. 15870 */ 15871 15872 static void 15873 fcp_reconfig_wait(struct fcp_port *pptr) 15874 { 15875 clock_t reconfig_start, wait_timeout; 15876 15877 /* 15878 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15879 * reconfiguration in progress. 15880 */ 15881 15882 mutex_enter(&pptr->port_mutex); 15883 if (pptr->port_tmp_cnt == 0) { 15884 mutex_exit(&pptr->port_mutex); 15885 return; 15886 } 15887 mutex_exit(&pptr->port_mutex); 15888 15889 /* 15890 * If we cause a reconfig by raising power, delay until all devices 15891 * report in (port_tmp_cnt returns to 0) 15892 */ 15893 15894 reconfig_start = ddi_get_lbolt(); 15895 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15896 15897 mutex_enter(&pptr->port_mutex); 15898 15899 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15900 pptr->port_tmp_cnt) { 15901 15902 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15903 reconfig_start + wait_timeout); 15904 } 15905 15906 mutex_exit(&pptr->port_mutex); 15907 15908 /* 15909 * Even if fcp_tmp_count isn't 0, continue without error. The port 15910 * we want may still be ok. If not, it will error out later 15911 */ 15912 } 15913 15914 /* 15915 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15916 * We rely on the fcp_global_mutex to provide protection against changes to 15917 * the fcp_lun_blacklist. 15918 * 15919 * You can describe a list of target port WWNs and LUN numbers which will 15920 * not be configured. LUN numbers will be interpreted as decimal. White 15921 * spaces and ',' can be used in the list of LUN numbers. 15922 * 15923 * To prevent LUNs 1 and 2 from being configured for target 15924 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15925 * 15926 * pwwn-lun-blacklist= 15927 * "510000f010fd92a1,1,2", 15928 * "510000e012079df1,1,2"; 15929 */ 15930 static void 15931 fcp_read_blacklist(dev_info_t *dip, 15932 struct fcp_black_list_entry **pplun_blacklist) { 15933 char **prop_array = NULL; 15934 char *curr_pwwn = NULL; 15935 char *curr_lun = NULL; 15936 uint32_t prop_item = 0; 15937 int idx = 0; 15938 int len = 0; 15939 15940 ASSERT(mutex_owned(&fcp_global_mutex)); 15941 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15942 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15943 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15944 return; 15945 } 15946 15947 for (idx = 0; idx < prop_item; idx++) { 15948 15949 curr_pwwn = prop_array[idx]; 15950 while (*curr_pwwn == ' ') { 15951 curr_pwwn++; 15952 } 15953 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15954 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15955 ", please check.", curr_pwwn); 15956 continue; 15957 } 15958 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15959 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15960 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15961 ", please check.", curr_pwwn); 15962 continue; 15963 } 15964 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15965 if (isxdigit(curr_pwwn[len]) != TRUE) { 15966 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15967 "blacklist, please check.", curr_pwwn); 15968 break; 15969 } 15970 } 15971 if (len != sizeof (la_wwn_t) * 2) { 15972 continue; 15973 } 15974 15975 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15976 *(curr_lun - 1) = '\0'; 15977 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15978 } 15979 15980 ddi_prop_free(prop_array); 15981 } 15982 15983 /* 15984 * Get the masking info about one remote target port designated by wwn. 15985 * Lun ids could be separated by ',' or white spaces. 15986 */ 15987 static void 15988 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15989 struct fcp_black_list_entry **pplun_blacklist) { 15990 int idx = 0; 15991 uint32_t offset = 0; 15992 unsigned long lun_id = 0; 15993 char lunid_buf[16]; 15994 char *pend = NULL; 15995 int illegal_digit = 0; 15996 15997 while (offset < strlen(curr_lun)) { 15998 while ((curr_lun[offset + idx] != ',') && 15999 (curr_lun[offset + idx] != '\0') && 16000 (curr_lun[offset + idx] != ' ')) { 16001 if (isdigit(curr_lun[offset + idx]) == 0) { 16002 illegal_digit++; 16003 } 16004 idx++; 16005 } 16006 if (illegal_digit > 0) { 16007 offset += (idx+1); /* To the start of next lun */ 16008 idx = 0; 16009 illegal_digit = 0; 16010 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16011 "the blacklist, please check digits.", 16012 curr_lun, curr_pwwn); 16013 continue; 16014 } 16015 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 16016 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16017 "the blacklist, please check the length of LUN#.", 16018 curr_lun, curr_pwwn); 16019 break; 16020 } 16021 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 16022 offset++; 16023 continue; 16024 } 16025 16026 bcopy(curr_lun + offset, lunid_buf, idx); 16027 lunid_buf[idx] = '\0'; 16028 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 16029 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 16030 } else { 16031 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16032 "the blacklist, please check %s.", 16033 curr_lun, curr_pwwn, lunid_buf); 16034 } 16035 offset += (idx+1); /* To the start of next lun */ 16036 idx = 0; 16037 } 16038 } 16039 16040 /* 16041 * Add one masking record 16042 */ 16043 static void 16044 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 16045 struct fcp_black_list_entry **pplun_blacklist) { 16046 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16047 struct fcp_black_list_entry *new_entry = NULL; 16048 la_wwn_t wwn; 16049 16050 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16051 while (tmp_entry) { 16052 if ((bcmp(&tmp_entry->wwn, &wwn, 16053 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16054 return; 16055 } 16056 16057 tmp_entry = tmp_entry->next; 16058 } 16059 16060 /* add to black list */ 16061 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16062 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16063 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16064 new_entry->lun = lun_id; 16065 new_entry->masked = 0; 16066 new_entry->next = *pplun_blacklist; 16067 *pplun_blacklist = new_entry; 16068 } 16069 16070 /* 16071 * Check if we should mask the specified lun of this fcp_tgt 16072 */ 16073 static int 16074 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 16075 struct fcp_black_list_entry *remote_port; 16076 16077 remote_port = fcp_lun_blacklist; 16078 while (remote_port != NULL) { 16079 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16080 if (remote_port->lun == lun_id) { 16081 remote_port->masked++; 16082 if (remote_port->masked == 1) { 16083 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16084 "%02x%02x%02x%02x%02x%02x%02x%02x " 16085 "is masked due to black listing.\n", 16086 lun_id, wwn->raw_wwn[0], 16087 wwn->raw_wwn[1], wwn->raw_wwn[2], 16088 wwn->raw_wwn[3], wwn->raw_wwn[4], 16089 wwn->raw_wwn[5], wwn->raw_wwn[6], 16090 wwn->raw_wwn[7]); 16091 } 16092 return (TRUE); 16093 } 16094 } 16095 remote_port = remote_port->next; 16096 } 16097 return (FALSE); 16098 } 16099 16100 /* 16101 * Release all allocated resources 16102 */ 16103 static void 16104 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 16105 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16106 struct fcp_black_list_entry *current_entry = NULL; 16107 16108 ASSERT(mutex_owned(&fcp_global_mutex)); 16109 /* 16110 * Traverse all luns 16111 */ 16112 while (tmp_entry) { 16113 current_entry = tmp_entry; 16114 tmp_entry = tmp_entry->next; 16115 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16116 } 16117 *pplun_blacklist = NULL; 16118 } 16119 16120 /* 16121 * In fcp module, 16122 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16123 */ 16124 static struct scsi_pkt * 16125 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16126 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16127 int flags, int (*callback)(), caddr_t arg) 16128 { 16129 fcp_port_t *pptr = ADDR2FCP(ap); 16130 fcp_pkt_t *cmd = NULL; 16131 fc_frame_hdr_t *hp; 16132 16133 /* 16134 * First step: get the packet 16135 */ 16136 if (pkt == NULL) { 16137 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16138 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16139 callback, arg); 16140 if (pkt == NULL) { 16141 return (NULL); 16142 } 16143 16144 /* 16145 * All fields in scsi_pkt will be initialized properly or 16146 * set to zero. We need do nothing for scsi_pkt. 16147 */ 16148 /* 16149 * But it's our responsibility to link other related data 16150 * structures. Their initialization will be done, just 16151 * before the scsi_pkt will be sent to FCA. 16152 */ 16153 cmd = PKT2CMD(pkt); 16154 cmd->cmd_pkt = pkt; 16155 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16156 /* 16157 * fc_packet_t 16158 */ 16159 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16160 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16161 sizeof (struct fcp_pkt)); 16162 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16163 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16164 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16165 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16166 /* 16167 * Fill in the Fabric Channel Header 16168 */ 16169 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16170 hp->r_ctl = R_CTL_COMMAND; 16171 hp->rsvd = 0; 16172 hp->type = FC_TYPE_SCSI_FCP; 16173 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16174 hp->seq_id = 0; 16175 hp->df_ctl = 0; 16176 hp->seq_cnt = 0; 16177 hp->ox_id = 0xffff; 16178 hp->rx_id = 0xffff; 16179 hp->ro = 0; 16180 } else { 16181 /* 16182 * We need think if we should reset any elements in 16183 * related data structures. 16184 */ 16185 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16186 fcp_trace, FCP_BUF_LEVEL_6, 0, 16187 "reusing pkt, flags %d", flags); 16188 cmd = PKT2CMD(pkt); 16189 if (cmd->cmd_fp_pkt->pkt_pd) { 16190 cmd->cmd_fp_pkt->pkt_pd = NULL; 16191 } 16192 } 16193 16194 /* 16195 * Second step: dma allocation/move 16196 */ 16197 if (bp && bp->b_bcount != 0) { 16198 /* 16199 * Mark if it's read or write 16200 */ 16201 if (bp->b_flags & B_READ) { 16202 cmd->cmd_flags |= CFLAG_IS_READ; 16203 } else { 16204 cmd->cmd_flags &= ~CFLAG_IS_READ; 16205 } 16206 16207 bp_mapin(bp); 16208 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16209 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16210 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16211 } else { 16212 /* 16213 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16214 * to send zero-length read/write. 16215 */ 16216 cmd->cmd_fp_pkt->pkt_data = NULL; 16217 cmd->cmd_fp_pkt->pkt_datalen = 0; 16218 } 16219 16220 return (pkt); 16221 } 16222 16223 static void 16224 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16225 { 16226 fcp_port_t *pptr = ADDR2FCP(ap); 16227 16228 /* 16229 * First we let FCA to uninitilize private part. 16230 */ 16231 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16232 PKT2CMD(pkt)->cmd_fp_pkt); 16233 16234 /* 16235 * Then we uninitialize fc_packet. 16236 */ 16237 16238 /* 16239 * Thirdly, we uninitializae fcp_pkt. 16240 */ 16241 16242 /* 16243 * In the end, we free scsi_pkt. 16244 */ 16245 scsi_hba_pkt_free(ap, pkt); 16246 } 16247 16248 static int 16249 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16250 { 16251 fcp_port_t *pptr = ADDR2FCP(ap); 16252 fcp_lun_t *plun = ADDR2LUN(ap); 16253 fcp_tgt_t *ptgt = plun->lun_tgt; 16254 fcp_pkt_t *cmd = PKT2CMD(pkt); 16255 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16256 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16257 int rval; 16258 16259 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16260 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16261 16262 /* 16263 * Firstly, we need initialize fcp_pkt_t 16264 * Secondly, we need initialize fcp_cmd_t. 16265 */ 16266 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16267 fcmd->fcp_data_len = fpkt->pkt_datalen; 16268 fcmd->fcp_ent_addr = plun->lun_addr; 16269 if (pkt->pkt_flags & FLAG_HTAG) { 16270 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16271 } else if (pkt->pkt_flags & FLAG_OTAG) { 16272 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16273 } else if (pkt->pkt_flags & FLAG_STAG) { 16274 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16275 } else { 16276 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16277 } 16278 16279 if (cmd->cmd_flags & CFLAG_IS_READ) { 16280 fcmd->fcp_cntl.cntl_read_data = 1; 16281 fcmd->fcp_cntl.cntl_write_data = 0; 16282 } else { 16283 fcmd->fcp_cntl.cntl_read_data = 0; 16284 fcmd->fcp_cntl.cntl_write_data = 1; 16285 } 16286 16287 /* 16288 * Then we need initialize fc_packet_t too. 16289 */ 16290 fpkt->pkt_timeout = pkt->pkt_time + 2; 16291 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16292 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16293 if (cmd->cmd_flags & CFLAG_IS_READ) { 16294 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16295 } else { 16296 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16297 } 16298 16299 if (pkt->pkt_flags & FLAG_NOINTR) { 16300 fpkt->pkt_comp = NULL; 16301 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16302 } else { 16303 fpkt->pkt_comp = fcp_cmd_callback; 16304 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16305 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16306 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16307 } 16308 } 16309 16310 /* 16311 * Lastly, we need initialize scsi_pkt 16312 */ 16313 pkt->pkt_reason = CMD_CMPLT; 16314 pkt->pkt_state = 0; 16315 pkt->pkt_statistics = 0; 16316 pkt->pkt_resid = 0; 16317 16318 /* 16319 * if interrupts aren't allowed (e.g. at dump time) then we'll 16320 * have to do polled I/O 16321 */ 16322 if (pkt->pkt_flags & FLAG_NOINTR) { 16323 return (fcp_dopoll(pptr, cmd)); 16324 } 16325 16326 cmd->cmd_state = FCP_PKT_ISSUED; 16327 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16328 if (rval == FC_SUCCESS) { 16329 return (TRAN_ACCEPT); 16330 } 16331 16332 /* 16333 * Need more consideration 16334 * 16335 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16336 */ 16337 cmd->cmd_state = FCP_PKT_IDLE; 16338 if (rval == FC_TRAN_BUSY) { 16339 return (TRAN_BUSY); 16340 } else { 16341 return (TRAN_FATAL_ERROR); 16342 } 16343 } 16344 16345 /* 16346 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16347 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16348 */ 16349 static void 16350 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16351 { 16352 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16353 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16354 } 16355 16356 /* 16357 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16358 */ 16359 static void 16360 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16361 { 16362 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16363 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16364 } 16365