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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Fibre Channel SCSI ULP Mapping driver 26 */ 27 28 #include <sys/scsi/scsi.h> 29 #include <sys/types.h> 30 #include <sys/varargs.h> 31 #include <sys/devctl.h> 32 #include <sys/thread.h> 33 #include <sys/thread.h> 34 #include <sys/open.h> 35 #include <sys/file.h> 36 #include <sys/sunndi.h> 37 #include <sys/console.h> 38 #include <sys/proc.h> 39 #include <sys/time.h> 40 #include <sys/utsname.h> 41 #include <sys/scsi/impl/scsi_reset_notify.h> 42 #include <sys/ndi_impldefs.h> 43 #include <sys/byteorder.h> 44 #include <sys/fs/dv_node.h> 45 #include <sys/ctype.h> 46 #include <sys/sunmdi.h> 47 48 #include <sys/fibre-channel/fc.h> 49 #include <sys/fibre-channel/impl/fc_ulpif.h> 50 #include <sys/fibre-channel/ulp/fcpvar.h> 51 52 /* 53 * Discovery Process 54 * ================= 55 * 56 * The discovery process is a major function of FCP. In order to help 57 * understand that function a flow diagram is given here. This diagram 58 * doesn't claim to cover all the cases and the events that can occur during 59 * the discovery process nor the subtleties of the code. The code paths shown 60 * are simplified. Its purpose is to help the reader (and potentially bug 61 * fixer) have an overall view of the logic of the code. For that reason the 62 * diagram covers the simple case of the line coming up cleanly or of a new 63 * port attaching to FCP the link being up. The reader must keep in mind 64 * that: 65 * 66 * - There are special cases where bringing devices online and offline 67 * is driven by Ioctl. 68 * 69 * - The behavior of the discovery process can be modified through the 70 * .conf file. 71 * 72 * - The line can go down and come back up at any time during the 73 * discovery process which explains some of the complexity of the code. 74 * 75 * ............................................................................ 76 * 77 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 78 * 79 * 80 * +-------------------------+ 81 * fp/fctl module --->| fcp_port_attach | 82 * +-------------------------+ 83 * | | 84 * | | 85 * | v 86 * | +-------------------------+ 87 * | | fcp_handle_port_attach | 88 * | +-------------------------+ 89 * | | 90 * | | 91 * +--------------------+ | 92 * | | 93 * v v 94 * +-------------------------+ 95 * | fcp_statec_callback | 96 * +-------------------------+ 97 * | 98 * | 99 * v 100 * +-------------------------+ 101 * | fcp_handle_devices | 102 * +-------------------------+ 103 * | 104 * | 105 * v 106 * +-------------------------+ 107 * | fcp_handle_mapflags | 108 * +-------------------------+ 109 * | 110 * | 111 * v 112 * +-------------------------+ 113 * | fcp_send_els | 114 * | | 115 * | PLOGI or PRLI To all the| 116 * | reachable devices. | 117 * +-------------------------+ 118 * 119 * 120 * ............................................................................ 121 * 122 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 123 * STEP 1 are called (it is actually the same function). 124 * 125 * 126 * +-------------------------+ 127 * | fcp_icmd_callback | 128 * fp/fctl module --->| | 129 * | callback for PLOGI and | 130 * | PRLI. | 131 * +-------------------------+ 132 * | 133 * | 134 * Received PLOGI Accept /-\ Received PRLI Accept 135 * _ _ _ _ _ _ / \_ _ _ _ _ _ 136 * | \ / | 137 * | \-/ | 138 * | | 139 * v v 140 * +-------------------------+ +-------------------------+ 141 * | fcp_send_els | | fcp_send_scsi | 142 * | | | | 143 * | PRLI | | REPORT_LUN | 144 * +-------------------------+ +-------------------------+ 145 * 146 * ............................................................................ 147 * 148 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 149 * (It is actually the same function). 150 * 151 * 152 * +-------------------------+ 153 * fp/fctl module ------->| fcp_scsi_callback | 154 * +-------------------------+ 155 * | 156 * | 157 * | 158 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 159 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 160 * | \ / | 161 * | \-/ | 162 * | | | 163 * | Receive INQUIRY reply| | 164 * | | | 165 * v v v 166 * +------------------------+ +----------------------+ +----------------------+ 167 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 168 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 169 * +------------------------+ +----------------------+ +----------------------+ 170 * | | | 171 * | | | 172 * | | | 173 * v v | 174 * +-----------------+ +-----------------+ | 175 * | fcp_send_scsi | | fcp_send_scsi | | 176 * | | | | | 177 * | INQUIRY | | INQUIRY PAGE83 | | 178 * | (To each LUN) | +-----------------+ | 179 * +-----------------+ | 180 * | 181 * v 182 * +------------------------+ 183 * | fcp_call_finish_init | 184 * +------------------------+ 185 * | 186 * v 187 * +-----------------------------+ 188 * | fcp_call_finish_init_held | 189 * +-----------------------------+ 190 * | 191 * | 192 * All LUNs scanned /-\ 193 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 194 * | \ / 195 * | \-/ 196 * v | 197 * +------------------+ | 198 * | fcp_finish_tgt | | 199 * +------------------+ | 200 * | Target Not Offline and | 201 * Target Not Offline and | not marked and tgt_node_state | 202 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 203 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 204 * | \ / | | 205 * | \-/ | | 206 * v v | 207 * +----------------------------+ +-------------------+ | 208 * | fcp_offline_target | | fcp_create_luns | | 209 * | | +-------------------+ | 210 * | A structure fcp_tgt_elem | | | 211 * | is created and queued in | v | 212 * | the FCP port list | +-------------------+ | 213 * | port_offline_tgts. It | | fcp_pass_to_hp | | 214 * | will be unqueued by the | | | | 215 * | watchdog timer. | | Called for each | | 216 * +----------------------------+ | LUN. Dispatches | | 217 * | | fcp_hp_task | | 218 * | +-------------------+ | 219 * | | | 220 * | | | 221 * | | | 222 * | +---------------->| 223 * | | 224 * +---------------------------------------------->| 225 * | 226 * | 227 * All the targets (devices) have been scanned /-\ 228 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 229 * | \ / 230 * | \-/ 231 * +-------------------------------------+ | 232 * | fcp_finish_init | | 233 * | | | 234 * | Signal broadcasts the condition | | 235 * | variable port_config_cv of the FCP | | 236 * | port. One potential code sequence | | 237 * | waiting on the condition variable | | 238 * | the code sequence handling | | 239 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 240 * | The other is in the function | | 241 * | fcp_reconfig_wait which is called | | 242 * | in the transmit path preventing IOs | | 243 * | from going through till the disco- | | 244 * | very process is over. | | 245 * +-------------------------------------+ | 246 * | | 247 * | | 248 * +--------------------------------->| 249 * | 250 * v 251 * Return 252 * 253 * ............................................................................ 254 * 255 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 256 * 257 * 258 * +-------------------------+ 259 * | fcp_hp_task | 260 * +-------------------------+ 261 * | 262 * | 263 * v 264 * +-------------------------+ 265 * | fcp_trigger_lun | 266 * +-------------------------+ 267 * | 268 * | 269 * v 270 * Bring offline /-\ Bring online 271 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 272 * | \ / | 273 * | \-/ | 274 * v v 275 * +---------------------+ +-----------------------+ 276 * | fcp_offline_child | | fcp_get_cip | 277 * +---------------------+ | | 278 * | Creates a dev_info_t | 279 * | or a mdi_pathinfo_t | 280 * | depending on whether | 281 * | mpxio is on or off. | 282 * +-----------------------+ 283 * | 284 * | 285 * v 286 * +-----------------------+ 287 * | fcp_online_child | 288 * | | 289 * | Set device online | 290 * | using NDI or MDI. | 291 * +-----------------------+ 292 * 293 * ............................................................................ 294 * 295 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 296 * what is described here. We only show the target offline path. 297 * 298 * 299 * +--------------------------+ 300 * | fcp_watch | 301 * +--------------------------+ 302 * | 303 * | 304 * v 305 * +--------------------------+ 306 * | fcp_scan_offline_tgts | 307 * +--------------------------+ 308 * | 309 * | 310 * v 311 * +--------------------------+ 312 * | fcp_offline_target_now | 313 * +--------------------------+ 314 * | 315 * | 316 * v 317 * +--------------------------+ 318 * | fcp_offline_tgt_luns | 319 * +--------------------------+ 320 * | 321 * | 322 * v 323 * +--------------------------+ 324 * | fcp_offline_lun | 325 * +--------------------------+ 326 * | 327 * | 328 * v 329 * +----------------------------------+ 330 * | fcp_offline_lun_now | 331 * | | 332 * | A request (or two if mpxio) is | 333 * | sent to the hot plug task using | 334 * | a fcp_hp_elem structure. | 335 * +----------------------------------+ 336 */ 337 338 /* 339 * Functions registered with DDI framework 340 */ 341 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 342 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 343 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 344 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 345 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 346 cred_t *credp, int *rval); 347 348 /* 349 * Functions registered with FC Transport framework 350 */ 351 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 352 fc_attach_cmd_t cmd, uint32_t s_id); 353 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 354 fc_detach_cmd_t cmd); 355 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 356 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 357 uint32_t claimed); 358 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 359 fc_unsol_buf_t *buf, uint32_t claimed); 360 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 361 fc_unsol_buf_t *buf, uint32_t claimed); 362 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 363 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 364 uint32_t dev_cnt, uint32_t port_sid); 365 366 /* 367 * Functions registered with SCSA framework 368 */ 369 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 370 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 371 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 372 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 373 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 374 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 375 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 376 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 377 static int fcp_scsi_reset(struct scsi_address *ap, int level); 378 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 379 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 380 int whom); 381 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 382 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 383 void (*callback)(caddr_t), caddr_t arg); 384 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 385 char *name, ddi_eventcookie_t *event_cookiep); 386 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 387 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 388 ddi_callback_id_t *cb_id); 389 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 390 ddi_callback_id_t cb_id); 391 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 392 ddi_eventcookie_t eventid, void *impldata); 393 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 394 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 395 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 396 ddi_bus_config_op_t op, void *arg); 397 398 /* 399 * Internal functions 400 */ 401 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 402 int mode, int *rval); 403 404 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 405 int mode, int *rval); 406 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 407 struct fcp_scsi_cmd *fscsi, int mode); 408 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 409 caddr_t base_addr, int mode); 410 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 411 412 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 413 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 414 int *fc_pkt_reason, int *fc_pkt_action); 415 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 416 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 417 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 418 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 419 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 420 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 421 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 422 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 423 424 static void fcp_handle_devices(struct fcp_port *pptr, 425 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 426 fcp_map_tag_t *map_tag, int cause); 427 static int fcp_handle_mapflags(struct fcp_port *pptr, 428 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 429 int tgt_cnt, int cause); 430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 431 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 433 int cause); 434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 435 uint32_t state); 436 static struct fcp_port *fcp_get_port(opaque_t port_handle); 437 static void fcp_unsol_callback(fc_packet_t *fpkt); 438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 439 uchar_t r_ctl, uchar_t type); 440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 442 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 443 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 446 int nodma, int flags); 447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 449 uchar_t *wwn); 450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 451 uint32_t d_id); 452 static void fcp_icmd_callback(fc_packet_t *fpkt); 453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 454 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 456 static void fcp_scsi_callback(fc_packet_t *fpkt); 457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 461 uint16_t lun_num); 462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 463 int link_cnt, int tgt_cnt, int cause); 464 static void fcp_finish_init(struct fcp_port *pptr); 465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 466 int tgt_cnt, int cause); 467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 468 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 470 int link_cnt, int tgt_cnt, int nowait, int flags); 471 static void fcp_offline_target_now(struct fcp_port *pptr, 472 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 474 int tgt_cnt, int flags); 475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 476 int nowait, int flags); 477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 478 int tgt_cnt); 479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 480 int tgt_cnt, int flags); 481 static void fcp_scan_offline_luns(struct fcp_port *pptr); 482 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 483 static void fcp_update_offline_flags(struct fcp_lun *plun); 484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 485 static void fcp_abort_commands(struct fcp_pkt *head, struct 486 fcp_port *pptr); 487 static void fcp_cmd_callback(fc_packet_t *fpkt); 488 static void fcp_complete_pkt(fc_packet_t *fpkt); 489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 490 struct fcp_port *pptr); 491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 492 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 494 static void fcp_dealloc_lun(struct fcp_lun *plun); 495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 496 fc_portmap_t *map_entry, int link_cnt); 497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 500 int internal); 501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 503 uint32_t s_id, int instance); 504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 505 int instance); 506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 508 int); 509 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 512 int flags); 513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 514 static int fcp_reset_target(struct scsi_address *ap, int level); 515 static int fcp_commoncap(struct scsi_address *ap, char *cap, 516 int val, int tgtonly, int doset); 517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 520 int sleep); 521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 522 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 526 int lcount, int tcount); 527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 530 int tgt_cnt); 531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 532 dev_info_t *pdip, caddr_t name); 533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 534 int lcount, int tcount, int flags, int *circ); 535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 536 int lcount, int tcount, int flags, int *circ); 537 static void fcp_remove_child(struct fcp_lun *plun); 538 static void fcp_watch(void *arg); 539 static void fcp_check_reset_delay(struct fcp_port *pptr); 540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 541 struct fcp_lun *rlun, int tgt_cnt); 542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 544 uchar_t *wwn, uint16_t lun); 545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 546 struct fcp_lun *plun); 547 static void fcp_post_callback(struct fcp_pkt *cmd); 548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 549 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 551 child_info_t *cip); 552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 553 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 554 int tgt_cnt, int flags); 555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 556 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 557 int tgt_cnt, int flags, int wait); 558 static void fcp_retransport_cmd(struct fcp_port *pptr, 559 struct fcp_pkt *cmd); 560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 561 uint_t statistics); 562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 563 static void fcp_update_targets(struct fcp_port *pptr, 564 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 565 static int fcp_call_finish_init(struct fcp_port *pptr, 566 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 567 static int fcp_call_finish_init_held(struct fcp_port *pptr, 568 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 569 static void fcp_reconfigure_luns(void * tgt_handle); 570 static void fcp_free_targets(struct fcp_port *pptr); 571 static void fcp_free_target(struct fcp_tgt *ptgt); 572 static int fcp_is_retryable(struct fcp_ipkt *icmd); 573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 576 static void fcp_print_error(fc_packet_t *fpkt); 577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 578 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 581 uint32_t *dev_cnt); 582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 585 struct fcp_ioctl *, struct fcp_port **); 586 static char *fcp_get_lun_path(struct fcp_lun *plun); 587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 588 int *rval); 589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 591 static char *fcp_get_lun_path(struct fcp_lun *plun); 592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 593 int *rval); 594 static void fcp_reconfig_wait(struct fcp_port *pptr); 595 596 /* 597 * New functions added for mpxio support 598 */ 599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 600 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 602 int tcount); 603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 604 dev_info_t *pdip); 605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 610 int what); 611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 612 fc_packet_t *fpkt); 613 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 614 615 /* 616 * New functions added for lun masking support 617 */ 618 static void fcp_read_blacklist(dev_info_t *dip, 619 struct fcp_black_list_entry **pplun_blacklist); 620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 621 struct fcp_black_list_entry **pplun_blacklist); 622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 623 struct fcp_black_list_entry **pplun_blacklist); 624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 626 627 extern struct mod_ops mod_driverops; 628 /* 629 * This variable is defined in modctl.c and set to '1' after the root driver 630 * and fs are loaded. It serves as an indication that the root filesystem can 631 * be used. 632 */ 633 extern int modrootloaded; 634 /* 635 * This table contains strings associated with the SCSI sense key codes. It 636 * is used by FCP to print a clear explanation of the code returned in the 637 * sense information by a device. 638 */ 639 extern char *sense_keys[]; 640 /* 641 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 642 * under this device that the paths to a physical device are created when 643 * MPxIO is used. 644 */ 645 extern dev_info_t *scsi_vhci_dip; 646 647 /* 648 * Report lun processing 649 */ 650 #define FCP_LUN_ADDRESSING 0x80 651 #define FCP_PD_ADDRESSING 0x00 652 #define FCP_VOLUME_ADDRESSING 0x40 653 654 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 655 #define MAX_INT_DMA 0x7fffffff 656 #define FCP_MAX_SENSE_LEN 252 657 #define FCP_MAX_RESPONSE_LEN 0xffffff 658 /* 659 * Property definitions 660 */ 661 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 662 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 663 #define TARGET_PROP (char *)fcp_target_prop 664 #define LUN_PROP (char *)fcp_lun_prop 665 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 666 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 667 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 668 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 669 #define INIT_PORT_PROP (char *)fcp_init_port_prop 670 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 671 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 672 /* 673 * Short hand macros. 674 */ 675 #define LUN_PORT (plun->lun_tgt->tgt_port) 676 #define LUN_TGT (plun->lun_tgt) 677 678 /* 679 * Driver private macros 680 */ 681 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 682 ((x) >= 'a' && (x) <= 'f') ? \ 683 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 684 685 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 686 687 #define FCP_N_NDI_EVENTS \ 688 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 689 690 #define FCP_LINK_STATE_CHANGED(p, c) \ 691 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 692 693 #define FCP_TGT_STATE_CHANGED(t, c) \ 694 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 695 696 #define FCP_STATE_CHANGED(p, t, c) \ 697 (FCP_TGT_STATE_CHANGED(t, c)) 698 699 #define FCP_MUST_RETRY(fpkt) \ 700 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 701 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 702 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 703 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 704 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 705 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 706 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 707 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 708 709 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 710 ((es)->es_key == KEY_UNIT_ATTENTION && \ 711 (es)->es_add_code == 0x3f && \ 712 (es)->es_qual_code == 0x0e) 713 714 #define FCP_SENSE_NO_LUN(es) \ 715 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 716 (es)->es_add_code == 0x25 && \ 717 (es)->es_qual_code == 0x0) 718 719 #define FCP_VERSION "1.187" 720 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 721 722 #define FCP_NUM_ELEMENTS(array) \ 723 (sizeof (array) / sizeof ((array)[0])) 724 725 /* 726 * Debugging, Error reporting, and tracing 727 */ 728 #define FCP_LOG_SIZE 1024 * 1024 729 730 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 731 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 732 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 733 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 734 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 735 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 736 #define FCP_LEVEL_7 0x00040 737 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 738 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 739 740 741 742 /* 743 * Log contents to system messages file 744 */ 745 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 746 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 747 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 748 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 749 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 750 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 751 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 752 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 753 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 754 755 756 /* 757 * Log contents to trace buffer 758 */ 759 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 760 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 761 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 762 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 763 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 764 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 765 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 766 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 767 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 768 769 770 /* 771 * Log contents to both system messages file and trace buffer 772 */ 773 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 774 FC_TRACE_LOG_MSG) 775 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 776 FC_TRACE_LOG_MSG) 777 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 778 FC_TRACE_LOG_MSG) 779 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 780 FC_TRACE_LOG_MSG) 781 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 782 FC_TRACE_LOG_MSG) 783 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 784 FC_TRACE_LOG_MSG) 785 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 786 FC_TRACE_LOG_MSG) 787 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 788 FC_TRACE_LOG_MSG) 789 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 790 FC_TRACE_LOG_MSG) 791 #ifdef DEBUG 792 #define FCP_DTRACE fc_trace_debug 793 #else 794 #define FCP_DTRACE 795 #endif 796 797 #define FCP_TRACE fc_trace_debug 798 799 static struct cb_ops fcp_cb_ops = { 800 fcp_open, /* open */ 801 fcp_close, /* close */ 802 nodev, /* strategy */ 803 nodev, /* print */ 804 nodev, /* dump */ 805 nodev, /* read */ 806 nodev, /* write */ 807 fcp_ioctl, /* ioctl */ 808 nodev, /* devmap */ 809 nodev, /* mmap */ 810 nodev, /* segmap */ 811 nochpoll, /* chpoll */ 812 ddi_prop_op, /* cb_prop_op */ 813 0, /* streamtab */ 814 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 815 CB_REV, /* rev */ 816 nodev, /* aread */ 817 nodev /* awrite */ 818 }; 819 820 821 static struct dev_ops fcp_ops = { 822 DEVO_REV, 823 0, 824 ddi_getinfo_1to1, 825 nulldev, /* identify */ 826 nulldev, /* probe */ 827 fcp_attach, /* attach and detach are mandatory */ 828 fcp_detach, 829 nodev, /* reset */ 830 &fcp_cb_ops, /* cb_ops */ 831 NULL, /* bus_ops */ 832 NULL, /* power */ 833 }; 834 835 836 char *fcp_version = FCP_NAME_VERSION; 837 838 static struct modldrv modldrv = { 839 &mod_driverops, 840 FCP_NAME_VERSION, 841 &fcp_ops 842 }; 843 844 845 static struct modlinkage modlinkage = { 846 MODREV_1, 847 &modldrv, 848 NULL 849 }; 850 851 852 static fc_ulp_modinfo_t fcp_modinfo = { 853 &fcp_modinfo, /* ulp_handle */ 854 FCTL_ULP_MODREV_4, /* ulp_rev */ 855 FC4_SCSI_FCP, /* ulp_type */ 856 "fcp", /* ulp_name */ 857 FCP_STATEC_MASK, /* ulp_statec_mask */ 858 fcp_port_attach, /* ulp_port_attach */ 859 fcp_port_detach, /* ulp_port_detach */ 860 fcp_port_ioctl, /* ulp_port_ioctl */ 861 fcp_els_callback, /* ulp_els_callback */ 862 fcp_data_callback, /* ulp_data_callback */ 863 fcp_statec_callback /* ulp_statec_callback */ 864 }; 865 866 #ifdef DEBUG 867 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 868 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 869 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 870 FCP_LEVEL_6 | FCP_LEVEL_7) 871 #else 872 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 873 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 874 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 875 FCP_LEVEL_6 | FCP_LEVEL_7) 876 #endif 877 878 /* FCP global variables */ 879 int fcp_bus_config_debug = 0; 880 static int fcp_log_size = FCP_LOG_SIZE; 881 static int fcp_trace = FCP_TRACE_DEFAULT; 882 static fc_trace_logq_t *fcp_logq = NULL; 883 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 884 /* 885 * The auto-configuration is set by default. The only way of disabling it is 886 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 887 */ 888 static int fcp_enable_auto_configuration = 1; 889 static int fcp_max_bus_config_retries = 4; 890 static int fcp_lun_ready_retry = 300; 891 /* 892 * The value assigned to the following variable has changed several times due 893 * to a problem with the data underruns reporting of some firmware(s). The 894 * current value of 50 gives a timeout value of 25 seconds for a max number 895 * of 256 LUNs. 896 */ 897 static int fcp_max_target_retries = 50; 898 /* 899 * Watchdog variables 900 * ------------------ 901 * 902 * fcp_watchdog_init 903 * 904 * Indicates if the watchdog timer is running or not. This is actually 905 * a counter of the number of Fibre Channel ports that attached. When 906 * the first port attaches the watchdog is started. When the last port 907 * detaches the watchdog timer is stopped. 908 * 909 * fcp_watchdog_time 910 * 911 * This is the watchdog clock counter. It is incremented by 912 * fcp_watchdog_time each time the watchdog timer expires. 913 * 914 * fcp_watchdog_timeout 915 * 916 * Increment value of the variable fcp_watchdog_time as well as the 917 * the timeout value of the watchdog timer. The unit is 1 second. It 918 * is strange that this is not a #define but a variable since the code 919 * never changes this value. The reason why it can be said that the 920 * unit is 1 second is because the number of ticks for the watchdog 921 * timer is determined like this: 922 * 923 * fcp_watchdog_tick = fcp_watchdog_timeout * 924 * drv_usectohz(1000000); 925 * 926 * The value 1000000 is hard coded in the code. 927 * 928 * fcp_watchdog_tick 929 * 930 * Watchdog timer value in ticks. 931 */ 932 static int fcp_watchdog_init = 0; 933 static int fcp_watchdog_time = 0; 934 static int fcp_watchdog_timeout = 1; 935 static int fcp_watchdog_tick; 936 937 /* 938 * fcp_offline_delay is a global variable to enable customisation of 939 * the timeout on link offlines or RSCNs. The default value is set 940 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 941 * specified in FCP4 Chapter 11 (see www.t10.org). 942 * 943 * The variable fcp_offline_delay is specified in SECONDS. 944 * 945 * If we made this a static var then the user would not be able to 946 * change it. This variable is set in fcp_attach(). 947 */ 948 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 949 950 static void *fcp_softstate = NULL; /* for soft state */ 951 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 952 static kmutex_t fcp_global_mutex; 953 static kmutex_t fcp_ioctl_mutex; 954 static dev_info_t *fcp_global_dip = NULL; 955 static timeout_id_t fcp_watchdog_id; 956 const char *fcp_lun_prop = "lun"; 957 const char *fcp_sam_lun_prop = "sam-lun"; 958 const char *fcp_target_prop = "target"; 959 /* 960 * NOTE: consumers of "node-wwn" property include stmsboot in ON 961 * consolidation. 962 */ 963 const char *fcp_node_wwn_prop = "node-wwn"; 964 const char *fcp_port_wwn_prop = "port-wwn"; 965 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 966 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 967 const char *fcp_manual_config_only = "manual_configuration_only"; 968 const char *fcp_init_port_prop = "initiator-port"; 969 const char *fcp_tgt_port_prop = "target-port"; 970 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 971 972 static struct fcp_port *fcp_port_head = NULL; 973 static ddi_eventcookie_t fcp_insert_eid; 974 static ddi_eventcookie_t fcp_remove_eid; 975 976 static ndi_event_definition_t fcp_ndi_event_defs[] = { 977 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 978 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 979 }; 980 981 /* 982 * List of valid commands for the scsi_ioctl call 983 */ 984 static uint8_t scsi_ioctl_list[] = { 985 SCMD_INQUIRY, 986 SCMD_REPORT_LUN, 987 SCMD_READ_CAPACITY 988 }; 989 990 /* 991 * this is used to dummy up a report lun response for cases 992 * where the target doesn't support it 993 */ 994 static uchar_t fcp_dummy_lun[] = { 995 0x00, /* MSB length (length = no of luns * 8) */ 996 0x00, 997 0x00, 998 0x08, /* LSB length */ 999 0x00, /* MSB reserved */ 1000 0x00, 1001 0x00, 1002 0x00, /* LSB reserved */ 1003 FCP_PD_ADDRESSING, 1004 0x00, /* LUN is ZERO at the first level */ 1005 0x00, 1006 0x00, /* second level is zero */ 1007 0x00, 1008 0x00, /* third level is zero */ 1009 0x00, 1010 0x00 /* fourth level is zero */ 1011 }; 1012 1013 static uchar_t fcp_alpa_to_switch[] = { 1014 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1015 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1016 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1017 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1018 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1019 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1020 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1021 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1022 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1023 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1024 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1025 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1026 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1027 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1028 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1029 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1030 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1031 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1032 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1033 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1034 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1035 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1036 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1037 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1038 }; 1039 1040 static caddr_t pid = "SESS01 "; 1041 1042 #if !defined(lint) 1043 1044 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1045 fcp_port::fcp_next fcp_watchdog_id)) 1046 1047 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1048 1049 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1050 fcp_insert_eid 1051 fcp_remove_eid 1052 fcp_watchdog_time)) 1053 1054 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1055 fcp_cb_ops 1056 fcp_ops 1057 callb_cpr)) 1058 1059 #endif /* lint */ 1060 1061 /* 1062 * This table is used to determine whether or not it's safe to copy in 1063 * the target node name for a lun. Since all luns behind the same target 1064 * have the same wwnn, only tagets that do not support multiple luns are 1065 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1066 */ 1067 1068 char *fcp_symmetric_disk_table[] = { 1069 "SEAGATE ST", 1070 "IBM DDYFT", 1071 "SUNW SUNWGS", /* Daktari enclosure */ 1072 "SUN SENA", /* SES device */ 1073 "SUN SESS01" /* VICOM SVE box */ 1074 }; 1075 1076 int fcp_symmetric_disk_table_size = 1077 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1078 1079 /* 1080 * The _init(9e) return value should be that of mod_install(9f). Under 1081 * some circumstances, a failure may not be related mod_install(9f) and 1082 * one would then require a return value to indicate the failure. Looking 1083 * at mod_install(9f), it is expected to return 0 for success and non-zero 1084 * for failure. mod_install(9f) for device drivers, further goes down the 1085 * calling chain and ends up in ddi_installdrv(), whose return values are 1086 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1087 * calling chain of mod_install(9f) which return values like EINVAL and 1088 * in some even return -1. 1089 * 1090 * To work around the vagaries of the mod_install() calling chain, return 1091 * either 0 or ENODEV depending on the success or failure of mod_install() 1092 */ 1093 int 1094 _init(void) 1095 { 1096 int rval; 1097 1098 /* 1099 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1100 * before registering with the transport first. 1101 */ 1102 if (ddi_soft_state_init(&fcp_softstate, 1103 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1104 return (EINVAL); 1105 } 1106 1107 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1108 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1109 1110 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1111 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1112 mutex_destroy(&fcp_global_mutex); 1113 mutex_destroy(&fcp_ioctl_mutex); 1114 ddi_soft_state_fini(&fcp_softstate); 1115 return (ENODEV); 1116 } 1117 1118 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1119 1120 if ((rval = mod_install(&modlinkage)) != 0) { 1121 fc_trace_free_logq(fcp_logq); 1122 (void) fc_ulp_remove(&fcp_modinfo); 1123 mutex_destroy(&fcp_global_mutex); 1124 mutex_destroy(&fcp_ioctl_mutex); 1125 ddi_soft_state_fini(&fcp_softstate); 1126 rval = ENODEV; 1127 } 1128 1129 return (rval); 1130 } 1131 1132 1133 /* 1134 * the system is done with us as a driver, so clean up 1135 */ 1136 int 1137 _fini(void) 1138 { 1139 int rval; 1140 1141 /* 1142 * don't start cleaning up until we know that the module remove 1143 * has worked -- if this works, then we know that each instance 1144 * has successfully been DDI_DETACHed 1145 */ 1146 if ((rval = mod_remove(&modlinkage)) != 0) { 1147 return (rval); 1148 } 1149 1150 (void) fc_ulp_remove(&fcp_modinfo); 1151 1152 ddi_soft_state_fini(&fcp_softstate); 1153 mutex_destroy(&fcp_global_mutex); 1154 mutex_destroy(&fcp_ioctl_mutex); 1155 fc_trace_free_logq(fcp_logq); 1156 1157 return (rval); 1158 } 1159 1160 1161 int 1162 _info(struct modinfo *modinfop) 1163 { 1164 return (mod_info(&modlinkage, modinfop)); 1165 } 1166 1167 1168 /* 1169 * attach the module 1170 */ 1171 static int 1172 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1173 { 1174 int rval = DDI_SUCCESS; 1175 1176 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1177 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1178 1179 if (cmd == DDI_ATTACH) { 1180 /* The FCP pseudo device is created here. */ 1181 mutex_enter(&fcp_global_mutex); 1182 fcp_global_dip = devi; 1183 mutex_exit(&fcp_global_mutex); 1184 1185 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1186 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1187 ddi_report_dev(fcp_global_dip); 1188 } else { 1189 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1190 mutex_enter(&fcp_global_mutex); 1191 fcp_global_dip = NULL; 1192 mutex_exit(&fcp_global_mutex); 1193 1194 rval = DDI_FAILURE; 1195 } 1196 /* 1197 * We check the fcp_offline_delay property at this 1198 * point. This variable is global for the driver, 1199 * not specific to an instance. 1200 * 1201 * We do not recommend setting the value to less 1202 * than 10 seconds (RA_TOV_els), or greater than 1203 * 60 seconds. 1204 */ 1205 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1206 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1207 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1208 if ((fcp_offline_delay < 10) || 1209 (fcp_offline_delay > 60)) { 1210 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1211 "to %d second(s). This is outside the " 1212 "recommended range of 10..60 seconds.", 1213 fcp_offline_delay); 1214 } 1215 } 1216 1217 return (rval); 1218 } 1219 1220 1221 /*ARGSUSED*/ 1222 static int 1223 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1224 { 1225 int res = DDI_SUCCESS; 1226 1227 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1228 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1229 1230 if (cmd == DDI_DETACH) { 1231 /* 1232 * Check if there are active ports/threads. If there 1233 * are any, we will fail, else we will succeed (there 1234 * should not be much to clean up) 1235 */ 1236 mutex_enter(&fcp_global_mutex); 1237 FCP_DTRACE(fcp_logq, "fcp", 1238 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1239 (void *) fcp_port_head); 1240 1241 if (fcp_port_head == NULL) { 1242 ddi_remove_minor_node(fcp_global_dip, NULL); 1243 fcp_global_dip = NULL; 1244 mutex_exit(&fcp_global_mutex); 1245 } else { 1246 mutex_exit(&fcp_global_mutex); 1247 res = DDI_FAILURE; 1248 } 1249 } 1250 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1251 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1252 1253 return (res); 1254 } 1255 1256 1257 /* ARGSUSED */ 1258 static int 1259 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1260 { 1261 if (otype != OTYP_CHR) { 1262 return (EINVAL); 1263 } 1264 1265 /* 1266 * Allow only root to talk; 1267 */ 1268 if (drv_priv(credp)) { 1269 return (EPERM); 1270 } 1271 1272 mutex_enter(&fcp_global_mutex); 1273 if (fcp_oflag & FCP_EXCL) { 1274 mutex_exit(&fcp_global_mutex); 1275 return (EBUSY); 1276 } 1277 1278 if (flag & FEXCL) { 1279 if (fcp_oflag & FCP_OPEN) { 1280 mutex_exit(&fcp_global_mutex); 1281 return (EBUSY); 1282 } 1283 fcp_oflag |= FCP_EXCL; 1284 } 1285 fcp_oflag |= FCP_OPEN; 1286 mutex_exit(&fcp_global_mutex); 1287 1288 return (0); 1289 } 1290 1291 1292 /* ARGSUSED */ 1293 static int 1294 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1295 { 1296 if (otype != OTYP_CHR) { 1297 return (EINVAL); 1298 } 1299 1300 mutex_enter(&fcp_global_mutex); 1301 if (!(fcp_oflag & FCP_OPEN)) { 1302 mutex_exit(&fcp_global_mutex); 1303 return (ENODEV); 1304 } 1305 fcp_oflag = FCP_IDLE; 1306 mutex_exit(&fcp_global_mutex); 1307 1308 return (0); 1309 } 1310 1311 1312 /* 1313 * fcp_ioctl 1314 * Entry point for the FCP ioctls 1315 * 1316 * Input: 1317 * See ioctl(9E) 1318 * 1319 * Output: 1320 * See ioctl(9E) 1321 * 1322 * Returns: 1323 * See ioctl(9E) 1324 * 1325 * Context: 1326 * Kernel context. 1327 */ 1328 /* ARGSUSED */ 1329 static int 1330 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1331 int *rval) 1332 { 1333 int ret = 0; 1334 1335 mutex_enter(&fcp_global_mutex); 1336 if (!(fcp_oflag & FCP_OPEN)) { 1337 mutex_exit(&fcp_global_mutex); 1338 return (ENXIO); 1339 } 1340 mutex_exit(&fcp_global_mutex); 1341 1342 switch (cmd) { 1343 case FCP_TGT_INQUIRY: 1344 case FCP_TGT_CREATE: 1345 case FCP_TGT_DELETE: 1346 ret = fcp_setup_device_data_ioctl(cmd, 1347 (struct fcp_ioctl *)data, mode, rval); 1348 break; 1349 1350 case FCP_TGT_SEND_SCSI: 1351 mutex_enter(&fcp_ioctl_mutex); 1352 ret = fcp_setup_scsi_ioctl( 1353 (struct fcp_scsi_cmd *)data, mode, rval); 1354 mutex_exit(&fcp_ioctl_mutex); 1355 break; 1356 1357 case FCP_STATE_COUNT: 1358 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1359 mode, rval); 1360 break; 1361 case FCP_GET_TARGET_MAPPINGS: 1362 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1363 mode, rval); 1364 break; 1365 default: 1366 fcp_log(CE_WARN, NULL, 1367 "!Invalid ioctl opcode = 0x%x", cmd); 1368 ret = EINVAL; 1369 } 1370 1371 return (ret); 1372 } 1373 1374 1375 /* 1376 * fcp_setup_device_data_ioctl 1377 * Setup handler for the "device data" style of 1378 * ioctl for FCP. See "fcp_util.h" for data structure 1379 * definition. 1380 * 1381 * Input: 1382 * cmd = FCP ioctl command 1383 * data = ioctl data 1384 * mode = See ioctl(9E) 1385 * 1386 * Output: 1387 * data = ioctl data 1388 * rval = return value - see ioctl(9E) 1389 * 1390 * Returns: 1391 * See ioctl(9E) 1392 * 1393 * Context: 1394 * Kernel context. 1395 */ 1396 /* ARGSUSED */ 1397 static int 1398 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1399 int *rval) 1400 { 1401 struct fcp_port *pptr; 1402 struct device_data *dev_data; 1403 uint32_t link_cnt; 1404 la_wwn_t *wwn_ptr = NULL; 1405 struct fcp_tgt *ptgt = NULL; 1406 struct fcp_lun *plun = NULL; 1407 int i, error; 1408 struct fcp_ioctl fioctl; 1409 1410 #ifdef _MULTI_DATAMODEL 1411 switch (ddi_model_convert_from(mode & FMODELS)) { 1412 case DDI_MODEL_ILP32: { 1413 struct fcp32_ioctl f32_ioctl; 1414 1415 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1416 sizeof (struct fcp32_ioctl), mode)) { 1417 return (EFAULT); 1418 } 1419 fioctl.fp_minor = f32_ioctl.fp_minor; 1420 fioctl.listlen = f32_ioctl.listlen; 1421 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1422 break; 1423 } 1424 case DDI_MODEL_NONE: 1425 if (ddi_copyin((void *)data, (void *)&fioctl, 1426 sizeof (struct fcp_ioctl), mode)) { 1427 return (EFAULT); 1428 } 1429 break; 1430 } 1431 1432 #else /* _MULTI_DATAMODEL */ 1433 if (ddi_copyin((void *)data, (void *)&fioctl, 1434 sizeof (struct fcp_ioctl), mode)) { 1435 return (EFAULT); 1436 } 1437 #endif /* _MULTI_DATAMODEL */ 1438 1439 /* 1440 * Right now we can assume that the minor number matches with 1441 * this instance of fp. If this changes we will need to 1442 * revisit this logic. 1443 */ 1444 mutex_enter(&fcp_global_mutex); 1445 pptr = fcp_port_head; 1446 while (pptr) { 1447 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1448 break; 1449 } else { 1450 pptr = pptr->port_next; 1451 } 1452 } 1453 mutex_exit(&fcp_global_mutex); 1454 if (pptr == NULL) { 1455 return (ENXIO); 1456 } 1457 mutex_enter(&pptr->port_mutex); 1458 1459 1460 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1461 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1462 mutex_exit(&pptr->port_mutex); 1463 return (ENOMEM); 1464 } 1465 1466 if (ddi_copyin(fioctl.list, dev_data, 1467 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1468 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1469 mutex_exit(&pptr->port_mutex); 1470 return (EFAULT); 1471 } 1472 link_cnt = pptr->port_link_cnt; 1473 1474 if (cmd == FCP_TGT_INQUIRY) { 1475 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1476 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1477 sizeof (wwn_ptr->raw_wwn)) == 0) { 1478 /* This ioctl is requesting INQ info of local HBA */ 1479 mutex_exit(&pptr->port_mutex); 1480 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1481 dev_data[0].dev_status = 0; 1482 if (ddi_copyout(dev_data, fioctl.list, 1483 (sizeof (struct device_data)) * fioctl.listlen, 1484 mode)) { 1485 kmem_free(dev_data, 1486 sizeof (*dev_data) * fioctl.listlen); 1487 return (EFAULT); 1488 } 1489 kmem_free(dev_data, 1490 sizeof (*dev_data) * fioctl.listlen); 1491 #ifdef _MULTI_DATAMODEL 1492 switch (ddi_model_convert_from(mode & FMODELS)) { 1493 case DDI_MODEL_ILP32: { 1494 struct fcp32_ioctl f32_ioctl; 1495 f32_ioctl.fp_minor = fioctl.fp_minor; 1496 f32_ioctl.listlen = fioctl.listlen; 1497 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1498 if (ddi_copyout((void *)&f32_ioctl, 1499 (void *)data, 1500 sizeof (struct fcp32_ioctl), mode)) { 1501 return (EFAULT); 1502 } 1503 break; 1504 } 1505 case DDI_MODEL_NONE: 1506 if (ddi_copyout((void *)&fioctl, (void *)data, 1507 sizeof (struct fcp_ioctl), mode)) { 1508 return (EFAULT); 1509 } 1510 break; 1511 } 1512 #else /* _MULTI_DATAMODEL */ 1513 if (ddi_copyout((void *)&fioctl, (void *)data, 1514 sizeof (struct fcp_ioctl), mode)) { 1515 return (EFAULT); 1516 } 1517 #endif /* _MULTI_DATAMODEL */ 1518 return (0); 1519 } 1520 } 1521 1522 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1523 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1524 mutex_exit(&pptr->port_mutex); 1525 return (ENXIO); 1526 } 1527 1528 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1529 i++) { 1530 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1531 1532 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1533 1534 1535 dev_data[i].dev_status = ENXIO; 1536 1537 if ((ptgt = fcp_lookup_target(pptr, 1538 (uchar_t *)wwn_ptr)) == NULL) { 1539 mutex_exit(&pptr->port_mutex); 1540 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1541 wwn_ptr, &error, 0) == NULL) { 1542 dev_data[i].dev_status = ENODEV; 1543 mutex_enter(&pptr->port_mutex); 1544 continue; 1545 } else { 1546 1547 dev_data[i].dev_status = EAGAIN; 1548 1549 mutex_enter(&pptr->port_mutex); 1550 continue; 1551 } 1552 } else { 1553 mutex_enter(&ptgt->tgt_mutex); 1554 if (ptgt->tgt_state & (FCP_TGT_MARK | 1555 FCP_TGT_BUSY)) { 1556 dev_data[i].dev_status = EAGAIN; 1557 mutex_exit(&ptgt->tgt_mutex); 1558 continue; 1559 } 1560 1561 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1562 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1563 dev_data[i].dev_status = ENOTSUP; 1564 } else { 1565 dev_data[i].dev_status = ENXIO; 1566 } 1567 mutex_exit(&ptgt->tgt_mutex); 1568 continue; 1569 } 1570 1571 switch (cmd) { 1572 case FCP_TGT_INQUIRY: 1573 /* 1574 * The reason we give device type of 1575 * lun 0 only even though in some 1576 * cases(like maxstrat) lun 0 device 1577 * type may be 0x3f(invalid) is that 1578 * for bridge boxes target will appear 1579 * as luns and the first lun could be 1580 * a device that utility may not care 1581 * about (like a tape device). 1582 */ 1583 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1584 dev_data[i].dev_status = 0; 1585 mutex_exit(&ptgt->tgt_mutex); 1586 1587 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1588 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1589 } else { 1590 dev_data[i].dev0_type = plun->lun_type; 1591 } 1592 mutex_enter(&ptgt->tgt_mutex); 1593 break; 1594 1595 case FCP_TGT_CREATE: 1596 mutex_exit(&ptgt->tgt_mutex); 1597 mutex_exit(&pptr->port_mutex); 1598 1599 /* 1600 * serialize state change call backs. 1601 * only one call back will be handled 1602 * at a time. 1603 */ 1604 mutex_enter(&fcp_global_mutex); 1605 if (fcp_oflag & FCP_BUSY) { 1606 mutex_exit(&fcp_global_mutex); 1607 if (dev_data) { 1608 kmem_free(dev_data, 1609 sizeof (*dev_data) * 1610 fioctl.listlen); 1611 } 1612 return (EBUSY); 1613 } 1614 fcp_oflag |= FCP_BUSY; 1615 mutex_exit(&fcp_global_mutex); 1616 1617 dev_data[i].dev_status = 1618 fcp_create_on_demand(pptr, 1619 wwn_ptr->raw_wwn); 1620 1621 if (dev_data[i].dev_status != 0) { 1622 char buf[25]; 1623 1624 for (i = 0; i < FC_WWN_SIZE; i++) { 1625 (void) sprintf(&buf[i << 1], 1626 "%02x", 1627 wwn_ptr->raw_wwn[i]); 1628 } 1629 1630 fcp_log(CE_WARN, pptr->port_dip, 1631 "!Failed to create nodes for" 1632 " pwwn=%s; error=%x", buf, 1633 dev_data[i].dev_status); 1634 } 1635 1636 /* allow state change call backs again */ 1637 mutex_enter(&fcp_global_mutex); 1638 fcp_oflag &= ~FCP_BUSY; 1639 mutex_exit(&fcp_global_mutex); 1640 1641 mutex_enter(&pptr->port_mutex); 1642 mutex_enter(&ptgt->tgt_mutex); 1643 1644 break; 1645 1646 case FCP_TGT_DELETE: 1647 break; 1648 1649 default: 1650 fcp_log(CE_WARN, pptr->port_dip, 1651 "!Invalid device data ioctl " 1652 "opcode = 0x%x", cmd); 1653 } 1654 mutex_exit(&ptgt->tgt_mutex); 1655 } 1656 } 1657 mutex_exit(&pptr->port_mutex); 1658 1659 if (ddi_copyout(dev_data, fioctl.list, 1660 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1661 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1662 return (EFAULT); 1663 } 1664 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1665 1666 #ifdef _MULTI_DATAMODEL 1667 switch (ddi_model_convert_from(mode & FMODELS)) { 1668 case DDI_MODEL_ILP32: { 1669 struct fcp32_ioctl f32_ioctl; 1670 1671 f32_ioctl.fp_minor = fioctl.fp_minor; 1672 f32_ioctl.listlen = fioctl.listlen; 1673 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1674 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1675 sizeof (struct fcp32_ioctl), mode)) { 1676 return (EFAULT); 1677 } 1678 break; 1679 } 1680 case DDI_MODEL_NONE: 1681 if (ddi_copyout((void *)&fioctl, (void *)data, 1682 sizeof (struct fcp_ioctl), mode)) { 1683 return (EFAULT); 1684 } 1685 break; 1686 } 1687 #else /* _MULTI_DATAMODEL */ 1688 1689 if (ddi_copyout((void *)&fioctl, (void *)data, 1690 sizeof (struct fcp_ioctl), mode)) { 1691 return (EFAULT); 1692 } 1693 #endif /* _MULTI_DATAMODEL */ 1694 1695 return (0); 1696 } 1697 1698 /* 1699 * Fetch the target mappings (path, etc.) for all LUNs 1700 * on this port. 1701 */ 1702 /* ARGSUSED */ 1703 static int 1704 fcp_get_target_mappings(struct fcp_ioctl *data, 1705 int mode, int *rval) 1706 { 1707 struct fcp_port *pptr; 1708 fc_hba_target_mappings_t *mappings; 1709 fc_hba_mapping_entry_t *map; 1710 struct fcp_tgt *ptgt = NULL; 1711 struct fcp_lun *plun = NULL; 1712 int i, mapIndex, mappingSize; 1713 int listlen; 1714 struct fcp_ioctl fioctl; 1715 char *path; 1716 fcp_ent_addr_t sam_lun_addr; 1717 1718 #ifdef _MULTI_DATAMODEL 1719 switch (ddi_model_convert_from(mode & FMODELS)) { 1720 case DDI_MODEL_ILP32: { 1721 struct fcp32_ioctl f32_ioctl; 1722 1723 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1724 sizeof (struct fcp32_ioctl), mode)) { 1725 return (EFAULT); 1726 } 1727 fioctl.fp_minor = f32_ioctl.fp_minor; 1728 fioctl.listlen = f32_ioctl.listlen; 1729 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1730 break; 1731 } 1732 case DDI_MODEL_NONE: 1733 if (ddi_copyin((void *)data, (void *)&fioctl, 1734 sizeof (struct fcp_ioctl), mode)) { 1735 return (EFAULT); 1736 } 1737 break; 1738 } 1739 1740 #else /* _MULTI_DATAMODEL */ 1741 if (ddi_copyin((void *)data, (void *)&fioctl, 1742 sizeof (struct fcp_ioctl), mode)) { 1743 return (EFAULT); 1744 } 1745 #endif /* _MULTI_DATAMODEL */ 1746 1747 /* 1748 * Right now we can assume that the minor number matches with 1749 * this instance of fp. If this changes we will need to 1750 * revisit this logic. 1751 */ 1752 mutex_enter(&fcp_global_mutex); 1753 pptr = fcp_port_head; 1754 while (pptr) { 1755 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1756 break; 1757 } else { 1758 pptr = pptr->port_next; 1759 } 1760 } 1761 mutex_exit(&fcp_global_mutex); 1762 if (pptr == NULL) { 1763 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1764 fioctl.fp_minor); 1765 return (ENXIO); 1766 } 1767 1768 1769 /* We use listlen to show the total buffer size */ 1770 mappingSize = fioctl.listlen; 1771 1772 /* Now calculate how many mapping entries will fit */ 1773 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1774 - sizeof (fc_hba_target_mappings_t); 1775 if (listlen <= 0) { 1776 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1777 return (ENXIO); 1778 } 1779 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1780 1781 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1782 return (ENOMEM); 1783 } 1784 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1785 1786 /* Now get to work */ 1787 mapIndex = 0; 1788 1789 mutex_enter(&pptr->port_mutex); 1790 /* Loop through all targets on this port */ 1791 for (i = 0; i < FCP_NUM_HASH; i++) { 1792 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1793 ptgt = ptgt->tgt_next) { 1794 1795 1796 /* Loop through all LUNs on this target */ 1797 for (plun = ptgt->tgt_lun; plun != NULL; 1798 plun = plun->lun_next) { 1799 if (plun->lun_state & FCP_LUN_OFFLINE) { 1800 continue; 1801 } 1802 1803 path = fcp_get_lun_path(plun); 1804 if (path == NULL) { 1805 continue; 1806 } 1807 1808 if (mapIndex >= listlen) { 1809 mapIndex ++; 1810 kmem_free(path, MAXPATHLEN); 1811 continue; 1812 } 1813 map = &mappings->entries[mapIndex++]; 1814 bcopy(path, map->targetDriver, 1815 sizeof (map->targetDriver)); 1816 map->d_id = ptgt->tgt_d_id; 1817 map->busNumber = 0; 1818 map->targetNumber = ptgt->tgt_d_id; 1819 map->osLUN = plun->lun_num; 1820 1821 /* 1822 * We had swapped lun when we stored it in 1823 * lun_addr. We need to swap it back before 1824 * returning it to user land 1825 */ 1826 1827 sam_lun_addr.ent_addr_0 = 1828 BE_16(plun->lun_addr.ent_addr_0); 1829 sam_lun_addr.ent_addr_1 = 1830 BE_16(plun->lun_addr.ent_addr_1); 1831 sam_lun_addr.ent_addr_2 = 1832 BE_16(plun->lun_addr.ent_addr_2); 1833 sam_lun_addr.ent_addr_3 = 1834 BE_16(plun->lun_addr.ent_addr_3); 1835 1836 bcopy(&sam_lun_addr, &map->samLUN, 1837 FCP_LUN_SIZE); 1838 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1839 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1840 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1841 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1842 1843 if (plun->lun_guid) { 1844 1845 /* convert ascii wwn to bytes */ 1846 fcp_ascii_to_wwn(plun->lun_guid, 1847 map->guid, sizeof (map->guid)); 1848 1849 if ((sizeof (map->guid)) < 1850 plun->lun_guid_size / 2) { 1851 cmn_err(CE_WARN, 1852 "fcp_get_target_mappings:" 1853 "guid copy space " 1854 "insufficient." 1855 "Copy Truncation - " 1856 "available %d; need %d", 1857 (int)sizeof (map->guid), 1858 (int) 1859 plun->lun_guid_size / 2); 1860 } 1861 } 1862 kmem_free(path, MAXPATHLEN); 1863 } 1864 } 1865 } 1866 mutex_exit(&pptr->port_mutex); 1867 mappings->numLuns = mapIndex; 1868 1869 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1870 kmem_free(mappings, mappingSize); 1871 return (EFAULT); 1872 } 1873 kmem_free(mappings, mappingSize); 1874 1875 #ifdef _MULTI_DATAMODEL 1876 switch (ddi_model_convert_from(mode & FMODELS)) { 1877 case DDI_MODEL_ILP32: { 1878 struct fcp32_ioctl f32_ioctl; 1879 1880 f32_ioctl.fp_minor = fioctl.fp_minor; 1881 f32_ioctl.listlen = fioctl.listlen; 1882 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1883 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1884 sizeof (struct fcp32_ioctl), mode)) { 1885 return (EFAULT); 1886 } 1887 break; 1888 } 1889 case DDI_MODEL_NONE: 1890 if (ddi_copyout((void *)&fioctl, (void *)data, 1891 sizeof (struct fcp_ioctl), mode)) { 1892 return (EFAULT); 1893 } 1894 break; 1895 } 1896 #else /* _MULTI_DATAMODEL */ 1897 1898 if (ddi_copyout((void *)&fioctl, (void *)data, 1899 sizeof (struct fcp_ioctl), mode)) { 1900 return (EFAULT); 1901 } 1902 #endif /* _MULTI_DATAMODEL */ 1903 1904 return (0); 1905 } 1906 1907 /* 1908 * fcp_setup_scsi_ioctl 1909 * Setup handler for the "scsi passthru" style of 1910 * ioctl for FCP. See "fcp_util.h" for data structure 1911 * definition. 1912 * 1913 * Input: 1914 * u_fscsi = ioctl data (user address space) 1915 * mode = See ioctl(9E) 1916 * 1917 * Output: 1918 * u_fscsi = ioctl data (user address space) 1919 * rval = return value - see ioctl(9E) 1920 * 1921 * Returns: 1922 * 0 = OK 1923 * EAGAIN = See errno.h 1924 * EBUSY = See errno.h 1925 * EFAULT = See errno.h 1926 * EINTR = See errno.h 1927 * EINVAL = See errno.h 1928 * EIO = See errno.h 1929 * ENOMEM = See errno.h 1930 * ENXIO = See errno.h 1931 * 1932 * Context: 1933 * Kernel context. 1934 */ 1935 /* ARGSUSED */ 1936 static int 1937 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1938 int mode, int *rval) 1939 { 1940 int ret = 0; 1941 int temp_ret; 1942 caddr_t k_cdbbufaddr = NULL; 1943 caddr_t k_bufaddr = NULL; 1944 caddr_t k_rqbufaddr = NULL; 1945 caddr_t u_cdbbufaddr; 1946 caddr_t u_bufaddr; 1947 caddr_t u_rqbufaddr; 1948 struct fcp_scsi_cmd k_fscsi; 1949 1950 /* 1951 * Get fcp_scsi_cmd array element from user address space 1952 */ 1953 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1954 != 0) { 1955 return (ret); 1956 } 1957 1958 1959 /* 1960 * Even though kmem_alloc() checks the validity of the 1961 * buffer length, this check is needed when the 1962 * kmem_flags set and the zero buffer length is passed. 1963 */ 1964 if ((k_fscsi.scsi_cdblen <= 0) || 1965 (k_fscsi.scsi_buflen <= 0) || 1966 (k_fscsi.scsi_buflen > FCP_MAX_RESPONSE_LEN) || 1967 (k_fscsi.scsi_rqlen <= 0) || 1968 (k_fscsi.scsi_rqlen > FCP_MAX_SENSE_LEN)) { 1969 return (EINVAL); 1970 } 1971 1972 /* 1973 * Allocate data for fcp_scsi_cmd pointer fields 1974 */ 1975 if (ret == 0) { 1976 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 1977 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 1978 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 1979 1980 if (k_cdbbufaddr == NULL || 1981 k_bufaddr == NULL || 1982 k_rqbufaddr == NULL) { 1983 ret = ENOMEM; 1984 } 1985 } 1986 1987 /* 1988 * Get fcp_scsi_cmd pointer fields from user 1989 * address space 1990 */ 1991 if (ret == 0) { 1992 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 1993 u_bufaddr = k_fscsi.scsi_bufaddr; 1994 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 1995 1996 if (ddi_copyin(u_cdbbufaddr, 1997 k_cdbbufaddr, 1998 k_fscsi.scsi_cdblen, 1999 mode)) { 2000 ret = EFAULT; 2001 } else if (ddi_copyin(u_bufaddr, 2002 k_bufaddr, 2003 k_fscsi.scsi_buflen, 2004 mode)) { 2005 ret = EFAULT; 2006 } else if (ddi_copyin(u_rqbufaddr, 2007 k_rqbufaddr, 2008 k_fscsi.scsi_rqlen, 2009 mode)) { 2010 ret = EFAULT; 2011 } 2012 } 2013 2014 /* 2015 * Send scsi command (blocking) 2016 */ 2017 if (ret == 0) { 2018 /* 2019 * Prior to sending the scsi command, the 2020 * fcp_scsi_cmd data structure must contain kernel, 2021 * not user, addresses. 2022 */ 2023 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2024 k_fscsi.scsi_bufaddr = k_bufaddr; 2025 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2026 2027 ret = fcp_send_scsi_ioctl(&k_fscsi); 2028 2029 /* 2030 * After sending the scsi command, the 2031 * fcp_scsi_cmd data structure must contain user, 2032 * not kernel, addresses. 2033 */ 2034 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2035 k_fscsi.scsi_bufaddr = u_bufaddr; 2036 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2037 } 2038 2039 /* 2040 * Put fcp_scsi_cmd pointer fields to user address space 2041 */ 2042 if (ret == 0) { 2043 if (ddi_copyout(k_cdbbufaddr, 2044 u_cdbbufaddr, 2045 k_fscsi.scsi_cdblen, 2046 mode)) { 2047 ret = EFAULT; 2048 } else if (ddi_copyout(k_bufaddr, 2049 u_bufaddr, 2050 k_fscsi.scsi_buflen, 2051 mode)) { 2052 ret = EFAULT; 2053 } else if (ddi_copyout(k_rqbufaddr, 2054 u_rqbufaddr, 2055 k_fscsi.scsi_rqlen, 2056 mode)) { 2057 ret = EFAULT; 2058 } 2059 } 2060 2061 /* 2062 * Free data for fcp_scsi_cmd pointer fields 2063 */ 2064 if (k_cdbbufaddr != NULL) { 2065 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2066 } 2067 if (k_bufaddr != NULL) { 2068 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2069 } 2070 if (k_rqbufaddr != NULL) { 2071 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2072 } 2073 2074 /* 2075 * Put fcp_scsi_cmd array element to user address space 2076 */ 2077 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2078 if (temp_ret != 0) { 2079 ret = temp_ret; 2080 } 2081 2082 /* 2083 * Return status 2084 */ 2085 return (ret); 2086 } 2087 2088 2089 /* 2090 * fcp_copyin_scsi_cmd 2091 * Copy in fcp_scsi_cmd data structure from user address space. 2092 * The data may be in 32 bit or 64 bit modes. 2093 * 2094 * Input: 2095 * base_addr = from address (user address space) 2096 * mode = See ioctl(9E) and ddi_copyin(9F) 2097 * 2098 * Output: 2099 * fscsi = to address (kernel address space) 2100 * 2101 * Returns: 2102 * 0 = OK 2103 * EFAULT = Error 2104 * 2105 * Context: 2106 * Kernel context. 2107 */ 2108 static int 2109 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2110 { 2111 #ifdef _MULTI_DATAMODEL 2112 struct fcp32_scsi_cmd f32scsi; 2113 2114 switch (ddi_model_convert_from(mode & FMODELS)) { 2115 case DDI_MODEL_ILP32: 2116 /* 2117 * Copy data from user address space 2118 */ 2119 if (ddi_copyin((void *)base_addr, 2120 &f32scsi, 2121 sizeof (struct fcp32_scsi_cmd), 2122 mode)) { 2123 return (EFAULT); 2124 } 2125 /* 2126 * Convert from 32 bit to 64 bit 2127 */ 2128 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2129 break; 2130 case DDI_MODEL_NONE: 2131 /* 2132 * Copy data from user address space 2133 */ 2134 if (ddi_copyin((void *)base_addr, 2135 fscsi, 2136 sizeof (struct fcp_scsi_cmd), 2137 mode)) { 2138 return (EFAULT); 2139 } 2140 break; 2141 } 2142 #else /* _MULTI_DATAMODEL */ 2143 /* 2144 * Copy data from user address space 2145 */ 2146 if (ddi_copyin((void *)base_addr, 2147 fscsi, 2148 sizeof (struct fcp_scsi_cmd), 2149 mode)) { 2150 return (EFAULT); 2151 } 2152 #endif /* _MULTI_DATAMODEL */ 2153 2154 return (0); 2155 } 2156 2157 2158 /* 2159 * fcp_copyout_scsi_cmd 2160 * Copy out fcp_scsi_cmd data structure to user address space. 2161 * The data may be in 32 bit or 64 bit modes. 2162 * 2163 * Input: 2164 * fscsi = to address (kernel address space) 2165 * mode = See ioctl(9E) and ddi_copyin(9F) 2166 * 2167 * Output: 2168 * base_addr = from address (user address space) 2169 * 2170 * Returns: 2171 * 0 = OK 2172 * EFAULT = Error 2173 * 2174 * Context: 2175 * Kernel context. 2176 */ 2177 static int 2178 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2179 { 2180 #ifdef _MULTI_DATAMODEL 2181 struct fcp32_scsi_cmd f32scsi; 2182 2183 switch (ddi_model_convert_from(mode & FMODELS)) { 2184 case DDI_MODEL_ILP32: 2185 /* 2186 * Convert from 64 bit to 32 bit 2187 */ 2188 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2189 /* 2190 * Copy data to user address space 2191 */ 2192 if (ddi_copyout(&f32scsi, 2193 (void *)base_addr, 2194 sizeof (struct fcp32_scsi_cmd), 2195 mode)) { 2196 return (EFAULT); 2197 } 2198 break; 2199 case DDI_MODEL_NONE: 2200 /* 2201 * Copy data to user address space 2202 */ 2203 if (ddi_copyout(fscsi, 2204 (void *)base_addr, 2205 sizeof (struct fcp_scsi_cmd), 2206 mode)) { 2207 return (EFAULT); 2208 } 2209 break; 2210 } 2211 #else /* _MULTI_DATAMODEL */ 2212 /* 2213 * Copy data to user address space 2214 */ 2215 if (ddi_copyout(fscsi, 2216 (void *)base_addr, 2217 sizeof (struct fcp_scsi_cmd), 2218 mode)) { 2219 return (EFAULT); 2220 } 2221 #endif /* _MULTI_DATAMODEL */ 2222 2223 return (0); 2224 } 2225 2226 2227 /* 2228 * fcp_send_scsi_ioctl 2229 * Sends the SCSI command in blocking mode. 2230 * 2231 * Input: 2232 * fscsi = SCSI command data structure 2233 * 2234 * Output: 2235 * fscsi = SCSI command data structure 2236 * 2237 * Returns: 2238 * 0 = OK 2239 * EAGAIN = See errno.h 2240 * EBUSY = See errno.h 2241 * EINTR = See errno.h 2242 * EINVAL = See errno.h 2243 * EIO = See errno.h 2244 * ENOMEM = See errno.h 2245 * ENXIO = See errno.h 2246 * 2247 * Context: 2248 * Kernel context. 2249 */ 2250 static int 2251 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2252 { 2253 struct fcp_lun *plun = NULL; 2254 struct fcp_port *pptr = NULL; 2255 struct fcp_tgt *ptgt = NULL; 2256 fc_packet_t *fpkt = NULL; 2257 struct fcp_ipkt *icmd = NULL; 2258 int target_created = FALSE; 2259 fc_frame_hdr_t *hp; 2260 struct fcp_cmd fcp_cmd; 2261 struct fcp_cmd *fcmd; 2262 union scsi_cdb *scsi_cdb; 2263 la_wwn_t *wwn_ptr; 2264 int nodma; 2265 struct fcp_rsp *rsp; 2266 struct fcp_rsp_info *rsp_info; 2267 caddr_t rsp_sense; 2268 int buf_len; 2269 int info_len; 2270 int sense_len; 2271 struct scsi_extended_sense *sense_to = NULL; 2272 timeout_id_t tid; 2273 uint8_t reconfig_lun = FALSE; 2274 uint8_t reconfig_pending = FALSE; 2275 uint8_t scsi_cmd; 2276 int rsp_len; 2277 int cmd_index; 2278 int fc_status; 2279 int pkt_state; 2280 int pkt_action; 2281 int pkt_reason; 2282 int ret, xport_retval = ~FC_SUCCESS; 2283 int lcount; 2284 int tcount; 2285 int reconfig_status; 2286 int port_busy = FALSE; 2287 uchar_t *lun_string; 2288 2289 /* 2290 * Check valid SCSI command 2291 */ 2292 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2293 ret = EINVAL; 2294 for (cmd_index = 0; 2295 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2296 ret != 0; 2297 cmd_index++) { 2298 /* 2299 * First byte of CDB is the SCSI command 2300 */ 2301 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2302 ret = 0; 2303 } 2304 } 2305 2306 /* 2307 * Check inputs 2308 */ 2309 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2310 ret = EINVAL; 2311 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2312 /* no larger than */ 2313 ret = EINVAL; 2314 } 2315 2316 2317 /* 2318 * Find FC port 2319 */ 2320 if (ret == 0) { 2321 /* 2322 * Acquire global mutex 2323 */ 2324 mutex_enter(&fcp_global_mutex); 2325 2326 pptr = fcp_port_head; 2327 while (pptr) { 2328 if (pptr->port_instance == 2329 (uint32_t)fscsi->scsi_fc_port_num) { 2330 break; 2331 } else { 2332 pptr = pptr->port_next; 2333 } 2334 } 2335 2336 if (pptr == NULL) { 2337 ret = ENXIO; 2338 } else { 2339 /* 2340 * fc_ulp_busy_port can raise power 2341 * so, we must not hold any mutexes involved in PM 2342 */ 2343 mutex_exit(&fcp_global_mutex); 2344 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2345 } 2346 2347 if (ret == 0) { 2348 2349 /* remember port is busy, so we will release later */ 2350 port_busy = TRUE; 2351 2352 /* 2353 * If there is a reconfiguration in progress, wait 2354 * for it to complete. 2355 */ 2356 2357 fcp_reconfig_wait(pptr); 2358 2359 /* reacquire mutexes in order */ 2360 mutex_enter(&fcp_global_mutex); 2361 mutex_enter(&pptr->port_mutex); 2362 2363 /* 2364 * Will port accept DMA? 2365 */ 2366 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2367 ? 1 : 0; 2368 2369 /* 2370 * If init or offline, device not known 2371 * 2372 * If we are discovering (onlining), we can 2373 * NOT obviously provide reliable data about 2374 * devices until it is complete 2375 */ 2376 if (pptr->port_state & (FCP_STATE_INIT | 2377 FCP_STATE_OFFLINE)) { 2378 ret = ENXIO; 2379 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2380 ret = EBUSY; 2381 } else { 2382 /* 2383 * Find target from pwwn 2384 * 2385 * The wwn must be put into a local 2386 * variable to ensure alignment. 2387 */ 2388 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2389 ptgt = fcp_lookup_target(pptr, 2390 (uchar_t *)wwn_ptr); 2391 2392 /* 2393 * If target not found, 2394 */ 2395 if (ptgt == NULL) { 2396 /* 2397 * Note: Still have global & 2398 * port mutexes 2399 */ 2400 mutex_exit(&pptr->port_mutex); 2401 ptgt = fcp_port_create_tgt(pptr, 2402 wwn_ptr, &ret, &fc_status, 2403 &pkt_state, &pkt_action, 2404 &pkt_reason); 2405 mutex_enter(&pptr->port_mutex); 2406 2407 fscsi->scsi_fc_status = fc_status; 2408 fscsi->scsi_pkt_state = 2409 (uchar_t)pkt_state; 2410 fscsi->scsi_pkt_reason = pkt_reason; 2411 fscsi->scsi_pkt_action = 2412 (uchar_t)pkt_action; 2413 2414 if (ptgt != NULL) { 2415 target_created = TRUE; 2416 } else if (ret == 0) { 2417 ret = ENOMEM; 2418 } 2419 } 2420 2421 if (ret == 0) { 2422 /* 2423 * Acquire target 2424 */ 2425 mutex_enter(&ptgt->tgt_mutex); 2426 2427 /* 2428 * If target is mark or busy, 2429 * then target can not be used 2430 */ 2431 if (ptgt->tgt_state & 2432 (FCP_TGT_MARK | 2433 FCP_TGT_BUSY)) { 2434 ret = EBUSY; 2435 } else { 2436 /* 2437 * Mark target as busy 2438 */ 2439 ptgt->tgt_state |= 2440 FCP_TGT_BUSY; 2441 } 2442 2443 /* 2444 * Release target 2445 */ 2446 lcount = pptr->port_link_cnt; 2447 tcount = ptgt->tgt_change_cnt; 2448 mutex_exit(&ptgt->tgt_mutex); 2449 } 2450 } 2451 2452 /* 2453 * Release port 2454 */ 2455 mutex_exit(&pptr->port_mutex); 2456 } 2457 2458 /* 2459 * Release global mutex 2460 */ 2461 mutex_exit(&fcp_global_mutex); 2462 } 2463 2464 if (ret == 0) { 2465 uint64_t belun = BE_64(fscsi->scsi_lun); 2466 2467 /* 2468 * If it's a target device, find lun from pwwn 2469 * The wwn must be put into a local 2470 * variable to ensure alignment. 2471 */ 2472 mutex_enter(&pptr->port_mutex); 2473 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2474 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2475 /* this is not a target */ 2476 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2477 ret = ENXIO; 2478 } else if ((belun << 16) != 0) { 2479 /* 2480 * Since fcp only support PD and LU addressing method 2481 * so far, the last 6 bytes of a valid LUN are expected 2482 * to be filled with 00h. 2483 */ 2484 fscsi->scsi_fc_status = FC_INVALID_LUN; 2485 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2486 " method 0x%02x with LUN number 0x%016" PRIx64, 2487 (uint8_t)(belun >> 62), belun); 2488 ret = ENXIO; 2489 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2490 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2491 /* 2492 * This is a SCSI target, but no LUN at this 2493 * address. 2494 * 2495 * In the future, we may want to send this to 2496 * the target, and let it respond 2497 * appropriately 2498 */ 2499 ret = ENXIO; 2500 } 2501 mutex_exit(&pptr->port_mutex); 2502 } 2503 2504 /* 2505 * Finished grabbing external resources 2506 * Allocate internal packet (icmd) 2507 */ 2508 if (ret == 0) { 2509 /* 2510 * Calc rsp len assuming rsp info included 2511 */ 2512 rsp_len = sizeof (struct fcp_rsp) + 2513 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2514 2515 icmd = fcp_icmd_alloc(pptr, ptgt, 2516 sizeof (struct fcp_cmd), 2517 rsp_len, 2518 fscsi->scsi_buflen, 2519 nodma, 2520 lcount, /* ipkt_link_cnt */ 2521 tcount, /* ipkt_change_cnt */ 2522 0, /* cause */ 2523 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2524 2525 if (icmd == NULL) { 2526 ret = ENOMEM; 2527 } else { 2528 /* 2529 * Setup internal packet as sema sync 2530 */ 2531 fcp_ipkt_sema_init(icmd); 2532 } 2533 } 2534 2535 if (ret == 0) { 2536 /* 2537 * Init fpkt pointer for use. 2538 */ 2539 2540 fpkt = icmd->ipkt_fpkt; 2541 2542 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2543 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2544 fpkt->pkt_timeout = fscsi->scsi_timeout; 2545 2546 /* 2547 * Init fcmd pointer for use by SCSI command 2548 */ 2549 2550 if (nodma) { 2551 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2552 } else { 2553 fcmd = &fcp_cmd; 2554 } 2555 bzero(fcmd, sizeof (struct fcp_cmd)); 2556 ptgt = plun->lun_tgt; 2557 2558 lun_string = (uchar_t *)&fscsi->scsi_lun; 2559 2560 fcmd->fcp_ent_addr.ent_addr_0 = 2561 BE_16(*(uint16_t *)&(lun_string[0])); 2562 fcmd->fcp_ent_addr.ent_addr_1 = 2563 BE_16(*(uint16_t *)&(lun_string[2])); 2564 fcmd->fcp_ent_addr.ent_addr_2 = 2565 BE_16(*(uint16_t *)&(lun_string[4])); 2566 fcmd->fcp_ent_addr.ent_addr_3 = 2567 BE_16(*(uint16_t *)&(lun_string[6])); 2568 2569 /* 2570 * Setup internal packet(icmd) 2571 */ 2572 icmd->ipkt_lun = plun; 2573 icmd->ipkt_restart = 0; 2574 icmd->ipkt_retries = 0; 2575 icmd->ipkt_opcode = 0; 2576 2577 /* 2578 * Init the frame HEADER Pointer for use 2579 */ 2580 hp = &fpkt->pkt_cmd_fhdr; 2581 2582 hp->s_id = pptr->port_id; 2583 hp->d_id = ptgt->tgt_d_id; 2584 hp->r_ctl = R_CTL_COMMAND; 2585 hp->type = FC_TYPE_SCSI_FCP; 2586 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2587 hp->rsvd = 0; 2588 hp->seq_id = 0; 2589 hp->seq_cnt = 0; 2590 hp->ox_id = 0xffff; 2591 hp->rx_id = 0xffff; 2592 hp->ro = 0; 2593 2594 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2595 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2596 fcmd->fcp_cntl.cntl_write_data = 0; 2597 fcmd->fcp_data_len = fscsi->scsi_buflen; 2598 2599 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2600 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2601 fscsi->scsi_cdblen); 2602 2603 if (!nodma) { 2604 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2605 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2606 } 2607 2608 /* 2609 * Send SCSI command to FC transport 2610 */ 2611 2612 if (ret == 0) { 2613 mutex_enter(&ptgt->tgt_mutex); 2614 2615 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2616 mutex_exit(&ptgt->tgt_mutex); 2617 fscsi->scsi_fc_status = xport_retval = 2618 fc_ulp_transport(pptr->port_fp_handle, 2619 fpkt); 2620 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2621 ret = EIO; 2622 } 2623 } else { 2624 mutex_exit(&ptgt->tgt_mutex); 2625 ret = EBUSY; 2626 } 2627 } 2628 } 2629 2630 /* 2631 * Wait for completion only if fc_ulp_transport was called and it 2632 * returned a success. This is the only time callback will happen. 2633 * Otherwise, there is no point in waiting 2634 */ 2635 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2636 ret = fcp_ipkt_sema_wait(icmd); 2637 } 2638 2639 /* 2640 * Copy data to IOCTL data structures 2641 */ 2642 rsp = NULL; 2643 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2644 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2645 2646 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2647 fcp_log(CE_WARN, pptr->port_dip, 2648 "!SCSI command to d_id=0x%x lun=0x%x" 2649 " failed, Bad FCP response values:" 2650 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2651 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2652 ptgt->tgt_d_id, plun->lun_num, 2653 rsp->reserved_0, rsp->reserved_1, 2654 rsp->fcp_u.fcp_status.reserved_0, 2655 rsp->fcp_u.fcp_status.reserved_1, 2656 rsp->fcp_response_len, rsp->fcp_sense_len); 2657 2658 ret = EIO; 2659 } 2660 } 2661 2662 if ((ret == 0) && (rsp != NULL)) { 2663 /* 2664 * Calc response lengths 2665 */ 2666 sense_len = 0; 2667 info_len = 0; 2668 2669 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2670 info_len = rsp->fcp_response_len; 2671 } 2672 2673 rsp_info = (struct fcp_rsp_info *) 2674 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2675 2676 /* 2677 * Get SCSI status 2678 */ 2679 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2680 /* 2681 * If a lun was just added or removed and the next command 2682 * comes through this interface, we need to capture the check 2683 * condition so we can discover the new topology. 2684 */ 2685 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2686 rsp->fcp_u.fcp_status.sense_len_set) { 2687 sense_len = rsp->fcp_sense_len; 2688 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2689 sense_to = (struct scsi_extended_sense *)rsp_sense; 2690 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2691 (FCP_SENSE_NO_LUN(sense_to))) { 2692 reconfig_lun = TRUE; 2693 } 2694 } 2695 2696 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2697 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2698 if (reconfig_lun == FALSE) { 2699 reconfig_status = 2700 fcp_is_reconfig_needed(ptgt, fpkt); 2701 } 2702 2703 if ((reconfig_lun == TRUE) || 2704 (reconfig_status == TRUE)) { 2705 mutex_enter(&ptgt->tgt_mutex); 2706 if (ptgt->tgt_tid == NULL) { 2707 /* 2708 * Either we've been notified the 2709 * REPORT_LUN data has changed, or 2710 * we've determined on our own that 2711 * we're out of date. Kick off 2712 * rediscovery. 2713 */ 2714 tid = timeout(fcp_reconfigure_luns, 2715 (caddr_t)ptgt, drv_usectohz(1)); 2716 2717 ptgt->tgt_tid = tid; 2718 ptgt->tgt_state |= FCP_TGT_BUSY; 2719 ret = EBUSY; 2720 reconfig_pending = TRUE; 2721 } 2722 mutex_exit(&ptgt->tgt_mutex); 2723 } 2724 } 2725 2726 /* 2727 * Calc residuals and buffer lengths 2728 */ 2729 2730 if (ret == 0) { 2731 buf_len = fscsi->scsi_buflen; 2732 fscsi->scsi_bufresid = 0; 2733 if (rsp->fcp_u.fcp_status.resid_under) { 2734 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2735 fscsi->scsi_bufresid = rsp->fcp_resid; 2736 } else { 2737 cmn_err(CE_WARN, "fcp: bad residue %x " 2738 "for txfer len %x", rsp->fcp_resid, 2739 fscsi->scsi_buflen); 2740 fscsi->scsi_bufresid = 2741 fscsi->scsi_buflen; 2742 } 2743 buf_len -= fscsi->scsi_bufresid; 2744 } 2745 if (rsp->fcp_u.fcp_status.resid_over) { 2746 fscsi->scsi_bufresid = -rsp->fcp_resid; 2747 } 2748 2749 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2750 if (fscsi->scsi_rqlen < sense_len) { 2751 sense_len = fscsi->scsi_rqlen; 2752 } 2753 2754 fscsi->scsi_fc_rspcode = 0; 2755 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2756 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2757 } 2758 fscsi->scsi_pkt_state = fpkt->pkt_state; 2759 fscsi->scsi_pkt_action = fpkt->pkt_action; 2760 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2761 2762 /* 2763 * Copy data and request sense 2764 * 2765 * Data must be copied by using the FCP_CP_IN macro. 2766 * This will ensure the proper byte order since the data 2767 * is being copied directly from the memory mapped 2768 * device register. 2769 * 2770 * The response (and request sense) will be in the 2771 * correct byte order. No special copy is necessary. 2772 */ 2773 2774 if (buf_len) { 2775 FCP_CP_IN(fpkt->pkt_data, 2776 fscsi->scsi_bufaddr, 2777 fpkt->pkt_data_acc, 2778 buf_len); 2779 } 2780 bcopy((void *)rsp_sense, 2781 (void *)fscsi->scsi_rqbufaddr, 2782 sense_len); 2783 } 2784 } 2785 2786 /* 2787 * Cleanup transport data structures if icmd was alloc-ed 2788 * So, cleanup happens in the same thread that icmd was alloc-ed 2789 */ 2790 if (icmd != NULL) { 2791 fcp_ipkt_sema_cleanup(icmd); 2792 } 2793 2794 /* restore pm busy/idle status */ 2795 if (port_busy) { 2796 fc_ulp_idle_port(pptr->port_fp_handle); 2797 } 2798 2799 /* 2800 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2801 * flag, it'll be cleared when the reconfig is complete. 2802 */ 2803 if ((ptgt != NULL) && !reconfig_pending) { 2804 /* 2805 * If target was created, 2806 */ 2807 if (target_created) { 2808 mutex_enter(&ptgt->tgt_mutex); 2809 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2810 mutex_exit(&ptgt->tgt_mutex); 2811 } else { 2812 /* 2813 * De-mark target as busy 2814 */ 2815 mutex_enter(&ptgt->tgt_mutex); 2816 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2817 mutex_exit(&ptgt->tgt_mutex); 2818 } 2819 } 2820 return (ret); 2821 } 2822 2823 2824 static int 2825 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2826 fc_packet_t *fpkt) 2827 { 2828 uchar_t *lun_string; 2829 uint16_t lun_num, i; 2830 int num_luns; 2831 int actual_luns; 2832 int num_masked_luns; 2833 int lun_buflen; 2834 struct fcp_lun *plun = NULL; 2835 struct fcp_reportlun_resp *report_lun; 2836 uint8_t reconfig_needed = FALSE; 2837 uint8_t lun_exists = FALSE; 2838 2839 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2840 2841 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2842 fpkt->pkt_datalen); 2843 2844 /* get number of luns (which is supplied as LUNS * 8) */ 2845 num_luns = BE_32(report_lun->num_lun) >> 3; 2846 2847 /* 2848 * Figure out exactly how many lun strings our response buffer 2849 * can hold. 2850 */ 2851 lun_buflen = (fpkt->pkt_datalen - 2852 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2853 2854 /* 2855 * Is our response buffer full or not? We don't want to 2856 * potentially walk beyond the number of luns we have. 2857 */ 2858 if (num_luns <= lun_buflen) { 2859 actual_luns = num_luns; 2860 } else { 2861 actual_luns = lun_buflen; 2862 } 2863 2864 mutex_enter(&ptgt->tgt_mutex); 2865 2866 /* Scan each lun to see if we have masked it. */ 2867 num_masked_luns = 0; 2868 if (fcp_lun_blacklist != NULL) { 2869 for (i = 0; i < actual_luns; i++) { 2870 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2871 switch (lun_string[0] & 0xC0) { 2872 case FCP_LUN_ADDRESSING: 2873 case FCP_PD_ADDRESSING: 2874 lun_num = ((lun_string[0] & 0x3F) << 8) 2875 | lun_string[1]; 2876 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2877 lun_num) == TRUE) { 2878 num_masked_luns++; 2879 } 2880 break; 2881 default: 2882 break; 2883 } 2884 } 2885 } 2886 2887 /* 2888 * The quick and easy check. If the number of LUNs reported 2889 * doesn't match the number we currently know about, we need 2890 * to reconfigure. 2891 */ 2892 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2893 mutex_exit(&ptgt->tgt_mutex); 2894 kmem_free(report_lun, fpkt->pkt_datalen); 2895 return (TRUE); 2896 } 2897 2898 /* 2899 * If the quick and easy check doesn't turn up anything, we walk 2900 * the list of luns from the REPORT_LUN response and look for 2901 * any luns we don't know about. If we find one, we know we need 2902 * to reconfigure. We will skip LUNs that are masked because of the 2903 * blacklist. 2904 */ 2905 for (i = 0; i < actual_luns; i++) { 2906 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2907 lun_exists = FALSE; 2908 switch (lun_string[0] & 0xC0) { 2909 case FCP_LUN_ADDRESSING: 2910 case FCP_PD_ADDRESSING: 2911 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2912 2913 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2914 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2915 lun_exists = TRUE; 2916 break; 2917 } 2918 2919 for (plun = ptgt->tgt_lun; plun; 2920 plun = plun->lun_next) { 2921 if (plun->lun_num == lun_num) { 2922 lun_exists = TRUE; 2923 break; 2924 } 2925 } 2926 break; 2927 default: 2928 break; 2929 } 2930 2931 if (lun_exists == FALSE) { 2932 reconfig_needed = TRUE; 2933 break; 2934 } 2935 } 2936 2937 mutex_exit(&ptgt->tgt_mutex); 2938 kmem_free(report_lun, fpkt->pkt_datalen); 2939 2940 return (reconfig_needed); 2941 } 2942 2943 /* 2944 * This function is called by fcp_handle_page83 and uses inquiry response data 2945 * stored in plun->lun_inq to determine whether or not a device is a member of 2946 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2947 * otherwise 1. 2948 */ 2949 static int 2950 fcp_symmetric_device_probe(struct fcp_lun *plun) 2951 { 2952 struct scsi_inquiry *stdinq = &plun->lun_inq; 2953 char *devidptr; 2954 int i, len; 2955 2956 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2957 devidptr = fcp_symmetric_disk_table[i]; 2958 len = (int)strlen(devidptr); 2959 2960 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 2961 return (0); 2962 } 2963 } 2964 return (1); 2965 } 2966 2967 2968 /* 2969 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 2970 * It basically returns the current count of # of state change callbacks 2971 * i.e the value of tgt_change_cnt. 2972 * 2973 * INPUT: 2974 * fcp_ioctl.fp_minor -> The minor # of the fp port 2975 * fcp_ioctl.listlen -> 1 2976 * fcp_ioctl.list -> Pointer to a 32 bit integer 2977 */ 2978 /*ARGSUSED2*/ 2979 static int 2980 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 2981 { 2982 int ret; 2983 uint32_t link_cnt; 2984 struct fcp_ioctl fioctl; 2985 struct fcp_port *pptr = NULL; 2986 2987 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 2988 &pptr)) != 0) { 2989 return (ret); 2990 } 2991 2992 ASSERT(pptr != NULL); 2993 2994 if (fioctl.listlen != 1) { 2995 return (EINVAL); 2996 } 2997 2998 mutex_enter(&pptr->port_mutex); 2999 if (pptr->port_state & FCP_STATE_OFFLINE) { 3000 mutex_exit(&pptr->port_mutex); 3001 return (ENXIO); 3002 } 3003 3004 /* 3005 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3006 * When the fcp initially attaches to the port and there are nothing 3007 * hanging out of the port or if there was a repeat offline state change 3008 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3009 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3010 * will differentiate the 2 cases. 3011 */ 3012 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3013 mutex_exit(&pptr->port_mutex); 3014 return (ENXIO); 3015 } 3016 3017 link_cnt = pptr->port_link_cnt; 3018 mutex_exit(&pptr->port_mutex); 3019 3020 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3021 return (EFAULT); 3022 } 3023 3024 #ifdef _MULTI_DATAMODEL 3025 switch (ddi_model_convert_from(mode & FMODELS)) { 3026 case DDI_MODEL_ILP32: { 3027 struct fcp32_ioctl f32_ioctl; 3028 3029 f32_ioctl.fp_minor = fioctl.fp_minor; 3030 f32_ioctl.listlen = fioctl.listlen; 3031 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3032 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3033 sizeof (struct fcp32_ioctl), mode)) { 3034 return (EFAULT); 3035 } 3036 break; 3037 } 3038 case DDI_MODEL_NONE: 3039 if (ddi_copyout((void *)&fioctl, (void *)data, 3040 sizeof (struct fcp_ioctl), mode)) { 3041 return (EFAULT); 3042 } 3043 break; 3044 } 3045 #else /* _MULTI_DATAMODEL */ 3046 3047 if (ddi_copyout((void *)&fioctl, (void *)data, 3048 sizeof (struct fcp_ioctl), mode)) { 3049 return (EFAULT); 3050 } 3051 #endif /* _MULTI_DATAMODEL */ 3052 3053 return (0); 3054 } 3055 3056 /* 3057 * This function copies the fcp_ioctl structure passed in from user land 3058 * into kernel land. Handles 32 bit applications. 3059 */ 3060 /*ARGSUSED*/ 3061 static int 3062 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3063 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3064 { 3065 struct fcp_port *t_pptr; 3066 3067 #ifdef _MULTI_DATAMODEL 3068 switch (ddi_model_convert_from(mode & FMODELS)) { 3069 case DDI_MODEL_ILP32: { 3070 struct fcp32_ioctl f32_ioctl; 3071 3072 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3073 sizeof (struct fcp32_ioctl), mode)) { 3074 return (EFAULT); 3075 } 3076 fioctl->fp_minor = f32_ioctl.fp_minor; 3077 fioctl->listlen = f32_ioctl.listlen; 3078 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3079 break; 3080 } 3081 case DDI_MODEL_NONE: 3082 if (ddi_copyin((void *)data, (void *)fioctl, 3083 sizeof (struct fcp_ioctl), mode)) { 3084 return (EFAULT); 3085 } 3086 break; 3087 } 3088 3089 #else /* _MULTI_DATAMODEL */ 3090 if (ddi_copyin((void *)data, (void *)fioctl, 3091 sizeof (struct fcp_ioctl), mode)) { 3092 return (EFAULT); 3093 } 3094 #endif /* _MULTI_DATAMODEL */ 3095 3096 /* 3097 * Right now we can assume that the minor number matches with 3098 * this instance of fp. If this changes we will need to 3099 * revisit this logic. 3100 */ 3101 mutex_enter(&fcp_global_mutex); 3102 t_pptr = fcp_port_head; 3103 while (t_pptr) { 3104 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3105 break; 3106 } else { 3107 t_pptr = t_pptr->port_next; 3108 } 3109 } 3110 *pptr = t_pptr; 3111 mutex_exit(&fcp_global_mutex); 3112 if (t_pptr == NULL) { 3113 return (ENXIO); 3114 } 3115 3116 return (0); 3117 } 3118 3119 /* 3120 * Function: fcp_port_create_tgt 3121 * 3122 * Description: As the name suggest this function creates the target context 3123 * specified by the the WWN provided by the caller. If the 3124 * creation goes well and the target is known by fp/fctl a PLOGI 3125 * followed by a PRLI are issued. 3126 * 3127 * Argument: pptr fcp port structure 3128 * pwwn WWN of the target 3129 * ret_val Address of the return code. It could be: 3130 * EIO, ENOMEM or 0. 3131 * fc_status PLOGI or PRLI status completion 3132 * fc_pkt_state PLOGI or PRLI state completion 3133 * fc_pkt_reason PLOGI or PRLI reason completion 3134 * fc_pkt_action PLOGI or PRLI action completion 3135 * 3136 * Return Value: NULL if it failed 3137 * Target structure address if it succeeds 3138 */ 3139 static struct fcp_tgt * 3140 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3141 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3142 { 3143 struct fcp_tgt *ptgt = NULL; 3144 fc_portmap_t devlist; 3145 int lcount; 3146 int error; 3147 3148 *ret_val = 0; 3149 3150 /* 3151 * Check FC port device & get port map 3152 */ 3153 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3154 &error, 1) == NULL) { 3155 *ret_val = EIO; 3156 } else { 3157 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3158 &devlist) != FC_SUCCESS) { 3159 *ret_val = EIO; 3160 } 3161 } 3162 3163 /* Set port map flags */ 3164 devlist.map_type = PORT_DEVICE_USER_CREATE; 3165 3166 /* Allocate target */ 3167 if (*ret_val == 0) { 3168 lcount = pptr->port_link_cnt; 3169 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3170 if (ptgt == NULL) { 3171 fcp_log(CE_WARN, pptr->port_dip, 3172 "!FC target allocation failed"); 3173 *ret_val = ENOMEM; 3174 } else { 3175 /* Setup target */ 3176 mutex_enter(&ptgt->tgt_mutex); 3177 3178 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3179 ptgt->tgt_tmp_cnt = 1; 3180 ptgt->tgt_d_id = devlist.map_did.port_id; 3181 ptgt->tgt_hard_addr = 3182 devlist.map_hard_addr.hard_addr; 3183 ptgt->tgt_pd_handle = devlist.map_pd; 3184 ptgt->tgt_fca_dev = NULL; 3185 3186 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3187 FC_WWN_SIZE); 3188 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3189 FC_WWN_SIZE); 3190 3191 mutex_exit(&ptgt->tgt_mutex); 3192 } 3193 } 3194 3195 /* Release global mutex for PLOGI and PRLI */ 3196 mutex_exit(&fcp_global_mutex); 3197 3198 /* Send PLOGI (If necessary) */ 3199 if (*ret_val == 0) { 3200 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3201 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3202 } 3203 3204 /* Send PRLI (If necessary) */ 3205 if (*ret_val == 0) { 3206 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3207 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3208 } 3209 3210 mutex_enter(&fcp_global_mutex); 3211 3212 return (ptgt); 3213 } 3214 3215 /* 3216 * Function: fcp_tgt_send_plogi 3217 * 3218 * Description: This function sends a PLOGI to the target specified by the 3219 * caller and waits till it completes. 3220 * 3221 * Argument: ptgt Target to send the plogi to. 3222 * fc_status Status returned by fp/fctl in the PLOGI request. 3223 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3224 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3225 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3226 * 3227 * Return Value: 0 3228 * ENOMEM 3229 * EIO 3230 * 3231 * Context: User context. 3232 */ 3233 static int 3234 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3235 int *fc_pkt_reason, int *fc_pkt_action) 3236 { 3237 struct fcp_port *pptr; 3238 struct fcp_ipkt *icmd; 3239 struct fc_packet *fpkt; 3240 fc_frame_hdr_t *hp; 3241 struct la_els_logi logi; 3242 int tcount; 3243 int lcount; 3244 int ret, login_retval = ~FC_SUCCESS; 3245 3246 ret = 0; 3247 3248 pptr = ptgt->tgt_port; 3249 3250 lcount = pptr->port_link_cnt; 3251 tcount = ptgt->tgt_change_cnt; 3252 3253 /* Alloc internal packet */ 3254 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3255 sizeof (la_els_logi_t), 0, 0, lcount, tcount, 0, 3256 FC_INVALID_RSCN_COUNT); 3257 3258 if (icmd == NULL) { 3259 ret = ENOMEM; 3260 } else { 3261 /* 3262 * Setup internal packet as sema sync 3263 */ 3264 fcp_ipkt_sema_init(icmd); 3265 3266 /* 3267 * Setup internal packet (icmd) 3268 */ 3269 icmd->ipkt_lun = NULL; 3270 icmd->ipkt_restart = 0; 3271 icmd->ipkt_retries = 0; 3272 icmd->ipkt_opcode = LA_ELS_PLOGI; 3273 3274 /* 3275 * Setup fc_packet 3276 */ 3277 fpkt = icmd->ipkt_fpkt; 3278 3279 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3280 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3281 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3282 3283 /* 3284 * Setup FC frame header 3285 */ 3286 hp = &fpkt->pkt_cmd_fhdr; 3287 3288 hp->s_id = pptr->port_id; /* source ID */ 3289 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3290 hp->r_ctl = R_CTL_ELS_REQ; 3291 hp->type = FC_TYPE_EXTENDED_LS; 3292 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3293 hp->seq_id = 0; 3294 hp->rsvd = 0; 3295 hp->df_ctl = 0; 3296 hp->seq_cnt = 0; 3297 hp->ox_id = 0xffff; /* i.e. none */ 3298 hp->rx_id = 0xffff; /* i.e. none */ 3299 hp->ro = 0; 3300 3301 /* 3302 * Setup PLOGI 3303 */ 3304 bzero(&logi, sizeof (struct la_els_logi)); 3305 logi.ls_code.ls_code = LA_ELS_PLOGI; 3306 3307 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3308 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3309 3310 /* 3311 * Send PLOGI 3312 */ 3313 *fc_status = login_retval = 3314 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3315 if (*fc_status != FC_SUCCESS) { 3316 ret = EIO; 3317 } 3318 } 3319 3320 /* 3321 * Wait for completion 3322 */ 3323 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3324 ret = fcp_ipkt_sema_wait(icmd); 3325 3326 *fc_pkt_state = fpkt->pkt_state; 3327 *fc_pkt_reason = fpkt->pkt_reason; 3328 *fc_pkt_action = fpkt->pkt_action; 3329 } 3330 3331 /* 3332 * Cleanup transport data structures if icmd was alloc-ed AND if there 3333 * is going to be no callback (i.e if fc_ulp_login() failed). 3334 * Otherwise, cleanup happens in callback routine. 3335 */ 3336 if (icmd != NULL) { 3337 fcp_ipkt_sema_cleanup(icmd); 3338 } 3339 3340 return (ret); 3341 } 3342 3343 /* 3344 * Function: fcp_tgt_send_prli 3345 * 3346 * Description: Does nothing as of today. 3347 * 3348 * Argument: ptgt Target to send the prli to. 3349 * fc_status Status returned by fp/fctl in the PRLI request. 3350 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3351 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3352 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3353 * 3354 * Return Value: 0 3355 */ 3356 /*ARGSUSED*/ 3357 static int 3358 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3359 int *fc_pkt_reason, int *fc_pkt_action) 3360 { 3361 return (0); 3362 } 3363 3364 /* 3365 * Function: fcp_ipkt_sema_init 3366 * 3367 * Description: Initializes the semaphore contained in the internal packet. 3368 * 3369 * Argument: icmd Internal packet the semaphore of which must be 3370 * initialized. 3371 * 3372 * Return Value: None 3373 * 3374 * Context: User context only. 3375 */ 3376 static void 3377 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3378 { 3379 struct fc_packet *fpkt; 3380 3381 fpkt = icmd->ipkt_fpkt; 3382 3383 /* Create semaphore for sync */ 3384 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3385 3386 /* Setup the completion callback */ 3387 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3388 } 3389 3390 /* 3391 * Function: fcp_ipkt_sema_wait 3392 * 3393 * Description: Wait on the semaphore embedded in the internal packet. The 3394 * semaphore is released in the callback. 3395 * 3396 * Argument: icmd Internal packet to wait on for completion. 3397 * 3398 * Return Value: 0 3399 * EIO 3400 * EBUSY 3401 * EAGAIN 3402 * 3403 * Context: User context only. 3404 * 3405 * This function does a conversion between the field pkt_state of the fc_packet 3406 * embedded in the internal packet (icmd) and the code it returns. 3407 */ 3408 static int 3409 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3410 { 3411 struct fc_packet *fpkt; 3412 int ret; 3413 3414 ret = EIO; 3415 fpkt = icmd->ipkt_fpkt; 3416 3417 /* 3418 * Wait on semaphore 3419 */ 3420 sema_p(&(icmd->ipkt_sema)); 3421 3422 /* 3423 * Check the status of the FC packet 3424 */ 3425 switch (fpkt->pkt_state) { 3426 case FC_PKT_SUCCESS: 3427 ret = 0; 3428 break; 3429 case FC_PKT_LOCAL_RJT: 3430 switch (fpkt->pkt_reason) { 3431 case FC_REASON_SEQ_TIMEOUT: 3432 case FC_REASON_RX_BUF_TIMEOUT: 3433 ret = EAGAIN; 3434 break; 3435 case FC_REASON_PKT_BUSY: 3436 ret = EBUSY; 3437 break; 3438 } 3439 break; 3440 case FC_PKT_TIMEOUT: 3441 ret = EAGAIN; 3442 break; 3443 case FC_PKT_LOCAL_BSY: 3444 case FC_PKT_TRAN_BSY: 3445 case FC_PKT_NPORT_BSY: 3446 case FC_PKT_FABRIC_BSY: 3447 ret = EBUSY; 3448 break; 3449 case FC_PKT_LS_RJT: 3450 case FC_PKT_BA_RJT: 3451 switch (fpkt->pkt_reason) { 3452 case FC_REASON_LOGICAL_BSY: 3453 ret = EBUSY; 3454 break; 3455 } 3456 break; 3457 case FC_PKT_FS_RJT: 3458 switch (fpkt->pkt_reason) { 3459 case FC_REASON_FS_LOGICAL_BUSY: 3460 ret = EBUSY; 3461 break; 3462 } 3463 break; 3464 } 3465 3466 return (ret); 3467 } 3468 3469 /* 3470 * Function: fcp_ipkt_sema_callback 3471 * 3472 * Description: Registered as the completion callback function for the FC 3473 * transport when the ipkt semaphore is used for sync. This will 3474 * cleanup the used data structures, if necessary and wake up 3475 * the user thread to complete the transaction. 3476 * 3477 * Argument: fpkt FC packet (points to the icmd) 3478 * 3479 * Return Value: None 3480 * 3481 * Context: User context only 3482 */ 3483 static void 3484 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3485 { 3486 struct fcp_ipkt *icmd; 3487 3488 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3489 3490 /* 3491 * Wake up user thread 3492 */ 3493 sema_v(&(icmd->ipkt_sema)); 3494 } 3495 3496 /* 3497 * Function: fcp_ipkt_sema_cleanup 3498 * 3499 * Description: Called to cleanup (if necessary) the data structures used 3500 * when ipkt sema is used for sync. This function will detect 3501 * whether the caller is the last thread (via counter) and 3502 * cleanup only if necessary. 3503 * 3504 * Argument: icmd Internal command packet 3505 * 3506 * Return Value: None 3507 * 3508 * Context: User context only 3509 */ 3510 static void 3511 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3512 { 3513 struct fcp_tgt *ptgt; 3514 struct fcp_port *pptr; 3515 3516 ptgt = icmd->ipkt_tgt; 3517 pptr = icmd->ipkt_port; 3518 3519 /* 3520 * Acquire data structure 3521 */ 3522 mutex_enter(&ptgt->tgt_mutex); 3523 3524 /* 3525 * Destroy semaphore 3526 */ 3527 sema_destroy(&(icmd->ipkt_sema)); 3528 3529 /* 3530 * Cleanup internal packet 3531 */ 3532 mutex_exit(&ptgt->tgt_mutex); 3533 fcp_icmd_free(pptr, icmd); 3534 } 3535 3536 /* 3537 * Function: fcp_port_attach 3538 * 3539 * Description: Called by the transport framework to resume, suspend or 3540 * attach a new port. 3541 * 3542 * Argument: ulph Port handle 3543 * *pinfo Port information 3544 * cmd Command 3545 * s_id Port ID 3546 * 3547 * Return Value: FC_FAILURE or FC_SUCCESS 3548 */ 3549 /*ARGSUSED*/ 3550 static int 3551 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3552 fc_attach_cmd_t cmd, uint32_t s_id) 3553 { 3554 int instance; 3555 int res = FC_FAILURE; /* default result */ 3556 3557 ASSERT(pinfo != NULL); 3558 3559 instance = ddi_get_instance(pinfo->port_dip); 3560 3561 switch (cmd) { 3562 case FC_CMD_ATTACH: 3563 /* 3564 * this port instance attaching for the first time (or after 3565 * being detached before) 3566 */ 3567 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3568 instance) == DDI_SUCCESS) { 3569 res = FC_SUCCESS; 3570 } else { 3571 ASSERT(ddi_get_soft_state(fcp_softstate, 3572 instance) == NULL); 3573 } 3574 break; 3575 3576 case FC_CMD_RESUME: 3577 case FC_CMD_POWER_UP: 3578 /* 3579 * this port instance was attached and the suspended and 3580 * will now be resumed 3581 */ 3582 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3583 instance) == DDI_SUCCESS) { 3584 res = FC_SUCCESS; 3585 } 3586 break; 3587 3588 default: 3589 /* shouldn't happen */ 3590 FCP_TRACE(fcp_logq, "fcp", 3591 fcp_trace, FCP_BUF_LEVEL_2, 0, 3592 "port_attach: unknown cmdcommand: %d", cmd); 3593 break; 3594 } 3595 3596 /* return result */ 3597 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3598 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3599 3600 return (res); 3601 } 3602 3603 3604 /* 3605 * detach or suspend this port instance 3606 * 3607 * acquires and releases the global mutex 3608 * 3609 * acquires and releases the mutex for this port 3610 * 3611 * acquires and releases the hotplug mutex for this port 3612 */ 3613 /*ARGSUSED*/ 3614 static int 3615 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3616 fc_detach_cmd_t cmd) 3617 { 3618 int flag; 3619 int instance; 3620 struct fcp_port *pptr; 3621 3622 instance = ddi_get_instance(info->port_dip); 3623 pptr = ddi_get_soft_state(fcp_softstate, instance); 3624 3625 switch (cmd) { 3626 case FC_CMD_SUSPEND: 3627 FCP_DTRACE(fcp_logq, "fcp", 3628 fcp_trace, FCP_BUF_LEVEL_8, 0, 3629 "port suspend called for port %d", instance); 3630 flag = FCP_STATE_SUSPENDED; 3631 break; 3632 3633 case FC_CMD_POWER_DOWN: 3634 FCP_DTRACE(fcp_logq, "fcp", 3635 fcp_trace, FCP_BUF_LEVEL_8, 0, 3636 "port power down called for port %d", instance); 3637 flag = FCP_STATE_POWER_DOWN; 3638 break; 3639 3640 case FC_CMD_DETACH: 3641 FCP_DTRACE(fcp_logq, "fcp", 3642 fcp_trace, FCP_BUF_LEVEL_8, 0, 3643 "port detach called for port %d", instance); 3644 flag = FCP_STATE_DETACHING; 3645 break; 3646 3647 default: 3648 /* shouldn't happen */ 3649 return (FC_FAILURE); 3650 } 3651 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3652 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3653 3654 return (fcp_handle_port_detach(pptr, flag, instance)); 3655 } 3656 3657 3658 /* 3659 * called for ioctls on the transport's devctl interface, and the transport 3660 * has passed it to us 3661 * 3662 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3663 * 3664 * return FC_SUCCESS if we decide to claim the ioctl, 3665 * else return FC_UNCLAIMED 3666 * 3667 * *rval is set iff we decide to claim the ioctl 3668 */ 3669 /*ARGSUSED*/ 3670 static int 3671 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3672 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3673 { 3674 int retval = FC_UNCLAIMED; /* return value */ 3675 struct fcp_port *pptr = NULL; /* our soft state */ 3676 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3677 dev_info_t *cdip; 3678 mdi_pathinfo_t *pip = NULL; 3679 char *ndi_nm; /* NDI name */ 3680 char *ndi_addr; /* NDI addr */ 3681 int is_mpxio, circ; 3682 int devi_entered = 0; 3683 time_t end_time; 3684 3685 ASSERT(rval != NULL); 3686 3687 FCP_DTRACE(fcp_logq, "fcp", 3688 fcp_trace, FCP_BUF_LEVEL_8, 0, 3689 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3690 3691 /* if already claimed then forget it */ 3692 if (claimed) { 3693 /* 3694 * for now, if this ioctl has already been claimed, then 3695 * we just ignore it 3696 */ 3697 return (retval); 3698 } 3699 3700 /* get our port info */ 3701 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3702 fcp_log(CE_WARN, NULL, 3703 "!fcp:Invalid port handle handle in ioctl"); 3704 *rval = ENXIO; 3705 return (retval); 3706 } 3707 is_mpxio = pptr->port_mpxio; 3708 3709 switch (cmd) { 3710 case DEVCTL_BUS_GETSTATE: 3711 case DEVCTL_BUS_QUIESCE: 3712 case DEVCTL_BUS_UNQUIESCE: 3713 case DEVCTL_BUS_RESET: 3714 case DEVCTL_BUS_RESETALL: 3715 3716 case DEVCTL_BUS_DEV_CREATE: 3717 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3718 return (retval); 3719 } 3720 break; 3721 3722 case DEVCTL_DEVICE_GETSTATE: 3723 case DEVCTL_DEVICE_OFFLINE: 3724 case DEVCTL_DEVICE_ONLINE: 3725 case DEVCTL_DEVICE_REMOVE: 3726 case DEVCTL_DEVICE_RESET: 3727 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3728 return (retval); 3729 } 3730 3731 ASSERT(dcp != NULL); 3732 3733 /* ensure we have a name and address */ 3734 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3735 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3736 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3737 fcp_trace, FCP_BUF_LEVEL_2, 0, 3738 "ioctl: can't get name (%s) or addr (%s)", 3739 ndi_nm ? ndi_nm : "<null ptr>", 3740 ndi_addr ? ndi_addr : "<null ptr>"); 3741 ndi_dc_freehdl(dcp); 3742 return (retval); 3743 } 3744 3745 3746 /* get our child's DIP */ 3747 ASSERT(pptr != NULL); 3748 if (is_mpxio) { 3749 mdi_devi_enter(pptr->port_dip, &circ); 3750 } else { 3751 ndi_devi_enter(pptr->port_dip, &circ); 3752 } 3753 devi_entered = 1; 3754 3755 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3756 ndi_addr)) == NULL) { 3757 /* Look for virtually enumerated devices. */ 3758 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3759 if (pip == NULL || 3760 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3761 *rval = ENXIO; 3762 goto out; 3763 } 3764 } 3765 break; 3766 3767 default: 3768 *rval = ENOTTY; 3769 return (retval); 3770 } 3771 3772 /* this ioctl is ours -- process it */ 3773 3774 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3775 3776 /* we assume it will be a success; else we'll set error value */ 3777 *rval = 0; 3778 3779 3780 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3781 fcp_trace, FCP_BUF_LEVEL_8, 0, 3782 "ioctl: claiming this one"); 3783 3784 /* handle ioctls now */ 3785 switch (cmd) { 3786 case DEVCTL_DEVICE_GETSTATE: 3787 ASSERT(cdip != NULL); 3788 ASSERT(dcp != NULL); 3789 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3790 *rval = EFAULT; 3791 } 3792 break; 3793 3794 case DEVCTL_DEVICE_REMOVE: 3795 case DEVCTL_DEVICE_OFFLINE: { 3796 int flag = 0; 3797 int lcount; 3798 int tcount; 3799 struct fcp_pkt *head = NULL; 3800 struct fcp_lun *plun; 3801 child_info_t *cip = CIP(cdip); 3802 int all = 1; 3803 struct fcp_lun *tplun; 3804 struct fcp_tgt *ptgt; 3805 3806 ASSERT(pptr != NULL); 3807 ASSERT(cdip != NULL); 3808 3809 mutex_enter(&pptr->port_mutex); 3810 if (pip != NULL) { 3811 cip = CIP(pip); 3812 } 3813 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3814 mutex_exit(&pptr->port_mutex); 3815 *rval = ENXIO; 3816 break; 3817 } 3818 3819 head = fcp_scan_commands(plun); 3820 if (head != NULL) { 3821 fcp_abort_commands(head, LUN_PORT); 3822 } 3823 lcount = pptr->port_link_cnt; 3824 tcount = plun->lun_tgt->tgt_change_cnt; 3825 mutex_exit(&pptr->port_mutex); 3826 3827 if (cmd == DEVCTL_DEVICE_REMOVE) { 3828 flag = NDI_DEVI_REMOVE; 3829 } 3830 3831 if (is_mpxio) { 3832 mdi_devi_exit(pptr->port_dip, circ); 3833 } else { 3834 ndi_devi_exit(pptr->port_dip, circ); 3835 } 3836 devi_entered = 0; 3837 3838 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3839 FCP_OFFLINE, lcount, tcount, flag); 3840 3841 if (*rval != NDI_SUCCESS) { 3842 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3843 break; 3844 } 3845 3846 fcp_update_offline_flags(plun); 3847 3848 ptgt = plun->lun_tgt; 3849 mutex_enter(&ptgt->tgt_mutex); 3850 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3851 tplun->lun_next) { 3852 mutex_enter(&tplun->lun_mutex); 3853 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3854 all = 0; 3855 } 3856 mutex_exit(&tplun->lun_mutex); 3857 } 3858 3859 if (all) { 3860 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3861 /* 3862 * The user is unconfiguring/offlining the device. 3863 * If fabric and the auto configuration is set 3864 * then make sure the user is the only one who 3865 * can reconfigure the device. 3866 */ 3867 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3868 fcp_enable_auto_configuration) { 3869 ptgt->tgt_manual_config_only = 1; 3870 } 3871 } 3872 mutex_exit(&ptgt->tgt_mutex); 3873 break; 3874 } 3875 3876 case DEVCTL_DEVICE_ONLINE: { 3877 int lcount; 3878 int tcount; 3879 struct fcp_lun *plun; 3880 child_info_t *cip = CIP(cdip); 3881 3882 ASSERT(cdip != NULL); 3883 ASSERT(pptr != NULL); 3884 3885 mutex_enter(&pptr->port_mutex); 3886 if (pip != NULL) { 3887 cip = CIP(pip); 3888 } 3889 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3890 mutex_exit(&pptr->port_mutex); 3891 *rval = ENXIO; 3892 break; 3893 } 3894 lcount = pptr->port_link_cnt; 3895 tcount = plun->lun_tgt->tgt_change_cnt; 3896 mutex_exit(&pptr->port_mutex); 3897 3898 /* 3899 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3900 * to allow the device attach to occur when the device is 3901 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3902 * from the scsi_probe()). 3903 */ 3904 mutex_enter(&LUN_TGT->tgt_mutex); 3905 plun->lun_state |= FCP_LUN_ONLINING; 3906 mutex_exit(&LUN_TGT->tgt_mutex); 3907 3908 if (is_mpxio) { 3909 mdi_devi_exit(pptr->port_dip, circ); 3910 } else { 3911 ndi_devi_exit(pptr->port_dip, circ); 3912 } 3913 devi_entered = 0; 3914 3915 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3916 FCP_ONLINE, lcount, tcount, 0); 3917 3918 if (*rval != NDI_SUCCESS) { 3919 /* Reset the FCP_LUN_ONLINING bit */ 3920 mutex_enter(&LUN_TGT->tgt_mutex); 3921 plun->lun_state &= ~FCP_LUN_ONLINING; 3922 mutex_exit(&LUN_TGT->tgt_mutex); 3923 *rval = EIO; 3924 break; 3925 } 3926 mutex_enter(&LUN_TGT->tgt_mutex); 3927 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3928 FCP_LUN_ONLINING); 3929 mutex_exit(&LUN_TGT->tgt_mutex); 3930 break; 3931 } 3932 3933 case DEVCTL_BUS_DEV_CREATE: { 3934 uchar_t *bytes = NULL; 3935 uint_t nbytes; 3936 struct fcp_tgt *ptgt = NULL; 3937 struct fcp_lun *plun = NULL; 3938 dev_info_t *useless_dip = NULL; 3939 3940 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3941 DEVCTL_CONSTRUCT, &useless_dip); 3942 if (*rval != 0 || useless_dip == NULL) { 3943 break; 3944 } 3945 3946 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3947 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3948 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3949 *rval = EINVAL; 3950 (void) ndi_devi_free(useless_dip); 3951 if (bytes != NULL) { 3952 ddi_prop_free(bytes); 3953 } 3954 break; 3955 } 3956 3957 *rval = fcp_create_on_demand(pptr, bytes); 3958 if (*rval == 0) { 3959 mutex_enter(&pptr->port_mutex); 3960 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 3961 if (ptgt) { 3962 /* 3963 * We now have a pointer to the target that 3964 * was created. Lets point to the first LUN on 3965 * this new target. 3966 */ 3967 mutex_enter(&ptgt->tgt_mutex); 3968 3969 plun = ptgt->tgt_lun; 3970 /* 3971 * There may be stale/offline LUN entries on 3972 * this list (this is by design) and so we have 3973 * to make sure we point to the first online 3974 * LUN 3975 */ 3976 while (plun && 3977 plun->lun_state & FCP_LUN_OFFLINE) { 3978 plun = plun->lun_next; 3979 } 3980 3981 mutex_exit(&ptgt->tgt_mutex); 3982 } 3983 mutex_exit(&pptr->port_mutex); 3984 } 3985 3986 if (*rval == 0 && ptgt && plun) { 3987 mutex_enter(&plun->lun_mutex); 3988 /* 3989 * Allow up to fcp_lun_ready_retry seconds to 3990 * configure all the luns behind the target. 3991 * 3992 * The intent here is to allow targets with long 3993 * reboot/reset-recovery times to become available 3994 * while limiting the maximum wait time for an 3995 * unresponsive target. 3996 */ 3997 end_time = ddi_get_lbolt() + 3998 SEC_TO_TICK(fcp_lun_ready_retry); 3999 4000 while (ddi_get_lbolt() < end_time) { 4001 retval = FC_SUCCESS; 4002 4003 /* 4004 * The new ndi interfaces for on-demand creation 4005 * are inflexible, Do some more work to pass on 4006 * a path name of some LUN (design is broken !) 4007 */ 4008 if (plun->lun_cip) { 4009 if (plun->lun_mpxio == 0) { 4010 cdip = DIP(plun->lun_cip); 4011 } else { 4012 cdip = mdi_pi_get_client( 4013 PIP(plun->lun_cip)); 4014 } 4015 if (cdip == NULL) { 4016 *rval = ENXIO; 4017 break; 4018 } 4019 4020 if (!i_ddi_devi_attached(cdip)) { 4021 mutex_exit(&plun->lun_mutex); 4022 delay(drv_usectohz(1000000)); 4023 mutex_enter(&plun->lun_mutex); 4024 } else { 4025 /* 4026 * This Lun is ready, lets 4027 * check the next one. 4028 */ 4029 mutex_exit(&plun->lun_mutex); 4030 plun = plun->lun_next; 4031 while (plun && (plun->lun_state 4032 & FCP_LUN_OFFLINE)) { 4033 plun = plun->lun_next; 4034 } 4035 if (!plun) { 4036 break; 4037 } 4038 mutex_enter(&plun->lun_mutex); 4039 } 4040 } else { 4041 /* 4042 * lun_cip field for a valid lun 4043 * should never be NULL. Fail the 4044 * command. 4045 */ 4046 *rval = ENXIO; 4047 break; 4048 } 4049 } 4050 if (plun) { 4051 mutex_exit(&plun->lun_mutex); 4052 } else { 4053 char devnm[MAXNAMELEN]; 4054 int nmlen; 4055 4056 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4057 ddi_node_name(cdip), 4058 ddi_get_name_addr(cdip)); 4059 4060 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4061 0) { 4062 *rval = EFAULT; 4063 } 4064 } 4065 } else { 4066 int i; 4067 char buf[25]; 4068 4069 for (i = 0; i < FC_WWN_SIZE; i++) { 4070 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4071 } 4072 4073 fcp_log(CE_WARN, pptr->port_dip, 4074 "!Failed to create nodes for pwwn=%s; error=%x", 4075 buf, *rval); 4076 } 4077 4078 (void) ndi_devi_free(useless_dip); 4079 ddi_prop_free(bytes); 4080 break; 4081 } 4082 4083 case DEVCTL_DEVICE_RESET: { 4084 struct fcp_lun *plun; 4085 struct scsi_address ap; 4086 child_info_t *cip = CIP(cdip); 4087 4088 ASSERT(cdip != NULL); 4089 ASSERT(pptr != NULL); 4090 mutex_enter(&pptr->port_mutex); 4091 if (pip != NULL) { 4092 cip = CIP(pip); 4093 } 4094 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4095 mutex_exit(&pptr->port_mutex); 4096 *rval = ENXIO; 4097 break; 4098 } 4099 mutex_exit(&pptr->port_mutex); 4100 4101 mutex_enter(&plun->lun_tgt->tgt_mutex); 4102 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4103 mutex_exit(&plun->lun_tgt->tgt_mutex); 4104 *rval = ENXIO; 4105 break; 4106 } 4107 ap.a_hba_tran = plun->lun_tran; 4108 ASSERT(pptr->port_tran != NULL); 4109 mutex_exit(&plun->lun_tgt->tgt_mutex); 4110 4111 /* 4112 * There is a chance lun_tran is NULL at this point. So check 4113 * for it. If it is NULL, it basically means that the tgt has 4114 * been freed. So, just return a "No such device or address" 4115 * error. 4116 */ 4117 if (ap.a_hba_tran == NULL) { 4118 *rval = ENXIO; 4119 break; 4120 } 4121 4122 /* 4123 * set up ap so that fcp_reset can figure out 4124 * which target to reset 4125 */ 4126 if (fcp_scsi_reset(&ap, RESET_TARGET) == FALSE) { 4127 *rval = EIO; 4128 } 4129 break; 4130 } 4131 4132 case DEVCTL_BUS_GETSTATE: 4133 ASSERT(dcp != NULL); 4134 ASSERT(pptr != NULL); 4135 ASSERT(pptr->port_dip != NULL); 4136 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4137 NDI_SUCCESS) { 4138 *rval = EFAULT; 4139 } 4140 break; 4141 4142 case DEVCTL_BUS_QUIESCE: 4143 case DEVCTL_BUS_UNQUIESCE: 4144 *rval = ENOTSUP; 4145 break; 4146 4147 case DEVCTL_BUS_RESET: 4148 case DEVCTL_BUS_RESETALL: 4149 ASSERT(pptr != NULL); 4150 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4151 break; 4152 4153 default: 4154 ASSERT(dcp != NULL); 4155 *rval = ENOTTY; 4156 break; 4157 } 4158 4159 /* all done -- clean up and return */ 4160 out: if (devi_entered) { 4161 if (is_mpxio) { 4162 mdi_devi_exit(pptr->port_dip, circ); 4163 } else { 4164 ndi_devi_exit(pptr->port_dip, circ); 4165 } 4166 } 4167 4168 if (dcp != NULL) { 4169 ndi_dc_freehdl(dcp); 4170 } 4171 4172 return (retval); 4173 } 4174 4175 4176 /*ARGSUSED*/ 4177 static int 4178 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4179 uint32_t claimed) 4180 { 4181 uchar_t r_ctl; 4182 uchar_t ls_code; 4183 struct fcp_port *pptr; 4184 4185 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4186 return (FC_UNCLAIMED); 4187 } 4188 4189 mutex_enter(&pptr->port_mutex); 4190 if (pptr->port_state & (FCP_STATE_DETACHING | 4191 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4192 mutex_exit(&pptr->port_mutex); 4193 return (FC_UNCLAIMED); 4194 } 4195 mutex_exit(&pptr->port_mutex); 4196 4197 r_ctl = buf->ub_frame.r_ctl; 4198 4199 switch (r_ctl & R_CTL_ROUTING) { 4200 case R_CTL_EXTENDED_SVC: 4201 if (r_ctl == R_CTL_ELS_REQ) { 4202 ls_code = buf->ub_buffer[0]; 4203 4204 switch (ls_code) { 4205 case LA_ELS_PRLI: 4206 /* 4207 * We really don't care if something fails. 4208 * If the PRLI was not sent out, then the 4209 * other end will time it out. 4210 */ 4211 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4212 return (FC_SUCCESS); 4213 } 4214 return (FC_UNCLAIMED); 4215 /* NOTREACHED */ 4216 4217 default: 4218 break; 4219 } 4220 } 4221 /* FALLTHROUGH */ 4222 4223 default: 4224 return (FC_UNCLAIMED); 4225 } 4226 } 4227 4228 4229 /*ARGSUSED*/ 4230 static int 4231 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4232 uint32_t claimed) 4233 { 4234 return (FC_UNCLAIMED); 4235 } 4236 4237 /* 4238 * Function: fcp_statec_callback 4239 * 4240 * Description: The purpose of this function is to handle a port state change. 4241 * It is called from fp/fctl and, in a few instances, internally. 4242 * 4243 * Argument: ulph fp/fctl port handle 4244 * port_handle fcp_port structure 4245 * port_state Physical state of the port 4246 * port_top Topology 4247 * *devlist Pointer to the first entry of a table 4248 * containing the remote ports that can be 4249 * reached. 4250 * dev_cnt Number of entries pointed by devlist. 4251 * port_sid Port ID of the local port. 4252 * 4253 * Return Value: None 4254 */ 4255 /*ARGSUSED*/ 4256 static void 4257 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4258 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4259 uint32_t dev_cnt, uint32_t port_sid) 4260 { 4261 uint32_t link_count; 4262 int map_len = 0; 4263 struct fcp_port *pptr; 4264 fcp_map_tag_t *map_tag = NULL; 4265 4266 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4267 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4268 return; /* nothing to work with! */ 4269 } 4270 4271 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4272 fcp_trace, FCP_BUF_LEVEL_2, 0, 4273 "fcp_statec_callback: port state/dev_cnt/top =" 4274 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4275 dev_cnt, port_top); 4276 4277 mutex_enter(&pptr->port_mutex); 4278 4279 /* 4280 * If a thread is in detach, don't do anything. 4281 */ 4282 if (pptr->port_state & (FCP_STATE_DETACHING | 4283 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4284 mutex_exit(&pptr->port_mutex); 4285 return; 4286 } 4287 4288 /* 4289 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4290 * init_pkt is called, it knows whether or not the target's status 4291 * (or pd) might be changing. 4292 */ 4293 4294 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4295 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4296 } 4297 4298 /* 4299 * the transport doesn't allocate or probe unless being 4300 * asked to by either the applications or ULPs 4301 * 4302 * in cases where the port is OFFLINE at the time of port 4303 * attach callback and the link comes ONLINE later, for 4304 * easier automatic node creation (i.e. without you having to 4305 * go out and run the utility to perform LOGINs) the 4306 * following conditional is helpful 4307 */ 4308 pptr->port_phys_state = port_state; 4309 4310 if (dev_cnt) { 4311 mutex_exit(&pptr->port_mutex); 4312 4313 map_len = sizeof (*map_tag) * dev_cnt; 4314 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4315 if (map_tag == NULL) { 4316 fcp_log(CE_WARN, pptr->port_dip, 4317 "!fcp%d: failed to allocate for map tags; " 4318 " state change will not be processed", 4319 pptr->port_instance); 4320 4321 mutex_enter(&pptr->port_mutex); 4322 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4323 mutex_exit(&pptr->port_mutex); 4324 4325 return; 4326 } 4327 4328 mutex_enter(&pptr->port_mutex); 4329 } 4330 4331 if (pptr->port_id != port_sid) { 4332 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4333 fcp_trace, FCP_BUF_LEVEL_3, 0, 4334 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4335 port_sid); 4336 /* 4337 * The local port changed ID. It is the first time a port ID 4338 * is assigned or something drastic happened. We might have 4339 * been unplugged and replugged on another loop or fabric port 4340 * or somebody grabbed the AL_PA we had or somebody rezoned 4341 * the fabric we were plugged into. 4342 */ 4343 pptr->port_id = port_sid; 4344 } 4345 4346 switch (FC_PORT_STATE_MASK(port_state)) { 4347 case FC_STATE_OFFLINE: 4348 case FC_STATE_RESET_REQUESTED: 4349 /* 4350 * link has gone from online to offline -- just update the 4351 * state of this port to BUSY and MARKed to go offline 4352 */ 4353 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4354 fcp_trace, FCP_BUF_LEVEL_3, 0, 4355 "link went offline"); 4356 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4357 /* 4358 * We were offline a while ago and this one 4359 * seems to indicate that the loop has gone 4360 * dead forever. 4361 */ 4362 pptr->port_tmp_cnt += dev_cnt; 4363 pptr->port_state &= ~FCP_STATE_OFFLINE; 4364 pptr->port_state |= FCP_STATE_INIT; 4365 link_count = pptr->port_link_cnt; 4366 fcp_handle_devices(pptr, devlist, dev_cnt, 4367 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4368 } else { 4369 pptr->port_link_cnt++; 4370 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4371 fcp_update_state(pptr, (FCP_LUN_BUSY | 4372 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4373 if (pptr->port_mpxio) { 4374 fcp_update_mpxio_path_verifybusy(pptr); 4375 } 4376 pptr->port_state |= FCP_STATE_OFFLINE; 4377 pptr->port_state &= 4378 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4379 pptr->port_tmp_cnt = 0; 4380 } 4381 mutex_exit(&pptr->port_mutex); 4382 break; 4383 4384 case FC_STATE_ONLINE: 4385 case FC_STATE_LIP: 4386 case FC_STATE_LIP_LBIT_SET: 4387 /* 4388 * link has gone from offline to online 4389 */ 4390 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4391 fcp_trace, FCP_BUF_LEVEL_3, 0, 4392 "link went online"); 4393 4394 pptr->port_link_cnt++; 4395 4396 while (pptr->port_ipkt_cnt) { 4397 mutex_exit(&pptr->port_mutex); 4398 delay(drv_usectohz(1000000)); 4399 mutex_enter(&pptr->port_mutex); 4400 } 4401 4402 pptr->port_topology = port_top; 4403 4404 /* 4405 * The state of the targets and luns accessible through this 4406 * port is updated. 4407 */ 4408 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4409 FCP_CAUSE_LINK_CHANGE); 4410 4411 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4412 pptr->port_state |= FCP_STATE_ONLINING; 4413 pptr->port_tmp_cnt = dev_cnt; 4414 link_count = pptr->port_link_cnt; 4415 4416 pptr->port_deadline = fcp_watchdog_time + 4417 FCP_ICMD_DEADLINE; 4418 4419 if (!dev_cnt) { 4420 /* 4421 * We go directly to the online state if no remote 4422 * ports were discovered. 4423 */ 4424 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4425 fcp_trace, FCP_BUF_LEVEL_3, 0, 4426 "No remote ports discovered"); 4427 4428 pptr->port_state &= ~FCP_STATE_ONLINING; 4429 pptr->port_state |= FCP_STATE_ONLINE; 4430 } 4431 4432 switch (port_top) { 4433 case FC_TOP_FABRIC: 4434 case FC_TOP_PUBLIC_LOOP: 4435 case FC_TOP_PRIVATE_LOOP: 4436 case FC_TOP_PT_PT: 4437 4438 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4439 fcp_retry_ns_registry(pptr, port_sid); 4440 } 4441 4442 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4443 map_tag, FCP_CAUSE_LINK_CHANGE); 4444 break; 4445 4446 default: 4447 /* 4448 * We got here because we were provided with an unknown 4449 * topology. 4450 */ 4451 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4452 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4453 } 4454 4455 pptr->port_tmp_cnt -= dev_cnt; 4456 fcp_log(CE_WARN, pptr->port_dip, 4457 "!unknown/unsupported topology (0x%x)", port_top); 4458 break; 4459 } 4460 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4461 fcp_trace, FCP_BUF_LEVEL_3, 0, 4462 "Notify ssd of the reset to reinstate the reservations"); 4463 4464 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4465 &pptr->port_reset_notify_listf); 4466 4467 mutex_exit(&pptr->port_mutex); 4468 4469 break; 4470 4471 case FC_STATE_RESET: 4472 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4473 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4474 fcp_trace, FCP_BUF_LEVEL_3, 0, 4475 "RESET state, waiting for Offline/Online state_cb"); 4476 mutex_exit(&pptr->port_mutex); 4477 break; 4478 4479 case FC_STATE_DEVICE_CHANGE: 4480 /* 4481 * We come here when an application has requested 4482 * Dynamic node creation/deletion in Fabric connectivity. 4483 */ 4484 if (pptr->port_state & (FCP_STATE_OFFLINE | 4485 FCP_STATE_INIT)) { 4486 /* 4487 * This case can happen when the FCTL is in the 4488 * process of giving us on online and the host on 4489 * the other side issues a PLOGI/PLOGO. Ideally 4490 * the state changes should be serialized unless 4491 * they are opposite (online-offline). 4492 * The transport will give us a final state change 4493 * so we can ignore this for the time being. 4494 */ 4495 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4496 mutex_exit(&pptr->port_mutex); 4497 break; 4498 } 4499 4500 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4501 fcp_retry_ns_registry(pptr, port_sid); 4502 } 4503 4504 /* 4505 * Extend the deadline under steady state conditions 4506 * to provide more time for the device-change-commands 4507 */ 4508 if (!pptr->port_ipkt_cnt) { 4509 pptr->port_deadline = fcp_watchdog_time + 4510 FCP_ICMD_DEADLINE; 4511 } 4512 4513 /* 4514 * There is another race condition here, where if we were 4515 * in ONLINEING state and a devices in the map logs out, 4516 * fp will give another state change as DEVICE_CHANGE 4517 * and OLD. This will result in that target being offlined. 4518 * The pd_handle is freed. If from the first statec callback 4519 * we were going to fire a PLOGI/PRLI, the system will 4520 * panic in fc_ulp_transport with invalid pd_handle. 4521 * The fix is to check for the link_cnt before issuing 4522 * any command down. 4523 */ 4524 fcp_update_targets(pptr, devlist, dev_cnt, 4525 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4526 4527 link_count = pptr->port_link_cnt; 4528 4529 fcp_handle_devices(pptr, devlist, dev_cnt, 4530 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4531 4532 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4533 4534 mutex_exit(&pptr->port_mutex); 4535 break; 4536 4537 case FC_STATE_TARGET_PORT_RESET: 4538 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4539 fcp_retry_ns_registry(pptr, port_sid); 4540 } 4541 4542 /* Do nothing else */ 4543 mutex_exit(&pptr->port_mutex); 4544 break; 4545 4546 default: 4547 fcp_log(CE_WARN, pptr->port_dip, 4548 "!Invalid state change=0x%x", port_state); 4549 mutex_exit(&pptr->port_mutex); 4550 break; 4551 } 4552 4553 if (map_tag) { 4554 kmem_free(map_tag, map_len); 4555 } 4556 } 4557 4558 /* 4559 * Function: fcp_handle_devices 4560 * 4561 * Description: This function updates the devices currently known by 4562 * walking the list provided by the caller. The list passed 4563 * by the caller is supposed to be the list of reachable 4564 * devices. 4565 * 4566 * Argument: *pptr Fcp port structure. 4567 * *devlist Pointer to the first entry of a table 4568 * containing the remote ports that can be 4569 * reached. 4570 * dev_cnt Number of entries pointed by devlist. 4571 * link_cnt Link state count. 4572 * *map_tag Array of fcp_map_tag_t structures. 4573 * cause What caused this function to be called. 4574 * 4575 * Return Value: None 4576 * 4577 * Notes: The pptr->port_mutex must be held. 4578 */ 4579 static void 4580 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4581 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4582 { 4583 int i; 4584 int check_finish_init = 0; 4585 fc_portmap_t *map_entry; 4586 struct fcp_tgt *ptgt = NULL; 4587 4588 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4589 fcp_trace, FCP_BUF_LEVEL_3, 0, 4590 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4591 4592 if (dev_cnt) { 4593 ASSERT(map_tag != NULL); 4594 } 4595 4596 /* 4597 * The following code goes through the list of remote ports that are 4598 * accessible through this (pptr) local port (The list walked is the 4599 * one provided by the caller which is the list of the remote ports 4600 * currently reachable). It checks if any of them was already 4601 * known by looking for the corresponding target structure based on 4602 * the world wide name. If a target is part of the list it is tagged 4603 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4604 * 4605 * Old comment 4606 * ----------- 4607 * Before we drop port mutex; we MUST get the tags updated; This 4608 * two step process is somewhat slow, but more reliable. 4609 */ 4610 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4611 map_entry = &(devlist[i]); 4612 4613 /* 4614 * get ptr to this map entry in our port's 4615 * list (if any) 4616 */ 4617 ptgt = fcp_lookup_target(pptr, 4618 (uchar_t *)&(map_entry->map_pwwn)); 4619 4620 if (ptgt) { 4621 map_tag[i] = ptgt->tgt_change_cnt; 4622 if (cause == FCP_CAUSE_LINK_CHANGE) { 4623 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4624 } 4625 } 4626 } 4627 4628 /* 4629 * At this point we know which devices of the new list were already 4630 * known (The field tgt_aux_state of the target structure has been 4631 * set to FCP_TGT_TAGGED). 4632 * 4633 * The following code goes through the list of targets currently known 4634 * by the local port (the list is actually a hashing table). If a 4635 * target is found and is not tagged, it means the target cannot 4636 * be reached anymore through the local port (pptr). It is offlined. 4637 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4638 */ 4639 for (i = 0; i < FCP_NUM_HASH; i++) { 4640 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4641 ptgt = ptgt->tgt_next) { 4642 mutex_enter(&ptgt->tgt_mutex); 4643 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4644 (cause == FCP_CAUSE_LINK_CHANGE) && 4645 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4646 fcp_offline_target_now(pptr, ptgt, 4647 link_cnt, ptgt->tgt_change_cnt, 0); 4648 } 4649 mutex_exit(&ptgt->tgt_mutex); 4650 } 4651 } 4652 4653 /* 4654 * At this point, the devices that were known but cannot be reached 4655 * anymore, have most likely been offlined. 4656 * 4657 * The following section of code seems to go through the list of 4658 * remote ports that can now be reached. For every single one it 4659 * checks if it is already known or if it is a new port. 4660 */ 4661 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4662 4663 if (check_finish_init) { 4664 ASSERT(i > 0); 4665 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4666 map_tag[i - 1], cause); 4667 check_finish_init = 0; 4668 } 4669 4670 /* get a pointer to this map entry */ 4671 map_entry = &(devlist[i]); 4672 4673 /* 4674 * Check for the duplicate map entry flag. If we have marked 4675 * this entry as a duplicate we skip it since the correct 4676 * (perhaps even same) state change will be encountered 4677 * later in the list. 4678 */ 4679 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4680 continue; 4681 } 4682 4683 /* get ptr to this map entry in our port's list (if any) */ 4684 ptgt = fcp_lookup_target(pptr, 4685 (uchar_t *)&(map_entry->map_pwwn)); 4686 4687 if (ptgt) { 4688 /* 4689 * This device was already known. The field 4690 * tgt_aux_state is reset (was probably set to 4691 * FCP_TGT_TAGGED previously in this routine). 4692 */ 4693 ptgt->tgt_aux_state = 0; 4694 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4695 fcp_trace, FCP_BUF_LEVEL_3, 0, 4696 "handle_devices: map did/state/type/flags = " 4697 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4698 "tgt_state=%d", 4699 map_entry->map_did.port_id, map_entry->map_state, 4700 map_entry->map_type, map_entry->map_flags, 4701 ptgt->tgt_d_id, ptgt->tgt_state); 4702 } 4703 4704 if (map_entry->map_type == PORT_DEVICE_OLD || 4705 map_entry->map_type == PORT_DEVICE_NEW || 4706 map_entry->map_type == PORT_DEVICE_CHANGED) { 4707 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4708 fcp_trace, FCP_BUF_LEVEL_2, 0, 4709 "map_type=%x, did = %x", 4710 map_entry->map_type, 4711 map_entry->map_did.port_id); 4712 } 4713 4714 switch (map_entry->map_type) { 4715 case PORT_DEVICE_NOCHANGE: 4716 case PORT_DEVICE_USER_CREATE: 4717 case PORT_DEVICE_USER_LOGIN: 4718 case PORT_DEVICE_NEW: 4719 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4720 4721 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4722 link_cnt, (ptgt) ? map_tag[i] : 0, 4723 cause) == TRUE) { 4724 4725 FCP_TGT_TRACE(ptgt, map_tag[i], 4726 FCP_TGT_TRACE_2); 4727 check_finish_init++; 4728 } 4729 break; 4730 4731 case PORT_DEVICE_OLD: 4732 if (ptgt != NULL) { 4733 FCP_TGT_TRACE(ptgt, map_tag[i], 4734 FCP_TGT_TRACE_3); 4735 4736 mutex_enter(&ptgt->tgt_mutex); 4737 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4738 /* 4739 * Must do an in-line wait for I/Os 4740 * to get drained 4741 */ 4742 mutex_exit(&ptgt->tgt_mutex); 4743 mutex_exit(&pptr->port_mutex); 4744 4745 mutex_enter(&ptgt->tgt_mutex); 4746 while (ptgt->tgt_ipkt_cnt || 4747 fcp_outstanding_lun_cmds(ptgt) 4748 == FC_SUCCESS) { 4749 mutex_exit(&ptgt->tgt_mutex); 4750 delay(drv_usectohz(1000000)); 4751 mutex_enter(&ptgt->tgt_mutex); 4752 } 4753 mutex_exit(&ptgt->tgt_mutex); 4754 4755 mutex_enter(&pptr->port_mutex); 4756 mutex_enter(&ptgt->tgt_mutex); 4757 4758 (void) fcp_offline_target(pptr, ptgt, 4759 link_cnt, map_tag[i], 0, 0); 4760 } 4761 mutex_exit(&ptgt->tgt_mutex); 4762 } 4763 check_finish_init++; 4764 break; 4765 4766 case PORT_DEVICE_USER_DELETE: 4767 case PORT_DEVICE_USER_LOGOUT: 4768 if (ptgt != NULL) { 4769 FCP_TGT_TRACE(ptgt, map_tag[i], 4770 FCP_TGT_TRACE_4); 4771 4772 mutex_enter(&ptgt->tgt_mutex); 4773 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4774 (void) fcp_offline_target(pptr, ptgt, 4775 link_cnt, map_tag[i], 1, 0); 4776 } 4777 mutex_exit(&ptgt->tgt_mutex); 4778 } 4779 check_finish_init++; 4780 break; 4781 4782 case PORT_DEVICE_CHANGED: 4783 if (ptgt != NULL) { 4784 FCP_TGT_TRACE(ptgt, map_tag[i], 4785 FCP_TGT_TRACE_5); 4786 4787 if (fcp_device_changed(pptr, ptgt, 4788 map_entry, link_cnt, map_tag[i], 4789 cause) == TRUE) { 4790 check_finish_init++; 4791 } 4792 } else { 4793 if (fcp_handle_mapflags(pptr, ptgt, 4794 map_entry, link_cnt, 0, cause) == TRUE) { 4795 check_finish_init++; 4796 } 4797 } 4798 break; 4799 4800 default: 4801 fcp_log(CE_WARN, pptr->port_dip, 4802 "!Invalid map_type=0x%x", map_entry->map_type); 4803 check_finish_init++; 4804 break; 4805 } 4806 } 4807 4808 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4809 ASSERT(i > 0); 4810 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4811 map_tag[i-1], cause); 4812 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4813 fcp_offline_all(pptr, link_cnt, cause); 4814 } 4815 } 4816 4817 /* 4818 * Function: fcp_handle_mapflags 4819 * 4820 * Description: This function creates a target structure if the ptgt passed 4821 * is NULL. It also kicks off the PLOGI if we are not logged 4822 * into the target yet or the PRLI if we are logged into the 4823 * target already. The rest of the treatment is done in the 4824 * callbacks of the PLOGI or PRLI. 4825 * 4826 * Argument: *pptr FCP Port structure. 4827 * *ptgt Target structure. 4828 * *map_entry Array of fc_portmap_t structures. 4829 * link_cnt Link state count. 4830 * tgt_cnt Target state count. 4831 * cause What caused this function to be called. 4832 * 4833 * Return Value: TRUE Failed 4834 * FALSE Succeeded 4835 * 4836 * Notes: pptr->port_mutex must be owned. 4837 */ 4838 static int 4839 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4840 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4841 { 4842 int lcount; 4843 int tcount; 4844 int ret = TRUE; 4845 int alloc; 4846 struct fcp_ipkt *icmd; 4847 struct fcp_lun *pseq_lun = NULL; 4848 uchar_t opcode; 4849 int valid_ptgt_was_passed = FALSE; 4850 4851 ASSERT(mutex_owned(&pptr->port_mutex)); 4852 4853 /* 4854 * This case is possible where the FCTL has come up and done discovery 4855 * before FCP was loaded and attached. FCTL would have discovered the 4856 * devices and later the ULP came online. In this case ULP's would get 4857 * PORT_DEVICE_NOCHANGE but target would be NULL. 4858 */ 4859 if (ptgt == NULL) { 4860 /* don't already have a target */ 4861 mutex_exit(&pptr->port_mutex); 4862 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4863 mutex_enter(&pptr->port_mutex); 4864 4865 if (ptgt == NULL) { 4866 fcp_log(CE_WARN, pptr->port_dip, 4867 "!FC target allocation failed"); 4868 return (ret); 4869 } 4870 mutex_enter(&ptgt->tgt_mutex); 4871 ptgt->tgt_statec_cause = cause; 4872 ptgt->tgt_tmp_cnt = 1; 4873 mutex_exit(&ptgt->tgt_mutex); 4874 } else { 4875 valid_ptgt_was_passed = TRUE; 4876 } 4877 4878 /* 4879 * Copy in the target parameters 4880 */ 4881 mutex_enter(&ptgt->tgt_mutex); 4882 ptgt->tgt_d_id = map_entry->map_did.port_id; 4883 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4884 ptgt->tgt_pd_handle = map_entry->map_pd; 4885 ptgt->tgt_fca_dev = NULL; 4886 4887 /* Copy port and node WWNs */ 4888 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4889 FC_WWN_SIZE); 4890 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4891 FC_WWN_SIZE); 4892 4893 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4894 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4895 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4896 valid_ptgt_was_passed) { 4897 /* 4898 * determine if there are any tape LUNs on this target 4899 */ 4900 for (pseq_lun = ptgt->tgt_lun; 4901 pseq_lun != NULL; 4902 pseq_lun = pseq_lun->lun_next) { 4903 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4904 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4905 fcp_update_tgt_state(ptgt, FCP_RESET, 4906 FCP_LUN_MARK); 4907 mutex_exit(&ptgt->tgt_mutex); 4908 return (ret); 4909 } 4910 } 4911 } 4912 4913 /* 4914 * If ptgt was NULL when this function was entered, then tgt_node_state 4915 * was never specifically initialized but zeroed out which means 4916 * FCP_TGT_NODE_NONE. 4917 */ 4918 switch (ptgt->tgt_node_state) { 4919 case FCP_TGT_NODE_NONE: 4920 case FCP_TGT_NODE_ON_DEMAND: 4921 if (FC_TOP_EXTERNAL(pptr->port_topology) && 4922 !fcp_enable_auto_configuration && 4923 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 4924 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 4925 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 4926 fcp_enable_auto_configuration && 4927 (ptgt->tgt_manual_config_only == 1) && 4928 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 4929 /* 4930 * If auto configuration is set and 4931 * the tgt_manual_config_only flag is set then 4932 * we only want the user to be able to change 4933 * the state through create_on_demand. 4934 */ 4935 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 4936 } else { 4937 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 4938 } 4939 break; 4940 4941 case FCP_TGT_NODE_PRESENT: 4942 break; 4943 } 4944 /* 4945 * If we are booting from a fabric device, make sure we 4946 * mark the node state appropriately for this target to be 4947 * enumerated 4948 */ 4949 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 4950 if (bcmp((caddr_t)pptr->port_boot_wwn, 4951 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 4952 sizeof (ptgt->tgt_port_wwn)) == 0) { 4953 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 4954 } 4955 } 4956 mutex_exit(&ptgt->tgt_mutex); 4957 4958 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4959 fcp_trace, FCP_BUF_LEVEL_3, 0, 4960 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 4961 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 4962 map_entry->map_rscn_info.ulp_rscn_count); 4963 4964 mutex_enter(&ptgt->tgt_mutex); 4965 4966 /* 4967 * Reset target OFFLINE state and mark the target BUSY 4968 */ 4969 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 4970 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 4971 4972 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 4973 lcount = link_cnt; 4974 4975 mutex_exit(&ptgt->tgt_mutex); 4976 mutex_exit(&pptr->port_mutex); 4977 4978 /* 4979 * if we are already logged in, then we do a PRLI, else 4980 * we do a PLOGI first (to get logged in) 4981 * 4982 * We will not check if we are the PLOGI initiator 4983 */ 4984 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 4985 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 4986 4987 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 4988 4989 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0, lcount, tcount, 4990 cause, map_entry->map_rscn_info.ulp_rscn_count); 4991 4992 if (icmd == NULL) { 4993 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 4994 /* 4995 * We've exited port_mutex before calling fcp_icmd_alloc, 4996 * we need to make sure we reacquire it before returning. 4997 */ 4998 mutex_enter(&pptr->port_mutex); 4999 return (FALSE); 5000 } 5001 5002 /* TRUE is only returned while target is intended skipped */ 5003 ret = FALSE; 5004 /* discover info about this target */ 5005 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5006 lcount, tcount, cause)) == DDI_SUCCESS) { 5007 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5008 } else { 5009 fcp_icmd_free(pptr, icmd); 5010 ret = TRUE; 5011 } 5012 mutex_enter(&pptr->port_mutex); 5013 5014 return (ret); 5015 } 5016 5017 /* 5018 * Function: fcp_send_els 5019 * 5020 * Description: Sends an ELS to the target specified by the caller. Supports 5021 * PLOGI and PRLI. 5022 * 5023 * Argument: *pptr Fcp port. 5024 * *ptgt Target to send the ELS to. 5025 * *icmd Internal packet 5026 * opcode ELS opcode 5027 * lcount Link state change counter 5028 * tcount Target state change counter 5029 * cause What caused the call 5030 * 5031 * Return Value: DDI_SUCCESS 5032 * Others 5033 */ 5034 static int 5035 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5036 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5037 { 5038 fc_packet_t *fpkt; 5039 fc_frame_hdr_t *hp; 5040 int internal = 0; 5041 int alloc; 5042 int cmd_len; 5043 int resp_len; 5044 int res = DDI_FAILURE; /* default result */ 5045 int rval = DDI_FAILURE; 5046 5047 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5048 ASSERT(ptgt->tgt_port == pptr); 5049 5050 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5051 fcp_trace, FCP_BUF_LEVEL_5, 0, 5052 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5053 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5054 5055 if (opcode == LA_ELS_PLOGI) { 5056 cmd_len = sizeof (la_els_logi_t); 5057 resp_len = sizeof (la_els_logi_t); 5058 } else { 5059 ASSERT(opcode == LA_ELS_PRLI); 5060 cmd_len = sizeof (la_els_prli_t); 5061 resp_len = sizeof (la_els_prli_t); 5062 } 5063 5064 if (icmd == NULL) { 5065 alloc = FCP_MAX(sizeof (la_els_logi_t), 5066 sizeof (la_els_prli_t)); 5067 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 0, 5068 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5069 if (icmd == NULL) { 5070 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5071 return (res); 5072 } 5073 internal++; 5074 } 5075 fpkt = icmd->ipkt_fpkt; 5076 5077 fpkt->pkt_cmdlen = cmd_len; 5078 fpkt->pkt_rsplen = resp_len; 5079 fpkt->pkt_datalen = 0; 5080 icmd->ipkt_retries = 0; 5081 5082 /* fill in fpkt info */ 5083 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5084 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5085 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5086 5087 /* get ptr to frame hdr in fpkt */ 5088 hp = &fpkt->pkt_cmd_fhdr; 5089 5090 /* 5091 * fill in frame hdr 5092 */ 5093 hp->r_ctl = R_CTL_ELS_REQ; 5094 hp->s_id = pptr->port_id; /* source ID */ 5095 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5096 hp->type = FC_TYPE_EXTENDED_LS; 5097 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5098 hp->seq_id = 0; 5099 hp->rsvd = 0; 5100 hp->df_ctl = 0; 5101 hp->seq_cnt = 0; 5102 hp->ox_id = 0xffff; /* i.e. none */ 5103 hp->rx_id = 0xffff; /* i.e. none */ 5104 hp->ro = 0; 5105 5106 /* 5107 * at this point we have a filled in cmd pkt 5108 * 5109 * fill in the respective info, then use the transport to send 5110 * the packet 5111 * 5112 * for a PLOGI call fc_ulp_login(), and 5113 * for a PRLI call fc_ulp_issue_els() 5114 */ 5115 switch (opcode) { 5116 case LA_ELS_PLOGI: { 5117 struct la_els_logi logi; 5118 5119 bzero(&logi, sizeof (struct la_els_logi)); 5120 5121 hp = &fpkt->pkt_cmd_fhdr; 5122 hp->r_ctl = R_CTL_ELS_REQ; 5123 logi.ls_code.ls_code = LA_ELS_PLOGI; 5124 logi.ls_code.mbz = 0; 5125 5126 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5127 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5128 5129 icmd->ipkt_opcode = LA_ELS_PLOGI; 5130 5131 mutex_enter(&pptr->port_mutex); 5132 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5133 5134 mutex_exit(&pptr->port_mutex); 5135 5136 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5137 if (rval == FC_SUCCESS) { 5138 res = DDI_SUCCESS; 5139 break; 5140 } 5141 5142 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5143 5144 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5145 rval, "PLOGI"); 5146 } else { 5147 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5148 fcp_trace, FCP_BUF_LEVEL_5, 0, 5149 "fcp_send_els1: state change occured" 5150 " for D_ID=0x%x", ptgt->tgt_d_id); 5151 mutex_exit(&pptr->port_mutex); 5152 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5153 } 5154 break; 5155 } 5156 5157 case LA_ELS_PRLI: { 5158 struct la_els_prli prli; 5159 struct fcp_prli *fprli; 5160 5161 bzero(&prli, sizeof (struct la_els_prli)); 5162 5163 hp = &fpkt->pkt_cmd_fhdr; 5164 hp->r_ctl = R_CTL_ELS_REQ; 5165 5166 /* fill in PRLI cmd ELS fields */ 5167 prli.ls_code = LA_ELS_PRLI; 5168 prli.page_length = 0x10; /* huh? */ 5169 prli.payload_length = sizeof (struct la_els_prli); 5170 5171 icmd->ipkt_opcode = LA_ELS_PRLI; 5172 5173 /* get ptr to PRLI service params */ 5174 fprli = (struct fcp_prli *)prli.service_params; 5175 5176 /* fill in service params */ 5177 fprli->type = 0x08; 5178 fprli->resvd1 = 0; 5179 fprli->orig_process_assoc_valid = 0; 5180 fprli->resp_process_assoc_valid = 0; 5181 fprli->establish_image_pair = 1; 5182 fprli->resvd2 = 0; 5183 fprli->resvd3 = 0; 5184 fprli->obsolete_1 = 0; 5185 fprli->obsolete_2 = 0; 5186 fprli->data_overlay_allowed = 0; 5187 fprli->initiator_fn = 1; 5188 fprli->confirmed_compl_allowed = 1; 5189 5190 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5191 fprli->target_fn = 1; 5192 } else { 5193 fprli->target_fn = 0; 5194 } 5195 5196 fprli->retry = 1; 5197 fprli->read_xfer_rdy_disabled = 1; 5198 fprli->write_xfer_rdy_disabled = 0; 5199 5200 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5201 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5202 5203 /* issue the PRLI request */ 5204 5205 mutex_enter(&pptr->port_mutex); 5206 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5207 5208 mutex_exit(&pptr->port_mutex); 5209 5210 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5211 if (rval == FC_SUCCESS) { 5212 res = DDI_SUCCESS; 5213 break; 5214 } 5215 5216 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5217 5218 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5219 rval, "PRLI"); 5220 } else { 5221 mutex_exit(&pptr->port_mutex); 5222 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5223 } 5224 break; 5225 } 5226 5227 default: 5228 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5229 break; 5230 } 5231 5232 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5233 fcp_trace, FCP_BUF_LEVEL_5, 0, 5234 "fcp_send_els: returning %d", res); 5235 5236 if (res != DDI_SUCCESS) { 5237 if (internal) { 5238 fcp_icmd_free(pptr, icmd); 5239 } 5240 } 5241 5242 return (res); 5243 } 5244 5245 5246 /* 5247 * called internally update the state of all of the tgts and each LUN 5248 * for this port (i.e. each target known to be attached to this port) 5249 * if they are not already offline 5250 * 5251 * must be called with the port mutex owned 5252 * 5253 * acquires and releases the target mutexes for each target attached 5254 * to this port 5255 */ 5256 void 5257 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5258 { 5259 int i; 5260 struct fcp_tgt *ptgt; 5261 5262 ASSERT(mutex_owned(&pptr->port_mutex)); 5263 5264 for (i = 0; i < FCP_NUM_HASH; i++) { 5265 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5266 ptgt = ptgt->tgt_next) { 5267 mutex_enter(&ptgt->tgt_mutex); 5268 fcp_update_tgt_state(ptgt, FCP_SET, state); 5269 ptgt->tgt_change_cnt++; 5270 ptgt->tgt_statec_cause = cause; 5271 ptgt->tgt_tmp_cnt = 1; 5272 ptgt->tgt_done = 0; 5273 mutex_exit(&ptgt->tgt_mutex); 5274 } 5275 } 5276 } 5277 5278 5279 static void 5280 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5281 { 5282 int i; 5283 int ndevs; 5284 struct fcp_tgt *ptgt; 5285 5286 ASSERT(mutex_owned(&pptr->port_mutex)); 5287 5288 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5289 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5290 ptgt = ptgt->tgt_next) { 5291 ndevs++; 5292 } 5293 } 5294 5295 if (ndevs == 0) { 5296 return; 5297 } 5298 pptr->port_tmp_cnt = ndevs; 5299 5300 for (i = 0; i < FCP_NUM_HASH; i++) { 5301 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5302 ptgt = ptgt->tgt_next) { 5303 (void) fcp_call_finish_init_held(pptr, ptgt, 5304 lcount, ptgt->tgt_change_cnt, cause); 5305 } 5306 } 5307 } 5308 5309 /* 5310 * Function: fcp_update_tgt_state 5311 * 5312 * Description: This function updates the field tgt_state of a target. That 5313 * field is a bitmap and which bit can be set or reset 5314 * individually. The action applied to the target state is also 5315 * applied to all the LUNs belonging to the target (provided the 5316 * LUN is not offline). A side effect of applying the state 5317 * modification to the target and the LUNs is the field tgt_trace 5318 * of the target and lun_trace of the LUNs is set to zero. 5319 * 5320 * 5321 * Argument: *ptgt Target structure. 5322 * flag Flag indication what action to apply (set/reset). 5323 * state State bits to update. 5324 * 5325 * Return Value: None 5326 * 5327 * Context: Interrupt, Kernel or User context. 5328 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5329 * calling this function. 5330 */ 5331 void 5332 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5333 { 5334 struct fcp_lun *plun; 5335 5336 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5337 5338 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5339 /* The target is not offline. */ 5340 if (flag == FCP_SET) { 5341 ptgt->tgt_state |= state; 5342 ptgt->tgt_trace = 0; 5343 } else { 5344 ptgt->tgt_state &= ~state; 5345 } 5346 5347 for (plun = ptgt->tgt_lun; plun != NULL; 5348 plun = plun->lun_next) { 5349 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5350 /* The LUN is not offline. */ 5351 if (flag == FCP_SET) { 5352 plun->lun_state |= state; 5353 plun->lun_trace = 0; 5354 } else { 5355 plun->lun_state &= ~state; 5356 } 5357 } 5358 } 5359 } 5360 } 5361 5362 /* 5363 * Function: fcp_update_tgt_state 5364 * 5365 * Description: This function updates the field lun_state of a LUN. That 5366 * field is a bitmap and which bit can be set or reset 5367 * individually. 5368 * 5369 * Argument: *plun LUN structure. 5370 * flag Flag indication what action to apply (set/reset). 5371 * state State bits to update. 5372 * 5373 * Return Value: None 5374 * 5375 * Context: Interrupt, Kernel or User context. 5376 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5377 * calling this function. 5378 */ 5379 void 5380 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5381 { 5382 struct fcp_tgt *ptgt = plun->lun_tgt; 5383 5384 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5385 5386 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5387 if (flag == FCP_SET) { 5388 plun->lun_state |= state; 5389 } else { 5390 plun->lun_state &= ~state; 5391 } 5392 } 5393 } 5394 5395 /* 5396 * Function: fcp_get_port 5397 * 5398 * Description: This function returns the fcp_port structure from the opaque 5399 * handle passed by the caller. That opaque handle is the handle 5400 * used by fp/fctl to identify a particular local port. That 5401 * handle has been stored in the corresponding fcp_port 5402 * structure. This function is going to walk the global list of 5403 * fcp_port structures till one has a port_fp_handle that matches 5404 * the handle passed by the caller. This function enters the 5405 * mutex fcp_global_mutex while walking the global list and then 5406 * releases it. 5407 * 5408 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5409 * particular port. 5410 * 5411 * Return Value: NULL Not found. 5412 * Not NULL Pointer to the fcp_port structure. 5413 * 5414 * Context: Interrupt, Kernel or User context. 5415 */ 5416 static struct fcp_port * 5417 fcp_get_port(opaque_t port_handle) 5418 { 5419 struct fcp_port *pptr; 5420 5421 ASSERT(port_handle != NULL); 5422 5423 mutex_enter(&fcp_global_mutex); 5424 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5425 if (pptr->port_fp_handle == port_handle) { 5426 break; 5427 } 5428 } 5429 mutex_exit(&fcp_global_mutex); 5430 5431 return (pptr); 5432 } 5433 5434 5435 static void 5436 fcp_unsol_callback(fc_packet_t *fpkt) 5437 { 5438 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5439 struct fcp_port *pptr = icmd->ipkt_port; 5440 5441 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5442 caddr_t state, reason, action, expln; 5443 5444 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5445 &action, &expln); 5446 5447 fcp_log(CE_WARN, pptr->port_dip, 5448 "!couldn't post response to unsolicited request: " 5449 " state=%s reason=%s rx_id=%x ox_id=%x", 5450 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5451 fpkt->pkt_cmd_fhdr.rx_id); 5452 } 5453 fcp_icmd_free(pptr, icmd); 5454 } 5455 5456 5457 /* 5458 * Perform general purpose preparation of a response to an unsolicited request 5459 */ 5460 static void 5461 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5462 uchar_t r_ctl, uchar_t type) 5463 { 5464 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5465 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5466 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5467 pkt->pkt_cmd_fhdr.type = type; 5468 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5469 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5470 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5471 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5472 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5473 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5474 pkt->pkt_cmd_fhdr.ro = 0; 5475 pkt->pkt_cmd_fhdr.rsvd = 0; 5476 pkt->pkt_comp = fcp_unsol_callback; 5477 pkt->pkt_pd = NULL; 5478 } 5479 5480 5481 /*ARGSUSED*/ 5482 static int 5483 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5484 { 5485 fc_packet_t *fpkt; 5486 struct la_els_prli prli; 5487 struct fcp_prli *fprli; 5488 struct fcp_ipkt *icmd; 5489 struct la_els_prli *from; 5490 struct fcp_prli *orig; 5491 struct fcp_tgt *ptgt; 5492 int tcount = 0; 5493 int lcount; 5494 5495 from = (struct la_els_prli *)buf->ub_buffer; 5496 orig = (struct fcp_prli *)from->service_params; 5497 5498 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5499 NULL) { 5500 mutex_enter(&ptgt->tgt_mutex); 5501 tcount = ptgt->tgt_change_cnt; 5502 mutex_exit(&ptgt->tgt_mutex); 5503 } 5504 mutex_enter(&pptr->port_mutex); 5505 lcount = pptr->port_link_cnt; 5506 mutex_exit(&pptr->port_mutex); 5507 5508 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5509 sizeof (la_els_prli_t), 0, 0, lcount, tcount, 0, 5510 FC_INVALID_RSCN_COUNT)) == NULL) { 5511 return (FC_FAILURE); 5512 } 5513 fpkt = icmd->ipkt_fpkt; 5514 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5515 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5516 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5517 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5518 fpkt->pkt_rsplen = 0; 5519 fpkt->pkt_datalen = 0; 5520 5521 icmd->ipkt_opcode = LA_ELS_PRLI; 5522 5523 bzero(&prli, sizeof (struct la_els_prli)); 5524 fprli = (struct fcp_prli *)prli.service_params; 5525 prli.ls_code = LA_ELS_ACC; 5526 prli.page_length = 0x10; 5527 prli.payload_length = sizeof (struct la_els_prli); 5528 5529 /* fill in service params */ 5530 fprli->type = 0x08; 5531 fprli->resvd1 = 0; 5532 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5533 fprli->orig_process_associator = orig->orig_process_associator; 5534 fprli->resp_process_assoc_valid = 0; 5535 fprli->establish_image_pair = 1; 5536 fprli->resvd2 = 0; 5537 fprli->resvd3 = 0; 5538 fprli->obsolete_1 = 0; 5539 fprli->obsolete_2 = 0; 5540 fprli->data_overlay_allowed = 0; 5541 fprli->initiator_fn = 1; 5542 fprli->confirmed_compl_allowed = 1; 5543 5544 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5545 fprli->target_fn = 1; 5546 } else { 5547 fprli->target_fn = 0; 5548 } 5549 5550 fprli->retry = 1; 5551 fprli->read_xfer_rdy_disabled = 1; 5552 fprli->write_xfer_rdy_disabled = 0; 5553 5554 /* save the unsol prli payload first */ 5555 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5556 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5557 5558 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5559 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5560 5561 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5562 5563 mutex_enter(&pptr->port_mutex); 5564 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5565 int rval; 5566 mutex_exit(&pptr->port_mutex); 5567 5568 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5569 FC_SUCCESS) { 5570 if (rval == FC_STATEC_BUSY || rval == FC_OFFLINE) { 5571 fcp_queue_ipkt(pptr, fpkt); 5572 return (FC_SUCCESS); 5573 } 5574 /* Let it timeout */ 5575 fcp_icmd_free(pptr, icmd); 5576 return (FC_FAILURE); 5577 } 5578 } else { 5579 mutex_exit(&pptr->port_mutex); 5580 fcp_icmd_free(pptr, icmd); 5581 return (FC_FAILURE); 5582 } 5583 5584 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5585 5586 return (FC_SUCCESS); 5587 } 5588 5589 /* 5590 * Function: fcp_icmd_alloc 5591 * 5592 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5593 * field is initialized to fcp_icmd_callback. Sometimes it is 5594 * modified by the caller (such as fcp_send_scsi). The 5595 * structure is also tied to the state of the line and of the 5596 * target at a particular time. That link is established by 5597 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5598 * and tcount which came respectively from pptr->link_cnt and 5599 * ptgt->tgt_change_cnt. 5600 * 5601 * Argument: *pptr Fcp port. 5602 * *ptgt Target (destination of the command). 5603 * cmd_len Length of the command. 5604 * resp_len Length of the expected response. 5605 * data_len Length of the data. 5606 * nodma Indicates weither the command and response. 5607 * will be transfer through DMA or not. 5608 * lcount Link state change counter. 5609 * tcount Target state change counter. 5610 * cause Reason that lead to this call. 5611 * 5612 * Return Value: NULL Failed. 5613 * Not NULL Internal packet address. 5614 */ 5615 static struct fcp_ipkt * 5616 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5617 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5618 uint32_t rscn_count) 5619 { 5620 int dma_setup = 0; 5621 fc_packet_t *fpkt; 5622 struct fcp_ipkt *icmd = NULL; 5623 5624 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5625 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5626 KM_NOSLEEP); 5627 if (icmd == NULL) { 5628 fcp_log(CE_WARN, pptr->port_dip, 5629 "!internal packet allocation failed"); 5630 return (NULL); 5631 } 5632 5633 /* 5634 * initialize the allocated packet 5635 */ 5636 icmd->ipkt_nodma = nodma; 5637 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5638 icmd->ipkt_lun = NULL; 5639 5640 icmd->ipkt_link_cnt = lcount; 5641 icmd->ipkt_change_cnt = tcount; 5642 icmd->ipkt_cause = cause; 5643 5644 mutex_enter(&pptr->port_mutex); 5645 icmd->ipkt_port = pptr; 5646 mutex_exit(&pptr->port_mutex); 5647 5648 /* keep track of amt of data to be sent in pkt */ 5649 icmd->ipkt_cmdlen = cmd_len; 5650 icmd->ipkt_resplen = resp_len; 5651 icmd->ipkt_datalen = data_len; 5652 5653 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5654 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5655 5656 /* set pkt's private ptr to point to cmd pkt */ 5657 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5658 5659 /* set FCA private ptr to memory just beyond */ 5660 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5661 ((char *)icmd + sizeof (struct fcp_ipkt) + 5662 pptr->port_dmacookie_sz); 5663 5664 /* get ptr to fpkt substruct and fill it in */ 5665 fpkt = icmd->ipkt_fpkt; 5666 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5667 sizeof (struct fcp_ipkt)); 5668 5669 if (ptgt != NULL) { 5670 icmd->ipkt_tgt = ptgt; 5671 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5672 } 5673 5674 fpkt->pkt_comp = fcp_icmd_callback; 5675 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5676 fpkt->pkt_cmdlen = cmd_len; 5677 fpkt->pkt_rsplen = resp_len; 5678 fpkt->pkt_datalen = data_len; 5679 5680 /* 5681 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5682 * rscn_count as fcp knows down to the transport. If a valid count was 5683 * passed into this function, we allocate memory to actually pass down 5684 * this info. 5685 * 5686 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5687 * basically mean that fcp will not be able to help transport 5688 * distinguish if a new RSCN has come after fcp was last informed about 5689 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5690 * 5068068 where the device might end up going offline in case of RSCN 5691 * storms. 5692 */ 5693 fpkt->pkt_ulp_rscn_infop = NULL; 5694 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5695 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5696 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5697 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5698 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5699 fcp_trace, FCP_BUF_LEVEL_6, 0, 5700 "Failed to alloc memory to pass rscn info"); 5701 } 5702 } 5703 5704 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5705 fc_ulp_rscn_info_t *rscnp; 5706 5707 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5708 rscnp->ulp_rscn_count = rscn_count; 5709 } 5710 5711 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5712 goto fail; 5713 } 5714 dma_setup++; 5715 5716 /* 5717 * Must hold target mutex across setting of pkt_pd and call to 5718 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5719 * away while we're not looking. 5720 */ 5721 if (ptgt != NULL) { 5722 mutex_enter(&ptgt->tgt_mutex); 5723 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5724 5725 /* ask transport to do its initialization on this pkt */ 5726 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5727 != FC_SUCCESS) { 5728 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5729 fcp_trace, FCP_BUF_LEVEL_6, 0, 5730 "fc_ulp_init_packet failed"); 5731 mutex_exit(&ptgt->tgt_mutex); 5732 goto fail; 5733 } 5734 mutex_exit(&ptgt->tgt_mutex); 5735 } else { 5736 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5737 != FC_SUCCESS) { 5738 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5739 fcp_trace, FCP_BUF_LEVEL_6, 0, 5740 "fc_ulp_init_packet failed"); 5741 goto fail; 5742 } 5743 } 5744 5745 mutex_enter(&pptr->port_mutex); 5746 if (pptr->port_state & (FCP_STATE_DETACHING | 5747 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5748 int rval; 5749 5750 mutex_exit(&pptr->port_mutex); 5751 5752 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5753 ASSERT(rval == FC_SUCCESS); 5754 5755 goto fail; 5756 } 5757 5758 if (ptgt != NULL) { 5759 mutex_enter(&ptgt->tgt_mutex); 5760 ptgt->tgt_ipkt_cnt++; 5761 mutex_exit(&ptgt->tgt_mutex); 5762 } 5763 5764 pptr->port_ipkt_cnt++; 5765 5766 mutex_exit(&pptr->port_mutex); 5767 5768 return (icmd); 5769 5770 fail: 5771 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5772 kmem_free(fpkt->pkt_ulp_rscn_infop, 5773 sizeof (fc_ulp_rscn_info_t)); 5774 fpkt->pkt_ulp_rscn_infop = NULL; 5775 } 5776 5777 if (dma_setup) { 5778 fcp_free_dma(pptr, icmd); 5779 } 5780 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5781 (size_t)pptr->port_dmacookie_sz); 5782 5783 return (NULL); 5784 } 5785 5786 /* 5787 * Function: fcp_icmd_free 5788 * 5789 * Description: Frees the internal command passed by the caller. 5790 * 5791 * Argument: *pptr Fcp port. 5792 * *icmd Internal packet to free. 5793 * 5794 * Return Value: None 5795 */ 5796 static void 5797 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5798 { 5799 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5800 5801 /* Let the underlying layers do their cleanup. */ 5802 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5803 icmd->ipkt_fpkt); 5804 5805 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5806 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5807 sizeof (fc_ulp_rscn_info_t)); 5808 } 5809 5810 fcp_free_dma(pptr, icmd); 5811 5812 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5813 (size_t)pptr->port_dmacookie_sz); 5814 5815 mutex_enter(&pptr->port_mutex); 5816 5817 if (ptgt) { 5818 mutex_enter(&ptgt->tgt_mutex); 5819 ptgt->tgt_ipkt_cnt--; 5820 mutex_exit(&ptgt->tgt_mutex); 5821 } 5822 5823 pptr->port_ipkt_cnt--; 5824 mutex_exit(&pptr->port_mutex); 5825 } 5826 5827 /* 5828 * Function: fcp_alloc_dma 5829 * 5830 * Description: Allocated the DMA resources required for the internal 5831 * packet. 5832 * 5833 * Argument: *pptr FCP port. 5834 * *icmd Internal FCP packet. 5835 * nodma Indicates if the Cmd and Resp will be DMAed. 5836 * flags Allocation flags (Sleep or NoSleep). 5837 * 5838 * Return Value: FC_SUCCESS 5839 * FC_NOMEM 5840 */ 5841 static int 5842 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5843 int nodma, int flags) 5844 { 5845 int rval; 5846 size_t real_size; 5847 uint_t ccount; 5848 int bound = 0; 5849 int cmd_resp = 0; 5850 fc_packet_t *fpkt; 5851 ddi_dma_cookie_t pkt_data_cookie; 5852 ddi_dma_cookie_t *cp; 5853 uint32_t cnt; 5854 5855 fpkt = &icmd->ipkt_fc_packet; 5856 5857 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5858 fpkt->pkt_resp_dma == NULL); 5859 5860 icmd->ipkt_nodma = nodma; 5861 5862 if (nodma) { 5863 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5864 if (fpkt->pkt_cmd == NULL) { 5865 goto fail; 5866 } 5867 5868 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5869 if (fpkt->pkt_resp == NULL) { 5870 goto fail; 5871 } 5872 } else { 5873 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5874 5875 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5876 if (rval == FC_FAILURE) { 5877 ASSERT(fpkt->pkt_cmd_dma == NULL && 5878 fpkt->pkt_resp_dma == NULL); 5879 goto fail; 5880 } 5881 cmd_resp++; 5882 } 5883 5884 if (fpkt->pkt_datalen != 0) { 5885 /* 5886 * set up DMA handle and memory for the data in this packet 5887 */ 5888 if (ddi_dma_alloc_handle(pptr->port_dip, 5889 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 5890 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 5891 goto fail; 5892 } 5893 5894 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 5895 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 5896 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 5897 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 5898 goto fail; 5899 } 5900 5901 /* was DMA mem size gotten < size asked for/needed ?? */ 5902 if (real_size < fpkt->pkt_datalen) { 5903 goto fail; 5904 } 5905 5906 /* bind DMA address and handle together */ 5907 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 5908 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 5909 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 5910 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 5911 goto fail; 5912 } 5913 bound++; 5914 5915 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 5916 goto fail; 5917 } 5918 5919 fpkt->pkt_data_cookie_cnt = ccount; 5920 5921 cp = fpkt->pkt_data_cookie; 5922 *cp = pkt_data_cookie; 5923 cp++; 5924 5925 for (cnt = 1; cnt < ccount; cnt++, cp++) { 5926 ddi_dma_nextcookie(fpkt->pkt_data_dma, 5927 &pkt_data_cookie); 5928 *cp = pkt_data_cookie; 5929 } 5930 5931 } 5932 5933 return (FC_SUCCESS); 5934 5935 fail: 5936 if (bound) { 5937 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 5938 } 5939 5940 if (fpkt->pkt_data_dma) { 5941 if (fpkt->pkt_data) { 5942 ddi_dma_mem_free(&fpkt->pkt_data_acc); 5943 } 5944 ddi_dma_free_handle(&fpkt->pkt_data_dma); 5945 } 5946 5947 if (nodma) { 5948 if (fpkt->pkt_cmd) { 5949 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 5950 } 5951 if (fpkt->pkt_resp) { 5952 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 5953 } 5954 } else { 5955 if (cmd_resp) { 5956 fcp_free_cmd_resp(pptr, fpkt); 5957 } 5958 } 5959 5960 return (FC_NOMEM); 5961 } 5962 5963 5964 static void 5965 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5966 { 5967 fc_packet_t *fpkt = icmd->ipkt_fpkt; 5968 5969 if (fpkt->pkt_data_dma) { 5970 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 5971 if (fpkt->pkt_data) { 5972 ddi_dma_mem_free(&fpkt->pkt_data_acc); 5973 } 5974 ddi_dma_free_handle(&fpkt->pkt_data_dma); 5975 } 5976 5977 if (icmd->ipkt_nodma) { 5978 if (fpkt->pkt_cmd) { 5979 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 5980 } 5981 if (fpkt->pkt_resp) { 5982 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 5983 } 5984 } else { 5985 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 5986 5987 fcp_free_cmd_resp(pptr, fpkt); 5988 } 5989 } 5990 5991 /* 5992 * Function: fcp_lookup_target 5993 * 5994 * Description: Finds a target given a WWN. 5995 * 5996 * Argument: *pptr FCP port. 5997 * *wwn World Wide Name of the device to look for. 5998 * 5999 * Return Value: NULL No target found 6000 * Not NULL Target structure 6001 * 6002 * Context: Interrupt context. 6003 * The mutex pptr->port_mutex must be owned. 6004 */ 6005 /* ARGSUSED */ 6006 static struct fcp_tgt * 6007 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6008 { 6009 int hash; 6010 struct fcp_tgt *ptgt; 6011 6012 ASSERT(mutex_owned(&pptr->port_mutex)); 6013 6014 hash = FCP_HASH(wwn); 6015 6016 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6017 ptgt = ptgt->tgt_next) { 6018 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6019 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6020 sizeof (ptgt->tgt_port_wwn)) == 0) { 6021 break; 6022 } 6023 } 6024 6025 return (ptgt); 6026 } 6027 6028 6029 /* 6030 * Find target structure given a port identifier 6031 */ 6032 static struct fcp_tgt * 6033 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6034 { 6035 fc_portid_t port_id; 6036 la_wwn_t pwwn; 6037 struct fcp_tgt *ptgt = NULL; 6038 6039 port_id.priv_lilp_posit = 0; 6040 port_id.port_id = d_id; 6041 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6042 &pwwn) == FC_SUCCESS) { 6043 mutex_enter(&pptr->port_mutex); 6044 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6045 mutex_exit(&pptr->port_mutex); 6046 } 6047 6048 return (ptgt); 6049 } 6050 6051 6052 /* 6053 * the packet completion callback routine for info cmd pkts 6054 * 6055 * this means fpkt pts to a response to either a PLOGI or a PRLI 6056 * 6057 * if there is an error an attempt is made to call a routine to resend 6058 * the command that failed 6059 */ 6060 static void 6061 fcp_icmd_callback(fc_packet_t *fpkt) 6062 { 6063 struct fcp_ipkt *icmd; 6064 struct fcp_port *pptr; 6065 struct fcp_tgt *ptgt; 6066 struct la_els_prli *prli; 6067 struct la_els_prli prli_s; 6068 struct fcp_prli *fprli; 6069 struct fcp_lun *plun; 6070 int free_pkt = 1; 6071 int rval; 6072 ls_code_t resp; 6073 uchar_t prli_acc = 0; 6074 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6075 int lun0_newalloc; 6076 6077 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6078 6079 /* get ptrs to the port and target structs for the cmd */ 6080 pptr = icmd->ipkt_port; 6081 ptgt = icmd->ipkt_tgt; 6082 6083 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6084 6085 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6086 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6087 sizeof (prli_s)); 6088 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6089 } 6090 6091 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6092 fcp_trace, FCP_BUF_LEVEL_2, 0, 6093 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6094 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6095 ptgt->tgt_d_id); 6096 6097 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6098 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6099 6100 mutex_enter(&ptgt->tgt_mutex); 6101 if (ptgt->tgt_pd_handle == NULL) { 6102 /* 6103 * in a fabric environment the port device handles 6104 * get created only after successful LOGIN into the 6105 * transport, so the transport makes this port 6106 * device (pd) handle available in this packet, so 6107 * save it now 6108 */ 6109 ASSERT(fpkt->pkt_pd != NULL); 6110 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6111 } 6112 mutex_exit(&ptgt->tgt_mutex); 6113 6114 /* which ELS cmd is this response for ?? */ 6115 switch (icmd->ipkt_opcode) { 6116 case LA_ELS_PLOGI: 6117 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6118 fcp_trace, FCP_BUF_LEVEL_5, 0, 6119 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6120 ptgt->tgt_d_id, 6121 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6122 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6123 6124 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6125 FCP_TGT_TRACE_15); 6126 6127 /* Note that we are not allocating a new icmd */ 6128 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6129 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6130 icmd->ipkt_cause) != DDI_SUCCESS) { 6131 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6132 FCP_TGT_TRACE_16); 6133 goto fail; 6134 } 6135 break; 6136 6137 case LA_ELS_PRLI: 6138 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6139 fcp_trace, FCP_BUF_LEVEL_5, 0, 6140 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6141 6142 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6143 FCP_TGT_TRACE_17); 6144 6145 prli = &prli_s; 6146 6147 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6148 sizeof (prli_s)); 6149 6150 fprli = (struct fcp_prli *)prli->service_params; 6151 6152 mutex_enter(&ptgt->tgt_mutex); 6153 ptgt->tgt_icap = fprli->initiator_fn; 6154 ptgt->tgt_tcap = fprli->target_fn; 6155 mutex_exit(&ptgt->tgt_mutex); 6156 6157 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6158 /* 6159 * this FCP device does not support target mode 6160 */ 6161 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6162 FCP_TGT_TRACE_18); 6163 goto fail; 6164 } 6165 if (fprli->retry == 1) { 6166 fc_ulp_disable_relogin(pptr->port_fp_handle, 6167 &ptgt->tgt_port_wwn); 6168 } 6169 6170 /* target is no longer offline */ 6171 mutex_enter(&pptr->port_mutex); 6172 mutex_enter(&ptgt->tgt_mutex); 6173 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6174 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6175 FCP_TGT_MARK); 6176 } else { 6177 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6178 fcp_trace, FCP_BUF_LEVEL_2, 0, 6179 "fcp_icmd_callback,1: state change " 6180 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6181 mutex_exit(&ptgt->tgt_mutex); 6182 mutex_exit(&pptr->port_mutex); 6183 goto fail; 6184 } 6185 mutex_exit(&ptgt->tgt_mutex); 6186 mutex_exit(&pptr->port_mutex); 6187 6188 /* 6189 * lun 0 should always respond to inquiry, so 6190 * get the LUN struct for LUN 0 6191 * 6192 * Currently we deal with first level of addressing. 6193 * If / when we start supporting 0x device types 6194 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6195 * this logic will need revisiting. 6196 */ 6197 lun0_newalloc = 0; 6198 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6199 /* 6200 * no LUN struct for LUN 0 yet exists, 6201 * so create one 6202 */ 6203 plun = fcp_alloc_lun(ptgt); 6204 if (plun == NULL) { 6205 fcp_log(CE_WARN, pptr->port_dip, 6206 "!Failed to allocate lun 0 for" 6207 " D_ID=%x", ptgt->tgt_d_id); 6208 goto fail; 6209 } 6210 lun0_newalloc = 1; 6211 } 6212 6213 /* fill in LUN info */ 6214 mutex_enter(&ptgt->tgt_mutex); 6215 /* 6216 * consider lun 0 as device not connected if it is 6217 * offlined or newly allocated 6218 */ 6219 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6220 lun0_newalloc) { 6221 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6222 } 6223 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6224 plun->lun_state &= ~FCP_LUN_OFFLINE; 6225 ptgt->tgt_lun_cnt = 1; 6226 ptgt->tgt_report_lun_cnt = 0; 6227 mutex_exit(&ptgt->tgt_mutex); 6228 6229 /* Retrieve the rscn count (if a valid one exists) */ 6230 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6231 rscn_count = ((fc_ulp_rscn_info_t *) 6232 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6233 ->ulp_rscn_count; 6234 } else { 6235 rscn_count = FC_INVALID_RSCN_COUNT; 6236 } 6237 6238 /* send Report Lun request to target */ 6239 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6240 sizeof (struct fcp_reportlun_resp), 6241 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6242 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6243 mutex_enter(&pptr->port_mutex); 6244 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6245 fcp_log(CE_WARN, pptr->port_dip, 6246 "!Failed to send REPORT LUN to" 6247 " D_ID=%x", ptgt->tgt_d_id); 6248 } else { 6249 FCP_TRACE(fcp_logq, 6250 pptr->port_instbuf, fcp_trace, 6251 FCP_BUF_LEVEL_5, 0, 6252 "fcp_icmd_callback,2:state change" 6253 " occured for D_ID=0x%x", 6254 ptgt->tgt_d_id); 6255 } 6256 mutex_exit(&pptr->port_mutex); 6257 6258 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6259 FCP_TGT_TRACE_19); 6260 6261 goto fail; 6262 } else { 6263 free_pkt = 0; 6264 fcp_icmd_free(pptr, icmd); 6265 } 6266 break; 6267 6268 default: 6269 fcp_log(CE_WARN, pptr->port_dip, 6270 "!fcp_icmd_callback Invalid opcode"); 6271 goto fail; 6272 } 6273 6274 return; 6275 } 6276 6277 6278 /* 6279 * Other PLOGI failures are not retried as the 6280 * transport does it already 6281 */ 6282 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6283 if (fcp_is_retryable(icmd) && 6284 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6285 6286 if (FCP_MUST_RETRY(fpkt)) { 6287 fcp_queue_ipkt(pptr, fpkt); 6288 return; 6289 } 6290 6291 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6292 fcp_trace, FCP_BUF_LEVEL_2, 0, 6293 "ELS PRLI is retried for d_id=0x%x, state=%x," 6294 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6295 fpkt->pkt_reason); 6296 6297 /* 6298 * Retry by recalling the routine that 6299 * originally queued this packet 6300 */ 6301 mutex_enter(&pptr->port_mutex); 6302 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6303 caddr_t msg; 6304 6305 mutex_exit(&pptr->port_mutex); 6306 6307 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6308 6309 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6310 fpkt->pkt_timeout += 6311 FCP_TIMEOUT_DELTA; 6312 } 6313 6314 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6315 fpkt); 6316 if (rval == FC_SUCCESS) { 6317 return; 6318 } 6319 6320 if (rval == FC_STATEC_BUSY || 6321 rval == FC_OFFLINE) { 6322 fcp_queue_ipkt(pptr, fpkt); 6323 return; 6324 } 6325 (void) fc_ulp_error(rval, &msg); 6326 6327 fcp_log(CE_NOTE, pptr->port_dip, 6328 "!ELS 0x%x failed to d_id=0x%x;" 6329 " %s", icmd->ipkt_opcode, 6330 ptgt->tgt_d_id, msg); 6331 } else { 6332 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6333 fcp_trace, FCP_BUF_LEVEL_2, 0, 6334 "fcp_icmd_callback,3: state change " 6335 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6336 mutex_exit(&pptr->port_mutex); 6337 } 6338 } 6339 } else { 6340 if (fcp_is_retryable(icmd) && 6341 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6342 if (FCP_MUST_RETRY(fpkt)) { 6343 fcp_queue_ipkt(pptr, fpkt); 6344 return; 6345 } 6346 } 6347 mutex_enter(&pptr->port_mutex); 6348 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6349 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6350 mutex_exit(&pptr->port_mutex); 6351 fcp_print_error(fpkt); 6352 } else { 6353 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6354 fcp_trace, FCP_BUF_LEVEL_2, 0, 6355 "fcp_icmd_callback,4: state change occured" 6356 " for D_ID=0x%x", ptgt->tgt_d_id); 6357 mutex_exit(&pptr->port_mutex); 6358 } 6359 } 6360 6361 fail: 6362 if (free_pkt) { 6363 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6364 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6365 fcp_icmd_free(pptr, icmd); 6366 } 6367 } 6368 6369 6370 /* 6371 * called internally to send an info cmd using the transport 6372 * 6373 * sends either an INQ or a REPORT_LUN 6374 * 6375 * when the packet is completed fcp_scsi_callback is called 6376 */ 6377 static int 6378 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6379 int lcount, int tcount, int cause, uint32_t rscn_count) 6380 { 6381 int nodma; 6382 struct fcp_ipkt *icmd; 6383 struct fcp_tgt *ptgt; 6384 struct fcp_port *pptr; 6385 fc_frame_hdr_t *hp; 6386 fc_packet_t *fpkt; 6387 struct fcp_cmd fcp_cmd; 6388 struct fcp_cmd *fcmd; 6389 union scsi_cdb *scsi_cdb; 6390 6391 ASSERT(plun != NULL); 6392 6393 ptgt = plun->lun_tgt; 6394 ASSERT(ptgt != NULL); 6395 6396 pptr = ptgt->tgt_port; 6397 ASSERT(pptr != NULL); 6398 6399 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6400 fcp_trace, FCP_BUF_LEVEL_5, 0, 6401 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6402 6403 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6404 6405 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6406 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6407 rscn_count); 6408 6409 if (icmd == NULL) { 6410 return (DDI_FAILURE); 6411 } 6412 6413 fpkt = icmd->ipkt_fpkt; 6414 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6415 icmd->ipkt_retries = 0; 6416 icmd->ipkt_opcode = opcode; 6417 icmd->ipkt_lun = plun; 6418 6419 if (nodma) { 6420 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6421 } else { 6422 fcmd = &fcp_cmd; 6423 } 6424 bzero(fcmd, sizeof (struct fcp_cmd)); 6425 6426 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6427 6428 hp = &fpkt->pkt_cmd_fhdr; 6429 6430 hp->s_id = pptr->port_id; 6431 hp->d_id = ptgt->tgt_d_id; 6432 hp->r_ctl = R_CTL_COMMAND; 6433 hp->type = FC_TYPE_SCSI_FCP; 6434 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6435 hp->rsvd = 0; 6436 hp->seq_id = 0; 6437 hp->seq_cnt = 0; 6438 hp->ox_id = 0xffff; 6439 hp->rx_id = 0xffff; 6440 hp->ro = 0; 6441 6442 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6443 6444 /* 6445 * Request SCSI target for expedited processing 6446 */ 6447 6448 /* 6449 * Set up for untagged queuing because we do not 6450 * know if the fibre device supports queuing. 6451 */ 6452 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6453 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6454 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6455 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6456 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6457 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6458 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6459 6460 switch (opcode) { 6461 case SCMD_INQUIRY_PAGE83: 6462 /* 6463 * Prepare to get the Inquiry VPD page 83 information 6464 */ 6465 fcmd->fcp_cntl.cntl_read_data = 1; 6466 fcmd->fcp_cntl.cntl_write_data = 0; 6467 fcmd->fcp_data_len = alloc_len; 6468 6469 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6470 fpkt->pkt_comp = fcp_scsi_callback; 6471 6472 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6473 scsi_cdb->g0_addr2 = 0x01; 6474 scsi_cdb->g0_addr1 = 0x83; 6475 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6476 break; 6477 6478 case SCMD_INQUIRY: 6479 fcmd->fcp_cntl.cntl_read_data = 1; 6480 fcmd->fcp_cntl.cntl_write_data = 0; 6481 fcmd->fcp_data_len = alloc_len; 6482 6483 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6484 fpkt->pkt_comp = fcp_scsi_callback; 6485 6486 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6487 scsi_cdb->g0_count0 = SUN_INQSIZE; 6488 break; 6489 6490 case SCMD_REPORT_LUN: { 6491 fc_portid_t d_id; 6492 opaque_t fca_dev; 6493 6494 ASSERT(alloc_len >= 16); 6495 6496 d_id.priv_lilp_posit = 0; 6497 d_id.port_id = ptgt->tgt_d_id; 6498 6499 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6500 6501 mutex_enter(&ptgt->tgt_mutex); 6502 ptgt->tgt_fca_dev = fca_dev; 6503 mutex_exit(&ptgt->tgt_mutex); 6504 6505 fcmd->fcp_cntl.cntl_read_data = 1; 6506 fcmd->fcp_cntl.cntl_write_data = 0; 6507 fcmd->fcp_data_len = alloc_len; 6508 6509 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6510 fpkt->pkt_comp = fcp_scsi_callback; 6511 6512 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6513 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6514 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6515 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6516 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6517 break; 6518 } 6519 6520 default: 6521 fcp_log(CE_WARN, pptr->port_dip, 6522 "!fcp_send_scsi Invalid opcode"); 6523 break; 6524 } 6525 6526 if (!nodma) { 6527 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6528 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6529 } 6530 6531 mutex_enter(&pptr->port_mutex); 6532 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6533 6534 mutex_exit(&pptr->port_mutex); 6535 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6536 FC_SUCCESS) { 6537 fcp_icmd_free(pptr, icmd); 6538 return (DDI_FAILURE); 6539 } 6540 return (DDI_SUCCESS); 6541 } else { 6542 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6543 fcp_trace, FCP_BUF_LEVEL_2, 0, 6544 "fcp_send_scsi,1: state change occured" 6545 " for D_ID=0x%x", ptgt->tgt_d_id); 6546 mutex_exit(&pptr->port_mutex); 6547 fcp_icmd_free(pptr, icmd); 6548 return (DDI_FAILURE); 6549 } 6550 } 6551 6552 6553 /* 6554 * called by fcp_scsi_callback to check to handle the case where 6555 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6556 */ 6557 static int 6558 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6559 { 6560 uchar_t rqlen; 6561 int rval = DDI_FAILURE; 6562 struct scsi_extended_sense sense_info, *sense; 6563 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6564 fpkt->pkt_ulp_private; 6565 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6566 struct fcp_port *pptr = ptgt->tgt_port; 6567 6568 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6569 6570 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6571 /* 6572 * SCSI-II Reserve Release support. Some older FC drives return 6573 * Reservation conflict for Report Luns command. 6574 */ 6575 if (icmd->ipkt_nodma) { 6576 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6577 rsp->fcp_u.fcp_status.sense_len_set = 0; 6578 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6579 } else { 6580 fcp_rsp_t new_resp; 6581 6582 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6583 fpkt->pkt_resp_acc, sizeof (new_resp)); 6584 6585 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6586 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6587 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6588 6589 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6590 fpkt->pkt_resp_acc, sizeof (new_resp)); 6591 } 6592 6593 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6594 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6595 6596 return (DDI_SUCCESS); 6597 } 6598 6599 sense = &sense_info; 6600 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6601 /* no need to continue if sense length is not set */ 6602 return (rval); 6603 } 6604 6605 /* casting 64-bit integer to 8-bit */ 6606 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6607 sizeof (struct scsi_extended_sense)); 6608 6609 if (rqlen < 14) { 6610 /* no need to continue if request length isn't long enough */ 6611 return (rval); 6612 } 6613 6614 if (icmd->ipkt_nodma) { 6615 /* 6616 * We can safely use fcp_response_len here since the 6617 * only path that calls fcp_check_reportlun, 6618 * fcp_scsi_callback, has already called 6619 * fcp_validate_fcp_response. 6620 */ 6621 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6622 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6623 } else { 6624 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6625 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6626 sizeof (struct scsi_extended_sense)); 6627 } 6628 6629 if (!FCP_SENSE_NO_LUN(sense)) { 6630 mutex_enter(&ptgt->tgt_mutex); 6631 /* clear the flag if any */ 6632 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6633 mutex_exit(&ptgt->tgt_mutex); 6634 } 6635 6636 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6637 (sense->es_add_code == 0x20)) { 6638 if (icmd->ipkt_nodma) { 6639 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6640 rsp->fcp_u.fcp_status.sense_len_set = 0; 6641 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6642 } else { 6643 fcp_rsp_t new_resp; 6644 6645 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6646 fpkt->pkt_resp_acc, sizeof (new_resp)); 6647 6648 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6649 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6650 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6651 6652 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6653 fpkt->pkt_resp_acc, sizeof (new_resp)); 6654 } 6655 6656 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6657 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6658 6659 return (DDI_SUCCESS); 6660 } 6661 6662 /* 6663 * This is for the STK library which returns a check condition, 6664 * to indicate device is not ready, manual assistance needed. 6665 * This is to a report lun command when the door is open. 6666 */ 6667 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6668 if (icmd->ipkt_nodma) { 6669 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6670 rsp->fcp_u.fcp_status.sense_len_set = 0; 6671 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6672 } else { 6673 fcp_rsp_t new_resp; 6674 6675 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6676 fpkt->pkt_resp_acc, sizeof (new_resp)); 6677 6678 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6679 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6680 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6681 6682 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6683 fpkt->pkt_resp_acc, sizeof (new_resp)); 6684 } 6685 6686 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6687 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6688 6689 return (DDI_SUCCESS); 6690 } 6691 6692 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6693 (FCP_SENSE_NO_LUN(sense))) { 6694 mutex_enter(&ptgt->tgt_mutex); 6695 if ((FCP_SENSE_NO_LUN(sense)) && 6696 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6697 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6698 mutex_exit(&ptgt->tgt_mutex); 6699 /* 6700 * reconfig was triggred by ILLEGAL REQUEST but 6701 * got ILLEGAL REQUEST again 6702 */ 6703 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6704 fcp_trace, FCP_BUF_LEVEL_3, 0, 6705 "!FCP: Unable to obtain Report Lun data" 6706 " target=%x", ptgt->tgt_d_id); 6707 } else { 6708 if (ptgt->tgt_tid == NULL) { 6709 timeout_id_t tid; 6710 /* 6711 * REPORT LUN data has changed. Kick off 6712 * rediscovery 6713 */ 6714 tid = timeout(fcp_reconfigure_luns, 6715 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6716 6717 ptgt->tgt_tid = tid; 6718 ptgt->tgt_state |= FCP_TGT_BUSY; 6719 } 6720 if (FCP_SENSE_NO_LUN(sense)) { 6721 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6722 } 6723 mutex_exit(&ptgt->tgt_mutex); 6724 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6725 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6726 fcp_trace, FCP_BUF_LEVEL_3, 0, 6727 "!FCP:Report Lun Has Changed" 6728 " target=%x", ptgt->tgt_d_id); 6729 } else if (FCP_SENSE_NO_LUN(sense)) { 6730 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6731 fcp_trace, FCP_BUF_LEVEL_3, 0, 6732 "!FCP:LU Not Supported" 6733 " target=%x", ptgt->tgt_d_id); 6734 } 6735 } 6736 rval = DDI_SUCCESS; 6737 } 6738 6739 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6740 fcp_trace, FCP_BUF_LEVEL_5, 0, 6741 "D_ID=%x, sense=%x, status=%x", 6742 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6743 rsp->fcp_u.fcp_status.scsi_status); 6744 6745 return (rval); 6746 } 6747 6748 /* 6749 * Function: fcp_scsi_callback 6750 * 6751 * Description: This is the callback routine set by fcp_send_scsi() after 6752 * it calls fcp_icmd_alloc(). The SCSI command completed here 6753 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6754 * INQUIRY_PAGE83. 6755 * 6756 * Argument: *fpkt FC packet used to convey the command 6757 * 6758 * Return Value: None 6759 */ 6760 static void 6761 fcp_scsi_callback(fc_packet_t *fpkt) 6762 { 6763 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6764 fpkt->pkt_ulp_private; 6765 struct fcp_rsp_info fcp_rsp_err, *bep; 6766 struct fcp_port *pptr; 6767 struct fcp_tgt *ptgt; 6768 struct fcp_lun *plun; 6769 struct fcp_rsp response, *rsp; 6770 6771 if (icmd->ipkt_nodma) { 6772 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6773 } else { 6774 rsp = &response; 6775 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6776 sizeof (struct fcp_rsp)); 6777 } 6778 6779 ptgt = icmd->ipkt_tgt; 6780 pptr = ptgt->tgt_port; 6781 plun = icmd->ipkt_lun; 6782 6783 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6784 fcp_trace, FCP_BUF_LEVEL_2, 0, 6785 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6786 "status=%x, lun num=%x", 6787 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6788 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6789 6790 /* 6791 * Pre-init LUN GUID with NWWN if it is not a device that 6792 * supports multiple luns and we know it's not page83 6793 * compliant. Although using a NWWN is not lun unique, 6794 * we will be fine since there is only one lun behind the taget 6795 * in this case. 6796 */ 6797 if ((plun->lun_guid_size == 0) && 6798 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6799 (fcp_symmetric_device_probe(plun) == 0)) { 6800 6801 char ascii_wwn[FC_WWN_SIZE*2+1]; 6802 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6803 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6804 } 6805 6806 /* 6807 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6808 * when thay have more data than what is asked in CDB. An overrun 6809 * is really when FCP_DL is smaller than the data length in CDB. 6810 * In the case here we know that REPORT LUN command we formed within 6811 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6812 * behavior. In reality this is FC_SUCCESS. 6813 */ 6814 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6815 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6816 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6817 fpkt->pkt_state = FC_PKT_SUCCESS; 6818 } 6819 6820 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6821 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6822 fcp_trace, FCP_BUF_LEVEL_2, 0, 6823 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6824 ptgt->tgt_d_id); 6825 6826 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6827 /* 6828 * Inquiry VPD page command on A5K SES devices would 6829 * result in data CRC errors. 6830 */ 6831 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6832 (void) fcp_handle_page83(fpkt, icmd, 1); 6833 return; 6834 } 6835 } 6836 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6837 FCP_MUST_RETRY(fpkt)) { 6838 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6839 fcp_retry_scsi_cmd(fpkt); 6840 return; 6841 } 6842 6843 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6844 FCP_TGT_TRACE_20); 6845 6846 mutex_enter(&pptr->port_mutex); 6847 mutex_enter(&ptgt->tgt_mutex); 6848 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6849 mutex_exit(&ptgt->tgt_mutex); 6850 mutex_exit(&pptr->port_mutex); 6851 fcp_print_error(fpkt); 6852 } else { 6853 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6854 fcp_trace, FCP_BUF_LEVEL_2, 0, 6855 "fcp_scsi_callback,1: state change occured" 6856 " for D_ID=0x%x", ptgt->tgt_d_id); 6857 mutex_exit(&ptgt->tgt_mutex); 6858 mutex_exit(&pptr->port_mutex); 6859 } 6860 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6861 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6862 fcp_icmd_free(pptr, icmd); 6863 return; 6864 } 6865 6866 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 6867 6868 mutex_enter(&pptr->port_mutex); 6869 mutex_enter(&ptgt->tgt_mutex); 6870 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6871 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6872 fcp_trace, FCP_BUF_LEVEL_2, 0, 6873 "fcp_scsi_callback,2: state change occured" 6874 " for D_ID=0x%x", ptgt->tgt_d_id); 6875 mutex_exit(&ptgt->tgt_mutex); 6876 mutex_exit(&pptr->port_mutex); 6877 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6878 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6879 fcp_icmd_free(pptr, icmd); 6880 return; 6881 } 6882 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 6883 6884 mutex_exit(&ptgt->tgt_mutex); 6885 mutex_exit(&pptr->port_mutex); 6886 6887 if (icmd->ipkt_nodma) { 6888 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 6889 sizeof (struct fcp_rsp)); 6890 } else { 6891 bep = &fcp_rsp_err; 6892 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 6893 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 6894 } 6895 6896 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 6897 fcp_retry_scsi_cmd(fpkt); 6898 return; 6899 } 6900 6901 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 6902 FCP_NO_FAILURE) { 6903 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6904 fcp_trace, FCP_BUF_LEVEL_2, 0, 6905 "rsp_code=0x%x, rsp_len_set=0x%x", 6906 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 6907 fcp_retry_scsi_cmd(fpkt); 6908 return; 6909 } 6910 6911 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 6912 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 6913 fcp_queue_ipkt(pptr, fpkt); 6914 return; 6915 } 6916 6917 /* 6918 * Devices that do not support INQUIRY_PAGE83, return check condition 6919 * with illegal request as per SCSI spec. 6920 * Crossbridge is one such device and Daktari's SES node is another. 6921 * We want to ideally enumerate these devices as a non-mpxio devices. 6922 * SES nodes (Daktari only currently) are an exception to this. 6923 */ 6924 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6925 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 6926 6927 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6928 fcp_trace, FCP_BUF_LEVEL_3, 0, 6929 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 6930 "check condition. May enumerate as non-mpxio device", 6931 ptgt->tgt_d_id, plun->lun_type); 6932 6933 /* 6934 * If we let Daktari's SES be enumerated as a non-mpxio 6935 * device, there will be a discrepency in that the other 6936 * internal FC disks will get enumerated as mpxio devices. 6937 * Applications like luxadm expect this to be consistent. 6938 * 6939 * So, we put in a hack here to check if this is an SES device 6940 * and handle it here. 6941 */ 6942 if (plun->lun_type == DTYPE_ESI) { 6943 /* 6944 * Since, pkt_state is actually FC_PKT_SUCCESS 6945 * at this stage, we fake a failure here so that 6946 * fcp_handle_page83 will create a device path using 6947 * the WWN instead of the GUID which is not there anyway 6948 */ 6949 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 6950 (void) fcp_handle_page83(fpkt, icmd, 1); 6951 return; 6952 } 6953 6954 mutex_enter(&ptgt->tgt_mutex); 6955 plun->lun_state &= ~(FCP_LUN_OFFLINE | 6956 FCP_LUN_MARK | FCP_LUN_BUSY); 6957 mutex_exit(&ptgt->tgt_mutex); 6958 6959 (void) fcp_call_finish_init(pptr, ptgt, 6960 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6961 icmd->ipkt_cause); 6962 fcp_icmd_free(pptr, icmd); 6963 return; 6964 } 6965 6966 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 6967 int rval = DDI_FAILURE; 6968 6969 /* 6970 * handle cases where report lun isn't supported 6971 * by faking up our own REPORT_LUN response or 6972 * UNIT ATTENTION 6973 */ 6974 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 6975 rval = fcp_check_reportlun(rsp, fpkt); 6976 6977 /* 6978 * fcp_check_reportlun might have modified the 6979 * FCP response. Copy it in again to get an updated 6980 * FCP response 6981 */ 6982 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 6983 rsp = &response; 6984 6985 FCP_CP_IN(fpkt->pkt_resp, rsp, 6986 fpkt->pkt_resp_acc, 6987 sizeof (struct fcp_rsp)); 6988 } 6989 } 6990 6991 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 6992 if (rval == DDI_SUCCESS) { 6993 (void) fcp_call_finish_init(pptr, ptgt, 6994 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6995 icmd->ipkt_cause); 6996 fcp_icmd_free(pptr, icmd); 6997 } else { 6998 fcp_retry_scsi_cmd(fpkt); 6999 } 7000 7001 return; 7002 } 7003 } else { 7004 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7005 mutex_enter(&ptgt->tgt_mutex); 7006 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7007 mutex_exit(&ptgt->tgt_mutex); 7008 } 7009 } 7010 7011 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7012 7013 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, DDI_DMA_SYNC_FORCPU); 7014 7015 switch (icmd->ipkt_opcode) { 7016 case SCMD_INQUIRY: 7017 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7018 fcp_handle_inquiry(fpkt, icmd); 7019 break; 7020 7021 case SCMD_REPORT_LUN: 7022 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7023 FCP_TGT_TRACE_22); 7024 fcp_handle_reportlun(fpkt, icmd); 7025 break; 7026 7027 case SCMD_INQUIRY_PAGE83: 7028 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7029 (void) fcp_handle_page83(fpkt, icmd, 0); 7030 break; 7031 7032 default: 7033 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7034 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7035 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7036 fcp_icmd_free(pptr, icmd); 7037 break; 7038 } 7039 } 7040 7041 7042 static void 7043 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7044 { 7045 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7046 fpkt->pkt_ulp_private; 7047 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7048 struct fcp_port *pptr = ptgt->tgt_port; 7049 7050 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7051 fcp_is_retryable(icmd)) { 7052 mutex_enter(&pptr->port_mutex); 7053 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7054 mutex_exit(&pptr->port_mutex); 7055 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7056 fcp_trace, FCP_BUF_LEVEL_3, 0, 7057 "Retrying %s to %x; state=%x, reason=%x", 7058 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7059 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7060 fpkt->pkt_state, fpkt->pkt_reason); 7061 7062 fcp_queue_ipkt(pptr, fpkt); 7063 } else { 7064 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7065 fcp_trace, FCP_BUF_LEVEL_3, 0, 7066 "fcp_retry_scsi_cmd,1: state change occured" 7067 " for D_ID=0x%x", ptgt->tgt_d_id); 7068 mutex_exit(&pptr->port_mutex); 7069 (void) fcp_call_finish_init(pptr, ptgt, 7070 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7071 icmd->ipkt_cause); 7072 fcp_icmd_free(pptr, icmd); 7073 } 7074 } else { 7075 fcp_print_error(fpkt); 7076 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7077 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7078 fcp_icmd_free(pptr, icmd); 7079 } 7080 } 7081 7082 /* 7083 * Function: fcp_handle_page83 7084 * 7085 * Description: Treats the response to INQUIRY_PAGE83. 7086 * 7087 * Argument: *fpkt FC packet used to convey the command. 7088 * *icmd Original fcp_ipkt structure. 7089 * ignore_page83_data 7090 * if it's 1, that means it's a special devices's 7091 * page83 response, it should be enumerated under mpxio 7092 * 7093 * Return Value: None 7094 */ 7095 static void 7096 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7097 int ignore_page83_data) 7098 { 7099 struct fcp_port *pptr; 7100 struct fcp_lun *plun; 7101 struct fcp_tgt *ptgt; 7102 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7103 int fail = 0; 7104 ddi_devid_t devid; 7105 char *guid = NULL; 7106 int ret; 7107 7108 ASSERT(icmd != NULL && fpkt != NULL); 7109 7110 pptr = icmd->ipkt_port; 7111 ptgt = icmd->ipkt_tgt; 7112 plun = icmd->ipkt_lun; 7113 7114 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7115 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7116 7117 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7118 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7119 7120 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7121 fcp_trace, FCP_BUF_LEVEL_5, 0, 7122 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7123 "dtype=0x%x, lun num=%x", 7124 pptr->port_instance, ptgt->tgt_d_id, 7125 dev_id_page[0], plun->lun_num); 7126 7127 ret = ddi_devid_scsi_encode( 7128 DEVID_SCSI_ENCODE_VERSION_LATEST, 7129 NULL, /* driver name */ 7130 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7131 sizeof (plun->lun_inq), /* size of standard inquiry */ 7132 NULL, /* page 80 data */ 7133 0, /* page 80 len */ 7134 dev_id_page, /* page 83 data */ 7135 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7136 &devid); 7137 7138 if (ret == DDI_SUCCESS) { 7139 7140 guid = ddi_devid_to_guid(devid); 7141 7142 if (guid) { 7143 /* 7144 * Check our current guid. If it's non null 7145 * and it has changed, we need to copy it into 7146 * lun_old_guid since we might still need it. 7147 */ 7148 if (plun->lun_guid && 7149 strcmp(guid, plun->lun_guid)) { 7150 unsigned int len; 7151 7152 /* 7153 * If the guid of the LUN changes, 7154 * reconfiguration should be triggered 7155 * to reflect the changes. 7156 * i.e. we should offline the LUN with 7157 * the old guid, and online the LUN with 7158 * the new guid. 7159 */ 7160 plun->lun_state |= FCP_LUN_CHANGED; 7161 7162 if (plun->lun_old_guid) { 7163 kmem_free(plun->lun_old_guid, 7164 plun->lun_old_guid_size); 7165 } 7166 7167 len = plun->lun_guid_size; 7168 plun->lun_old_guid_size = len; 7169 7170 plun->lun_old_guid = kmem_zalloc(len, 7171 KM_NOSLEEP); 7172 7173 if (plun->lun_old_guid) { 7174 /* 7175 * The alloc was successful then 7176 * let's do the copy. 7177 */ 7178 bcopy(plun->lun_guid, 7179 plun->lun_old_guid, len); 7180 } else { 7181 fail = 1; 7182 plun->lun_old_guid_size = 0; 7183 } 7184 } 7185 if (!fail) { 7186 if (fcp_copy_guid_2_lun_block( 7187 plun, guid)) { 7188 fail = 1; 7189 } 7190 } 7191 ddi_devid_free_guid(guid); 7192 7193 } else { 7194 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7195 fcp_trace, FCP_BUF_LEVEL_2, 0, 7196 "fcp_handle_page83: unable to create " 7197 "GUID"); 7198 7199 /* couldn't create good guid from devid */ 7200 fail = 1; 7201 } 7202 ddi_devid_free(devid); 7203 7204 } else if (ret == DDI_NOT_WELL_FORMED) { 7205 /* NULL filled data for page 83 */ 7206 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7207 fcp_trace, FCP_BUF_LEVEL_2, 0, 7208 "fcp_handle_page83: retry GUID"); 7209 7210 icmd->ipkt_retries = 0; 7211 fcp_retry_scsi_cmd(fpkt); 7212 return; 7213 } else { 7214 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7215 fcp_trace, FCP_BUF_LEVEL_2, 0, 7216 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7217 ret); 7218 /* 7219 * Since the page83 validation 7220 * introduced late, we are being 7221 * tolerant to the existing devices 7222 * that already found to be working 7223 * under mpxio, like A5200's SES device, 7224 * its page83 response will not be standard-compliant, 7225 * but we still want it to be enumerated under mpxio. 7226 */ 7227 if (fcp_symmetric_device_probe(plun) != 0) { 7228 fail = 1; 7229 } 7230 } 7231 7232 } else { 7233 /* bad packet state */ 7234 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7235 7236 /* 7237 * For some special devices (A5K SES and Daktari's SES devices), 7238 * they should be enumerated under mpxio 7239 * or "luxadm dis" will fail 7240 */ 7241 if (ignore_page83_data) { 7242 fail = 0; 7243 } else { 7244 fail = 1; 7245 } 7246 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7247 fcp_trace, FCP_BUF_LEVEL_2, 0, 7248 "!Devid page cmd failed. " 7249 "fpkt_state: %x fpkt_reason: %x", 7250 "ignore_page83: %d", 7251 fpkt->pkt_state, fpkt->pkt_reason, 7252 ignore_page83_data); 7253 } 7254 7255 mutex_enter(&pptr->port_mutex); 7256 mutex_enter(&plun->lun_mutex); 7257 /* 7258 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7259 * mismatch between lun_cip and lun_mpxio. 7260 */ 7261 if (plun->lun_cip == NULL) { 7262 /* 7263 * If we don't have a guid for this lun it's because we were 7264 * unable to glean one from the page 83 response. Set the 7265 * control flag to 0 here to make sure that we don't attempt to 7266 * enumerate it under mpxio. 7267 */ 7268 if (fail || pptr->port_mpxio == 0) { 7269 plun->lun_mpxio = 0; 7270 } else { 7271 plun->lun_mpxio = 1; 7272 } 7273 } 7274 mutex_exit(&plun->lun_mutex); 7275 mutex_exit(&pptr->port_mutex); 7276 7277 mutex_enter(&ptgt->tgt_mutex); 7278 plun->lun_state &= 7279 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7280 mutex_exit(&ptgt->tgt_mutex); 7281 7282 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7283 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7284 7285 fcp_icmd_free(pptr, icmd); 7286 } 7287 7288 /* 7289 * Function: fcp_handle_inquiry 7290 * 7291 * Description: Called by fcp_scsi_callback to handle the response to an 7292 * INQUIRY request. 7293 * 7294 * Argument: *fpkt FC packet used to convey the command. 7295 * *icmd Original fcp_ipkt structure. 7296 * 7297 * Return Value: None 7298 */ 7299 static void 7300 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7301 { 7302 struct fcp_port *pptr; 7303 struct fcp_lun *plun; 7304 struct fcp_tgt *ptgt; 7305 uchar_t dtype; 7306 uchar_t pqual; 7307 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7308 7309 ASSERT(icmd != NULL && fpkt != NULL); 7310 7311 pptr = icmd->ipkt_port; 7312 ptgt = icmd->ipkt_tgt; 7313 plun = icmd->ipkt_lun; 7314 7315 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7316 sizeof (struct scsi_inquiry)); 7317 7318 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7319 pqual = plun->lun_inq.inq_dtype >> 5; 7320 7321 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7322 fcp_trace, FCP_BUF_LEVEL_5, 0, 7323 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7324 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7325 plun->lun_num, dtype, pqual); 7326 7327 if (pqual != 0) { 7328 /* 7329 * Non-zero peripheral qualifier 7330 */ 7331 fcp_log(CE_CONT, pptr->port_dip, 7332 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7333 "Device type=0x%x Peripheral qual=0x%x\n", 7334 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7335 7336 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7337 fcp_trace, FCP_BUF_LEVEL_5, 0, 7338 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7339 "Device type=0x%x Peripheral qual=0x%x\n", 7340 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7341 7342 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7343 7344 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7345 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7346 fcp_icmd_free(pptr, icmd); 7347 return; 7348 } 7349 7350 /* 7351 * If the device is already initialized, check the dtype 7352 * for a change. If it has changed then update the flags 7353 * so the create_luns will offline the old device and 7354 * create the new device. Refer to bug: 4764752 7355 */ 7356 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7357 plun->lun_state |= FCP_LUN_CHANGED; 7358 } 7359 plun->lun_type = plun->lun_inq.inq_dtype; 7360 7361 /* 7362 * This code is setting/initializing the throttling in the FCA 7363 * driver. 7364 */ 7365 mutex_enter(&pptr->port_mutex); 7366 if (!pptr->port_notify) { 7367 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7368 uint32_t cmd = 0; 7369 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7370 ((cmd & 0xFFFFFF00 >> 8) | 7371 FCP_SVE_THROTTLE << 8)); 7372 pptr->port_notify = 1; 7373 mutex_exit(&pptr->port_mutex); 7374 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7375 mutex_enter(&pptr->port_mutex); 7376 } 7377 } 7378 7379 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7380 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7381 fcp_trace, FCP_BUF_LEVEL_2, 0, 7382 "fcp_handle_inquiry,1:state change occured" 7383 " for D_ID=0x%x", ptgt->tgt_d_id); 7384 mutex_exit(&pptr->port_mutex); 7385 7386 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7387 (void) fcp_call_finish_init(pptr, ptgt, 7388 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7389 icmd->ipkt_cause); 7390 fcp_icmd_free(pptr, icmd); 7391 return; 7392 } 7393 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7394 mutex_exit(&pptr->port_mutex); 7395 7396 /* Retrieve the rscn count (if a valid one exists) */ 7397 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7398 rscn_count = ((fc_ulp_rscn_info_t *) 7399 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7400 } else { 7401 rscn_count = FC_INVALID_RSCN_COUNT; 7402 } 7403 7404 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7405 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7406 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7407 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7408 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7409 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7410 (void) fcp_call_finish_init(pptr, ptgt, 7411 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7412 icmd->ipkt_cause); 7413 } 7414 7415 /* 7416 * Read Inquiry VPD Page 0x83 to uniquely 7417 * identify this logical unit. 7418 */ 7419 fcp_icmd_free(pptr, icmd); 7420 } 7421 7422 /* 7423 * Function: fcp_handle_reportlun 7424 * 7425 * Description: Called by fcp_scsi_callback to handle the response to a 7426 * REPORT_LUN request. 7427 * 7428 * Argument: *fpkt FC packet used to convey the command. 7429 * *icmd Original fcp_ipkt structure. 7430 * 7431 * Return Value: None 7432 */ 7433 static void 7434 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7435 { 7436 int i; 7437 int nluns_claimed; 7438 int nluns_bufmax; 7439 int len; 7440 uint16_t lun_num; 7441 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7442 struct fcp_port *pptr; 7443 struct fcp_tgt *ptgt; 7444 struct fcp_lun *plun; 7445 struct fcp_reportlun_resp *report_lun; 7446 7447 pptr = icmd->ipkt_port; 7448 ptgt = icmd->ipkt_tgt; 7449 len = fpkt->pkt_datalen; 7450 7451 if ((len < FCP_LUN_HEADER) || 7452 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7453 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7454 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7455 fcp_icmd_free(pptr, icmd); 7456 return; 7457 } 7458 7459 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7460 fpkt->pkt_datalen); 7461 7462 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7463 fcp_trace, FCP_BUF_LEVEL_5, 0, 7464 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7465 pptr->port_instance, ptgt->tgt_d_id); 7466 7467 /* 7468 * Get the number of luns (which is supplied as LUNS * 8) the 7469 * device claims it has. 7470 */ 7471 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7472 7473 /* 7474 * Get the maximum number of luns the buffer submitted can hold. 7475 */ 7476 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7477 7478 /* 7479 * Due to limitations of certain hardware, we support only 16 bit LUNs 7480 */ 7481 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7482 kmem_free(report_lun, len); 7483 7484 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7485 " 0x%x number of LUNs for target=%x", nluns_claimed, 7486 ptgt->tgt_d_id); 7487 7488 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7489 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7490 fcp_icmd_free(pptr, icmd); 7491 return; 7492 } 7493 7494 /* 7495 * If there are more LUNs than we have allocated memory for, 7496 * allocate more space and send down yet another report lun if 7497 * the maximum number of attempts hasn't been reached. 7498 */ 7499 mutex_enter(&ptgt->tgt_mutex); 7500 7501 if ((nluns_claimed > nluns_bufmax) && 7502 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7503 7504 struct fcp_lun *plun; 7505 7506 ptgt->tgt_report_lun_cnt++; 7507 plun = ptgt->tgt_lun; 7508 ASSERT(plun != NULL); 7509 mutex_exit(&ptgt->tgt_mutex); 7510 7511 kmem_free(report_lun, len); 7512 7513 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7514 fcp_trace, FCP_BUF_LEVEL_5, 0, 7515 "!Dynamically discovered %d LUNs for D_ID=%x", 7516 nluns_claimed, ptgt->tgt_d_id); 7517 7518 /* Retrieve the rscn count (if a valid one exists) */ 7519 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7520 rscn_count = ((fc_ulp_rscn_info_t *) 7521 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7522 ulp_rscn_count; 7523 } else { 7524 rscn_count = FC_INVALID_RSCN_COUNT; 7525 } 7526 7527 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7528 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7529 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7530 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7531 (void) fcp_call_finish_init(pptr, ptgt, 7532 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7533 icmd->ipkt_cause); 7534 } 7535 7536 fcp_icmd_free(pptr, icmd); 7537 return; 7538 } 7539 7540 if (nluns_claimed > nluns_bufmax) { 7541 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7542 fcp_trace, FCP_BUF_LEVEL_5, 0, 7543 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7544 " Number of LUNs lost=%x", 7545 ptgt->tgt_port_wwn.raw_wwn[0], 7546 ptgt->tgt_port_wwn.raw_wwn[1], 7547 ptgt->tgt_port_wwn.raw_wwn[2], 7548 ptgt->tgt_port_wwn.raw_wwn[3], 7549 ptgt->tgt_port_wwn.raw_wwn[4], 7550 ptgt->tgt_port_wwn.raw_wwn[5], 7551 ptgt->tgt_port_wwn.raw_wwn[6], 7552 ptgt->tgt_port_wwn.raw_wwn[7], 7553 nluns_claimed - nluns_bufmax); 7554 7555 nluns_claimed = nluns_bufmax; 7556 } 7557 ptgt->tgt_lun_cnt = nluns_claimed; 7558 7559 /* 7560 * Identify missing LUNs and print warning messages 7561 */ 7562 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7563 int offline; 7564 int exists = 0; 7565 7566 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7567 7568 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7569 uchar_t *lun_string; 7570 7571 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7572 7573 switch (lun_string[0] & 0xC0) { 7574 case FCP_LUN_ADDRESSING: 7575 case FCP_PD_ADDRESSING: 7576 lun_num = ((lun_string[0] & 0x3F) << 8) | 7577 lun_string[1]; 7578 if (plun->lun_num == lun_num) { 7579 exists++; 7580 break; 7581 } 7582 break; 7583 7584 default: 7585 break; 7586 } 7587 } 7588 7589 if (!exists && !offline) { 7590 mutex_exit(&ptgt->tgt_mutex); 7591 7592 mutex_enter(&pptr->port_mutex); 7593 mutex_enter(&ptgt->tgt_mutex); 7594 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7595 /* 7596 * set disappear flag when device was connected 7597 */ 7598 if (!(plun->lun_state & 7599 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7600 plun->lun_state |= FCP_LUN_DISAPPEARED; 7601 } 7602 mutex_exit(&ptgt->tgt_mutex); 7603 mutex_exit(&pptr->port_mutex); 7604 if (!(plun->lun_state & 7605 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7606 fcp_log(CE_NOTE, pptr->port_dip, 7607 "!Lun=%x for target=%x disappeared", 7608 plun->lun_num, ptgt->tgt_d_id); 7609 } 7610 mutex_enter(&ptgt->tgt_mutex); 7611 } else { 7612 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7613 fcp_trace, FCP_BUF_LEVEL_5, 0, 7614 "fcp_handle_reportlun,1: state change" 7615 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7616 mutex_exit(&ptgt->tgt_mutex); 7617 mutex_exit(&pptr->port_mutex); 7618 kmem_free(report_lun, len); 7619 (void) fcp_call_finish_init(pptr, ptgt, 7620 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7621 icmd->ipkt_cause); 7622 fcp_icmd_free(pptr, icmd); 7623 return; 7624 } 7625 } else if (exists) { 7626 /* 7627 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7628 * actually exists in REPORT_LUN response 7629 */ 7630 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7631 plun->lun_state &= 7632 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7633 } 7634 if (offline || plun->lun_num == 0) { 7635 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7636 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7637 mutex_exit(&ptgt->tgt_mutex); 7638 fcp_log(CE_NOTE, pptr->port_dip, 7639 "!Lun=%x for target=%x reappeared", 7640 plun->lun_num, ptgt->tgt_d_id); 7641 mutex_enter(&ptgt->tgt_mutex); 7642 } 7643 } 7644 } 7645 } 7646 7647 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7648 mutex_exit(&ptgt->tgt_mutex); 7649 7650 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7651 fcp_trace, FCP_BUF_LEVEL_5, 0, 7652 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7653 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7654 7655 /* scan each lun */ 7656 for (i = 0; i < nluns_claimed; i++) { 7657 uchar_t *lun_string; 7658 7659 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7660 7661 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7662 fcp_trace, FCP_BUF_LEVEL_5, 0, 7663 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7664 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7665 lun_string[0]); 7666 7667 switch (lun_string[0] & 0xC0) { 7668 case FCP_LUN_ADDRESSING: 7669 case FCP_PD_ADDRESSING: 7670 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7671 7672 /* We will skip masked LUNs because of the blacklist. */ 7673 if (fcp_lun_blacklist != NULL) { 7674 mutex_enter(&ptgt->tgt_mutex); 7675 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7676 lun_num) == TRUE) { 7677 ptgt->tgt_lun_cnt--; 7678 mutex_exit(&ptgt->tgt_mutex); 7679 break; 7680 } 7681 mutex_exit(&ptgt->tgt_mutex); 7682 } 7683 7684 /* see if this LUN is already allocated */ 7685 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7686 plun = fcp_alloc_lun(ptgt); 7687 if (plun == NULL) { 7688 fcp_log(CE_NOTE, pptr->port_dip, 7689 "!Lun allocation failed" 7690 " target=%x lun=%x", 7691 ptgt->tgt_d_id, lun_num); 7692 break; 7693 } 7694 } 7695 7696 mutex_enter(&plun->lun_tgt->tgt_mutex); 7697 /* convert to LUN */ 7698 plun->lun_addr.ent_addr_0 = 7699 BE_16(*(uint16_t *)&(lun_string[0])); 7700 plun->lun_addr.ent_addr_1 = 7701 BE_16(*(uint16_t *)&(lun_string[2])); 7702 plun->lun_addr.ent_addr_2 = 7703 BE_16(*(uint16_t *)&(lun_string[4])); 7704 plun->lun_addr.ent_addr_3 = 7705 BE_16(*(uint16_t *)&(lun_string[6])); 7706 7707 plun->lun_num = lun_num; 7708 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7709 plun->lun_state &= ~FCP_LUN_OFFLINE; 7710 mutex_exit(&plun->lun_tgt->tgt_mutex); 7711 7712 /* Retrieve the rscn count (if a valid one exists) */ 7713 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7714 rscn_count = ((fc_ulp_rscn_info_t *) 7715 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7716 ulp_rscn_count; 7717 } else { 7718 rscn_count = FC_INVALID_RSCN_COUNT; 7719 } 7720 7721 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7722 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7723 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7724 mutex_enter(&pptr->port_mutex); 7725 mutex_enter(&plun->lun_tgt->tgt_mutex); 7726 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7727 fcp_log(CE_NOTE, pptr->port_dip, 7728 "!failed to send INQUIRY" 7729 " target=%x lun=%x", 7730 ptgt->tgt_d_id, plun->lun_num); 7731 } else { 7732 FCP_TRACE(fcp_logq, 7733 pptr->port_instbuf, fcp_trace, 7734 FCP_BUF_LEVEL_5, 0, 7735 "fcp_handle_reportlun,2: state" 7736 " change occured for D_ID=0x%x", 7737 ptgt->tgt_d_id); 7738 } 7739 mutex_exit(&plun->lun_tgt->tgt_mutex); 7740 mutex_exit(&pptr->port_mutex); 7741 } else { 7742 continue; 7743 } 7744 break; 7745 7746 case FCP_VOLUME_ADDRESSING: 7747 /* FALLTHROUGH */ 7748 default: 7749 fcp_log(CE_WARN, NULL, 7750 "!Unsupported LUN Addressing method %x " 7751 "in response to REPORT_LUN", lun_string[0]); 7752 break; 7753 } 7754 7755 /* 7756 * each time through this loop we should decrement 7757 * the tmp_cnt by one -- since we go through this loop 7758 * one time for each LUN, the tmp_cnt should never be <=0 7759 */ 7760 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7761 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7762 } 7763 7764 if (i == 0) { 7765 fcp_log(CE_WARN, pptr->port_dip, 7766 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7767 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7768 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7769 } 7770 7771 kmem_free(report_lun, len); 7772 fcp_icmd_free(pptr, icmd); 7773 } 7774 7775 7776 /* 7777 * called internally to return a LUN given a target and a LUN number 7778 */ 7779 static struct fcp_lun * 7780 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7781 { 7782 struct fcp_lun *plun; 7783 7784 mutex_enter(&ptgt->tgt_mutex); 7785 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7786 if (plun->lun_num == lun_num) { 7787 mutex_exit(&ptgt->tgt_mutex); 7788 return (plun); 7789 } 7790 } 7791 mutex_exit(&ptgt->tgt_mutex); 7792 7793 return (NULL); 7794 } 7795 7796 7797 /* 7798 * handle finishing one target for fcp_finish_init 7799 * 7800 * return true (non-zero) if we want finish_init to continue with the 7801 * next target 7802 * 7803 * called with the port mutex held 7804 */ 7805 /*ARGSUSED*/ 7806 static int 7807 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7808 int link_cnt, int tgt_cnt, int cause) 7809 { 7810 int rval = 1; 7811 ASSERT(pptr != NULL); 7812 ASSERT(ptgt != NULL); 7813 7814 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7815 fcp_trace, FCP_BUF_LEVEL_5, 0, 7816 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7817 ptgt->tgt_state); 7818 7819 ASSERT(mutex_owned(&pptr->port_mutex)); 7820 7821 if ((pptr->port_link_cnt != link_cnt) || 7822 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7823 /* 7824 * oh oh -- another link reset or target change 7825 * must have occurred while we are in here 7826 */ 7827 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7828 7829 return (0); 7830 } else { 7831 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7832 } 7833 7834 mutex_enter(&ptgt->tgt_mutex); 7835 7836 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7837 /* 7838 * tgt is not offline -- is it marked (i.e. needs 7839 * to be offlined) ?? 7840 */ 7841 if (ptgt->tgt_state & FCP_TGT_MARK) { 7842 /* 7843 * this target not offline *and* 7844 * marked 7845 */ 7846 ptgt->tgt_state &= ~FCP_TGT_MARK; 7847 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7848 tgt_cnt, 0, 0); 7849 } else { 7850 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7851 7852 /* create the LUNs */ 7853 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7854 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7855 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7856 cause); 7857 ptgt->tgt_device_created = 1; 7858 } else { 7859 fcp_update_tgt_state(ptgt, FCP_RESET, 7860 FCP_LUN_BUSY); 7861 } 7862 } 7863 } 7864 7865 mutex_exit(&ptgt->tgt_mutex); 7866 7867 return (rval); 7868 } 7869 7870 7871 /* 7872 * this routine is called to finish port initialization 7873 * 7874 * Each port has a "temp" counter -- when a state change happens (e.g. 7875 * port online), the temp count is set to the number of devices in the map. 7876 * Then, as each device gets "discovered", the temp counter is decremented 7877 * by one. When this count reaches zero we know that all of the devices 7878 * in the map have been discovered (or an error has occurred), so we can 7879 * then finish initialization -- which is done by this routine (well, this 7880 * and fcp-finish_tgt()) 7881 * 7882 * acquires and releases the global mutex 7883 * 7884 * called with the port mutex owned 7885 */ 7886 static void 7887 fcp_finish_init(struct fcp_port *pptr) 7888 { 7889 #ifdef DEBUG 7890 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 7891 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 7892 FCP_STACK_DEPTH); 7893 #endif /* DEBUG */ 7894 7895 ASSERT(mutex_owned(&pptr->port_mutex)); 7896 7897 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7898 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 7899 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 7900 7901 if ((pptr->port_state & FCP_STATE_ONLINING) && 7902 !(pptr->port_state & (FCP_STATE_SUSPENDED | 7903 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 7904 pptr->port_state &= ~FCP_STATE_ONLINING; 7905 pptr->port_state |= FCP_STATE_ONLINE; 7906 } 7907 7908 /* Wake up threads waiting on config done */ 7909 cv_broadcast(&pptr->port_config_cv); 7910 } 7911 7912 7913 /* 7914 * called from fcp_finish_init to create the LUNs for a target 7915 * 7916 * called with the port mutex owned 7917 */ 7918 static void 7919 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 7920 { 7921 struct fcp_lun *plun; 7922 struct fcp_port *pptr; 7923 child_info_t *cip = NULL; 7924 7925 ASSERT(ptgt != NULL); 7926 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 7927 7928 pptr = ptgt->tgt_port; 7929 7930 ASSERT(pptr != NULL); 7931 7932 /* scan all LUNs for this target */ 7933 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7934 if (plun->lun_state & FCP_LUN_OFFLINE) { 7935 continue; 7936 } 7937 7938 if (plun->lun_state & FCP_LUN_MARK) { 7939 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7940 fcp_trace, FCP_BUF_LEVEL_2, 0, 7941 "fcp_create_luns: offlining marked LUN!"); 7942 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 7943 continue; 7944 } 7945 7946 plun->lun_state &= ~FCP_LUN_BUSY; 7947 7948 /* 7949 * There are conditions in which FCP_LUN_INIT flag is cleared 7950 * but we have a valid plun->lun_cip. To cover this case also 7951 * CLEAR_BUSY whenever we have a valid lun_cip. 7952 */ 7953 if (plun->lun_mpxio && plun->lun_cip && 7954 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 7955 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 7956 0, 0))) { 7957 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7958 fcp_trace, FCP_BUF_LEVEL_2, 0, 7959 "fcp_create_luns: enable lun %p failed!", 7960 plun); 7961 } 7962 7963 if (plun->lun_state & FCP_LUN_INIT && 7964 !(plun->lun_state & FCP_LUN_CHANGED)) { 7965 continue; 7966 } 7967 7968 if (cause == FCP_CAUSE_USER_CREATE) { 7969 continue; 7970 } 7971 7972 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7973 fcp_trace, FCP_BUF_LEVEL_6, 0, 7974 "create_luns: passing ONLINE elem to HP thread"); 7975 7976 /* 7977 * If lun has changed, prepare for offlining the old path. 7978 * Do not offline the old path right now, since it may be 7979 * still opened. 7980 */ 7981 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 7982 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 7983 } 7984 7985 /* pass an ONLINE element to the hotplug thread */ 7986 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 7987 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 7988 7989 /* 7990 * We can not synchronous attach (i.e pass 7991 * NDI_ONLINE_ATTACH) here as we might be 7992 * coming from an interrupt or callback 7993 * thread. 7994 */ 7995 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 7996 link_cnt, tgt_cnt, 0, 0)) { 7997 fcp_log(CE_CONT, pptr->port_dip, 7998 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 7999 plun->lun_tgt->tgt_d_id, plun->lun_num); 8000 } 8001 } 8002 } 8003 } 8004 8005 8006 /* 8007 * function to online/offline devices 8008 */ 8009 static int 8010 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8011 int online, int lcount, int tcount, int flags) 8012 { 8013 int rval = NDI_FAILURE; 8014 int circ; 8015 child_info_t *ccip; 8016 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8017 int is_mpxio = pptr->port_mpxio; 8018 dev_info_t *cdip, *pdip; 8019 char *devname; 8020 8021 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8022 /* 8023 * When this event gets serviced, lun_cip and lun_mpxio 8024 * has changed, so it should be invalidated now. 8025 */ 8026 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8027 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8028 "plun: %p, cip: %p, what:%d", plun, cip, online); 8029 return (rval); 8030 } 8031 8032 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8033 fcp_trace, FCP_BUF_LEVEL_2, 0, 8034 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8035 "flags=%x mpxio=%x\n", 8036 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8037 plun->lun_mpxio); 8038 8039 /* 8040 * lun_mpxio needs checking here because we can end up in a race 8041 * condition where this task has been dispatched while lun_mpxio is 8042 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8043 * enable MPXIO for the LUN, but was unable to, and hence cleared 8044 * the flag. We rely on the serialization of the tasks here. We return 8045 * NDI_SUCCESS so any callers continue without reporting spurious 8046 * errors, and the still think we're an MPXIO LUN. 8047 */ 8048 8049 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8050 online == FCP_MPXIO_PATH_SET_BUSY) { 8051 if (plun->lun_mpxio) { 8052 rval = fcp_update_mpxio_path(plun, cip, online); 8053 } else { 8054 rval = NDI_SUCCESS; 8055 } 8056 return (rval); 8057 } 8058 8059 /* 8060 * Explicit devfs_clean() due to ndi_devi_offline() not 8061 * executing devfs_clean() if parent lock is held. 8062 */ 8063 ASSERT(!servicing_interrupt()); 8064 if (online == FCP_OFFLINE) { 8065 if (plun->lun_mpxio == 0) { 8066 if (plun->lun_cip == cip) { 8067 cdip = DIP(plun->lun_cip); 8068 } else { 8069 cdip = DIP(cip); 8070 } 8071 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8072 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8073 } else if ((plun->lun_cip != cip) && cip) { 8074 /* 8075 * This means a DTYPE/GUID change, we shall get the 8076 * dip of the old cip instead of the current lun_cip. 8077 */ 8078 cdip = mdi_pi_get_client(PIP(cip)); 8079 } 8080 if (cdip) { 8081 if (i_ddi_devi_attached(cdip)) { 8082 pdip = ddi_get_parent(cdip); 8083 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8084 ndi_devi_enter(pdip, &circ); 8085 (void) ddi_deviname(cdip, devname); 8086 ndi_devi_exit(pdip, circ); 8087 /* 8088 * Release parent lock before calling 8089 * devfs_clean(). 8090 */ 8091 rval = devfs_clean(pdip, devname + 1, 8092 DV_CLEAN_FORCE); 8093 kmem_free(devname, MAXNAMELEN + 1); 8094 /* 8095 * Return if devfs_clean() fails for 8096 * non-MPXIO case. 8097 * For MPXIO case, another path could be 8098 * offlined. 8099 */ 8100 if (rval && plun->lun_mpxio == 0) { 8101 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8102 fcp_trace, FCP_BUF_LEVEL_3, 0, 8103 "fcp_trigger_lun: devfs_clean " 8104 "failed rval=%x dip=%p", 8105 rval, pdip); 8106 return (NDI_FAILURE); 8107 } 8108 } 8109 } 8110 } 8111 8112 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8113 return (NDI_FAILURE); 8114 } 8115 8116 if (is_mpxio) { 8117 mdi_devi_enter(pptr->port_dip, &circ); 8118 } else { 8119 ndi_devi_enter(pptr->port_dip, &circ); 8120 } 8121 8122 mutex_enter(&pptr->port_mutex); 8123 mutex_enter(&plun->lun_mutex); 8124 8125 if (online == FCP_ONLINE) { 8126 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8127 if (ccip == NULL) { 8128 goto fail; 8129 } 8130 } else { 8131 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8132 goto fail; 8133 } 8134 ccip = cip; 8135 } 8136 8137 if (online == FCP_ONLINE) { 8138 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8139 &circ); 8140 fc_ulp_log_device_event(pptr->port_fp_handle, 8141 FC_ULP_DEVICE_ONLINE); 8142 } else { 8143 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8144 &circ); 8145 fc_ulp_log_device_event(pptr->port_fp_handle, 8146 FC_ULP_DEVICE_OFFLINE); 8147 } 8148 8149 fail: mutex_exit(&plun->lun_mutex); 8150 mutex_exit(&pptr->port_mutex); 8151 8152 if (is_mpxio) { 8153 mdi_devi_exit(pptr->port_dip, circ); 8154 } else { 8155 ndi_devi_exit(pptr->port_dip, circ); 8156 } 8157 8158 fc_ulp_idle_port(pptr->port_fp_handle); 8159 8160 return (rval); 8161 } 8162 8163 8164 /* 8165 * take a target offline by taking all of its LUNs offline 8166 */ 8167 /*ARGSUSED*/ 8168 static int 8169 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8170 int link_cnt, int tgt_cnt, int nowait, int flags) 8171 { 8172 struct fcp_tgt_elem *elem; 8173 8174 ASSERT(mutex_owned(&pptr->port_mutex)); 8175 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8176 8177 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8178 8179 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8180 ptgt->tgt_change_cnt)) { 8181 mutex_exit(&ptgt->tgt_mutex); 8182 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8183 mutex_enter(&ptgt->tgt_mutex); 8184 8185 return (0); 8186 } 8187 8188 ptgt->tgt_pd_handle = NULL; 8189 mutex_exit(&ptgt->tgt_mutex); 8190 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8191 mutex_enter(&ptgt->tgt_mutex); 8192 8193 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8194 8195 if (ptgt->tgt_tcap && 8196 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8197 elem->flags = flags; 8198 elem->time = fcp_watchdog_time; 8199 if (nowait == 0) { 8200 elem->time += fcp_offline_delay; 8201 } 8202 elem->ptgt = ptgt; 8203 elem->link_cnt = link_cnt; 8204 elem->tgt_cnt = tgt_cnt; 8205 elem->next = pptr->port_offline_tgts; 8206 pptr->port_offline_tgts = elem; 8207 } else { 8208 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8209 } 8210 8211 return (1); 8212 } 8213 8214 8215 static void 8216 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8217 int link_cnt, int tgt_cnt, int flags) 8218 { 8219 ASSERT(mutex_owned(&pptr->port_mutex)); 8220 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8221 8222 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8223 ptgt->tgt_state = FCP_TGT_OFFLINE; 8224 ptgt->tgt_pd_handle = NULL; 8225 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8226 } 8227 8228 8229 static void 8230 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8231 int flags) 8232 { 8233 struct fcp_lun *plun; 8234 8235 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8236 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8237 8238 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8239 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8240 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8241 } 8242 } 8243 } 8244 8245 8246 /* 8247 * take a LUN offline 8248 * 8249 * enters and leaves with the target mutex held, releasing it in the process 8250 * 8251 * allocates memory in non-sleep mode 8252 */ 8253 static void 8254 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8255 int nowait, int flags) 8256 { 8257 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8258 struct fcp_lun_elem *elem; 8259 8260 ASSERT(plun != NULL); 8261 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8262 8263 if (nowait) { 8264 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8265 return; 8266 } 8267 8268 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8269 elem->flags = flags; 8270 elem->time = fcp_watchdog_time; 8271 if (nowait == 0) { 8272 elem->time += fcp_offline_delay; 8273 } 8274 elem->plun = plun; 8275 elem->link_cnt = link_cnt; 8276 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8277 elem->next = pptr->port_offline_luns; 8278 pptr->port_offline_luns = elem; 8279 } else { 8280 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8281 } 8282 } 8283 8284 8285 static void 8286 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8287 { 8288 struct fcp_pkt *head = NULL; 8289 8290 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8291 8292 mutex_exit(&LUN_TGT->tgt_mutex); 8293 8294 head = fcp_scan_commands(plun); 8295 if (head != NULL) { 8296 fcp_abort_commands(head, LUN_PORT); 8297 } 8298 8299 mutex_enter(&LUN_TGT->tgt_mutex); 8300 8301 if (plun->lun_cip && plun->lun_mpxio) { 8302 /* 8303 * Intimate MPxIO lun busy is cleared 8304 */ 8305 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8306 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8307 0, 0)) { 8308 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8309 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8310 LUN_TGT->tgt_d_id, plun->lun_num); 8311 } 8312 /* 8313 * Intimate MPxIO that the lun is now marked for offline 8314 */ 8315 mutex_exit(&LUN_TGT->tgt_mutex); 8316 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8317 mutex_enter(&LUN_TGT->tgt_mutex); 8318 } 8319 } 8320 8321 static void 8322 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8323 int flags) 8324 { 8325 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8326 8327 mutex_exit(&LUN_TGT->tgt_mutex); 8328 fcp_update_offline_flags(plun); 8329 mutex_enter(&LUN_TGT->tgt_mutex); 8330 8331 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8332 8333 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8334 fcp_trace, FCP_BUF_LEVEL_4, 0, 8335 "offline_lun: passing OFFLINE elem to HP thread"); 8336 8337 if (plun->lun_cip) { 8338 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8339 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8340 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8341 LUN_TGT->tgt_trace); 8342 8343 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8344 link_cnt, tgt_cnt, flags, 0)) { 8345 fcp_log(CE_CONT, LUN_PORT->port_dip, 8346 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8347 LUN_TGT->tgt_d_id, plun->lun_num); 8348 } 8349 } 8350 } 8351 8352 static void 8353 fcp_scan_offline_luns(struct fcp_port *pptr) 8354 { 8355 struct fcp_lun_elem *elem; 8356 struct fcp_lun_elem *prev; 8357 struct fcp_lun_elem *next; 8358 8359 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8360 8361 prev = NULL; 8362 elem = pptr->port_offline_luns; 8363 while (elem) { 8364 next = elem->next; 8365 if (elem->time <= fcp_watchdog_time) { 8366 int changed = 1; 8367 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8368 8369 mutex_enter(&ptgt->tgt_mutex); 8370 if (pptr->port_link_cnt == elem->link_cnt && 8371 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8372 changed = 0; 8373 } 8374 8375 if (!changed && 8376 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8377 fcp_offline_lun_now(elem->plun, 8378 elem->link_cnt, elem->tgt_cnt, elem->flags); 8379 } 8380 mutex_exit(&ptgt->tgt_mutex); 8381 8382 kmem_free(elem, sizeof (*elem)); 8383 8384 if (prev) { 8385 prev->next = next; 8386 } else { 8387 pptr->port_offline_luns = next; 8388 } 8389 } else { 8390 prev = elem; 8391 } 8392 elem = next; 8393 } 8394 } 8395 8396 8397 static void 8398 fcp_scan_offline_tgts(struct fcp_port *pptr) 8399 { 8400 struct fcp_tgt_elem *elem; 8401 struct fcp_tgt_elem *prev; 8402 struct fcp_tgt_elem *next; 8403 8404 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8405 8406 prev = NULL; 8407 elem = pptr->port_offline_tgts; 8408 while (elem) { 8409 next = elem->next; 8410 if (elem->time <= fcp_watchdog_time) { 8411 int changed = 1; 8412 struct fcp_tgt *ptgt = elem->ptgt; 8413 8414 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8415 changed = 0; 8416 } 8417 8418 mutex_enter(&ptgt->tgt_mutex); 8419 if (!changed && !(ptgt->tgt_state & 8420 FCP_TGT_OFFLINE)) { 8421 fcp_offline_target_now(pptr, 8422 ptgt, elem->link_cnt, elem->tgt_cnt, 8423 elem->flags); 8424 } 8425 mutex_exit(&ptgt->tgt_mutex); 8426 8427 kmem_free(elem, sizeof (*elem)); 8428 8429 if (prev) { 8430 prev->next = next; 8431 } else { 8432 pptr->port_offline_tgts = next; 8433 } 8434 } else { 8435 prev = elem; 8436 } 8437 elem = next; 8438 } 8439 } 8440 8441 8442 static void 8443 fcp_update_offline_flags(struct fcp_lun *plun) 8444 { 8445 struct fcp_port *pptr = LUN_PORT; 8446 ASSERT(plun != NULL); 8447 8448 mutex_enter(&LUN_TGT->tgt_mutex); 8449 plun->lun_state |= FCP_LUN_OFFLINE; 8450 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8451 8452 mutex_enter(&plun->lun_mutex); 8453 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8454 dev_info_t *cdip = NULL; 8455 8456 mutex_exit(&LUN_TGT->tgt_mutex); 8457 8458 if (plun->lun_mpxio == 0) { 8459 cdip = DIP(plun->lun_cip); 8460 } else if (plun->lun_cip) { 8461 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8462 } 8463 8464 mutex_exit(&plun->lun_mutex); 8465 if (cdip) { 8466 (void) ndi_event_retrieve_cookie( 8467 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8468 &fcp_remove_eid, NDI_EVENT_NOPASS); 8469 (void) ndi_event_run_callbacks( 8470 pptr->port_ndi_event_hdl, cdip, 8471 fcp_remove_eid, NULL); 8472 } 8473 } else { 8474 mutex_exit(&plun->lun_mutex); 8475 mutex_exit(&LUN_TGT->tgt_mutex); 8476 } 8477 } 8478 8479 8480 /* 8481 * Scan all of the command pkts for this port, moving pkts that 8482 * match our LUN onto our own list (headed by "head") 8483 */ 8484 static struct fcp_pkt * 8485 fcp_scan_commands(struct fcp_lun *plun) 8486 { 8487 struct fcp_port *pptr = LUN_PORT; 8488 8489 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8490 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8491 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8492 8493 struct fcp_pkt *head = NULL; /* head of our list */ 8494 struct fcp_pkt *tail = NULL; /* tail of our list */ 8495 8496 int cmds_found = 0; 8497 8498 mutex_enter(&pptr->port_pkt_mutex); 8499 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8500 struct fcp_lun *tlun = 8501 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8502 8503 ncmd = cmd->cmd_next; /* set next command */ 8504 8505 /* 8506 * if this pkt is for a different LUN or the 8507 * command is sent down, skip it. 8508 */ 8509 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8510 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8511 pcmd = cmd; 8512 continue; 8513 } 8514 cmds_found++; 8515 if (pcmd != NULL) { 8516 ASSERT(pptr->port_pkt_head != cmd); 8517 pcmd->cmd_next = cmd->cmd_next; 8518 } else { 8519 ASSERT(cmd == pptr->port_pkt_head); 8520 pptr->port_pkt_head = cmd->cmd_next; 8521 } 8522 8523 if (cmd == pptr->port_pkt_tail) { 8524 pptr->port_pkt_tail = pcmd; 8525 if (pcmd) { 8526 pcmd->cmd_next = NULL; 8527 } 8528 } 8529 8530 if (head == NULL) { 8531 head = tail = cmd; 8532 } else { 8533 ASSERT(tail != NULL); 8534 8535 tail->cmd_next = cmd; 8536 tail = cmd; 8537 } 8538 cmd->cmd_next = NULL; 8539 } 8540 mutex_exit(&pptr->port_pkt_mutex); 8541 8542 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8543 fcp_trace, FCP_BUF_LEVEL_8, 0, 8544 "scan commands: %d cmd(s) found", cmds_found); 8545 8546 return (head); 8547 } 8548 8549 8550 /* 8551 * Abort all the commands in the command queue 8552 */ 8553 static void 8554 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8555 { 8556 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8557 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8558 8559 ASSERT(mutex_owned(&pptr->port_mutex)); 8560 8561 /* scan through the pkts and invalid them */ 8562 for (cmd = head; cmd != NULL; cmd = ncmd) { 8563 struct scsi_pkt *pkt = cmd->cmd_pkt; 8564 8565 ncmd = cmd->cmd_next; 8566 ASSERT(pkt != NULL); 8567 8568 /* 8569 * The lun is going to be marked offline. Indicate 8570 * the target driver not to requeue or retry this command 8571 * as the device is going to be offlined pretty soon. 8572 */ 8573 pkt->pkt_reason = CMD_DEV_GONE; 8574 pkt->pkt_statistics = 0; 8575 pkt->pkt_state = 0; 8576 8577 /* reset cmd flags/state */ 8578 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8579 cmd->cmd_state = FCP_PKT_IDLE; 8580 8581 /* 8582 * ensure we have a packet completion routine, 8583 * then call it. 8584 */ 8585 ASSERT(pkt->pkt_comp != NULL); 8586 8587 mutex_exit(&pptr->port_mutex); 8588 fcp_post_callback(cmd); 8589 mutex_enter(&pptr->port_mutex); 8590 } 8591 } 8592 8593 8594 /* 8595 * the pkt_comp callback for command packets 8596 */ 8597 static void 8598 fcp_cmd_callback(fc_packet_t *fpkt) 8599 { 8600 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8601 struct scsi_pkt *pkt = cmd->cmd_pkt; 8602 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8603 8604 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8605 8606 if (cmd->cmd_state == FCP_PKT_IDLE) { 8607 cmn_err(CE_PANIC, "Packet already completed %p", 8608 (void *)cmd); 8609 } 8610 8611 /* 8612 * Watch thread should be freeing the packet, ignore the pkt. 8613 */ 8614 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8615 fcp_log(CE_CONT, pptr->port_dip, 8616 "!FCP: Pkt completed while aborting\n"); 8617 return; 8618 } 8619 cmd->cmd_state = FCP_PKT_IDLE; 8620 8621 fcp_complete_pkt(fpkt); 8622 8623 #ifdef DEBUG 8624 mutex_enter(&pptr->port_pkt_mutex); 8625 pptr->port_npkts--; 8626 mutex_exit(&pptr->port_pkt_mutex); 8627 #endif /* DEBUG */ 8628 8629 fcp_post_callback(cmd); 8630 } 8631 8632 8633 static void 8634 fcp_complete_pkt(fc_packet_t *fpkt) 8635 { 8636 int error = 0; 8637 struct fcp_pkt *cmd = (struct fcp_pkt *) 8638 fpkt->pkt_ulp_private; 8639 struct scsi_pkt *pkt = cmd->cmd_pkt; 8640 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8641 struct fcp_lun *plun; 8642 struct fcp_tgt *ptgt; 8643 struct fcp_rsp *rsp; 8644 struct scsi_address save; 8645 8646 #ifdef DEBUG 8647 save = pkt->pkt_address; 8648 #endif /* DEBUG */ 8649 8650 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8651 8652 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8653 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8654 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8655 sizeof (struct fcp_rsp)); 8656 } 8657 8658 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8659 STATE_SENT_CMD | STATE_GOT_STATUS; 8660 8661 pkt->pkt_resid = 0; 8662 8663 if (cmd->cmd_pkt->pkt_numcookies) { 8664 pkt->pkt_state |= STATE_XFERRED_DATA; 8665 if (fpkt->pkt_data_resid) { 8666 error++; 8667 } 8668 } 8669 8670 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8671 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8672 /* 8673 * The next two checks make sure that if there 8674 * is no sense data or a valid response and 8675 * the command came back with check condition, 8676 * the command should be retried. 8677 */ 8678 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8679 !rsp->fcp_u.fcp_status.sense_len_set) { 8680 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8681 pkt->pkt_resid = cmd->cmd_dmacount; 8682 } 8683 } 8684 8685 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8686 return; 8687 } 8688 8689 plun = ADDR2LUN(&pkt->pkt_address); 8690 ptgt = plun->lun_tgt; 8691 ASSERT(ptgt != NULL); 8692 8693 /* 8694 * Update the transfer resid, if appropriate 8695 */ 8696 if (rsp->fcp_u.fcp_status.resid_over || 8697 rsp->fcp_u.fcp_status.resid_under) { 8698 pkt->pkt_resid = rsp->fcp_resid; 8699 } 8700 8701 /* 8702 * First see if we got a FCP protocol error. 8703 */ 8704 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8705 struct fcp_rsp_info *bep; 8706 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8707 sizeof (struct fcp_rsp)); 8708 8709 if (fcp_validate_fcp_response(rsp, pptr) != 8710 FC_SUCCESS) { 8711 pkt->pkt_reason = CMD_CMPLT; 8712 *(pkt->pkt_scbp) = STATUS_CHECK; 8713 8714 fcp_log(CE_WARN, pptr->port_dip, 8715 "!SCSI command to d_id=0x%x lun=0x%x" 8716 " failed, Bad FCP response values:" 8717 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8718 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8719 ptgt->tgt_d_id, plun->lun_num, 8720 rsp->reserved_0, rsp->reserved_1, 8721 rsp->fcp_u.fcp_status.reserved_0, 8722 rsp->fcp_u.fcp_status.reserved_1, 8723 rsp->fcp_response_len, rsp->fcp_sense_len); 8724 8725 return; 8726 } 8727 8728 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8729 FCP_CP_IN(fpkt->pkt_resp + 8730 sizeof (struct fcp_rsp), bep, 8731 fpkt->pkt_resp_acc, 8732 sizeof (struct fcp_rsp_info)); 8733 } 8734 8735 if (bep->rsp_code != FCP_NO_FAILURE) { 8736 child_info_t *cip; 8737 8738 pkt->pkt_reason = CMD_TRAN_ERR; 8739 8740 mutex_enter(&plun->lun_mutex); 8741 cip = plun->lun_cip; 8742 mutex_exit(&plun->lun_mutex); 8743 8744 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8745 fcp_trace, FCP_BUF_LEVEL_2, 0, 8746 "FCP response error on cmd=%p" 8747 " target=0x%x, cip=%p", cmd, 8748 ptgt->tgt_d_id, cip); 8749 } 8750 } 8751 8752 /* 8753 * See if we got a SCSI error with sense data 8754 */ 8755 if (rsp->fcp_u.fcp_status.sense_len_set) { 8756 uchar_t rqlen; 8757 caddr_t sense_from; 8758 child_info_t *cip; 8759 timeout_id_t tid; 8760 struct scsi_arq_status *arq; 8761 struct scsi_extended_sense *sense_to; 8762 8763 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8764 sense_to = &arq->sts_sensedata; 8765 8766 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8767 sizeof (struct scsi_extended_sense)); 8768 8769 sense_from = (caddr_t)fpkt->pkt_resp + 8770 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8771 8772 if (fcp_validate_fcp_response(rsp, pptr) != 8773 FC_SUCCESS) { 8774 pkt->pkt_reason = CMD_CMPLT; 8775 *(pkt->pkt_scbp) = STATUS_CHECK; 8776 8777 fcp_log(CE_WARN, pptr->port_dip, 8778 "!SCSI command to d_id=0x%x lun=0x%x" 8779 " failed, Bad FCP response values:" 8780 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8781 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8782 ptgt->tgt_d_id, plun->lun_num, 8783 rsp->reserved_0, rsp->reserved_1, 8784 rsp->fcp_u.fcp_status.reserved_0, 8785 rsp->fcp_u.fcp_status.reserved_1, 8786 rsp->fcp_response_len, rsp->fcp_sense_len); 8787 8788 return; 8789 } 8790 8791 /* 8792 * copy in sense information 8793 */ 8794 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8795 FCP_CP_IN(sense_from, sense_to, 8796 fpkt->pkt_resp_acc, rqlen); 8797 } else { 8798 bcopy(sense_from, sense_to, rqlen); 8799 } 8800 8801 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8802 (FCP_SENSE_NO_LUN(sense_to))) { 8803 mutex_enter(&ptgt->tgt_mutex); 8804 if (ptgt->tgt_tid == NULL) { 8805 /* 8806 * Kick off rediscovery 8807 */ 8808 tid = timeout(fcp_reconfigure_luns, 8809 (caddr_t)ptgt, drv_usectohz(1)); 8810 8811 ptgt->tgt_tid = tid; 8812 ptgt->tgt_state |= FCP_TGT_BUSY; 8813 } 8814 mutex_exit(&ptgt->tgt_mutex); 8815 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8816 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8817 fcp_trace, FCP_BUF_LEVEL_3, 0, 8818 "!FCP: Report Lun Has Changed" 8819 " target=%x", ptgt->tgt_d_id); 8820 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8821 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8822 fcp_trace, FCP_BUF_LEVEL_3, 0, 8823 "!FCP: LU Not Supported" 8824 " target=%x", ptgt->tgt_d_id); 8825 } 8826 } 8827 ASSERT(pkt->pkt_scbp != NULL); 8828 8829 pkt->pkt_state |= STATE_ARQ_DONE; 8830 8831 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8832 8833 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8834 arq->sts_rqpkt_reason = 0; 8835 arq->sts_rqpkt_statistics = 0; 8836 8837 arq->sts_rqpkt_state = STATE_GOT_BUS | 8838 STATE_GOT_TARGET | STATE_SENT_CMD | 8839 STATE_GOT_STATUS | STATE_ARQ_DONE | 8840 STATE_XFERRED_DATA; 8841 8842 mutex_enter(&plun->lun_mutex); 8843 cip = plun->lun_cip; 8844 mutex_exit(&plun->lun_mutex); 8845 8846 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8847 fcp_trace, FCP_BUF_LEVEL_8, 0, 8848 "SCSI Check condition on cmd=%p target=0x%x" 8849 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 8850 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 8851 cmd->cmd_fcp_cmd.fcp_cdb[0], 8852 rsp->fcp_u.fcp_status.scsi_status, 8853 sense_to->es_key, sense_to->es_add_code, 8854 sense_to->es_qual_code); 8855 } 8856 } else { 8857 plun = ADDR2LUN(&pkt->pkt_address); 8858 ptgt = plun->lun_tgt; 8859 ASSERT(ptgt != NULL); 8860 8861 /* 8862 * Work harder to translate errors into target driver 8863 * understandable ones. Note with despair that the target 8864 * drivers don't decode pkt_state and pkt_reason exhaustively 8865 * They resort to using the big hammer most often, which 8866 * may not get fixed in the life time of this driver. 8867 */ 8868 pkt->pkt_state = 0; 8869 pkt->pkt_statistics = 0; 8870 8871 switch (fpkt->pkt_state) { 8872 case FC_PKT_TRAN_ERROR: 8873 switch (fpkt->pkt_reason) { 8874 case FC_REASON_OVERRUN: 8875 pkt->pkt_reason = CMD_CMD_OVR; 8876 pkt->pkt_statistics |= STAT_ABORTED; 8877 break; 8878 8879 case FC_REASON_XCHG_BSY: { 8880 caddr_t ptr; 8881 8882 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8883 8884 ptr = (caddr_t)pkt->pkt_scbp; 8885 if (ptr) { 8886 *ptr = STATUS_BUSY; 8887 } 8888 break; 8889 } 8890 8891 case FC_REASON_ABORTED: 8892 pkt->pkt_reason = CMD_TRAN_ERR; 8893 pkt->pkt_statistics |= STAT_ABORTED; 8894 break; 8895 8896 case FC_REASON_ABORT_FAILED: 8897 pkt->pkt_reason = CMD_ABORT_FAIL; 8898 break; 8899 8900 case FC_REASON_NO_SEQ_INIT: 8901 case FC_REASON_CRC_ERROR: 8902 pkt->pkt_reason = CMD_TRAN_ERR; 8903 pkt->pkt_statistics |= STAT_ABORTED; 8904 break; 8905 default: 8906 pkt->pkt_reason = CMD_TRAN_ERR; 8907 break; 8908 } 8909 break; 8910 8911 case FC_PKT_PORT_OFFLINE: { 8912 dev_info_t *cdip = NULL; 8913 caddr_t ptr; 8914 8915 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 8916 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8917 fcp_trace, FCP_BUF_LEVEL_8, 0, 8918 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 8919 ptgt->tgt_d_id); 8920 } 8921 8922 mutex_enter(&plun->lun_mutex); 8923 if (plun->lun_mpxio == 0) { 8924 cdip = DIP(plun->lun_cip); 8925 } else if (plun->lun_cip) { 8926 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8927 } 8928 8929 mutex_exit(&plun->lun_mutex); 8930 8931 if (cdip) { 8932 (void) ndi_event_retrieve_cookie( 8933 pptr->port_ndi_event_hdl, cdip, 8934 FCAL_REMOVE_EVENT, &fcp_remove_eid, 8935 NDI_EVENT_NOPASS); 8936 (void) ndi_event_run_callbacks( 8937 pptr->port_ndi_event_hdl, cdip, 8938 fcp_remove_eid, NULL); 8939 } 8940 8941 /* 8942 * If the link goes off-line for a lip, 8943 * this will cause a error to the ST SG 8944 * SGEN drivers. By setting BUSY we will 8945 * give the drivers the chance to retry 8946 * before it blows of the job. ST will 8947 * remember how many times it has retried. 8948 */ 8949 8950 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 8951 (plun->lun_type == DTYPE_CHANGER)) { 8952 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 8953 ptr = (caddr_t)pkt->pkt_scbp; 8954 if (ptr) { 8955 *ptr = STATUS_BUSY; 8956 } 8957 } else { 8958 pkt->pkt_reason = CMD_TRAN_ERR; 8959 pkt->pkt_statistics |= STAT_BUS_RESET; 8960 } 8961 break; 8962 } 8963 8964 case FC_PKT_TRAN_BSY: 8965 /* 8966 * Use the ssd Qfull handling here. 8967 */ 8968 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 8969 pkt->pkt_state = STATE_GOT_BUS; 8970 break; 8971 8972 case FC_PKT_TIMEOUT: 8973 pkt->pkt_reason = CMD_TIMEOUT; 8974 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 8975 pkt->pkt_statistics |= STAT_TIMEOUT; 8976 } else { 8977 pkt->pkt_statistics |= STAT_ABORTED; 8978 } 8979 break; 8980 8981 case FC_PKT_LOCAL_RJT: 8982 switch (fpkt->pkt_reason) { 8983 case FC_REASON_OFFLINE: { 8984 dev_info_t *cdip = NULL; 8985 8986 mutex_enter(&plun->lun_mutex); 8987 if (plun->lun_mpxio == 0) { 8988 cdip = DIP(plun->lun_cip); 8989 } else if (plun->lun_cip) { 8990 cdip = mdi_pi_get_client( 8991 PIP(plun->lun_cip)); 8992 } 8993 mutex_exit(&plun->lun_mutex); 8994 8995 if (cdip) { 8996 (void) ndi_event_retrieve_cookie( 8997 pptr->port_ndi_event_hdl, cdip, 8998 FCAL_REMOVE_EVENT, 8999 &fcp_remove_eid, 9000 NDI_EVENT_NOPASS); 9001 (void) ndi_event_run_callbacks( 9002 pptr->port_ndi_event_hdl, 9003 cdip, fcp_remove_eid, NULL); 9004 } 9005 9006 pkt->pkt_reason = CMD_TRAN_ERR; 9007 pkt->pkt_statistics |= STAT_BUS_RESET; 9008 9009 break; 9010 } 9011 9012 case FC_REASON_NOMEM: 9013 case FC_REASON_QFULL: { 9014 caddr_t ptr; 9015 9016 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9017 ptr = (caddr_t)pkt->pkt_scbp; 9018 if (ptr) { 9019 *ptr = STATUS_BUSY; 9020 } 9021 break; 9022 } 9023 9024 case FC_REASON_DMA_ERROR: 9025 pkt->pkt_reason = CMD_DMA_DERR; 9026 pkt->pkt_statistics |= STAT_ABORTED; 9027 break; 9028 9029 case FC_REASON_CRC_ERROR: 9030 case FC_REASON_UNDERRUN: { 9031 uchar_t status; 9032 /* 9033 * Work around for Bugid: 4240945. 9034 * IB on A5k doesn't set the Underrun bit 9035 * in the fcp status, when it is transferring 9036 * less than requested amount of data. Work 9037 * around the ses problem to keep luxadm 9038 * happy till ibfirmware is fixed. 9039 */ 9040 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9041 FCP_CP_IN(fpkt->pkt_resp, rsp, 9042 fpkt->pkt_resp_acc, 9043 sizeof (struct fcp_rsp)); 9044 } 9045 status = rsp->fcp_u.fcp_status.scsi_status; 9046 if (((plun->lun_type & DTYPE_MASK) == 9047 DTYPE_ESI) && (status == STATUS_GOOD)) { 9048 pkt->pkt_reason = CMD_CMPLT; 9049 *pkt->pkt_scbp = status; 9050 pkt->pkt_resid = 0; 9051 } else { 9052 pkt->pkt_reason = CMD_TRAN_ERR; 9053 pkt->pkt_statistics |= STAT_ABORTED; 9054 } 9055 break; 9056 } 9057 9058 case FC_REASON_NO_CONNECTION: 9059 case FC_REASON_UNSUPPORTED: 9060 case FC_REASON_ILLEGAL_REQ: 9061 case FC_REASON_BAD_SID: 9062 case FC_REASON_DIAG_BUSY: 9063 case FC_REASON_FCAL_OPN_FAIL: 9064 case FC_REASON_BAD_XID: 9065 default: 9066 pkt->pkt_reason = CMD_TRAN_ERR; 9067 pkt->pkt_statistics |= STAT_ABORTED; 9068 break; 9069 9070 } 9071 break; 9072 9073 case FC_PKT_NPORT_RJT: 9074 case FC_PKT_FABRIC_RJT: 9075 case FC_PKT_NPORT_BSY: 9076 case FC_PKT_FABRIC_BSY: 9077 default: 9078 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9079 fcp_trace, FCP_BUF_LEVEL_8, 0, 9080 "FC Status 0x%x, reason 0x%x", 9081 fpkt->pkt_state, fpkt->pkt_reason); 9082 pkt->pkt_reason = CMD_TRAN_ERR; 9083 pkt->pkt_statistics |= STAT_ABORTED; 9084 break; 9085 } 9086 9087 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9088 fcp_trace, FCP_BUF_LEVEL_9, 0, 9089 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9090 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9091 fpkt->pkt_reason); 9092 } 9093 9094 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9095 } 9096 9097 9098 static int 9099 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9100 { 9101 if (rsp->reserved_0 || rsp->reserved_1 || 9102 rsp->fcp_u.fcp_status.reserved_0 || 9103 rsp->fcp_u.fcp_status.reserved_1) { 9104 /* 9105 * These reserved fields should ideally be zero. FCP-2 does say 9106 * that the recipient need not check for reserved fields to be 9107 * zero. If they are not zero, we will not make a fuss about it 9108 * - just log it (in debug to both trace buffer and messages 9109 * file and to trace buffer only in non-debug) and move on. 9110 * 9111 * Non-zero reserved fields were seen with minnows. 9112 * 9113 * qlc takes care of some of this but we cannot assume that all 9114 * FCAs will do so. 9115 */ 9116 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9117 FCP_BUF_LEVEL_5, 0, 9118 "Got fcp response packet with non-zero reserved fields " 9119 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9120 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9121 rsp->reserved_0, rsp->reserved_1, 9122 rsp->fcp_u.fcp_status.reserved_0, 9123 rsp->fcp_u.fcp_status.reserved_1); 9124 } 9125 9126 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9127 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9128 return (FC_FAILURE); 9129 } 9130 9131 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9132 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9133 sizeof (struct fcp_rsp))) { 9134 return (FC_FAILURE); 9135 } 9136 9137 return (FC_SUCCESS); 9138 } 9139 9140 9141 /* 9142 * This is called when there is a change the in device state. The case we're 9143 * handling here is, if the d_id s does not match, offline this tgt and online 9144 * a new tgt with the new d_id. called from fcp_handle_devices with 9145 * port_mutex held. 9146 */ 9147 static int 9148 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9149 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9150 { 9151 ASSERT(mutex_owned(&pptr->port_mutex)); 9152 9153 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9154 fcp_trace, FCP_BUF_LEVEL_3, 0, 9155 "Starting fcp_device_changed..."); 9156 9157 /* 9158 * The two cases where the port_device_changed is called is 9159 * either it changes it's d_id or it's hard address. 9160 */ 9161 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9162 (FC_TOP_EXTERNAL(pptr->port_topology) && 9163 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9164 9165 /* offline this target */ 9166 mutex_enter(&ptgt->tgt_mutex); 9167 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9168 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9169 0, 1, NDI_DEVI_REMOVE); 9170 } 9171 mutex_exit(&ptgt->tgt_mutex); 9172 9173 fcp_log(CE_NOTE, pptr->port_dip, 9174 "Change in target properties: Old D_ID=%x New D_ID=%x" 9175 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9176 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9177 map_entry->map_hard_addr.hard_addr); 9178 } 9179 9180 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9181 link_cnt, tgt_cnt, cause)); 9182 } 9183 9184 /* 9185 * Function: fcp_alloc_lun 9186 * 9187 * Description: Creates a new lun structure and adds it to the list 9188 * of luns of the target. 9189 * 9190 * Argument: ptgt Target the lun will belong to. 9191 * 9192 * Return Value: NULL Failed 9193 * Not NULL Succeeded 9194 * 9195 * Context: Kernel context 9196 */ 9197 static struct fcp_lun * 9198 fcp_alloc_lun(struct fcp_tgt *ptgt) 9199 { 9200 struct fcp_lun *plun; 9201 9202 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9203 if (plun != NULL) { 9204 /* 9205 * Initialize the mutex before putting in the target list 9206 * especially before releasing the target mutex. 9207 */ 9208 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9209 plun->lun_tgt = ptgt; 9210 9211 mutex_enter(&ptgt->tgt_mutex); 9212 plun->lun_next = ptgt->tgt_lun; 9213 ptgt->tgt_lun = plun; 9214 plun->lun_old_guid = NULL; 9215 plun->lun_old_guid_size = 0; 9216 mutex_exit(&ptgt->tgt_mutex); 9217 } 9218 9219 return (plun); 9220 } 9221 9222 /* 9223 * Function: fcp_dealloc_lun 9224 * 9225 * Description: Frees the LUN structure passed by the caller. 9226 * 9227 * Argument: plun LUN structure to free. 9228 * 9229 * Return Value: None 9230 * 9231 * Context: Kernel context. 9232 */ 9233 static void 9234 fcp_dealloc_lun(struct fcp_lun *plun) 9235 { 9236 mutex_enter(&plun->lun_mutex); 9237 if (plun->lun_cip) { 9238 fcp_remove_child(plun); 9239 } 9240 mutex_exit(&plun->lun_mutex); 9241 9242 mutex_destroy(&plun->lun_mutex); 9243 if (plun->lun_guid) { 9244 kmem_free(plun->lun_guid, plun->lun_guid_size); 9245 } 9246 if (plun->lun_old_guid) { 9247 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9248 } 9249 kmem_free(plun, sizeof (*plun)); 9250 } 9251 9252 /* 9253 * Function: fcp_alloc_tgt 9254 * 9255 * Description: Creates a new target structure and adds it to the port 9256 * hash list. 9257 * 9258 * Argument: pptr fcp port structure 9259 * *map_entry entry describing the target to create 9260 * link_cnt Link state change counter 9261 * 9262 * Return Value: NULL Failed 9263 * Not NULL Succeeded 9264 * 9265 * Context: Kernel context. 9266 */ 9267 static struct fcp_tgt * 9268 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9269 { 9270 int hash; 9271 uchar_t *wwn; 9272 struct fcp_tgt *ptgt; 9273 9274 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9275 if (ptgt != NULL) { 9276 mutex_enter(&pptr->port_mutex); 9277 if (link_cnt != pptr->port_link_cnt) { 9278 /* 9279 * oh oh -- another link reset 9280 * in progress -- give up 9281 */ 9282 mutex_exit(&pptr->port_mutex); 9283 kmem_free(ptgt, sizeof (*ptgt)); 9284 ptgt = NULL; 9285 } else { 9286 /* 9287 * initialize the mutex before putting in the port 9288 * wwn list, especially before releasing the port 9289 * mutex. 9290 */ 9291 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9292 9293 /* add new target entry to the port's hash list */ 9294 wwn = (uchar_t *)&map_entry->map_pwwn; 9295 hash = FCP_HASH(wwn); 9296 9297 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9298 pptr->port_tgt_hash_table[hash] = ptgt; 9299 9300 /* save cross-ptr */ 9301 ptgt->tgt_port = pptr; 9302 9303 ptgt->tgt_change_cnt = 1; 9304 9305 /* initialize the target manual_config_only flag */ 9306 if (fcp_enable_auto_configuration) { 9307 ptgt->tgt_manual_config_only = 0; 9308 } else { 9309 ptgt->tgt_manual_config_only = 1; 9310 } 9311 9312 mutex_exit(&pptr->port_mutex); 9313 } 9314 } 9315 9316 return (ptgt); 9317 } 9318 9319 /* 9320 * Function: fcp_dealloc_tgt 9321 * 9322 * Description: Frees the target structure passed by the caller. 9323 * 9324 * Argument: ptgt Target structure to free. 9325 * 9326 * Return Value: None 9327 * 9328 * Context: Kernel context. 9329 */ 9330 static void 9331 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9332 { 9333 mutex_destroy(&ptgt->tgt_mutex); 9334 kmem_free(ptgt, sizeof (*ptgt)); 9335 } 9336 9337 9338 /* 9339 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9340 * 9341 * Device discovery commands will not be retried for-ever as 9342 * this will have repercussions on other devices that need to 9343 * be submitted to the hotplug thread. After a quick glance 9344 * at the SCSI-3 spec, it was found that the spec doesn't 9345 * mandate a forever retry, rather recommends a delayed retry. 9346 * 9347 * Since Photon IB is single threaded, STATUS_BUSY is common 9348 * in a 4+initiator environment. Make sure the total time 9349 * spent on retries (including command timeout) does not 9350 * 60 seconds 9351 */ 9352 static void 9353 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9354 { 9355 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9356 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9357 9358 mutex_enter(&pptr->port_mutex); 9359 mutex_enter(&ptgt->tgt_mutex); 9360 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9361 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9362 fcp_trace, FCP_BUF_LEVEL_2, 0, 9363 "fcp_queue_ipkt,1:state change occured" 9364 " for D_ID=0x%x", ptgt->tgt_d_id); 9365 mutex_exit(&ptgt->tgt_mutex); 9366 mutex_exit(&pptr->port_mutex); 9367 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9368 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9369 fcp_icmd_free(pptr, icmd); 9370 return; 9371 } 9372 mutex_exit(&ptgt->tgt_mutex); 9373 9374 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9375 9376 if (pptr->port_ipkt_list != NULL) { 9377 /* add pkt to front of doubly-linked list */ 9378 pptr->port_ipkt_list->ipkt_prev = icmd; 9379 icmd->ipkt_next = pptr->port_ipkt_list; 9380 pptr->port_ipkt_list = icmd; 9381 icmd->ipkt_prev = NULL; 9382 } else { 9383 /* this is the first/only pkt on the list */ 9384 pptr->port_ipkt_list = icmd; 9385 icmd->ipkt_next = NULL; 9386 icmd->ipkt_prev = NULL; 9387 } 9388 mutex_exit(&pptr->port_mutex); 9389 } 9390 9391 /* 9392 * Function: fcp_transport 9393 * 9394 * Description: This function submits the Fibre Channel packet to the transort 9395 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9396 * fails the submission, the treatment depends on the value of 9397 * the variable internal. 9398 * 9399 * Argument: port_handle fp/fctl port handle. 9400 * *fpkt Packet to submit to the transport layer. 9401 * internal Not zero when it's an internal packet. 9402 * 9403 * Return Value: FC_TRAN_BUSY 9404 * FC_STATEC_BUSY 9405 * FC_OFFLINE 9406 * FC_LOGINREQ 9407 * FC_DEVICE_BUSY 9408 * FC_SUCCESS 9409 */ 9410 static int 9411 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9412 { 9413 int rval; 9414 9415 rval = fc_ulp_transport(port_handle, fpkt); 9416 if (rval == FC_SUCCESS) { 9417 return (rval); 9418 } 9419 9420 /* 9421 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9422 * a command, if the underlying modules see that there is a state 9423 * change, or if a port is OFFLINE, that means, that state change 9424 * hasn't reached FCP yet, so re-queue the command for deferred 9425 * submission. 9426 */ 9427 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9428 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9429 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9430 /* 9431 * Defer packet re-submission. Life hang is possible on 9432 * internal commands if the port driver sends FC_STATEC_BUSY 9433 * for ever, but that shouldn't happen in a good environment. 9434 * Limiting re-transport for internal commands is probably a 9435 * good idea.. 9436 * A race condition can happen when a port sees barrage of 9437 * link transitions offline to online. If the FCTL has 9438 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9439 * internal commands should be queued to do the discovery. 9440 * The race condition is when an online comes and FCP starts 9441 * its internal discovery and the link goes offline. It is 9442 * possible that the statec_callback has not reached FCP 9443 * and FCP is carrying on with its internal discovery. 9444 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9445 * that the link has gone offline. At this point FCP should 9446 * drop all the internal commands and wait for the 9447 * statec_callback. It will be facilitated by incrementing 9448 * port_link_cnt. 9449 * 9450 * For external commands, the (FC)pkt_timeout is decremented 9451 * by the QUEUE Delay added by our driver, Care is taken to 9452 * ensure that it doesn't become zero (zero means no timeout) 9453 * If the time expires right inside driver queue itself, 9454 * the watch thread will return it to the original caller 9455 * indicating that the command has timed-out. 9456 */ 9457 if (internal) { 9458 char *op; 9459 struct fcp_ipkt *icmd; 9460 9461 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9462 switch (icmd->ipkt_opcode) { 9463 case SCMD_REPORT_LUN: 9464 op = "REPORT LUN"; 9465 break; 9466 9467 case SCMD_INQUIRY: 9468 op = "INQUIRY"; 9469 break; 9470 9471 case SCMD_INQUIRY_PAGE83: 9472 op = "INQUIRY-83"; 9473 break; 9474 9475 default: 9476 op = "Internal SCSI COMMAND"; 9477 break; 9478 } 9479 9480 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9481 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9482 rval = FC_SUCCESS; 9483 } 9484 } else { 9485 struct fcp_pkt *cmd; 9486 struct fcp_port *pptr; 9487 9488 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9489 cmd->cmd_state = FCP_PKT_IDLE; 9490 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9491 9492 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9493 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9494 fcp_trace, FCP_BUF_LEVEL_9, 0, 9495 "fcp_transport: xport busy for pkt %p", 9496 cmd->cmd_pkt); 9497 rval = FC_TRAN_BUSY; 9498 } else { 9499 fcp_queue_pkt(pptr, cmd); 9500 rval = FC_SUCCESS; 9501 } 9502 } 9503 } 9504 9505 return (rval); 9506 } 9507 9508 /*VARARGS3*/ 9509 static void 9510 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9511 { 9512 char buf[256]; 9513 va_list ap; 9514 9515 if (dip == NULL) { 9516 dip = fcp_global_dip; 9517 } 9518 9519 va_start(ap, fmt); 9520 (void) vsprintf(buf, fmt, ap); 9521 va_end(ap); 9522 9523 scsi_log(dip, "fcp", level, buf); 9524 } 9525 9526 /* 9527 * This function retries NS registry of FC4 type. 9528 * It assumes that fcp_mutex is held. 9529 * The function does nothing if topology is not fabric 9530 * So, the topology has to be set before this function can be called 9531 */ 9532 static void 9533 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9534 { 9535 int rval; 9536 9537 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9538 9539 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9540 ((pptr->port_topology != FC_TOP_FABRIC) && 9541 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9542 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9543 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9544 } 9545 return; 9546 } 9547 mutex_exit(&pptr->port_mutex); 9548 rval = fcp_do_ns_registry(pptr, s_id); 9549 mutex_enter(&pptr->port_mutex); 9550 9551 if (rval == 0) { 9552 /* Registry successful. Reset flag */ 9553 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9554 } 9555 } 9556 9557 /* 9558 * This function registers the ULP with the switch by calling transport i/f 9559 */ 9560 static int 9561 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9562 { 9563 fc_ns_cmd_t ns_cmd; 9564 ns_rfc_type_t rfc; 9565 uint32_t types[8]; 9566 9567 /* 9568 * Prepare the Name server structure to 9569 * register with the transport in case of 9570 * Fabric configuration. 9571 */ 9572 bzero(&rfc, sizeof (rfc)); 9573 bzero(types, sizeof (types)); 9574 9575 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9576 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9577 9578 rfc.rfc_port_id.port_id = s_id; 9579 bcopy(types, rfc.rfc_types, sizeof (types)); 9580 9581 ns_cmd.ns_flags = 0; 9582 ns_cmd.ns_cmd = NS_RFT_ID; 9583 ns_cmd.ns_req_len = sizeof (rfc); 9584 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9585 ns_cmd.ns_resp_len = 0; 9586 ns_cmd.ns_resp_payload = NULL; 9587 9588 /* 9589 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9590 */ 9591 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9592 fcp_log(CE_WARN, pptr->port_dip, 9593 "!ns_registry: failed name server registration"); 9594 return (1); 9595 } 9596 9597 return (0); 9598 } 9599 9600 /* 9601 * Function: fcp_handle_port_attach 9602 * 9603 * Description: This function is called from fcp_port_attach() to attach a 9604 * new port. This routine does the following: 9605 * 9606 * 1) Allocates an fcp_port structure and initializes it. 9607 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9608 * server. 9609 * 3) Kicks off the enumeration of the targets/luns visible 9610 * through this new port. That is done by calling 9611 * fcp_statec_callback() if the port is online. 9612 * 9613 * Argument: ulph fp/fctl port handle. 9614 * *pinfo Port information. 9615 * s_id Port ID. 9616 * instance Device instance number for the local port 9617 * (returned by ddi_get_instance()). 9618 * 9619 * Return Value: DDI_SUCCESS 9620 * DDI_FAILURE 9621 * 9622 * Context: User and Kernel context. 9623 */ 9624 /*ARGSUSED*/ 9625 int 9626 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9627 uint32_t s_id, int instance) 9628 { 9629 int res = DDI_FAILURE; 9630 scsi_hba_tran_t *tran; 9631 int mutex_initted = FALSE; 9632 int hba_attached = FALSE; 9633 int soft_state_linked = FALSE; 9634 int event_bind = FALSE; 9635 struct fcp_port *pptr; 9636 fc_portmap_t *tmp_list = NULL; 9637 uint32_t max_cnt, alloc_cnt; 9638 uchar_t *boot_wwn = NULL; 9639 uint_t nbytes; 9640 int manual_cfg; 9641 9642 /* 9643 * this port instance attaching for the first time (or after 9644 * being detached before) 9645 */ 9646 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9647 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9648 9649 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9650 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9651 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9652 instance); 9653 return (res); 9654 } 9655 9656 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9657 /* this shouldn't happen */ 9658 ddi_soft_state_free(fcp_softstate, instance); 9659 cmn_err(CE_WARN, "fcp: bad soft state"); 9660 return (res); 9661 } 9662 9663 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9664 9665 /* 9666 * Make a copy of ulp_port_info as fctl allocates 9667 * a temp struct. 9668 */ 9669 (void) fcp_cp_pinfo(pptr, pinfo); 9670 9671 /* 9672 * Check for manual_configuration_only property. 9673 * Enable manual configurtion if the property is 9674 * set to 1, otherwise disable manual configuration. 9675 */ 9676 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9677 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9678 MANUAL_CFG_ONLY, 9679 -1)) != -1) { 9680 if (manual_cfg == 1) { 9681 char *pathname; 9682 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9683 (void) ddi_pathname(pptr->port_dip, pathname); 9684 cmn_err(CE_NOTE, 9685 "%s (%s%d) %s is enabled via %s.conf.", 9686 pathname, 9687 ddi_driver_name(pptr->port_dip), 9688 ddi_get_instance(pptr->port_dip), 9689 MANUAL_CFG_ONLY, 9690 ddi_driver_name(pptr->port_dip)); 9691 fcp_enable_auto_configuration = 0; 9692 kmem_free(pathname, MAXPATHLEN); 9693 } 9694 } 9695 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)) 9696 pptr->port_link_cnt = 1; 9697 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)) 9698 pptr->port_id = s_id; 9699 pptr->port_instance = instance; 9700 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)) 9701 pptr->port_state = FCP_STATE_INIT; 9702 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)) 9703 9704 pptr->port_dmacookie_sz = (pptr->port_data_dma_attr.dma_attr_sgllen * 9705 sizeof (ddi_dma_cookie_t)); 9706 9707 /* 9708 * The two mutexes of fcp_port are initialized. The variable 9709 * mutex_initted is incremented to remember that fact. That variable 9710 * is checked when the routine fails and the mutexes have to be 9711 * destroyed. 9712 */ 9713 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9714 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9715 mutex_initted++; 9716 9717 /* 9718 * The SCSI tran structure is allocate and initialized now. 9719 */ 9720 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9721 fcp_log(CE_WARN, pptr->port_dip, 9722 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9723 goto fail; 9724 } 9725 9726 /* link in the transport structure then fill it in */ 9727 pptr->port_tran = tran; 9728 tran->tran_hba_private = pptr; 9729 tran->tran_tgt_init = fcp_scsi_tgt_init; 9730 tran->tran_tgt_probe = NULL; 9731 tran->tran_tgt_free = fcp_scsi_tgt_free; 9732 tran->tran_start = fcp_scsi_start; 9733 tran->tran_reset = fcp_scsi_reset; 9734 tran->tran_abort = fcp_scsi_abort; 9735 tran->tran_getcap = fcp_scsi_getcap; 9736 tran->tran_setcap = fcp_scsi_setcap; 9737 tran->tran_init_pkt = NULL; 9738 tran->tran_destroy_pkt = NULL; 9739 tran->tran_dmafree = NULL; 9740 tran->tran_sync_pkt = NULL; 9741 tran->tran_reset_notify = fcp_scsi_reset_notify; 9742 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9743 tran->tran_get_name = fcp_scsi_get_name; 9744 tran->tran_clear_aca = NULL; 9745 tran->tran_clear_task_set = NULL; 9746 tran->tran_terminate_task = NULL; 9747 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9748 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9749 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9750 tran->tran_post_event = fcp_scsi_bus_post_event; 9751 tran->tran_quiesce = NULL; 9752 tran->tran_unquiesce = NULL; 9753 tran->tran_bus_reset = NULL; 9754 tran->tran_bus_config = fcp_scsi_bus_config; 9755 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9756 tran->tran_bus_power = NULL; 9757 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9758 9759 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9760 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9761 tran->tran_setup_pkt = fcp_pkt_setup; 9762 tran->tran_teardown_pkt = fcp_pkt_teardown; 9763 tran->tran_hba_len = pptr->port_priv_pkt_len + 9764 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9765 9766 /* 9767 * Allocate an ndi event handle 9768 */ 9769 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9770 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9771 9772 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9773 sizeof (fcp_ndi_event_defs)); 9774 9775 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9776 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9777 9778 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9779 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9780 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9781 9782 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9783 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9784 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9785 goto fail; 9786 } 9787 event_bind++; /* Checked in fail case */ 9788 9789 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9790 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9791 != DDI_SUCCESS) { 9792 fcp_log(CE_WARN, pptr->port_dip, 9793 "!fcp%d: scsi_hba_attach_setup failed", instance); 9794 goto fail; 9795 } 9796 hba_attached++; /* Checked in fail case */ 9797 9798 pptr->port_mpxio = 0; 9799 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9800 MDI_SUCCESS) { 9801 pptr->port_mpxio++; 9802 } 9803 9804 /* 9805 * The following code is putting the new port structure in the global 9806 * list of ports and, if it is the first port to attach, it start the 9807 * fcp_watchdog_tick. 9808 * 9809 * Why put this new port in the global before we are done attaching it? 9810 * We are actually making the structure globally known before we are 9811 * done attaching it. The reason for that is: because of the code that 9812 * follows. At this point the resources to handle the port are 9813 * allocated. This function is now going to do the following: 9814 * 9815 * 1) It is going to try to register with the name server advertizing 9816 * the new FCP capability of the port. 9817 * 2) It is going to play the role of the fp/fctl layer by building 9818 * a list of worlwide names reachable through this port and call 9819 * itself on fcp_statec_callback(). That requires the port to 9820 * be part of the global list. 9821 */ 9822 mutex_enter(&fcp_global_mutex); 9823 if (fcp_port_head == NULL) { 9824 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 9825 } 9826 pptr->port_next = fcp_port_head; 9827 fcp_port_head = pptr; 9828 soft_state_linked++; 9829 9830 if (fcp_watchdog_init++ == 0) { 9831 fcp_watchdog_tick = fcp_watchdog_timeout * 9832 drv_usectohz(1000000); 9833 fcp_watchdog_id = timeout(fcp_watch, NULL, 9834 fcp_watchdog_tick); 9835 } 9836 mutex_exit(&fcp_global_mutex); 9837 9838 /* 9839 * Here an attempt is made to register with the name server, the new 9840 * FCP capability. That is done using an RTF_ID to the name server. 9841 * It is done synchronously. The function fcp_do_ns_registry() 9842 * doesn't return till the name server responded. 9843 * On failures, just ignore it for now and it will get retried during 9844 * state change callbacks. We'll set a flag to show this failure 9845 */ 9846 if (fcp_do_ns_registry(pptr, s_id)) { 9847 mutex_enter(&pptr->port_mutex); 9848 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 9849 mutex_exit(&pptr->port_mutex); 9850 } else { 9851 mutex_enter(&pptr->port_mutex); 9852 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9853 mutex_exit(&pptr->port_mutex); 9854 } 9855 9856 /* 9857 * Lookup for boot WWN property 9858 */ 9859 if (modrootloaded != 1) { 9860 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 9861 ddi_get_parent(pinfo->port_dip), 9862 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 9863 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 9864 (nbytes == FC_WWN_SIZE)) { 9865 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 9866 } 9867 if (boot_wwn) { 9868 ddi_prop_free(boot_wwn); 9869 } 9870 } 9871 9872 /* 9873 * Handle various topologies and link states. 9874 */ 9875 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 9876 case FC_STATE_OFFLINE: 9877 9878 /* 9879 * we're attaching a port where the link is offline 9880 * 9881 * Wait for ONLINE, at which time a state 9882 * change will cause a statec_callback 9883 * 9884 * in the mean time, do not do anything 9885 */ 9886 res = DDI_SUCCESS; 9887 pptr->port_state |= FCP_STATE_OFFLINE; 9888 break; 9889 9890 case FC_STATE_ONLINE: { 9891 if (pptr->port_topology == FC_TOP_UNKNOWN) { 9892 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 9893 res = DDI_SUCCESS; 9894 break; 9895 } 9896 /* 9897 * discover devices and create nodes (a private 9898 * loop or point-to-point) 9899 */ 9900 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 9901 9902 /* 9903 * At this point we are going to build a list of all the ports 9904 * that can be reached through this local port. It looks like 9905 * we cannot handle more than FCP_MAX_DEVICES per local port 9906 * (128). 9907 */ 9908 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 9909 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 9910 KM_NOSLEEP)) == NULL) { 9911 fcp_log(CE_WARN, pptr->port_dip, 9912 "!fcp%d: failed to allocate portmap", 9913 instance); 9914 goto fail; 9915 } 9916 9917 /* 9918 * fc_ulp_getportmap() is going to provide us with the list of 9919 * remote ports in the buffer we just allocated. The way the 9920 * list is going to be retrieved depends on the topology. 9921 * However, if we are connected to a Fabric, a name server 9922 * request may be sent to get the list of FCP capable ports. 9923 * It should be noted that is the case the request is 9924 * synchronous. This means we are stuck here till the name 9925 * server replies. A lot of things can change during that time 9926 * and including, may be, being called on 9927 * fcp_statec_callback() for different reasons. I'm not sure 9928 * the code can handle that. 9929 */ 9930 max_cnt = FCP_MAX_DEVICES; 9931 alloc_cnt = FCP_MAX_DEVICES; 9932 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 9933 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 9934 FC_SUCCESS) { 9935 caddr_t msg; 9936 9937 (void) fc_ulp_error(res, &msg); 9938 9939 /* 9940 * this just means the transport is 9941 * busy perhaps building a portmap so, 9942 * for now, succeed this port attach 9943 * when the transport has a new map, 9944 * it'll send us a state change then 9945 */ 9946 fcp_log(CE_WARN, pptr->port_dip, 9947 "!failed to get port map : %s", msg); 9948 9949 res = DDI_SUCCESS; 9950 break; /* go return result */ 9951 } 9952 if (max_cnt > alloc_cnt) { 9953 alloc_cnt = max_cnt; 9954 } 9955 9956 /* 9957 * We are now going to call fcp_statec_callback() ourselves. 9958 * By issuing this call we are trying to kick off the enumera- 9959 * tion process. 9960 */ 9961 /* 9962 * let the state change callback do the SCSI device 9963 * discovery and create the devinfos 9964 */ 9965 fcp_statec_callback(ulph, pptr->port_fp_handle, 9966 pptr->port_phys_state, pptr->port_topology, tmp_list, 9967 max_cnt, pptr->port_id); 9968 9969 res = DDI_SUCCESS; 9970 break; 9971 } 9972 9973 default: 9974 /* unknown port state */ 9975 fcp_log(CE_WARN, pptr->port_dip, 9976 "!fcp%d: invalid port state at attach=0x%x", 9977 instance, pptr->port_phys_state); 9978 9979 mutex_enter(&pptr->port_mutex); 9980 pptr->port_phys_state = FCP_STATE_OFFLINE; 9981 mutex_exit(&pptr->port_mutex); 9982 9983 res = DDI_SUCCESS; 9984 break; 9985 } 9986 9987 /* free temp list if used */ 9988 if (tmp_list != NULL) { 9989 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 9990 } 9991 9992 /* note the attach time */ 9993 pptr->port_attach_time = lbolt64; 9994 9995 /* all done */ 9996 return (res); 9997 9998 /* a failure we have to clean up after */ 9999 fail: 10000 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10001 10002 if (soft_state_linked) { 10003 /* remove this fcp_port from the linked list */ 10004 (void) fcp_soft_state_unlink(pptr); 10005 } 10006 10007 /* unbind and free event set */ 10008 if (pptr->port_ndi_event_hdl) { 10009 if (event_bind) { 10010 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10011 &pptr->port_ndi_events, NDI_SLEEP); 10012 } 10013 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10014 } 10015 10016 if (pptr->port_ndi_event_defs) { 10017 (void) kmem_free(pptr->port_ndi_event_defs, 10018 sizeof (fcp_ndi_event_defs)); 10019 } 10020 10021 /* 10022 * Clean up mpxio stuff 10023 */ 10024 if (pptr->port_mpxio) { 10025 (void) mdi_phci_unregister(pptr->port_dip, 0); 10026 pptr->port_mpxio--; 10027 } 10028 10029 /* undo SCSI HBA setup */ 10030 if (hba_attached) { 10031 (void) scsi_hba_detach(pptr->port_dip); 10032 } 10033 if (pptr->port_tran != NULL) { 10034 scsi_hba_tran_free(pptr->port_tran); 10035 } 10036 10037 mutex_enter(&fcp_global_mutex); 10038 10039 /* 10040 * We check soft_state_linked, because it is incremented right before 10041 * we call increment fcp_watchdog_init. Therefore, we know if 10042 * soft_state_linked is still FALSE, we do not want to decrement 10043 * fcp_watchdog_init or possibly call untimeout. 10044 */ 10045 10046 if (soft_state_linked) { 10047 if (--fcp_watchdog_init == 0) { 10048 timeout_id_t tid = fcp_watchdog_id; 10049 10050 mutex_exit(&fcp_global_mutex); 10051 (void) untimeout(tid); 10052 } else { 10053 mutex_exit(&fcp_global_mutex); 10054 } 10055 } else { 10056 mutex_exit(&fcp_global_mutex); 10057 } 10058 10059 if (mutex_initted) { 10060 mutex_destroy(&pptr->port_mutex); 10061 mutex_destroy(&pptr->port_pkt_mutex); 10062 } 10063 10064 if (tmp_list != NULL) { 10065 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10066 } 10067 10068 /* this makes pptr invalid */ 10069 ddi_soft_state_free(fcp_softstate, instance); 10070 10071 return (DDI_FAILURE); 10072 } 10073 10074 10075 static int 10076 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10077 { 10078 int count = 0; 10079 10080 mutex_enter(&pptr->port_mutex); 10081 10082 /* 10083 * if the port is powered down or suspended, nothing else 10084 * to do; just return. 10085 */ 10086 if (flag != FCP_STATE_DETACHING) { 10087 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10088 FCP_STATE_SUSPENDED)) { 10089 pptr->port_state |= flag; 10090 mutex_exit(&pptr->port_mutex); 10091 return (FC_SUCCESS); 10092 } 10093 } 10094 10095 if (pptr->port_state & FCP_STATE_IN_MDI) { 10096 mutex_exit(&pptr->port_mutex); 10097 return (FC_FAILURE); 10098 } 10099 10100 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10101 fcp_trace, FCP_BUF_LEVEL_2, 0, 10102 "fcp_handle_port_detach: port is detaching"); 10103 10104 pptr->port_state |= flag; 10105 10106 /* 10107 * Wait for any ongoing reconfig/ipkt to complete, that 10108 * ensures the freeing to targets/luns is safe. 10109 * No more ref to this port should happen from statec/ioctl 10110 * after that as it was removed from the global port list. 10111 */ 10112 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10113 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10114 /* 10115 * Let's give sufficient time for reconfig/ipkt 10116 * to complete. 10117 */ 10118 if (count++ >= FCP_ICMD_DEADLINE) { 10119 break; 10120 } 10121 mutex_exit(&pptr->port_mutex); 10122 delay(drv_usectohz(1000000)); 10123 mutex_enter(&pptr->port_mutex); 10124 } 10125 10126 /* 10127 * if the driver is still busy then fail to 10128 * suspend/power down. 10129 */ 10130 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10131 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10132 pptr->port_state &= ~flag; 10133 mutex_exit(&pptr->port_mutex); 10134 return (FC_FAILURE); 10135 } 10136 10137 if (flag == FCP_STATE_DETACHING) { 10138 pptr = fcp_soft_state_unlink(pptr); 10139 ASSERT(pptr != NULL); 10140 } 10141 10142 pptr->port_link_cnt++; 10143 pptr->port_state |= FCP_STATE_OFFLINE; 10144 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10145 10146 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10147 FCP_CAUSE_LINK_DOWN); 10148 mutex_exit(&pptr->port_mutex); 10149 10150 /* kill watch dog timer if we're the last */ 10151 mutex_enter(&fcp_global_mutex); 10152 if (--fcp_watchdog_init == 0) { 10153 timeout_id_t tid = fcp_watchdog_id; 10154 mutex_exit(&fcp_global_mutex); 10155 (void) untimeout(tid); 10156 } else { 10157 mutex_exit(&fcp_global_mutex); 10158 } 10159 10160 /* clean up the port structures */ 10161 if (flag == FCP_STATE_DETACHING) { 10162 fcp_cleanup_port(pptr, instance); 10163 } 10164 10165 return (FC_SUCCESS); 10166 } 10167 10168 10169 static void 10170 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10171 { 10172 ASSERT(pptr != NULL); 10173 10174 /* unbind and free event set */ 10175 if (pptr->port_ndi_event_hdl) { 10176 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10177 &pptr->port_ndi_events, NDI_SLEEP); 10178 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10179 } 10180 10181 if (pptr->port_ndi_event_defs) { 10182 (void) kmem_free(pptr->port_ndi_event_defs, 10183 sizeof (fcp_ndi_event_defs)); 10184 } 10185 10186 /* free the lun/target structures and devinfos */ 10187 fcp_free_targets(pptr); 10188 10189 /* 10190 * Clean up mpxio stuff 10191 */ 10192 if (pptr->port_mpxio) { 10193 (void) mdi_phci_unregister(pptr->port_dip, 0); 10194 pptr->port_mpxio--; 10195 } 10196 10197 /* clean up SCSA stuff */ 10198 (void) scsi_hba_detach(pptr->port_dip); 10199 if (pptr->port_tran != NULL) { 10200 scsi_hba_tran_free(pptr->port_tran); 10201 } 10202 10203 #ifdef KSTATS_CODE 10204 /* clean up kstats */ 10205 if (pptr->fcp_ksp != NULL) { 10206 kstat_delete(pptr->fcp_ksp); 10207 } 10208 #endif 10209 10210 /* clean up soft state mutexes/condition variables */ 10211 mutex_destroy(&pptr->port_mutex); 10212 mutex_destroy(&pptr->port_pkt_mutex); 10213 10214 /* all done with soft state */ 10215 ddi_soft_state_free(fcp_softstate, instance); 10216 } 10217 10218 /* 10219 * Function: fcp_kmem_cache_constructor 10220 * 10221 * Description: This function allocates and initializes the resources required 10222 * to build a scsi_pkt structure the target driver. The result 10223 * of the allocation and initialization will be cached in the 10224 * memory cache. As DMA resources may be allocated here, that 10225 * means DMA resources will be tied up in the cache manager. 10226 * This is a tradeoff that has been made for performance reasons. 10227 * 10228 * Argument: *buf Memory to preinitialize. 10229 * *arg FCP port structure (fcp_port). 10230 * kmflags Value passed to kmem_cache_alloc() and 10231 * propagated to the constructor. 10232 * 10233 * Return Value: 0 Allocation/Initialization was successful. 10234 * -1 Allocation or Initialization failed. 10235 * 10236 * 10237 * If the returned value is 0, the buffer is initialized like this: 10238 * 10239 * +================================+ 10240 * +----> | struct scsi_pkt | 10241 * | | | 10242 * | +--- | pkt_ha_private | 10243 * | | | | 10244 * | | +================================+ 10245 * | | 10246 * | | +================================+ 10247 * | +--> | struct fcp_pkt | <---------+ 10248 * | | | | 10249 * +----- | cmd_pkt | | 10250 * | cmd_fp_pkt | ---+ | 10251 * +-------->| cmd_fcp_rsp[] | | | 10252 * | +--->| cmd_fcp_cmd[] | | | 10253 * | | |--------------------------------| | | 10254 * | | | struct fc_packet | <--+ | 10255 * | | | | | 10256 * | | | pkt_ulp_private | ----------+ 10257 * | | | pkt_fca_private | -----+ 10258 * | | | pkt_data_cookie | ---+ | 10259 * | | | pkt_cmdlen | | | 10260 * | |(a) | pkt_rsplen | | | 10261 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10262 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10263 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10264 * | pkt_resp_cookie | ---|-|--+ | | | 10265 * | pkt_cmd_dma | | | | | | | 10266 * | pkt_cmd_acc | | | | | | | 10267 * +================================+ | | | | | | 10268 * | dma_cookies | <--+ | | | | | 10269 * | | | | | | | 10270 * +================================+ | | | | | 10271 * | fca_private | <----+ | | | | 10272 * | | | | | | 10273 * +================================+ | | | | 10274 * | | | | 10275 * | | | | 10276 * +================================+ (d) | | | | 10277 * | fcp_resp cookies | <-------+ | | | 10278 * | | | | | 10279 * +================================+ | | | 10280 * | | | 10281 * +================================+ (d) | | | 10282 * | fcp_resp | <-----------+ | | 10283 * | (DMA resources associated) | | | 10284 * +================================+ | | 10285 * | | 10286 * | | 10287 * | | 10288 * +================================+ (c) | | 10289 * | fcp_cmd cookies | <---------------+ | 10290 * | | | 10291 * +================================+ | 10292 * | 10293 * +================================+ (c) | 10294 * | fcp_cmd | <--------------------+ 10295 * | (DMA resources associated) | 10296 * +================================+ 10297 * 10298 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10299 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10300 * (c) Only if DMA is used for the FCP_CMD buffer. 10301 * (d) Only if DMA is used for the FCP_RESP buffer 10302 */ 10303 static int 10304 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10305 int kmflags) 10306 { 10307 struct fcp_pkt *cmd; 10308 struct fcp_port *pptr; 10309 fc_packet_t *fpkt; 10310 10311 pptr = (struct fcp_port *)tran->tran_hba_private; 10312 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10313 bzero(cmd, tran->tran_hba_len); 10314 10315 cmd->cmd_pkt = pkt; 10316 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10317 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10318 cmd->cmd_fp_pkt = fpkt; 10319 10320 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10321 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10322 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10323 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10324 10325 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10326 sizeof (struct fcp_pkt)); 10327 10328 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10329 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10330 10331 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10332 /* 10333 * The underlying HBA doesn't want to DMA the fcp_cmd or 10334 * fcp_resp. The transfer of information will be done by 10335 * bcopy. 10336 * The naming of the flags (that is actually a value) is 10337 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10338 * DMA" but instead "NO DMA". 10339 */ 10340 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10341 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10342 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10343 } else { 10344 /* 10345 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10346 * buffer. A buffer is allocated for each one the ddi_dma_* 10347 * interfaces. 10348 */ 10349 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10350 return (-1); 10351 } 10352 } 10353 10354 return (0); 10355 } 10356 10357 /* 10358 * Function: fcp_kmem_cache_destructor 10359 * 10360 * Description: Called by the destructor of the cache managed by SCSA. 10361 * All the resources pre-allocated in fcp_pkt_constructor 10362 * and the data also pre-initialized in fcp_pkt_constructor 10363 * are freed and uninitialized here. 10364 * 10365 * Argument: *buf Memory to uninitialize. 10366 * *arg FCP port structure (fcp_port). 10367 * 10368 * Return Value: None 10369 * 10370 * Context: kernel 10371 */ 10372 static void 10373 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10374 { 10375 struct fcp_pkt *cmd; 10376 struct fcp_port *pptr; 10377 10378 pptr = (struct fcp_port *)(tran->tran_hba_private); 10379 cmd = pkt->pkt_ha_private; 10380 10381 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10382 /* 10383 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10384 * buffer and DMA resources allocated to do so are released. 10385 */ 10386 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10387 } 10388 } 10389 10390 /* 10391 * Function: fcp_alloc_cmd_resp 10392 * 10393 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10394 * will be DMAed by the HBA. The buffer is allocated applying 10395 * the DMA requirements for the HBA. The buffers allocated will 10396 * also be bound. DMA resources are allocated in the process. 10397 * They will be released by fcp_free_cmd_resp(). 10398 * 10399 * Argument: *pptr FCP port. 10400 * *fpkt fc packet for which the cmd and resp packet should be 10401 * allocated. 10402 * flags Allocation flags. 10403 * 10404 * Return Value: FC_FAILURE 10405 * FC_SUCCESS 10406 * 10407 * Context: User or Kernel context only if flags == KM_SLEEP. 10408 * Interrupt context if the KM_SLEEP is not specified. 10409 */ 10410 static int 10411 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10412 { 10413 int rval; 10414 int cmd_len; 10415 int resp_len; 10416 ulong_t real_len; 10417 int (*cb) (caddr_t); 10418 ddi_dma_cookie_t pkt_cookie; 10419 ddi_dma_cookie_t *cp; 10420 uint32_t cnt; 10421 10422 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10423 10424 cmd_len = fpkt->pkt_cmdlen; 10425 resp_len = fpkt->pkt_rsplen; 10426 10427 ASSERT(fpkt->pkt_cmd_dma == NULL); 10428 10429 /* Allocation of a DMA handle used in subsequent calls. */ 10430 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10431 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10432 return (FC_FAILURE); 10433 } 10434 10435 /* A buffer is allocated that satisfies the DMA requirements. */ 10436 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10437 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10438 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10439 10440 if (rval != DDI_SUCCESS) { 10441 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10442 return (FC_FAILURE); 10443 } 10444 10445 if (real_len < cmd_len) { 10446 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10447 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10448 return (FC_FAILURE); 10449 } 10450 10451 /* The buffer allocated is DMA bound. */ 10452 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10453 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10454 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10455 10456 if (rval != DDI_DMA_MAPPED) { 10457 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10458 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10459 return (FC_FAILURE); 10460 } 10461 10462 if (fpkt->pkt_cmd_cookie_cnt > 10463 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10464 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10465 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10466 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10467 return (FC_FAILURE); 10468 } 10469 10470 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10471 10472 /* 10473 * The buffer where the scatter/gather list is going to be built is 10474 * allocated. 10475 */ 10476 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10477 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10478 KM_NOSLEEP); 10479 10480 if (cp == NULL) { 10481 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10482 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10483 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10484 return (FC_FAILURE); 10485 } 10486 10487 /* 10488 * The scatter/gather list for the buffer we just allocated is built 10489 * here. 10490 */ 10491 *cp = pkt_cookie; 10492 cp++; 10493 10494 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10495 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10496 &pkt_cookie); 10497 *cp = pkt_cookie; 10498 } 10499 10500 ASSERT(fpkt->pkt_resp_dma == NULL); 10501 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10502 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10503 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10504 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10505 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10506 return (FC_FAILURE); 10507 } 10508 10509 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10510 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10511 (caddr_t *)&fpkt->pkt_resp, &real_len, 10512 &fpkt->pkt_resp_acc); 10513 10514 if (rval != DDI_SUCCESS) { 10515 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10516 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10517 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10518 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10519 kmem_free(fpkt->pkt_cmd_cookie, 10520 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10521 return (FC_FAILURE); 10522 } 10523 10524 if (real_len < resp_len) { 10525 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10526 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10527 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10528 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10529 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10530 kmem_free(fpkt->pkt_cmd_cookie, 10531 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10532 return (FC_FAILURE); 10533 } 10534 10535 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10536 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10537 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10538 10539 if (rval != DDI_DMA_MAPPED) { 10540 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10541 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10542 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10543 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10544 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10545 kmem_free(fpkt->pkt_cmd_cookie, 10546 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10547 return (FC_FAILURE); 10548 } 10549 10550 if (fpkt->pkt_resp_cookie_cnt > 10551 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10552 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10553 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10554 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10555 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10556 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10557 kmem_free(fpkt->pkt_cmd_cookie, 10558 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10559 return (FC_FAILURE); 10560 } 10561 10562 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10563 10564 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10565 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10566 KM_NOSLEEP); 10567 10568 if (cp == NULL) { 10569 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10570 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10571 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10572 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10573 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10574 kmem_free(fpkt->pkt_cmd_cookie, 10575 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10576 return (FC_FAILURE); 10577 } 10578 10579 *cp = pkt_cookie; 10580 cp++; 10581 10582 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10583 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10584 &pkt_cookie); 10585 *cp = pkt_cookie; 10586 } 10587 10588 return (FC_SUCCESS); 10589 } 10590 10591 /* 10592 * Function: fcp_free_cmd_resp 10593 * 10594 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10595 * allocated by fcp_alloc_cmd_resp() and all the resources 10596 * associated with them. That includes the DMA resources and the 10597 * buffer allocated for the cookies of each one of them. 10598 * 10599 * Argument: *pptr FCP port context. 10600 * *fpkt fc packet containing the cmd and resp packet 10601 * to be released. 10602 * 10603 * Return Value: None 10604 * 10605 * Context: Interrupt, User and Kernel context. 10606 */ 10607 /* ARGSUSED */ 10608 static void 10609 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10610 { 10611 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10612 10613 if (fpkt->pkt_resp_dma) { 10614 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10615 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10616 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10617 } 10618 10619 if (fpkt->pkt_resp_cookie) { 10620 kmem_free(fpkt->pkt_resp_cookie, 10621 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10622 fpkt->pkt_resp_cookie = NULL; 10623 } 10624 10625 if (fpkt->pkt_cmd_dma) { 10626 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10627 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10628 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10629 } 10630 10631 if (fpkt->pkt_cmd_cookie) { 10632 kmem_free(fpkt->pkt_cmd_cookie, 10633 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10634 fpkt->pkt_cmd_cookie = NULL; 10635 } 10636 } 10637 10638 10639 /* 10640 * called by the transport to do our own target initialization 10641 * 10642 * can acquire and release the global mutex 10643 */ 10644 /* ARGSUSED */ 10645 static int 10646 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10647 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10648 { 10649 int *words; 10650 uchar_t *bytes; 10651 uint_t nbytes; 10652 uint_t nwords; 10653 struct fcp_tgt *ptgt; 10654 struct fcp_lun *plun; 10655 struct fcp_port *pptr = (struct fcp_port *) 10656 hba_tran->tran_hba_private; 10657 10658 ASSERT(pptr != NULL); 10659 10660 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10661 FCP_BUF_LEVEL_8, 0, 10662 "fcp_phys_tgt_init: called for %s (instance %d)", 10663 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10664 10665 /* get our port WWN property */ 10666 bytes = NULL; 10667 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 10668 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 10669 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 10670 /* no port WWN property */ 10671 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10672 FCP_BUF_LEVEL_8, 0, 10673 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10674 " for %s (instance %d): bytes=%p nbytes=%x", 10675 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10676 nbytes); 10677 10678 if (bytes != NULL) { 10679 ddi_prop_free(bytes); 10680 } 10681 10682 return (DDI_NOT_WELL_FORMED); 10683 } 10684 10685 words = NULL; 10686 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tgt_dip, 10687 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 10688 LUN_PROP, &words, &nwords) != DDI_PROP_SUCCESS) { 10689 ASSERT(bytes != NULL); 10690 10691 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10692 FCP_BUF_LEVEL_8, 0, 10693 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10694 " for %s (instance %d)", ddi_get_name(tgt_dip), 10695 ddi_get_instance(tgt_dip)); 10696 10697 ddi_prop_free(bytes); 10698 10699 return (DDI_NOT_WELL_FORMED); 10700 } 10701 10702 if (nwords == 0) { 10703 ddi_prop_free(bytes); 10704 ddi_prop_free(words); 10705 return (DDI_NOT_WELL_FORMED); 10706 } 10707 10708 ASSERT(bytes != NULL && words != NULL); 10709 10710 mutex_enter(&pptr->port_mutex); 10711 if ((plun = fcp_lookup_lun(pptr, bytes, *words)) == NULL) { 10712 mutex_exit(&pptr->port_mutex); 10713 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10714 FCP_BUF_LEVEL_8, 0, 10715 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10716 " for %s (instance %d)", ddi_get_name(tgt_dip), 10717 ddi_get_instance(tgt_dip)); 10718 10719 ddi_prop_free(bytes); 10720 ddi_prop_free(words); 10721 10722 return (DDI_FAILURE); 10723 } 10724 10725 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10726 FC_WWN_SIZE) == 0); 10727 ASSERT(plun->lun_num == (uint16_t)*words); 10728 10729 ddi_prop_free(bytes); 10730 ddi_prop_free(words); 10731 10732 ptgt = plun->lun_tgt; 10733 10734 mutex_enter(&ptgt->tgt_mutex); 10735 plun->lun_tgt_count++; 10736 scsi_device_hba_private_set(sd, plun); 10737 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10738 plun->lun_tran = hba_tran; 10739 mutex_exit(&ptgt->tgt_mutex); 10740 mutex_exit(&pptr->port_mutex); 10741 10742 return (DDI_SUCCESS); 10743 } 10744 10745 /*ARGSUSED*/ 10746 static int 10747 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10748 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10749 { 10750 int words; 10751 uchar_t *bytes; 10752 uint_t nbytes; 10753 struct fcp_tgt *ptgt; 10754 struct fcp_lun *plun; 10755 struct fcp_port *pptr = (struct fcp_port *) 10756 hba_tran->tran_hba_private; 10757 child_info_t *cip; 10758 10759 ASSERT(pptr != NULL); 10760 10761 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10762 fcp_trace, FCP_BUF_LEVEL_8, 0, 10763 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10764 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10765 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10766 10767 cip = (child_info_t *)sd->sd_pathinfo; 10768 if (cip == NULL) { 10769 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10770 fcp_trace, FCP_BUF_LEVEL_8, 0, 10771 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10772 " for %s (instance %d)", ddi_get_name(tgt_dip), 10773 ddi_get_instance(tgt_dip)); 10774 10775 return (DDI_NOT_WELL_FORMED); 10776 } 10777 10778 /* get our port WWN property */ 10779 bytes = NULL; 10780 if ((mdi_prop_lookup_byte_array(PIP(cip), PORT_WWN_PROP, &bytes, 10781 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 10782 if (bytes) { 10783 (void) mdi_prop_free(bytes); 10784 } 10785 return (DDI_NOT_WELL_FORMED); 10786 } 10787 10788 words = 0; 10789 if (mdi_prop_lookup_int(PIP(cip), LUN_PROP, &words) != 10790 DDI_PROP_SUCCESS) { 10791 ASSERT(bytes != NULL); 10792 10793 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10794 fcp_trace, FCP_BUF_LEVEL_8, 0, 10795 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10796 " for %s (instance %d)", ddi_get_name(tgt_dip), 10797 ddi_get_instance(tgt_dip)); 10798 10799 (void) mdi_prop_free(bytes); 10800 return (DDI_NOT_WELL_FORMED); 10801 } 10802 10803 ASSERT(bytes != NULL); 10804 10805 mutex_enter(&pptr->port_mutex); 10806 if ((plun = fcp_lookup_lun(pptr, bytes, words)) == NULL) { 10807 mutex_exit(&pptr->port_mutex); 10808 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10809 fcp_trace, FCP_BUF_LEVEL_8, 0, 10810 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10811 " for %s (instance %d)", ddi_get_name(tgt_dip), 10812 ddi_get_instance(tgt_dip)); 10813 10814 (void) mdi_prop_free(bytes); 10815 (void) mdi_prop_free(&words); 10816 10817 return (DDI_FAILURE); 10818 } 10819 10820 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10821 FC_WWN_SIZE) == 0); 10822 ASSERT(plun->lun_num == (uint16_t)words); 10823 10824 (void) mdi_prop_free(bytes); 10825 (void) mdi_prop_free(&words); 10826 10827 ptgt = plun->lun_tgt; 10828 10829 mutex_enter(&ptgt->tgt_mutex); 10830 plun->lun_tgt_count++; 10831 scsi_device_hba_private_set(sd, plun); 10832 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10833 plun->lun_tran = hba_tran; 10834 mutex_exit(&ptgt->tgt_mutex); 10835 mutex_exit(&pptr->port_mutex); 10836 10837 return (DDI_SUCCESS); 10838 } 10839 10840 10841 /* 10842 * called by the transport to do our own target initialization 10843 * 10844 * can acquire and release the global mutex 10845 */ 10846 /* ARGSUSED */ 10847 static int 10848 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10849 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10850 { 10851 struct fcp_port *pptr = (struct fcp_port *) 10852 hba_tran->tran_hba_private; 10853 int rval; 10854 10855 ASSERT(pptr != NULL); 10856 10857 /* 10858 * Child node is getting initialized. Look at the mpxio component 10859 * type on the child device to see if this device is mpxio managed 10860 * or not. 10861 */ 10862 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 10863 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10864 } else { 10865 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 10866 } 10867 10868 return (rval); 10869 } 10870 10871 10872 /* ARGSUSED */ 10873 static void 10874 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10875 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10876 { 10877 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 10878 struct fcp_tgt *ptgt; 10879 10880 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 10881 fcp_trace, FCP_BUF_LEVEL_8, 0, 10882 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 10883 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 10884 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10885 10886 if (plun == NULL) { 10887 return; 10888 } 10889 ptgt = plun->lun_tgt; 10890 10891 ASSERT(ptgt != NULL); 10892 10893 mutex_enter(&ptgt->tgt_mutex); 10894 ASSERT(plun->lun_tgt_count > 0); 10895 10896 if (--plun->lun_tgt_count == 0) { 10897 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 10898 } 10899 plun->lun_tran = NULL; 10900 mutex_exit(&ptgt->tgt_mutex); 10901 } 10902 10903 /* 10904 * Function: fcp_scsi_start 10905 * 10906 * Description: This function is called by the target driver to request a 10907 * command to be sent. 10908 * 10909 * Argument: *ap SCSI address of the device. 10910 * *pkt SCSI packet containing the cmd to send. 10911 * 10912 * Return Value: TRAN_ACCEPT 10913 * TRAN_BUSY 10914 * TRAN_BADPKT 10915 * TRAN_FATAL_ERROR 10916 */ 10917 static int 10918 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 10919 { 10920 struct fcp_port *pptr = ADDR2FCP(ap); 10921 struct fcp_lun *plun = ADDR2LUN(ap); 10922 struct fcp_pkt *cmd = PKT2CMD(pkt); 10923 struct fcp_tgt *ptgt = plun->lun_tgt; 10924 int rval; 10925 10926 /* ensure command isn't already issued */ 10927 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 10928 10929 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10930 fcp_trace, FCP_BUF_LEVEL_9, 0, 10931 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 10932 10933 /* 10934 * It is strange that we enter the fcp_port mutex and the target 10935 * mutex to check the lun state (which has a mutex of its own). 10936 */ 10937 mutex_enter(&pptr->port_mutex); 10938 mutex_enter(&ptgt->tgt_mutex); 10939 10940 /* 10941 * If the device is offline and is not in the process of coming 10942 * online, fail the request. 10943 */ 10944 10945 if ((plun->lun_state & FCP_LUN_OFFLINE) && 10946 !(plun->lun_state & FCP_LUN_ONLINING)) { 10947 mutex_exit(&ptgt->tgt_mutex); 10948 mutex_exit(&pptr->port_mutex); 10949 10950 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 10951 pkt->pkt_reason = CMD_DEV_GONE; 10952 } 10953 10954 return (TRAN_FATAL_ERROR); 10955 } 10956 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 10957 10958 /* 10959 * If we are suspended, kernel is trying to dump, so don't 10960 * block, fail or defer requests - send them down right away. 10961 * NOTE: If we are in panic (i.e. trying to dump), we can't 10962 * assume we have been suspended. There is hardware such as 10963 * the v880 that doesn't do PM. Thus, the check for 10964 * ddi_in_panic. 10965 * 10966 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 10967 * of changing. So, if we can queue the packet, do it. Eventually, 10968 * either the device will have gone away or changed and we can fail 10969 * the request, or we can proceed if the device didn't change. 10970 * 10971 * If the pd in the target or the packet is NULL it's probably 10972 * because the device has gone away, we allow the request to be 10973 * put on the internal queue here in case the device comes back within 10974 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 10975 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 10976 * could be NULL because the device was disappearing during or since 10977 * packet initialization. 10978 */ 10979 10980 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 10981 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 10982 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 10983 (ptgt->tgt_pd_handle == NULL) || 10984 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 10985 /* 10986 * If ((LUN is busy AND 10987 * LUN not suspended AND 10988 * The system is not in panic state) OR 10989 * (The port is coming up)) 10990 * 10991 * We check to see if the any of the flags FLAG_NOINTR or 10992 * FLAG_NOQUEUE is set. If one of them is set the value 10993 * returned will be TRAN_BUSY. If not, the request is queued. 10994 */ 10995 mutex_exit(&ptgt->tgt_mutex); 10996 mutex_exit(&pptr->port_mutex); 10997 10998 /* see if using interrupts is allowed (so queueing'll work) */ 10999 if (pkt->pkt_flags & FLAG_NOINTR) { 11000 pkt->pkt_resid = 0; 11001 return (TRAN_BUSY); 11002 } 11003 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11004 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11005 fcp_trace, FCP_BUF_LEVEL_9, 0, 11006 "fcp_scsi_start: lun busy for pkt %p", pkt); 11007 return (TRAN_BUSY); 11008 } 11009 #ifdef DEBUG 11010 mutex_enter(&pptr->port_pkt_mutex); 11011 pptr->port_npkts++; 11012 mutex_exit(&pptr->port_pkt_mutex); 11013 #endif /* DEBUG */ 11014 11015 /* got queue up the pkt for later */ 11016 fcp_queue_pkt(pptr, cmd); 11017 return (TRAN_ACCEPT); 11018 } 11019 cmd->cmd_state = FCP_PKT_ISSUED; 11020 11021 mutex_exit(&ptgt->tgt_mutex); 11022 mutex_exit(&pptr->port_mutex); 11023 11024 /* 11025 * Now that we released the mutexes, what was protected by them can 11026 * change. 11027 */ 11028 11029 /* 11030 * If there is a reconfiguration in progress, wait for it to complete. 11031 */ 11032 fcp_reconfig_wait(pptr); 11033 11034 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11035 pkt->pkt_time : 0; 11036 11037 /* prepare the packet */ 11038 11039 fcp_prepare_pkt(pptr, cmd, plun); 11040 11041 if (cmd->cmd_pkt->pkt_time) { 11042 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11043 } else { 11044 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11045 } 11046 11047 /* 11048 * if interrupts aren't allowed (e.g. at dump time) then we'll 11049 * have to do polled I/O 11050 */ 11051 if (pkt->pkt_flags & FLAG_NOINTR) { 11052 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11053 return (fcp_dopoll(pptr, cmd)); 11054 } 11055 11056 #ifdef DEBUG 11057 mutex_enter(&pptr->port_pkt_mutex); 11058 pptr->port_npkts++; 11059 mutex_exit(&pptr->port_pkt_mutex); 11060 #endif /* DEBUG */ 11061 11062 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11063 if (rval == FC_SUCCESS) { 11064 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11065 fcp_trace, FCP_BUF_LEVEL_9, 0, 11066 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11067 return (TRAN_ACCEPT); 11068 } 11069 11070 cmd->cmd_state = FCP_PKT_IDLE; 11071 11072 #ifdef DEBUG 11073 mutex_enter(&pptr->port_pkt_mutex); 11074 pptr->port_npkts--; 11075 mutex_exit(&pptr->port_pkt_mutex); 11076 #endif /* DEBUG */ 11077 11078 /* 11079 * For lack of clearer definitions, choose 11080 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11081 */ 11082 11083 if (rval == FC_TRAN_BUSY) { 11084 pkt->pkt_resid = 0; 11085 rval = TRAN_BUSY; 11086 } else { 11087 mutex_enter(&ptgt->tgt_mutex); 11088 if (plun->lun_state & FCP_LUN_OFFLINE) { 11089 child_info_t *cip; 11090 11091 mutex_enter(&plun->lun_mutex); 11092 cip = plun->lun_cip; 11093 mutex_exit(&plun->lun_mutex); 11094 11095 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11096 fcp_trace, FCP_BUF_LEVEL_6, 0, 11097 "fcp_transport failed 2 for %x: %x; dip=%p", 11098 plun->lun_tgt->tgt_d_id, rval, cip); 11099 11100 rval = TRAN_FATAL_ERROR; 11101 } else { 11102 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11103 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11104 fcp_trace, FCP_BUF_LEVEL_9, 0, 11105 "fcp_scsi_start: FC_BUSY for pkt %p", 11106 pkt); 11107 rval = TRAN_BUSY; 11108 } else { 11109 rval = TRAN_ACCEPT; 11110 fcp_queue_pkt(pptr, cmd); 11111 } 11112 } 11113 mutex_exit(&ptgt->tgt_mutex); 11114 } 11115 11116 return (rval); 11117 } 11118 11119 /* 11120 * called by the transport to abort a packet 11121 */ 11122 /*ARGSUSED*/ 11123 static int 11124 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11125 { 11126 int tgt_cnt; 11127 struct fcp_port *pptr = ADDR2FCP(ap); 11128 struct fcp_lun *plun = ADDR2LUN(ap); 11129 struct fcp_tgt *ptgt = plun->lun_tgt; 11130 11131 if (pkt == NULL) { 11132 if (ptgt) { 11133 mutex_enter(&ptgt->tgt_mutex); 11134 tgt_cnt = ptgt->tgt_change_cnt; 11135 mutex_exit(&ptgt->tgt_mutex); 11136 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11137 return (TRUE); 11138 } 11139 } 11140 return (FALSE); 11141 } 11142 11143 11144 /* 11145 * Perform reset 11146 */ 11147 int 11148 fcp_scsi_reset(struct scsi_address *ap, int level) 11149 { 11150 int rval = 0; 11151 struct fcp_port *pptr = ADDR2FCP(ap); 11152 struct fcp_lun *plun = ADDR2LUN(ap); 11153 struct fcp_tgt *ptgt = plun->lun_tgt; 11154 11155 if (level == RESET_ALL) { 11156 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11157 rval = 1; 11158 } 11159 } else if (level == RESET_TARGET || level == RESET_LUN) { 11160 /* 11161 * If we are in the middle of discovery, return 11162 * SUCCESS as this target will be rediscovered 11163 * anyway 11164 */ 11165 mutex_enter(&ptgt->tgt_mutex); 11166 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11167 mutex_exit(&ptgt->tgt_mutex); 11168 return (1); 11169 } 11170 mutex_exit(&ptgt->tgt_mutex); 11171 11172 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11173 rval = 1; 11174 } 11175 } 11176 return (rval); 11177 } 11178 11179 11180 /* 11181 * called by the framework to get a SCSI capability 11182 */ 11183 static int 11184 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11185 { 11186 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11187 } 11188 11189 11190 /* 11191 * called by the framework to set a SCSI capability 11192 */ 11193 static int 11194 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11195 { 11196 return (fcp_commoncap(ap, cap, value, whom, 1)); 11197 } 11198 11199 /* 11200 * Function: fcp_pkt_setup 11201 * 11202 * Description: This function sets up the scsi_pkt structure passed by the 11203 * caller. This function assumes fcp_pkt_constructor has been 11204 * called previously for the packet passed by the caller. If 11205 * successful this call will have the following results: 11206 * 11207 * - The resources needed that will be constant through out 11208 * the whole transaction are allocated. 11209 * - The fields that will be constant through out the whole 11210 * transaction are initialized. 11211 * - The scsi packet will be linked to the LUN structure 11212 * addressed by the transaction. 11213 * 11214 * Argument: 11215 * *pkt Pointer to a scsi_pkt structure. 11216 * callback 11217 * arg 11218 * 11219 * Return Value: 0 Success 11220 * !0 Failure 11221 * 11222 * Context: Kernel context or interrupt context 11223 */ 11224 /* ARGSUSED */ 11225 static int 11226 fcp_pkt_setup(struct scsi_pkt *pkt, 11227 int (*callback)(caddr_t arg), 11228 caddr_t arg) 11229 { 11230 struct fcp_pkt *cmd; 11231 struct fcp_port *pptr; 11232 struct fcp_lun *plun; 11233 struct fcp_tgt *ptgt; 11234 int kf; 11235 fc_packet_t *fpkt; 11236 fc_frame_hdr_t *hp; 11237 11238 pptr = ADDR2FCP(&pkt->pkt_address); 11239 plun = ADDR2LUN(&pkt->pkt_address); 11240 ptgt = plun->lun_tgt; 11241 11242 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11243 fpkt = cmd->cmd_fp_pkt; 11244 11245 /* 11246 * this request is for dma allocation only 11247 */ 11248 /* 11249 * First step of fcp_scsi_init_pkt: pkt allocation 11250 * We determine if the caller is willing to wait for the 11251 * resources. 11252 */ 11253 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11254 11255 /* 11256 * Selective zeroing of the pkt. 11257 */ 11258 cmd->cmd_back = NULL; 11259 cmd->cmd_next = NULL; 11260 11261 /* 11262 * Zero out fcp command 11263 */ 11264 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11265 11266 cmd->cmd_state = FCP_PKT_IDLE; 11267 11268 fpkt = cmd->cmd_fp_pkt; 11269 fpkt->pkt_data_acc = NULL; 11270 11271 mutex_enter(&ptgt->tgt_mutex); 11272 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11273 11274 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11275 != FC_SUCCESS) { 11276 mutex_exit(&ptgt->tgt_mutex); 11277 return (-1); 11278 } 11279 11280 mutex_exit(&ptgt->tgt_mutex); 11281 11282 /* Fill in the Fabric Channel Header */ 11283 hp = &fpkt->pkt_cmd_fhdr; 11284 hp->r_ctl = R_CTL_COMMAND; 11285 hp->rsvd = 0; 11286 hp->type = FC_TYPE_SCSI_FCP; 11287 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11288 hp->seq_id = 0; 11289 hp->df_ctl = 0; 11290 hp->seq_cnt = 0; 11291 hp->ox_id = 0xffff; 11292 hp->rx_id = 0xffff; 11293 hp->ro = 0; 11294 11295 /* 11296 * A doubly linked list (cmd_forw, cmd_back) is built 11297 * out of every allocated packet on a per-lun basis 11298 * 11299 * The packets are maintained in the list so as to satisfy 11300 * scsi_abort() requests. At present (which is unlikely to 11301 * change in the future) nobody performs a real scsi_abort 11302 * in the SCSI target drivers (as they don't keep the packets 11303 * after doing scsi_transport - so they don't know how to 11304 * abort a packet other than sending a NULL to abort all 11305 * outstanding packets) 11306 */ 11307 mutex_enter(&plun->lun_mutex); 11308 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11309 plun->lun_pkt_head->cmd_back = cmd; 11310 } else { 11311 plun->lun_pkt_tail = cmd; 11312 } 11313 plun->lun_pkt_head = cmd; 11314 mutex_exit(&plun->lun_mutex); 11315 return (0); 11316 } 11317 11318 /* 11319 * Function: fcp_pkt_teardown 11320 * 11321 * Description: This function releases a scsi_pkt structure and all the 11322 * resources attached to it. 11323 * 11324 * Argument: *pkt Pointer to a scsi_pkt structure. 11325 * 11326 * Return Value: None 11327 * 11328 * Context: User, Kernel or Interrupt context. 11329 */ 11330 static void 11331 fcp_pkt_teardown(struct scsi_pkt *pkt) 11332 { 11333 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11334 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11335 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11336 11337 /* 11338 * Remove the packet from the per-lun list 11339 */ 11340 mutex_enter(&plun->lun_mutex); 11341 if (cmd->cmd_back) { 11342 ASSERT(cmd != plun->lun_pkt_head); 11343 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11344 } else { 11345 ASSERT(cmd == plun->lun_pkt_head); 11346 plun->lun_pkt_head = cmd->cmd_forw; 11347 } 11348 11349 if (cmd->cmd_forw) { 11350 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11351 } else { 11352 ASSERT(cmd == plun->lun_pkt_tail); 11353 plun->lun_pkt_tail = cmd->cmd_back; 11354 } 11355 11356 mutex_exit(&plun->lun_mutex); 11357 11358 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11359 } 11360 11361 /* 11362 * Routine for reset notification setup, to register or cancel. 11363 * This function is called by SCSA 11364 */ 11365 /*ARGSUSED*/ 11366 static int 11367 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11368 void (*callback)(caddr_t), caddr_t arg) 11369 { 11370 struct fcp_port *pptr = ADDR2FCP(ap); 11371 11372 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11373 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11374 } 11375 11376 11377 static int 11378 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11379 ddi_eventcookie_t *event_cookiep) 11380 { 11381 struct fcp_port *pptr = fcp_dip2port(dip); 11382 11383 if (pptr == NULL) { 11384 return (DDI_FAILURE); 11385 } 11386 11387 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11388 event_cookiep, NDI_EVENT_NOPASS)); 11389 } 11390 11391 11392 static int 11393 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11394 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11395 ddi_callback_id_t *cb_id) 11396 { 11397 struct fcp_port *pptr = fcp_dip2port(dip); 11398 11399 if (pptr == NULL) { 11400 return (DDI_FAILURE); 11401 } 11402 11403 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11404 eventid, callback, arg, NDI_SLEEP, cb_id)); 11405 } 11406 11407 11408 static int 11409 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11410 { 11411 11412 struct fcp_port *pptr = fcp_dip2port(dip); 11413 11414 if (pptr == NULL) { 11415 return (DDI_FAILURE); 11416 } 11417 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11418 } 11419 11420 11421 /* 11422 * called by the transport to post an event 11423 */ 11424 static int 11425 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11426 ddi_eventcookie_t eventid, void *impldata) 11427 { 11428 struct fcp_port *pptr = fcp_dip2port(dip); 11429 11430 if (pptr == NULL) { 11431 return (DDI_FAILURE); 11432 } 11433 11434 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11435 eventid, impldata)); 11436 } 11437 11438 11439 /* 11440 * A target in in many cases in Fibre Channel has a one to one relation 11441 * with a port identifier (which is also known as D_ID and also as AL_PA 11442 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11443 * will most likely result in resetting all LUNs (which means a reset will 11444 * occur on all the SCSI devices connected at the other end of the bridge) 11445 * That is the latest favorite topic for discussion, for, one can debate as 11446 * hot as one likes and come up with arguably a best solution to one's 11447 * satisfaction 11448 * 11449 * To stay on track and not digress much, here are the problems stated 11450 * briefly: 11451 * 11452 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11453 * target drivers use RESET_TARGET even if their instance is on a 11454 * LUN. Doesn't that sound a bit broken ? 11455 * 11456 * FCP SCSI (the current spec) only defines RESET TARGET in the 11457 * control fields of an FCP_CMND structure. It should have been 11458 * fixed right there, giving flexibility to the initiators to 11459 * minimize havoc that could be caused by resetting a target. 11460 */ 11461 static int 11462 fcp_reset_target(struct scsi_address *ap, int level) 11463 { 11464 int rval = FC_FAILURE; 11465 char lun_id[25]; 11466 struct fcp_port *pptr = ADDR2FCP(ap); 11467 struct fcp_lun *plun = ADDR2LUN(ap); 11468 struct fcp_tgt *ptgt = plun->lun_tgt; 11469 struct scsi_pkt *pkt; 11470 struct fcp_pkt *cmd; 11471 struct fcp_rsp *rsp; 11472 uint32_t tgt_cnt; 11473 struct fcp_rsp_info *rsp_info; 11474 struct fcp_reset_elem *p; 11475 int bval; 11476 11477 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11478 KM_NOSLEEP)) == NULL) { 11479 return (rval); 11480 } 11481 11482 mutex_enter(&ptgt->tgt_mutex); 11483 if (level == RESET_TARGET) { 11484 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11485 mutex_exit(&ptgt->tgt_mutex); 11486 kmem_free(p, sizeof (struct fcp_reset_elem)); 11487 return (rval); 11488 } 11489 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11490 (void) strcpy(lun_id, " "); 11491 } else { 11492 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11493 mutex_exit(&ptgt->tgt_mutex); 11494 kmem_free(p, sizeof (struct fcp_reset_elem)); 11495 return (rval); 11496 } 11497 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11498 11499 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11500 } 11501 tgt_cnt = ptgt->tgt_change_cnt; 11502 11503 mutex_exit(&ptgt->tgt_mutex); 11504 11505 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11506 0, 0, NULL, 0)) == NULL) { 11507 kmem_free(p, sizeof (struct fcp_reset_elem)); 11508 mutex_enter(&ptgt->tgt_mutex); 11509 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11510 mutex_exit(&ptgt->tgt_mutex); 11511 return (rval); 11512 } 11513 pkt->pkt_time = FCP_POLL_TIMEOUT; 11514 11515 /* fill in cmd part of packet */ 11516 cmd = PKT2CMD(pkt); 11517 if (level == RESET_TARGET) { 11518 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11519 } else { 11520 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11521 } 11522 cmd->cmd_fp_pkt->pkt_comp = NULL; 11523 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11524 11525 /* prepare a packet for transport */ 11526 fcp_prepare_pkt(pptr, cmd, plun); 11527 11528 if (cmd->cmd_pkt->pkt_time) { 11529 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11530 } else { 11531 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11532 } 11533 11534 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11535 bval = fcp_dopoll(pptr, cmd); 11536 fc_ulp_idle_port(pptr->port_fp_handle); 11537 11538 /* submit the packet */ 11539 if (bval == TRAN_ACCEPT) { 11540 int error = 3; 11541 11542 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11543 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11544 sizeof (struct fcp_rsp)); 11545 11546 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11547 if (fcp_validate_fcp_response(rsp, pptr) == 11548 FC_SUCCESS) { 11549 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11550 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11551 sizeof (struct fcp_rsp), rsp_info, 11552 cmd->cmd_fp_pkt->pkt_resp_acc, 11553 sizeof (struct fcp_rsp_info)); 11554 } 11555 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11556 rval = FC_SUCCESS; 11557 error = 0; 11558 } else { 11559 error = 1; 11560 } 11561 } else { 11562 error = 2; 11563 } 11564 } 11565 11566 switch (error) { 11567 case 0: 11568 fcp_log(CE_WARN, pptr->port_dip, 11569 "!FCP: WWN 0x%08x%08x %s reset successfully", 11570 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11571 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11572 break; 11573 11574 case 1: 11575 fcp_log(CE_WARN, pptr->port_dip, 11576 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11577 " response code=%x", 11578 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11579 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11580 rsp_info->rsp_code); 11581 break; 11582 11583 case 2: 11584 fcp_log(CE_WARN, pptr->port_dip, 11585 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11586 " Bad FCP response values: rsvd1=%x," 11587 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11588 " rsplen=%x, senselen=%x", 11589 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11590 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11591 rsp->reserved_0, rsp->reserved_1, 11592 rsp->fcp_u.fcp_status.reserved_0, 11593 rsp->fcp_u.fcp_status.reserved_1, 11594 rsp->fcp_response_len, rsp->fcp_sense_len); 11595 break; 11596 11597 default: 11598 fcp_log(CE_WARN, pptr->port_dip, 11599 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11600 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11601 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11602 break; 11603 } 11604 } 11605 scsi_destroy_pkt(pkt); 11606 11607 if (rval == FC_FAILURE) { 11608 mutex_enter(&ptgt->tgt_mutex); 11609 if (level == RESET_TARGET) { 11610 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11611 } else { 11612 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11613 } 11614 mutex_exit(&ptgt->tgt_mutex); 11615 kmem_free(p, sizeof (struct fcp_reset_elem)); 11616 return (rval); 11617 } 11618 11619 mutex_enter(&pptr->port_mutex); 11620 if (level == RESET_TARGET) { 11621 p->tgt = ptgt; 11622 p->lun = NULL; 11623 } else { 11624 p->tgt = NULL; 11625 p->lun = plun; 11626 } 11627 p->tgt = ptgt; 11628 p->tgt_cnt = tgt_cnt; 11629 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11630 p->next = pptr->port_reset_list; 11631 pptr->port_reset_list = p; 11632 11633 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11634 fcp_trace, FCP_BUF_LEVEL_3, 0, 11635 "Notify ssd of the reset to reinstate the reservations"); 11636 11637 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11638 &pptr->port_reset_notify_listf); 11639 11640 mutex_exit(&pptr->port_mutex); 11641 11642 return (rval); 11643 } 11644 11645 11646 /* 11647 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11648 * SCSI capabilities 11649 */ 11650 /* ARGSUSED */ 11651 static int 11652 fcp_commoncap(struct scsi_address *ap, char *cap, 11653 int val, int tgtonly, int doset) 11654 { 11655 struct fcp_port *pptr = ADDR2FCP(ap); 11656 struct fcp_lun *plun = ADDR2LUN(ap); 11657 struct fcp_tgt *ptgt = plun->lun_tgt; 11658 int cidx; 11659 int rval = FALSE; 11660 11661 if (cap == (char *)0) { 11662 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11663 fcp_trace, FCP_BUF_LEVEL_3, 0, 11664 "fcp_commoncap: invalid arg"); 11665 return (rval); 11666 } 11667 11668 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11669 return (UNDEFINED); 11670 } 11671 11672 /* 11673 * Process setcap request. 11674 */ 11675 if (doset) { 11676 /* 11677 * At present, we can only set binary (0/1) values 11678 */ 11679 switch (cidx) { 11680 case SCSI_CAP_ARQ: 11681 if (val == 0) { 11682 rval = FALSE; 11683 } else { 11684 rval = TRUE; 11685 } 11686 break; 11687 11688 case SCSI_CAP_LUN_RESET: 11689 if (val) { 11690 plun->lun_cap |= FCP_LUN_CAP_RESET; 11691 } else { 11692 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11693 } 11694 rval = TRUE; 11695 break; 11696 11697 case SCSI_CAP_SECTOR_SIZE: 11698 rval = TRUE; 11699 break; 11700 default: 11701 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11702 fcp_trace, FCP_BUF_LEVEL_4, 0, 11703 "fcp_setcap: unsupported %d", cidx); 11704 rval = UNDEFINED; 11705 break; 11706 } 11707 11708 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11709 fcp_trace, FCP_BUF_LEVEL_5, 0, 11710 "set cap: cap=%s, val/tgtonly/doset/rval = " 11711 "0x%x/0x%x/0x%x/%d", 11712 cap, val, tgtonly, doset, rval); 11713 11714 } else { 11715 /* 11716 * Process getcap request. 11717 */ 11718 switch (cidx) { 11719 case SCSI_CAP_DMA_MAX: 11720 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11721 11722 /* 11723 * Need to make an adjustment qlc is uint_t 64 11724 * st is int, so we will make the adjustment here 11725 * being as nobody wants to touch this. 11726 * It still leaves the max single block length 11727 * of 2 gig. This should last . 11728 */ 11729 11730 if (rval == -1) { 11731 rval = MAX_INT_DMA; 11732 } 11733 11734 break; 11735 11736 case SCSI_CAP_INITIATOR_ID: 11737 rval = pptr->port_id; 11738 break; 11739 11740 case SCSI_CAP_ARQ: 11741 case SCSI_CAP_RESET_NOTIFICATION: 11742 case SCSI_CAP_TAGGED_QING: 11743 rval = TRUE; 11744 break; 11745 11746 case SCSI_CAP_SCSI_VERSION: 11747 rval = 3; 11748 break; 11749 11750 case SCSI_CAP_INTERCONNECT_TYPE: 11751 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11752 (ptgt->tgt_hard_addr == 0)) { 11753 rval = INTERCONNECT_FABRIC; 11754 } else { 11755 rval = INTERCONNECT_FIBRE; 11756 } 11757 break; 11758 11759 case SCSI_CAP_LUN_RESET: 11760 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11761 TRUE : FALSE; 11762 break; 11763 11764 default: 11765 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11766 fcp_trace, FCP_BUF_LEVEL_4, 0, 11767 "fcp_getcap: unsupported %d", cidx); 11768 rval = UNDEFINED; 11769 break; 11770 } 11771 11772 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11773 fcp_trace, FCP_BUF_LEVEL_8, 0, 11774 "get cap: cap=%s, val/tgtonly/doset/rval = " 11775 "0x%x/0x%x/0x%x/%d", 11776 cap, val, tgtonly, doset, rval); 11777 } 11778 11779 return (rval); 11780 } 11781 11782 /* 11783 * called by the transport to get the port-wwn and lun 11784 * properties of this device, and to create a "name" based on them 11785 * 11786 * these properties don't exist on sun4m 11787 * 11788 * return 1 for success else return 0 11789 */ 11790 /* ARGSUSED */ 11791 static int 11792 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11793 { 11794 int i; 11795 int *lun; 11796 int numChars; 11797 uint_t nlun; 11798 uint_t count; 11799 uint_t nbytes; 11800 uchar_t *bytes; 11801 uint16_t lun_num; 11802 uint32_t tgt_id; 11803 char **conf_wwn; 11804 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11805 uchar_t barray[FC_WWN_SIZE]; 11806 dev_info_t *tgt_dip; 11807 struct fcp_tgt *ptgt; 11808 struct fcp_port *pptr; 11809 struct fcp_lun *plun; 11810 11811 ASSERT(sd != NULL); 11812 ASSERT(name != NULL); 11813 11814 tgt_dip = sd->sd_dev; 11815 pptr = ddi_get_soft_state(fcp_softstate, 11816 ddi_get_instance(ddi_get_parent(tgt_dip))); 11817 if (pptr == NULL) { 11818 return (0); 11819 } 11820 11821 ASSERT(tgt_dip != NULL); 11822 11823 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11824 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11825 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11826 name[0] = '\0'; 11827 return (0); 11828 } 11829 11830 if (nlun == 0) { 11831 ddi_prop_free(lun); 11832 return (0); 11833 } 11834 11835 lun_num = lun[0]; 11836 ddi_prop_free(lun); 11837 11838 /* 11839 * Lookup for .conf WWN property 11840 */ 11841 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 11842 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 11843 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 11844 ASSERT(count >= 1); 11845 11846 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 11847 ddi_prop_free(conf_wwn); 11848 mutex_enter(&pptr->port_mutex); 11849 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 11850 mutex_exit(&pptr->port_mutex); 11851 return (0); 11852 } 11853 ptgt = plun->lun_tgt; 11854 mutex_exit(&pptr->port_mutex); 11855 11856 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 11857 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 11858 11859 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 11860 ptgt->tgt_hard_addr != 0) { 11861 tgt_id = (uint32_t)fcp_alpa_to_switch[ 11862 ptgt->tgt_hard_addr]; 11863 } else { 11864 tgt_id = ptgt->tgt_d_id; 11865 } 11866 11867 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 11868 TARGET_PROP, tgt_id); 11869 } 11870 11871 /* get the our port-wwn property */ 11872 bytes = NULL; 11873 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 11874 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 11875 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 11876 if (bytes != NULL) { 11877 ddi_prop_free(bytes); 11878 } 11879 return (0); 11880 } 11881 11882 for (i = 0; i < FC_WWN_SIZE; i++) { 11883 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 11884 } 11885 11886 /* Stick in the address of the form "wWWN,LUN" */ 11887 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 11888 11889 ASSERT(numChars < len); 11890 if (numChars >= len) { 11891 fcp_log(CE_WARN, pptr->port_dip, 11892 "!fcp_scsi_get_name: " 11893 "name parameter length too small, it needs to be %d", 11894 numChars+1); 11895 } 11896 11897 ddi_prop_free(bytes); 11898 11899 return (1); 11900 } 11901 11902 11903 /* 11904 * called by the transport to get the SCSI target id value, returning 11905 * it in "name" 11906 * 11907 * this isn't needed/used on sun4m 11908 * 11909 * return 1 for success else return 0 11910 */ 11911 /* ARGSUSED */ 11912 static int 11913 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 11914 { 11915 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 11916 struct fcp_tgt *ptgt; 11917 int numChars; 11918 11919 if (plun == NULL) { 11920 return (0); 11921 } 11922 11923 if ((ptgt = plun->lun_tgt) == NULL) { 11924 return (0); 11925 } 11926 11927 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 11928 11929 ASSERT(numChars < len); 11930 if (numChars >= len) { 11931 fcp_log(CE_WARN, NULL, 11932 "!fcp_scsi_get_bus_addr: " 11933 "name parameter length too small, it needs to be %d", 11934 numChars+1); 11935 } 11936 11937 return (1); 11938 } 11939 11940 11941 /* 11942 * called internally to reset the link where the specified port lives 11943 */ 11944 static int 11945 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 11946 { 11947 la_wwn_t wwn; 11948 struct fcp_lun *plun; 11949 struct fcp_tgt *ptgt; 11950 11951 /* disable restart of lip if we're suspended */ 11952 mutex_enter(&pptr->port_mutex); 11953 11954 if (pptr->port_state & (FCP_STATE_SUSPENDED | 11955 FCP_STATE_POWER_DOWN)) { 11956 mutex_exit(&pptr->port_mutex); 11957 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11958 fcp_trace, FCP_BUF_LEVEL_2, 0, 11959 "fcp_linkreset, fcp%d: link reset " 11960 "disabled due to DDI_SUSPEND", 11961 ddi_get_instance(pptr->port_dip)); 11962 return (FC_FAILURE); 11963 } 11964 11965 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 11966 mutex_exit(&pptr->port_mutex); 11967 return (FC_SUCCESS); 11968 } 11969 11970 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11971 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 11972 11973 /* 11974 * If ap == NULL assume local link reset. 11975 */ 11976 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 11977 plun = ADDR2LUN(ap); 11978 ptgt = plun->lun_tgt; 11979 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 11980 } else { 11981 bzero((caddr_t)&wwn, sizeof (wwn)); 11982 } 11983 mutex_exit(&pptr->port_mutex); 11984 11985 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 11986 } 11987 11988 11989 /* 11990 * called from fcp_port_attach() to resume a port 11991 * return DDI_* success/failure status 11992 * acquires and releases the global mutex 11993 * acquires and releases the port mutex 11994 */ 11995 /*ARGSUSED*/ 11996 11997 static int 11998 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 11999 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12000 { 12001 int res = DDI_FAILURE; /* default result */ 12002 struct fcp_port *pptr; /* port state ptr */ 12003 uint32_t alloc_cnt; 12004 uint32_t max_cnt; 12005 fc_portmap_t *tmp_list = NULL; 12006 12007 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12008 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12009 instance); 12010 12011 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12012 cmn_err(CE_WARN, "fcp: bad soft state"); 12013 return (res); 12014 } 12015 12016 mutex_enter(&pptr->port_mutex); 12017 switch (cmd) { 12018 case FC_CMD_RESUME: 12019 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12020 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12021 break; 12022 12023 case FC_CMD_POWER_UP: 12024 /* 12025 * If the port is DDI_SUSPENded, defer rediscovery 12026 * until DDI_RESUME occurs 12027 */ 12028 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12029 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12030 mutex_exit(&pptr->port_mutex); 12031 return (DDI_SUCCESS); 12032 } 12033 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12034 } 12035 pptr->port_id = s_id; 12036 pptr->port_state = FCP_STATE_INIT; 12037 mutex_exit(&pptr->port_mutex); 12038 12039 /* 12040 * Make a copy of ulp_port_info as fctl allocates 12041 * a temp struct. 12042 */ 12043 (void) fcp_cp_pinfo(pptr, pinfo); 12044 12045 mutex_enter(&fcp_global_mutex); 12046 if (fcp_watchdog_init++ == 0) { 12047 fcp_watchdog_tick = fcp_watchdog_timeout * 12048 drv_usectohz(1000000); 12049 fcp_watchdog_id = timeout(fcp_watch, 12050 NULL, fcp_watchdog_tick); 12051 } 12052 mutex_exit(&fcp_global_mutex); 12053 12054 /* 12055 * Handle various topologies and link states. 12056 */ 12057 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12058 case FC_STATE_OFFLINE: 12059 /* 12060 * Wait for ONLINE, at which time a state 12061 * change will cause a statec_callback 12062 */ 12063 res = DDI_SUCCESS; 12064 break; 12065 12066 case FC_STATE_ONLINE: 12067 12068 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12069 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12070 res = DDI_SUCCESS; 12071 break; 12072 } 12073 12074 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12075 !fcp_enable_auto_configuration) { 12076 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12077 if (tmp_list == NULL) { 12078 if (!alloc_cnt) { 12079 res = DDI_SUCCESS; 12080 } 12081 break; 12082 } 12083 max_cnt = alloc_cnt; 12084 } else { 12085 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12086 12087 alloc_cnt = FCP_MAX_DEVICES; 12088 12089 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12090 (sizeof (fc_portmap_t)) * alloc_cnt, 12091 KM_NOSLEEP)) == NULL) { 12092 fcp_log(CE_WARN, pptr->port_dip, 12093 "!fcp%d: failed to allocate portmap", 12094 instance); 12095 break; 12096 } 12097 12098 max_cnt = alloc_cnt; 12099 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12100 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12101 FC_SUCCESS) { 12102 caddr_t msg; 12103 12104 (void) fc_ulp_error(res, &msg); 12105 12106 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12107 fcp_trace, FCP_BUF_LEVEL_2, 0, 12108 "resume failed getportmap: reason=0x%x", 12109 res); 12110 12111 fcp_log(CE_WARN, pptr->port_dip, 12112 "!failed to get port map : %s", msg); 12113 break; 12114 } 12115 if (max_cnt > alloc_cnt) { 12116 alloc_cnt = max_cnt; 12117 } 12118 } 12119 12120 /* 12121 * do the SCSI device discovery and create 12122 * the devinfos 12123 */ 12124 fcp_statec_callback(ulph, pptr->port_fp_handle, 12125 pptr->port_phys_state, pptr->port_topology, tmp_list, 12126 max_cnt, pptr->port_id); 12127 12128 res = DDI_SUCCESS; 12129 break; 12130 12131 default: 12132 fcp_log(CE_WARN, pptr->port_dip, 12133 "!fcp%d: invalid port state at attach=0x%x", 12134 instance, pptr->port_phys_state); 12135 12136 mutex_enter(&pptr->port_mutex); 12137 pptr->port_phys_state = FCP_STATE_OFFLINE; 12138 mutex_exit(&pptr->port_mutex); 12139 res = DDI_SUCCESS; 12140 12141 break; 12142 } 12143 12144 if (tmp_list != NULL) { 12145 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12146 } 12147 12148 return (res); 12149 } 12150 12151 12152 static void 12153 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12154 { 12155 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12156 pptr->port_dip = pinfo->port_dip; 12157 pptr->port_fp_handle = pinfo->port_handle; 12158 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12159 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12160 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12161 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12162 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12163 pptr->port_max_exch = pinfo->port_fca_max_exch; 12164 pptr->port_phys_state = pinfo->port_state; 12165 pptr->port_topology = pinfo->port_flags; 12166 pptr->port_reset_action = pinfo->port_reset_action; 12167 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12168 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12169 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12170 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12171 } 12172 12173 /* 12174 * If the elements wait field is set to 1 then 12175 * another thread is waiting for the operation to complete. Once 12176 * it is complete, the waiting thread is signaled and the element is 12177 * freed by the waiting thread. If the elements wait field is set to 0 12178 * the element is freed. 12179 */ 12180 static void 12181 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12182 { 12183 ASSERT(elem != NULL); 12184 mutex_enter(&elem->mutex); 12185 elem->result = result; 12186 if (elem->wait) { 12187 elem->wait = 0; 12188 cv_signal(&elem->cv); 12189 mutex_exit(&elem->mutex); 12190 } else { 12191 mutex_exit(&elem->mutex); 12192 cv_destroy(&elem->cv); 12193 mutex_destroy(&elem->mutex); 12194 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12195 } 12196 } 12197 12198 /* 12199 * This function is invoked from the taskq thread to allocate 12200 * devinfo nodes and to online/offline them. 12201 */ 12202 static void 12203 fcp_hp_task(void *arg) 12204 { 12205 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12206 struct fcp_lun *plun = elem->lun; 12207 struct fcp_port *pptr = elem->port; 12208 int result; 12209 12210 ASSERT(elem->what == FCP_ONLINE || 12211 elem->what == FCP_OFFLINE || 12212 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12213 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12214 12215 mutex_enter(&pptr->port_mutex); 12216 mutex_enter(&plun->lun_mutex); 12217 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12218 plun->lun_event_count != elem->event_cnt) || 12219 pptr->port_state & (FCP_STATE_SUSPENDED | 12220 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12221 mutex_exit(&plun->lun_mutex); 12222 mutex_exit(&pptr->port_mutex); 12223 fcp_process_elem(elem, NDI_FAILURE); 12224 return; 12225 } 12226 mutex_exit(&plun->lun_mutex); 12227 mutex_exit(&pptr->port_mutex); 12228 12229 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12230 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12231 fcp_process_elem(elem, result); 12232 } 12233 12234 12235 static child_info_t * 12236 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12237 int tcount) 12238 { 12239 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12240 12241 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12242 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12243 12244 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12245 /* 12246 * Child has not been created yet. Create the child device 12247 * based on the per-Lun flags. 12248 */ 12249 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12250 plun->lun_cip = 12251 CIP(fcp_create_dip(plun, lcount, tcount)); 12252 plun->lun_mpxio = 0; 12253 } else { 12254 plun->lun_cip = 12255 CIP(fcp_create_pip(plun, lcount, tcount)); 12256 plun->lun_mpxio = 1; 12257 } 12258 } else { 12259 plun->lun_cip = cip; 12260 } 12261 12262 return (plun->lun_cip); 12263 } 12264 12265 12266 static int 12267 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12268 { 12269 int rval = FC_FAILURE; 12270 dev_info_t *pdip; 12271 struct dev_info *dip; 12272 int circular; 12273 12274 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12275 12276 pdip = plun->lun_tgt->tgt_port->port_dip; 12277 12278 if (plun->lun_cip == NULL) { 12279 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12280 fcp_trace, FCP_BUF_LEVEL_3, 0, 12281 "fcp_is_dip_present: plun->lun_cip is NULL: " 12282 "plun: %p lun state: %x num: %d target state: %x", 12283 plun, plun->lun_state, plun->lun_num, 12284 plun->lun_tgt->tgt_port->port_state); 12285 return (rval); 12286 } 12287 ndi_devi_enter(pdip, &circular); 12288 dip = DEVI(pdip)->devi_child; 12289 while (dip) { 12290 if (dip == DEVI(cdip)) { 12291 rval = FC_SUCCESS; 12292 break; 12293 } 12294 dip = dip->devi_sibling; 12295 } 12296 ndi_devi_exit(pdip, circular); 12297 return (rval); 12298 } 12299 12300 static int 12301 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12302 { 12303 int rval = FC_FAILURE; 12304 12305 ASSERT(plun != NULL); 12306 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12307 12308 if (plun->lun_mpxio == 0) { 12309 rval = fcp_is_dip_present(plun, DIP(cip)); 12310 } else { 12311 rval = fcp_is_pip_present(plun, PIP(cip)); 12312 } 12313 12314 return (rval); 12315 } 12316 12317 /* 12318 * Function: fcp_create_dip 12319 * 12320 * Description: Creates a dev_info_t structure for the LUN specified by the 12321 * caller. 12322 * 12323 * Argument: plun Lun structure 12324 * link_cnt Link state count. 12325 * tgt_cnt Target state change count. 12326 * 12327 * Return Value: NULL if it failed 12328 * dev_info_t structure address if it succeeded 12329 * 12330 * Context: Kernel context 12331 */ 12332 static dev_info_t * 12333 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12334 { 12335 int failure = 0; 12336 uint32_t tgt_id; 12337 uint64_t sam_lun; 12338 struct fcp_tgt *ptgt = plun->lun_tgt; 12339 struct fcp_port *pptr = ptgt->tgt_port; 12340 dev_info_t *pdip = pptr->port_dip; 12341 dev_info_t *cdip = NULL; 12342 dev_info_t *old_dip = DIP(plun->lun_cip); 12343 char *nname = NULL; 12344 char **compatible = NULL; 12345 int ncompatible; 12346 char *scsi_binding_set; 12347 char t_pwwn[17]; 12348 12349 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12350 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12351 12352 /* get the 'scsi-binding-set' property */ 12353 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12354 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12355 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12356 scsi_binding_set = NULL; 12357 } 12358 12359 /* determine the node name and compatible */ 12360 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12361 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12362 if (scsi_binding_set) { 12363 ddi_prop_free(scsi_binding_set); 12364 } 12365 12366 if (nname == NULL) { 12367 #ifdef DEBUG 12368 cmn_err(CE_WARN, "%s%d: no driver for " 12369 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12370 " compatible: %s", 12371 ddi_driver_name(pdip), ddi_get_instance(pdip), 12372 ptgt->tgt_port_wwn.raw_wwn[0], 12373 ptgt->tgt_port_wwn.raw_wwn[1], 12374 ptgt->tgt_port_wwn.raw_wwn[2], 12375 ptgt->tgt_port_wwn.raw_wwn[3], 12376 ptgt->tgt_port_wwn.raw_wwn[4], 12377 ptgt->tgt_port_wwn.raw_wwn[5], 12378 ptgt->tgt_port_wwn.raw_wwn[6], 12379 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12380 *compatible); 12381 #endif /* DEBUG */ 12382 failure++; 12383 goto end_of_fcp_create_dip; 12384 } 12385 12386 cdip = fcp_find_existing_dip(plun, pdip, nname); 12387 12388 /* 12389 * if the old_dip does not match the cdip, that means there is 12390 * some property change. since we'll be using the cdip, we need 12391 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12392 * then the dtype for the device has been updated. Offline the 12393 * the old device and create a new device with the new device type 12394 * Refer to bug: 4764752 12395 */ 12396 if (old_dip && (cdip != old_dip || 12397 plun->lun_state & FCP_LUN_CHANGED)) { 12398 plun->lun_state &= ~(FCP_LUN_INIT); 12399 mutex_exit(&plun->lun_mutex); 12400 mutex_exit(&pptr->port_mutex); 12401 12402 mutex_enter(&ptgt->tgt_mutex); 12403 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12404 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12405 mutex_exit(&ptgt->tgt_mutex); 12406 12407 #ifdef DEBUG 12408 if (cdip != NULL) { 12409 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12410 fcp_trace, FCP_BUF_LEVEL_2, 0, 12411 "Old dip=%p; New dip=%p don't match", old_dip, 12412 cdip); 12413 } else { 12414 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12415 fcp_trace, FCP_BUF_LEVEL_2, 0, 12416 "Old dip=%p; New dip=NULL don't match", old_dip); 12417 } 12418 #endif 12419 12420 mutex_enter(&pptr->port_mutex); 12421 mutex_enter(&plun->lun_mutex); 12422 } 12423 12424 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12425 plun->lun_state &= ~(FCP_LUN_CHANGED); 12426 if (ndi_devi_alloc(pptr->port_dip, nname, 12427 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12428 failure++; 12429 goto end_of_fcp_create_dip; 12430 } 12431 } 12432 12433 /* 12434 * Previously all the properties for the devinfo were destroyed here 12435 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12436 * the devid property (and other properties established by the target 12437 * driver or framework) which the code does not always recreate, this 12438 * call was removed. 12439 * This opens a theoretical possibility that we may return with a 12440 * stale devid on the node if the scsi entity behind the fibre channel 12441 * lun has changed. 12442 */ 12443 12444 /* decorate the node with compatible */ 12445 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12446 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12447 failure++; 12448 goto end_of_fcp_create_dip; 12449 } 12450 12451 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12452 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12453 failure++; 12454 goto end_of_fcp_create_dip; 12455 } 12456 12457 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12458 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12459 failure++; 12460 goto end_of_fcp_create_dip; 12461 } 12462 12463 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12464 t_pwwn[16] = '\0'; 12465 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12466 != DDI_PROP_SUCCESS) { 12467 failure++; 12468 goto end_of_fcp_create_dip; 12469 } 12470 12471 /* 12472 * If there is no hard address - We might have to deal with 12473 * that by using WWN - Having said that it is important to 12474 * recognize this problem early so ssd can be informed of 12475 * the right interconnect type. 12476 */ 12477 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12478 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12479 } else { 12480 tgt_id = ptgt->tgt_d_id; 12481 } 12482 12483 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12484 tgt_id) != DDI_PROP_SUCCESS) { 12485 failure++; 12486 goto end_of_fcp_create_dip; 12487 } 12488 12489 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12490 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12491 failure++; 12492 goto end_of_fcp_create_dip; 12493 } 12494 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12495 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12496 sam_lun) != DDI_PROP_SUCCESS) { 12497 failure++; 12498 goto end_of_fcp_create_dip; 12499 } 12500 12501 end_of_fcp_create_dip: 12502 scsi_hba_nodename_compatible_free(nname, compatible); 12503 12504 if (cdip != NULL && failure) { 12505 (void) ndi_prop_remove_all(cdip); 12506 (void) ndi_devi_free(cdip); 12507 cdip = NULL; 12508 } 12509 12510 return (cdip); 12511 } 12512 12513 /* 12514 * Function: fcp_create_pip 12515 * 12516 * Description: Creates a Path Id for the LUN specified by the caller. 12517 * 12518 * Argument: plun Lun structure 12519 * link_cnt Link state count. 12520 * tgt_cnt Target state count. 12521 * 12522 * Return Value: NULL if it failed 12523 * mdi_pathinfo_t structure address if it succeeded 12524 * 12525 * Context: Kernel context 12526 */ 12527 static mdi_pathinfo_t * 12528 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12529 { 12530 int i; 12531 char buf[MAXNAMELEN]; 12532 char uaddr[MAXNAMELEN]; 12533 int failure = 0; 12534 uint32_t tgt_id; 12535 uint64_t sam_lun; 12536 struct fcp_tgt *ptgt = plun->lun_tgt; 12537 struct fcp_port *pptr = ptgt->tgt_port; 12538 dev_info_t *pdip = pptr->port_dip; 12539 mdi_pathinfo_t *pip = NULL; 12540 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12541 char *nname = NULL; 12542 char **compatible = NULL; 12543 int ncompatible; 12544 char *scsi_binding_set; 12545 char t_pwwn[17]; 12546 12547 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12548 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12549 12550 scsi_binding_set = "vhci"; 12551 12552 /* determine the node name and compatible */ 12553 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12554 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12555 12556 if (nname == NULL) { 12557 #ifdef DEBUG 12558 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12559 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12560 " compatible: %s", 12561 ddi_driver_name(pdip), ddi_get_instance(pdip), 12562 ptgt->tgt_port_wwn.raw_wwn[0], 12563 ptgt->tgt_port_wwn.raw_wwn[1], 12564 ptgt->tgt_port_wwn.raw_wwn[2], 12565 ptgt->tgt_port_wwn.raw_wwn[3], 12566 ptgt->tgt_port_wwn.raw_wwn[4], 12567 ptgt->tgt_port_wwn.raw_wwn[5], 12568 ptgt->tgt_port_wwn.raw_wwn[6], 12569 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12570 *compatible); 12571 #endif /* DEBUG */ 12572 failure++; 12573 goto end_of_fcp_create_pip; 12574 } 12575 12576 pip = fcp_find_existing_pip(plun, pdip); 12577 12578 /* 12579 * if the old_dip does not match the cdip, that means there is 12580 * some property change. since we'll be using the cdip, we need 12581 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12582 * then the dtype for the device has been updated. Offline the 12583 * the old device and create a new device with the new device type 12584 * Refer to bug: 4764752 12585 */ 12586 if (old_pip && (pip != old_pip || 12587 plun->lun_state & FCP_LUN_CHANGED)) { 12588 plun->lun_state &= ~(FCP_LUN_INIT); 12589 mutex_exit(&plun->lun_mutex); 12590 mutex_exit(&pptr->port_mutex); 12591 12592 mutex_enter(&ptgt->tgt_mutex); 12593 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12594 FCP_OFFLINE, lcount, tcount, 12595 NDI_DEVI_REMOVE, 0); 12596 mutex_exit(&ptgt->tgt_mutex); 12597 12598 if (pip != NULL) { 12599 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12600 fcp_trace, FCP_BUF_LEVEL_2, 0, 12601 "Old pip=%p; New pip=%p don't match", 12602 old_pip, pip); 12603 } else { 12604 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12605 fcp_trace, FCP_BUF_LEVEL_2, 0, 12606 "Old pip=%p; New pip=NULL don't match", 12607 old_pip); 12608 } 12609 12610 mutex_enter(&pptr->port_mutex); 12611 mutex_enter(&plun->lun_mutex); 12612 } 12613 12614 /* 12615 * Since FC_WWN_SIZE is 8 bytes and its not like the 12616 * lun_guid_size which is dependent on the target, I don't 12617 * believe the same trancation happens here UNLESS the standards 12618 * change the FC_WWN_SIZE value to something larger than 12619 * MAXNAMELEN(currently 255 bytes). 12620 */ 12621 12622 for (i = 0; i < FC_WWN_SIZE; i++) { 12623 (void) sprintf(&buf[i << 1], "%02x", 12624 ptgt->tgt_port_wwn.raw_wwn[i]); 12625 } 12626 12627 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12628 buf, plun->lun_num); 12629 12630 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12631 /* 12632 * Release the locks before calling into 12633 * mdi_pi_alloc_compatible() since this can result in a 12634 * callback into fcp which can result in a deadlock 12635 * (see bug # 4870272). 12636 * 12637 * Basically, what we are trying to avoid is the scenario where 12638 * one thread does ndi_devi_enter() and tries to grab 12639 * fcp_mutex and another does it the other way round. 12640 * 12641 * But before we do that, make sure that nobody releases the 12642 * port in the meantime. We can do this by setting a flag. 12643 */ 12644 plun->lun_state &= ~(FCP_LUN_CHANGED); 12645 pptr->port_state |= FCP_STATE_IN_MDI; 12646 mutex_exit(&plun->lun_mutex); 12647 mutex_exit(&pptr->port_mutex); 12648 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12649 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12650 fcp_log(CE_WARN, pptr->port_dip, 12651 "!path alloc failed:0x%x", plun); 12652 mutex_enter(&pptr->port_mutex); 12653 mutex_enter(&plun->lun_mutex); 12654 pptr->port_state &= ~FCP_STATE_IN_MDI; 12655 failure++; 12656 goto end_of_fcp_create_pip; 12657 } 12658 mutex_enter(&pptr->port_mutex); 12659 mutex_enter(&plun->lun_mutex); 12660 pptr->port_state &= ~FCP_STATE_IN_MDI; 12661 } else { 12662 (void) mdi_prop_remove(pip, NULL); 12663 } 12664 12665 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12666 12667 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12668 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12669 != DDI_PROP_SUCCESS) { 12670 failure++; 12671 goto end_of_fcp_create_pip; 12672 } 12673 12674 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12675 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12676 != DDI_PROP_SUCCESS) { 12677 failure++; 12678 goto end_of_fcp_create_pip; 12679 } 12680 12681 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12682 t_pwwn[16] = '\0'; 12683 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12684 != DDI_PROP_SUCCESS) { 12685 failure++; 12686 goto end_of_fcp_create_pip; 12687 } 12688 12689 /* 12690 * If there is no hard address - We might have to deal with 12691 * that by using WWN - Having said that it is important to 12692 * recognize this problem early so ssd can be informed of 12693 * the right interconnect type. 12694 */ 12695 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12696 ptgt->tgt_hard_addr != 0) { 12697 tgt_id = (uint32_t) 12698 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12699 } else { 12700 tgt_id = ptgt->tgt_d_id; 12701 } 12702 12703 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12704 != DDI_PROP_SUCCESS) { 12705 failure++; 12706 goto end_of_fcp_create_pip; 12707 } 12708 12709 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12710 != DDI_PROP_SUCCESS) { 12711 failure++; 12712 goto end_of_fcp_create_pip; 12713 } 12714 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12715 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12716 != DDI_PROP_SUCCESS) { 12717 failure++; 12718 goto end_of_fcp_create_pip; 12719 } 12720 12721 end_of_fcp_create_pip: 12722 scsi_hba_nodename_compatible_free(nname, compatible); 12723 12724 if (pip != NULL && failure) { 12725 (void) mdi_prop_remove(pip, NULL); 12726 mutex_exit(&plun->lun_mutex); 12727 mutex_exit(&pptr->port_mutex); 12728 (void) mdi_pi_free(pip, 0); 12729 mutex_enter(&pptr->port_mutex); 12730 mutex_enter(&plun->lun_mutex); 12731 pip = NULL; 12732 } 12733 12734 return (pip); 12735 } 12736 12737 static dev_info_t * 12738 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12739 { 12740 uint_t nbytes; 12741 uchar_t *bytes; 12742 uint_t nwords; 12743 uint32_t tgt_id; 12744 int *words; 12745 dev_info_t *cdip; 12746 dev_info_t *ndip; 12747 struct fcp_tgt *ptgt = plun->lun_tgt; 12748 struct fcp_port *pptr = ptgt->tgt_port; 12749 int circular; 12750 12751 ndi_devi_enter(pdip, &circular); 12752 12753 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12754 while ((cdip = ndip) != NULL) { 12755 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12756 12757 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12758 continue; 12759 } 12760 12761 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12762 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12763 &nbytes) != DDI_PROP_SUCCESS) { 12764 continue; 12765 } 12766 12767 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12768 if (bytes != NULL) { 12769 ddi_prop_free(bytes); 12770 } 12771 continue; 12772 } 12773 ASSERT(bytes != NULL); 12774 12775 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12776 ddi_prop_free(bytes); 12777 continue; 12778 } 12779 12780 ddi_prop_free(bytes); 12781 12782 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12783 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12784 &nbytes) != DDI_PROP_SUCCESS) { 12785 continue; 12786 } 12787 12788 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12789 if (bytes != NULL) { 12790 ddi_prop_free(bytes); 12791 } 12792 continue; 12793 } 12794 ASSERT(bytes != NULL); 12795 12796 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12797 ddi_prop_free(bytes); 12798 continue; 12799 } 12800 12801 ddi_prop_free(bytes); 12802 12803 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12804 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12805 &nwords) != DDI_PROP_SUCCESS) { 12806 continue; 12807 } 12808 12809 if (nwords != 1 || words == NULL) { 12810 if (words != NULL) { 12811 ddi_prop_free(words); 12812 } 12813 continue; 12814 } 12815 ASSERT(words != NULL); 12816 12817 /* 12818 * If there is no hard address - We might have to deal with 12819 * that by using WWN - Having said that it is important to 12820 * recognize this problem early so ssd can be informed of 12821 * the right interconnect type. 12822 */ 12823 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12824 ptgt->tgt_hard_addr != 0) { 12825 tgt_id = 12826 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12827 } else { 12828 tgt_id = ptgt->tgt_d_id; 12829 } 12830 12831 if (tgt_id != (uint32_t)*words) { 12832 ddi_prop_free(words); 12833 continue; 12834 } 12835 ddi_prop_free(words); 12836 12837 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12838 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 12839 &nwords) != DDI_PROP_SUCCESS) { 12840 continue; 12841 } 12842 12843 if (nwords != 1 || words == NULL) { 12844 if (words != NULL) { 12845 ddi_prop_free(words); 12846 } 12847 continue; 12848 } 12849 ASSERT(words != NULL); 12850 12851 if (plun->lun_num == (uint16_t)*words) { 12852 ddi_prop_free(words); 12853 break; 12854 } 12855 ddi_prop_free(words); 12856 } 12857 ndi_devi_exit(pdip, circular); 12858 12859 return (cdip); 12860 } 12861 12862 12863 static int 12864 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 12865 { 12866 dev_info_t *pdip; 12867 char buf[MAXNAMELEN]; 12868 char uaddr[MAXNAMELEN]; 12869 int rval = FC_FAILURE; 12870 12871 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12872 12873 pdip = plun->lun_tgt->tgt_port->port_dip; 12874 12875 /* 12876 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 12877 * non-NULL even when the LUN is not there as in the case when a LUN is 12878 * configured and then deleted on the device end (for T3/T4 case). In 12879 * such cases, pip will be NULL. 12880 * 12881 * If the device generates an RSCN, it will end up getting offlined when 12882 * it disappeared and a new LUN will get created when it is rediscovered 12883 * on the device. If we check for lun_cip here, the LUN will not end 12884 * up getting onlined since this function will end up returning a 12885 * FC_SUCCESS. 12886 * 12887 * The behavior is different on other devices. For instance, on a HDS, 12888 * there was no RSCN generated by the device but the next I/O generated 12889 * a check condition and rediscovery got triggered that way. So, in 12890 * such cases, this path will not be exercised 12891 */ 12892 if (pip == NULL) { 12893 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12894 fcp_trace, FCP_BUF_LEVEL_4, 0, 12895 "fcp_is_pip_present: plun->lun_cip is NULL: " 12896 "plun: %p lun state: %x num: %d target state: %x", 12897 plun, plun->lun_state, plun->lun_num, 12898 plun->lun_tgt->tgt_port->port_state); 12899 return (rval); 12900 } 12901 12902 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 12903 12904 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12905 12906 if (plun->lun_old_guid) { 12907 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 12908 rval = FC_SUCCESS; 12909 } 12910 } else { 12911 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 12912 rval = FC_SUCCESS; 12913 } 12914 } 12915 return (rval); 12916 } 12917 12918 static mdi_pathinfo_t * 12919 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 12920 { 12921 char buf[MAXNAMELEN]; 12922 char uaddr[MAXNAMELEN]; 12923 mdi_pathinfo_t *pip; 12924 struct fcp_tgt *ptgt = plun->lun_tgt; 12925 struct fcp_port *pptr = ptgt->tgt_port; 12926 12927 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12928 12929 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 12930 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 12931 12932 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 12933 12934 return (pip); 12935 } 12936 12937 12938 static int 12939 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 12940 int tcount, int flags, int *circ) 12941 { 12942 int rval; 12943 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12944 struct fcp_tgt *ptgt = plun->lun_tgt; 12945 dev_info_t *cdip = NULL; 12946 12947 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12948 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12949 12950 if (plun->lun_cip == NULL) { 12951 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12952 fcp_trace, FCP_BUF_LEVEL_3, 0, 12953 "fcp_online_child: plun->lun_cip is NULL: " 12954 "plun: %p state: %x num: %d target state: %x", 12955 plun, plun->lun_state, plun->lun_num, 12956 plun->lun_tgt->tgt_port->port_state); 12957 return (NDI_FAILURE); 12958 } 12959 again: 12960 if (plun->lun_mpxio == 0) { 12961 cdip = DIP(cip); 12962 mutex_exit(&plun->lun_mutex); 12963 mutex_exit(&pptr->port_mutex); 12964 12965 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12966 fcp_trace, FCP_BUF_LEVEL_3, 0, 12967 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 12968 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 12969 12970 /* 12971 * We could check for FCP_LUN_INIT here but chances 12972 * of getting here when it's already in FCP_LUN_INIT 12973 * is rare and a duplicate ndi_devi_online wouldn't 12974 * hurt either (as the node would already have been 12975 * in CF2) 12976 */ 12977 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 12978 rval = ndi_devi_bind_driver(cdip, flags); 12979 } else { 12980 rval = ndi_devi_online(cdip, flags); 12981 } 12982 /* 12983 * We log the message into trace buffer if the device 12984 * is "ses" and into syslog for any other device 12985 * type. This is to prevent the ndi_devi_online failure 12986 * message that appears for V880/A5K ses devices. 12987 */ 12988 if (rval == NDI_SUCCESS) { 12989 mutex_enter(&ptgt->tgt_mutex); 12990 plun->lun_state |= FCP_LUN_INIT; 12991 mutex_exit(&ptgt->tgt_mutex); 12992 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 12993 fcp_log(CE_NOTE, pptr->port_dip, 12994 "!ndi_devi_online:" 12995 " failed for %s: target=%x lun=%x %x", 12996 ddi_get_name(cdip), ptgt->tgt_d_id, 12997 plun->lun_num, rval); 12998 } else { 12999 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13000 fcp_trace, FCP_BUF_LEVEL_3, 0, 13001 " !ndi_devi_online:" 13002 " failed for %s: target=%x lun=%x %x", 13003 ddi_get_name(cdip), ptgt->tgt_d_id, 13004 plun->lun_num, rval); 13005 } 13006 } else { 13007 cdip = mdi_pi_get_client(PIP(cip)); 13008 mutex_exit(&plun->lun_mutex); 13009 mutex_exit(&pptr->port_mutex); 13010 13011 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13012 fcp_trace, FCP_BUF_LEVEL_3, 0, 13013 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13014 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13015 13016 /* 13017 * Hold path and exit phci to avoid deadlock with power 13018 * management code during mdi_pi_online. 13019 */ 13020 mdi_hold_path(PIP(cip)); 13021 mdi_devi_exit_phci(pptr->port_dip, *circ); 13022 13023 rval = mdi_pi_online(PIP(cip), flags); 13024 13025 mdi_devi_enter_phci(pptr->port_dip, circ); 13026 mdi_rele_path(PIP(cip)); 13027 13028 if (rval == MDI_SUCCESS) { 13029 mutex_enter(&ptgt->tgt_mutex); 13030 plun->lun_state |= FCP_LUN_INIT; 13031 mutex_exit(&ptgt->tgt_mutex); 13032 13033 /* 13034 * Clear MPxIO path permanent disable in case 13035 * fcp hotplug dropped the offline event. 13036 */ 13037 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13038 13039 } else if (rval == MDI_NOT_SUPPORTED) { 13040 child_info_t *old_cip = cip; 13041 13042 /* 13043 * MPxIO does not support this device yet. 13044 * Enumerate in legacy mode. 13045 */ 13046 mutex_enter(&pptr->port_mutex); 13047 mutex_enter(&plun->lun_mutex); 13048 plun->lun_mpxio = 0; 13049 plun->lun_cip = NULL; 13050 cdip = fcp_create_dip(plun, lcount, tcount); 13051 plun->lun_cip = cip = CIP(cdip); 13052 if (cip == NULL) { 13053 fcp_log(CE_WARN, pptr->port_dip, 13054 "!fcp_online_child: " 13055 "Create devinfo failed for LU=%p", plun); 13056 mutex_exit(&plun->lun_mutex); 13057 13058 mutex_enter(&ptgt->tgt_mutex); 13059 plun->lun_state |= FCP_LUN_OFFLINE; 13060 mutex_exit(&ptgt->tgt_mutex); 13061 13062 mutex_exit(&pptr->port_mutex); 13063 13064 /* 13065 * free the mdi_pathinfo node 13066 */ 13067 (void) mdi_pi_free(PIP(old_cip), 0); 13068 } else { 13069 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13070 fcp_trace, FCP_BUF_LEVEL_3, 0, 13071 "fcp_online_child: creating devinfo " 13072 "node 0x%p for plun 0x%p", 13073 cip, plun); 13074 mutex_exit(&plun->lun_mutex); 13075 mutex_exit(&pptr->port_mutex); 13076 /* 13077 * free the mdi_pathinfo node 13078 */ 13079 (void) mdi_pi_free(PIP(old_cip), 0); 13080 mutex_enter(&pptr->port_mutex); 13081 mutex_enter(&plun->lun_mutex); 13082 goto again; 13083 } 13084 } else { 13085 if (cdip) { 13086 fcp_log(CE_NOTE, pptr->port_dip, 13087 "!fcp_online_child: mdi_pi_online:" 13088 " failed for %s: target=%x lun=%x %x", 13089 ddi_get_name(cdip), ptgt->tgt_d_id, 13090 plun->lun_num, rval); 13091 } 13092 } 13093 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13094 } 13095 13096 if (rval == NDI_SUCCESS) { 13097 if (cdip) { 13098 (void) ndi_event_retrieve_cookie( 13099 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13100 &fcp_insert_eid, NDI_EVENT_NOPASS); 13101 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13102 cdip, fcp_insert_eid, NULL); 13103 } 13104 } 13105 mutex_enter(&pptr->port_mutex); 13106 mutex_enter(&plun->lun_mutex); 13107 return (rval); 13108 } 13109 13110 /* ARGSUSED */ 13111 static int 13112 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13113 int tcount, int flags, int *circ) 13114 { 13115 int rval; 13116 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13117 struct fcp_tgt *ptgt = plun->lun_tgt; 13118 dev_info_t *cdip; 13119 13120 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13121 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13122 13123 if (plun->lun_cip == NULL) { 13124 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13125 fcp_trace, FCP_BUF_LEVEL_3, 0, 13126 "fcp_offline_child: plun->lun_cip is NULL: " 13127 "plun: %p lun state: %x num: %d target state: %x", 13128 plun, plun->lun_state, plun->lun_num, 13129 plun->lun_tgt->tgt_port->port_state); 13130 return (NDI_FAILURE); 13131 } 13132 13133 if (plun->lun_mpxio == 0) { 13134 cdip = DIP(cip); 13135 mutex_exit(&plun->lun_mutex); 13136 mutex_exit(&pptr->port_mutex); 13137 rval = ndi_devi_offline(DIP(cip), flags); 13138 if (rval != NDI_SUCCESS) { 13139 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13140 fcp_trace, FCP_BUF_LEVEL_3, 0, 13141 "fcp_offline_child: ndi_devi_offline failed " 13142 "rval=%x cip=%p", rval, cip); 13143 } 13144 } else { 13145 cdip = mdi_pi_get_client(PIP(cip)); 13146 mutex_exit(&plun->lun_mutex); 13147 mutex_exit(&pptr->port_mutex); 13148 13149 /* 13150 * Exit phci to avoid deadlock with power management code 13151 * during mdi_pi_offline 13152 */ 13153 mdi_hold_path(PIP(cip)); 13154 mdi_devi_exit_phci(pptr->port_dip, *circ); 13155 13156 rval = mdi_pi_offline(PIP(cip), flags); 13157 13158 mdi_devi_enter_phci(pptr->port_dip, circ); 13159 mdi_rele_path(PIP(cip)); 13160 13161 if (rval == MDI_SUCCESS) { 13162 /* 13163 * Clear MPxIO path permanent disable as the path is 13164 * already offlined. 13165 */ 13166 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13167 13168 if (flags & NDI_DEVI_REMOVE) { 13169 (void) mdi_pi_free(PIP(cip), 0); 13170 } 13171 } else { 13172 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13173 fcp_trace, FCP_BUF_LEVEL_3, 0, 13174 "fcp_offline_child: mdi_pi_offline failed " 13175 "rval=%x cip=%p", rval, cip); 13176 } 13177 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13178 } 13179 13180 mutex_enter(&ptgt->tgt_mutex); 13181 plun->lun_state &= ~FCP_LUN_INIT; 13182 mutex_exit(&ptgt->tgt_mutex); 13183 13184 mutex_enter(&pptr->port_mutex); 13185 mutex_enter(&plun->lun_mutex); 13186 13187 if (rval == NDI_SUCCESS) { 13188 cdip = NULL; 13189 if (flags & NDI_DEVI_REMOVE) { 13190 /* 13191 * If the guid of the LUN changes, lun_cip will not 13192 * equal to cip, and after offlining the LUN with the 13193 * old guid, we should keep lun_cip since it's the cip 13194 * of the LUN with the new guid. 13195 * Otherwise remove our reference to child node. 13196 */ 13197 if (plun->lun_cip == cip) { 13198 plun->lun_cip = NULL; 13199 } 13200 if (plun->lun_old_guid) { 13201 kmem_free(plun->lun_old_guid, 13202 plun->lun_old_guid_size); 13203 plun->lun_old_guid = NULL; 13204 plun->lun_old_guid_size = 0; 13205 } 13206 } 13207 } 13208 13209 if (cdip) { 13210 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13211 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13212 " target=%x lun=%x", "ndi_offline", 13213 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13214 } 13215 13216 return (rval); 13217 } 13218 13219 static void 13220 fcp_remove_child(struct fcp_lun *plun) 13221 { 13222 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13223 13224 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13225 if (plun->lun_mpxio == 0) { 13226 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13227 (void) ndi_devi_free(DIP(plun->lun_cip)); 13228 } else { 13229 mutex_exit(&plun->lun_mutex); 13230 mutex_exit(&plun->lun_tgt->tgt_mutex); 13231 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13232 FCP_TRACE(fcp_logq, 13233 plun->lun_tgt->tgt_port->port_instbuf, 13234 fcp_trace, FCP_BUF_LEVEL_3, 0, 13235 "lun=%p pip freed %p", plun, plun->lun_cip); 13236 (void) mdi_prop_remove(PIP(plun->lun_cip), NULL); 13237 (void) mdi_pi_free(PIP(plun->lun_cip), 0); 13238 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13239 mutex_enter(&plun->lun_tgt->tgt_mutex); 13240 mutex_enter(&plun->lun_mutex); 13241 } 13242 } 13243 13244 plun->lun_cip = NULL; 13245 } 13246 13247 /* 13248 * called when a timeout occurs 13249 * 13250 * can be scheduled during an attach or resume (if not already running) 13251 * 13252 * one timeout is set up for all ports 13253 * 13254 * acquires and releases the global mutex 13255 */ 13256 /*ARGSUSED*/ 13257 static void 13258 fcp_watch(void *arg) 13259 { 13260 struct fcp_port *pptr; 13261 struct fcp_ipkt *icmd; 13262 struct fcp_ipkt *nicmd; 13263 struct fcp_pkt *cmd; 13264 struct fcp_pkt *ncmd; 13265 struct fcp_pkt *tail; 13266 struct fcp_pkt *pcmd; 13267 struct fcp_pkt *save_head; 13268 struct fcp_port *save_port; 13269 13270 /* increment global watchdog time */ 13271 fcp_watchdog_time += fcp_watchdog_timeout; 13272 13273 mutex_enter(&fcp_global_mutex); 13274 13275 /* scan each port in our list */ 13276 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13277 save_port = fcp_port_head; 13278 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13279 mutex_exit(&fcp_global_mutex); 13280 13281 mutex_enter(&pptr->port_mutex); 13282 if (pptr->port_ipkt_list == NULL && 13283 (pptr->port_state & (FCP_STATE_SUSPENDED | 13284 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13285 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13286 mutex_exit(&pptr->port_mutex); 13287 mutex_enter(&fcp_global_mutex); 13288 goto end_of_watchdog; 13289 } 13290 13291 /* 13292 * We check if a list of targets need to be offlined. 13293 */ 13294 if (pptr->port_offline_tgts) { 13295 fcp_scan_offline_tgts(pptr); 13296 } 13297 13298 /* 13299 * We check if a list of luns need to be offlined. 13300 */ 13301 if (pptr->port_offline_luns) { 13302 fcp_scan_offline_luns(pptr); 13303 } 13304 13305 /* 13306 * We check if a list of targets or luns need to be reset. 13307 */ 13308 if (pptr->port_reset_list) { 13309 fcp_check_reset_delay(pptr); 13310 } 13311 13312 mutex_exit(&pptr->port_mutex); 13313 13314 /* 13315 * This is where the pending commands (pkt) are checked for 13316 * timeout. 13317 */ 13318 mutex_enter(&pptr->port_pkt_mutex); 13319 tail = pptr->port_pkt_tail; 13320 13321 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13322 cmd != NULL; cmd = ncmd) { 13323 ncmd = cmd->cmd_next; 13324 /* 13325 * If a command is in this queue the bit CFLAG_IN_QUEUE 13326 * must be set. 13327 */ 13328 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13329 /* 13330 * FCP_INVALID_TIMEOUT will be set for those 13331 * command that need to be failed. Mostly those 13332 * cmds that could not be queued down for the 13333 * "timeout" value. cmd->cmd_timeout is used 13334 * to try and requeue the command regularly. 13335 */ 13336 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13337 /* 13338 * This command hasn't timed out yet. Let's 13339 * go to the next one. 13340 */ 13341 pcmd = cmd; 13342 goto end_of_loop; 13343 } 13344 13345 if (cmd == pptr->port_pkt_head) { 13346 ASSERT(pcmd == NULL); 13347 pptr->port_pkt_head = cmd->cmd_next; 13348 } else { 13349 ASSERT(pcmd != NULL); 13350 pcmd->cmd_next = cmd->cmd_next; 13351 } 13352 13353 if (cmd == pptr->port_pkt_tail) { 13354 ASSERT(cmd->cmd_next == NULL); 13355 pptr->port_pkt_tail = pcmd; 13356 if (pcmd) { 13357 pcmd->cmd_next = NULL; 13358 } 13359 } 13360 cmd->cmd_next = NULL; 13361 13362 /* 13363 * save the current head before dropping the 13364 * mutex - If the head doesn't remain the 13365 * same after re acquiring the mutex, just 13366 * bail out and revisit on next tick. 13367 * 13368 * PS: The tail pointer can change as the commands 13369 * get requeued after failure to retransport 13370 */ 13371 save_head = pptr->port_pkt_head; 13372 mutex_exit(&pptr->port_pkt_mutex); 13373 13374 if (cmd->cmd_fp_pkt->pkt_timeout == 13375 FCP_INVALID_TIMEOUT) { 13376 struct scsi_pkt *pkt = cmd->cmd_pkt; 13377 struct fcp_lun *plun; 13378 struct fcp_tgt *ptgt; 13379 13380 plun = ADDR2LUN(&pkt->pkt_address); 13381 ptgt = plun->lun_tgt; 13382 13383 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13384 fcp_trace, FCP_BUF_LEVEL_2, 0, 13385 "SCSI cmd 0x%x to D_ID=%x timed out", 13386 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13387 13388 cmd->cmd_state == FCP_PKT_ABORTING ? 13389 fcp_fail_cmd(cmd, CMD_RESET, 13390 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13391 CMD_TIMEOUT, STAT_ABORTED); 13392 } else { 13393 fcp_retransport_cmd(pptr, cmd); 13394 } 13395 mutex_enter(&pptr->port_pkt_mutex); 13396 if (save_head && save_head != pptr->port_pkt_head) { 13397 /* 13398 * Looks like linked list got changed (mostly 13399 * happens when an an OFFLINE LUN code starts 13400 * returning overflow queue commands in 13401 * parallel. So bail out and revisit during 13402 * next tick 13403 */ 13404 break; 13405 } 13406 end_of_loop: 13407 /* 13408 * Scan only upto the previously known tail pointer 13409 * to avoid excessive processing - lots of new packets 13410 * could have been added to the tail or the old ones 13411 * re-queued. 13412 */ 13413 if (cmd == tail) { 13414 break; 13415 } 13416 } 13417 mutex_exit(&pptr->port_pkt_mutex); 13418 13419 mutex_enter(&pptr->port_mutex); 13420 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13421 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13422 13423 nicmd = icmd->ipkt_next; 13424 if ((icmd->ipkt_restart != 0) && 13425 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13426 /* packet has not timed out */ 13427 continue; 13428 } 13429 13430 /* time for packet re-transport */ 13431 if (icmd == pptr->port_ipkt_list) { 13432 pptr->port_ipkt_list = icmd->ipkt_next; 13433 if (pptr->port_ipkt_list) { 13434 pptr->port_ipkt_list->ipkt_prev = 13435 NULL; 13436 } 13437 } else { 13438 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13439 if (icmd->ipkt_next) { 13440 icmd->ipkt_next->ipkt_prev = 13441 icmd->ipkt_prev; 13442 } 13443 } 13444 icmd->ipkt_next = NULL; 13445 icmd->ipkt_prev = NULL; 13446 mutex_exit(&pptr->port_mutex); 13447 13448 if (fcp_is_retryable(icmd)) { 13449 fc_ulp_rscn_info_t *rscnp = 13450 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13451 pkt_ulp_rscn_infop; 13452 13453 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13454 fcp_trace, FCP_BUF_LEVEL_2, 0, 13455 "%x to D_ID=%x Retrying..", 13456 icmd->ipkt_opcode, 13457 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13458 13459 /* 13460 * Update the RSCN count in the packet 13461 * before resending. 13462 */ 13463 13464 if (rscnp != NULL) { 13465 rscnp->ulp_rscn_count = 13466 fc_ulp_get_rscn_count(pptr-> 13467 port_fp_handle); 13468 } 13469 13470 mutex_enter(&pptr->port_mutex); 13471 mutex_enter(&ptgt->tgt_mutex); 13472 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13473 mutex_exit(&ptgt->tgt_mutex); 13474 mutex_exit(&pptr->port_mutex); 13475 switch (icmd->ipkt_opcode) { 13476 int rval; 13477 case LA_ELS_PLOGI: 13478 if ((rval = fc_ulp_login( 13479 pptr->port_fp_handle, 13480 &icmd->ipkt_fpkt, 1)) == 13481 FC_SUCCESS) { 13482 mutex_enter( 13483 &pptr->port_mutex); 13484 continue; 13485 } 13486 if (fcp_handle_ipkt_errors( 13487 pptr, ptgt, icmd, rval, 13488 "PLOGI") == DDI_SUCCESS) { 13489 mutex_enter( 13490 &pptr->port_mutex); 13491 continue; 13492 } 13493 break; 13494 13495 case LA_ELS_PRLI: 13496 if ((rval = fc_ulp_issue_els( 13497 pptr->port_fp_handle, 13498 icmd->ipkt_fpkt)) == 13499 FC_SUCCESS) { 13500 mutex_enter( 13501 &pptr->port_mutex); 13502 continue; 13503 } 13504 if (fcp_handle_ipkt_errors( 13505 pptr, ptgt, icmd, rval, 13506 "PRLI") == DDI_SUCCESS) { 13507 mutex_enter( 13508 &pptr->port_mutex); 13509 continue; 13510 } 13511 break; 13512 13513 default: 13514 if ((rval = fcp_transport( 13515 pptr->port_fp_handle, 13516 icmd->ipkt_fpkt, 1)) == 13517 FC_SUCCESS) { 13518 mutex_enter( 13519 &pptr->port_mutex); 13520 continue; 13521 } 13522 if (fcp_handle_ipkt_errors( 13523 pptr, ptgt, icmd, rval, 13524 "PRLI") == DDI_SUCCESS) { 13525 mutex_enter( 13526 &pptr->port_mutex); 13527 continue; 13528 } 13529 break; 13530 } 13531 } else { 13532 mutex_exit(&ptgt->tgt_mutex); 13533 mutex_exit(&pptr->port_mutex); 13534 } 13535 } else { 13536 fcp_print_error(icmd->ipkt_fpkt); 13537 } 13538 13539 (void) fcp_call_finish_init(pptr, ptgt, 13540 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13541 icmd->ipkt_cause); 13542 fcp_icmd_free(pptr, icmd); 13543 mutex_enter(&pptr->port_mutex); 13544 } 13545 13546 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13547 mutex_exit(&pptr->port_mutex); 13548 mutex_enter(&fcp_global_mutex); 13549 13550 end_of_watchdog: 13551 /* 13552 * Bail out early before getting into trouble 13553 */ 13554 if (save_port != fcp_port_head) { 13555 break; 13556 } 13557 } 13558 13559 if (fcp_watchdog_init > 0) { 13560 /* reschedule timeout to go again */ 13561 fcp_watchdog_id = 13562 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13563 } 13564 mutex_exit(&fcp_global_mutex); 13565 } 13566 13567 13568 static void 13569 fcp_check_reset_delay(struct fcp_port *pptr) 13570 { 13571 uint32_t tgt_cnt; 13572 int level; 13573 struct fcp_tgt *ptgt; 13574 struct fcp_lun *plun; 13575 struct fcp_reset_elem *cur = NULL; 13576 struct fcp_reset_elem *next = NULL; 13577 struct fcp_reset_elem *prev = NULL; 13578 13579 ASSERT(mutex_owned(&pptr->port_mutex)); 13580 13581 next = pptr->port_reset_list; 13582 while ((cur = next) != NULL) { 13583 next = cur->next; 13584 13585 if (cur->timeout < fcp_watchdog_time) { 13586 prev = cur; 13587 continue; 13588 } 13589 13590 ptgt = cur->tgt; 13591 plun = cur->lun; 13592 tgt_cnt = cur->tgt_cnt; 13593 13594 if (ptgt) { 13595 level = RESET_TARGET; 13596 } else { 13597 ASSERT(plun != NULL); 13598 level = RESET_LUN; 13599 ptgt = plun->lun_tgt; 13600 } 13601 if (prev) { 13602 prev->next = next; 13603 } else { 13604 /* 13605 * Because we drop port mutex while doing aborts for 13606 * packets, we can't rely on reset_list pointing to 13607 * our head 13608 */ 13609 if (cur == pptr->port_reset_list) { 13610 pptr->port_reset_list = next; 13611 } else { 13612 struct fcp_reset_elem *which; 13613 13614 which = pptr->port_reset_list; 13615 while (which && which->next != cur) { 13616 which = which->next; 13617 } 13618 ASSERT(which != NULL); 13619 13620 which->next = next; 13621 prev = which; 13622 } 13623 } 13624 13625 kmem_free(cur, sizeof (*cur)); 13626 13627 if (tgt_cnt == ptgt->tgt_change_cnt) { 13628 mutex_enter(&ptgt->tgt_mutex); 13629 if (level == RESET_TARGET) { 13630 fcp_update_tgt_state(ptgt, 13631 FCP_RESET, FCP_LUN_BUSY); 13632 } else { 13633 fcp_update_lun_state(plun, 13634 FCP_RESET, FCP_LUN_BUSY); 13635 } 13636 mutex_exit(&ptgt->tgt_mutex); 13637 13638 mutex_exit(&pptr->port_mutex); 13639 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13640 mutex_enter(&pptr->port_mutex); 13641 } 13642 } 13643 } 13644 13645 13646 static void 13647 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13648 struct fcp_lun *rlun, int tgt_cnt) 13649 { 13650 int rval; 13651 struct fcp_lun *tlun, *nlun; 13652 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13653 *cmd = NULL, *head = NULL, 13654 *tail = NULL; 13655 13656 mutex_enter(&pptr->port_pkt_mutex); 13657 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13658 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13659 struct fcp_tgt *ptgt = plun->lun_tgt; 13660 13661 ncmd = cmd->cmd_next; 13662 13663 if (ptgt != ttgt && plun != rlun) { 13664 pcmd = cmd; 13665 continue; 13666 } 13667 13668 if (pcmd != NULL) { 13669 ASSERT(pptr->port_pkt_head != cmd); 13670 pcmd->cmd_next = ncmd; 13671 } else { 13672 ASSERT(cmd == pptr->port_pkt_head); 13673 pptr->port_pkt_head = ncmd; 13674 } 13675 if (pptr->port_pkt_tail == cmd) { 13676 ASSERT(cmd->cmd_next == NULL); 13677 pptr->port_pkt_tail = pcmd; 13678 if (pcmd != NULL) { 13679 pcmd->cmd_next = NULL; 13680 } 13681 } 13682 13683 if (head == NULL) { 13684 head = tail = cmd; 13685 } else { 13686 ASSERT(tail != NULL); 13687 tail->cmd_next = cmd; 13688 tail = cmd; 13689 } 13690 cmd->cmd_next = NULL; 13691 } 13692 mutex_exit(&pptr->port_pkt_mutex); 13693 13694 for (cmd = head; cmd != NULL; cmd = ncmd) { 13695 struct scsi_pkt *pkt = cmd->cmd_pkt; 13696 13697 ncmd = cmd->cmd_next; 13698 ASSERT(pkt != NULL); 13699 13700 mutex_enter(&pptr->port_mutex); 13701 if (ttgt->tgt_change_cnt == tgt_cnt) { 13702 mutex_exit(&pptr->port_mutex); 13703 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13704 pkt->pkt_reason = CMD_RESET; 13705 pkt->pkt_statistics |= STAT_DEV_RESET; 13706 cmd->cmd_state = FCP_PKT_IDLE; 13707 fcp_post_callback(cmd); 13708 } else { 13709 mutex_exit(&pptr->port_mutex); 13710 } 13711 } 13712 13713 /* 13714 * If the FCA will return all the commands in its queue then our 13715 * work is easy, just return. 13716 */ 13717 13718 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13719 return; 13720 } 13721 13722 /* 13723 * For RESET_LUN get hold of target pointer 13724 */ 13725 if (ttgt == NULL) { 13726 ASSERT(rlun != NULL); 13727 13728 ttgt = rlun->lun_tgt; 13729 13730 ASSERT(ttgt != NULL); 13731 } 13732 13733 /* 13734 * There are some severe race conditions here. 13735 * While we are trying to abort the pkt, it might be completing 13736 * so mark it aborted and if the abort does not succeed then 13737 * handle it in the watch thread. 13738 */ 13739 mutex_enter(&ttgt->tgt_mutex); 13740 nlun = ttgt->tgt_lun; 13741 mutex_exit(&ttgt->tgt_mutex); 13742 while ((tlun = nlun) != NULL) { 13743 int restart = 0; 13744 if (rlun && rlun != tlun) { 13745 mutex_enter(&ttgt->tgt_mutex); 13746 nlun = tlun->lun_next; 13747 mutex_exit(&ttgt->tgt_mutex); 13748 continue; 13749 } 13750 mutex_enter(&tlun->lun_mutex); 13751 cmd = tlun->lun_pkt_head; 13752 while (cmd != NULL) { 13753 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13754 struct scsi_pkt *pkt; 13755 13756 restart = 1; 13757 cmd->cmd_state = FCP_PKT_ABORTING; 13758 mutex_exit(&tlun->lun_mutex); 13759 rval = fc_ulp_abort(pptr->port_fp_handle, 13760 cmd->cmd_fp_pkt, KM_SLEEP); 13761 if (rval == FC_SUCCESS) { 13762 pkt = cmd->cmd_pkt; 13763 pkt->pkt_reason = CMD_RESET; 13764 pkt->pkt_statistics |= STAT_DEV_RESET; 13765 cmd->cmd_state = FCP_PKT_IDLE; 13766 fcp_post_callback(cmd); 13767 } else { 13768 caddr_t msg; 13769 13770 (void) fc_ulp_error(rval, &msg); 13771 13772 /* 13773 * This part is tricky. The abort 13774 * failed and now the command could 13775 * be completing. The cmd_state == 13776 * FCP_PKT_ABORTING should save 13777 * us in fcp_cmd_callback. If we 13778 * are already aborting ignore the 13779 * command in fcp_cmd_callback. 13780 * Here we leave this packet for 20 13781 * sec to be aborted in the 13782 * fcp_watch thread. 13783 */ 13784 fcp_log(CE_WARN, pptr->port_dip, 13785 "!Abort failed after reset %s", 13786 msg); 13787 13788 cmd->cmd_timeout = 13789 fcp_watchdog_time + 13790 cmd->cmd_pkt->pkt_time + 13791 FCP_FAILED_DELAY; 13792 13793 cmd->cmd_fp_pkt->pkt_timeout = 13794 FCP_INVALID_TIMEOUT; 13795 /* 13796 * This is a hack, cmd is put in the 13797 * overflow queue so that it can be 13798 * timed out finally 13799 */ 13800 cmd->cmd_flags |= CFLAG_IN_QUEUE; 13801 13802 mutex_enter(&pptr->port_pkt_mutex); 13803 if (pptr->port_pkt_head) { 13804 ASSERT(pptr->port_pkt_tail 13805 != NULL); 13806 pptr->port_pkt_tail->cmd_next 13807 = cmd; 13808 pptr->port_pkt_tail = cmd; 13809 } else { 13810 ASSERT(pptr->port_pkt_tail 13811 == NULL); 13812 pptr->port_pkt_head = 13813 pptr->port_pkt_tail 13814 = cmd; 13815 } 13816 cmd->cmd_next = NULL; 13817 mutex_exit(&pptr->port_pkt_mutex); 13818 } 13819 mutex_enter(&tlun->lun_mutex); 13820 cmd = tlun->lun_pkt_head; 13821 } else { 13822 cmd = cmd->cmd_forw; 13823 } 13824 } 13825 mutex_exit(&tlun->lun_mutex); 13826 13827 mutex_enter(&ttgt->tgt_mutex); 13828 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 13829 mutex_exit(&ttgt->tgt_mutex); 13830 13831 mutex_enter(&pptr->port_mutex); 13832 if (tgt_cnt != ttgt->tgt_change_cnt) { 13833 mutex_exit(&pptr->port_mutex); 13834 return; 13835 } else { 13836 mutex_exit(&pptr->port_mutex); 13837 } 13838 } 13839 } 13840 13841 13842 /* 13843 * unlink the soft state, returning the soft state found (if any) 13844 * 13845 * acquires and releases the global mutex 13846 */ 13847 struct fcp_port * 13848 fcp_soft_state_unlink(struct fcp_port *pptr) 13849 { 13850 struct fcp_port *hptr; /* ptr index */ 13851 struct fcp_port *tptr; /* prev hptr */ 13852 13853 mutex_enter(&fcp_global_mutex); 13854 for (hptr = fcp_port_head, tptr = NULL; 13855 hptr != NULL; 13856 tptr = hptr, hptr = hptr->port_next) { 13857 if (hptr == pptr) { 13858 /* we found a match -- remove this item */ 13859 if (tptr == NULL) { 13860 /* we're at the head of the list */ 13861 fcp_port_head = hptr->port_next; 13862 } else { 13863 tptr->port_next = hptr->port_next; 13864 } 13865 break; /* success */ 13866 } 13867 } 13868 if (fcp_port_head == NULL) { 13869 fcp_cleanup_blacklist(&fcp_lun_blacklist); 13870 } 13871 mutex_exit(&fcp_global_mutex); 13872 return (hptr); 13873 } 13874 13875 13876 /* 13877 * called by fcp_scsi_hba_tgt_init to find a LUN given a 13878 * WWN and a LUN number 13879 */ 13880 /* ARGSUSED */ 13881 static struct fcp_lun * 13882 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 13883 { 13884 int hash; 13885 struct fcp_tgt *ptgt; 13886 struct fcp_lun *plun; 13887 13888 ASSERT(mutex_owned(&pptr->port_mutex)); 13889 13890 hash = FCP_HASH(wwn); 13891 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 13892 ptgt = ptgt->tgt_next) { 13893 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 13894 sizeof (ptgt->tgt_port_wwn)) == 0) { 13895 mutex_enter(&ptgt->tgt_mutex); 13896 for (plun = ptgt->tgt_lun; 13897 plun != NULL; 13898 plun = plun->lun_next) { 13899 if (plun->lun_num == lun) { 13900 mutex_exit(&ptgt->tgt_mutex); 13901 return (plun); 13902 } 13903 } 13904 mutex_exit(&ptgt->tgt_mutex); 13905 return (NULL); 13906 } 13907 } 13908 return (NULL); 13909 } 13910 13911 /* 13912 * Function: fcp_prepare_pkt 13913 * 13914 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 13915 * for fcp_start(). It binds the data or partially maps it. 13916 * Builds the FCP header and starts the initialization of the 13917 * Fibre Channel header. 13918 * 13919 * Argument: *pptr FCP port. 13920 * *cmd FCP packet. 13921 * *plun LUN the command will be sent to. 13922 * 13923 * Context: User, Kernel and Interrupt context. 13924 */ 13925 static void 13926 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 13927 struct fcp_lun *plun) 13928 { 13929 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 13930 struct fcp_tgt *ptgt = plun->lun_tgt; 13931 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 13932 13933 ASSERT(cmd->cmd_pkt->pkt_comp || 13934 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 13935 13936 if (cmd->cmd_pkt->pkt_numcookies) { 13937 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 13938 fcmd->fcp_cntl.cntl_read_data = 1; 13939 fcmd->fcp_cntl.cntl_write_data = 0; 13940 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 13941 } else { 13942 fcmd->fcp_cntl.cntl_read_data = 0; 13943 fcmd->fcp_cntl.cntl_write_data = 1; 13944 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 13945 } 13946 13947 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 13948 13949 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 13950 ASSERT(fpkt->pkt_data_cookie_cnt <= 13951 pptr->port_data_dma_attr.dma_attr_sgllen); 13952 13953 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 13954 13955 /* FCA needs pkt_datalen to be set */ 13956 fpkt->pkt_datalen = cmd->cmd_dmacount; 13957 fcmd->fcp_data_len = cmd->cmd_dmacount; 13958 } else { 13959 fcmd->fcp_cntl.cntl_read_data = 0; 13960 fcmd->fcp_cntl.cntl_write_data = 0; 13961 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 13962 fpkt->pkt_datalen = 0; 13963 fcmd->fcp_data_len = 0; 13964 } 13965 13966 /* set up the Tagged Queuing type */ 13967 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 13968 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 13969 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 13970 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 13971 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 13972 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 13973 } else { 13974 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 13975 } 13976 13977 fcmd->fcp_ent_addr = plun->lun_addr; 13978 13979 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 13980 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 13981 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 13982 } else { 13983 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 13984 } 13985 13986 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 13987 cmd->cmd_pkt->pkt_state = 0; 13988 cmd->cmd_pkt->pkt_statistics = 0; 13989 cmd->cmd_pkt->pkt_resid = 0; 13990 13991 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 13992 13993 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 13994 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 13995 fpkt->pkt_comp = NULL; 13996 } else { 13997 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 13998 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 13999 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14000 } 14001 fpkt->pkt_comp = fcp_cmd_callback; 14002 } 14003 14004 mutex_enter(&pptr->port_mutex); 14005 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14006 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14007 } 14008 mutex_exit(&pptr->port_mutex); 14009 14010 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14011 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14012 14013 /* 14014 * Save a few kernel cycles here 14015 */ 14016 #ifndef __lock_lint 14017 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14018 #endif /* __lock_lint */ 14019 } 14020 14021 static void 14022 fcp_post_callback(struct fcp_pkt *cmd) 14023 { 14024 scsi_hba_pkt_comp(cmd->cmd_pkt); 14025 } 14026 14027 14028 /* 14029 * called to do polled I/O by fcp_start() 14030 * 14031 * return a transport status value, i.e. TRAN_ACCECPT for success 14032 */ 14033 static int 14034 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14035 { 14036 int rval; 14037 14038 #ifdef DEBUG 14039 mutex_enter(&pptr->port_pkt_mutex); 14040 pptr->port_npkts++; 14041 mutex_exit(&pptr->port_pkt_mutex); 14042 #endif /* DEBUG */ 14043 14044 if (cmd->cmd_fp_pkt->pkt_timeout) { 14045 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14046 } else { 14047 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14048 } 14049 14050 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14051 14052 cmd->cmd_state = FCP_PKT_ISSUED; 14053 14054 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14055 14056 #ifdef DEBUG 14057 mutex_enter(&pptr->port_pkt_mutex); 14058 pptr->port_npkts--; 14059 mutex_exit(&pptr->port_pkt_mutex); 14060 #endif /* DEBUG */ 14061 14062 cmd->cmd_state = FCP_PKT_IDLE; 14063 14064 switch (rval) { 14065 case FC_SUCCESS: 14066 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14067 fcp_complete_pkt(cmd->cmd_fp_pkt); 14068 rval = TRAN_ACCEPT; 14069 } else { 14070 rval = TRAN_FATAL_ERROR; 14071 } 14072 break; 14073 14074 case FC_TRAN_BUSY: 14075 rval = TRAN_BUSY; 14076 cmd->cmd_pkt->pkt_resid = 0; 14077 break; 14078 14079 case FC_BADPACKET: 14080 rval = TRAN_BADPKT; 14081 break; 14082 14083 default: 14084 rval = TRAN_FATAL_ERROR; 14085 break; 14086 } 14087 14088 return (rval); 14089 } 14090 14091 14092 /* 14093 * called by some of the following transport-called routines to convert 14094 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14095 */ 14096 static struct fcp_port * 14097 fcp_dip2port(dev_info_t *dip) 14098 { 14099 int instance; 14100 14101 instance = ddi_get_instance(dip); 14102 return (ddi_get_soft_state(fcp_softstate, instance)); 14103 } 14104 14105 14106 /* 14107 * called internally to return a LUN given a dip 14108 */ 14109 struct fcp_lun * 14110 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14111 { 14112 struct fcp_tgt *ptgt; 14113 struct fcp_lun *plun; 14114 int i; 14115 14116 14117 ASSERT(mutex_owned(&pptr->port_mutex)); 14118 14119 for (i = 0; i < FCP_NUM_HASH; i++) { 14120 for (ptgt = pptr->port_tgt_hash_table[i]; 14121 ptgt != NULL; 14122 ptgt = ptgt->tgt_next) { 14123 mutex_enter(&ptgt->tgt_mutex); 14124 for (plun = ptgt->tgt_lun; plun != NULL; 14125 plun = plun->lun_next) { 14126 mutex_enter(&plun->lun_mutex); 14127 if (plun->lun_cip == cip) { 14128 mutex_exit(&plun->lun_mutex); 14129 mutex_exit(&ptgt->tgt_mutex); 14130 return (plun); /* match found */ 14131 } 14132 mutex_exit(&plun->lun_mutex); 14133 } 14134 mutex_exit(&ptgt->tgt_mutex); 14135 } 14136 } 14137 return (NULL); /* no LUN found */ 14138 } 14139 14140 /* 14141 * pass an element to the hotplug list, kick the hotplug thread 14142 * and wait for the element to get processed by the hotplug thread. 14143 * on return the element is freed. 14144 * 14145 * return zero success and non-zero on failure 14146 * 14147 * acquires/releases the target mutex 14148 * 14149 */ 14150 static int 14151 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14152 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14153 { 14154 struct fcp_hp_elem *elem; 14155 int rval; 14156 14157 mutex_enter(&plun->lun_tgt->tgt_mutex); 14158 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14159 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14160 mutex_exit(&plun->lun_tgt->tgt_mutex); 14161 fcp_log(CE_CONT, pptr->port_dip, 14162 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14163 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14164 return (NDI_FAILURE); 14165 } 14166 mutex_exit(&plun->lun_tgt->tgt_mutex); 14167 mutex_enter(&elem->mutex); 14168 if (elem->wait) { 14169 while (elem->wait) { 14170 cv_wait(&elem->cv, &elem->mutex); 14171 } 14172 } 14173 rval = (elem->result); 14174 mutex_exit(&elem->mutex); 14175 mutex_destroy(&elem->mutex); 14176 cv_destroy(&elem->cv); 14177 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14178 return (rval); 14179 } 14180 14181 /* 14182 * pass an element to the hotplug list, and then 14183 * kick the hotplug thread 14184 * 14185 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14186 * 14187 * acquires/releases the hotplug mutex 14188 * 14189 * called with the target mutex owned 14190 * 14191 * memory acquired in NOSLEEP mode 14192 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14193 * for the hp daemon to process the request and is responsible for 14194 * freeing the element 14195 */ 14196 static struct fcp_hp_elem * 14197 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14198 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14199 { 14200 struct fcp_hp_elem *elem; 14201 dev_info_t *pdip; 14202 14203 ASSERT(pptr != NULL); 14204 ASSERT(plun != NULL); 14205 ASSERT(plun->lun_tgt != NULL); 14206 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14207 14208 /* create space for a hotplug element */ 14209 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14210 == NULL) { 14211 fcp_log(CE_WARN, NULL, 14212 "!can't allocate memory for hotplug element"); 14213 return (NULL); 14214 } 14215 14216 /* fill in hotplug element */ 14217 elem->port = pptr; 14218 elem->lun = plun; 14219 elem->cip = cip; 14220 elem->old_lun_mpxio = plun->lun_mpxio; 14221 elem->what = what; 14222 elem->flags = flags; 14223 elem->link_cnt = link_cnt; 14224 elem->tgt_cnt = tgt_cnt; 14225 elem->wait = wait; 14226 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14227 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14228 14229 /* schedule the hotplug task */ 14230 pdip = pptr->port_dip; 14231 mutex_enter(&plun->lun_mutex); 14232 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14233 plun->lun_event_count++; 14234 elem->event_cnt = plun->lun_event_count; 14235 } 14236 mutex_exit(&plun->lun_mutex); 14237 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14238 (void *)elem, KM_NOSLEEP) == NULL) { 14239 mutex_enter(&plun->lun_mutex); 14240 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14241 plun->lun_event_count--; 14242 } 14243 mutex_exit(&plun->lun_mutex); 14244 kmem_free(elem, sizeof (*elem)); 14245 return (0); 14246 } 14247 14248 return (elem); 14249 } 14250 14251 14252 static void 14253 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14254 { 14255 int rval; 14256 struct scsi_address *ap; 14257 struct fcp_lun *plun; 14258 struct fcp_tgt *ptgt; 14259 fc_packet_t *fpkt; 14260 14261 ap = &cmd->cmd_pkt->pkt_address; 14262 plun = ADDR2LUN(ap); 14263 ptgt = plun->lun_tgt; 14264 14265 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14266 14267 cmd->cmd_state = FCP_PKT_IDLE; 14268 14269 mutex_enter(&pptr->port_mutex); 14270 mutex_enter(&ptgt->tgt_mutex); 14271 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14272 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14273 fc_ulp_rscn_info_t *rscnp; 14274 14275 cmd->cmd_state = FCP_PKT_ISSUED; 14276 14277 /* 14278 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14279 * originally NULL, hence we try to set it to the pd pointed 14280 * to by the SCSI device we're trying to get to. 14281 */ 14282 14283 fpkt = cmd->cmd_fp_pkt; 14284 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14285 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14286 /* 14287 * We need to notify the transport that we now have a 14288 * reference to the remote port handle. 14289 */ 14290 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14291 } 14292 14293 mutex_exit(&ptgt->tgt_mutex); 14294 mutex_exit(&pptr->port_mutex); 14295 14296 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14297 14298 /* prepare the packet */ 14299 14300 fcp_prepare_pkt(pptr, cmd, plun); 14301 14302 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14303 pkt_ulp_rscn_infop; 14304 14305 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14306 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14307 14308 if (rscnp != NULL) { 14309 rscnp->ulp_rscn_count = 14310 fc_ulp_get_rscn_count(pptr-> 14311 port_fp_handle); 14312 } 14313 14314 rval = fcp_transport(pptr->port_fp_handle, 14315 cmd->cmd_fp_pkt, 0); 14316 14317 if (rval == FC_SUCCESS) { 14318 return; 14319 } 14320 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14321 } else { 14322 mutex_exit(&ptgt->tgt_mutex); 14323 mutex_exit(&pptr->port_mutex); 14324 } 14325 14326 fcp_queue_pkt(pptr, cmd); 14327 } 14328 14329 14330 static void 14331 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14332 { 14333 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14334 14335 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14336 cmd->cmd_state = FCP_PKT_IDLE; 14337 14338 cmd->cmd_pkt->pkt_reason = reason; 14339 cmd->cmd_pkt->pkt_state = 0; 14340 cmd->cmd_pkt->pkt_statistics = statistics; 14341 14342 fcp_post_callback(cmd); 14343 } 14344 14345 /* 14346 * Function: fcp_queue_pkt 14347 * 14348 * Description: This function queues the packet passed by the caller into 14349 * the list of packets of the FCP port. 14350 * 14351 * Argument: *pptr FCP port. 14352 * *cmd FCP packet to queue. 14353 * 14354 * Return Value: None 14355 * 14356 * Context: User, Kernel and Interrupt context. 14357 */ 14358 static void 14359 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14360 { 14361 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14362 14363 mutex_enter(&pptr->port_pkt_mutex); 14364 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14365 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14366 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14367 14368 /* 14369 * zero pkt_time means hang around for ever 14370 */ 14371 if (cmd->cmd_pkt->pkt_time) { 14372 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14373 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14374 } else { 14375 /* 14376 * Indicate the watch thread to fail the 14377 * command by setting it to highest value 14378 */ 14379 cmd->cmd_timeout = fcp_watchdog_time; 14380 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14381 } 14382 } 14383 14384 if (pptr->port_pkt_head) { 14385 ASSERT(pptr->port_pkt_tail != NULL); 14386 14387 pptr->port_pkt_tail->cmd_next = cmd; 14388 pptr->port_pkt_tail = cmd; 14389 } else { 14390 ASSERT(pptr->port_pkt_tail == NULL); 14391 14392 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14393 } 14394 cmd->cmd_next = NULL; 14395 mutex_exit(&pptr->port_pkt_mutex); 14396 } 14397 14398 /* 14399 * Function: fcp_update_targets 14400 * 14401 * Description: This function applies the specified change of state to all 14402 * the targets listed. The operation applied is 'set'. 14403 * 14404 * Argument: *pptr FCP port. 14405 * *dev_list Array of fc_portmap_t structures. 14406 * count Length of dev_list. 14407 * state State bits to update. 14408 * cause Reason for the update. 14409 * 14410 * Return Value: None 14411 * 14412 * Context: User, Kernel and Interrupt context. 14413 * The mutex pptr->port_mutex must be held. 14414 */ 14415 static void 14416 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14417 uint32_t count, uint32_t state, int cause) 14418 { 14419 fc_portmap_t *map_entry; 14420 struct fcp_tgt *ptgt; 14421 14422 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14423 14424 while (count--) { 14425 map_entry = &(dev_list[count]); 14426 ptgt = fcp_lookup_target(pptr, 14427 (uchar_t *)&(map_entry->map_pwwn)); 14428 if (ptgt == NULL) { 14429 continue; 14430 } 14431 14432 mutex_enter(&ptgt->tgt_mutex); 14433 ptgt->tgt_trace = 0; 14434 ptgt->tgt_change_cnt++; 14435 ptgt->tgt_statec_cause = cause; 14436 ptgt->tgt_tmp_cnt = 1; 14437 fcp_update_tgt_state(ptgt, FCP_SET, state); 14438 mutex_exit(&ptgt->tgt_mutex); 14439 } 14440 } 14441 14442 static int 14443 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14444 int lcount, int tcount, int cause) 14445 { 14446 int rval; 14447 14448 mutex_enter(&pptr->port_mutex); 14449 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14450 mutex_exit(&pptr->port_mutex); 14451 14452 return (rval); 14453 } 14454 14455 14456 static int 14457 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14458 int lcount, int tcount, int cause) 14459 { 14460 int finish_init = 0; 14461 int finish_tgt = 0; 14462 int do_finish_init = 0; 14463 int rval = FCP_NO_CHANGE; 14464 14465 if (cause == FCP_CAUSE_LINK_CHANGE || 14466 cause == FCP_CAUSE_LINK_DOWN) { 14467 do_finish_init = 1; 14468 } 14469 14470 if (ptgt != NULL) { 14471 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14472 FCP_BUF_LEVEL_2, 0, 14473 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14474 " cause = %d, d_id = 0x%x, tgt_done = %d", 14475 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14476 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14477 ptgt->tgt_d_id, ptgt->tgt_done); 14478 14479 mutex_enter(&ptgt->tgt_mutex); 14480 14481 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14482 rval = FCP_DEV_CHANGE; 14483 if (do_finish_init && ptgt->tgt_done == 0) { 14484 ptgt->tgt_done++; 14485 finish_init = 1; 14486 } 14487 } else { 14488 if (--ptgt->tgt_tmp_cnt <= 0) { 14489 ptgt->tgt_tmp_cnt = 0; 14490 finish_tgt = 1; 14491 14492 if (do_finish_init) { 14493 finish_init = 1; 14494 } 14495 } 14496 } 14497 mutex_exit(&ptgt->tgt_mutex); 14498 } else { 14499 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14500 FCP_BUF_LEVEL_2, 0, 14501 "Call Finish Init for NO target"); 14502 14503 if (do_finish_init) { 14504 finish_init = 1; 14505 } 14506 } 14507 14508 if (finish_tgt) { 14509 ASSERT(ptgt != NULL); 14510 14511 mutex_enter(&ptgt->tgt_mutex); 14512 #ifdef DEBUG 14513 bzero(ptgt->tgt_tmp_cnt_stack, 14514 sizeof (ptgt->tgt_tmp_cnt_stack)); 14515 14516 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14517 FCP_STACK_DEPTH); 14518 #endif /* DEBUG */ 14519 mutex_exit(&ptgt->tgt_mutex); 14520 14521 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14522 } 14523 14524 if (finish_init && lcount == pptr->port_link_cnt) { 14525 ASSERT(pptr->port_tmp_cnt > 0); 14526 if (--pptr->port_tmp_cnt == 0) { 14527 fcp_finish_init(pptr); 14528 } 14529 } else if (lcount != pptr->port_link_cnt) { 14530 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14531 fcp_trace, FCP_BUF_LEVEL_2, 0, 14532 "fcp_call_finish_init_held,1: state change occured" 14533 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14534 } 14535 14536 return (rval); 14537 } 14538 14539 14540 static void 14541 fcp_reconfigure_luns(void * tgt_handle) 14542 { 14543 uint32_t dev_cnt; 14544 fc_portmap_t *devlist; 14545 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14546 struct fcp_port *pptr = ptgt->tgt_port; 14547 14548 /* 14549 * If the timer that fires this off got canceled too late, the 14550 * target could have been destroyed. 14551 */ 14552 14553 if (ptgt->tgt_tid == NULL) { 14554 return; 14555 } 14556 14557 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14558 if (devlist == NULL) { 14559 fcp_log(CE_WARN, pptr->port_dip, 14560 "!fcp%d: failed to allocate for portmap", 14561 pptr->port_instance); 14562 return; 14563 } 14564 14565 dev_cnt = 1; 14566 devlist->map_pd = ptgt->tgt_pd_handle; 14567 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14568 devlist->map_did.port_id = ptgt->tgt_d_id; 14569 14570 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14571 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14572 14573 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14574 devlist->map_type = PORT_DEVICE_NEW; 14575 devlist->map_flags = 0; 14576 14577 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14578 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14579 14580 /* 14581 * Clear the tgt_tid after no more references to 14582 * the fcp_tgt 14583 */ 14584 mutex_enter(&ptgt->tgt_mutex); 14585 ptgt->tgt_tid = NULL; 14586 mutex_exit(&ptgt->tgt_mutex); 14587 14588 kmem_free(devlist, sizeof (*devlist)); 14589 } 14590 14591 14592 static void 14593 fcp_free_targets(struct fcp_port *pptr) 14594 { 14595 int i; 14596 struct fcp_tgt *ptgt; 14597 14598 mutex_enter(&pptr->port_mutex); 14599 for (i = 0; i < FCP_NUM_HASH; i++) { 14600 ptgt = pptr->port_tgt_hash_table[i]; 14601 while (ptgt != NULL) { 14602 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14603 14604 fcp_free_target(ptgt); 14605 ptgt = next_tgt; 14606 } 14607 } 14608 mutex_exit(&pptr->port_mutex); 14609 } 14610 14611 14612 static void 14613 fcp_free_target(struct fcp_tgt *ptgt) 14614 { 14615 struct fcp_lun *plun; 14616 timeout_id_t tid; 14617 14618 mutex_enter(&ptgt->tgt_mutex); 14619 tid = ptgt->tgt_tid; 14620 14621 /* 14622 * Cancel any pending timeouts for this target. 14623 */ 14624 14625 if (tid != NULL) { 14626 /* 14627 * Set tgt_tid to NULL first to avoid a race in the callback. 14628 * If tgt_tid is NULL, the callback will simply return. 14629 */ 14630 ptgt->tgt_tid = NULL; 14631 mutex_exit(&ptgt->tgt_mutex); 14632 (void) untimeout(tid); 14633 mutex_enter(&ptgt->tgt_mutex); 14634 } 14635 14636 plun = ptgt->tgt_lun; 14637 while (plun != NULL) { 14638 struct fcp_lun *next_lun = plun->lun_next; 14639 14640 fcp_dealloc_lun(plun); 14641 plun = next_lun; 14642 } 14643 14644 mutex_exit(&ptgt->tgt_mutex); 14645 fcp_dealloc_tgt(ptgt); 14646 } 14647 14648 /* 14649 * Function: fcp_is_retryable 14650 * 14651 * Description: Indicates if the internal packet is retryable. 14652 * 14653 * Argument: *icmd FCP internal packet. 14654 * 14655 * Return Value: 0 Not retryable 14656 * 1 Retryable 14657 * 14658 * Context: User, Kernel and Interrupt context 14659 */ 14660 static int 14661 fcp_is_retryable(struct fcp_ipkt *icmd) 14662 { 14663 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14664 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14665 return (0); 14666 } 14667 14668 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14669 icmd->ipkt_port->port_deadline) ? 1 : 0); 14670 } 14671 14672 /* 14673 * Function: fcp_create_on_demand 14674 * 14675 * Argument: *pptr FCP port. 14676 * *pwwn Port WWN. 14677 * 14678 * Return Value: 0 Success 14679 * EIO 14680 * ENOMEM 14681 * EBUSY 14682 * EINVAL 14683 * 14684 * Context: User and Kernel context 14685 */ 14686 static int 14687 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14688 { 14689 int wait_ms; 14690 int tcount; 14691 int lcount; 14692 int ret; 14693 int error; 14694 int rval = EIO; 14695 int ntries; 14696 fc_portmap_t *devlist; 14697 opaque_t pd; 14698 struct fcp_lun *plun; 14699 struct fcp_tgt *ptgt; 14700 int old_manual = 0; 14701 14702 /* Allocates the fc_portmap_t structure. */ 14703 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14704 14705 /* 14706 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14707 * in the commented statement below: 14708 * 14709 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14710 * 14711 * Below, the deadline for the discovery process is set. 14712 */ 14713 mutex_enter(&pptr->port_mutex); 14714 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14715 mutex_exit(&pptr->port_mutex); 14716 14717 /* 14718 * We try to find the remote port based on the WWN provided by the 14719 * caller. We actually ask fp/fctl if it has it. 14720 */ 14721 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14722 (la_wwn_t *)pwwn, &error, 1); 14723 14724 if (pd == NULL) { 14725 kmem_free(devlist, sizeof (*devlist)); 14726 return (rval); 14727 } 14728 14729 /* 14730 * The remote port was found. We ask fp/fctl to update our 14731 * fc_portmap_t structure. 14732 */ 14733 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14734 (la_wwn_t *)pwwn, devlist); 14735 if (ret != FC_SUCCESS) { 14736 kmem_free(devlist, sizeof (*devlist)); 14737 return (rval); 14738 } 14739 14740 /* 14741 * The map flag field is set to indicates that the creation is being 14742 * done at the user request (Ioclt probably luxadm or cfgadm). 14743 */ 14744 devlist->map_type = PORT_DEVICE_USER_CREATE; 14745 14746 mutex_enter(&pptr->port_mutex); 14747 14748 /* 14749 * We check to see if fcp already has a target that describes the 14750 * device being created. If not it is created. 14751 */ 14752 ptgt = fcp_lookup_target(pptr, pwwn); 14753 if (ptgt == NULL) { 14754 lcount = pptr->port_link_cnt; 14755 mutex_exit(&pptr->port_mutex); 14756 14757 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14758 if (ptgt == NULL) { 14759 fcp_log(CE_WARN, pptr->port_dip, 14760 "!FC target allocation failed"); 14761 return (ENOMEM); 14762 } 14763 14764 mutex_enter(&pptr->port_mutex); 14765 } 14766 14767 mutex_enter(&ptgt->tgt_mutex); 14768 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 14769 ptgt->tgt_tmp_cnt = 1; 14770 ptgt->tgt_device_created = 0; 14771 /* 14772 * If fabric and auto config is set but the target was 14773 * manually unconfigured then reset to the manual_config_only to 14774 * 0 so the device will get configured. 14775 */ 14776 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14777 fcp_enable_auto_configuration && 14778 ptgt->tgt_manual_config_only == 1) { 14779 old_manual = 1; 14780 ptgt->tgt_manual_config_only = 0; 14781 } 14782 mutex_exit(&ptgt->tgt_mutex); 14783 14784 fcp_update_targets(pptr, devlist, 1, 14785 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 14786 14787 lcount = pptr->port_link_cnt; 14788 tcount = ptgt->tgt_change_cnt; 14789 14790 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 14791 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 14792 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14793 fcp_enable_auto_configuration && old_manual) { 14794 mutex_enter(&ptgt->tgt_mutex); 14795 ptgt->tgt_manual_config_only = 1; 14796 mutex_exit(&ptgt->tgt_mutex); 14797 } 14798 14799 if (pptr->port_link_cnt != lcount || 14800 ptgt->tgt_change_cnt != tcount) { 14801 rval = EBUSY; 14802 } 14803 mutex_exit(&pptr->port_mutex); 14804 14805 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14806 FCP_BUF_LEVEL_3, 0, 14807 "fcp_create_on_demand: mapflags ptgt=%x, " 14808 "lcount=%x::port_link_cnt=%x, " 14809 "tcount=%x: tgt_change_cnt=%x, rval=%x", 14810 ptgt, lcount, pptr->port_link_cnt, 14811 tcount, ptgt->tgt_change_cnt, rval); 14812 return (rval); 14813 } 14814 14815 /* 14816 * Due to lack of synchronization mechanisms, we perform 14817 * periodic monitoring of our request; Because requests 14818 * get dropped when another one supercedes (either because 14819 * of a link change or a target change), it is difficult to 14820 * provide a clean synchronization mechanism (such as a 14821 * semaphore or a conditional variable) without exhaustively 14822 * rewriting the mainline discovery code of this driver. 14823 */ 14824 wait_ms = 500; 14825 14826 ntries = fcp_max_target_retries; 14827 14828 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14829 FCP_BUF_LEVEL_3, 0, 14830 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 14831 "lcount=%x::port_link_cnt=%x, " 14832 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14833 "tgt_tmp_cnt =%x", 14834 ntries, ptgt, lcount, pptr->port_link_cnt, 14835 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14836 ptgt->tgt_tmp_cnt); 14837 14838 mutex_enter(&ptgt->tgt_mutex); 14839 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 14840 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 14841 mutex_exit(&ptgt->tgt_mutex); 14842 mutex_exit(&pptr->port_mutex); 14843 14844 delay(drv_usectohz(wait_ms * 1000)); 14845 14846 mutex_enter(&pptr->port_mutex); 14847 mutex_enter(&ptgt->tgt_mutex); 14848 } 14849 14850 14851 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 14852 rval = EBUSY; 14853 } else { 14854 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 14855 FCP_TGT_NODE_PRESENT) { 14856 rval = 0; 14857 } 14858 } 14859 14860 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14861 FCP_BUF_LEVEL_3, 0, 14862 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 14863 "lcount=%x::port_link_cnt=%x, " 14864 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 14865 "tgt_tmp_cnt =%x", 14866 ntries, ptgt, lcount, pptr->port_link_cnt, 14867 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 14868 ptgt->tgt_tmp_cnt); 14869 14870 if (rval) { 14871 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14872 fcp_enable_auto_configuration && old_manual) { 14873 ptgt->tgt_manual_config_only = 1; 14874 } 14875 mutex_exit(&ptgt->tgt_mutex); 14876 mutex_exit(&pptr->port_mutex); 14877 kmem_free(devlist, sizeof (*devlist)); 14878 14879 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14880 FCP_BUF_LEVEL_3, 0, 14881 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 14882 "lcount=%x::port_link_cnt=%x, " 14883 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 14884 "tgt_device_created=%x, tgt D_ID=%x", 14885 ntries, ptgt, lcount, pptr->port_link_cnt, 14886 tcount, ptgt->tgt_change_cnt, rval, 14887 ptgt->tgt_device_created, ptgt->tgt_d_id); 14888 return (rval); 14889 } 14890 14891 if ((plun = ptgt->tgt_lun) != NULL) { 14892 tcount = plun->lun_tgt->tgt_change_cnt; 14893 } else { 14894 rval = EINVAL; 14895 } 14896 lcount = pptr->port_link_cnt; 14897 14898 /* 14899 * Configuring the target with no LUNs will fail. We 14900 * should reset the node state so that it is not 14901 * automatically configured when the LUNs are added 14902 * to this target. 14903 */ 14904 if (ptgt->tgt_lun_cnt == 0) { 14905 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 14906 } 14907 mutex_exit(&ptgt->tgt_mutex); 14908 mutex_exit(&pptr->port_mutex); 14909 14910 while (plun) { 14911 child_info_t *cip; 14912 14913 mutex_enter(&plun->lun_mutex); 14914 cip = plun->lun_cip; 14915 mutex_exit(&plun->lun_mutex); 14916 14917 mutex_enter(&ptgt->tgt_mutex); 14918 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 14919 mutex_exit(&ptgt->tgt_mutex); 14920 14921 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 14922 FCP_ONLINE, lcount, tcount, 14923 NDI_ONLINE_ATTACH); 14924 if (rval != NDI_SUCCESS) { 14925 FCP_TRACE(fcp_logq, 14926 pptr->port_instbuf, fcp_trace, 14927 FCP_BUF_LEVEL_3, 0, 14928 "fcp_create_on_demand: " 14929 "pass_to_hp_and_wait failed " 14930 "rval=%x", rval); 14931 rval = EIO; 14932 } else { 14933 mutex_enter(&LUN_TGT->tgt_mutex); 14934 plun->lun_state &= ~(FCP_LUN_OFFLINE | 14935 FCP_LUN_BUSY); 14936 mutex_exit(&LUN_TGT->tgt_mutex); 14937 } 14938 mutex_enter(&ptgt->tgt_mutex); 14939 } 14940 14941 plun = plun->lun_next; 14942 mutex_exit(&ptgt->tgt_mutex); 14943 } 14944 14945 kmem_free(devlist, sizeof (*devlist)); 14946 14947 if (FC_TOP_EXTERNAL(pptr->port_topology) && 14948 fcp_enable_auto_configuration && old_manual) { 14949 mutex_enter(&ptgt->tgt_mutex); 14950 /* if successful then set manual to 0 */ 14951 if (rval == 0) { 14952 ptgt->tgt_manual_config_only = 0; 14953 } else { 14954 /* reset to 1 so the user has to do the config */ 14955 ptgt->tgt_manual_config_only = 1; 14956 } 14957 mutex_exit(&ptgt->tgt_mutex); 14958 } 14959 14960 return (rval); 14961 } 14962 14963 14964 static void 14965 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 14966 { 14967 int count; 14968 uchar_t byte; 14969 14970 count = 0; 14971 while (*string) { 14972 byte = FCP_ATOB(*string); string++; 14973 byte = byte << 4 | FCP_ATOB(*string); string++; 14974 bytes[count++] = byte; 14975 14976 if (count >= byte_len) { 14977 break; 14978 } 14979 } 14980 } 14981 14982 static void 14983 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 14984 { 14985 int i; 14986 14987 for (i = 0; i < FC_WWN_SIZE; i++) { 14988 (void) sprintf(string + (i * 2), 14989 "%02x", wwn[i]); 14990 } 14991 14992 } 14993 14994 static void 14995 fcp_print_error(fc_packet_t *fpkt) 14996 { 14997 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 14998 fpkt->pkt_ulp_private; 14999 struct fcp_port *pptr; 15000 struct fcp_tgt *ptgt; 15001 struct fcp_lun *plun; 15002 caddr_t buf; 15003 int scsi_cmd = 0; 15004 15005 ptgt = icmd->ipkt_tgt; 15006 plun = icmd->ipkt_lun; 15007 pptr = ptgt->tgt_port; 15008 15009 buf = kmem_zalloc(256, KM_NOSLEEP); 15010 if (buf == NULL) { 15011 return; 15012 } 15013 15014 switch (icmd->ipkt_opcode) { 15015 case SCMD_REPORT_LUN: 15016 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15017 " lun=0x%%x failed"); 15018 scsi_cmd++; 15019 break; 15020 15021 case SCMD_INQUIRY_PAGE83: 15022 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15023 " lun=0x%%x failed"); 15024 scsi_cmd++; 15025 break; 15026 15027 case SCMD_INQUIRY: 15028 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15029 " lun=0x%%x failed"); 15030 scsi_cmd++; 15031 break; 15032 15033 case LA_ELS_PLOGI: 15034 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15035 break; 15036 15037 case LA_ELS_PRLI: 15038 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15039 break; 15040 } 15041 15042 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15043 struct fcp_rsp response, *rsp; 15044 uchar_t asc, ascq; 15045 caddr_t sense_key = NULL; 15046 struct fcp_rsp_info fcp_rsp_err, *bep; 15047 15048 if (icmd->ipkt_nodma) { 15049 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15050 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15051 sizeof (struct fcp_rsp)); 15052 } else { 15053 rsp = &response; 15054 bep = &fcp_rsp_err; 15055 15056 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15057 sizeof (struct fcp_rsp)); 15058 15059 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15060 bep, fpkt->pkt_resp_acc, 15061 sizeof (struct fcp_rsp_info)); 15062 } 15063 15064 15065 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15066 (void) sprintf(buf + strlen(buf), 15067 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15068 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15069 " senselen=%%x. Giving up"); 15070 15071 fcp_log(CE_WARN, pptr->port_dip, buf, 15072 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15073 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15074 rsp->fcp_u.fcp_status.reserved_1, 15075 rsp->fcp_response_len, rsp->fcp_sense_len); 15076 15077 kmem_free(buf, 256); 15078 return; 15079 } 15080 15081 if (rsp->fcp_u.fcp_status.rsp_len_set && 15082 bep->rsp_code != FCP_NO_FAILURE) { 15083 (void) sprintf(buf + strlen(buf), 15084 " FCP Response code = 0x%x", bep->rsp_code); 15085 } 15086 15087 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15088 struct scsi_extended_sense sense_info, *sense_ptr; 15089 15090 if (icmd->ipkt_nodma) { 15091 sense_ptr = (struct scsi_extended_sense *) 15092 ((caddr_t)fpkt->pkt_resp + 15093 sizeof (struct fcp_rsp) + 15094 rsp->fcp_response_len); 15095 } else { 15096 sense_ptr = &sense_info; 15097 15098 FCP_CP_IN(fpkt->pkt_resp + 15099 sizeof (struct fcp_rsp) + 15100 rsp->fcp_response_len, &sense_info, 15101 fpkt->pkt_resp_acc, 15102 sizeof (struct scsi_extended_sense)); 15103 } 15104 15105 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15106 NUM_IMPL_SENSE_KEYS) { 15107 sense_key = sense_keys[sense_ptr->es_key]; 15108 } else { 15109 sense_key = "Undefined"; 15110 } 15111 15112 asc = sense_ptr->es_add_code; 15113 ascq = sense_ptr->es_qual_code; 15114 15115 (void) sprintf(buf + strlen(buf), 15116 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15117 " Giving up"); 15118 15119 fcp_log(CE_WARN, pptr->port_dip, buf, 15120 ptgt->tgt_d_id, plun->lun_num, sense_key, 15121 asc, ascq); 15122 } else { 15123 (void) sprintf(buf + strlen(buf), 15124 " : SCSI status=%%x. Giving up"); 15125 15126 fcp_log(CE_WARN, pptr->port_dip, buf, 15127 ptgt->tgt_d_id, plun->lun_num, 15128 rsp->fcp_u.fcp_status.scsi_status); 15129 } 15130 } else { 15131 caddr_t state, reason, action, expln; 15132 15133 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15134 &action, &expln); 15135 15136 (void) sprintf(buf + strlen(buf), ": State:%%s," 15137 " Reason:%%s. Giving up"); 15138 15139 if (scsi_cmd) { 15140 fcp_log(CE_WARN, pptr->port_dip, buf, 15141 ptgt->tgt_d_id, plun->lun_num, state, reason); 15142 } else { 15143 fcp_log(CE_WARN, pptr->port_dip, buf, 15144 ptgt->tgt_d_id, state, reason); 15145 } 15146 } 15147 15148 kmem_free(buf, 256); 15149 } 15150 15151 15152 static int 15153 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15154 struct fcp_ipkt *icmd, int rval, caddr_t op) 15155 { 15156 int ret = DDI_FAILURE; 15157 char *error; 15158 15159 switch (rval) { 15160 case FC_DEVICE_BUSY_NEW_RSCN: 15161 /* 15162 * This means that there was a new RSCN that the transport 15163 * knows about (which the ULP *may* know about too) but the 15164 * pkt that was sent down was related to an older RSCN. So, we 15165 * are just going to reset the retry count and deadline and 15166 * continue to retry. The idea is that transport is currently 15167 * working on the new RSCN and will soon let the ULPs know 15168 * about it and when it does the existing logic will kick in 15169 * where it will change the tcount to indicate that something 15170 * changed on the target. So, rediscovery will start and there 15171 * will not be an infinite retry. 15172 * 15173 * For a full flow of how the RSCN info is transferred back and 15174 * forth, see fp.c 15175 */ 15176 icmd->ipkt_retries = 0; 15177 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15178 FCP_ICMD_DEADLINE; 15179 15180 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15181 FCP_BUF_LEVEL_3, 0, 15182 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15183 rval, ptgt->tgt_d_id); 15184 /* FALLTHROUGH */ 15185 15186 case FC_STATEC_BUSY: 15187 case FC_DEVICE_BUSY: 15188 case FC_PBUSY: 15189 case FC_FBUSY: 15190 case FC_TRAN_BUSY: 15191 case FC_OFFLINE: 15192 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15193 FCP_BUF_LEVEL_3, 0, 15194 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15195 rval, ptgt->tgt_d_id); 15196 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15197 fcp_is_retryable(icmd)) { 15198 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15199 ret = DDI_SUCCESS; 15200 } 15201 break; 15202 15203 case FC_LOGINREQ: 15204 /* 15205 * FC_LOGINREQ used to be handled just like all the cases 15206 * above. It has been changed to handled a PRLI that fails 15207 * with FC_LOGINREQ different than other ipkts that fail 15208 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15209 * a simple matter to turn it into a PLOGI instead, so that's 15210 * exactly what we do here. 15211 */ 15212 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15213 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15214 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15215 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15216 } else { 15217 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15218 FCP_BUF_LEVEL_3, 0, 15219 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15220 rval, ptgt->tgt_d_id); 15221 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15222 fcp_is_retryable(icmd)) { 15223 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15224 ret = DDI_SUCCESS; 15225 } 15226 } 15227 break; 15228 15229 default: 15230 mutex_enter(&pptr->port_mutex); 15231 mutex_enter(&ptgt->tgt_mutex); 15232 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15233 mutex_exit(&ptgt->tgt_mutex); 15234 mutex_exit(&pptr->port_mutex); 15235 15236 (void) fc_ulp_error(rval, &error); 15237 fcp_log(CE_WARN, pptr->port_dip, 15238 "!Failed to send %s to D_ID=%x error=%s", 15239 op, ptgt->tgt_d_id, error); 15240 } else { 15241 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15242 fcp_trace, FCP_BUF_LEVEL_2, 0, 15243 "fcp_handle_ipkt_errors,1: state change occured" 15244 " for D_ID=0x%x", ptgt->tgt_d_id); 15245 mutex_exit(&ptgt->tgt_mutex); 15246 mutex_exit(&pptr->port_mutex); 15247 } 15248 break; 15249 } 15250 15251 return (ret); 15252 } 15253 15254 15255 /* 15256 * Check of outstanding commands on any LUN for this target 15257 */ 15258 static int 15259 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15260 { 15261 struct fcp_lun *plun; 15262 struct fcp_pkt *cmd; 15263 15264 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15265 mutex_enter(&plun->lun_mutex); 15266 for (cmd = plun->lun_pkt_head; cmd != NULL; 15267 cmd = cmd->cmd_forw) { 15268 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15269 mutex_exit(&plun->lun_mutex); 15270 return (FC_SUCCESS); 15271 } 15272 } 15273 mutex_exit(&plun->lun_mutex); 15274 } 15275 15276 return (FC_FAILURE); 15277 } 15278 15279 static fc_portmap_t * 15280 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15281 { 15282 int i; 15283 fc_portmap_t *devlist; 15284 fc_portmap_t *devptr = NULL; 15285 struct fcp_tgt *ptgt; 15286 15287 mutex_enter(&pptr->port_mutex); 15288 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15289 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15290 ptgt = ptgt->tgt_next) { 15291 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15292 ++*dev_cnt; 15293 } 15294 } 15295 } 15296 15297 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15298 KM_NOSLEEP); 15299 if (devlist == NULL) { 15300 mutex_exit(&pptr->port_mutex); 15301 fcp_log(CE_WARN, pptr->port_dip, 15302 "!fcp%d: failed to allocate for portmap for construct map", 15303 pptr->port_instance); 15304 return (devptr); 15305 } 15306 15307 for (i = 0; i < FCP_NUM_HASH; i++) { 15308 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15309 ptgt = ptgt->tgt_next) { 15310 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15311 int ret; 15312 15313 ret = fc_ulp_pwwn_to_portmap( 15314 pptr->port_fp_handle, 15315 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15316 devlist); 15317 15318 if (ret == FC_SUCCESS) { 15319 devlist++; 15320 continue; 15321 } 15322 15323 devlist->map_pd = NULL; 15324 devlist->map_did.port_id = ptgt->tgt_d_id; 15325 devlist->map_hard_addr.hard_addr = 15326 ptgt->tgt_hard_addr; 15327 15328 devlist->map_state = PORT_DEVICE_INVALID; 15329 devlist->map_type = PORT_DEVICE_OLD; 15330 15331 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15332 &devlist->map_nwwn, FC_WWN_SIZE); 15333 15334 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15335 &devlist->map_pwwn, FC_WWN_SIZE); 15336 15337 devlist++; 15338 } 15339 } 15340 } 15341 15342 mutex_exit(&pptr->port_mutex); 15343 15344 return (devptr); 15345 } 15346 /* 15347 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15348 */ 15349 static void 15350 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15351 { 15352 int i; 15353 struct fcp_tgt *ptgt; 15354 struct fcp_lun *plun; 15355 15356 for (i = 0; i < FCP_NUM_HASH; i++) { 15357 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15358 ptgt = ptgt->tgt_next) { 15359 mutex_enter(&ptgt->tgt_mutex); 15360 for (plun = ptgt->tgt_lun; plun != NULL; 15361 plun = plun->lun_next) { 15362 if (plun->lun_mpxio && 15363 plun->lun_state & FCP_LUN_BUSY) { 15364 if (!fcp_pass_to_hp(pptr, plun, 15365 plun->lun_cip, 15366 FCP_MPXIO_PATH_SET_BUSY, 15367 pptr->port_link_cnt, 15368 ptgt->tgt_change_cnt, 0, 0)) { 15369 FCP_TRACE(fcp_logq, 15370 pptr->port_instbuf, 15371 fcp_trace, 15372 FCP_BUF_LEVEL_2, 0, 15373 "path_verifybusy: " 15374 "disable lun %p failed!", 15375 plun); 15376 } 15377 } 15378 } 15379 mutex_exit(&ptgt->tgt_mutex); 15380 } 15381 } 15382 } 15383 15384 static int 15385 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15386 { 15387 dev_info_t *cdip = NULL; 15388 dev_info_t *pdip = NULL; 15389 15390 ASSERT(plun); 15391 15392 mutex_enter(&plun->lun_mutex); 15393 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15394 mutex_exit(&plun->lun_mutex); 15395 return (NDI_FAILURE); 15396 } 15397 mutex_exit(&plun->lun_mutex); 15398 cdip = mdi_pi_get_client(PIP(cip)); 15399 pdip = mdi_pi_get_phci(PIP(cip)); 15400 15401 ASSERT(cdip != NULL); 15402 ASSERT(pdip != NULL); 15403 15404 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15405 /* LUN ready for IO */ 15406 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15407 } else { 15408 /* LUN busy to accept IO */ 15409 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15410 } 15411 return (NDI_SUCCESS); 15412 } 15413 15414 /* 15415 * Caller must free the returned string of MAXPATHLEN len 15416 * If the device is offline (-1 instance number) NULL 15417 * will be returned. 15418 */ 15419 static char * 15420 fcp_get_lun_path(struct fcp_lun *plun) { 15421 dev_info_t *dip = NULL; 15422 char *path = NULL; 15423 if (plun == NULL) { 15424 return (NULL); 15425 } 15426 if (plun->lun_mpxio == 0) { 15427 dip = DIP(plun->lun_cip); 15428 } else { 15429 dip = mdi_pi_get_client(PIP(plun->lun_cip)); 15430 } 15431 if (dip == NULL) { 15432 return (NULL); 15433 } 15434 if (ddi_get_instance(dip) < 0) { 15435 return (NULL); 15436 } 15437 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15438 if (path == NULL) { 15439 return (NULL); 15440 } 15441 15442 (void) ddi_pathname(dip, path); 15443 /* 15444 * In reality, the user wants a fully valid path (one they can open) 15445 * but this string is lacking the mount point, and the minor node. 15446 * It would be nice if we could "figure these out" somehow 15447 * and fill them in. Otherwise, the userland code has to understand 15448 * driver specific details of which minor node is the "best" or 15449 * "right" one to expose. (Ex: which slice is the whole disk, or 15450 * which tape doesn't rewind) 15451 */ 15452 return (path); 15453 } 15454 15455 static int 15456 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15457 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15458 { 15459 int64_t reset_delay; 15460 int rval, retry = 0; 15461 struct fcp_port *pptr = fcp_dip2port(parent); 15462 15463 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15464 (lbolt64 - pptr->port_attach_time); 15465 if (reset_delay < 0) { 15466 reset_delay = 0; 15467 } 15468 15469 if (fcp_bus_config_debug) { 15470 flag |= NDI_DEVI_DEBUG; 15471 } 15472 15473 switch (op) { 15474 case BUS_CONFIG_ONE: 15475 /* 15476 * Retry the command since we need to ensure 15477 * the fabric devices are available for root 15478 */ 15479 while (retry++ < fcp_max_bus_config_retries) { 15480 rval = (ndi_busop_bus_config(parent, 15481 flag | NDI_MDI_FALLBACK, op, 15482 arg, childp, (clock_t)reset_delay)); 15483 if (rval == 0) { 15484 return (rval); 15485 } 15486 } 15487 15488 /* 15489 * drain taskq to make sure nodes are created and then 15490 * try again. 15491 */ 15492 taskq_wait(DEVI(parent)->devi_taskq); 15493 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15494 op, arg, childp, 0)); 15495 15496 case BUS_CONFIG_DRIVER: 15497 case BUS_CONFIG_ALL: { 15498 /* 15499 * delay till all devices report in (port_tmp_cnt == 0) 15500 * or FCP_INIT_WAIT_TIMEOUT 15501 */ 15502 mutex_enter(&pptr->port_mutex); 15503 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15504 (void) cv_timedwait(&pptr->port_config_cv, 15505 &pptr->port_mutex, 15506 ddi_get_lbolt() + (clock_t)reset_delay); 15507 reset_delay = 15508 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15509 (lbolt64 - pptr->port_attach_time); 15510 } 15511 mutex_exit(&pptr->port_mutex); 15512 /* drain taskq to make sure nodes are created */ 15513 taskq_wait(DEVI(parent)->devi_taskq); 15514 return (ndi_busop_bus_config(parent, flag, op, 15515 arg, childp, 0)); 15516 } 15517 15518 default: 15519 return (NDI_FAILURE); 15520 } 15521 /*NOTREACHED*/ 15522 } 15523 15524 static int 15525 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15526 ddi_bus_config_op_t op, void *arg) 15527 { 15528 if (fcp_bus_config_debug) { 15529 flag |= NDI_DEVI_DEBUG; 15530 } 15531 15532 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15533 } 15534 15535 15536 /* 15537 * Routine to copy GUID into the lun structure. 15538 * returns 0 if copy was successful and 1 if encountered a 15539 * failure and did not copy the guid. 15540 */ 15541 static int 15542 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15543 { 15544 15545 int retval = 0; 15546 15547 /* add one for the null terminator */ 15548 const unsigned int len = strlen(guidp) + 1; 15549 15550 if ((guidp == NULL) || (plun == NULL)) { 15551 return (1); 15552 } 15553 15554 /* 15555 * if the plun->lun_guid already has been allocated, 15556 * then check the size. if the size is exact, reuse 15557 * it....if not free it an allocate the required size. 15558 * The reallocation should NOT typically happen 15559 * unless the GUIDs reported changes between passes. 15560 * We free up and alloc again even if the 15561 * size was more than required. This is due to the 15562 * fact that the field lun_guid_size - serves 15563 * dual role of indicating the size of the wwn 15564 * size and ALSO the allocation size. 15565 */ 15566 if (plun->lun_guid) { 15567 if (plun->lun_guid_size != len) { 15568 /* 15569 * free the allocated memory and 15570 * initialize the field 15571 * lun_guid_size to 0. 15572 */ 15573 kmem_free(plun->lun_guid, plun->lun_guid_size); 15574 plun->lun_guid = NULL; 15575 plun->lun_guid_size = 0; 15576 } 15577 } 15578 /* 15579 * alloc only if not already done. 15580 */ 15581 if (plun->lun_guid == NULL) { 15582 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15583 if (plun->lun_guid == NULL) { 15584 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15585 "Unable to allocate" 15586 "Memory for GUID!!! size %d", len); 15587 retval = 1; 15588 } else { 15589 plun->lun_guid_size = len; 15590 } 15591 } 15592 if (plun->lun_guid) { 15593 /* 15594 * now copy the GUID 15595 */ 15596 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15597 } 15598 return (retval); 15599 } 15600 15601 /* 15602 * fcp_reconfig_wait 15603 * 15604 * Wait for a rediscovery/reconfiguration to complete before continuing. 15605 */ 15606 15607 static void 15608 fcp_reconfig_wait(struct fcp_port *pptr) 15609 { 15610 clock_t reconfig_start, wait_timeout; 15611 15612 /* 15613 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15614 * reconfiguration in progress. 15615 */ 15616 15617 mutex_enter(&pptr->port_mutex); 15618 if (pptr->port_tmp_cnt == 0) { 15619 mutex_exit(&pptr->port_mutex); 15620 return; 15621 } 15622 mutex_exit(&pptr->port_mutex); 15623 15624 /* 15625 * If we cause a reconfig by raising power, delay until all devices 15626 * report in (port_tmp_cnt returns to 0) 15627 */ 15628 15629 reconfig_start = ddi_get_lbolt(); 15630 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15631 15632 mutex_enter(&pptr->port_mutex); 15633 15634 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15635 pptr->port_tmp_cnt) { 15636 15637 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15638 reconfig_start + wait_timeout); 15639 } 15640 15641 mutex_exit(&pptr->port_mutex); 15642 15643 /* 15644 * Even if fcp_tmp_count isn't 0, continue without error. The port 15645 * we want may still be ok. If not, it will error out later 15646 */ 15647 } 15648 15649 /* 15650 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15651 * We rely on the fcp_global_mutex to provide protection against changes to 15652 * the fcp_lun_blacklist. 15653 * 15654 * You can describe a list of target port WWNs and LUN numbers which will 15655 * not be configured. LUN numbers will be interpreted as decimal. White 15656 * spaces and ',' can be used in the list of LUN numbers. 15657 * 15658 * To prevent LUNs 1 and 2 from being configured for target 15659 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15660 * 15661 * pwwn-lun-blacklist= 15662 * "510000f010fd92a1,1,2", 15663 * "510000e012079df1,1,2"; 15664 */ 15665 static void 15666 fcp_read_blacklist(dev_info_t *dip, 15667 struct fcp_black_list_entry **pplun_blacklist) { 15668 char **prop_array = NULL; 15669 char *curr_pwwn = NULL; 15670 char *curr_lun = NULL; 15671 uint32_t prop_item = 0; 15672 int idx = 0; 15673 int len = 0; 15674 15675 ASSERT(mutex_owned(&fcp_global_mutex)); 15676 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15677 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15678 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15679 return; 15680 } 15681 15682 for (idx = 0; idx < prop_item; idx++) { 15683 15684 curr_pwwn = prop_array[idx]; 15685 while (*curr_pwwn == ' ') { 15686 curr_pwwn++; 15687 } 15688 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15689 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15690 ", please check.", curr_pwwn); 15691 continue; 15692 } 15693 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15694 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15695 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15696 ", please check.", curr_pwwn); 15697 continue; 15698 } 15699 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15700 if (isxdigit(curr_pwwn[len]) != TRUE) { 15701 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15702 "blacklist, please check.", curr_pwwn); 15703 break; 15704 } 15705 } 15706 if (len != sizeof (la_wwn_t) * 2) { 15707 continue; 15708 } 15709 15710 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15711 *(curr_lun - 1) = '\0'; 15712 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15713 } 15714 15715 ddi_prop_free(prop_array); 15716 } 15717 15718 /* 15719 * Get the masking info about one remote target port designated by wwn. 15720 * Lun ids could be separated by ',' or white spaces. 15721 */ 15722 static void 15723 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15724 struct fcp_black_list_entry **pplun_blacklist) { 15725 int idx = 0; 15726 uint32_t offset = 0; 15727 unsigned long lun_id = 0; 15728 char lunid_buf[16]; 15729 char *pend = NULL; 15730 int illegal_digit = 0; 15731 15732 while (offset < strlen(curr_lun)) { 15733 while ((curr_lun[offset + idx] != ',') && 15734 (curr_lun[offset + idx] != '\0') && 15735 (curr_lun[offset + idx] != ' ')) { 15736 if (isdigit(curr_lun[offset + idx]) == 0) { 15737 illegal_digit++; 15738 } 15739 idx++; 15740 } 15741 if (illegal_digit > 0) { 15742 offset += (idx+1); /* To the start of next lun */ 15743 idx = 0; 15744 illegal_digit = 0; 15745 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15746 "the blacklist, please check digits.", 15747 curr_lun, curr_pwwn); 15748 continue; 15749 } 15750 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 15751 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15752 "the blacklist, please check the length of LUN#.", 15753 curr_lun, curr_pwwn); 15754 break; 15755 } 15756 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 15757 offset++; 15758 continue; 15759 } 15760 15761 bcopy(curr_lun + offset, lunid_buf, idx); 15762 lunid_buf[idx] = '\0'; 15763 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 15764 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 15765 } else { 15766 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 15767 "the blacklist, please check %s.", 15768 curr_lun, curr_pwwn, lunid_buf); 15769 } 15770 offset += (idx+1); /* To the start of next lun */ 15771 idx = 0; 15772 } 15773 } 15774 15775 /* 15776 * Add one masking record 15777 */ 15778 static void 15779 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 15780 struct fcp_black_list_entry **pplun_blacklist) { 15781 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15782 struct fcp_black_list_entry *new_entry = NULL; 15783 la_wwn_t wwn; 15784 15785 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 15786 while (tmp_entry) { 15787 if ((bcmp(&tmp_entry->wwn, &wwn, 15788 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 15789 return; 15790 } 15791 15792 tmp_entry = tmp_entry->next; 15793 } 15794 15795 /* add to black list */ 15796 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 15797 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 15798 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 15799 new_entry->lun = lun_id; 15800 new_entry->masked = 0; 15801 new_entry->next = *pplun_blacklist; 15802 *pplun_blacklist = new_entry; 15803 } 15804 15805 /* 15806 * Check if we should mask the specified lun of this fcp_tgt 15807 */ 15808 static int 15809 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 15810 struct fcp_black_list_entry *remote_port; 15811 15812 remote_port = fcp_lun_blacklist; 15813 while (remote_port != NULL) { 15814 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 15815 if (remote_port->lun == lun_id) { 15816 remote_port->masked++; 15817 if (remote_port->masked == 1) { 15818 fcp_log(CE_NOTE, NULL, "LUN %d of port " 15819 "%02x%02x%02x%02x%02x%02x%02x%02x " 15820 "is masked due to black listing.\n", 15821 lun_id, wwn->raw_wwn[0], 15822 wwn->raw_wwn[1], wwn->raw_wwn[2], 15823 wwn->raw_wwn[3], wwn->raw_wwn[4], 15824 wwn->raw_wwn[5], wwn->raw_wwn[6], 15825 wwn->raw_wwn[7]); 15826 } 15827 return (TRUE); 15828 } 15829 } 15830 remote_port = remote_port->next; 15831 } 15832 return (FALSE); 15833 } 15834 15835 /* 15836 * Release all allocated resources 15837 */ 15838 static void 15839 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 15840 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 15841 struct fcp_black_list_entry *current_entry = NULL; 15842 15843 ASSERT(mutex_owned(&fcp_global_mutex)); 15844 /* 15845 * Traverse all luns 15846 */ 15847 while (tmp_entry) { 15848 current_entry = tmp_entry; 15849 tmp_entry = tmp_entry->next; 15850 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 15851 } 15852 *pplun_blacklist = NULL; 15853 } 15854