XXXX introduce drv_sectohz
1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 * 24 * Fibre Channel SCSI ULP Mapping driver 25 */ 26 27 #include <sys/scsi/scsi.h> 28 #include <sys/types.h> 29 #include <sys/varargs.h> 30 #include <sys/devctl.h> 31 #include <sys/thread.h> 32 #include <sys/thread.h> 33 #include <sys/open.h> 34 #include <sys/file.h> 35 #include <sys/sunndi.h> 36 #include <sys/console.h> 37 #include <sys/proc.h> 38 #include <sys/time.h> 39 #include <sys/utsname.h> 40 #include <sys/scsi/impl/scsi_reset_notify.h> 41 #include <sys/ndi_impldefs.h> 42 #include <sys/byteorder.h> 43 #include <sys/fs/dv_node.h> 44 #include <sys/ctype.h> 45 #include <sys/sunmdi.h> 46 47 #include <sys/fibre-channel/fc.h> 48 #include <sys/fibre-channel/impl/fc_ulpif.h> 49 #include <sys/fibre-channel/ulp/fcpvar.h> 50 51 /* 52 * Discovery Process 53 * ================= 54 * 55 * The discovery process is a major function of FCP. In order to help 56 * understand that function a flow diagram is given here. This diagram 57 * doesn't claim to cover all the cases and the events that can occur during 58 * the discovery process nor the subtleties of the code. The code paths shown 59 * are simplified. Its purpose is to help the reader (and potentially bug 60 * fixer) have an overall view of the logic of the code. For that reason the 61 * diagram covers the simple case of the line coming up cleanly or of a new 62 * port attaching to FCP the link being up. The reader must keep in mind 63 * that: 64 * 65 * - There are special cases where bringing devices online and offline 66 * is driven by Ioctl. 67 * 68 * - The behavior of the discovery process can be modified through the 69 * .conf file. 70 * 71 * - The line can go down and come back up at any time during the 72 * discovery process which explains some of the complexity of the code. 73 * 74 * ............................................................................ 75 * 76 * STEP 1: The line comes up or a new Fibre Channel port attaches to FCP. 77 * 78 * 79 * +-------------------------+ 80 * fp/fctl module --->| fcp_port_attach | 81 * +-------------------------+ 82 * | | 83 * | | 84 * | v 85 * | +-------------------------+ 86 * | | fcp_handle_port_attach | 87 * | +-------------------------+ 88 * | | 89 * | | 90 * +--------------------+ | 91 * | | 92 * v v 93 * +-------------------------+ 94 * | fcp_statec_callback | 95 * +-------------------------+ 96 * | 97 * | 98 * v 99 * +-------------------------+ 100 * | fcp_handle_devices | 101 * +-------------------------+ 102 * | 103 * | 104 * v 105 * +-------------------------+ 106 * | fcp_handle_mapflags | 107 * +-------------------------+ 108 * | 109 * | 110 * v 111 * +-------------------------+ 112 * | fcp_send_els | 113 * | | 114 * | PLOGI or PRLI To all the| 115 * | reachable devices. | 116 * +-------------------------+ 117 * 118 * 119 * ............................................................................ 120 * 121 * STEP 2: The callback functions of the PLOGI and/or PRLI requests sent during 122 * STEP 1 are called (it is actually the same function). 123 * 124 * 125 * +-------------------------+ 126 * | fcp_icmd_callback | 127 * fp/fctl module --->| | 128 * | callback for PLOGI and | 129 * | PRLI. | 130 * +-------------------------+ 131 * | 132 * | 133 * Received PLOGI Accept /-\ Received PRLI Accept 134 * _ _ _ _ _ _ / \_ _ _ _ _ _ 135 * | \ / | 136 * | \-/ | 137 * | | 138 * v v 139 * +-------------------------+ +-------------------------+ 140 * | fcp_send_els | | fcp_send_scsi | 141 * | | | | 142 * | PRLI | | REPORT_LUN | 143 * +-------------------------+ +-------------------------+ 144 * 145 * ............................................................................ 146 * 147 * STEP 3: The callback functions of the SCSI commands issued by FCP are called 148 * (It is actually the same function). 149 * 150 * 151 * +-------------------------+ 152 * fp/fctl module ------->| fcp_scsi_callback | 153 * +-------------------------+ 154 * | 155 * | 156 * | 157 * Receive REPORT_LUN reply /-\ Receive INQUIRY PAGE83 reply 158 * _ _ _ _ _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ _ _ _ _ 159 * | \ / | 160 * | \-/ | 161 * | | | 162 * | Receive INQUIRY reply| | 163 * | | | 164 * v v v 165 * +------------------------+ +----------------------+ +----------------------+ 166 * | fcp_handle_reportlun | | fcp_handle_inquiry | | fcp_handle_page83 | 167 * |(Called for each Target)| | (Called for each LUN)| |(Called for each LUN) | 168 * +------------------------+ +----------------------+ +----------------------+ 169 * | | | 170 * | | | 171 * | | | 172 * v v | 173 * +-----------------+ +-----------------+ | 174 * | fcp_send_scsi | | fcp_send_scsi | | 175 * | | | | | 176 * | INQUIRY | | INQUIRY PAGE83 | | 177 * | (To each LUN) | +-----------------+ | 178 * +-----------------+ | 179 * | 180 * v 181 * +------------------------+ 182 * | fcp_call_finish_init | 183 * +------------------------+ 184 * | 185 * v 186 * +-----------------------------+ 187 * | fcp_call_finish_init_held | 188 * +-----------------------------+ 189 * | 190 * | 191 * All LUNs scanned /-\ 192 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ __ / \ 193 * | \ / 194 * | \-/ 195 * v | 196 * +------------------+ | 197 * | fcp_finish_tgt | | 198 * +------------------+ | 199 * | Target Not Offline and | 200 * Target Not Offline and | not marked and tgt_node_state | 201 * marked /-\ not FCP_TGT_NODE_ON_DEMAND | 202 * _ _ _ _ _ _ / \_ _ _ _ _ _ _ _ | 203 * | \ / | | 204 * | \-/ | | 205 * v v | 206 * +----------------------------+ +-------------------+ | 207 * | fcp_offline_target | | fcp_create_luns | | 208 * | | +-------------------+ | 209 * | A structure fcp_tgt_elem | | | 210 * | is created and queued in | v | 211 * | the FCP port list | +-------------------+ | 212 * | port_offline_tgts. It | | fcp_pass_to_hp | | 213 * | will be unqueued by the | | | | 214 * | watchdog timer. | | Called for each | | 215 * +----------------------------+ | LUN. Dispatches | | 216 * | | fcp_hp_task | | 217 * | +-------------------+ | 218 * | | | 219 * | | | 220 * | | | 221 * | +---------------->| 222 * | | 223 * +---------------------------------------------->| 224 * | 225 * | 226 * All the targets (devices) have been scanned /-\ 227 * _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ / \ 228 * | \ / 229 * | \-/ 230 * +-------------------------------------+ | 231 * | fcp_finish_init | | 232 * | | | 233 * | Signal broadcasts the condition | | 234 * | variable port_config_cv of the FCP | | 235 * | port. One potential code sequence | | 236 * | waiting on the condition variable | | 237 * | the code sequence handling | | 238 * | BUS_CONFIG_ALL and BUS_CONFIG_DRIVER| | 239 * | The other is in the function | | 240 * | fcp_reconfig_wait which is called | | 241 * | in the transmit path preventing IOs | | 242 * | from going through till the disco- | | 243 * | very process is over. | | 244 * +-------------------------------------+ | 245 * | | 246 * | | 247 * +--------------------------------->| 248 * | 249 * v 250 * Return 251 * 252 * ............................................................................ 253 * 254 * STEP 4: The hot plug task is called (for each fcp_hp_elem). 255 * 256 * 257 * +-------------------------+ 258 * | fcp_hp_task | 259 * +-------------------------+ 260 * | 261 * | 262 * v 263 * +-------------------------+ 264 * | fcp_trigger_lun | 265 * +-------------------------+ 266 * | 267 * | 268 * v 269 * Bring offline /-\ Bring online 270 * _ _ _ _ _ _ _ _ _/ \_ _ _ _ _ _ _ _ _ _ 271 * | \ / | 272 * | \-/ | 273 * v v 274 * +---------------------+ +-----------------------+ 275 * | fcp_offline_child | | fcp_get_cip | 276 * +---------------------+ | | 277 * | Creates a dev_info_t | 278 * | or a mdi_pathinfo_t | 279 * | depending on whether | 280 * | mpxio is on or off. | 281 * +-----------------------+ 282 * | 283 * | 284 * v 285 * +-----------------------+ 286 * | fcp_online_child | 287 * | | 288 * | Set device online | 289 * | using NDI or MDI. | 290 * +-----------------------+ 291 * 292 * ............................................................................ 293 * 294 * STEP 5: The watchdog timer expires. The watch dog timer does much more that 295 * what is described here. We only show the target offline path. 296 * 297 * 298 * +--------------------------+ 299 * | fcp_watch | 300 * +--------------------------+ 301 * | 302 * | 303 * v 304 * +--------------------------+ 305 * | fcp_scan_offline_tgts | 306 * +--------------------------+ 307 * | 308 * | 309 * v 310 * +--------------------------+ 311 * | fcp_offline_target_now | 312 * +--------------------------+ 313 * | 314 * | 315 * v 316 * +--------------------------+ 317 * | fcp_offline_tgt_luns | 318 * +--------------------------+ 319 * | 320 * | 321 * v 322 * +--------------------------+ 323 * | fcp_offline_lun | 324 * +--------------------------+ 325 * | 326 * | 327 * v 328 * +----------------------------------+ 329 * | fcp_offline_lun_now | 330 * | | 331 * | A request (or two if mpxio) is | 332 * | sent to the hot plug task using | 333 * | a fcp_hp_elem structure. | 334 * +----------------------------------+ 335 */ 336 337 /* 338 * Functions registered with DDI framework 339 */ 340 static int fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 341 static int fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 342 static int fcp_open(dev_t *devp, int flag, int otype, cred_t *credp); 343 static int fcp_close(dev_t dev, int flag, int otype, cred_t *credp); 344 static int fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, 345 cred_t *credp, int *rval); 346 347 /* 348 * Functions registered with FC Transport framework 349 */ 350 static int fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 351 fc_attach_cmd_t cmd, uint32_t s_id); 352 static int fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 353 fc_detach_cmd_t cmd); 354 static int fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, 355 int cmd, intptr_t data, int mode, cred_t *credp, int *rval, 356 uint32_t claimed); 357 static int fcp_els_callback(opaque_t ulph, opaque_t port_handle, 358 fc_unsol_buf_t *buf, uint32_t claimed); 359 static int fcp_data_callback(opaque_t ulph, opaque_t port_handle, 360 fc_unsol_buf_t *buf, uint32_t claimed); 361 static void fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 362 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 363 uint32_t dev_cnt, uint32_t port_sid); 364 365 /* 366 * Functions registered with SCSA framework 367 */ 368 static int fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 369 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 370 static int fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 371 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 372 static void fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 373 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 374 static int fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 375 static int fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 376 static int fcp_scsi_reset(struct scsi_address *ap, int level); 377 static int fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom); 378 static int fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, 379 int whom); 380 static void fcp_pkt_teardown(struct scsi_pkt *pkt); 381 static int fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 382 void (*callback)(caddr_t), caddr_t arg); 383 static int fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, 384 char *name, ddi_eventcookie_t *event_cookiep); 385 static int fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 386 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 387 ddi_callback_id_t *cb_id); 388 static int fcp_scsi_bus_remove_eventcall(dev_info_t *devi, 389 ddi_callback_id_t cb_id); 390 static int fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 391 ddi_eventcookie_t eventid, void *impldata); 392 static int fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 393 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 394 static int fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 395 ddi_bus_config_op_t op, void *arg); 396 397 /* 398 * Internal functions 399 */ 400 static int fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, 401 int mode, int *rval); 402 403 static int fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 404 int mode, int *rval); 405 static int fcp_copyin_scsi_cmd(caddr_t base_addr, 406 struct fcp_scsi_cmd *fscsi, int mode); 407 static int fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, 408 caddr_t base_addr, int mode); 409 static int fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi); 410 411 static struct fcp_tgt *fcp_port_create_tgt(struct fcp_port *pptr, 412 la_wwn_t *pwwn, int *ret_val, int *fc_status, int *fc_pkt_state, 413 int *fc_pkt_reason, int *fc_pkt_action); 414 static int fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, 415 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 416 static int fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, 417 int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action); 418 static void fcp_ipkt_sema_init(struct fcp_ipkt *icmd); 419 static int fcp_ipkt_sema_wait(struct fcp_ipkt *icmd); 420 static void fcp_ipkt_sema_callback(struct fc_packet *fpkt); 421 static void fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd); 422 423 static void fcp_handle_devices(struct fcp_port *pptr, 424 fc_portmap_t devlist[], uint32_t dev_cnt, int link_cnt, 425 fcp_map_tag_t *map_tag, int cause); 426 static int fcp_handle_mapflags(struct fcp_port *pptr, 427 struct fcp_tgt *ptgt, fc_portmap_t *map_entry, int link_cnt, 428 int tgt_cnt, int cause); 429 static int fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause); 430 static int fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 431 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause); 432 static void fcp_update_state(struct fcp_port *pptr, uint32_t state, 433 int cause); 434 static void fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, 435 uint32_t state); 436 static struct fcp_port *fcp_get_port(opaque_t port_handle); 437 static void fcp_unsol_callback(fc_packet_t *fpkt); 438 static void fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 439 uchar_t r_ctl, uchar_t type); 440 static int fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf); 441 static struct fcp_ipkt *fcp_icmd_alloc(struct fcp_port *pptr, 442 struct fcp_tgt *ptgt, int cmd_len, int resp_len, int data_len, 443 int nodma, int lcount, int tcount, int cause, uint32_t rscn_count); 444 static void fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd); 445 static int fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 446 int nodma, int flags); 447 static void fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd); 448 static struct fcp_tgt *fcp_lookup_target(struct fcp_port *pptr, 449 uchar_t *wwn); 450 static struct fcp_tgt *fcp_get_target_by_did(struct fcp_port *pptr, 451 uint32_t d_id); 452 static void fcp_icmd_callback(fc_packet_t *fpkt); 453 static int fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, 454 int len, int lcount, int tcount, int cause, uint32_t rscn_count); 455 static int fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt); 456 static void fcp_scsi_callback(fc_packet_t *fpkt); 457 static void fcp_retry_scsi_cmd(fc_packet_t *fpkt); 458 static void fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 459 static void fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd); 460 static struct fcp_lun *fcp_get_lun(struct fcp_tgt *ptgt, 461 uint16_t lun_num); 462 static int fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 463 int link_cnt, int tgt_cnt, int cause); 464 static void fcp_finish_init(struct fcp_port *pptr); 465 static void fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, 466 int tgt_cnt, int cause); 467 static int fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, 468 int old_mpxio, int online, int link_cnt, int tgt_cnt, int flags); 469 static int fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 470 int link_cnt, int tgt_cnt, int nowait, int flags); 471 static void fcp_offline_target_now(struct fcp_port *pptr, 472 struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int flags); 473 static void fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, 474 int tgt_cnt, int flags); 475 static void fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 476 int nowait, int flags); 477 static void fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, 478 int tgt_cnt); 479 static void fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, 480 int tgt_cnt, int flags); 481 static void fcp_scan_offline_luns(struct fcp_port *pptr); 482 static void fcp_scan_offline_tgts(struct fcp_port *pptr); 483 static void fcp_update_offline_flags(struct fcp_lun *plun); 484 static struct fcp_pkt *fcp_scan_commands(struct fcp_lun *plun); 485 static void fcp_abort_commands(struct fcp_pkt *head, struct 486 fcp_port *pptr); 487 static void fcp_cmd_callback(fc_packet_t *fpkt); 488 static void fcp_complete_pkt(fc_packet_t *fpkt); 489 static int fcp_validate_fcp_response(struct fcp_rsp *rsp, 490 struct fcp_port *pptr); 491 static int fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 492 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause); 493 static struct fcp_lun *fcp_alloc_lun(struct fcp_tgt *ptgt); 494 static void fcp_dealloc_lun(struct fcp_lun *plun); 495 static struct fcp_tgt *fcp_alloc_tgt(struct fcp_port *pptr, 496 fc_portmap_t *map_entry, int link_cnt); 497 static void fcp_dealloc_tgt(struct fcp_tgt *ptgt); 498 static void fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt); 499 static int fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, 500 int internal); 501 static void fcp_log(int level, dev_info_t *dip, const char *fmt, ...); 502 static int fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 503 uint32_t s_id, int instance); 504 static int fcp_handle_port_detach(struct fcp_port *pptr, int flag, 505 int instance); 506 static void fcp_cleanup_port(struct fcp_port *pptr, int instance); 507 static int fcp_kmem_cache_constructor(struct scsi_pkt *, scsi_hba_tran_t *, 508 int); 509 static void fcp_kmem_cache_destructor(struct scsi_pkt *, scsi_hba_tran_t *); 510 static int fcp_pkt_setup(struct scsi_pkt *, int (*)(), caddr_t); 511 static int fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, 512 int flags); 513 static void fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt); 514 static int fcp_reset_target(struct scsi_address *ap, int level); 515 static int fcp_commoncap(struct scsi_address *ap, char *cap, 516 int val, int tgtonly, int doset); 517 static int fcp_scsi_get_name(struct scsi_device *sd, char *name, int len); 518 static int fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len); 519 static int fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, 520 int sleep); 521 static int fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 522 uint32_t s_id, fc_attach_cmd_t cmd, int instance); 523 static void fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo); 524 static void fcp_process_elem(struct fcp_hp_elem *elem, int result); 525 static child_info_t *fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, 526 int lcount, int tcount); 527 static int fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip); 528 static int fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip); 529 static dev_info_t *fcp_create_dip(struct fcp_lun *plun, int link_cnt, 530 int tgt_cnt); 531 static dev_info_t *fcp_find_existing_dip(struct fcp_lun *plun, 532 dev_info_t *pdip, caddr_t name); 533 static int fcp_online_child(struct fcp_lun *plun, child_info_t *cip, 534 int lcount, int tcount, int flags, int *circ); 535 static int fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, 536 int lcount, int tcount, int flags, int *circ); 537 static void fcp_remove_child(struct fcp_lun *plun); 538 static void fcp_watch(void *arg); 539 static void fcp_check_reset_delay(struct fcp_port *pptr); 540 static void fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 541 struct fcp_lun *rlun, int tgt_cnt); 542 struct fcp_port *fcp_soft_state_unlink(struct fcp_port *pptr); 543 static struct fcp_lun *fcp_lookup_lun(struct fcp_port *pptr, 544 uchar_t *wwn, uint16_t lun); 545 static void fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 546 struct fcp_lun *plun); 547 static void fcp_post_callback(struct fcp_pkt *cmd); 548 static int fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd); 549 static struct fcp_port *fcp_dip2port(dev_info_t *dip); 550 struct fcp_lun *fcp_get_lun_from_cip(struct fcp_port *pptr, 551 child_info_t *cip); 552 static int fcp_pass_to_hp_and_wait(struct fcp_port *pptr, 553 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 554 int tgt_cnt, int flags); 555 static struct fcp_hp_elem *fcp_pass_to_hp(struct fcp_port *pptr, 556 struct fcp_lun *plun, child_info_t *cip, int what, int link_cnt, 557 int tgt_cnt, int flags, int wait); 558 static void fcp_retransport_cmd(struct fcp_port *pptr, 559 struct fcp_pkt *cmd); 560 static void fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, 561 uint_t statistics); 562 static void fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd); 563 static void fcp_update_targets(struct fcp_port *pptr, 564 fc_portmap_t *dev_list, uint32_t count, uint32_t state, int cause); 565 static int fcp_call_finish_init(struct fcp_port *pptr, 566 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 567 static int fcp_call_finish_init_held(struct fcp_port *pptr, 568 struct fcp_tgt *ptgt, int lcount, int tcount, int cause); 569 static void fcp_reconfigure_luns(void * tgt_handle); 570 static void fcp_free_targets(struct fcp_port *pptr); 571 static void fcp_free_target(struct fcp_tgt *ptgt); 572 static int fcp_is_retryable(struct fcp_ipkt *icmd); 573 static int fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn); 574 static void fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int); 575 static void fcp_wwn_to_ascii(uchar_t bytes[], char *string); 576 static void fcp_print_error(fc_packet_t *fpkt); 577 static int fcp_handle_ipkt_errors(struct fcp_port *pptr, 578 struct fcp_tgt *ptgt, struct fcp_ipkt *icmd, int rval, caddr_t op); 579 static int fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt); 580 static fc_portmap_t *fcp_construct_map(struct fcp_port *pptr, 581 uint32_t *dev_cnt); 582 static void fcp_offline_all(struct fcp_port *pptr, int lcount, int cause); 583 static int fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval); 584 static int fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *, int, int *, 585 struct fcp_ioctl *, struct fcp_port **); 586 static char *fcp_get_lun_path(struct fcp_lun *plun); 587 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 588 int *rval); 589 static int fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id); 590 static void fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id); 591 static char *fcp_get_lun_path(struct fcp_lun *plun); 592 static int fcp_get_target_mappings(struct fcp_ioctl *data, int mode, 593 int *rval); 594 static void fcp_reconfig_wait(struct fcp_port *pptr); 595 596 /* 597 * New functions added for mpxio support 598 */ 599 static int fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 600 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 601 static mdi_pathinfo_t *fcp_create_pip(struct fcp_lun *plun, int lcount, 602 int tcount); 603 static mdi_pathinfo_t *fcp_find_existing_pip(struct fcp_lun *plun, 604 dev_info_t *pdip); 605 static int fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip); 606 static void fcp_handle_page83(fc_packet_t *, struct fcp_ipkt *, int); 607 static void fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr); 608 static int fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp); 609 static int fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, 610 int what); 611 static int fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 612 fc_packet_t *fpkt); 613 static int fcp_symmetric_device_probe(struct fcp_lun *plun); 614 615 /* 616 * New functions added for lun masking support 617 */ 618 static void fcp_read_blacklist(dev_info_t *dip, 619 struct fcp_black_list_entry **pplun_blacklist); 620 static void fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 621 struct fcp_black_list_entry **pplun_blacklist); 622 static void fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 623 struct fcp_black_list_entry **pplun_blacklist); 624 static int fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id); 625 static void fcp_cleanup_blacklist(struct fcp_black_list_entry **lun_blacklist); 626 627 /* 628 * New functions to support software FCA (like fcoei) 629 */ 630 static struct scsi_pkt *fcp_pseudo_init_pkt( 631 struct scsi_address *ap, struct scsi_pkt *pkt, 632 struct buf *bp, int cmdlen, int statuslen, 633 int tgtlen, int flags, int (*callback)(), caddr_t arg); 634 static void fcp_pseudo_destroy_pkt( 635 struct scsi_address *ap, struct scsi_pkt *pkt); 636 static void fcp_pseudo_sync_pkt( 637 struct scsi_address *ap, struct scsi_pkt *pkt); 638 static int fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt); 639 static void fcp_pseudo_dmafree( 640 struct scsi_address *ap, struct scsi_pkt *pkt); 641 642 extern struct mod_ops mod_driverops; 643 /* 644 * This variable is defined in modctl.c and set to '1' after the root driver 645 * and fs are loaded. It serves as an indication that the root filesystem can 646 * be used. 647 */ 648 extern int modrootloaded; 649 /* 650 * This table contains strings associated with the SCSI sense key codes. It 651 * is used by FCP to print a clear explanation of the code returned in the 652 * sense information by a device. 653 */ 654 extern char *sense_keys[]; 655 /* 656 * This device is created by the SCSI pseudo nexus driver (SCSI vHCI). It is 657 * under this device that the paths to a physical device are created when 658 * MPxIO is used. 659 */ 660 extern dev_info_t *scsi_vhci_dip; 661 662 /* 663 * Report lun processing 664 */ 665 #define FCP_LUN_ADDRESSING 0x80 666 #define FCP_PD_ADDRESSING 0x00 667 #define FCP_VOLUME_ADDRESSING 0x40 668 669 #define FCP_SVE_THROTTLE 0x28 /* Vicom */ 670 #define MAX_INT_DMA 0x7fffffff 671 /* 672 * Property definitions 673 */ 674 #define NODE_WWN_PROP (char *)fcp_node_wwn_prop 675 #define PORT_WWN_PROP (char *)fcp_port_wwn_prop 676 #define TARGET_PROP (char *)fcp_target_prop 677 #define LUN_PROP (char *)fcp_lun_prop 678 #define SAM_LUN_PROP (char *)fcp_sam_lun_prop 679 #define CONF_WWN_PROP (char *)fcp_conf_wwn_prop 680 #define OBP_BOOT_WWN (char *)fcp_obp_boot_wwn 681 #define MANUAL_CFG_ONLY (char *)fcp_manual_config_only 682 #define INIT_PORT_PROP (char *)fcp_init_port_prop 683 #define TGT_PORT_PROP (char *)fcp_tgt_port_prop 684 #define LUN_BLACKLIST_PROP (char *)fcp_lun_blacklist_prop 685 /* 686 * Short hand macros. 687 */ 688 #define LUN_PORT (plun->lun_tgt->tgt_port) 689 #define LUN_TGT (plun->lun_tgt) 690 691 /* 692 * Driver private macros 693 */ 694 #define FCP_ATOB(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : \ 695 ((x) >= 'a' && (x) <= 'f') ? \ 696 ((x) - 'a' + 10) : ((x) - 'A' + 10)) 697 698 #define FCP_MAX(a, b) ((a) > (b) ? (a) : (b)) 699 700 #define FCP_N_NDI_EVENTS \ 701 (sizeof (fcp_ndi_event_defs) / sizeof (ndi_event_definition_t)) 702 703 #define FCP_LINK_STATE_CHANGED(p, c) \ 704 ((p)->port_link_cnt != (c)->ipkt_link_cnt) 705 706 #define FCP_TGT_STATE_CHANGED(t, c) \ 707 ((t)->tgt_change_cnt != (c)->ipkt_change_cnt) 708 709 #define FCP_STATE_CHANGED(p, t, c) \ 710 (FCP_TGT_STATE_CHANGED(t, c)) 711 712 #define FCP_MUST_RETRY(fpkt) \ 713 ((fpkt)->pkt_state == FC_PKT_LOCAL_BSY || \ 714 (fpkt)->pkt_state == FC_PKT_LOCAL_RJT || \ 715 (fpkt)->pkt_state == FC_PKT_TRAN_BSY || \ 716 (fpkt)->pkt_state == FC_PKT_ELS_IN_PROGRESS || \ 717 (fpkt)->pkt_state == FC_PKT_NPORT_BSY || \ 718 (fpkt)->pkt_state == FC_PKT_FABRIC_BSY || \ 719 (fpkt)->pkt_state == FC_PKT_PORT_OFFLINE || \ 720 (fpkt)->pkt_reason == FC_REASON_OFFLINE) 721 722 #define FCP_SENSE_REPORTLUN_CHANGED(es) \ 723 ((es)->es_key == KEY_UNIT_ATTENTION && \ 724 (es)->es_add_code == 0x3f && \ 725 (es)->es_qual_code == 0x0e) 726 727 #define FCP_SENSE_NO_LUN(es) \ 728 ((es)->es_key == KEY_ILLEGAL_REQUEST && \ 729 (es)->es_add_code == 0x25 && \ 730 (es)->es_qual_code == 0x0) 731 732 #define FCP_VERSION "20091208-1.192" 733 #define FCP_NAME_VERSION "SunFC FCP v" FCP_VERSION 734 735 #define FCP_NUM_ELEMENTS(array) \ 736 (sizeof (array) / sizeof ((array)[0])) 737 738 /* 739 * Debugging, Error reporting, and tracing 740 */ 741 #define FCP_LOG_SIZE 1024 * 1024 742 743 #define FCP_LEVEL_1 0x00001 /* attach/detach PM CPR */ 744 #define FCP_LEVEL_2 0x00002 /* failures/Invalid data */ 745 #define FCP_LEVEL_3 0x00004 /* state change, discovery */ 746 #define FCP_LEVEL_4 0x00008 /* ULP messages */ 747 #define FCP_LEVEL_5 0x00010 /* ELS/SCSI cmds */ 748 #define FCP_LEVEL_6 0x00020 /* Transport failures */ 749 #define FCP_LEVEL_7 0x00040 750 #define FCP_LEVEL_8 0x00080 /* I/O tracing */ 751 #define FCP_LEVEL_9 0x00100 /* I/O tracing */ 752 753 754 755 /* 756 * Log contents to system messages file 757 */ 758 #define FCP_MSG_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_MSG) 759 #define FCP_MSG_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_MSG) 760 #define FCP_MSG_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_MSG) 761 #define FCP_MSG_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_MSG) 762 #define FCP_MSG_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_MSG) 763 #define FCP_MSG_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_MSG) 764 #define FCP_MSG_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_MSG) 765 #define FCP_MSG_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_MSG) 766 #define FCP_MSG_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_MSG) 767 768 769 /* 770 * Log contents to trace buffer 771 */ 772 #define FCP_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF) 773 #define FCP_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF) 774 #define FCP_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF) 775 #define FCP_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF) 776 #define FCP_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF) 777 #define FCP_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF) 778 #define FCP_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF) 779 #define FCP_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF) 780 #define FCP_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF) 781 782 783 /* 784 * Log contents to both system messages file and trace buffer 785 */ 786 #define FCP_MSG_BUF_LEVEL_1 (FCP_LEVEL_1 | FC_TRACE_LOG_BUF | \ 787 FC_TRACE_LOG_MSG) 788 #define FCP_MSG_BUF_LEVEL_2 (FCP_LEVEL_2 | FC_TRACE_LOG_BUF | \ 789 FC_TRACE_LOG_MSG) 790 #define FCP_MSG_BUF_LEVEL_3 (FCP_LEVEL_3 | FC_TRACE_LOG_BUF | \ 791 FC_TRACE_LOG_MSG) 792 #define FCP_MSG_BUF_LEVEL_4 (FCP_LEVEL_4 | FC_TRACE_LOG_BUF | \ 793 FC_TRACE_LOG_MSG) 794 #define FCP_MSG_BUF_LEVEL_5 (FCP_LEVEL_5 | FC_TRACE_LOG_BUF | \ 795 FC_TRACE_LOG_MSG) 796 #define FCP_MSG_BUF_LEVEL_6 (FCP_LEVEL_6 | FC_TRACE_LOG_BUF | \ 797 FC_TRACE_LOG_MSG) 798 #define FCP_MSG_BUF_LEVEL_7 (FCP_LEVEL_7 | FC_TRACE_LOG_BUF | \ 799 FC_TRACE_LOG_MSG) 800 #define FCP_MSG_BUF_LEVEL_8 (FCP_LEVEL_8 | FC_TRACE_LOG_BUF | \ 801 FC_TRACE_LOG_MSG) 802 #define FCP_MSG_BUF_LEVEL_9 (FCP_LEVEL_9 | FC_TRACE_LOG_BUF | \ 803 FC_TRACE_LOG_MSG) 804 #ifdef DEBUG 805 #define FCP_DTRACE fc_trace_debug 806 #else 807 #define FCP_DTRACE 808 #endif 809 810 #define FCP_TRACE fc_trace_debug 811 812 static struct cb_ops fcp_cb_ops = { 813 fcp_open, /* open */ 814 fcp_close, /* close */ 815 nodev, /* strategy */ 816 nodev, /* print */ 817 nodev, /* dump */ 818 nodev, /* read */ 819 nodev, /* write */ 820 fcp_ioctl, /* ioctl */ 821 nodev, /* devmap */ 822 nodev, /* mmap */ 823 nodev, /* segmap */ 824 nochpoll, /* chpoll */ 825 ddi_prop_op, /* cb_prop_op */ 826 0, /* streamtab */ 827 D_NEW | D_MP | D_HOTPLUG, /* cb_flag */ 828 CB_REV, /* rev */ 829 nodev, /* aread */ 830 nodev /* awrite */ 831 }; 832 833 834 static struct dev_ops fcp_ops = { 835 DEVO_REV, 836 0, 837 ddi_getinfo_1to1, 838 nulldev, /* identify */ 839 nulldev, /* probe */ 840 fcp_attach, /* attach and detach are mandatory */ 841 fcp_detach, 842 nodev, /* reset */ 843 &fcp_cb_ops, /* cb_ops */ 844 NULL, /* bus_ops */ 845 NULL, /* power */ 846 }; 847 848 849 char *fcp_version = FCP_NAME_VERSION; 850 851 static struct modldrv modldrv = { 852 &mod_driverops, 853 FCP_NAME_VERSION, 854 &fcp_ops 855 }; 856 857 858 static struct modlinkage modlinkage = { 859 MODREV_1, 860 &modldrv, 861 NULL 862 }; 863 864 865 static fc_ulp_modinfo_t fcp_modinfo = { 866 &fcp_modinfo, /* ulp_handle */ 867 FCTL_ULP_MODREV_4, /* ulp_rev */ 868 FC4_SCSI_FCP, /* ulp_type */ 869 "fcp", /* ulp_name */ 870 FCP_STATEC_MASK, /* ulp_statec_mask */ 871 fcp_port_attach, /* ulp_port_attach */ 872 fcp_port_detach, /* ulp_port_detach */ 873 fcp_port_ioctl, /* ulp_port_ioctl */ 874 fcp_els_callback, /* ulp_els_callback */ 875 fcp_data_callback, /* ulp_data_callback */ 876 fcp_statec_callback /* ulp_statec_callback */ 877 }; 878 879 #ifdef DEBUG 880 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 881 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 882 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 883 FCP_LEVEL_6 | FCP_LEVEL_7) 884 #else 885 #define FCP_TRACE_DEFAULT (FC_TRACE_LOG_MASK | FCP_LEVEL_1 | \ 886 FCP_LEVEL_2 | FCP_LEVEL_3 | \ 887 FCP_LEVEL_4 | FCP_LEVEL_5 | \ 888 FCP_LEVEL_6 | FCP_LEVEL_7) 889 #endif 890 891 /* FCP global variables */ 892 int fcp_bus_config_debug = 0; 893 static int fcp_log_size = FCP_LOG_SIZE; 894 static int fcp_trace = FCP_TRACE_DEFAULT; 895 static fc_trace_logq_t *fcp_logq = NULL; 896 static struct fcp_black_list_entry *fcp_lun_blacklist = NULL; 897 /* 898 * The auto-configuration is set by default. The only way of disabling it is 899 * through the property MANUAL_CFG_ONLY in the fcp.conf file. 900 */ 901 static int fcp_enable_auto_configuration = 1; 902 static int fcp_max_bus_config_retries = 4; 903 static int fcp_lun_ready_retry = 300; 904 /* 905 * The value assigned to the following variable has changed several times due 906 * to a problem with the data underruns reporting of some firmware(s). The 907 * current value of 50 gives a timeout value of 25 seconds for a max number 908 * of 256 LUNs. 909 */ 910 static int fcp_max_target_retries = 50; 911 /* 912 * Watchdog variables 913 * ------------------ 914 * 915 * fcp_watchdog_init 916 * 917 * Indicates if the watchdog timer is running or not. This is actually 918 * a counter of the number of Fibre Channel ports that attached. When 919 * the first port attaches the watchdog is started. When the last port 920 * detaches the watchdog timer is stopped. 921 * 922 * fcp_watchdog_time 923 * 924 * This is the watchdog clock counter. It is incremented by 925 * fcp_watchdog_time each time the watchdog timer expires. 926 * 927 * fcp_watchdog_timeout 928 * 929 * Increment value of the variable fcp_watchdog_time as well as the 930 * the timeout value of the watchdog timer. The unit is 1 second. It 931 * is strange that this is not a #define but a variable since the code 932 * never changes this value. The reason why it can be said that the 933 * unit is 1 second is because the number of ticks for the watchdog 934 * timer is determined like this: 935 * 936 * fcp_watchdog_tick = fcp_watchdog_timeout * 937 * drv_usectohz(1000000); 938 * 939 * The value 1000000 is hard coded in the code. 940 * 941 * fcp_watchdog_tick 942 * 943 * Watchdog timer value in ticks. 944 */ 945 static int fcp_watchdog_init = 0; 946 static int fcp_watchdog_time = 0; 947 static int fcp_watchdog_timeout = 1; 948 static int fcp_watchdog_tick; 949 950 /* 951 * fcp_offline_delay is a global variable to enable customisation of 952 * the timeout on link offlines or RSCNs. The default value is set 953 * to match FCP_OFFLINE_DELAY (20sec), which is 2*RA_TOV_els as 954 * specified in FCP4 Chapter 11 (see www.t10.org). 955 * 956 * The variable fcp_offline_delay is specified in SECONDS. 957 * 958 * If we made this a static var then the user would not be able to 959 * change it. This variable is set in fcp_attach(). 960 */ 961 unsigned int fcp_offline_delay = FCP_OFFLINE_DELAY; 962 963 static void *fcp_softstate = NULL; /* for soft state */ 964 static uchar_t fcp_oflag = FCP_IDLE; /* open flag */ 965 static kmutex_t fcp_global_mutex; 966 static kmutex_t fcp_ioctl_mutex; 967 static dev_info_t *fcp_global_dip = NULL; 968 static timeout_id_t fcp_watchdog_id; 969 const char *fcp_lun_prop = "lun"; 970 const char *fcp_sam_lun_prop = "sam-lun"; 971 const char *fcp_target_prop = "target"; 972 /* 973 * NOTE: consumers of "node-wwn" property include stmsboot in ON 974 * consolidation. 975 */ 976 const char *fcp_node_wwn_prop = "node-wwn"; 977 const char *fcp_port_wwn_prop = "port-wwn"; 978 const char *fcp_conf_wwn_prop = "fc-port-wwn"; 979 const char *fcp_obp_boot_wwn = "fc-boot-dev-portwwn"; 980 const char *fcp_manual_config_only = "manual_configuration_only"; 981 const char *fcp_init_port_prop = "initiator-port"; 982 const char *fcp_tgt_port_prop = "target-port"; 983 const char *fcp_lun_blacklist_prop = "pwwn-lun-blacklist"; 984 985 static struct fcp_port *fcp_port_head = NULL; 986 static ddi_eventcookie_t fcp_insert_eid; 987 static ddi_eventcookie_t fcp_remove_eid; 988 989 static ndi_event_definition_t fcp_ndi_event_defs[] = { 990 { FCP_EVENT_TAG_INSERT, FCAL_INSERT_EVENT, EPL_KERNEL }, 991 { FCP_EVENT_TAG_REMOVE, FCAL_REMOVE_EVENT, EPL_INTERRUPT } 992 }; 993 994 /* 995 * List of valid commands for the scsi_ioctl call 996 */ 997 static uint8_t scsi_ioctl_list[] = { 998 SCMD_INQUIRY, 999 SCMD_REPORT_LUN, 1000 SCMD_READ_CAPACITY 1001 }; 1002 1003 /* 1004 * this is used to dummy up a report lun response for cases 1005 * where the target doesn't support it 1006 */ 1007 static uchar_t fcp_dummy_lun[] = { 1008 0x00, /* MSB length (length = no of luns * 8) */ 1009 0x00, 1010 0x00, 1011 0x08, /* LSB length */ 1012 0x00, /* MSB reserved */ 1013 0x00, 1014 0x00, 1015 0x00, /* LSB reserved */ 1016 FCP_PD_ADDRESSING, 1017 0x00, /* LUN is ZERO at the first level */ 1018 0x00, 1019 0x00, /* second level is zero */ 1020 0x00, 1021 0x00, /* third level is zero */ 1022 0x00, 1023 0x00 /* fourth level is zero */ 1024 }; 1025 1026 static uchar_t fcp_alpa_to_switch[] = { 1027 0x00, 0x7d, 0x7c, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 1028 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x78, 0x00, 0x00, 0x00, 1029 0x00, 0x00, 0x00, 0x77, 0x76, 0x00, 0x00, 0x75, 0x00, 0x74, 1030 0x73, 0x72, 0x00, 0x00, 0x00, 0x71, 0x00, 0x70, 0x6f, 0x6e, 1031 0x00, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x00, 0x00, 0x67, 1032 0x66, 0x65, 0x64, 0x63, 0x62, 0x00, 0x00, 0x61, 0x60, 0x00, 1033 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x5d, 1034 0x5c, 0x5b, 0x00, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x00, 1035 0x00, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x00, 0x00, 0x4e, 1036 0x4d, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 1037 0x00, 0x4a, 0x49, 0x48, 0x00, 0x47, 0x46, 0x45, 0x44, 0x43, 1038 0x42, 0x00, 0x00, 0x41, 0x40, 0x3f, 0x3e, 0x3d, 0x3c, 0x00, 1039 0x00, 0x3b, 0x3a, 0x00, 0x39, 0x00, 0x00, 0x00, 0x38, 0x37, 1040 0x36, 0x00, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 1041 0x00, 0x00, 0x00, 0x33, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 1042 0x00, 0x31, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x2e, 0x2d, 0x2c, 1043 0x00, 0x00, 0x00, 0x2b, 0x00, 0x2a, 0x29, 0x28, 0x00, 0x27, 1044 0x26, 0x25, 0x24, 0x23, 0x22, 0x00, 0x00, 0x21, 0x20, 0x1f, 1045 0x1e, 0x1d, 0x1c, 0x00, 0x00, 0x1b, 0x1a, 0x00, 0x19, 0x00, 1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x17, 0x16, 0x15, 1047 0x00, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x00, 0x00, 0x0e, 1048 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x00, 0x00, 0x08, 0x07, 0x00, 1049 0x06, 0x00, 0x00, 0x00, 0x05, 0x04, 0x03, 0x00, 0x02, 0x00, 1050 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1051 }; 1052 1053 static caddr_t pid = "SESS01 "; 1054 1055 #if !defined(lint) 1056 1057 _NOTE(MUTEX_PROTECTS_DATA(fcp_global_mutex, 1058 fcp_port::fcp_next fcp_watchdog_id)) 1059 1060 _NOTE(DATA_READABLE_WITHOUT_LOCK(fcp_watchdog_time)) 1061 1062 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1063 fcp_insert_eid 1064 fcp_remove_eid 1065 fcp_watchdog_time)) 1066 1067 _NOTE(SCHEME_PROTECTS_DATA("Unshared", 1068 fcp_cb_ops 1069 fcp_ops 1070 callb_cpr)) 1071 1072 #endif /* lint */ 1073 1074 /* 1075 * This table is used to determine whether or not it's safe to copy in 1076 * the target node name for a lun. Since all luns behind the same target 1077 * have the same wwnn, only tagets that do not support multiple luns are 1078 * eligible to be enumerated under mpxio if they aren't page83 compliant. 1079 */ 1080 1081 char *fcp_symmetric_disk_table[] = { 1082 "SEAGATE ST", 1083 "IBM DDYFT", 1084 "SUNW SUNWGS", /* Daktari enclosure */ 1085 "SUN SENA", /* SES device */ 1086 "SUN SESS01" /* VICOM SVE box */ 1087 }; 1088 1089 int fcp_symmetric_disk_table_size = 1090 sizeof (fcp_symmetric_disk_table)/sizeof (char *); 1091 1092 /* 1093 * This structure is bogus. scsi_hba_attach_setup() requires, as in the kernel 1094 * will panic if you don't pass this in to the routine, this information. 1095 * Need to determine what the actual impact to the system is by providing 1096 * this information if any. Since dma allocation is done in pkt_init it may 1097 * not have any impact. These values are straight from the Writing Device 1098 * Driver manual. 1099 */ 1100 static ddi_dma_attr_t pseudo_fca_dma_attr = { 1101 DMA_ATTR_V0, /* ddi_dma_attr version */ 1102 0, /* low address */ 1103 0xffffffff, /* high address */ 1104 0x00ffffff, /* counter upper bound */ 1105 1, /* alignment requirements */ 1106 0x3f, /* burst sizes */ 1107 1, /* minimum DMA access */ 1108 0xffffffff, /* maximum DMA access */ 1109 (1 << 24) - 1, /* segment boundary restrictions */ 1110 1, /* scater/gather list length */ 1111 512, /* device granularity */ 1112 0 /* DMA flags */ 1113 }; 1114 1115 /* 1116 * The _init(9e) return value should be that of mod_install(9f). Under 1117 * some circumstances, a failure may not be related mod_install(9f) and 1118 * one would then require a return value to indicate the failure. Looking 1119 * at mod_install(9f), it is expected to return 0 for success and non-zero 1120 * for failure. mod_install(9f) for device drivers, further goes down the 1121 * calling chain and ends up in ddi_installdrv(), whose return values are 1122 * DDI_SUCCESS and DDI_FAILURE - There are also other functions in the 1123 * calling chain of mod_install(9f) which return values like EINVAL and 1124 * in some even return -1. 1125 * 1126 * To work around the vagaries of the mod_install() calling chain, return 1127 * either 0 or ENODEV depending on the success or failure of mod_install() 1128 */ 1129 int 1130 _init(void) 1131 { 1132 int rval; 1133 1134 /* 1135 * Allocate soft state and prepare to do ddi_soft_state_zalloc() 1136 * before registering with the transport first. 1137 */ 1138 if (ddi_soft_state_init(&fcp_softstate, 1139 sizeof (struct fcp_port), FCP_INIT_ITEMS) != 0) { 1140 return (EINVAL); 1141 } 1142 1143 mutex_init(&fcp_global_mutex, NULL, MUTEX_DRIVER, NULL); 1144 mutex_init(&fcp_ioctl_mutex, NULL, MUTEX_DRIVER, NULL); 1145 1146 if ((rval = fc_ulp_add(&fcp_modinfo)) != FC_SUCCESS) { 1147 cmn_err(CE_WARN, "fcp: fc_ulp_add failed"); 1148 mutex_destroy(&fcp_global_mutex); 1149 mutex_destroy(&fcp_ioctl_mutex); 1150 ddi_soft_state_fini(&fcp_softstate); 1151 return (ENODEV); 1152 } 1153 1154 fcp_logq = fc_trace_alloc_logq(fcp_log_size); 1155 1156 if ((rval = mod_install(&modlinkage)) != 0) { 1157 fc_trace_free_logq(fcp_logq); 1158 (void) fc_ulp_remove(&fcp_modinfo); 1159 mutex_destroy(&fcp_global_mutex); 1160 mutex_destroy(&fcp_ioctl_mutex); 1161 ddi_soft_state_fini(&fcp_softstate); 1162 rval = ENODEV; 1163 } 1164 1165 return (rval); 1166 } 1167 1168 1169 /* 1170 * the system is done with us as a driver, so clean up 1171 */ 1172 int 1173 _fini(void) 1174 { 1175 int rval; 1176 1177 /* 1178 * don't start cleaning up until we know that the module remove 1179 * has worked -- if this works, then we know that each instance 1180 * has successfully been DDI_DETACHed 1181 */ 1182 if ((rval = mod_remove(&modlinkage)) != 0) { 1183 return (rval); 1184 } 1185 1186 (void) fc_ulp_remove(&fcp_modinfo); 1187 1188 ddi_soft_state_fini(&fcp_softstate); 1189 mutex_destroy(&fcp_global_mutex); 1190 mutex_destroy(&fcp_ioctl_mutex); 1191 fc_trace_free_logq(fcp_logq); 1192 1193 return (rval); 1194 } 1195 1196 1197 int 1198 _info(struct modinfo *modinfop) 1199 { 1200 return (mod_info(&modlinkage, modinfop)); 1201 } 1202 1203 1204 /* 1205 * attach the module 1206 */ 1207 static int 1208 fcp_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 1209 { 1210 int rval = DDI_SUCCESS; 1211 1212 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1213 FCP_BUF_LEVEL_8, 0, "fcp module attach: cmd=0x%x", cmd); 1214 1215 if (cmd == DDI_ATTACH) { 1216 /* The FCP pseudo device is created here. */ 1217 mutex_enter(&fcp_global_mutex); 1218 fcp_global_dip = devi; 1219 mutex_exit(&fcp_global_mutex); 1220 1221 if (ddi_create_minor_node(fcp_global_dip, "fcp", S_IFCHR, 1222 0, DDI_PSEUDO, 0) == DDI_SUCCESS) { 1223 ddi_report_dev(fcp_global_dip); 1224 } else { 1225 cmn_err(CE_WARN, "FCP: Cannot create minor node"); 1226 mutex_enter(&fcp_global_mutex); 1227 fcp_global_dip = NULL; 1228 mutex_exit(&fcp_global_mutex); 1229 1230 rval = DDI_FAILURE; 1231 } 1232 /* 1233 * We check the fcp_offline_delay property at this 1234 * point. This variable is global for the driver, 1235 * not specific to an instance. 1236 * 1237 * We do not recommend setting the value to less 1238 * than 10 seconds (RA_TOV_els), or greater than 1239 * 60 seconds. 1240 */ 1241 fcp_offline_delay = ddi_prop_get_int(DDI_DEV_T_ANY, 1242 devi, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1243 "fcp_offline_delay", FCP_OFFLINE_DELAY); 1244 if ((fcp_offline_delay < 10) || 1245 (fcp_offline_delay > 60)) { 1246 cmn_err(CE_WARN, "Setting fcp_offline_delay " 1247 "to %d second(s). This is outside the " 1248 "recommended range of 10..60 seconds.", 1249 fcp_offline_delay); 1250 } 1251 } 1252 1253 return (rval); 1254 } 1255 1256 1257 /*ARGSUSED*/ 1258 static int 1259 fcp_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 1260 { 1261 int res = DDI_SUCCESS; 1262 1263 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1264 FCP_BUF_LEVEL_8, 0, "module detach: cmd=0x%x", cmd); 1265 1266 if (cmd == DDI_DETACH) { 1267 /* 1268 * Check if there are active ports/threads. If there 1269 * are any, we will fail, else we will succeed (there 1270 * should not be much to clean up) 1271 */ 1272 mutex_enter(&fcp_global_mutex); 1273 FCP_DTRACE(fcp_logq, "fcp", 1274 fcp_trace, FCP_BUF_LEVEL_8, 0, "port_head=%p", 1275 (void *) fcp_port_head); 1276 1277 if (fcp_port_head == NULL) { 1278 ddi_remove_minor_node(fcp_global_dip, NULL); 1279 fcp_global_dip = NULL; 1280 mutex_exit(&fcp_global_mutex); 1281 } else { 1282 mutex_exit(&fcp_global_mutex); 1283 res = DDI_FAILURE; 1284 } 1285 } 1286 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 1287 FCP_BUF_LEVEL_8, 0, "module detach returning %d", res); 1288 1289 return (res); 1290 } 1291 1292 1293 /* ARGSUSED */ 1294 static int 1295 fcp_open(dev_t *devp, int flag, int otype, cred_t *credp) 1296 { 1297 if (otype != OTYP_CHR) { 1298 return (EINVAL); 1299 } 1300 1301 /* 1302 * Allow only root to talk; 1303 */ 1304 if (drv_priv(credp)) { 1305 return (EPERM); 1306 } 1307 1308 mutex_enter(&fcp_global_mutex); 1309 if (fcp_oflag & FCP_EXCL) { 1310 mutex_exit(&fcp_global_mutex); 1311 return (EBUSY); 1312 } 1313 1314 if (flag & FEXCL) { 1315 if (fcp_oflag & FCP_OPEN) { 1316 mutex_exit(&fcp_global_mutex); 1317 return (EBUSY); 1318 } 1319 fcp_oflag |= FCP_EXCL; 1320 } 1321 fcp_oflag |= FCP_OPEN; 1322 mutex_exit(&fcp_global_mutex); 1323 1324 return (0); 1325 } 1326 1327 1328 /* ARGSUSED */ 1329 static int 1330 fcp_close(dev_t dev, int flag, int otype, cred_t *credp) 1331 { 1332 if (otype != OTYP_CHR) { 1333 return (EINVAL); 1334 } 1335 1336 mutex_enter(&fcp_global_mutex); 1337 if (!(fcp_oflag & FCP_OPEN)) { 1338 mutex_exit(&fcp_global_mutex); 1339 return (ENODEV); 1340 } 1341 fcp_oflag = FCP_IDLE; 1342 mutex_exit(&fcp_global_mutex); 1343 1344 return (0); 1345 } 1346 1347 1348 /* 1349 * fcp_ioctl 1350 * Entry point for the FCP ioctls 1351 * 1352 * Input: 1353 * See ioctl(9E) 1354 * 1355 * Output: 1356 * See ioctl(9E) 1357 * 1358 * Returns: 1359 * See ioctl(9E) 1360 * 1361 * Context: 1362 * Kernel context. 1363 */ 1364 /* ARGSUSED */ 1365 static int 1366 fcp_ioctl(dev_t dev, int cmd, intptr_t data, int mode, cred_t *credp, 1367 int *rval) 1368 { 1369 int ret = 0; 1370 1371 mutex_enter(&fcp_global_mutex); 1372 if (!(fcp_oflag & FCP_OPEN)) { 1373 mutex_exit(&fcp_global_mutex); 1374 return (ENXIO); 1375 } 1376 mutex_exit(&fcp_global_mutex); 1377 1378 switch (cmd) { 1379 case FCP_TGT_INQUIRY: 1380 case FCP_TGT_CREATE: 1381 case FCP_TGT_DELETE: 1382 ret = fcp_setup_device_data_ioctl(cmd, 1383 (struct fcp_ioctl *)data, mode, rval); 1384 break; 1385 1386 case FCP_TGT_SEND_SCSI: 1387 mutex_enter(&fcp_ioctl_mutex); 1388 ret = fcp_setup_scsi_ioctl( 1389 (struct fcp_scsi_cmd *)data, mode, rval); 1390 mutex_exit(&fcp_ioctl_mutex); 1391 break; 1392 1393 case FCP_STATE_COUNT: 1394 ret = fcp_get_statec_count((struct fcp_ioctl *)data, 1395 mode, rval); 1396 break; 1397 case FCP_GET_TARGET_MAPPINGS: 1398 ret = fcp_get_target_mappings((struct fcp_ioctl *)data, 1399 mode, rval); 1400 break; 1401 default: 1402 fcp_log(CE_WARN, NULL, 1403 "!Invalid ioctl opcode = 0x%x", cmd); 1404 ret = EINVAL; 1405 } 1406 1407 return (ret); 1408 } 1409 1410 1411 /* 1412 * fcp_setup_device_data_ioctl 1413 * Setup handler for the "device data" style of 1414 * ioctl for FCP. See "fcp_util.h" for data structure 1415 * definition. 1416 * 1417 * Input: 1418 * cmd = FCP ioctl command 1419 * data = ioctl data 1420 * mode = See ioctl(9E) 1421 * 1422 * Output: 1423 * data = ioctl data 1424 * rval = return value - see ioctl(9E) 1425 * 1426 * Returns: 1427 * See ioctl(9E) 1428 * 1429 * Context: 1430 * Kernel context. 1431 */ 1432 /* ARGSUSED */ 1433 static int 1434 fcp_setup_device_data_ioctl(int cmd, struct fcp_ioctl *data, int mode, 1435 int *rval) 1436 { 1437 struct fcp_port *pptr; 1438 struct device_data *dev_data; 1439 uint32_t link_cnt; 1440 la_wwn_t *wwn_ptr = NULL; 1441 struct fcp_tgt *ptgt = NULL; 1442 struct fcp_lun *plun = NULL; 1443 int i, error; 1444 struct fcp_ioctl fioctl; 1445 1446 #ifdef _MULTI_DATAMODEL 1447 switch (ddi_model_convert_from(mode & FMODELS)) { 1448 case DDI_MODEL_ILP32: { 1449 struct fcp32_ioctl f32_ioctl; 1450 1451 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1452 sizeof (struct fcp32_ioctl), mode)) { 1453 return (EFAULT); 1454 } 1455 fioctl.fp_minor = f32_ioctl.fp_minor; 1456 fioctl.listlen = f32_ioctl.listlen; 1457 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1458 break; 1459 } 1460 case DDI_MODEL_NONE: 1461 if (ddi_copyin((void *)data, (void *)&fioctl, 1462 sizeof (struct fcp_ioctl), mode)) { 1463 return (EFAULT); 1464 } 1465 break; 1466 } 1467 1468 #else /* _MULTI_DATAMODEL */ 1469 if (ddi_copyin((void *)data, (void *)&fioctl, 1470 sizeof (struct fcp_ioctl), mode)) { 1471 return (EFAULT); 1472 } 1473 #endif /* _MULTI_DATAMODEL */ 1474 1475 /* 1476 * Right now we can assume that the minor number matches with 1477 * this instance of fp. If this changes we will need to 1478 * revisit this logic. 1479 */ 1480 mutex_enter(&fcp_global_mutex); 1481 pptr = fcp_port_head; 1482 while (pptr) { 1483 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1484 break; 1485 } else { 1486 pptr = pptr->port_next; 1487 } 1488 } 1489 mutex_exit(&fcp_global_mutex); 1490 if (pptr == NULL) { 1491 return (ENXIO); 1492 } 1493 mutex_enter(&pptr->port_mutex); 1494 1495 1496 if ((dev_data = kmem_zalloc((sizeof (struct device_data)) * 1497 fioctl.listlen, KM_NOSLEEP)) == NULL) { 1498 mutex_exit(&pptr->port_mutex); 1499 return (ENOMEM); 1500 } 1501 1502 if (ddi_copyin(fioctl.list, dev_data, 1503 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1504 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1505 mutex_exit(&pptr->port_mutex); 1506 return (EFAULT); 1507 } 1508 link_cnt = pptr->port_link_cnt; 1509 1510 if (cmd == FCP_TGT_INQUIRY) { 1511 wwn_ptr = (la_wwn_t *)&(dev_data[0].dev_pwwn); 1512 if (bcmp(wwn_ptr->raw_wwn, pptr->port_pwwn.raw_wwn, 1513 sizeof (wwn_ptr->raw_wwn)) == 0) { 1514 /* This ioctl is requesting INQ info of local HBA */ 1515 mutex_exit(&pptr->port_mutex); 1516 dev_data[0].dev0_type = DTYPE_UNKNOWN; 1517 dev_data[0].dev_status = 0; 1518 if (ddi_copyout(dev_data, fioctl.list, 1519 (sizeof (struct device_data)) * fioctl.listlen, 1520 mode)) { 1521 kmem_free(dev_data, 1522 sizeof (*dev_data) * fioctl.listlen); 1523 return (EFAULT); 1524 } 1525 kmem_free(dev_data, 1526 sizeof (*dev_data) * fioctl.listlen); 1527 #ifdef _MULTI_DATAMODEL 1528 switch (ddi_model_convert_from(mode & FMODELS)) { 1529 case DDI_MODEL_ILP32: { 1530 struct fcp32_ioctl f32_ioctl; 1531 f32_ioctl.fp_minor = fioctl.fp_minor; 1532 f32_ioctl.listlen = fioctl.listlen; 1533 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1534 if (ddi_copyout((void *)&f32_ioctl, 1535 (void *)data, 1536 sizeof (struct fcp32_ioctl), mode)) { 1537 return (EFAULT); 1538 } 1539 break; 1540 } 1541 case DDI_MODEL_NONE: 1542 if (ddi_copyout((void *)&fioctl, (void *)data, 1543 sizeof (struct fcp_ioctl), mode)) { 1544 return (EFAULT); 1545 } 1546 break; 1547 } 1548 #else /* _MULTI_DATAMODEL */ 1549 if (ddi_copyout((void *)&fioctl, (void *)data, 1550 sizeof (struct fcp_ioctl), mode)) { 1551 return (EFAULT); 1552 } 1553 #endif /* _MULTI_DATAMODEL */ 1554 return (0); 1555 } 1556 } 1557 1558 if (pptr->port_state & (FCP_STATE_INIT | FCP_STATE_OFFLINE)) { 1559 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1560 mutex_exit(&pptr->port_mutex); 1561 return (ENXIO); 1562 } 1563 1564 for (i = 0; (i < fioctl.listlen) && (link_cnt == pptr->port_link_cnt); 1565 i++) { 1566 wwn_ptr = (la_wwn_t *)&(dev_data[i].dev_pwwn); 1567 1568 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1569 1570 1571 dev_data[i].dev_status = ENXIO; 1572 1573 if ((ptgt = fcp_lookup_target(pptr, 1574 (uchar_t *)wwn_ptr)) == NULL) { 1575 mutex_exit(&pptr->port_mutex); 1576 if (fc_ulp_get_remote_port(pptr->port_fp_handle, 1577 wwn_ptr, &error, 0) == NULL) { 1578 dev_data[i].dev_status = ENODEV; 1579 mutex_enter(&pptr->port_mutex); 1580 continue; 1581 } else { 1582 1583 dev_data[i].dev_status = EAGAIN; 1584 1585 mutex_enter(&pptr->port_mutex); 1586 continue; 1587 } 1588 } else { 1589 mutex_enter(&ptgt->tgt_mutex); 1590 if (ptgt->tgt_state & (FCP_TGT_MARK | 1591 FCP_TGT_BUSY)) { 1592 dev_data[i].dev_status = EAGAIN; 1593 mutex_exit(&ptgt->tgt_mutex); 1594 continue; 1595 } 1596 1597 if (ptgt->tgt_state & FCP_TGT_OFFLINE) { 1598 if (ptgt->tgt_icap && !ptgt->tgt_tcap) { 1599 dev_data[i].dev_status = ENOTSUP; 1600 } else { 1601 dev_data[i].dev_status = ENXIO; 1602 } 1603 mutex_exit(&ptgt->tgt_mutex); 1604 continue; 1605 } 1606 1607 switch (cmd) { 1608 case FCP_TGT_INQUIRY: 1609 /* 1610 * The reason we give device type of 1611 * lun 0 only even though in some 1612 * cases(like maxstrat) lun 0 device 1613 * type may be 0x3f(invalid) is that 1614 * for bridge boxes target will appear 1615 * as luns and the first lun could be 1616 * a device that utility may not care 1617 * about (like a tape device). 1618 */ 1619 dev_data[i].dev_lun_cnt = ptgt->tgt_lun_cnt; 1620 dev_data[i].dev_status = 0; 1621 mutex_exit(&ptgt->tgt_mutex); 1622 1623 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 1624 dev_data[i].dev0_type = DTYPE_UNKNOWN; 1625 } else { 1626 dev_data[i].dev0_type = plun->lun_type; 1627 } 1628 mutex_enter(&ptgt->tgt_mutex); 1629 break; 1630 1631 case FCP_TGT_CREATE: 1632 mutex_exit(&ptgt->tgt_mutex); 1633 mutex_exit(&pptr->port_mutex); 1634 1635 /* 1636 * serialize state change call backs. 1637 * only one call back will be handled 1638 * at a time. 1639 */ 1640 mutex_enter(&fcp_global_mutex); 1641 if (fcp_oflag & FCP_BUSY) { 1642 mutex_exit(&fcp_global_mutex); 1643 if (dev_data) { 1644 kmem_free(dev_data, 1645 sizeof (*dev_data) * 1646 fioctl.listlen); 1647 } 1648 return (EBUSY); 1649 } 1650 fcp_oflag |= FCP_BUSY; 1651 mutex_exit(&fcp_global_mutex); 1652 1653 dev_data[i].dev_status = 1654 fcp_create_on_demand(pptr, 1655 wwn_ptr->raw_wwn); 1656 1657 if (dev_data[i].dev_status != 0) { 1658 char buf[25]; 1659 1660 for (i = 0; i < FC_WWN_SIZE; i++) { 1661 (void) sprintf(&buf[i << 1], 1662 "%02x", 1663 wwn_ptr->raw_wwn[i]); 1664 } 1665 1666 fcp_log(CE_WARN, pptr->port_dip, 1667 "!Failed to create nodes for" 1668 " pwwn=%s; error=%x", buf, 1669 dev_data[i].dev_status); 1670 } 1671 1672 /* allow state change call backs again */ 1673 mutex_enter(&fcp_global_mutex); 1674 fcp_oflag &= ~FCP_BUSY; 1675 mutex_exit(&fcp_global_mutex); 1676 1677 mutex_enter(&pptr->port_mutex); 1678 mutex_enter(&ptgt->tgt_mutex); 1679 1680 break; 1681 1682 case FCP_TGT_DELETE: 1683 break; 1684 1685 default: 1686 fcp_log(CE_WARN, pptr->port_dip, 1687 "!Invalid device data ioctl " 1688 "opcode = 0x%x", cmd); 1689 } 1690 mutex_exit(&ptgt->tgt_mutex); 1691 } 1692 } 1693 mutex_exit(&pptr->port_mutex); 1694 1695 if (ddi_copyout(dev_data, fioctl.list, 1696 (sizeof (struct device_data)) * fioctl.listlen, mode)) { 1697 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1698 return (EFAULT); 1699 } 1700 kmem_free(dev_data, sizeof (*dev_data) * fioctl.listlen); 1701 1702 #ifdef _MULTI_DATAMODEL 1703 switch (ddi_model_convert_from(mode & FMODELS)) { 1704 case DDI_MODEL_ILP32: { 1705 struct fcp32_ioctl f32_ioctl; 1706 1707 f32_ioctl.fp_minor = fioctl.fp_minor; 1708 f32_ioctl.listlen = fioctl.listlen; 1709 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1710 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1711 sizeof (struct fcp32_ioctl), mode)) { 1712 return (EFAULT); 1713 } 1714 break; 1715 } 1716 case DDI_MODEL_NONE: 1717 if (ddi_copyout((void *)&fioctl, (void *)data, 1718 sizeof (struct fcp_ioctl), mode)) { 1719 return (EFAULT); 1720 } 1721 break; 1722 } 1723 #else /* _MULTI_DATAMODEL */ 1724 1725 if (ddi_copyout((void *)&fioctl, (void *)data, 1726 sizeof (struct fcp_ioctl), mode)) { 1727 return (EFAULT); 1728 } 1729 #endif /* _MULTI_DATAMODEL */ 1730 1731 return (0); 1732 } 1733 1734 /* 1735 * Fetch the target mappings (path, etc.) for all LUNs 1736 * on this port. 1737 */ 1738 /* ARGSUSED */ 1739 static int 1740 fcp_get_target_mappings(struct fcp_ioctl *data, 1741 int mode, int *rval) 1742 { 1743 struct fcp_port *pptr; 1744 fc_hba_target_mappings_t *mappings; 1745 fc_hba_mapping_entry_t *map; 1746 struct fcp_tgt *ptgt = NULL; 1747 struct fcp_lun *plun = NULL; 1748 int i, mapIndex, mappingSize; 1749 int listlen; 1750 struct fcp_ioctl fioctl; 1751 char *path; 1752 fcp_ent_addr_t sam_lun_addr; 1753 1754 #ifdef _MULTI_DATAMODEL 1755 switch (ddi_model_convert_from(mode & FMODELS)) { 1756 case DDI_MODEL_ILP32: { 1757 struct fcp32_ioctl f32_ioctl; 1758 1759 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 1760 sizeof (struct fcp32_ioctl), mode)) { 1761 return (EFAULT); 1762 } 1763 fioctl.fp_minor = f32_ioctl.fp_minor; 1764 fioctl.listlen = f32_ioctl.listlen; 1765 fioctl.list = (caddr_t)(long)f32_ioctl.list; 1766 break; 1767 } 1768 case DDI_MODEL_NONE: 1769 if (ddi_copyin((void *)data, (void *)&fioctl, 1770 sizeof (struct fcp_ioctl), mode)) { 1771 return (EFAULT); 1772 } 1773 break; 1774 } 1775 1776 #else /* _MULTI_DATAMODEL */ 1777 if (ddi_copyin((void *)data, (void *)&fioctl, 1778 sizeof (struct fcp_ioctl), mode)) { 1779 return (EFAULT); 1780 } 1781 #endif /* _MULTI_DATAMODEL */ 1782 1783 /* 1784 * Right now we can assume that the minor number matches with 1785 * this instance of fp. If this changes we will need to 1786 * revisit this logic. 1787 */ 1788 mutex_enter(&fcp_global_mutex); 1789 pptr = fcp_port_head; 1790 while (pptr) { 1791 if (pptr->port_instance == (uint32_t)fioctl.fp_minor) { 1792 break; 1793 } else { 1794 pptr = pptr->port_next; 1795 } 1796 } 1797 mutex_exit(&fcp_global_mutex); 1798 if (pptr == NULL) { 1799 cmn_err(CE_NOTE, "target mappings: unknown instance number: %d", 1800 fioctl.fp_minor); 1801 return (ENXIO); 1802 } 1803 1804 1805 /* We use listlen to show the total buffer size */ 1806 mappingSize = fioctl.listlen; 1807 1808 /* Now calculate how many mapping entries will fit */ 1809 listlen = fioctl.listlen + sizeof (fc_hba_mapping_entry_t) 1810 - sizeof (fc_hba_target_mappings_t); 1811 if (listlen <= 0) { 1812 cmn_err(CE_NOTE, "target mappings: Insufficient buffer"); 1813 return (ENXIO); 1814 } 1815 listlen = listlen / sizeof (fc_hba_mapping_entry_t); 1816 1817 if ((mappings = kmem_zalloc(mappingSize, KM_SLEEP)) == NULL) { 1818 return (ENOMEM); 1819 } 1820 mappings->version = FC_HBA_TARGET_MAPPINGS_VERSION; 1821 1822 /* Now get to work */ 1823 mapIndex = 0; 1824 1825 mutex_enter(&pptr->port_mutex); 1826 /* Loop through all targets on this port */ 1827 for (i = 0; i < FCP_NUM_HASH; i++) { 1828 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 1829 ptgt = ptgt->tgt_next) { 1830 1831 mutex_enter(&ptgt->tgt_mutex); 1832 1833 /* Loop through all LUNs on this target */ 1834 for (plun = ptgt->tgt_lun; plun != NULL; 1835 plun = plun->lun_next) { 1836 if (plun->lun_state & FCP_LUN_OFFLINE) { 1837 continue; 1838 } 1839 1840 path = fcp_get_lun_path(plun); 1841 if (path == NULL) { 1842 continue; 1843 } 1844 1845 if (mapIndex >= listlen) { 1846 mapIndex ++; 1847 kmem_free(path, MAXPATHLEN); 1848 continue; 1849 } 1850 map = &mappings->entries[mapIndex++]; 1851 bcopy(path, map->targetDriver, 1852 sizeof (map->targetDriver)); 1853 map->d_id = ptgt->tgt_d_id; 1854 map->busNumber = 0; 1855 map->targetNumber = ptgt->tgt_d_id; 1856 map->osLUN = plun->lun_num; 1857 1858 /* 1859 * We had swapped lun when we stored it in 1860 * lun_addr. We need to swap it back before 1861 * returning it to user land 1862 */ 1863 1864 sam_lun_addr.ent_addr_0 = 1865 BE_16(plun->lun_addr.ent_addr_0); 1866 sam_lun_addr.ent_addr_1 = 1867 BE_16(plun->lun_addr.ent_addr_1); 1868 sam_lun_addr.ent_addr_2 = 1869 BE_16(plun->lun_addr.ent_addr_2); 1870 sam_lun_addr.ent_addr_3 = 1871 BE_16(plun->lun_addr.ent_addr_3); 1872 1873 bcopy(&sam_lun_addr, &map->samLUN, 1874 FCP_LUN_SIZE); 1875 bcopy(ptgt->tgt_node_wwn.raw_wwn, 1876 map->NodeWWN.raw_wwn, sizeof (la_wwn_t)); 1877 bcopy(ptgt->tgt_port_wwn.raw_wwn, 1878 map->PortWWN.raw_wwn, sizeof (la_wwn_t)); 1879 1880 if (plun->lun_guid) { 1881 1882 /* convert ascii wwn to bytes */ 1883 fcp_ascii_to_wwn(plun->lun_guid, 1884 map->guid, sizeof (map->guid)); 1885 1886 if ((sizeof (map->guid)) < 1887 plun->lun_guid_size / 2) { 1888 cmn_err(CE_WARN, 1889 "fcp_get_target_mappings:" 1890 "guid copy space " 1891 "insufficient." 1892 "Copy Truncation - " 1893 "available %d; need %d", 1894 (int)sizeof (map->guid), 1895 (int) 1896 plun->lun_guid_size / 2); 1897 } 1898 } 1899 kmem_free(path, MAXPATHLEN); 1900 } 1901 mutex_exit(&ptgt->tgt_mutex); 1902 } 1903 } 1904 mutex_exit(&pptr->port_mutex); 1905 mappings->numLuns = mapIndex; 1906 1907 if (ddi_copyout(mappings, fioctl.list, mappingSize, mode)) { 1908 kmem_free(mappings, mappingSize); 1909 return (EFAULT); 1910 } 1911 kmem_free(mappings, mappingSize); 1912 1913 #ifdef _MULTI_DATAMODEL 1914 switch (ddi_model_convert_from(mode & FMODELS)) { 1915 case DDI_MODEL_ILP32: { 1916 struct fcp32_ioctl f32_ioctl; 1917 1918 f32_ioctl.fp_minor = fioctl.fp_minor; 1919 f32_ioctl.listlen = fioctl.listlen; 1920 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 1921 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 1922 sizeof (struct fcp32_ioctl), mode)) { 1923 return (EFAULT); 1924 } 1925 break; 1926 } 1927 case DDI_MODEL_NONE: 1928 if (ddi_copyout((void *)&fioctl, (void *)data, 1929 sizeof (struct fcp_ioctl), mode)) { 1930 return (EFAULT); 1931 } 1932 break; 1933 } 1934 #else /* _MULTI_DATAMODEL */ 1935 1936 if (ddi_copyout((void *)&fioctl, (void *)data, 1937 sizeof (struct fcp_ioctl), mode)) { 1938 return (EFAULT); 1939 } 1940 #endif /* _MULTI_DATAMODEL */ 1941 1942 return (0); 1943 } 1944 1945 /* 1946 * fcp_setup_scsi_ioctl 1947 * Setup handler for the "scsi passthru" style of 1948 * ioctl for FCP. See "fcp_util.h" for data structure 1949 * definition. 1950 * 1951 * Input: 1952 * u_fscsi = ioctl data (user address space) 1953 * mode = See ioctl(9E) 1954 * 1955 * Output: 1956 * u_fscsi = ioctl data (user address space) 1957 * rval = return value - see ioctl(9E) 1958 * 1959 * Returns: 1960 * 0 = OK 1961 * EAGAIN = See errno.h 1962 * EBUSY = See errno.h 1963 * EFAULT = See errno.h 1964 * EINTR = See errno.h 1965 * EINVAL = See errno.h 1966 * EIO = See errno.h 1967 * ENOMEM = See errno.h 1968 * ENXIO = See errno.h 1969 * 1970 * Context: 1971 * Kernel context. 1972 */ 1973 /* ARGSUSED */ 1974 static int 1975 fcp_setup_scsi_ioctl(struct fcp_scsi_cmd *u_fscsi, 1976 int mode, int *rval) 1977 { 1978 int ret = 0; 1979 int temp_ret; 1980 caddr_t k_cdbbufaddr = NULL; 1981 caddr_t k_bufaddr = NULL; 1982 caddr_t k_rqbufaddr = NULL; 1983 caddr_t u_cdbbufaddr; 1984 caddr_t u_bufaddr; 1985 caddr_t u_rqbufaddr; 1986 struct fcp_scsi_cmd k_fscsi; 1987 1988 /* 1989 * Get fcp_scsi_cmd array element from user address space 1990 */ 1991 if ((ret = fcp_copyin_scsi_cmd((caddr_t)u_fscsi, &k_fscsi, mode)) 1992 != 0) { 1993 return (ret); 1994 } 1995 1996 1997 /* 1998 * Even though kmem_alloc() checks the validity of the 1999 * buffer length, this check is needed when the 2000 * kmem_flags set and the zero buffer length is passed. 2001 */ 2002 if ((k_fscsi.scsi_cdblen <= 0) || 2003 (k_fscsi.scsi_buflen <= 0) || 2004 (k_fscsi.scsi_rqlen <= 0)) { 2005 return (EINVAL); 2006 } 2007 2008 /* 2009 * Allocate data for fcp_scsi_cmd pointer fields 2010 */ 2011 if (ret == 0) { 2012 k_cdbbufaddr = kmem_alloc(k_fscsi.scsi_cdblen, KM_NOSLEEP); 2013 k_bufaddr = kmem_alloc(k_fscsi.scsi_buflen, KM_NOSLEEP); 2014 k_rqbufaddr = kmem_alloc(k_fscsi.scsi_rqlen, KM_NOSLEEP); 2015 2016 if (k_cdbbufaddr == NULL || 2017 k_bufaddr == NULL || 2018 k_rqbufaddr == NULL) { 2019 ret = ENOMEM; 2020 } 2021 } 2022 2023 /* 2024 * Get fcp_scsi_cmd pointer fields from user 2025 * address space 2026 */ 2027 if (ret == 0) { 2028 u_cdbbufaddr = k_fscsi.scsi_cdbbufaddr; 2029 u_bufaddr = k_fscsi.scsi_bufaddr; 2030 u_rqbufaddr = k_fscsi.scsi_rqbufaddr; 2031 2032 if (ddi_copyin(u_cdbbufaddr, 2033 k_cdbbufaddr, 2034 k_fscsi.scsi_cdblen, 2035 mode)) { 2036 ret = EFAULT; 2037 } else if (ddi_copyin(u_bufaddr, 2038 k_bufaddr, 2039 k_fscsi.scsi_buflen, 2040 mode)) { 2041 ret = EFAULT; 2042 } else if (ddi_copyin(u_rqbufaddr, 2043 k_rqbufaddr, 2044 k_fscsi.scsi_rqlen, 2045 mode)) { 2046 ret = EFAULT; 2047 } 2048 } 2049 2050 /* 2051 * Send scsi command (blocking) 2052 */ 2053 if (ret == 0) { 2054 /* 2055 * Prior to sending the scsi command, the 2056 * fcp_scsi_cmd data structure must contain kernel, 2057 * not user, addresses. 2058 */ 2059 k_fscsi.scsi_cdbbufaddr = k_cdbbufaddr; 2060 k_fscsi.scsi_bufaddr = k_bufaddr; 2061 k_fscsi.scsi_rqbufaddr = k_rqbufaddr; 2062 2063 ret = fcp_send_scsi_ioctl(&k_fscsi); 2064 2065 /* 2066 * After sending the scsi command, the 2067 * fcp_scsi_cmd data structure must contain user, 2068 * not kernel, addresses. 2069 */ 2070 k_fscsi.scsi_cdbbufaddr = u_cdbbufaddr; 2071 k_fscsi.scsi_bufaddr = u_bufaddr; 2072 k_fscsi.scsi_rqbufaddr = u_rqbufaddr; 2073 } 2074 2075 /* 2076 * Put fcp_scsi_cmd pointer fields to user address space 2077 */ 2078 if (ret == 0) { 2079 if (ddi_copyout(k_cdbbufaddr, 2080 u_cdbbufaddr, 2081 k_fscsi.scsi_cdblen, 2082 mode)) { 2083 ret = EFAULT; 2084 } else if (ddi_copyout(k_bufaddr, 2085 u_bufaddr, 2086 k_fscsi.scsi_buflen, 2087 mode)) { 2088 ret = EFAULT; 2089 } else if (ddi_copyout(k_rqbufaddr, 2090 u_rqbufaddr, 2091 k_fscsi.scsi_rqlen, 2092 mode)) { 2093 ret = EFAULT; 2094 } 2095 } 2096 2097 /* 2098 * Free data for fcp_scsi_cmd pointer fields 2099 */ 2100 if (k_cdbbufaddr != NULL) { 2101 kmem_free(k_cdbbufaddr, k_fscsi.scsi_cdblen); 2102 } 2103 if (k_bufaddr != NULL) { 2104 kmem_free(k_bufaddr, k_fscsi.scsi_buflen); 2105 } 2106 if (k_rqbufaddr != NULL) { 2107 kmem_free(k_rqbufaddr, k_fscsi.scsi_rqlen); 2108 } 2109 2110 /* 2111 * Put fcp_scsi_cmd array element to user address space 2112 */ 2113 temp_ret = fcp_copyout_scsi_cmd(&k_fscsi, (caddr_t)u_fscsi, mode); 2114 if (temp_ret != 0) { 2115 ret = temp_ret; 2116 } 2117 2118 /* 2119 * Return status 2120 */ 2121 return (ret); 2122 } 2123 2124 2125 /* 2126 * fcp_copyin_scsi_cmd 2127 * Copy in fcp_scsi_cmd data structure from user address space. 2128 * The data may be in 32 bit or 64 bit modes. 2129 * 2130 * Input: 2131 * base_addr = from address (user address space) 2132 * mode = See ioctl(9E) and ddi_copyin(9F) 2133 * 2134 * Output: 2135 * fscsi = to address (kernel address space) 2136 * 2137 * Returns: 2138 * 0 = OK 2139 * EFAULT = Error 2140 * 2141 * Context: 2142 * Kernel context. 2143 */ 2144 static int 2145 fcp_copyin_scsi_cmd(caddr_t base_addr, struct fcp_scsi_cmd *fscsi, int mode) 2146 { 2147 #ifdef _MULTI_DATAMODEL 2148 struct fcp32_scsi_cmd f32scsi; 2149 2150 switch (ddi_model_convert_from(mode & FMODELS)) { 2151 case DDI_MODEL_ILP32: 2152 /* 2153 * Copy data from user address space 2154 */ 2155 if (ddi_copyin((void *)base_addr, 2156 &f32scsi, 2157 sizeof (struct fcp32_scsi_cmd), 2158 mode)) { 2159 return (EFAULT); 2160 } 2161 /* 2162 * Convert from 32 bit to 64 bit 2163 */ 2164 FCP32_SCSI_CMD_TO_FCP_SCSI_CMD(&f32scsi, fscsi); 2165 break; 2166 case DDI_MODEL_NONE: 2167 /* 2168 * Copy data from user address space 2169 */ 2170 if (ddi_copyin((void *)base_addr, 2171 fscsi, 2172 sizeof (struct fcp_scsi_cmd), 2173 mode)) { 2174 return (EFAULT); 2175 } 2176 break; 2177 } 2178 #else /* _MULTI_DATAMODEL */ 2179 /* 2180 * Copy data from user address space 2181 */ 2182 if (ddi_copyin((void *)base_addr, 2183 fscsi, 2184 sizeof (struct fcp_scsi_cmd), 2185 mode)) { 2186 return (EFAULT); 2187 } 2188 #endif /* _MULTI_DATAMODEL */ 2189 2190 return (0); 2191 } 2192 2193 2194 /* 2195 * fcp_copyout_scsi_cmd 2196 * Copy out fcp_scsi_cmd data structure to user address space. 2197 * The data may be in 32 bit or 64 bit modes. 2198 * 2199 * Input: 2200 * fscsi = to address (kernel address space) 2201 * mode = See ioctl(9E) and ddi_copyin(9F) 2202 * 2203 * Output: 2204 * base_addr = from address (user address space) 2205 * 2206 * Returns: 2207 * 0 = OK 2208 * EFAULT = Error 2209 * 2210 * Context: 2211 * Kernel context. 2212 */ 2213 static int 2214 fcp_copyout_scsi_cmd(struct fcp_scsi_cmd *fscsi, caddr_t base_addr, int mode) 2215 { 2216 #ifdef _MULTI_DATAMODEL 2217 struct fcp32_scsi_cmd f32scsi; 2218 2219 switch (ddi_model_convert_from(mode & FMODELS)) { 2220 case DDI_MODEL_ILP32: 2221 /* 2222 * Convert from 64 bit to 32 bit 2223 */ 2224 FCP_SCSI_CMD_TO_FCP32_SCSI_CMD(fscsi, &f32scsi); 2225 /* 2226 * Copy data to user address space 2227 */ 2228 if (ddi_copyout(&f32scsi, 2229 (void *)base_addr, 2230 sizeof (struct fcp32_scsi_cmd), 2231 mode)) { 2232 return (EFAULT); 2233 } 2234 break; 2235 case DDI_MODEL_NONE: 2236 /* 2237 * Copy data to user address space 2238 */ 2239 if (ddi_copyout(fscsi, 2240 (void *)base_addr, 2241 sizeof (struct fcp_scsi_cmd), 2242 mode)) { 2243 return (EFAULT); 2244 } 2245 break; 2246 } 2247 #else /* _MULTI_DATAMODEL */ 2248 /* 2249 * Copy data to user address space 2250 */ 2251 if (ddi_copyout(fscsi, 2252 (void *)base_addr, 2253 sizeof (struct fcp_scsi_cmd), 2254 mode)) { 2255 return (EFAULT); 2256 } 2257 #endif /* _MULTI_DATAMODEL */ 2258 2259 return (0); 2260 } 2261 2262 2263 /* 2264 * fcp_send_scsi_ioctl 2265 * Sends the SCSI command in blocking mode. 2266 * 2267 * Input: 2268 * fscsi = SCSI command data structure 2269 * 2270 * Output: 2271 * fscsi = SCSI command data structure 2272 * 2273 * Returns: 2274 * 0 = OK 2275 * EAGAIN = See errno.h 2276 * EBUSY = See errno.h 2277 * EINTR = See errno.h 2278 * EINVAL = See errno.h 2279 * EIO = See errno.h 2280 * ENOMEM = See errno.h 2281 * ENXIO = See errno.h 2282 * 2283 * Context: 2284 * Kernel context. 2285 */ 2286 static int 2287 fcp_send_scsi_ioctl(struct fcp_scsi_cmd *fscsi) 2288 { 2289 struct fcp_lun *plun = NULL; 2290 struct fcp_port *pptr = NULL; 2291 struct fcp_tgt *ptgt = NULL; 2292 fc_packet_t *fpkt = NULL; 2293 struct fcp_ipkt *icmd = NULL; 2294 int target_created = FALSE; 2295 fc_frame_hdr_t *hp; 2296 struct fcp_cmd fcp_cmd; 2297 struct fcp_cmd *fcmd; 2298 union scsi_cdb *scsi_cdb; 2299 la_wwn_t *wwn_ptr; 2300 int nodma; 2301 struct fcp_rsp *rsp; 2302 struct fcp_rsp_info *rsp_info; 2303 caddr_t rsp_sense; 2304 int buf_len; 2305 int info_len; 2306 int sense_len; 2307 struct scsi_extended_sense *sense_to = NULL; 2308 timeout_id_t tid; 2309 uint8_t reconfig_lun = FALSE; 2310 uint8_t reconfig_pending = FALSE; 2311 uint8_t scsi_cmd; 2312 int rsp_len; 2313 int cmd_index; 2314 int fc_status; 2315 int pkt_state; 2316 int pkt_action; 2317 int pkt_reason; 2318 int ret, xport_retval = ~FC_SUCCESS; 2319 int lcount; 2320 int tcount; 2321 int reconfig_status; 2322 int port_busy = FALSE; 2323 uchar_t *lun_string; 2324 2325 /* 2326 * Check valid SCSI command 2327 */ 2328 scsi_cmd = ((uint8_t *)fscsi->scsi_cdbbufaddr)[0]; 2329 ret = EINVAL; 2330 for (cmd_index = 0; 2331 cmd_index < FCP_NUM_ELEMENTS(scsi_ioctl_list) && 2332 ret != 0; 2333 cmd_index++) { 2334 /* 2335 * First byte of CDB is the SCSI command 2336 */ 2337 if (scsi_ioctl_list[cmd_index] == scsi_cmd) { 2338 ret = 0; 2339 } 2340 } 2341 2342 /* 2343 * Check inputs 2344 */ 2345 if (fscsi->scsi_flags != FCP_SCSI_READ) { 2346 ret = EINVAL; 2347 } else if (fscsi->scsi_cdblen > FCP_CDB_SIZE) { 2348 /* no larger than */ 2349 ret = EINVAL; 2350 } 2351 2352 2353 /* 2354 * Find FC port 2355 */ 2356 if (ret == 0) { 2357 /* 2358 * Acquire global mutex 2359 */ 2360 mutex_enter(&fcp_global_mutex); 2361 2362 pptr = fcp_port_head; 2363 while (pptr) { 2364 if (pptr->port_instance == 2365 (uint32_t)fscsi->scsi_fc_port_num) { 2366 break; 2367 } else { 2368 pptr = pptr->port_next; 2369 } 2370 } 2371 2372 if (pptr == NULL) { 2373 ret = ENXIO; 2374 } else { 2375 /* 2376 * fc_ulp_busy_port can raise power 2377 * so, we must not hold any mutexes involved in PM 2378 */ 2379 mutex_exit(&fcp_global_mutex); 2380 ret = fc_ulp_busy_port(pptr->port_fp_handle); 2381 } 2382 2383 if (ret == 0) { 2384 2385 /* remember port is busy, so we will release later */ 2386 port_busy = TRUE; 2387 2388 /* 2389 * If there is a reconfiguration in progress, wait 2390 * for it to complete. 2391 */ 2392 2393 fcp_reconfig_wait(pptr); 2394 2395 /* reacquire mutexes in order */ 2396 mutex_enter(&fcp_global_mutex); 2397 mutex_enter(&pptr->port_mutex); 2398 2399 /* 2400 * Will port accept DMA? 2401 */ 2402 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) 2403 ? 1 : 0; 2404 2405 /* 2406 * If init or offline, device not known 2407 * 2408 * If we are discovering (onlining), we can 2409 * NOT obviously provide reliable data about 2410 * devices until it is complete 2411 */ 2412 if (pptr->port_state & (FCP_STATE_INIT | 2413 FCP_STATE_OFFLINE)) { 2414 ret = ENXIO; 2415 } else if (pptr->port_state & FCP_STATE_ONLINING) { 2416 ret = EBUSY; 2417 } else { 2418 /* 2419 * Find target from pwwn 2420 * 2421 * The wwn must be put into a local 2422 * variable to ensure alignment. 2423 */ 2424 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2425 ptgt = fcp_lookup_target(pptr, 2426 (uchar_t *)wwn_ptr); 2427 2428 /* 2429 * If target not found, 2430 */ 2431 if (ptgt == NULL) { 2432 /* 2433 * Note: Still have global & 2434 * port mutexes 2435 */ 2436 mutex_exit(&pptr->port_mutex); 2437 ptgt = fcp_port_create_tgt(pptr, 2438 wwn_ptr, &ret, &fc_status, 2439 &pkt_state, &pkt_action, 2440 &pkt_reason); 2441 mutex_enter(&pptr->port_mutex); 2442 2443 fscsi->scsi_fc_status = fc_status; 2444 fscsi->scsi_pkt_state = 2445 (uchar_t)pkt_state; 2446 fscsi->scsi_pkt_reason = pkt_reason; 2447 fscsi->scsi_pkt_action = 2448 (uchar_t)pkt_action; 2449 2450 if (ptgt != NULL) { 2451 target_created = TRUE; 2452 } else if (ret == 0) { 2453 ret = ENOMEM; 2454 } 2455 } 2456 2457 if (ret == 0) { 2458 /* 2459 * Acquire target 2460 */ 2461 mutex_enter(&ptgt->tgt_mutex); 2462 2463 /* 2464 * If target is mark or busy, 2465 * then target can not be used 2466 */ 2467 if (ptgt->tgt_state & 2468 (FCP_TGT_MARK | 2469 FCP_TGT_BUSY)) { 2470 ret = EBUSY; 2471 } else { 2472 /* 2473 * Mark target as busy 2474 */ 2475 ptgt->tgt_state |= 2476 FCP_TGT_BUSY; 2477 } 2478 2479 /* 2480 * Release target 2481 */ 2482 lcount = pptr->port_link_cnt; 2483 tcount = ptgt->tgt_change_cnt; 2484 mutex_exit(&ptgt->tgt_mutex); 2485 } 2486 } 2487 2488 /* 2489 * Release port 2490 */ 2491 mutex_exit(&pptr->port_mutex); 2492 } 2493 2494 /* 2495 * Release global mutex 2496 */ 2497 mutex_exit(&fcp_global_mutex); 2498 } 2499 2500 if (ret == 0) { 2501 uint64_t belun = BE_64(fscsi->scsi_lun); 2502 2503 /* 2504 * If it's a target device, find lun from pwwn 2505 * The wwn must be put into a local 2506 * variable to ensure alignment. 2507 */ 2508 mutex_enter(&pptr->port_mutex); 2509 wwn_ptr = (la_wwn_t *)&(fscsi->scsi_fc_pwwn); 2510 if (!ptgt->tgt_tcap && ptgt->tgt_icap) { 2511 /* this is not a target */ 2512 fscsi->scsi_fc_status = FC_DEVICE_NOT_TGT; 2513 ret = ENXIO; 2514 } else if ((belun << 16) != 0) { 2515 /* 2516 * Since fcp only support PD and LU addressing method 2517 * so far, the last 6 bytes of a valid LUN are expected 2518 * to be filled with 00h. 2519 */ 2520 fscsi->scsi_fc_status = FC_INVALID_LUN; 2521 cmn_err(CE_WARN, "fcp: Unsupported LUN addressing" 2522 " method 0x%02x with LUN number 0x%016" PRIx64, 2523 (uint8_t)(belun >> 62), belun); 2524 ret = ENXIO; 2525 } else if ((plun = fcp_lookup_lun(pptr, (uchar_t *)wwn_ptr, 2526 (uint16_t)((belun >> 48) & 0x3fff))) == NULL) { 2527 /* 2528 * This is a SCSI target, but no LUN at this 2529 * address. 2530 * 2531 * In the future, we may want to send this to 2532 * the target, and let it respond 2533 * appropriately 2534 */ 2535 ret = ENXIO; 2536 } 2537 mutex_exit(&pptr->port_mutex); 2538 } 2539 2540 /* 2541 * Finished grabbing external resources 2542 * Allocate internal packet (icmd) 2543 */ 2544 if (ret == 0) { 2545 /* 2546 * Calc rsp len assuming rsp info included 2547 */ 2548 rsp_len = sizeof (struct fcp_rsp) + 2549 sizeof (struct fcp_rsp_info) + fscsi->scsi_rqlen; 2550 2551 icmd = fcp_icmd_alloc(pptr, ptgt, 2552 sizeof (struct fcp_cmd), 2553 rsp_len, 2554 fscsi->scsi_buflen, 2555 nodma, 2556 lcount, /* ipkt_link_cnt */ 2557 tcount, /* ipkt_change_cnt */ 2558 0, /* cause */ 2559 FC_INVALID_RSCN_COUNT); /* invalidate the count */ 2560 2561 if (icmd == NULL) { 2562 ret = ENOMEM; 2563 } else { 2564 /* 2565 * Setup internal packet as sema sync 2566 */ 2567 fcp_ipkt_sema_init(icmd); 2568 } 2569 } 2570 2571 if (ret == 0) { 2572 /* 2573 * Init fpkt pointer for use. 2574 */ 2575 2576 fpkt = icmd->ipkt_fpkt; 2577 2578 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 2579 fpkt->pkt_tran_type = FC_PKT_FCP_READ; /* only rd for now */ 2580 fpkt->pkt_timeout = fscsi->scsi_timeout; 2581 2582 /* 2583 * Init fcmd pointer for use by SCSI command 2584 */ 2585 2586 if (nodma) { 2587 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 2588 } else { 2589 fcmd = &fcp_cmd; 2590 } 2591 bzero(fcmd, sizeof (struct fcp_cmd)); 2592 ptgt = plun->lun_tgt; 2593 2594 lun_string = (uchar_t *)&fscsi->scsi_lun; 2595 2596 fcmd->fcp_ent_addr.ent_addr_0 = 2597 BE_16(*(uint16_t *)&(lun_string[0])); 2598 fcmd->fcp_ent_addr.ent_addr_1 = 2599 BE_16(*(uint16_t *)&(lun_string[2])); 2600 fcmd->fcp_ent_addr.ent_addr_2 = 2601 BE_16(*(uint16_t *)&(lun_string[4])); 2602 fcmd->fcp_ent_addr.ent_addr_3 = 2603 BE_16(*(uint16_t *)&(lun_string[6])); 2604 2605 /* 2606 * Setup internal packet(icmd) 2607 */ 2608 icmd->ipkt_lun = plun; 2609 icmd->ipkt_restart = 0; 2610 icmd->ipkt_retries = 0; 2611 icmd->ipkt_opcode = 0; 2612 2613 /* 2614 * Init the frame HEADER Pointer for use 2615 */ 2616 hp = &fpkt->pkt_cmd_fhdr; 2617 2618 hp->s_id = pptr->port_id; 2619 hp->d_id = ptgt->tgt_d_id; 2620 hp->r_ctl = R_CTL_COMMAND; 2621 hp->type = FC_TYPE_SCSI_FCP; 2622 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 2623 hp->rsvd = 0; 2624 hp->seq_id = 0; 2625 hp->seq_cnt = 0; 2626 hp->ox_id = 0xffff; 2627 hp->rx_id = 0xffff; 2628 hp->ro = 0; 2629 2630 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 2631 fcmd->fcp_cntl.cntl_read_data = 1; /* only rd for now */ 2632 fcmd->fcp_cntl.cntl_write_data = 0; 2633 fcmd->fcp_data_len = fscsi->scsi_buflen; 2634 2635 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 2636 bcopy((char *)fscsi->scsi_cdbbufaddr, (char *)scsi_cdb, 2637 fscsi->scsi_cdblen); 2638 2639 if (!nodma) { 2640 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 2641 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 2642 } 2643 2644 /* 2645 * Send SCSI command to FC transport 2646 */ 2647 2648 if (ret == 0) { 2649 mutex_enter(&ptgt->tgt_mutex); 2650 2651 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 2652 mutex_exit(&ptgt->tgt_mutex); 2653 fscsi->scsi_fc_status = xport_retval = 2654 fc_ulp_transport(pptr->port_fp_handle, 2655 fpkt); 2656 if (fscsi->scsi_fc_status != FC_SUCCESS) { 2657 ret = EIO; 2658 } 2659 } else { 2660 mutex_exit(&ptgt->tgt_mutex); 2661 ret = EBUSY; 2662 } 2663 } 2664 } 2665 2666 /* 2667 * Wait for completion only if fc_ulp_transport was called and it 2668 * returned a success. This is the only time callback will happen. 2669 * Otherwise, there is no point in waiting 2670 */ 2671 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2672 ret = fcp_ipkt_sema_wait(icmd); 2673 } 2674 2675 /* 2676 * Copy data to IOCTL data structures 2677 */ 2678 rsp = NULL; 2679 if ((ret == 0) && (xport_retval == FC_SUCCESS)) { 2680 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 2681 2682 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 2683 fcp_log(CE_WARN, pptr->port_dip, 2684 "!SCSI command to d_id=0x%x lun=0x%x" 2685 " failed, Bad FCP response values:" 2686 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 2687 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 2688 ptgt->tgt_d_id, plun->lun_num, 2689 rsp->reserved_0, rsp->reserved_1, 2690 rsp->fcp_u.fcp_status.reserved_0, 2691 rsp->fcp_u.fcp_status.reserved_1, 2692 rsp->fcp_response_len, rsp->fcp_sense_len); 2693 2694 ret = EIO; 2695 } 2696 } 2697 2698 if ((ret == 0) && (rsp != NULL)) { 2699 /* 2700 * Calc response lengths 2701 */ 2702 sense_len = 0; 2703 info_len = 0; 2704 2705 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2706 info_len = rsp->fcp_response_len; 2707 } 2708 2709 rsp_info = (struct fcp_rsp_info *) 2710 ((uint8_t *)rsp + sizeof (struct fcp_rsp)); 2711 2712 /* 2713 * Get SCSI status 2714 */ 2715 fscsi->scsi_bufstatus = rsp->fcp_u.fcp_status.scsi_status; 2716 /* 2717 * If a lun was just added or removed and the next command 2718 * comes through this interface, we need to capture the check 2719 * condition so we can discover the new topology. 2720 */ 2721 if (fscsi->scsi_bufstatus != STATUS_GOOD && 2722 rsp->fcp_u.fcp_status.sense_len_set) { 2723 sense_len = rsp->fcp_sense_len; 2724 rsp_sense = (caddr_t)((uint8_t *)rsp_info + info_len); 2725 sense_to = (struct scsi_extended_sense *)rsp_sense; 2726 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 2727 (FCP_SENSE_NO_LUN(sense_to))) { 2728 reconfig_lun = TRUE; 2729 } 2730 } 2731 2732 if (fscsi->scsi_bufstatus == STATUS_GOOD && (ptgt != NULL) && 2733 (reconfig_lun || (scsi_cdb->scc_cmd == SCMD_REPORT_LUN))) { 2734 if (reconfig_lun == FALSE) { 2735 reconfig_status = 2736 fcp_is_reconfig_needed(ptgt, fpkt); 2737 } 2738 2739 if ((reconfig_lun == TRUE) || 2740 (reconfig_status == TRUE)) { 2741 mutex_enter(&ptgt->tgt_mutex); 2742 if (ptgt->tgt_tid == NULL) { 2743 /* 2744 * Either we've been notified the 2745 * REPORT_LUN data has changed, or 2746 * we've determined on our own that 2747 * we're out of date. Kick off 2748 * rediscovery. 2749 */ 2750 tid = timeout(fcp_reconfigure_luns, 2751 (caddr_t)ptgt, drv_usectohz(1)); 2752 2753 ptgt->tgt_tid = tid; 2754 ptgt->tgt_state |= FCP_TGT_BUSY; 2755 ret = EBUSY; 2756 reconfig_pending = TRUE; 2757 } 2758 mutex_exit(&ptgt->tgt_mutex); 2759 } 2760 } 2761 2762 /* 2763 * Calc residuals and buffer lengths 2764 */ 2765 2766 if (ret == 0) { 2767 buf_len = fscsi->scsi_buflen; 2768 fscsi->scsi_bufresid = 0; 2769 if (rsp->fcp_u.fcp_status.resid_under) { 2770 if (rsp->fcp_resid <= fscsi->scsi_buflen) { 2771 fscsi->scsi_bufresid = rsp->fcp_resid; 2772 } else { 2773 cmn_err(CE_WARN, "fcp: bad residue %x " 2774 "for txfer len %x", rsp->fcp_resid, 2775 fscsi->scsi_buflen); 2776 fscsi->scsi_bufresid = 2777 fscsi->scsi_buflen; 2778 } 2779 buf_len -= fscsi->scsi_bufresid; 2780 } 2781 if (rsp->fcp_u.fcp_status.resid_over) { 2782 fscsi->scsi_bufresid = -rsp->fcp_resid; 2783 } 2784 2785 fscsi->scsi_rqresid = fscsi->scsi_rqlen - sense_len; 2786 if (fscsi->scsi_rqlen < sense_len) { 2787 sense_len = fscsi->scsi_rqlen; 2788 } 2789 2790 fscsi->scsi_fc_rspcode = 0; 2791 if (rsp->fcp_u.fcp_status.rsp_len_set) { 2792 fscsi->scsi_fc_rspcode = rsp_info->rsp_code; 2793 } 2794 fscsi->scsi_pkt_state = fpkt->pkt_state; 2795 fscsi->scsi_pkt_action = fpkt->pkt_action; 2796 fscsi->scsi_pkt_reason = fpkt->pkt_reason; 2797 2798 /* 2799 * Copy data and request sense 2800 * 2801 * Data must be copied by using the FCP_CP_IN macro. 2802 * This will ensure the proper byte order since the data 2803 * is being copied directly from the memory mapped 2804 * device register. 2805 * 2806 * The response (and request sense) will be in the 2807 * correct byte order. No special copy is necessary. 2808 */ 2809 2810 if (buf_len) { 2811 FCP_CP_IN(fpkt->pkt_data, 2812 fscsi->scsi_bufaddr, 2813 fpkt->pkt_data_acc, 2814 buf_len); 2815 } 2816 bcopy((void *)rsp_sense, 2817 (void *)fscsi->scsi_rqbufaddr, 2818 sense_len); 2819 } 2820 } 2821 2822 /* 2823 * Cleanup transport data structures if icmd was alloc-ed 2824 * So, cleanup happens in the same thread that icmd was alloc-ed 2825 */ 2826 if (icmd != NULL) { 2827 fcp_ipkt_sema_cleanup(icmd); 2828 } 2829 2830 /* restore pm busy/idle status */ 2831 if (port_busy) { 2832 fc_ulp_idle_port(pptr->port_fp_handle); 2833 } 2834 2835 /* 2836 * Cleanup target. if a reconfig is pending, don't clear the BUSY 2837 * flag, it'll be cleared when the reconfig is complete. 2838 */ 2839 if ((ptgt != NULL) && !reconfig_pending) { 2840 /* 2841 * If target was created, 2842 */ 2843 if (target_created) { 2844 mutex_enter(&ptgt->tgt_mutex); 2845 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2846 mutex_exit(&ptgt->tgt_mutex); 2847 } else { 2848 /* 2849 * De-mark target as busy 2850 */ 2851 mutex_enter(&ptgt->tgt_mutex); 2852 ptgt->tgt_state &= ~FCP_TGT_BUSY; 2853 mutex_exit(&ptgt->tgt_mutex); 2854 } 2855 } 2856 return (ret); 2857 } 2858 2859 2860 static int 2861 fcp_is_reconfig_needed(struct fcp_tgt *ptgt, 2862 fc_packet_t *fpkt) 2863 { 2864 uchar_t *lun_string; 2865 uint16_t lun_num, i; 2866 int num_luns; 2867 int actual_luns; 2868 int num_masked_luns; 2869 int lun_buflen; 2870 struct fcp_lun *plun = NULL; 2871 struct fcp_reportlun_resp *report_lun; 2872 uint8_t reconfig_needed = FALSE; 2873 uint8_t lun_exists = FALSE; 2874 fcp_port_t *pptr = ptgt->tgt_port; 2875 2876 report_lun = kmem_zalloc(fpkt->pkt_datalen, KM_SLEEP); 2877 2878 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 2879 fpkt->pkt_datalen); 2880 2881 /* get number of luns (which is supplied as LUNS * 8) */ 2882 num_luns = BE_32(report_lun->num_lun) >> 3; 2883 2884 /* 2885 * Figure out exactly how many lun strings our response buffer 2886 * can hold. 2887 */ 2888 lun_buflen = (fpkt->pkt_datalen - 2889 2 * sizeof (uint32_t)) / sizeof (longlong_t); 2890 2891 /* 2892 * Is our response buffer full or not? We don't want to 2893 * potentially walk beyond the number of luns we have. 2894 */ 2895 if (num_luns <= lun_buflen) { 2896 actual_luns = num_luns; 2897 } else { 2898 actual_luns = lun_buflen; 2899 } 2900 2901 mutex_enter(&ptgt->tgt_mutex); 2902 2903 /* Scan each lun to see if we have masked it. */ 2904 num_masked_luns = 0; 2905 if (fcp_lun_blacklist != NULL) { 2906 for (i = 0; i < actual_luns; i++) { 2907 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2908 switch (lun_string[0] & 0xC0) { 2909 case FCP_LUN_ADDRESSING: 2910 case FCP_PD_ADDRESSING: 2911 case FCP_VOLUME_ADDRESSING: 2912 lun_num = ((lun_string[0] & 0x3F) << 8) 2913 | lun_string[1]; 2914 if (fcp_should_mask(&ptgt->tgt_port_wwn, 2915 lun_num) == TRUE) { 2916 num_masked_luns++; 2917 } 2918 break; 2919 default: 2920 break; 2921 } 2922 } 2923 } 2924 2925 /* 2926 * The quick and easy check. If the number of LUNs reported 2927 * doesn't match the number we currently know about, we need 2928 * to reconfigure. 2929 */ 2930 if (num_luns && num_luns != (ptgt->tgt_lun_cnt + num_masked_luns)) { 2931 mutex_exit(&ptgt->tgt_mutex); 2932 kmem_free(report_lun, fpkt->pkt_datalen); 2933 return (TRUE); 2934 } 2935 2936 /* 2937 * If the quick and easy check doesn't turn up anything, we walk 2938 * the list of luns from the REPORT_LUN response and look for 2939 * any luns we don't know about. If we find one, we know we need 2940 * to reconfigure. We will skip LUNs that are masked because of the 2941 * blacklist. 2942 */ 2943 for (i = 0; i < actual_luns; i++) { 2944 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 2945 lun_exists = FALSE; 2946 switch (lun_string[0] & 0xC0) { 2947 case FCP_LUN_ADDRESSING: 2948 case FCP_PD_ADDRESSING: 2949 case FCP_VOLUME_ADDRESSING: 2950 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 2951 2952 if ((fcp_lun_blacklist != NULL) && (fcp_should_mask( 2953 &ptgt->tgt_port_wwn, lun_num) == TRUE)) { 2954 lun_exists = TRUE; 2955 break; 2956 } 2957 2958 for (plun = ptgt->tgt_lun; plun; 2959 plun = plun->lun_next) { 2960 if (plun->lun_num == lun_num) { 2961 lun_exists = TRUE; 2962 break; 2963 } 2964 } 2965 break; 2966 default: 2967 break; 2968 } 2969 2970 if (lun_exists == FALSE) { 2971 reconfig_needed = TRUE; 2972 break; 2973 } 2974 } 2975 2976 mutex_exit(&ptgt->tgt_mutex); 2977 kmem_free(report_lun, fpkt->pkt_datalen); 2978 2979 return (reconfig_needed); 2980 } 2981 2982 /* 2983 * This function is called by fcp_handle_page83 and uses inquiry response data 2984 * stored in plun->lun_inq to determine whether or not a device is a member of 2985 * the table fcp_symmetric_disk_table_size. We return 0 if it is in the table, 2986 * otherwise 1. 2987 */ 2988 static int 2989 fcp_symmetric_device_probe(struct fcp_lun *plun) 2990 { 2991 struct scsi_inquiry *stdinq = &plun->lun_inq; 2992 char *devidptr; 2993 int i, len; 2994 2995 for (i = 0; i < fcp_symmetric_disk_table_size; i++) { 2996 devidptr = fcp_symmetric_disk_table[i]; 2997 len = (int)strlen(devidptr); 2998 2999 if (bcmp(stdinq->inq_vid, devidptr, len) == 0) { 3000 return (0); 3001 } 3002 } 3003 return (1); 3004 } 3005 3006 3007 /* 3008 * This function is called by fcp_ioctl for the FCP_STATE_COUNT ioctl 3009 * It basically returns the current count of # of state change callbacks 3010 * i.e the value of tgt_change_cnt. 3011 * 3012 * INPUT: 3013 * fcp_ioctl.fp_minor -> The minor # of the fp port 3014 * fcp_ioctl.listlen -> 1 3015 * fcp_ioctl.list -> Pointer to a 32 bit integer 3016 */ 3017 /*ARGSUSED2*/ 3018 static int 3019 fcp_get_statec_count(struct fcp_ioctl *data, int mode, int *rval) 3020 { 3021 int ret; 3022 uint32_t link_cnt; 3023 struct fcp_ioctl fioctl; 3024 struct fcp_port *pptr = NULL; 3025 3026 if ((ret = fcp_copyin_fcp_ioctl_data(data, mode, rval, &fioctl, 3027 &pptr)) != 0) { 3028 return (ret); 3029 } 3030 3031 ASSERT(pptr != NULL); 3032 3033 if (fioctl.listlen != 1) { 3034 return (EINVAL); 3035 } 3036 3037 mutex_enter(&pptr->port_mutex); 3038 if (pptr->port_state & FCP_STATE_OFFLINE) { 3039 mutex_exit(&pptr->port_mutex); 3040 return (ENXIO); 3041 } 3042 3043 /* 3044 * FCP_STATE_INIT is set in 2 cases (not sure why it is overloaded): 3045 * When the fcp initially attaches to the port and there are nothing 3046 * hanging out of the port or if there was a repeat offline state change 3047 * callback (refer fcp_statec_callback() FC_STATE_OFFLINE case). 3048 * In the latter case, port_tmp_cnt will be non-zero and that is how we 3049 * will differentiate the 2 cases. 3050 */ 3051 if ((pptr->port_state & FCP_STATE_INIT) && pptr->port_tmp_cnt) { 3052 mutex_exit(&pptr->port_mutex); 3053 return (ENXIO); 3054 } 3055 3056 link_cnt = pptr->port_link_cnt; 3057 mutex_exit(&pptr->port_mutex); 3058 3059 if (ddi_copyout(&link_cnt, fioctl.list, (sizeof (uint32_t)), mode)) { 3060 return (EFAULT); 3061 } 3062 3063 #ifdef _MULTI_DATAMODEL 3064 switch (ddi_model_convert_from(mode & FMODELS)) { 3065 case DDI_MODEL_ILP32: { 3066 struct fcp32_ioctl f32_ioctl; 3067 3068 f32_ioctl.fp_minor = fioctl.fp_minor; 3069 f32_ioctl.listlen = fioctl.listlen; 3070 f32_ioctl.list = (caddr32_t)(long)fioctl.list; 3071 if (ddi_copyout((void *)&f32_ioctl, (void *)data, 3072 sizeof (struct fcp32_ioctl), mode)) { 3073 return (EFAULT); 3074 } 3075 break; 3076 } 3077 case DDI_MODEL_NONE: 3078 if (ddi_copyout((void *)&fioctl, (void *)data, 3079 sizeof (struct fcp_ioctl), mode)) { 3080 return (EFAULT); 3081 } 3082 break; 3083 } 3084 #else /* _MULTI_DATAMODEL */ 3085 3086 if (ddi_copyout((void *)&fioctl, (void *)data, 3087 sizeof (struct fcp_ioctl), mode)) { 3088 return (EFAULT); 3089 } 3090 #endif /* _MULTI_DATAMODEL */ 3091 3092 return (0); 3093 } 3094 3095 /* 3096 * This function copies the fcp_ioctl structure passed in from user land 3097 * into kernel land. Handles 32 bit applications. 3098 */ 3099 /*ARGSUSED*/ 3100 static int 3101 fcp_copyin_fcp_ioctl_data(struct fcp_ioctl *data, int mode, int *rval, 3102 struct fcp_ioctl *fioctl, struct fcp_port **pptr) 3103 { 3104 struct fcp_port *t_pptr; 3105 3106 #ifdef _MULTI_DATAMODEL 3107 switch (ddi_model_convert_from(mode & FMODELS)) { 3108 case DDI_MODEL_ILP32: { 3109 struct fcp32_ioctl f32_ioctl; 3110 3111 if (ddi_copyin((void *)data, (void *)&f32_ioctl, 3112 sizeof (struct fcp32_ioctl), mode)) { 3113 return (EFAULT); 3114 } 3115 fioctl->fp_minor = f32_ioctl.fp_minor; 3116 fioctl->listlen = f32_ioctl.listlen; 3117 fioctl->list = (caddr_t)(long)f32_ioctl.list; 3118 break; 3119 } 3120 case DDI_MODEL_NONE: 3121 if (ddi_copyin((void *)data, (void *)fioctl, 3122 sizeof (struct fcp_ioctl), mode)) { 3123 return (EFAULT); 3124 } 3125 break; 3126 } 3127 3128 #else /* _MULTI_DATAMODEL */ 3129 if (ddi_copyin((void *)data, (void *)fioctl, 3130 sizeof (struct fcp_ioctl), mode)) { 3131 return (EFAULT); 3132 } 3133 #endif /* _MULTI_DATAMODEL */ 3134 3135 /* 3136 * Right now we can assume that the minor number matches with 3137 * this instance of fp. If this changes we will need to 3138 * revisit this logic. 3139 */ 3140 mutex_enter(&fcp_global_mutex); 3141 t_pptr = fcp_port_head; 3142 while (t_pptr) { 3143 if (t_pptr->port_instance == (uint32_t)fioctl->fp_minor) { 3144 break; 3145 } else { 3146 t_pptr = t_pptr->port_next; 3147 } 3148 } 3149 *pptr = t_pptr; 3150 mutex_exit(&fcp_global_mutex); 3151 if (t_pptr == NULL) { 3152 return (ENXIO); 3153 } 3154 3155 return (0); 3156 } 3157 3158 /* 3159 * Function: fcp_port_create_tgt 3160 * 3161 * Description: As the name suggest this function creates the target context 3162 * specified by the the WWN provided by the caller. If the 3163 * creation goes well and the target is known by fp/fctl a PLOGI 3164 * followed by a PRLI are issued. 3165 * 3166 * Argument: pptr fcp port structure 3167 * pwwn WWN of the target 3168 * ret_val Address of the return code. It could be: 3169 * EIO, ENOMEM or 0. 3170 * fc_status PLOGI or PRLI status completion 3171 * fc_pkt_state PLOGI or PRLI state completion 3172 * fc_pkt_reason PLOGI or PRLI reason completion 3173 * fc_pkt_action PLOGI or PRLI action completion 3174 * 3175 * Return Value: NULL if it failed 3176 * Target structure address if it succeeds 3177 */ 3178 static struct fcp_tgt * 3179 fcp_port_create_tgt(struct fcp_port *pptr, la_wwn_t *pwwn, int *ret_val, 3180 int *fc_status, int *fc_pkt_state, int *fc_pkt_reason, int *fc_pkt_action) 3181 { 3182 struct fcp_tgt *ptgt = NULL; 3183 fc_portmap_t devlist; 3184 int lcount; 3185 int error; 3186 3187 *ret_val = 0; 3188 3189 /* 3190 * Check FC port device & get port map 3191 */ 3192 if (fc_ulp_get_remote_port(pptr->port_fp_handle, pwwn, 3193 &error, 1) == NULL) { 3194 *ret_val = EIO; 3195 } else { 3196 if (fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, pwwn, 3197 &devlist) != FC_SUCCESS) { 3198 *ret_val = EIO; 3199 } 3200 } 3201 3202 /* Set port map flags */ 3203 devlist.map_type = PORT_DEVICE_USER_CREATE; 3204 3205 /* Allocate target */ 3206 if (*ret_val == 0) { 3207 lcount = pptr->port_link_cnt; 3208 ptgt = fcp_alloc_tgt(pptr, &devlist, lcount); 3209 if (ptgt == NULL) { 3210 fcp_log(CE_WARN, pptr->port_dip, 3211 "!FC target allocation failed"); 3212 *ret_val = ENOMEM; 3213 } else { 3214 /* Setup target */ 3215 mutex_enter(&ptgt->tgt_mutex); 3216 3217 ptgt->tgt_statec_cause = FCP_CAUSE_TGT_CHANGE; 3218 ptgt->tgt_tmp_cnt = 1; 3219 ptgt->tgt_d_id = devlist.map_did.port_id; 3220 ptgt->tgt_hard_addr = 3221 devlist.map_hard_addr.hard_addr; 3222 ptgt->tgt_pd_handle = devlist.map_pd; 3223 ptgt->tgt_fca_dev = NULL; 3224 3225 bcopy(&devlist.map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 3226 FC_WWN_SIZE); 3227 bcopy(&devlist.map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 3228 FC_WWN_SIZE); 3229 3230 mutex_exit(&ptgt->tgt_mutex); 3231 } 3232 } 3233 3234 /* Release global mutex for PLOGI and PRLI */ 3235 mutex_exit(&fcp_global_mutex); 3236 3237 /* Send PLOGI (If necessary) */ 3238 if (*ret_val == 0) { 3239 *ret_val = fcp_tgt_send_plogi(ptgt, fc_status, 3240 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3241 } 3242 3243 /* Send PRLI (If necessary) */ 3244 if (*ret_val == 0) { 3245 *ret_val = fcp_tgt_send_prli(ptgt, fc_status, 3246 fc_pkt_state, fc_pkt_reason, fc_pkt_action); 3247 } 3248 3249 mutex_enter(&fcp_global_mutex); 3250 3251 return (ptgt); 3252 } 3253 3254 /* 3255 * Function: fcp_tgt_send_plogi 3256 * 3257 * Description: This function sends a PLOGI to the target specified by the 3258 * caller and waits till it completes. 3259 * 3260 * Argument: ptgt Target to send the plogi to. 3261 * fc_status Status returned by fp/fctl in the PLOGI request. 3262 * fc_pkt_state State returned by fp/fctl in the PLOGI request. 3263 * fc_pkt_reason Reason returned by fp/fctl in the PLOGI request. 3264 * fc_pkt_action Action returned by fp/fctl in the PLOGI request. 3265 * 3266 * Return Value: 0 3267 * ENOMEM 3268 * EIO 3269 * 3270 * Context: User context. 3271 */ 3272 static int 3273 fcp_tgt_send_plogi(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3274 int *fc_pkt_reason, int *fc_pkt_action) 3275 { 3276 struct fcp_port *pptr; 3277 struct fcp_ipkt *icmd; 3278 struct fc_packet *fpkt; 3279 fc_frame_hdr_t *hp; 3280 struct la_els_logi logi; 3281 int tcount; 3282 int lcount; 3283 int ret, login_retval = ~FC_SUCCESS; 3284 3285 ret = 0; 3286 3287 pptr = ptgt->tgt_port; 3288 3289 lcount = pptr->port_link_cnt; 3290 tcount = ptgt->tgt_change_cnt; 3291 3292 /* Alloc internal packet */ 3293 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_logi_t), 3294 sizeof (la_els_logi_t), 0, 3295 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 3296 lcount, tcount, 0, FC_INVALID_RSCN_COUNT); 3297 3298 if (icmd == NULL) { 3299 ret = ENOMEM; 3300 } else { 3301 /* 3302 * Setup internal packet as sema sync 3303 */ 3304 fcp_ipkt_sema_init(icmd); 3305 3306 /* 3307 * Setup internal packet (icmd) 3308 */ 3309 icmd->ipkt_lun = NULL; 3310 icmd->ipkt_restart = 0; 3311 icmd->ipkt_retries = 0; 3312 icmd->ipkt_opcode = LA_ELS_PLOGI; 3313 3314 /* 3315 * Setup fc_packet 3316 */ 3317 fpkt = icmd->ipkt_fpkt; 3318 3319 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 3320 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 3321 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 3322 3323 /* 3324 * Setup FC frame header 3325 */ 3326 hp = &fpkt->pkt_cmd_fhdr; 3327 3328 hp->s_id = pptr->port_id; /* source ID */ 3329 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 3330 hp->r_ctl = R_CTL_ELS_REQ; 3331 hp->type = FC_TYPE_EXTENDED_LS; 3332 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 3333 hp->seq_id = 0; 3334 hp->rsvd = 0; 3335 hp->df_ctl = 0; 3336 hp->seq_cnt = 0; 3337 hp->ox_id = 0xffff; /* i.e. none */ 3338 hp->rx_id = 0xffff; /* i.e. none */ 3339 hp->ro = 0; 3340 3341 /* 3342 * Setup PLOGI 3343 */ 3344 bzero(&logi, sizeof (struct la_els_logi)); 3345 logi.ls_code.ls_code = LA_ELS_PLOGI; 3346 3347 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 3348 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 3349 3350 /* 3351 * Send PLOGI 3352 */ 3353 *fc_status = login_retval = 3354 fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 3355 if (*fc_status != FC_SUCCESS) { 3356 ret = EIO; 3357 } 3358 } 3359 3360 /* 3361 * Wait for completion 3362 */ 3363 if ((ret == 0) && (login_retval == FC_SUCCESS)) { 3364 ret = fcp_ipkt_sema_wait(icmd); 3365 3366 *fc_pkt_state = fpkt->pkt_state; 3367 *fc_pkt_reason = fpkt->pkt_reason; 3368 *fc_pkt_action = fpkt->pkt_action; 3369 } 3370 3371 /* 3372 * Cleanup transport data structures if icmd was alloc-ed AND if there 3373 * is going to be no callback (i.e if fc_ulp_login() failed). 3374 * Otherwise, cleanup happens in callback routine. 3375 */ 3376 if (icmd != NULL) { 3377 fcp_ipkt_sema_cleanup(icmd); 3378 } 3379 3380 return (ret); 3381 } 3382 3383 /* 3384 * Function: fcp_tgt_send_prli 3385 * 3386 * Description: Does nothing as of today. 3387 * 3388 * Argument: ptgt Target to send the prli to. 3389 * fc_status Status returned by fp/fctl in the PRLI request. 3390 * fc_pkt_state State returned by fp/fctl in the PRLI request. 3391 * fc_pkt_reason Reason returned by fp/fctl in the PRLI request. 3392 * fc_pkt_action Action returned by fp/fctl in the PRLI request. 3393 * 3394 * Return Value: 0 3395 */ 3396 /*ARGSUSED*/ 3397 static int 3398 fcp_tgt_send_prli(struct fcp_tgt *ptgt, int *fc_status, int *fc_pkt_state, 3399 int *fc_pkt_reason, int *fc_pkt_action) 3400 { 3401 return (0); 3402 } 3403 3404 /* 3405 * Function: fcp_ipkt_sema_init 3406 * 3407 * Description: Initializes the semaphore contained in the internal packet. 3408 * 3409 * Argument: icmd Internal packet the semaphore of which must be 3410 * initialized. 3411 * 3412 * Return Value: None 3413 * 3414 * Context: User context only. 3415 */ 3416 static void 3417 fcp_ipkt_sema_init(struct fcp_ipkt *icmd) 3418 { 3419 struct fc_packet *fpkt; 3420 3421 fpkt = icmd->ipkt_fpkt; 3422 3423 /* Create semaphore for sync */ 3424 sema_init(&(icmd->ipkt_sema), 0, NULL, SEMA_DRIVER, NULL); 3425 3426 /* Setup the completion callback */ 3427 fpkt->pkt_comp = fcp_ipkt_sema_callback; 3428 } 3429 3430 /* 3431 * Function: fcp_ipkt_sema_wait 3432 * 3433 * Description: Wait on the semaphore embedded in the internal packet. The 3434 * semaphore is released in the callback. 3435 * 3436 * Argument: icmd Internal packet to wait on for completion. 3437 * 3438 * Return Value: 0 3439 * EIO 3440 * EBUSY 3441 * EAGAIN 3442 * 3443 * Context: User context only. 3444 * 3445 * This function does a conversion between the field pkt_state of the fc_packet 3446 * embedded in the internal packet (icmd) and the code it returns. 3447 */ 3448 static int 3449 fcp_ipkt_sema_wait(struct fcp_ipkt *icmd) 3450 { 3451 struct fc_packet *fpkt; 3452 int ret; 3453 3454 ret = EIO; 3455 fpkt = icmd->ipkt_fpkt; 3456 3457 /* 3458 * Wait on semaphore 3459 */ 3460 sema_p(&(icmd->ipkt_sema)); 3461 3462 /* 3463 * Check the status of the FC packet 3464 */ 3465 switch (fpkt->pkt_state) { 3466 case FC_PKT_SUCCESS: 3467 ret = 0; 3468 break; 3469 case FC_PKT_LOCAL_RJT: 3470 switch (fpkt->pkt_reason) { 3471 case FC_REASON_SEQ_TIMEOUT: 3472 case FC_REASON_RX_BUF_TIMEOUT: 3473 ret = EAGAIN; 3474 break; 3475 case FC_REASON_PKT_BUSY: 3476 ret = EBUSY; 3477 break; 3478 } 3479 break; 3480 case FC_PKT_TIMEOUT: 3481 ret = EAGAIN; 3482 break; 3483 case FC_PKT_LOCAL_BSY: 3484 case FC_PKT_TRAN_BSY: 3485 case FC_PKT_NPORT_BSY: 3486 case FC_PKT_FABRIC_BSY: 3487 ret = EBUSY; 3488 break; 3489 case FC_PKT_LS_RJT: 3490 case FC_PKT_BA_RJT: 3491 switch (fpkt->pkt_reason) { 3492 case FC_REASON_LOGICAL_BSY: 3493 ret = EBUSY; 3494 break; 3495 } 3496 break; 3497 case FC_PKT_FS_RJT: 3498 switch (fpkt->pkt_reason) { 3499 case FC_REASON_FS_LOGICAL_BUSY: 3500 ret = EBUSY; 3501 break; 3502 } 3503 break; 3504 } 3505 3506 return (ret); 3507 } 3508 3509 /* 3510 * Function: fcp_ipkt_sema_callback 3511 * 3512 * Description: Registered as the completion callback function for the FC 3513 * transport when the ipkt semaphore is used for sync. This will 3514 * cleanup the used data structures, if necessary and wake up 3515 * the user thread to complete the transaction. 3516 * 3517 * Argument: fpkt FC packet (points to the icmd) 3518 * 3519 * Return Value: None 3520 * 3521 * Context: User context only 3522 */ 3523 static void 3524 fcp_ipkt_sema_callback(struct fc_packet *fpkt) 3525 { 3526 struct fcp_ipkt *icmd; 3527 3528 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 3529 3530 /* 3531 * Wake up user thread 3532 */ 3533 sema_v(&(icmd->ipkt_sema)); 3534 } 3535 3536 /* 3537 * Function: fcp_ipkt_sema_cleanup 3538 * 3539 * Description: Called to cleanup (if necessary) the data structures used 3540 * when ipkt sema is used for sync. This function will detect 3541 * whether the caller is the last thread (via counter) and 3542 * cleanup only if necessary. 3543 * 3544 * Argument: icmd Internal command packet 3545 * 3546 * Return Value: None 3547 * 3548 * Context: User context only 3549 */ 3550 static void 3551 fcp_ipkt_sema_cleanup(struct fcp_ipkt *icmd) 3552 { 3553 struct fcp_tgt *ptgt; 3554 struct fcp_port *pptr; 3555 3556 ptgt = icmd->ipkt_tgt; 3557 pptr = icmd->ipkt_port; 3558 3559 /* 3560 * Acquire data structure 3561 */ 3562 mutex_enter(&ptgt->tgt_mutex); 3563 3564 /* 3565 * Destroy semaphore 3566 */ 3567 sema_destroy(&(icmd->ipkt_sema)); 3568 3569 /* 3570 * Cleanup internal packet 3571 */ 3572 mutex_exit(&ptgt->tgt_mutex); 3573 fcp_icmd_free(pptr, icmd); 3574 } 3575 3576 /* 3577 * Function: fcp_port_attach 3578 * 3579 * Description: Called by the transport framework to resume, suspend or 3580 * attach a new port. 3581 * 3582 * Argument: ulph Port handle 3583 * *pinfo Port information 3584 * cmd Command 3585 * s_id Port ID 3586 * 3587 * Return Value: FC_FAILURE or FC_SUCCESS 3588 */ 3589 /*ARGSUSED*/ 3590 static int 3591 fcp_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 3592 fc_attach_cmd_t cmd, uint32_t s_id) 3593 { 3594 int instance; 3595 int res = FC_FAILURE; /* default result */ 3596 3597 ASSERT(pinfo != NULL); 3598 3599 instance = ddi_get_instance(pinfo->port_dip); 3600 3601 switch (cmd) { 3602 case FC_CMD_ATTACH: 3603 /* 3604 * this port instance attaching for the first time (or after 3605 * being detached before) 3606 */ 3607 if (fcp_handle_port_attach(ulph, pinfo, s_id, 3608 instance) == DDI_SUCCESS) { 3609 res = FC_SUCCESS; 3610 } else { 3611 ASSERT(ddi_get_soft_state(fcp_softstate, 3612 instance) == NULL); 3613 } 3614 break; 3615 3616 case FC_CMD_RESUME: 3617 case FC_CMD_POWER_UP: 3618 /* 3619 * this port instance was attached and the suspended and 3620 * will now be resumed 3621 */ 3622 if (fcp_handle_port_resume(ulph, pinfo, s_id, cmd, 3623 instance) == DDI_SUCCESS) { 3624 res = FC_SUCCESS; 3625 } 3626 break; 3627 3628 default: 3629 /* shouldn't happen */ 3630 FCP_TRACE(fcp_logq, "fcp", 3631 fcp_trace, FCP_BUF_LEVEL_2, 0, 3632 "port_attach: unknown cmdcommand: %d", cmd); 3633 break; 3634 } 3635 3636 /* return result */ 3637 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3638 FCP_BUF_LEVEL_1, 0, "fcp_port_attach returning %d", res); 3639 3640 return (res); 3641 } 3642 3643 3644 /* 3645 * detach or suspend this port instance 3646 * 3647 * acquires and releases the global mutex 3648 * 3649 * acquires and releases the mutex for this port 3650 * 3651 * acquires and releases the hotplug mutex for this port 3652 */ 3653 /*ARGSUSED*/ 3654 static int 3655 fcp_port_detach(opaque_t ulph, fc_ulp_port_info_t *info, 3656 fc_detach_cmd_t cmd) 3657 { 3658 int flag; 3659 int instance; 3660 struct fcp_port *pptr; 3661 3662 instance = ddi_get_instance(info->port_dip); 3663 pptr = ddi_get_soft_state(fcp_softstate, instance); 3664 3665 switch (cmd) { 3666 case FC_CMD_SUSPEND: 3667 FCP_DTRACE(fcp_logq, "fcp", 3668 fcp_trace, FCP_BUF_LEVEL_8, 0, 3669 "port suspend called for port %d", instance); 3670 flag = FCP_STATE_SUSPENDED; 3671 break; 3672 3673 case FC_CMD_POWER_DOWN: 3674 FCP_DTRACE(fcp_logq, "fcp", 3675 fcp_trace, FCP_BUF_LEVEL_8, 0, 3676 "port power down called for port %d", instance); 3677 flag = FCP_STATE_POWER_DOWN; 3678 break; 3679 3680 case FC_CMD_DETACH: 3681 FCP_DTRACE(fcp_logq, "fcp", 3682 fcp_trace, FCP_BUF_LEVEL_8, 0, 3683 "port detach called for port %d", instance); 3684 flag = FCP_STATE_DETACHING; 3685 break; 3686 3687 default: 3688 /* shouldn't happen */ 3689 return (FC_FAILURE); 3690 } 3691 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 3692 FCP_BUF_LEVEL_1, 0, "fcp_port_detach returning"); 3693 3694 return (fcp_handle_port_detach(pptr, flag, instance)); 3695 } 3696 3697 3698 /* 3699 * called for ioctls on the transport's devctl interface, and the transport 3700 * has passed it to us 3701 * 3702 * this will only be called for device control ioctls (i.e. hotplugging stuff) 3703 * 3704 * return FC_SUCCESS if we decide to claim the ioctl, 3705 * else return FC_UNCLAIMED 3706 * 3707 * *rval is set iff we decide to claim the ioctl 3708 */ 3709 /*ARGSUSED*/ 3710 static int 3711 fcp_port_ioctl(opaque_t ulph, opaque_t port_handle, dev_t dev, int cmd, 3712 intptr_t data, int mode, cred_t *credp, int *rval, uint32_t claimed) 3713 { 3714 int retval = FC_UNCLAIMED; /* return value */ 3715 struct fcp_port *pptr = NULL; /* our soft state */ 3716 struct devctl_iocdata *dcp = NULL; /* for devctl */ 3717 dev_info_t *cdip; 3718 mdi_pathinfo_t *pip = NULL; 3719 char *ndi_nm; /* NDI name */ 3720 char *ndi_addr; /* NDI addr */ 3721 int is_mpxio, circ; 3722 int devi_entered = 0; 3723 clock_t end_time; 3724 3725 ASSERT(rval != NULL); 3726 3727 FCP_DTRACE(fcp_logq, "fcp", 3728 fcp_trace, FCP_BUF_LEVEL_8, 0, 3729 "fcp_port_ioctl(cmd=0x%x, claimed=%d)", cmd, claimed); 3730 3731 /* if already claimed then forget it */ 3732 if (claimed) { 3733 /* 3734 * for now, if this ioctl has already been claimed, then 3735 * we just ignore it 3736 */ 3737 return (retval); 3738 } 3739 3740 /* get our port info */ 3741 if ((pptr = fcp_get_port(port_handle)) == NULL) { 3742 fcp_log(CE_WARN, NULL, 3743 "!fcp:Invalid port handle handle in ioctl"); 3744 *rval = ENXIO; 3745 return (retval); 3746 } 3747 is_mpxio = pptr->port_mpxio; 3748 3749 switch (cmd) { 3750 case DEVCTL_BUS_GETSTATE: 3751 case DEVCTL_BUS_QUIESCE: 3752 case DEVCTL_BUS_UNQUIESCE: 3753 case DEVCTL_BUS_RESET: 3754 case DEVCTL_BUS_RESETALL: 3755 3756 case DEVCTL_BUS_DEV_CREATE: 3757 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3758 return (retval); 3759 } 3760 break; 3761 3762 case DEVCTL_DEVICE_GETSTATE: 3763 case DEVCTL_DEVICE_OFFLINE: 3764 case DEVCTL_DEVICE_ONLINE: 3765 case DEVCTL_DEVICE_REMOVE: 3766 case DEVCTL_DEVICE_RESET: 3767 if (ndi_dc_allochdl((void *)data, &dcp) != NDI_SUCCESS) { 3768 return (retval); 3769 } 3770 3771 ASSERT(dcp != NULL); 3772 3773 /* ensure we have a name and address */ 3774 if (((ndi_nm = ndi_dc_getname(dcp)) == NULL) || 3775 ((ndi_addr = ndi_dc_getaddr(dcp)) == NULL)) { 3776 FCP_TRACE(fcp_logq, pptr->port_instbuf, 3777 fcp_trace, FCP_BUF_LEVEL_2, 0, 3778 "ioctl: can't get name (%s) or addr (%s)", 3779 ndi_nm ? ndi_nm : "<null ptr>", 3780 ndi_addr ? ndi_addr : "<null ptr>"); 3781 ndi_dc_freehdl(dcp); 3782 return (retval); 3783 } 3784 3785 3786 /* get our child's DIP */ 3787 ASSERT(pptr != NULL); 3788 if (is_mpxio) { 3789 mdi_devi_enter(pptr->port_dip, &circ); 3790 } else { 3791 ndi_devi_enter(pptr->port_dip, &circ); 3792 } 3793 devi_entered = 1; 3794 3795 if ((cdip = ndi_devi_find(pptr->port_dip, ndi_nm, 3796 ndi_addr)) == NULL) { 3797 /* Look for virtually enumerated devices. */ 3798 pip = mdi_pi_find(pptr->port_dip, NULL, ndi_addr); 3799 if (pip == NULL || 3800 ((cdip = mdi_pi_get_client(pip)) == NULL)) { 3801 *rval = ENXIO; 3802 goto out; 3803 } 3804 } 3805 break; 3806 3807 default: 3808 *rval = ENOTTY; 3809 return (retval); 3810 } 3811 3812 /* this ioctl is ours -- process it */ 3813 3814 retval = FC_SUCCESS; /* just means we claim the ioctl */ 3815 3816 /* we assume it will be a success; else we'll set error value */ 3817 *rval = 0; 3818 3819 3820 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 3821 fcp_trace, FCP_BUF_LEVEL_8, 0, 3822 "ioctl: claiming this one"); 3823 3824 /* handle ioctls now */ 3825 switch (cmd) { 3826 case DEVCTL_DEVICE_GETSTATE: 3827 ASSERT(cdip != NULL); 3828 ASSERT(dcp != NULL); 3829 if (ndi_dc_return_dev_state(cdip, dcp) != NDI_SUCCESS) { 3830 *rval = EFAULT; 3831 } 3832 break; 3833 3834 case DEVCTL_DEVICE_REMOVE: 3835 case DEVCTL_DEVICE_OFFLINE: { 3836 int flag = 0; 3837 int lcount; 3838 int tcount; 3839 struct fcp_pkt *head = NULL; 3840 struct fcp_lun *plun; 3841 child_info_t *cip = CIP(cdip); 3842 int all = 1; 3843 struct fcp_lun *tplun; 3844 struct fcp_tgt *ptgt; 3845 3846 ASSERT(pptr != NULL); 3847 ASSERT(cdip != NULL); 3848 3849 mutex_enter(&pptr->port_mutex); 3850 if (pip != NULL) { 3851 cip = CIP(pip); 3852 } 3853 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3854 mutex_exit(&pptr->port_mutex); 3855 *rval = ENXIO; 3856 break; 3857 } 3858 3859 head = fcp_scan_commands(plun); 3860 if (head != NULL) { 3861 fcp_abort_commands(head, LUN_PORT); 3862 } 3863 lcount = pptr->port_link_cnt; 3864 tcount = plun->lun_tgt->tgt_change_cnt; 3865 mutex_exit(&pptr->port_mutex); 3866 3867 if (cmd == DEVCTL_DEVICE_REMOVE) { 3868 flag = NDI_DEVI_REMOVE; 3869 } 3870 3871 if (is_mpxio) { 3872 mdi_devi_exit(pptr->port_dip, circ); 3873 } else { 3874 ndi_devi_exit(pptr->port_dip, circ); 3875 } 3876 devi_entered = 0; 3877 3878 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3879 FCP_OFFLINE, lcount, tcount, flag); 3880 3881 if (*rval != NDI_SUCCESS) { 3882 *rval = (*rval == NDI_BUSY) ? EBUSY : EIO; 3883 break; 3884 } 3885 3886 fcp_update_offline_flags(plun); 3887 3888 ptgt = plun->lun_tgt; 3889 mutex_enter(&ptgt->tgt_mutex); 3890 for (tplun = ptgt->tgt_lun; tplun != NULL; tplun = 3891 tplun->lun_next) { 3892 mutex_enter(&tplun->lun_mutex); 3893 if (!(tplun->lun_state & FCP_LUN_OFFLINE)) { 3894 all = 0; 3895 } 3896 mutex_exit(&tplun->lun_mutex); 3897 } 3898 3899 if (all) { 3900 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 3901 /* 3902 * The user is unconfiguring/offlining the device. 3903 * If fabric and the auto configuration is set 3904 * then make sure the user is the only one who 3905 * can reconfigure the device. 3906 */ 3907 if (FC_TOP_EXTERNAL(pptr->port_topology) && 3908 fcp_enable_auto_configuration) { 3909 ptgt->tgt_manual_config_only = 1; 3910 } 3911 } 3912 mutex_exit(&ptgt->tgt_mutex); 3913 break; 3914 } 3915 3916 case DEVCTL_DEVICE_ONLINE: { 3917 int lcount; 3918 int tcount; 3919 struct fcp_lun *plun; 3920 child_info_t *cip = CIP(cdip); 3921 3922 ASSERT(cdip != NULL); 3923 ASSERT(pptr != NULL); 3924 3925 mutex_enter(&pptr->port_mutex); 3926 if (pip != NULL) { 3927 cip = CIP(pip); 3928 } 3929 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 3930 mutex_exit(&pptr->port_mutex); 3931 *rval = ENXIO; 3932 break; 3933 } 3934 lcount = pptr->port_link_cnt; 3935 tcount = plun->lun_tgt->tgt_change_cnt; 3936 mutex_exit(&pptr->port_mutex); 3937 3938 /* 3939 * The FCP_LUN_ONLINING flag is used in fcp_scsi_start() 3940 * to allow the device attach to occur when the device is 3941 * FCP_LUN_OFFLINE (so we don't reject the INQUIRY command 3942 * from the scsi_probe()). 3943 */ 3944 mutex_enter(&LUN_TGT->tgt_mutex); 3945 plun->lun_state |= FCP_LUN_ONLINING; 3946 mutex_exit(&LUN_TGT->tgt_mutex); 3947 3948 if (is_mpxio) { 3949 mdi_devi_exit(pptr->port_dip, circ); 3950 } else { 3951 ndi_devi_exit(pptr->port_dip, circ); 3952 } 3953 devi_entered = 0; 3954 3955 *rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 3956 FCP_ONLINE, lcount, tcount, 0); 3957 3958 if (*rval != NDI_SUCCESS) { 3959 /* Reset the FCP_LUN_ONLINING bit */ 3960 mutex_enter(&LUN_TGT->tgt_mutex); 3961 plun->lun_state &= ~FCP_LUN_ONLINING; 3962 mutex_exit(&LUN_TGT->tgt_mutex); 3963 *rval = EIO; 3964 break; 3965 } 3966 mutex_enter(&LUN_TGT->tgt_mutex); 3967 plun->lun_state &= ~(FCP_LUN_OFFLINE | FCP_LUN_BUSY | 3968 FCP_LUN_ONLINING); 3969 mutex_exit(&LUN_TGT->tgt_mutex); 3970 break; 3971 } 3972 3973 case DEVCTL_BUS_DEV_CREATE: { 3974 uchar_t *bytes = NULL; 3975 uint_t nbytes; 3976 struct fcp_tgt *ptgt = NULL; 3977 struct fcp_lun *plun = NULL; 3978 dev_info_t *useless_dip = NULL; 3979 3980 *rval = ndi_dc_devi_create(dcp, pptr->port_dip, 3981 DEVCTL_CONSTRUCT, &useless_dip); 3982 if (*rval != 0 || useless_dip == NULL) { 3983 break; 3984 } 3985 3986 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, useless_dip, 3987 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 3988 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 3989 *rval = EINVAL; 3990 (void) ndi_devi_free(useless_dip); 3991 if (bytes != NULL) { 3992 ddi_prop_free(bytes); 3993 } 3994 break; 3995 } 3996 3997 *rval = fcp_create_on_demand(pptr, bytes); 3998 if (*rval == 0) { 3999 mutex_enter(&pptr->port_mutex); 4000 ptgt = fcp_lookup_target(pptr, (uchar_t *)bytes); 4001 if (ptgt) { 4002 /* 4003 * We now have a pointer to the target that 4004 * was created. Lets point to the first LUN on 4005 * this new target. 4006 */ 4007 mutex_enter(&ptgt->tgt_mutex); 4008 4009 plun = ptgt->tgt_lun; 4010 /* 4011 * There may be stale/offline LUN entries on 4012 * this list (this is by design) and so we have 4013 * to make sure we point to the first online 4014 * LUN 4015 */ 4016 while (plun && 4017 plun->lun_state & FCP_LUN_OFFLINE) { 4018 plun = plun->lun_next; 4019 } 4020 4021 mutex_exit(&ptgt->tgt_mutex); 4022 } 4023 mutex_exit(&pptr->port_mutex); 4024 } 4025 4026 if (*rval == 0 && ptgt && plun) { 4027 mutex_enter(&plun->lun_mutex); 4028 /* 4029 * Allow up to fcp_lun_ready_retry seconds to 4030 * configure all the luns behind the target. 4031 * 4032 * The intent here is to allow targets with long 4033 * reboot/reset-recovery times to become available 4034 * while limiting the maximum wait time for an 4035 * unresponsive target. 4036 */ 4037 end_time = ddi_get_lbolt() + 4038 SEC_TO_TICK(fcp_lun_ready_retry); 4039 4040 while (ddi_get_lbolt() < end_time) { 4041 retval = FC_SUCCESS; 4042 4043 /* 4044 * The new ndi interfaces for on-demand creation 4045 * are inflexible, Do some more work to pass on 4046 * a path name of some LUN (design is broken !) 4047 */ 4048 if (plun->lun_cip) { 4049 if (plun->lun_mpxio == 0) { 4050 cdip = DIP(plun->lun_cip); 4051 } else { 4052 cdip = mdi_pi_get_client( 4053 PIP(plun->lun_cip)); 4054 } 4055 if (cdip == NULL) { 4056 *rval = ENXIO; 4057 break; 4058 } 4059 4060 if (!i_ddi_devi_attached(cdip)) { 4061 mutex_exit(&plun->lun_mutex); 4062 delay(drv_sectohz(1)); 4063 mutex_enter(&plun->lun_mutex); 4064 } else { 4065 /* 4066 * This Lun is ready, lets 4067 * check the next one. 4068 */ 4069 mutex_exit(&plun->lun_mutex); 4070 plun = plun->lun_next; 4071 while (plun && (plun->lun_state 4072 & FCP_LUN_OFFLINE)) { 4073 plun = plun->lun_next; 4074 } 4075 if (!plun) { 4076 break; 4077 } 4078 mutex_enter(&plun->lun_mutex); 4079 } 4080 } else { 4081 /* 4082 * lun_cip field for a valid lun 4083 * should never be NULL. Fail the 4084 * command. 4085 */ 4086 *rval = ENXIO; 4087 break; 4088 } 4089 } 4090 if (plun) { 4091 mutex_exit(&plun->lun_mutex); 4092 } else { 4093 char devnm[MAXNAMELEN]; 4094 int nmlen; 4095 4096 nmlen = snprintf(devnm, MAXNAMELEN, "%s@%s", 4097 ddi_node_name(cdip), 4098 ddi_get_name_addr(cdip)); 4099 4100 if (copyout(&devnm, dcp->cpyout_buf, nmlen) != 4101 0) { 4102 *rval = EFAULT; 4103 } 4104 } 4105 } else { 4106 int i; 4107 char buf[25]; 4108 4109 for (i = 0; i < FC_WWN_SIZE; i++) { 4110 (void) sprintf(&buf[i << 1], "%02x", bytes[i]); 4111 } 4112 4113 fcp_log(CE_WARN, pptr->port_dip, 4114 "!Failed to create nodes for pwwn=%s; error=%x", 4115 buf, *rval); 4116 } 4117 4118 (void) ndi_devi_free(useless_dip); 4119 ddi_prop_free(bytes); 4120 break; 4121 } 4122 4123 case DEVCTL_DEVICE_RESET: { 4124 struct fcp_lun *plun; 4125 child_info_t *cip = CIP(cdip); 4126 4127 ASSERT(cdip != NULL); 4128 ASSERT(pptr != NULL); 4129 mutex_enter(&pptr->port_mutex); 4130 if (pip != NULL) { 4131 cip = CIP(pip); 4132 } 4133 if ((plun = fcp_get_lun_from_cip(pptr, cip)) == NULL) { 4134 mutex_exit(&pptr->port_mutex); 4135 *rval = ENXIO; 4136 break; 4137 } 4138 mutex_exit(&pptr->port_mutex); 4139 4140 mutex_enter(&plun->lun_tgt->tgt_mutex); 4141 if (!(plun->lun_state & FCP_SCSI_LUN_TGT_INIT)) { 4142 mutex_exit(&plun->lun_tgt->tgt_mutex); 4143 4144 *rval = ENXIO; 4145 break; 4146 } 4147 4148 if (plun->lun_sd == NULL) { 4149 mutex_exit(&plun->lun_tgt->tgt_mutex); 4150 4151 *rval = ENXIO; 4152 break; 4153 } 4154 mutex_exit(&plun->lun_tgt->tgt_mutex); 4155 4156 /* 4157 * set up ap so that fcp_reset can figure out 4158 * which target to reset 4159 */ 4160 if (fcp_scsi_reset(&plun->lun_sd->sd_address, 4161 RESET_TARGET) == FALSE) { 4162 *rval = EIO; 4163 } 4164 break; 4165 } 4166 4167 case DEVCTL_BUS_GETSTATE: 4168 ASSERT(dcp != NULL); 4169 ASSERT(pptr != NULL); 4170 ASSERT(pptr->port_dip != NULL); 4171 if (ndi_dc_return_bus_state(pptr->port_dip, dcp) != 4172 NDI_SUCCESS) { 4173 *rval = EFAULT; 4174 } 4175 break; 4176 4177 case DEVCTL_BUS_QUIESCE: 4178 case DEVCTL_BUS_UNQUIESCE: 4179 *rval = ENOTSUP; 4180 break; 4181 4182 case DEVCTL_BUS_RESET: 4183 case DEVCTL_BUS_RESETALL: 4184 ASSERT(pptr != NULL); 4185 (void) fcp_linkreset(pptr, NULL, KM_SLEEP); 4186 break; 4187 4188 default: 4189 ASSERT(dcp != NULL); 4190 *rval = ENOTTY; 4191 break; 4192 } 4193 4194 /* all done -- clean up and return */ 4195 out: if (devi_entered) { 4196 if (is_mpxio) { 4197 mdi_devi_exit(pptr->port_dip, circ); 4198 } else { 4199 ndi_devi_exit(pptr->port_dip, circ); 4200 } 4201 } 4202 4203 if (dcp != NULL) { 4204 ndi_dc_freehdl(dcp); 4205 } 4206 4207 return (retval); 4208 } 4209 4210 4211 /*ARGSUSED*/ 4212 static int 4213 fcp_els_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4214 uint32_t claimed) 4215 { 4216 uchar_t r_ctl; 4217 uchar_t ls_code; 4218 struct fcp_port *pptr; 4219 4220 if ((pptr = fcp_get_port(port_handle)) == NULL || claimed) { 4221 return (FC_UNCLAIMED); 4222 } 4223 4224 mutex_enter(&pptr->port_mutex); 4225 if (pptr->port_state & (FCP_STATE_DETACHING | 4226 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4227 mutex_exit(&pptr->port_mutex); 4228 return (FC_UNCLAIMED); 4229 } 4230 mutex_exit(&pptr->port_mutex); 4231 4232 r_ctl = buf->ub_frame.r_ctl; 4233 4234 switch (r_ctl & R_CTL_ROUTING) { 4235 case R_CTL_EXTENDED_SVC: 4236 if (r_ctl == R_CTL_ELS_REQ) { 4237 ls_code = buf->ub_buffer[0]; 4238 4239 switch (ls_code) { 4240 case LA_ELS_PRLI: 4241 /* 4242 * We really don't care if something fails. 4243 * If the PRLI was not sent out, then the 4244 * other end will time it out. 4245 */ 4246 if (fcp_unsol_prli(pptr, buf) == FC_SUCCESS) { 4247 return (FC_SUCCESS); 4248 } 4249 return (FC_UNCLAIMED); 4250 /* NOTREACHED */ 4251 4252 default: 4253 break; 4254 } 4255 } 4256 /* FALLTHROUGH */ 4257 4258 default: 4259 return (FC_UNCLAIMED); 4260 } 4261 } 4262 4263 4264 /*ARGSUSED*/ 4265 static int 4266 fcp_data_callback(opaque_t ulph, opaque_t port_handle, fc_unsol_buf_t *buf, 4267 uint32_t claimed) 4268 { 4269 return (FC_UNCLAIMED); 4270 } 4271 4272 /* 4273 * Function: fcp_statec_callback 4274 * 4275 * Description: The purpose of this function is to handle a port state change. 4276 * It is called from fp/fctl and, in a few instances, internally. 4277 * 4278 * Argument: ulph fp/fctl port handle 4279 * port_handle fcp_port structure 4280 * port_state Physical state of the port 4281 * port_top Topology 4282 * *devlist Pointer to the first entry of a table 4283 * containing the remote ports that can be 4284 * reached. 4285 * dev_cnt Number of entries pointed by devlist. 4286 * port_sid Port ID of the local port. 4287 * 4288 * Return Value: None 4289 */ 4290 /*ARGSUSED*/ 4291 static void 4292 fcp_statec_callback(opaque_t ulph, opaque_t port_handle, 4293 uint32_t port_state, uint32_t port_top, fc_portmap_t *devlist, 4294 uint32_t dev_cnt, uint32_t port_sid) 4295 { 4296 uint32_t link_count; 4297 int map_len = 0; 4298 struct fcp_port *pptr; 4299 fcp_map_tag_t *map_tag = NULL; 4300 4301 if ((pptr = fcp_get_port(port_handle)) == NULL) { 4302 fcp_log(CE_WARN, NULL, "!Invalid port handle in callback"); 4303 return; /* nothing to work with! */ 4304 } 4305 4306 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4307 fcp_trace, FCP_BUF_LEVEL_2, 0, 4308 "fcp_statec_callback: port state/dev_cnt/top =" 4309 "%d/%d/%d", FC_PORT_STATE_MASK(port_state), 4310 dev_cnt, port_top); 4311 4312 mutex_enter(&pptr->port_mutex); 4313 4314 /* 4315 * If a thread is in detach, don't do anything. 4316 */ 4317 if (pptr->port_state & (FCP_STATE_DETACHING | 4318 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 4319 mutex_exit(&pptr->port_mutex); 4320 return; 4321 } 4322 4323 /* 4324 * First thing we do is set the FCP_STATE_IN_CB_DEVC flag so that if 4325 * init_pkt is called, it knows whether or not the target's status 4326 * (or pd) might be changing. 4327 */ 4328 4329 if (FC_PORT_STATE_MASK(port_state) == FC_STATE_DEVICE_CHANGE) { 4330 pptr->port_state |= FCP_STATE_IN_CB_DEVC; 4331 } 4332 4333 /* 4334 * the transport doesn't allocate or probe unless being 4335 * asked to by either the applications or ULPs 4336 * 4337 * in cases where the port is OFFLINE at the time of port 4338 * attach callback and the link comes ONLINE later, for 4339 * easier automatic node creation (i.e. without you having to 4340 * go out and run the utility to perform LOGINs) the 4341 * following conditional is helpful 4342 */ 4343 pptr->port_phys_state = port_state; 4344 4345 if (dev_cnt) { 4346 mutex_exit(&pptr->port_mutex); 4347 4348 map_len = sizeof (*map_tag) * dev_cnt; 4349 map_tag = kmem_alloc(map_len, KM_NOSLEEP); 4350 if (map_tag == NULL) { 4351 fcp_log(CE_WARN, pptr->port_dip, 4352 "!fcp%d: failed to allocate for map tags; " 4353 " state change will not be processed", 4354 pptr->port_instance); 4355 4356 mutex_enter(&pptr->port_mutex); 4357 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4358 mutex_exit(&pptr->port_mutex); 4359 4360 return; 4361 } 4362 4363 mutex_enter(&pptr->port_mutex); 4364 } 4365 4366 if (pptr->port_id != port_sid) { 4367 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4368 fcp_trace, FCP_BUF_LEVEL_3, 0, 4369 "fcp: Port S_ID=0x%x => 0x%x", pptr->port_id, 4370 port_sid); 4371 /* 4372 * The local port changed ID. It is the first time a port ID 4373 * is assigned or something drastic happened. We might have 4374 * been unplugged and replugged on another loop or fabric port 4375 * or somebody grabbed the AL_PA we had or somebody rezoned 4376 * the fabric we were plugged into. 4377 */ 4378 pptr->port_id = port_sid; 4379 } 4380 4381 switch (FC_PORT_STATE_MASK(port_state)) { 4382 case FC_STATE_OFFLINE: 4383 case FC_STATE_RESET_REQUESTED: 4384 /* 4385 * link has gone from online to offline -- just update the 4386 * state of this port to BUSY and MARKed to go offline 4387 */ 4388 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4389 fcp_trace, FCP_BUF_LEVEL_3, 0, 4390 "link went offline"); 4391 if ((pptr->port_state & FCP_STATE_OFFLINE) && dev_cnt) { 4392 /* 4393 * We were offline a while ago and this one 4394 * seems to indicate that the loop has gone 4395 * dead forever. 4396 */ 4397 pptr->port_tmp_cnt += dev_cnt; 4398 pptr->port_state &= ~FCP_STATE_OFFLINE; 4399 pptr->port_state |= FCP_STATE_INIT; 4400 link_count = pptr->port_link_cnt; 4401 fcp_handle_devices(pptr, devlist, dev_cnt, 4402 link_count, map_tag, FCP_CAUSE_LINK_DOWN); 4403 } else { 4404 pptr->port_link_cnt++; 4405 ASSERT(!(pptr->port_state & FCP_STATE_SUSPENDED)); 4406 fcp_update_state(pptr, (FCP_LUN_BUSY | 4407 FCP_LUN_MARK), FCP_CAUSE_LINK_DOWN); 4408 if (pptr->port_mpxio) { 4409 fcp_update_mpxio_path_verifybusy(pptr); 4410 } 4411 pptr->port_state |= FCP_STATE_OFFLINE; 4412 pptr->port_state &= 4413 ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 4414 pptr->port_tmp_cnt = 0; 4415 } 4416 mutex_exit(&pptr->port_mutex); 4417 break; 4418 4419 case FC_STATE_ONLINE: 4420 case FC_STATE_LIP: 4421 case FC_STATE_LIP_LBIT_SET: 4422 /* 4423 * link has gone from offline to online 4424 */ 4425 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4426 fcp_trace, FCP_BUF_LEVEL_3, 0, 4427 "link went online"); 4428 4429 pptr->port_link_cnt++; 4430 4431 while (pptr->port_ipkt_cnt) { 4432 mutex_exit(&pptr->port_mutex); 4433 delay(drv_sectohz(1)); 4434 mutex_enter(&pptr->port_mutex); 4435 } 4436 4437 pptr->port_topology = port_top; 4438 4439 /* 4440 * The state of the targets and luns accessible through this 4441 * port is updated. 4442 */ 4443 fcp_update_state(pptr, FCP_LUN_BUSY | FCP_LUN_MARK, 4444 FCP_CAUSE_LINK_CHANGE); 4445 4446 pptr->port_state &= ~(FCP_STATE_INIT | FCP_STATE_OFFLINE); 4447 pptr->port_state |= FCP_STATE_ONLINING; 4448 pptr->port_tmp_cnt = dev_cnt; 4449 link_count = pptr->port_link_cnt; 4450 4451 pptr->port_deadline = fcp_watchdog_time + 4452 FCP_ICMD_DEADLINE; 4453 4454 if (!dev_cnt) { 4455 /* 4456 * We go directly to the online state if no remote 4457 * ports were discovered. 4458 */ 4459 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4460 fcp_trace, FCP_BUF_LEVEL_3, 0, 4461 "No remote ports discovered"); 4462 4463 pptr->port_state &= ~FCP_STATE_ONLINING; 4464 pptr->port_state |= FCP_STATE_ONLINE; 4465 } 4466 4467 switch (port_top) { 4468 case FC_TOP_FABRIC: 4469 case FC_TOP_PUBLIC_LOOP: 4470 case FC_TOP_PRIVATE_LOOP: 4471 case FC_TOP_PT_PT: 4472 4473 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4474 fcp_retry_ns_registry(pptr, port_sid); 4475 } 4476 4477 fcp_handle_devices(pptr, devlist, dev_cnt, link_count, 4478 map_tag, FCP_CAUSE_LINK_CHANGE); 4479 break; 4480 4481 default: 4482 /* 4483 * We got here because we were provided with an unknown 4484 * topology. 4485 */ 4486 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4487 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 4488 } 4489 4490 pptr->port_tmp_cnt -= dev_cnt; 4491 fcp_log(CE_WARN, pptr->port_dip, 4492 "!unknown/unsupported topology (0x%x)", port_top); 4493 break; 4494 } 4495 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4496 fcp_trace, FCP_BUF_LEVEL_3, 0, 4497 "Notify ssd of the reset to reinstate the reservations"); 4498 4499 scsi_hba_reset_notify_callback(&pptr->port_mutex, 4500 &pptr->port_reset_notify_listf); 4501 4502 mutex_exit(&pptr->port_mutex); 4503 4504 break; 4505 4506 case FC_STATE_RESET: 4507 ASSERT(pptr->port_state & FCP_STATE_OFFLINE); 4508 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4509 fcp_trace, FCP_BUF_LEVEL_3, 0, 4510 "RESET state, waiting for Offline/Online state_cb"); 4511 mutex_exit(&pptr->port_mutex); 4512 break; 4513 4514 case FC_STATE_DEVICE_CHANGE: 4515 /* 4516 * We come here when an application has requested 4517 * Dynamic node creation/deletion in Fabric connectivity. 4518 */ 4519 if (pptr->port_state & (FCP_STATE_OFFLINE | 4520 FCP_STATE_INIT)) { 4521 /* 4522 * This case can happen when the FCTL is in the 4523 * process of giving us on online and the host on 4524 * the other side issues a PLOGI/PLOGO. Ideally 4525 * the state changes should be serialized unless 4526 * they are opposite (online-offline). 4527 * The transport will give us a final state change 4528 * so we can ignore this for the time being. 4529 */ 4530 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4531 mutex_exit(&pptr->port_mutex); 4532 break; 4533 } 4534 4535 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4536 fcp_retry_ns_registry(pptr, port_sid); 4537 } 4538 4539 /* 4540 * Extend the deadline under steady state conditions 4541 * to provide more time for the device-change-commands 4542 */ 4543 if (!pptr->port_ipkt_cnt) { 4544 pptr->port_deadline = fcp_watchdog_time + 4545 FCP_ICMD_DEADLINE; 4546 } 4547 4548 /* 4549 * There is another race condition here, where if we were 4550 * in ONLINEING state and a devices in the map logs out, 4551 * fp will give another state change as DEVICE_CHANGE 4552 * and OLD. This will result in that target being offlined. 4553 * The pd_handle is freed. If from the first statec callback 4554 * we were going to fire a PLOGI/PRLI, the system will 4555 * panic in fc_ulp_transport with invalid pd_handle. 4556 * The fix is to check for the link_cnt before issuing 4557 * any command down. 4558 */ 4559 fcp_update_targets(pptr, devlist, dev_cnt, 4560 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_TGT_CHANGE); 4561 4562 link_count = pptr->port_link_cnt; 4563 4564 fcp_handle_devices(pptr, devlist, dev_cnt, 4565 link_count, map_tag, FCP_CAUSE_TGT_CHANGE); 4566 4567 pptr->port_state &= ~FCP_STATE_IN_CB_DEVC; 4568 4569 mutex_exit(&pptr->port_mutex); 4570 break; 4571 4572 case FC_STATE_TARGET_PORT_RESET: 4573 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 4574 fcp_retry_ns_registry(pptr, port_sid); 4575 } 4576 4577 /* Do nothing else */ 4578 mutex_exit(&pptr->port_mutex); 4579 break; 4580 4581 default: 4582 fcp_log(CE_WARN, pptr->port_dip, 4583 "!Invalid state change=0x%x", port_state); 4584 mutex_exit(&pptr->port_mutex); 4585 break; 4586 } 4587 4588 if (map_tag) { 4589 kmem_free(map_tag, map_len); 4590 } 4591 } 4592 4593 /* 4594 * Function: fcp_handle_devices 4595 * 4596 * Description: This function updates the devices currently known by 4597 * walking the list provided by the caller. The list passed 4598 * by the caller is supposed to be the list of reachable 4599 * devices. 4600 * 4601 * Argument: *pptr Fcp port structure. 4602 * *devlist Pointer to the first entry of a table 4603 * containing the remote ports that can be 4604 * reached. 4605 * dev_cnt Number of entries pointed by devlist. 4606 * link_cnt Link state count. 4607 * *map_tag Array of fcp_map_tag_t structures. 4608 * cause What caused this function to be called. 4609 * 4610 * Return Value: None 4611 * 4612 * Notes: The pptr->port_mutex must be held. 4613 */ 4614 static void 4615 fcp_handle_devices(struct fcp_port *pptr, fc_portmap_t devlist[], 4616 uint32_t dev_cnt, int link_cnt, fcp_map_tag_t *map_tag, int cause) 4617 { 4618 int i; 4619 int check_finish_init = 0; 4620 fc_portmap_t *map_entry; 4621 struct fcp_tgt *ptgt = NULL; 4622 4623 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4624 fcp_trace, FCP_BUF_LEVEL_3, 0, 4625 "fcp_handle_devices: called for %d dev(s)", dev_cnt); 4626 4627 if (dev_cnt) { 4628 ASSERT(map_tag != NULL); 4629 } 4630 4631 /* 4632 * The following code goes through the list of remote ports that are 4633 * accessible through this (pptr) local port (The list walked is the 4634 * one provided by the caller which is the list of the remote ports 4635 * currently reachable). It checks if any of them was already 4636 * known by looking for the corresponding target structure based on 4637 * the world wide name. If a target is part of the list it is tagged 4638 * (ptgt->tgt_aux_state = FCP_TGT_TAGGED). 4639 * 4640 * Old comment 4641 * ----------- 4642 * Before we drop port mutex; we MUST get the tags updated; This 4643 * two step process is somewhat slow, but more reliable. 4644 */ 4645 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4646 map_entry = &(devlist[i]); 4647 4648 /* 4649 * get ptr to this map entry in our port's 4650 * list (if any) 4651 */ 4652 ptgt = fcp_lookup_target(pptr, 4653 (uchar_t *)&(map_entry->map_pwwn)); 4654 4655 if (ptgt) { 4656 map_tag[i] = ptgt->tgt_change_cnt; 4657 if (cause == FCP_CAUSE_LINK_CHANGE) { 4658 ptgt->tgt_aux_state = FCP_TGT_TAGGED; 4659 } 4660 } 4661 } 4662 4663 /* 4664 * At this point we know which devices of the new list were already 4665 * known (The field tgt_aux_state of the target structure has been 4666 * set to FCP_TGT_TAGGED). 4667 * 4668 * The following code goes through the list of targets currently known 4669 * by the local port (the list is actually a hashing table). If a 4670 * target is found and is not tagged, it means the target cannot 4671 * be reached anymore through the local port (pptr). It is offlined. 4672 * The offlining only occurs if the cause is FCP_CAUSE_LINK_CHANGE. 4673 */ 4674 for (i = 0; i < FCP_NUM_HASH; i++) { 4675 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 4676 ptgt = ptgt->tgt_next) { 4677 mutex_enter(&ptgt->tgt_mutex); 4678 if ((ptgt->tgt_aux_state != FCP_TGT_TAGGED) && 4679 (cause == FCP_CAUSE_LINK_CHANGE) && 4680 !(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4681 fcp_offline_target_now(pptr, ptgt, 4682 link_cnt, ptgt->tgt_change_cnt, 0); 4683 } 4684 mutex_exit(&ptgt->tgt_mutex); 4685 } 4686 } 4687 4688 /* 4689 * At this point, the devices that were known but cannot be reached 4690 * anymore, have most likely been offlined. 4691 * 4692 * The following section of code seems to go through the list of 4693 * remote ports that can now be reached. For every single one it 4694 * checks if it is already known or if it is a new port. 4695 */ 4696 for (i = 0; (i < dev_cnt) && (pptr->port_link_cnt == link_cnt); i++) { 4697 4698 if (check_finish_init) { 4699 ASSERT(i > 0); 4700 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4701 map_tag[i - 1], cause); 4702 check_finish_init = 0; 4703 } 4704 4705 /* get a pointer to this map entry */ 4706 map_entry = &(devlist[i]); 4707 4708 /* 4709 * Check for the duplicate map entry flag. If we have marked 4710 * this entry as a duplicate we skip it since the correct 4711 * (perhaps even same) state change will be encountered 4712 * later in the list. 4713 */ 4714 if (map_entry->map_flags & PORT_DEVICE_DUPLICATE_MAP_ENTRY) { 4715 continue; 4716 } 4717 4718 /* get ptr to this map entry in our port's list (if any) */ 4719 ptgt = fcp_lookup_target(pptr, 4720 (uchar_t *)&(map_entry->map_pwwn)); 4721 4722 if (ptgt) { 4723 /* 4724 * This device was already known. The field 4725 * tgt_aux_state is reset (was probably set to 4726 * FCP_TGT_TAGGED previously in this routine). 4727 */ 4728 ptgt->tgt_aux_state = 0; 4729 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4730 fcp_trace, FCP_BUF_LEVEL_3, 0, 4731 "handle_devices: map did/state/type/flags = " 4732 "0x%x/0x%x/0x%x/0x%x, tgt_d_id=0x%x, " 4733 "tgt_state=%d", 4734 map_entry->map_did.port_id, map_entry->map_state, 4735 map_entry->map_type, map_entry->map_flags, 4736 ptgt->tgt_d_id, ptgt->tgt_state); 4737 } 4738 4739 if (map_entry->map_type == PORT_DEVICE_OLD || 4740 map_entry->map_type == PORT_DEVICE_NEW || 4741 map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED || 4742 map_entry->map_type == PORT_DEVICE_CHANGED) { 4743 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4744 fcp_trace, FCP_BUF_LEVEL_2, 0, 4745 "map_type=%x, did = %x", 4746 map_entry->map_type, 4747 map_entry->map_did.port_id); 4748 } 4749 4750 switch (map_entry->map_type) { 4751 case PORT_DEVICE_NOCHANGE: 4752 case PORT_DEVICE_USER_CREATE: 4753 case PORT_DEVICE_USER_LOGIN: 4754 case PORT_DEVICE_NEW: 4755 case PORT_DEVICE_REPORTLUN_CHANGED: 4756 FCP_TGT_TRACE(ptgt, map_tag[i], FCP_TGT_TRACE_1); 4757 4758 if (fcp_handle_mapflags(pptr, ptgt, map_entry, 4759 link_cnt, (ptgt) ? map_tag[i] : 0, 4760 cause) == TRUE) { 4761 4762 FCP_TGT_TRACE(ptgt, map_tag[i], 4763 FCP_TGT_TRACE_2); 4764 check_finish_init++; 4765 } 4766 break; 4767 4768 case PORT_DEVICE_OLD: 4769 if (ptgt != NULL) { 4770 FCP_TGT_TRACE(ptgt, map_tag[i], 4771 FCP_TGT_TRACE_3); 4772 4773 mutex_enter(&ptgt->tgt_mutex); 4774 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4775 /* 4776 * Must do an in-line wait for I/Os 4777 * to get drained 4778 */ 4779 mutex_exit(&ptgt->tgt_mutex); 4780 mutex_exit(&pptr->port_mutex); 4781 4782 mutex_enter(&ptgt->tgt_mutex); 4783 while (ptgt->tgt_ipkt_cnt || 4784 fcp_outstanding_lun_cmds(ptgt) 4785 == FC_SUCCESS) { 4786 mutex_exit(&ptgt->tgt_mutex); 4787 delay(drv_sectohz(1)); 4788 mutex_enter(&ptgt->tgt_mutex); 4789 } 4790 mutex_exit(&ptgt->tgt_mutex); 4791 4792 mutex_enter(&pptr->port_mutex); 4793 mutex_enter(&ptgt->tgt_mutex); 4794 4795 (void) fcp_offline_target(pptr, ptgt, 4796 link_cnt, map_tag[i], 0, 0); 4797 } 4798 mutex_exit(&ptgt->tgt_mutex); 4799 } 4800 check_finish_init++; 4801 break; 4802 4803 case PORT_DEVICE_USER_DELETE: 4804 case PORT_DEVICE_USER_LOGOUT: 4805 if (ptgt != NULL) { 4806 FCP_TGT_TRACE(ptgt, map_tag[i], 4807 FCP_TGT_TRACE_4); 4808 4809 mutex_enter(&ptgt->tgt_mutex); 4810 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 4811 (void) fcp_offline_target(pptr, ptgt, 4812 link_cnt, map_tag[i], 1, 0); 4813 } 4814 mutex_exit(&ptgt->tgt_mutex); 4815 } 4816 check_finish_init++; 4817 break; 4818 4819 case PORT_DEVICE_CHANGED: 4820 if (ptgt != NULL) { 4821 FCP_TGT_TRACE(ptgt, map_tag[i], 4822 FCP_TGT_TRACE_5); 4823 4824 if (fcp_device_changed(pptr, ptgt, 4825 map_entry, link_cnt, map_tag[i], 4826 cause) == TRUE) { 4827 check_finish_init++; 4828 } 4829 } else { 4830 if (fcp_handle_mapflags(pptr, ptgt, 4831 map_entry, link_cnt, 0, cause) == TRUE) { 4832 check_finish_init++; 4833 } 4834 } 4835 break; 4836 4837 default: 4838 fcp_log(CE_WARN, pptr->port_dip, 4839 "!Invalid map_type=0x%x", map_entry->map_type); 4840 check_finish_init++; 4841 break; 4842 } 4843 } 4844 4845 if (check_finish_init && pptr->port_link_cnt == link_cnt) { 4846 ASSERT(i > 0); 4847 (void) fcp_call_finish_init_held(pptr, ptgt, link_cnt, 4848 map_tag[i-1], cause); 4849 } else if (dev_cnt == 0 && pptr->port_link_cnt == link_cnt) { 4850 fcp_offline_all(pptr, link_cnt, cause); 4851 } 4852 } 4853 4854 static int 4855 fcp_handle_reportlun_changed(struct fcp_tgt *ptgt, int cause) 4856 { 4857 struct fcp_lun *plun; 4858 struct fcp_port *pptr; 4859 int rscn_count; 4860 int lun0_newalloc; 4861 int ret = TRUE; 4862 4863 ASSERT(ptgt); 4864 pptr = ptgt->tgt_port; 4865 lun0_newalloc = 0; 4866 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 4867 /* 4868 * no LUN struct for LUN 0 yet exists, 4869 * so create one 4870 */ 4871 plun = fcp_alloc_lun(ptgt); 4872 if (plun == NULL) { 4873 fcp_log(CE_WARN, pptr->port_dip, 4874 "!Failed to allocate lun 0 for" 4875 " D_ID=%x", ptgt->tgt_d_id); 4876 return (ret); 4877 } 4878 lun0_newalloc = 1; 4879 } 4880 4881 mutex_enter(&ptgt->tgt_mutex); 4882 /* 4883 * consider lun 0 as device not connected if it is 4884 * offlined or newly allocated 4885 */ 4886 if ((plun->lun_state & FCP_LUN_OFFLINE) || lun0_newalloc) { 4887 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 4888 } 4889 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 4890 plun->lun_state &= ~FCP_LUN_OFFLINE; 4891 ptgt->tgt_lun_cnt = 1; 4892 ptgt->tgt_report_lun_cnt = 0; 4893 mutex_exit(&ptgt->tgt_mutex); 4894 4895 rscn_count = fc_ulp_get_rscn_count(pptr->port_fp_handle); 4896 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 4897 sizeof (struct fcp_reportlun_resp), pptr->port_link_cnt, 4898 ptgt->tgt_change_cnt, cause, rscn_count) != DDI_SUCCESS) { 4899 FCP_TRACE(fcp_logq, pptr->port_instbuf, 4900 fcp_trace, FCP_BUF_LEVEL_3, 0, "!Failed to send REPORTLUN " 4901 "to D_ID=%x", ptgt->tgt_d_id); 4902 } else { 4903 ret = FALSE; 4904 } 4905 4906 return (ret); 4907 } 4908 4909 /* 4910 * Function: fcp_handle_mapflags 4911 * 4912 * Description: This function creates a target structure if the ptgt passed 4913 * is NULL. It also kicks off the PLOGI if we are not logged 4914 * into the target yet or the PRLI if we are logged into the 4915 * target already. The rest of the treatment is done in the 4916 * callbacks of the PLOGI or PRLI. 4917 * 4918 * Argument: *pptr FCP Port structure. 4919 * *ptgt Target structure. 4920 * *map_entry Array of fc_portmap_t structures. 4921 * link_cnt Link state count. 4922 * tgt_cnt Target state count. 4923 * cause What caused this function to be called. 4924 * 4925 * Return Value: TRUE Failed 4926 * FALSE Succeeded 4927 * 4928 * Notes: pptr->port_mutex must be owned. 4929 */ 4930 static int 4931 fcp_handle_mapflags(struct fcp_port *pptr, struct fcp_tgt *ptgt, 4932 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 4933 { 4934 int lcount; 4935 int tcount; 4936 int ret = TRUE; 4937 int alloc; 4938 struct fcp_ipkt *icmd; 4939 struct fcp_lun *pseq_lun = NULL; 4940 uchar_t opcode; 4941 int valid_ptgt_was_passed = FALSE; 4942 4943 ASSERT(mutex_owned(&pptr->port_mutex)); 4944 4945 /* 4946 * This case is possible where the FCTL has come up and done discovery 4947 * before FCP was loaded and attached. FCTL would have discovered the 4948 * devices and later the ULP came online. In this case ULP's would get 4949 * PORT_DEVICE_NOCHANGE but target would be NULL. 4950 */ 4951 if (ptgt == NULL) { 4952 /* don't already have a target */ 4953 mutex_exit(&pptr->port_mutex); 4954 ptgt = fcp_alloc_tgt(pptr, map_entry, link_cnt); 4955 mutex_enter(&pptr->port_mutex); 4956 4957 if (ptgt == NULL) { 4958 fcp_log(CE_WARN, pptr->port_dip, 4959 "!FC target allocation failed"); 4960 return (ret); 4961 } 4962 mutex_enter(&ptgt->tgt_mutex); 4963 ptgt->tgt_statec_cause = cause; 4964 ptgt->tgt_tmp_cnt = 1; 4965 mutex_exit(&ptgt->tgt_mutex); 4966 } else { 4967 valid_ptgt_was_passed = TRUE; 4968 } 4969 4970 /* 4971 * Copy in the target parameters 4972 */ 4973 mutex_enter(&ptgt->tgt_mutex); 4974 ptgt->tgt_d_id = map_entry->map_did.port_id; 4975 ptgt->tgt_hard_addr = map_entry->map_hard_addr.hard_addr; 4976 ptgt->tgt_pd_handle = map_entry->map_pd; 4977 ptgt->tgt_fca_dev = NULL; 4978 4979 /* Copy port and node WWNs */ 4980 bcopy(&map_entry->map_nwwn, &ptgt->tgt_node_wwn.raw_wwn[0], 4981 FC_WWN_SIZE); 4982 bcopy(&map_entry->map_pwwn, &ptgt->tgt_port_wwn.raw_wwn[0], 4983 FC_WWN_SIZE); 4984 4985 if (!(map_entry->map_flags & PORT_DEVICE_NO_SKIP_DEVICE_DISCOVERY) && 4986 (map_entry->map_type == PORT_DEVICE_NOCHANGE) && 4987 (map_entry->map_state == PORT_DEVICE_LOGGED_IN) && 4988 valid_ptgt_was_passed) { 4989 /* 4990 * determine if there are any tape LUNs on this target 4991 */ 4992 for (pseq_lun = ptgt->tgt_lun; 4993 pseq_lun != NULL; 4994 pseq_lun = pseq_lun->lun_next) { 4995 if ((pseq_lun->lun_type == DTYPE_SEQUENTIAL) && 4996 !(pseq_lun->lun_state & FCP_LUN_OFFLINE)) { 4997 fcp_update_tgt_state(ptgt, FCP_RESET, 4998 FCP_LUN_MARK); 4999 mutex_exit(&ptgt->tgt_mutex); 5000 return (ret); 5001 } 5002 } 5003 } 5004 5005 /* 5006 * if UA'REPORT_LUN_CHANGED received, 5007 * send out REPORT LUN promptly, skip PLOGI/PRLI process 5008 */ 5009 if (map_entry->map_type == PORT_DEVICE_REPORTLUN_CHANGED) { 5010 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | FCP_TGT_MARK); 5011 mutex_exit(&ptgt->tgt_mutex); 5012 mutex_exit(&pptr->port_mutex); 5013 5014 ret = fcp_handle_reportlun_changed(ptgt, cause); 5015 5016 mutex_enter(&pptr->port_mutex); 5017 return (ret); 5018 } 5019 5020 /* 5021 * If ptgt was NULL when this function was entered, then tgt_node_state 5022 * was never specifically initialized but zeroed out which means 5023 * FCP_TGT_NODE_NONE. 5024 */ 5025 switch (ptgt->tgt_node_state) { 5026 case FCP_TGT_NODE_NONE: 5027 case FCP_TGT_NODE_ON_DEMAND: 5028 if (FC_TOP_EXTERNAL(pptr->port_topology) && 5029 !fcp_enable_auto_configuration && 5030 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5031 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5032 } else if (FC_TOP_EXTERNAL(pptr->port_topology) && 5033 fcp_enable_auto_configuration && 5034 (ptgt->tgt_manual_config_only == 1) && 5035 map_entry->map_type != PORT_DEVICE_USER_CREATE) { 5036 /* 5037 * If auto configuration is set and 5038 * the tgt_manual_config_only flag is set then 5039 * we only want the user to be able to change 5040 * the state through create_on_demand. 5041 */ 5042 ptgt->tgt_node_state = FCP_TGT_NODE_ON_DEMAND; 5043 } else { 5044 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5045 } 5046 break; 5047 5048 case FCP_TGT_NODE_PRESENT: 5049 break; 5050 } 5051 /* 5052 * If we are booting from a fabric device, make sure we 5053 * mark the node state appropriately for this target to be 5054 * enumerated 5055 */ 5056 if (FC_TOP_EXTERNAL(pptr->port_topology) && pptr->port_boot_wwn[0]) { 5057 if (bcmp((caddr_t)pptr->port_boot_wwn, 5058 (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 5059 sizeof (ptgt->tgt_port_wwn)) == 0) { 5060 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 5061 } 5062 } 5063 mutex_exit(&ptgt->tgt_mutex); 5064 5065 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5066 fcp_trace, FCP_BUF_LEVEL_3, 0, 5067 "map_pd=%p, map_type=%x, did = %x, ulp_rscn_count=0x%x", 5068 map_entry->map_pd, map_entry->map_type, map_entry->map_did.port_id, 5069 map_entry->map_rscn_info.ulp_rscn_count); 5070 5071 mutex_enter(&ptgt->tgt_mutex); 5072 5073 /* 5074 * Reset target OFFLINE state and mark the target BUSY 5075 */ 5076 ptgt->tgt_state &= ~FCP_TGT_OFFLINE; 5077 ptgt->tgt_state |= (FCP_TGT_BUSY | FCP_TGT_MARK); 5078 5079 tcount = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 5080 lcount = link_cnt; 5081 5082 mutex_exit(&ptgt->tgt_mutex); 5083 mutex_exit(&pptr->port_mutex); 5084 5085 /* 5086 * if we are already logged in, then we do a PRLI, else 5087 * we do a PLOGI first (to get logged in) 5088 * 5089 * We will not check if we are the PLOGI initiator 5090 */ 5091 opcode = (map_entry->map_state == PORT_DEVICE_LOGGED_IN && 5092 map_entry->map_pd != NULL) ? LA_ELS_PRLI : LA_ELS_PLOGI; 5093 5094 alloc = FCP_MAX(sizeof (la_els_logi_t), sizeof (la_els_prli_t)); 5095 5096 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5097 pptr->port_state & FCP_STATE_FCA_IS_NODMA, lcount, tcount, 5098 cause, map_entry->map_rscn_info.ulp_rscn_count); 5099 5100 if (icmd == NULL) { 5101 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_29); 5102 /* 5103 * We've exited port_mutex before calling fcp_icmd_alloc, 5104 * we need to make sure we reacquire it before returning. 5105 */ 5106 mutex_enter(&pptr->port_mutex); 5107 return (FALSE); 5108 } 5109 5110 /* TRUE is only returned while target is intended skipped */ 5111 ret = FALSE; 5112 /* discover info about this target */ 5113 if ((fcp_send_els(pptr, ptgt, icmd, opcode, 5114 lcount, tcount, cause)) == DDI_SUCCESS) { 5115 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_9); 5116 } else { 5117 fcp_icmd_free(pptr, icmd); 5118 ret = TRUE; 5119 } 5120 mutex_enter(&pptr->port_mutex); 5121 5122 return (ret); 5123 } 5124 5125 /* 5126 * Function: fcp_send_els 5127 * 5128 * Description: Sends an ELS to the target specified by the caller. Supports 5129 * PLOGI and PRLI. 5130 * 5131 * Argument: *pptr Fcp port. 5132 * *ptgt Target to send the ELS to. 5133 * *icmd Internal packet 5134 * opcode ELS opcode 5135 * lcount Link state change counter 5136 * tcount Target state change counter 5137 * cause What caused the call 5138 * 5139 * Return Value: DDI_SUCCESS 5140 * Others 5141 */ 5142 static int 5143 fcp_send_els(struct fcp_port *pptr, struct fcp_tgt *ptgt, 5144 struct fcp_ipkt *icmd, uchar_t opcode, int lcount, int tcount, int cause) 5145 { 5146 fc_packet_t *fpkt; 5147 fc_frame_hdr_t *hp; 5148 int internal = 0; 5149 int alloc; 5150 int cmd_len; 5151 int resp_len; 5152 int res = DDI_FAILURE; /* default result */ 5153 int rval = DDI_FAILURE; 5154 5155 ASSERT(opcode == LA_ELS_PLOGI || opcode == LA_ELS_PRLI); 5156 ASSERT(ptgt->tgt_port == pptr); 5157 5158 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5159 fcp_trace, FCP_BUF_LEVEL_5, 0, 5160 "fcp_send_els: d_id=0x%x ELS 0x%x (%s)", ptgt->tgt_d_id, opcode, 5161 (opcode == LA_ELS_PLOGI) ? "PLOGI" : "PRLI"); 5162 5163 if (opcode == LA_ELS_PLOGI) { 5164 cmd_len = sizeof (la_els_logi_t); 5165 resp_len = sizeof (la_els_logi_t); 5166 } else { 5167 ASSERT(opcode == LA_ELS_PRLI); 5168 cmd_len = sizeof (la_els_prli_t); 5169 resp_len = sizeof (la_els_prli_t); 5170 } 5171 5172 if (icmd == NULL) { 5173 alloc = FCP_MAX(sizeof (la_els_logi_t), 5174 sizeof (la_els_prli_t)); 5175 icmd = fcp_icmd_alloc(pptr, ptgt, alloc, alloc, 0, 5176 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5177 lcount, tcount, cause, FC_INVALID_RSCN_COUNT); 5178 if (icmd == NULL) { 5179 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_10); 5180 return (res); 5181 } 5182 internal++; 5183 } 5184 fpkt = icmd->ipkt_fpkt; 5185 5186 fpkt->pkt_cmdlen = cmd_len; 5187 fpkt->pkt_rsplen = resp_len; 5188 fpkt->pkt_datalen = 0; 5189 icmd->ipkt_retries = 0; 5190 5191 /* fill in fpkt info */ 5192 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5193 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 5194 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5195 5196 /* get ptr to frame hdr in fpkt */ 5197 hp = &fpkt->pkt_cmd_fhdr; 5198 5199 /* 5200 * fill in frame hdr 5201 */ 5202 hp->r_ctl = R_CTL_ELS_REQ; 5203 hp->s_id = pptr->port_id; /* source ID */ 5204 hp->d_id = ptgt->tgt_d_id; /* dest ID */ 5205 hp->type = FC_TYPE_EXTENDED_LS; 5206 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 5207 hp->seq_id = 0; 5208 hp->rsvd = 0; 5209 hp->df_ctl = 0; 5210 hp->seq_cnt = 0; 5211 hp->ox_id = 0xffff; /* i.e. none */ 5212 hp->rx_id = 0xffff; /* i.e. none */ 5213 hp->ro = 0; 5214 5215 /* 5216 * at this point we have a filled in cmd pkt 5217 * 5218 * fill in the respective info, then use the transport to send 5219 * the packet 5220 * 5221 * for a PLOGI call fc_ulp_login(), and 5222 * for a PRLI call fc_ulp_issue_els() 5223 */ 5224 switch (opcode) { 5225 case LA_ELS_PLOGI: { 5226 struct la_els_logi logi; 5227 5228 bzero(&logi, sizeof (struct la_els_logi)); 5229 5230 hp = &fpkt->pkt_cmd_fhdr; 5231 hp->r_ctl = R_CTL_ELS_REQ; 5232 logi.ls_code.ls_code = LA_ELS_PLOGI; 5233 logi.ls_code.mbz = 0; 5234 5235 FCP_CP_OUT((uint8_t *)&logi, fpkt->pkt_cmd, 5236 fpkt->pkt_cmd_acc, sizeof (struct la_els_logi)); 5237 5238 icmd->ipkt_opcode = LA_ELS_PLOGI; 5239 5240 mutex_enter(&pptr->port_mutex); 5241 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5242 5243 mutex_exit(&pptr->port_mutex); 5244 5245 rval = fc_ulp_login(pptr->port_fp_handle, &fpkt, 1); 5246 if (rval == FC_SUCCESS) { 5247 res = DDI_SUCCESS; 5248 break; 5249 } 5250 5251 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_11); 5252 5253 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5254 rval, "PLOGI"); 5255 } else { 5256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5257 fcp_trace, FCP_BUF_LEVEL_5, 0, 5258 "fcp_send_els1: state change occured" 5259 " for D_ID=0x%x", ptgt->tgt_d_id); 5260 mutex_exit(&pptr->port_mutex); 5261 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_12); 5262 } 5263 break; 5264 } 5265 5266 case LA_ELS_PRLI: { 5267 struct la_els_prli prli; 5268 struct fcp_prli *fprli; 5269 5270 bzero(&prli, sizeof (struct la_els_prli)); 5271 5272 hp = &fpkt->pkt_cmd_fhdr; 5273 hp->r_ctl = R_CTL_ELS_REQ; 5274 5275 /* fill in PRLI cmd ELS fields */ 5276 prli.ls_code = LA_ELS_PRLI; 5277 prli.page_length = 0x10; /* huh? */ 5278 prli.payload_length = sizeof (struct la_els_prli); 5279 5280 icmd->ipkt_opcode = LA_ELS_PRLI; 5281 5282 /* get ptr to PRLI service params */ 5283 fprli = (struct fcp_prli *)prli.service_params; 5284 5285 /* fill in service params */ 5286 fprli->type = 0x08; 5287 fprli->resvd1 = 0; 5288 fprli->orig_process_assoc_valid = 0; 5289 fprli->resp_process_assoc_valid = 0; 5290 fprli->establish_image_pair = 1; 5291 fprli->resvd2 = 0; 5292 fprli->resvd3 = 0; 5293 fprli->obsolete_1 = 0; 5294 fprli->obsolete_2 = 0; 5295 fprli->data_overlay_allowed = 0; 5296 fprli->initiator_fn = 1; 5297 fprli->confirmed_compl_allowed = 1; 5298 5299 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5300 fprli->target_fn = 1; 5301 } else { 5302 fprli->target_fn = 0; 5303 } 5304 5305 fprli->retry = 1; 5306 fprli->read_xfer_rdy_disabled = 1; 5307 fprli->write_xfer_rdy_disabled = 0; 5308 5309 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5310 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5311 5312 /* issue the PRLI request */ 5313 5314 mutex_enter(&pptr->port_mutex); 5315 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 5316 5317 mutex_exit(&pptr->port_mutex); 5318 5319 rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt); 5320 if (rval == FC_SUCCESS) { 5321 res = DDI_SUCCESS; 5322 break; 5323 } 5324 5325 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_13); 5326 5327 res = fcp_handle_ipkt_errors(pptr, ptgt, icmd, 5328 rval, "PRLI"); 5329 } else { 5330 mutex_exit(&pptr->port_mutex); 5331 FCP_TGT_TRACE(ptgt, tcount, FCP_TGT_TRACE_14); 5332 } 5333 break; 5334 } 5335 5336 default: 5337 fcp_log(CE_WARN, NULL, "!invalid ELS opcode=0x%x", opcode); 5338 break; 5339 } 5340 5341 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5342 fcp_trace, FCP_BUF_LEVEL_5, 0, 5343 "fcp_send_els: returning %d", res); 5344 5345 if (res != DDI_SUCCESS) { 5346 if (internal) { 5347 fcp_icmd_free(pptr, icmd); 5348 } 5349 } 5350 5351 return (res); 5352 } 5353 5354 5355 /* 5356 * called internally update the state of all of the tgts and each LUN 5357 * for this port (i.e. each target known to be attached to this port) 5358 * if they are not already offline 5359 * 5360 * must be called with the port mutex owned 5361 * 5362 * acquires and releases the target mutexes for each target attached 5363 * to this port 5364 */ 5365 void 5366 fcp_update_state(struct fcp_port *pptr, uint32_t state, int cause) 5367 { 5368 int i; 5369 struct fcp_tgt *ptgt; 5370 5371 ASSERT(mutex_owned(&pptr->port_mutex)); 5372 5373 for (i = 0; i < FCP_NUM_HASH; i++) { 5374 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5375 ptgt = ptgt->tgt_next) { 5376 mutex_enter(&ptgt->tgt_mutex); 5377 fcp_update_tgt_state(ptgt, FCP_SET, state); 5378 ptgt->tgt_change_cnt++; 5379 ptgt->tgt_statec_cause = cause; 5380 ptgt->tgt_tmp_cnt = 1; 5381 ptgt->tgt_done = 0; 5382 mutex_exit(&ptgt->tgt_mutex); 5383 } 5384 } 5385 } 5386 5387 5388 static void 5389 fcp_offline_all(struct fcp_port *pptr, int lcount, int cause) 5390 { 5391 int i; 5392 int ndevs; 5393 struct fcp_tgt *ptgt; 5394 5395 ASSERT(mutex_owned(&pptr->port_mutex)); 5396 5397 for (ndevs = 0, i = 0; i < FCP_NUM_HASH; i++) { 5398 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5399 ptgt = ptgt->tgt_next) { 5400 ndevs++; 5401 } 5402 } 5403 5404 if (ndevs == 0) { 5405 return; 5406 } 5407 pptr->port_tmp_cnt = ndevs; 5408 5409 for (i = 0; i < FCP_NUM_HASH; i++) { 5410 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 5411 ptgt = ptgt->tgt_next) { 5412 (void) fcp_call_finish_init_held(pptr, ptgt, 5413 lcount, ptgt->tgt_change_cnt, cause); 5414 } 5415 } 5416 } 5417 5418 /* 5419 * Function: fcp_update_tgt_state 5420 * 5421 * Description: This function updates the field tgt_state of a target. That 5422 * field is a bitmap and which bit can be set or reset 5423 * individually. The action applied to the target state is also 5424 * applied to all the LUNs belonging to the target (provided the 5425 * LUN is not offline). A side effect of applying the state 5426 * modification to the target and the LUNs is the field tgt_trace 5427 * of the target and lun_trace of the LUNs is set to zero. 5428 * 5429 * 5430 * Argument: *ptgt Target structure. 5431 * flag Flag indication what action to apply (set/reset). 5432 * state State bits to update. 5433 * 5434 * Return Value: None 5435 * 5436 * Context: Interrupt, Kernel or User context. 5437 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5438 * calling this function. 5439 */ 5440 void 5441 fcp_update_tgt_state(struct fcp_tgt *ptgt, int flag, uint32_t state) 5442 { 5443 struct fcp_lun *plun; 5444 5445 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5446 5447 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 5448 /* The target is not offline. */ 5449 if (flag == FCP_SET) { 5450 ptgt->tgt_state |= state; 5451 ptgt->tgt_trace = 0; 5452 } else { 5453 ptgt->tgt_state &= ~state; 5454 } 5455 5456 for (plun = ptgt->tgt_lun; plun != NULL; 5457 plun = plun->lun_next) { 5458 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 5459 /* The LUN is not offline. */ 5460 if (flag == FCP_SET) { 5461 plun->lun_state |= state; 5462 plun->lun_trace = 0; 5463 } else { 5464 plun->lun_state &= ~state; 5465 } 5466 } 5467 } 5468 } 5469 } 5470 5471 /* 5472 * Function: fcp_update_tgt_state 5473 * 5474 * Description: This function updates the field lun_state of a LUN. That 5475 * field is a bitmap and which bit can be set or reset 5476 * individually. 5477 * 5478 * Argument: *plun LUN structure. 5479 * flag Flag indication what action to apply (set/reset). 5480 * state State bits to update. 5481 * 5482 * Return Value: None 5483 * 5484 * Context: Interrupt, Kernel or User context. 5485 * The mutex of the target (ptgt->tgt_mutex) must be owned when 5486 * calling this function. 5487 */ 5488 void 5489 fcp_update_lun_state(struct fcp_lun *plun, int flag, uint32_t state) 5490 { 5491 struct fcp_tgt *ptgt = plun->lun_tgt; 5492 5493 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 5494 5495 if (!(plun->lun_state & FCP_TGT_OFFLINE)) { 5496 if (flag == FCP_SET) { 5497 plun->lun_state |= state; 5498 } else { 5499 plun->lun_state &= ~state; 5500 } 5501 } 5502 } 5503 5504 /* 5505 * Function: fcp_get_port 5506 * 5507 * Description: This function returns the fcp_port structure from the opaque 5508 * handle passed by the caller. That opaque handle is the handle 5509 * used by fp/fctl to identify a particular local port. That 5510 * handle has been stored in the corresponding fcp_port 5511 * structure. This function is going to walk the global list of 5512 * fcp_port structures till one has a port_fp_handle that matches 5513 * the handle passed by the caller. This function enters the 5514 * mutex fcp_global_mutex while walking the global list and then 5515 * releases it. 5516 * 5517 * Argument: port_handle Opaque handle that fp/fctl uses to identify a 5518 * particular port. 5519 * 5520 * Return Value: NULL Not found. 5521 * Not NULL Pointer to the fcp_port structure. 5522 * 5523 * Context: Interrupt, Kernel or User context. 5524 */ 5525 static struct fcp_port * 5526 fcp_get_port(opaque_t port_handle) 5527 { 5528 struct fcp_port *pptr; 5529 5530 ASSERT(port_handle != NULL); 5531 5532 mutex_enter(&fcp_global_mutex); 5533 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 5534 if (pptr->port_fp_handle == port_handle) { 5535 break; 5536 } 5537 } 5538 mutex_exit(&fcp_global_mutex); 5539 5540 return (pptr); 5541 } 5542 5543 5544 static void 5545 fcp_unsol_callback(fc_packet_t *fpkt) 5546 { 5547 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 5548 struct fcp_port *pptr = icmd->ipkt_port; 5549 5550 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 5551 caddr_t state, reason, action, expln; 5552 5553 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 5554 &action, &expln); 5555 5556 fcp_log(CE_WARN, pptr->port_dip, 5557 "!couldn't post response to unsolicited request: " 5558 " state=%s reason=%s rx_id=%x ox_id=%x", 5559 state, reason, fpkt->pkt_cmd_fhdr.ox_id, 5560 fpkt->pkt_cmd_fhdr.rx_id); 5561 } 5562 fcp_icmd_free(pptr, icmd); 5563 } 5564 5565 5566 /* 5567 * Perform general purpose preparation of a response to an unsolicited request 5568 */ 5569 static void 5570 fcp_unsol_resp_init(fc_packet_t *pkt, fc_unsol_buf_t *buf, 5571 uchar_t r_ctl, uchar_t type) 5572 { 5573 pkt->pkt_cmd_fhdr.r_ctl = r_ctl; 5574 pkt->pkt_cmd_fhdr.d_id = buf->ub_frame.s_id; 5575 pkt->pkt_cmd_fhdr.s_id = buf->ub_frame.d_id; 5576 pkt->pkt_cmd_fhdr.type = type; 5577 pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_XCHG_CONTEXT; 5578 pkt->pkt_cmd_fhdr.seq_id = buf->ub_frame.seq_id; 5579 pkt->pkt_cmd_fhdr.df_ctl = buf->ub_frame.df_ctl; 5580 pkt->pkt_cmd_fhdr.seq_cnt = buf->ub_frame.seq_cnt; 5581 pkt->pkt_cmd_fhdr.ox_id = buf->ub_frame.ox_id; 5582 pkt->pkt_cmd_fhdr.rx_id = buf->ub_frame.rx_id; 5583 pkt->pkt_cmd_fhdr.ro = 0; 5584 pkt->pkt_cmd_fhdr.rsvd = 0; 5585 pkt->pkt_comp = fcp_unsol_callback; 5586 pkt->pkt_pd = NULL; 5587 pkt->pkt_ub_resp_token = (opaque_t)buf; 5588 } 5589 5590 5591 /*ARGSUSED*/ 5592 static int 5593 fcp_unsol_prli(struct fcp_port *pptr, fc_unsol_buf_t *buf) 5594 { 5595 fc_packet_t *fpkt; 5596 struct la_els_prli prli; 5597 struct fcp_prli *fprli; 5598 struct fcp_ipkt *icmd; 5599 struct la_els_prli *from; 5600 struct fcp_prli *orig; 5601 struct fcp_tgt *ptgt; 5602 int tcount = 0; 5603 int lcount; 5604 5605 from = (struct la_els_prli *)buf->ub_buffer; 5606 orig = (struct fcp_prli *)from->service_params; 5607 if ((ptgt = fcp_get_target_by_did(pptr, buf->ub_frame.s_id)) != 5608 NULL) { 5609 mutex_enter(&ptgt->tgt_mutex); 5610 tcount = ptgt->tgt_change_cnt; 5611 mutex_exit(&ptgt->tgt_mutex); 5612 } 5613 5614 mutex_enter(&pptr->port_mutex); 5615 lcount = pptr->port_link_cnt; 5616 mutex_exit(&pptr->port_mutex); 5617 5618 if ((icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (la_els_prli_t), 5619 sizeof (la_els_prli_t), 0, 5620 pptr->port_state & FCP_STATE_FCA_IS_NODMA, 5621 lcount, tcount, 0, FC_INVALID_RSCN_COUNT)) == NULL) { 5622 return (FC_FAILURE); 5623 } 5624 5625 fpkt = icmd->ipkt_fpkt; 5626 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 5627 fpkt->pkt_tran_type = FC_PKT_OUTBOUND; 5628 fpkt->pkt_timeout = FCP_ELS_TIMEOUT; 5629 fpkt->pkt_cmdlen = sizeof (la_els_prli_t); 5630 fpkt->pkt_rsplen = 0; 5631 fpkt->pkt_datalen = 0; 5632 5633 icmd->ipkt_opcode = LA_ELS_PRLI; 5634 5635 bzero(&prli, sizeof (struct la_els_prli)); 5636 fprli = (struct fcp_prli *)prli.service_params; 5637 prli.ls_code = LA_ELS_ACC; 5638 prli.page_length = 0x10; 5639 prli.payload_length = sizeof (struct la_els_prli); 5640 5641 /* fill in service params */ 5642 fprli->type = 0x08; 5643 fprli->resvd1 = 0; 5644 fprli->orig_process_assoc_valid = orig->orig_process_assoc_valid; 5645 fprli->orig_process_associator = orig->orig_process_associator; 5646 fprli->resp_process_assoc_valid = 0; 5647 fprli->establish_image_pair = 1; 5648 fprli->resvd2 = 0; 5649 fprli->resvd3 = 0; 5650 fprli->obsolete_1 = 0; 5651 fprli->obsolete_2 = 0; 5652 fprli->data_overlay_allowed = 0; 5653 fprli->initiator_fn = 1; 5654 fprli->confirmed_compl_allowed = 1; 5655 5656 if (fc_ulp_is_name_present("ltct") == FC_SUCCESS) { 5657 fprli->target_fn = 1; 5658 } else { 5659 fprli->target_fn = 0; 5660 } 5661 5662 fprli->retry = 1; 5663 fprli->read_xfer_rdy_disabled = 1; 5664 fprli->write_xfer_rdy_disabled = 0; 5665 5666 /* save the unsol prli payload first */ 5667 FCP_CP_OUT((uint8_t *)from, fpkt->pkt_resp, 5668 fpkt->pkt_resp_acc, sizeof (struct la_els_prli)); 5669 5670 FCP_CP_OUT((uint8_t *)&prli, fpkt->pkt_cmd, 5671 fpkt->pkt_cmd_acc, sizeof (struct la_els_prli)); 5672 5673 fcp_unsol_resp_init(fpkt, buf, R_CTL_ELS_RSP, FC_TYPE_EXTENDED_LS); 5674 5675 mutex_enter(&pptr->port_mutex); 5676 if (!FCP_LINK_STATE_CHANGED(pptr, icmd)) { 5677 int rval; 5678 mutex_exit(&pptr->port_mutex); 5679 5680 if ((rval = fc_ulp_issue_els(pptr->port_fp_handle, fpkt)) != 5681 FC_SUCCESS) { 5682 if ((rval == FC_STATEC_BUSY || rval == FC_OFFLINE) && 5683 ptgt != NULL) { 5684 fcp_queue_ipkt(pptr, fpkt); 5685 return (FC_SUCCESS); 5686 } 5687 /* Let it timeout */ 5688 fcp_icmd_free(pptr, icmd); 5689 return (FC_FAILURE); 5690 } 5691 } else { 5692 mutex_exit(&pptr->port_mutex); 5693 fcp_icmd_free(pptr, icmd); 5694 return (FC_FAILURE); 5695 } 5696 5697 (void) fc_ulp_ubrelease(pptr->port_fp_handle, 1, &buf->ub_token); 5698 5699 return (FC_SUCCESS); 5700 } 5701 5702 /* 5703 * Function: fcp_icmd_alloc 5704 * 5705 * Description: This function allocated a fcp_ipkt structure. The pkt_comp 5706 * field is initialized to fcp_icmd_callback. Sometimes it is 5707 * modified by the caller (such as fcp_send_scsi). The 5708 * structure is also tied to the state of the line and of the 5709 * target at a particular time. That link is established by 5710 * setting the fields ipkt_link_cnt and ipkt_change_cnt to lcount 5711 * and tcount which came respectively from pptr->link_cnt and 5712 * ptgt->tgt_change_cnt. 5713 * 5714 * Argument: *pptr Fcp port. 5715 * *ptgt Target (destination of the command). 5716 * cmd_len Length of the command. 5717 * resp_len Length of the expected response. 5718 * data_len Length of the data. 5719 * nodma Indicates weither the command and response. 5720 * will be transfer through DMA or not. 5721 * lcount Link state change counter. 5722 * tcount Target state change counter. 5723 * cause Reason that lead to this call. 5724 * 5725 * Return Value: NULL Failed. 5726 * Not NULL Internal packet address. 5727 */ 5728 static struct fcp_ipkt * 5729 fcp_icmd_alloc(struct fcp_port *pptr, struct fcp_tgt *ptgt, int cmd_len, 5730 int resp_len, int data_len, int nodma, int lcount, int tcount, int cause, 5731 uint32_t rscn_count) 5732 { 5733 int dma_setup = 0; 5734 fc_packet_t *fpkt; 5735 struct fcp_ipkt *icmd = NULL; 5736 5737 icmd = kmem_zalloc(sizeof (struct fcp_ipkt) + 5738 pptr->port_dmacookie_sz + pptr->port_priv_pkt_len, 5739 KM_NOSLEEP); 5740 if (icmd == NULL) { 5741 fcp_log(CE_WARN, pptr->port_dip, 5742 "!internal packet allocation failed"); 5743 return (NULL); 5744 } 5745 5746 /* 5747 * initialize the allocated packet 5748 */ 5749 icmd->ipkt_nodma = nodma; 5750 icmd->ipkt_next = icmd->ipkt_prev = NULL; 5751 icmd->ipkt_lun = NULL; 5752 5753 icmd->ipkt_link_cnt = lcount; 5754 icmd->ipkt_change_cnt = tcount; 5755 icmd->ipkt_cause = cause; 5756 5757 mutex_enter(&pptr->port_mutex); 5758 icmd->ipkt_port = pptr; 5759 mutex_exit(&pptr->port_mutex); 5760 5761 /* keep track of amt of data to be sent in pkt */ 5762 icmd->ipkt_cmdlen = cmd_len; 5763 icmd->ipkt_resplen = resp_len; 5764 icmd->ipkt_datalen = data_len; 5765 5766 /* set up pkt's ptr to the fc_packet_t struct, just after the ipkt */ 5767 icmd->ipkt_fpkt = (fc_packet_t *)(&icmd->ipkt_fc_packet); 5768 5769 /* set pkt's private ptr to point to cmd pkt */ 5770 icmd->ipkt_fpkt->pkt_ulp_private = (opaque_t)icmd; 5771 5772 /* set FCA private ptr to memory just beyond */ 5773 icmd->ipkt_fpkt->pkt_fca_private = (opaque_t) 5774 ((char *)icmd + sizeof (struct fcp_ipkt) + 5775 pptr->port_dmacookie_sz); 5776 5777 /* get ptr to fpkt substruct and fill it in */ 5778 fpkt = icmd->ipkt_fpkt; 5779 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)icmd + 5780 sizeof (struct fcp_ipkt)); 5781 5782 if (ptgt != NULL) { 5783 icmd->ipkt_tgt = ptgt; 5784 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 5785 } 5786 5787 fpkt->pkt_comp = fcp_icmd_callback; 5788 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 5789 fpkt->pkt_cmdlen = cmd_len; 5790 fpkt->pkt_rsplen = resp_len; 5791 fpkt->pkt_datalen = data_len; 5792 5793 /* 5794 * The pkt_ulp_rscn_infop (aka pkt_ulp_rsvd1) field is used to pass the 5795 * rscn_count as fcp knows down to the transport. If a valid count was 5796 * passed into this function, we allocate memory to actually pass down 5797 * this info. 5798 * 5799 * BTW, if the kmem_zalloc fails, we won't try too hard. This will 5800 * basically mean that fcp will not be able to help transport 5801 * distinguish if a new RSCN has come after fcp was last informed about 5802 * it. In such cases, it might lead to the problem mentioned in CR/bug # 5803 * 5068068 where the device might end up going offline in case of RSCN 5804 * storms. 5805 */ 5806 fpkt->pkt_ulp_rscn_infop = NULL; 5807 if (rscn_count != FC_INVALID_RSCN_COUNT) { 5808 fpkt->pkt_ulp_rscn_infop = kmem_zalloc( 5809 sizeof (fc_ulp_rscn_info_t), KM_NOSLEEP); 5810 if (fpkt->pkt_ulp_rscn_infop == NULL) { 5811 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5812 fcp_trace, FCP_BUF_LEVEL_6, 0, 5813 "Failed to alloc memory to pass rscn info"); 5814 } 5815 } 5816 5817 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5818 fc_ulp_rscn_info_t *rscnp; 5819 5820 rscnp = (fc_ulp_rscn_info_t *)fpkt->pkt_ulp_rscn_infop; 5821 rscnp->ulp_rscn_count = rscn_count; 5822 } 5823 5824 if (fcp_alloc_dma(pptr, icmd, nodma, KM_NOSLEEP) != FC_SUCCESS) { 5825 goto fail; 5826 } 5827 dma_setup++; 5828 5829 /* 5830 * Must hold target mutex across setting of pkt_pd and call to 5831 * fc_ulp_init_packet to ensure the handle to the target doesn't go 5832 * away while we're not looking. 5833 */ 5834 if (ptgt != NULL) { 5835 mutex_enter(&ptgt->tgt_mutex); 5836 fpkt->pkt_pd = ptgt->tgt_pd_handle; 5837 5838 /* ask transport to do its initialization on this pkt */ 5839 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5840 != FC_SUCCESS) { 5841 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5842 fcp_trace, FCP_BUF_LEVEL_6, 0, 5843 "fc_ulp_init_packet failed"); 5844 mutex_exit(&ptgt->tgt_mutex); 5845 goto fail; 5846 } 5847 mutex_exit(&ptgt->tgt_mutex); 5848 } else { 5849 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, KM_NOSLEEP) 5850 != FC_SUCCESS) { 5851 FCP_TRACE(fcp_logq, pptr->port_instbuf, 5852 fcp_trace, FCP_BUF_LEVEL_6, 0, 5853 "fc_ulp_init_packet failed"); 5854 goto fail; 5855 } 5856 } 5857 5858 mutex_enter(&pptr->port_mutex); 5859 if (pptr->port_state & (FCP_STATE_DETACHING | 5860 FCP_STATE_SUSPENDED | FCP_STATE_POWER_DOWN)) { 5861 int rval; 5862 5863 mutex_exit(&pptr->port_mutex); 5864 5865 rval = fc_ulp_uninit_packet(pptr->port_fp_handle, fpkt); 5866 ASSERT(rval == FC_SUCCESS); 5867 5868 goto fail; 5869 } 5870 5871 if (ptgt != NULL) { 5872 mutex_enter(&ptgt->tgt_mutex); 5873 ptgt->tgt_ipkt_cnt++; 5874 mutex_exit(&ptgt->tgt_mutex); 5875 } 5876 5877 pptr->port_ipkt_cnt++; 5878 5879 mutex_exit(&pptr->port_mutex); 5880 5881 return (icmd); 5882 5883 fail: 5884 if (fpkt->pkt_ulp_rscn_infop != NULL) { 5885 kmem_free(fpkt->pkt_ulp_rscn_infop, 5886 sizeof (fc_ulp_rscn_info_t)); 5887 fpkt->pkt_ulp_rscn_infop = NULL; 5888 } 5889 5890 if (dma_setup) { 5891 fcp_free_dma(pptr, icmd); 5892 } 5893 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5894 (size_t)pptr->port_dmacookie_sz); 5895 5896 return (NULL); 5897 } 5898 5899 /* 5900 * Function: fcp_icmd_free 5901 * 5902 * Description: Frees the internal command passed by the caller. 5903 * 5904 * Argument: *pptr Fcp port. 5905 * *icmd Internal packet to free. 5906 * 5907 * Return Value: None 5908 */ 5909 static void 5910 fcp_icmd_free(struct fcp_port *pptr, struct fcp_ipkt *icmd) 5911 { 5912 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 5913 5914 /* Let the underlying layers do their cleanup. */ 5915 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 5916 icmd->ipkt_fpkt); 5917 5918 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop) { 5919 kmem_free(icmd->ipkt_fpkt->pkt_ulp_rscn_infop, 5920 sizeof (fc_ulp_rscn_info_t)); 5921 } 5922 5923 fcp_free_dma(pptr, icmd); 5924 5925 kmem_free(icmd, sizeof (struct fcp_ipkt) + pptr->port_priv_pkt_len + 5926 (size_t)pptr->port_dmacookie_sz); 5927 5928 mutex_enter(&pptr->port_mutex); 5929 5930 if (ptgt) { 5931 mutex_enter(&ptgt->tgt_mutex); 5932 ptgt->tgt_ipkt_cnt--; 5933 mutex_exit(&ptgt->tgt_mutex); 5934 } 5935 5936 pptr->port_ipkt_cnt--; 5937 mutex_exit(&pptr->port_mutex); 5938 } 5939 5940 /* 5941 * Function: fcp_alloc_dma 5942 * 5943 * Description: Allocated the DMA resources required for the internal 5944 * packet. 5945 * 5946 * Argument: *pptr FCP port. 5947 * *icmd Internal FCP packet. 5948 * nodma Indicates if the Cmd and Resp will be DMAed. 5949 * flags Allocation flags (Sleep or NoSleep). 5950 * 5951 * Return Value: FC_SUCCESS 5952 * FC_NOMEM 5953 */ 5954 static int 5955 fcp_alloc_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd, 5956 int nodma, int flags) 5957 { 5958 int rval; 5959 size_t real_size; 5960 uint_t ccount; 5961 int bound = 0; 5962 int cmd_resp = 0; 5963 fc_packet_t *fpkt; 5964 ddi_dma_cookie_t pkt_data_cookie; 5965 ddi_dma_cookie_t *cp; 5966 uint32_t cnt; 5967 5968 fpkt = &icmd->ipkt_fc_packet; 5969 5970 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_data_dma == NULL && 5971 fpkt->pkt_resp_dma == NULL); 5972 5973 icmd->ipkt_nodma = nodma; 5974 5975 if (nodma) { 5976 fpkt->pkt_cmd = kmem_zalloc(fpkt->pkt_cmdlen, flags); 5977 if (fpkt->pkt_cmd == NULL) { 5978 goto fail; 5979 } 5980 5981 fpkt->pkt_resp = kmem_zalloc(fpkt->pkt_rsplen, flags); 5982 if (fpkt->pkt_resp == NULL) { 5983 goto fail; 5984 } 5985 } else { 5986 ASSERT(fpkt->pkt_cmdlen && fpkt->pkt_rsplen); 5987 5988 rval = fcp_alloc_cmd_resp(pptr, fpkt, flags); 5989 if (rval == FC_FAILURE) { 5990 ASSERT(fpkt->pkt_cmd_dma == NULL && 5991 fpkt->pkt_resp_dma == NULL); 5992 goto fail; 5993 } 5994 cmd_resp++; 5995 } 5996 5997 if ((fpkt->pkt_datalen != 0) && 5998 !(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 5999 /* 6000 * set up DMA handle and memory for the data in this packet 6001 */ 6002 if (ddi_dma_alloc_handle(pptr->port_dip, 6003 &pptr->port_data_dma_attr, DDI_DMA_DONTWAIT, 6004 NULL, &fpkt->pkt_data_dma) != DDI_SUCCESS) { 6005 goto fail; 6006 } 6007 6008 if (ddi_dma_mem_alloc(fpkt->pkt_data_dma, fpkt->pkt_datalen, 6009 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, 6010 DDI_DMA_DONTWAIT, NULL, &fpkt->pkt_data, 6011 &real_size, &fpkt->pkt_data_acc) != DDI_SUCCESS) { 6012 goto fail; 6013 } 6014 6015 /* was DMA mem size gotten < size asked for/needed ?? */ 6016 if (real_size < fpkt->pkt_datalen) { 6017 goto fail; 6018 } 6019 6020 /* bind DMA address and handle together */ 6021 if (ddi_dma_addr_bind_handle(fpkt->pkt_data_dma, 6022 NULL, fpkt->pkt_data, real_size, DDI_DMA_READ | 6023 DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 6024 &pkt_data_cookie, &ccount) != DDI_DMA_MAPPED) { 6025 goto fail; 6026 } 6027 bound++; 6028 6029 if (ccount > pptr->port_data_dma_attr.dma_attr_sgllen) { 6030 goto fail; 6031 } 6032 6033 fpkt->pkt_data_cookie_cnt = ccount; 6034 6035 cp = fpkt->pkt_data_cookie; 6036 *cp = pkt_data_cookie; 6037 cp++; 6038 6039 for (cnt = 1; cnt < ccount; cnt++, cp++) { 6040 ddi_dma_nextcookie(fpkt->pkt_data_dma, 6041 &pkt_data_cookie); 6042 *cp = pkt_data_cookie; 6043 } 6044 6045 } else if (fpkt->pkt_datalen != 0) { 6046 /* 6047 * If it's a pseudo FCA, then it can't support DMA even in 6048 * SCSI data phase. 6049 */ 6050 fpkt->pkt_data = kmem_alloc(fpkt->pkt_datalen, flags); 6051 if (fpkt->pkt_data == NULL) { 6052 goto fail; 6053 } 6054 6055 } 6056 6057 return (FC_SUCCESS); 6058 6059 fail: 6060 if (bound) { 6061 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6062 } 6063 6064 if (fpkt->pkt_data_dma) { 6065 if (fpkt->pkt_data) { 6066 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6067 } 6068 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6069 } else { 6070 if (fpkt->pkt_data) { 6071 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6072 } 6073 } 6074 6075 if (nodma) { 6076 if (fpkt->pkt_cmd) { 6077 kmem_free(fpkt->pkt_cmd, fpkt->pkt_cmdlen); 6078 } 6079 if (fpkt->pkt_resp) { 6080 kmem_free(fpkt->pkt_resp, fpkt->pkt_rsplen); 6081 } 6082 } else { 6083 if (cmd_resp) { 6084 fcp_free_cmd_resp(pptr, fpkt); 6085 } 6086 } 6087 6088 return (FC_NOMEM); 6089 } 6090 6091 6092 static void 6093 fcp_free_dma(struct fcp_port *pptr, struct fcp_ipkt *icmd) 6094 { 6095 fc_packet_t *fpkt = icmd->ipkt_fpkt; 6096 6097 if (fpkt->pkt_data_dma) { 6098 (void) ddi_dma_unbind_handle(fpkt->pkt_data_dma); 6099 if (fpkt->pkt_data) { 6100 ddi_dma_mem_free(&fpkt->pkt_data_acc); 6101 } 6102 ddi_dma_free_handle(&fpkt->pkt_data_dma); 6103 } else { 6104 if (fpkt->pkt_data) { 6105 kmem_free(fpkt->pkt_data, fpkt->pkt_datalen); 6106 } 6107 /* 6108 * Need we reset pkt_* to zero??? 6109 */ 6110 } 6111 6112 if (icmd->ipkt_nodma) { 6113 if (fpkt->pkt_cmd) { 6114 kmem_free(fpkt->pkt_cmd, icmd->ipkt_cmdlen); 6115 } 6116 if (fpkt->pkt_resp) { 6117 kmem_free(fpkt->pkt_resp, icmd->ipkt_resplen); 6118 } 6119 } else { 6120 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 6121 6122 fcp_free_cmd_resp(pptr, fpkt); 6123 } 6124 } 6125 6126 /* 6127 * Function: fcp_lookup_target 6128 * 6129 * Description: Finds a target given a WWN. 6130 * 6131 * Argument: *pptr FCP port. 6132 * *wwn World Wide Name of the device to look for. 6133 * 6134 * Return Value: NULL No target found 6135 * Not NULL Target structure 6136 * 6137 * Context: Interrupt context. 6138 * The mutex pptr->port_mutex must be owned. 6139 */ 6140 /* ARGSUSED */ 6141 static struct fcp_tgt * 6142 fcp_lookup_target(struct fcp_port *pptr, uchar_t *wwn) 6143 { 6144 int hash; 6145 struct fcp_tgt *ptgt; 6146 6147 ASSERT(mutex_owned(&pptr->port_mutex)); 6148 6149 hash = FCP_HASH(wwn); 6150 6151 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 6152 ptgt = ptgt->tgt_next) { 6153 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN) && 6154 bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 6155 sizeof (ptgt->tgt_port_wwn)) == 0) { 6156 break; 6157 } 6158 } 6159 6160 return (ptgt); 6161 } 6162 6163 6164 /* 6165 * Find target structure given a port identifier 6166 */ 6167 static struct fcp_tgt * 6168 fcp_get_target_by_did(struct fcp_port *pptr, uint32_t d_id) 6169 { 6170 fc_portid_t port_id; 6171 la_wwn_t pwwn; 6172 struct fcp_tgt *ptgt = NULL; 6173 6174 port_id.priv_lilp_posit = 0; 6175 port_id.port_id = d_id; 6176 if (fc_ulp_get_pwwn_by_did(pptr->port_fp_handle, port_id, 6177 &pwwn) == FC_SUCCESS) { 6178 mutex_enter(&pptr->port_mutex); 6179 ptgt = fcp_lookup_target(pptr, pwwn.raw_wwn); 6180 mutex_exit(&pptr->port_mutex); 6181 } 6182 6183 return (ptgt); 6184 } 6185 6186 6187 /* 6188 * the packet completion callback routine for info cmd pkts 6189 * 6190 * this means fpkt pts to a response to either a PLOGI or a PRLI 6191 * 6192 * if there is an error an attempt is made to call a routine to resend 6193 * the command that failed 6194 */ 6195 static void 6196 fcp_icmd_callback(fc_packet_t *fpkt) 6197 { 6198 struct fcp_ipkt *icmd; 6199 struct fcp_port *pptr; 6200 struct fcp_tgt *ptgt; 6201 struct la_els_prli *prli; 6202 struct la_els_prli prli_s; 6203 struct fcp_prli *fprli; 6204 struct fcp_lun *plun; 6205 int free_pkt = 1; 6206 int rval; 6207 ls_code_t resp; 6208 uchar_t prli_acc = 0; 6209 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 6210 int lun0_newalloc; 6211 6212 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 6213 6214 /* get ptrs to the port and target structs for the cmd */ 6215 pptr = icmd->ipkt_port; 6216 ptgt = icmd->ipkt_tgt; 6217 6218 FCP_CP_IN(fpkt->pkt_resp, &resp, fpkt->pkt_resp_acc, sizeof (resp)); 6219 6220 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 6221 FCP_CP_IN(fpkt->pkt_cmd, &prli_s, fpkt->pkt_cmd_acc, 6222 sizeof (prli_s)); 6223 prli_acc = (prli_s.ls_code == LA_ELS_ACC); 6224 } 6225 6226 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6227 fcp_trace, FCP_BUF_LEVEL_2, 0, 6228 "ELS (%x) callback state=0x%x reason=0x%x for %x", 6229 icmd->ipkt_opcode, fpkt->pkt_state, fpkt->pkt_reason, 6230 ptgt->tgt_d_id); 6231 6232 if ((fpkt->pkt_state == FC_PKT_SUCCESS) && 6233 ((resp.ls_code == LA_ELS_ACC) || prli_acc)) { 6234 6235 mutex_enter(&ptgt->tgt_mutex); 6236 if (ptgt->tgt_pd_handle == NULL) { 6237 /* 6238 * in a fabric environment the port device handles 6239 * get created only after successful LOGIN into the 6240 * transport, so the transport makes this port 6241 * device (pd) handle available in this packet, so 6242 * save it now 6243 */ 6244 ASSERT(fpkt->pkt_pd != NULL); 6245 ptgt->tgt_pd_handle = fpkt->pkt_pd; 6246 } 6247 mutex_exit(&ptgt->tgt_mutex); 6248 6249 /* which ELS cmd is this response for ?? */ 6250 switch (icmd->ipkt_opcode) { 6251 case LA_ELS_PLOGI: 6252 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6253 fcp_trace, FCP_BUF_LEVEL_5, 0, 6254 "PLOGI to d_id=0x%x succeeded, wwn=%08x%08x", 6255 ptgt->tgt_d_id, 6256 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 6257 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4])); 6258 6259 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6260 FCP_TGT_TRACE_15); 6261 6262 /* Note that we are not allocating a new icmd */ 6263 if (fcp_send_els(pptr, ptgt, icmd, LA_ELS_PRLI, 6264 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6265 icmd->ipkt_cause) != DDI_SUCCESS) { 6266 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6267 FCP_TGT_TRACE_16); 6268 goto fail; 6269 } 6270 break; 6271 6272 case LA_ELS_PRLI: 6273 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6274 fcp_trace, FCP_BUF_LEVEL_5, 0, 6275 "PRLI to d_id=0x%x succeeded", ptgt->tgt_d_id); 6276 6277 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6278 FCP_TGT_TRACE_17); 6279 6280 prli = &prli_s; 6281 6282 FCP_CP_IN(fpkt->pkt_resp, prli, fpkt->pkt_resp_acc, 6283 sizeof (prli_s)); 6284 6285 fprli = (struct fcp_prli *)prli->service_params; 6286 6287 mutex_enter(&ptgt->tgt_mutex); 6288 ptgt->tgt_icap = fprli->initiator_fn; 6289 ptgt->tgt_tcap = fprli->target_fn; 6290 mutex_exit(&ptgt->tgt_mutex); 6291 6292 if ((fprli->type != 0x08) || (fprli->target_fn != 1)) { 6293 /* 6294 * this FCP device does not support target mode 6295 */ 6296 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6297 FCP_TGT_TRACE_18); 6298 goto fail; 6299 } 6300 if (fprli->retry == 1) { 6301 fc_ulp_disable_relogin(pptr->port_fp_handle, 6302 &ptgt->tgt_port_wwn); 6303 } 6304 6305 /* target is no longer offline */ 6306 mutex_enter(&pptr->port_mutex); 6307 mutex_enter(&ptgt->tgt_mutex); 6308 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6309 ptgt->tgt_state &= ~(FCP_TGT_OFFLINE | 6310 FCP_TGT_MARK); 6311 } else { 6312 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6313 fcp_trace, FCP_BUF_LEVEL_2, 0, 6314 "fcp_icmd_callback,1: state change " 6315 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6316 mutex_exit(&ptgt->tgt_mutex); 6317 mutex_exit(&pptr->port_mutex); 6318 goto fail; 6319 } 6320 mutex_exit(&ptgt->tgt_mutex); 6321 mutex_exit(&pptr->port_mutex); 6322 6323 /* 6324 * lun 0 should always respond to inquiry, so 6325 * get the LUN struct for LUN 0 6326 * 6327 * Currently we deal with first level of addressing. 6328 * If / when we start supporting 0x device types 6329 * (DTYPE_ARRAY_CTRL, i.e. array controllers) 6330 * this logic will need revisiting. 6331 */ 6332 lun0_newalloc = 0; 6333 if ((plun = fcp_get_lun(ptgt, 0)) == NULL) { 6334 /* 6335 * no LUN struct for LUN 0 yet exists, 6336 * so create one 6337 */ 6338 plun = fcp_alloc_lun(ptgt); 6339 if (plun == NULL) { 6340 fcp_log(CE_WARN, pptr->port_dip, 6341 "!Failed to allocate lun 0 for" 6342 " D_ID=%x", ptgt->tgt_d_id); 6343 goto fail; 6344 } 6345 lun0_newalloc = 1; 6346 } 6347 6348 /* fill in LUN info */ 6349 mutex_enter(&ptgt->tgt_mutex); 6350 /* 6351 * consider lun 0 as device not connected if it is 6352 * offlined or newly allocated 6353 */ 6354 if ((plun->lun_state & FCP_LUN_OFFLINE) || 6355 lun0_newalloc) { 6356 plun->lun_state |= FCP_LUN_DEVICE_NOT_CONNECTED; 6357 } 6358 plun->lun_state |= (FCP_LUN_BUSY | FCP_LUN_MARK); 6359 plun->lun_state &= ~FCP_LUN_OFFLINE; 6360 ptgt->tgt_lun_cnt = 1; 6361 ptgt->tgt_report_lun_cnt = 0; 6362 mutex_exit(&ptgt->tgt_mutex); 6363 6364 /* Retrieve the rscn count (if a valid one exists) */ 6365 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 6366 rscn_count = ((fc_ulp_rscn_info_t *) 6367 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop)) 6368 ->ulp_rscn_count; 6369 } else { 6370 rscn_count = FC_INVALID_RSCN_COUNT; 6371 } 6372 6373 /* send Report Lun request to target */ 6374 if (fcp_send_scsi(plun, SCMD_REPORT_LUN, 6375 sizeof (struct fcp_reportlun_resp), 6376 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 6377 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 6378 mutex_enter(&pptr->port_mutex); 6379 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6380 fcp_log(CE_WARN, pptr->port_dip, 6381 "!Failed to send REPORT LUN to" 6382 " D_ID=%x", ptgt->tgt_d_id); 6383 } else { 6384 FCP_TRACE(fcp_logq, 6385 pptr->port_instbuf, fcp_trace, 6386 FCP_BUF_LEVEL_5, 0, 6387 "fcp_icmd_callback,2:state change" 6388 " occured for D_ID=0x%x", 6389 ptgt->tgt_d_id); 6390 } 6391 mutex_exit(&pptr->port_mutex); 6392 6393 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6394 FCP_TGT_TRACE_19); 6395 6396 goto fail; 6397 } else { 6398 free_pkt = 0; 6399 fcp_icmd_free(pptr, icmd); 6400 } 6401 break; 6402 6403 default: 6404 fcp_log(CE_WARN, pptr->port_dip, 6405 "!fcp_icmd_callback Invalid opcode"); 6406 goto fail; 6407 } 6408 6409 return; 6410 } 6411 6412 6413 /* 6414 * Other PLOGI failures are not retried as the 6415 * transport does it already 6416 */ 6417 if (icmd->ipkt_opcode != LA_ELS_PLOGI) { 6418 if (fcp_is_retryable(icmd) && 6419 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6420 6421 if (FCP_MUST_RETRY(fpkt)) { 6422 fcp_queue_ipkt(pptr, fpkt); 6423 return; 6424 } 6425 6426 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6427 fcp_trace, FCP_BUF_LEVEL_2, 0, 6428 "ELS PRLI is retried for d_id=0x%x, state=%x," 6429 " reason= %x", ptgt->tgt_d_id, fpkt->pkt_state, 6430 fpkt->pkt_reason); 6431 6432 /* 6433 * Retry by recalling the routine that 6434 * originally queued this packet 6435 */ 6436 mutex_enter(&pptr->port_mutex); 6437 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6438 caddr_t msg; 6439 6440 mutex_exit(&pptr->port_mutex); 6441 6442 ASSERT(icmd->ipkt_opcode != LA_ELS_PLOGI); 6443 6444 if (fpkt->pkt_state == FC_PKT_TIMEOUT) { 6445 fpkt->pkt_timeout += 6446 FCP_TIMEOUT_DELTA; 6447 } 6448 6449 rval = fc_ulp_issue_els(pptr->port_fp_handle, 6450 fpkt); 6451 if (rval == FC_SUCCESS) { 6452 return; 6453 } 6454 6455 if (rval == FC_STATEC_BUSY || 6456 rval == FC_OFFLINE) { 6457 fcp_queue_ipkt(pptr, fpkt); 6458 return; 6459 } 6460 (void) fc_ulp_error(rval, &msg); 6461 6462 fcp_log(CE_NOTE, pptr->port_dip, 6463 "!ELS 0x%x failed to d_id=0x%x;" 6464 " %s", icmd->ipkt_opcode, 6465 ptgt->tgt_d_id, msg); 6466 } else { 6467 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6468 fcp_trace, FCP_BUF_LEVEL_2, 0, 6469 "fcp_icmd_callback,3: state change " 6470 " occured for D_ID=0x%x", ptgt->tgt_d_id); 6471 mutex_exit(&pptr->port_mutex); 6472 } 6473 } 6474 } else { 6475 if (fcp_is_retryable(icmd) && 6476 icmd->ipkt_retries++ < FCP_MAX_RETRIES) { 6477 if (FCP_MUST_RETRY(fpkt)) { 6478 fcp_queue_ipkt(pptr, fpkt); 6479 return; 6480 } 6481 } 6482 mutex_enter(&pptr->port_mutex); 6483 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd) && 6484 fpkt->pkt_state != FC_PKT_PORT_OFFLINE) { 6485 mutex_exit(&pptr->port_mutex); 6486 fcp_print_error(fpkt); 6487 } else { 6488 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6489 fcp_trace, FCP_BUF_LEVEL_2, 0, 6490 "fcp_icmd_callback,4: state change occured" 6491 " for D_ID=0x%x", ptgt->tgt_d_id); 6492 mutex_exit(&pptr->port_mutex); 6493 } 6494 } 6495 6496 fail: 6497 if (free_pkt) { 6498 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6499 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6500 fcp_icmd_free(pptr, icmd); 6501 } 6502 } 6503 6504 6505 /* 6506 * called internally to send an info cmd using the transport 6507 * 6508 * sends either an INQ or a REPORT_LUN 6509 * 6510 * when the packet is completed fcp_scsi_callback is called 6511 */ 6512 static int 6513 fcp_send_scsi(struct fcp_lun *plun, uchar_t opcode, int alloc_len, 6514 int lcount, int tcount, int cause, uint32_t rscn_count) 6515 { 6516 int nodma; 6517 struct fcp_ipkt *icmd; 6518 struct fcp_tgt *ptgt; 6519 struct fcp_port *pptr; 6520 fc_frame_hdr_t *hp; 6521 fc_packet_t *fpkt; 6522 struct fcp_cmd fcp_cmd; 6523 struct fcp_cmd *fcmd; 6524 union scsi_cdb *scsi_cdb; 6525 6526 ASSERT(plun != NULL); 6527 6528 ptgt = plun->lun_tgt; 6529 ASSERT(ptgt != NULL); 6530 6531 pptr = ptgt->tgt_port; 6532 ASSERT(pptr != NULL); 6533 6534 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6535 fcp_trace, FCP_BUF_LEVEL_5, 0, 6536 "fcp_send_scsi: d_id=0x%x opcode=0x%x", ptgt->tgt_d_id, opcode); 6537 6538 nodma = (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) ? 1 : 0; 6539 icmd = fcp_icmd_alloc(pptr, ptgt, sizeof (struct fcp_cmd), 6540 FCP_MAX_RSP_IU_SIZE, alloc_len, nodma, lcount, tcount, cause, 6541 rscn_count); 6542 6543 if (icmd == NULL) { 6544 return (DDI_FAILURE); 6545 } 6546 6547 fpkt = icmd->ipkt_fpkt; 6548 fpkt->pkt_tran_flags = FC_TRAN_CLASS3 | FC_TRAN_INTR; 6549 icmd->ipkt_retries = 0; 6550 icmd->ipkt_opcode = opcode; 6551 icmd->ipkt_lun = plun; 6552 6553 if (nodma) { 6554 fcmd = (struct fcp_cmd *)fpkt->pkt_cmd; 6555 } else { 6556 fcmd = &fcp_cmd; 6557 } 6558 bzero(fcmd, sizeof (struct fcp_cmd)); 6559 6560 fpkt->pkt_timeout = FCP_SCSI_CMD_TIMEOUT; 6561 6562 hp = &fpkt->pkt_cmd_fhdr; 6563 6564 hp->s_id = pptr->port_id; 6565 hp->d_id = ptgt->tgt_d_id; 6566 hp->r_ctl = R_CTL_COMMAND; 6567 hp->type = FC_TYPE_SCSI_FCP; 6568 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 6569 hp->rsvd = 0; 6570 hp->seq_id = 0; 6571 hp->seq_cnt = 0; 6572 hp->ox_id = 0xffff; 6573 hp->rx_id = 0xffff; 6574 hp->ro = 0; 6575 6576 bcopy(&(plun->lun_addr), &(fcmd->fcp_ent_addr), FCP_LUN_SIZE); 6577 6578 /* 6579 * Request SCSI target for expedited processing 6580 */ 6581 6582 /* 6583 * Set up for untagged queuing because we do not 6584 * know if the fibre device supports queuing. 6585 */ 6586 fcmd->fcp_cntl.cntl_reserved_0 = 0; 6587 fcmd->fcp_cntl.cntl_reserved_1 = 0; 6588 fcmd->fcp_cntl.cntl_reserved_2 = 0; 6589 fcmd->fcp_cntl.cntl_reserved_3 = 0; 6590 fcmd->fcp_cntl.cntl_reserved_4 = 0; 6591 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 6592 scsi_cdb = (union scsi_cdb *)fcmd->fcp_cdb; 6593 6594 switch (opcode) { 6595 case SCMD_INQUIRY_PAGE83: 6596 /* 6597 * Prepare to get the Inquiry VPD page 83 information 6598 */ 6599 fcmd->fcp_cntl.cntl_read_data = 1; 6600 fcmd->fcp_cntl.cntl_write_data = 0; 6601 fcmd->fcp_data_len = alloc_len; 6602 6603 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6604 fpkt->pkt_comp = fcp_scsi_callback; 6605 6606 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6607 scsi_cdb->g0_addr2 = 0x01; 6608 scsi_cdb->g0_addr1 = 0x83; 6609 scsi_cdb->g0_count0 = (uchar_t)alloc_len; 6610 break; 6611 6612 case SCMD_INQUIRY: 6613 fcmd->fcp_cntl.cntl_read_data = 1; 6614 fcmd->fcp_cntl.cntl_write_data = 0; 6615 fcmd->fcp_data_len = alloc_len; 6616 6617 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6618 fpkt->pkt_comp = fcp_scsi_callback; 6619 6620 scsi_cdb->scc_cmd = SCMD_INQUIRY; 6621 scsi_cdb->g0_count0 = SUN_INQSIZE; 6622 break; 6623 6624 case SCMD_REPORT_LUN: { 6625 fc_portid_t d_id; 6626 opaque_t fca_dev; 6627 6628 ASSERT(alloc_len >= 16); 6629 6630 d_id.priv_lilp_posit = 0; 6631 d_id.port_id = ptgt->tgt_d_id; 6632 6633 fca_dev = fc_ulp_get_fca_device(pptr->port_fp_handle, d_id); 6634 6635 mutex_enter(&ptgt->tgt_mutex); 6636 ptgt->tgt_fca_dev = fca_dev; 6637 mutex_exit(&ptgt->tgt_mutex); 6638 6639 fcmd->fcp_cntl.cntl_read_data = 1; 6640 fcmd->fcp_cntl.cntl_write_data = 0; 6641 fcmd->fcp_data_len = alloc_len; 6642 6643 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 6644 fpkt->pkt_comp = fcp_scsi_callback; 6645 6646 scsi_cdb->scc_cmd = SCMD_REPORT_LUN; 6647 scsi_cdb->scc5_count0 = alloc_len & 0xff; 6648 scsi_cdb->scc5_count1 = (alloc_len >> 8) & 0xff; 6649 scsi_cdb->scc5_count2 = (alloc_len >> 16) & 0xff; 6650 scsi_cdb->scc5_count3 = (alloc_len >> 24) & 0xff; 6651 break; 6652 } 6653 6654 default: 6655 fcp_log(CE_WARN, pptr->port_dip, 6656 "!fcp_send_scsi Invalid opcode"); 6657 break; 6658 } 6659 6660 if (!nodma) { 6661 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 6662 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 6663 } 6664 6665 mutex_enter(&pptr->port_mutex); 6666 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 6667 6668 mutex_exit(&pptr->port_mutex); 6669 if (fcp_transport(pptr->port_fp_handle, fpkt, 1) != 6670 FC_SUCCESS) { 6671 fcp_icmd_free(pptr, icmd); 6672 return (DDI_FAILURE); 6673 } 6674 return (DDI_SUCCESS); 6675 } else { 6676 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6677 fcp_trace, FCP_BUF_LEVEL_2, 0, 6678 "fcp_send_scsi,1: state change occured" 6679 " for D_ID=0x%x", ptgt->tgt_d_id); 6680 mutex_exit(&pptr->port_mutex); 6681 fcp_icmd_free(pptr, icmd); 6682 return (DDI_FAILURE); 6683 } 6684 } 6685 6686 6687 /* 6688 * called by fcp_scsi_callback to check to handle the case where 6689 * REPORT_LUN returns ILLEGAL REQUEST or a UNIT ATTENTION 6690 */ 6691 static int 6692 fcp_check_reportlun(struct fcp_rsp *rsp, fc_packet_t *fpkt) 6693 { 6694 uchar_t rqlen; 6695 int rval = DDI_FAILURE; 6696 struct scsi_extended_sense sense_info, *sense; 6697 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6698 fpkt->pkt_ulp_private; 6699 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 6700 struct fcp_port *pptr = ptgt->tgt_port; 6701 6702 ASSERT(icmd->ipkt_opcode == SCMD_REPORT_LUN); 6703 6704 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_RESERVATION_CONFLICT) { 6705 /* 6706 * SCSI-II Reserve Release support. Some older FC drives return 6707 * Reservation conflict for Report Luns command. 6708 */ 6709 if (icmd->ipkt_nodma) { 6710 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6711 rsp->fcp_u.fcp_status.sense_len_set = 0; 6712 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6713 } else { 6714 fcp_rsp_t new_resp; 6715 6716 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6717 fpkt->pkt_resp_acc, sizeof (new_resp)); 6718 6719 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6720 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6721 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6722 6723 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6724 fpkt->pkt_resp_acc, sizeof (new_resp)); 6725 } 6726 6727 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6728 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6729 6730 return (DDI_SUCCESS); 6731 } 6732 6733 sense = &sense_info; 6734 if (!rsp->fcp_u.fcp_status.sense_len_set) { 6735 /* no need to continue if sense length is not set */ 6736 return (rval); 6737 } 6738 6739 /* casting 64-bit integer to 8-bit */ 6740 rqlen = (uchar_t)min(rsp->fcp_sense_len, 6741 sizeof (struct scsi_extended_sense)); 6742 6743 if (rqlen < 14) { 6744 /* no need to continue if request length isn't long enough */ 6745 return (rval); 6746 } 6747 6748 if (icmd->ipkt_nodma) { 6749 /* 6750 * We can safely use fcp_response_len here since the 6751 * only path that calls fcp_check_reportlun, 6752 * fcp_scsi_callback, has already called 6753 * fcp_validate_fcp_response. 6754 */ 6755 sense = (struct scsi_extended_sense *)(fpkt->pkt_resp + 6756 sizeof (struct fcp_rsp) + rsp->fcp_response_len); 6757 } else { 6758 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp) + 6759 rsp->fcp_response_len, sense, fpkt->pkt_resp_acc, 6760 sizeof (struct scsi_extended_sense)); 6761 } 6762 6763 if (!FCP_SENSE_NO_LUN(sense)) { 6764 mutex_enter(&ptgt->tgt_mutex); 6765 /* clear the flag if any */ 6766 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6767 mutex_exit(&ptgt->tgt_mutex); 6768 } 6769 6770 if ((sense->es_key == KEY_ILLEGAL_REQUEST) && 6771 (sense->es_add_code == 0x20)) { 6772 if (icmd->ipkt_nodma) { 6773 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6774 rsp->fcp_u.fcp_status.sense_len_set = 0; 6775 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6776 } else { 6777 fcp_rsp_t new_resp; 6778 6779 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6780 fpkt->pkt_resp_acc, sizeof (new_resp)); 6781 6782 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6783 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6784 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6785 6786 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6787 fpkt->pkt_resp_acc, sizeof (new_resp)); 6788 } 6789 6790 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6791 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6792 6793 return (DDI_SUCCESS); 6794 } 6795 6796 /* 6797 * This is for the STK library which returns a check condition, 6798 * to indicate device is not ready, manual assistance needed. 6799 * This is to a report lun command when the door is open. 6800 */ 6801 if ((sense->es_key == KEY_NOT_READY) && (sense->es_add_code == 0x04)) { 6802 if (icmd->ipkt_nodma) { 6803 rsp->fcp_u.fcp_status.rsp_len_set = 0; 6804 rsp->fcp_u.fcp_status.sense_len_set = 0; 6805 rsp->fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6806 } else { 6807 fcp_rsp_t new_resp; 6808 6809 FCP_CP_IN(fpkt->pkt_resp, &new_resp, 6810 fpkt->pkt_resp_acc, sizeof (new_resp)); 6811 6812 new_resp.fcp_u.fcp_status.rsp_len_set = 0; 6813 new_resp.fcp_u.fcp_status.sense_len_set = 0; 6814 new_resp.fcp_u.fcp_status.scsi_status = STATUS_GOOD; 6815 6816 FCP_CP_OUT(&new_resp, fpkt->pkt_resp, 6817 fpkt->pkt_resp_acc, sizeof (new_resp)); 6818 } 6819 6820 FCP_CP_OUT(fcp_dummy_lun, fpkt->pkt_data, 6821 fpkt->pkt_data_acc, sizeof (fcp_dummy_lun)); 6822 6823 return (DDI_SUCCESS); 6824 } 6825 6826 if ((FCP_SENSE_REPORTLUN_CHANGED(sense)) || 6827 (FCP_SENSE_NO_LUN(sense))) { 6828 mutex_enter(&ptgt->tgt_mutex); 6829 if ((FCP_SENSE_NO_LUN(sense)) && 6830 (ptgt->tgt_state & FCP_TGT_ILLREQ)) { 6831 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 6832 mutex_exit(&ptgt->tgt_mutex); 6833 /* 6834 * reconfig was triggred by ILLEGAL REQUEST but 6835 * got ILLEGAL REQUEST again 6836 */ 6837 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6838 fcp_trace, FCP_BUF_LEVEL_3, 0, 6839 "!FCP: Unable to obtain Report Lun data" 6840 " target=%x", ptgt->tgt_d_id); 6841 } else { 6842 if (ptgt->tgt_tid == NULL) { 6843 timeout_id_t tid; 6844 /* 6845 * REPORT LUN data has changed. Kick off 6846 * rediscovery 6847 */ 6848 tid = timeout(fcp_reconfigure_luns, 6849 (caddr_t)ptgt, (clock_t)drv_usectohz(1)); 6850 6851 ptgt->tgt_tid = tid; 6852 ptgt->tgt_state |= FCP_TGT_BUSY; 6853 } 6854 if (FCP_SENSE_NO_LUN(sense)) { 6855 ptgt->tgt_state |= FCP_TGT_ILLREQ; 6856 } 6857 mutex_exit(&ptgt->tgt_mutex); 6858 if (FCP_SENSE_REPORTLUN_CHANGED(sense)) { 6859 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6860 fcp_trace, FCP_BUF_LEVEL_3, 0, 6861 "!FCP:Report Lun Has Changed" 6862 " target=%x", ptgt->tgt_d_id); 6863 } else if (FCP_SENSE_NO_LUN(sense)) { 6864 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6865 fcp_trace, FCP_BUF_LEVEL_3, 0, 6866 "!FCP:LU Not Supported" 6867 " target=%x", ptgt->tgt_d_id); 6868 } 6869 } 6870 rval = DDI_SUCCESS; 6871 } 6872 6873 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6874 fcp_trace, FCP_BUF_LEVEL_5, 0, 6875 "D_ID=%x, sense=%x, status=%x", 6876 fpkt->pkt_cmd_fhdr.d_id, sense->es_key, 6877 rsp->fcp_u.fcp_status.scsi_status); 6878 6879 return (rval); 6880 } 6881 6882 /* 6883 * Function: fcp_scsi_callback 6884 * 6885 * Description: This is the callback routine set by fcp_send_scsi() after 6886 * it calls fcp_icmd_alloc(). The SCSI command completed here 6887 * and autogenerated by FCP are: REPORT_LUN, INQUIRY and 6888 * INQUIRY_PAGE83. 6889 * 6890 * Argument: *fpkt FC packet used to convey the command 6891 * 6892 * Return Value: None 6893 */ 6894 static void 6895 fcp_scsi_callback(fc_packet_t *fpkt) 6896 { 6897 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 6898 fpkt->pkt_ulp_private; 6899 struct fcp_rsp_info fcp_rsp_err, *bep; 6900 struct fcp_port *pptr; 6901 struct fcp_tgt *ptgt; 6902 struct fcp_lun *plun; 6903 struct fcp_rsp response, *rsp; 6904 6905 ptgt = icmd->ipkt_tgt; 6906 pptr = ptgt->tgt_port; 6907 plun = icmd->ipkt_lun; 6908 6909 if (icmd->ipkt_nodma) { 6910 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 6911 } else { 6912 rsp = &response; 6913 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 6914 sizeof (struct fcp_rsp)); 6915 } 6916 6917 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6918 fcp_trace, FCP_BUF_LEVEL_2, 0, 6919 "SCSI callback state=0x%x for %x, op_code=0x%x, " 6920 "status=%x, lun num=%x", 6921 fpkt->pkt_state, ptgt->tgt_d_id, icmd->ipkt_opcode, 6922 rsp->fcp_u.fcp_status.scsi_status, plun->lun_num); 6923 6924 /* 6925 * Pre-init LUN GUID with NWWN if it is not a device that 6926 * supports multiple luns and we know it's not page83 6927 * compliant. Although using a NWWN is not lun unique, 6928 * we will be fine since there is only one lun behind the taget 6929 * in this case. 6930 */ 6931 if ((plun->lun_guid_size == 0) && 6932 (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 6933 (fcp_symmetric_device_probe(plun) == 0)) { 6934 6935 char ascii_wwn[FC_WWN_SIZE*2+1]; 6936 fcp_wwn_to_ascii(&ptgt->tgt_node_wwn.raw_wwn[0], ascii_wwn); 6937 (void) fcp_copy_guid_2_lun_block(plun, ascii_wwn); 6938 } 6939 6940 /* 6941 * Some old FC tapes and FC <-> SCSI bridge devices return overrun 6942 * when thay have more data than what is asked in CDB. An overrun 6943 * is really when FCP_DL is smaller than the data length in CDB. 6944 * In the case here we know that REPORT LUN command we formed within 6945 * this binary has correct FCP_DL. So this OVERRUN is due to bad device 6946 * behavior. In reality this is FC_SUCCESS. 6947 */ 6948 if ((fpkt->pkt_state != FC_PKT_SUCCESS) && 6949 (fpkt->pkt_reason == FC_REASON_OVERRUN) && 6950 (icmd->ipkt_opcode == SCMD_REPORT_LUN)) { 6951 fpkt->pkt_state = FC_PKT_SUCCESS; 6952 } 6953 6954 if (fpkt->pkt_state != FC_PKT_SUCCESS) { 6955 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6956 fcp_trace, FCP_BUF_LEVEL_2, 0, 6957 "icmd failed with state=0x%x for %x", fpkt->pkt_state, 6958 ptgt->tgt_d_id); 6959 6960 if (fpkt->pkt_reason == FC_REASON_CRC_ERROR) { 6961 /* 6962 * Inquiry VPD page command on A5K SES devices would 6963 * result in data CRC errors. 6964 */ 6965 if (icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) { 6966 (void) fcp_handle_page83(fpkt, icmd, 1); 6967 return; 6968 } 6969 } 6970 if (fpkt->pkt_state == FC_PKT_TIMEOUT || 6971 FCP_MUST_RETRY(fpkt)) { 6972 fpkt->pkt_timeout += FCP_TIMEOUT_DELTA; 6973 fcp_retry_scsi_cmd(fpkt); 6974 return; 6975 } 6976 6977 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 6978 FCP_TGT_TRACE_20); 6979 6980 mutex_enter(&pptr->port_mutex); 6981 mutex_enter(&ptgt->tgt_mutex); 6982 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 6983 mutex_exit(&ptgt->tgt_mutex); 6984 mutex_exit(&pptr->port_mutex); 6985 fcp_print_error(fpkt); 6986 } else { 6987 FCP_TRACE(fcp_logq, pptr->port_instbuf, 6988 fcp_trace, FCP_BUF_LEVEL_2, 0, 6989 "fcp_scsi_callback,1: state change occured" 6990 " for D_ID=0x%x", ptgt->tgt_d_id); 6991 mutex_exit(&ptgt->tgt_mutex); 6992 mutex_exit(&pptr->port_mutex); 6993 } 6994 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 6995 icmd->ipkt_change_cnt, icmd->ipkt_cause); 6996 fcp_icmd_free(pptr, icmd); 6997 return; 6998 } 6999 7000 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, FCP_TGT_TRACE_21); 7001 7002 mutex_enter(&pptr->port_mutex); 7003 mutex_enter(&ptgt->tgt_mutex); 7004 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7005 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7006 fcp_trace, FCP_BUF_LEVEL_2, 0, 7007 "fcp_scsi_callback,2: state change occured" 7008 " for D_ID=0x%x", ptgt->tgt_d_id); 7009 mutex_exit(&ptgt->tgt_mutex); 7010 mutex_exit(&pptr->port_mutex); 7011 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7012 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7013 fcp_icmd_free(pptr, icmd); 7014 return; 7015 } 7016 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7017 7018 mutex_exit(&ptgt->tgt_mutex); 7019 mutex_exit(&pptr->port_mutex); 7020 7021 if (icmd->ipkt_nodma) { 7022 bep = (struct fcp_rsp_info *)(fpkt->pkt_resp + 7023 sizeof (struct fcp_rsp)); 7024 } else { 7025 bep = &fcp_rsp_err; 7026 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), bep, 7027 fpkt->pkt_resp_acc, sizeof (struct fcp_rsp_info)); 7028 } 7029 7030 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 7031 fcp_retry_scsi_cmd(fpkt); 7032 return; 7033 } 7034 7035 if (rsp->fcp_u.fcp_status.rsp_len_set && bep->rsp_code != 7036 FCP_NO_FAILURE) { 7037 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7038 fcp_trace, FCP_BUF_LEVEL_2, 0, 7039 "rsp_code=0x%x, rsp_len_set=0x%x", 7040 bep->rsp_code, rsp->fcp_u.fcp_status.rsp_len_set); 7041 fcp_retry_scsi_cmd(fpkt); 7042 return; 7043 } 7044 7045 if (rsp->fcp_u.fcp_status.scsi_status == STATUS_QFULL || 7046 rsp->fcp_u.fcp_status.scsi_status == STATUS_BUSY) { 7047 fcp_queue_ipkt(pptr, fpkt); 7048 return; 7049 } 7050 7051 /* 7052 * Devices that do not support INQUIRY_PAGE83, return check condition 7053 * with illegal request as per SCSI spec. 7054 * Crossbridge is one such device and Daktari's SES node is another. 7055 * We want to ideally enumerate these devices as a non-mpxio devices. 7056 * SES nodes (Daktari only currently) are an exception to this. 7057 */ 7058 if ((icmd->ipkt_opcode == SCMD_INQUIRY_PAGE83) && 7059 (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK)) { 7060 7061 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7062 fcp_trace, FCP_BUF_LEVEL_3, 0, 7063 "INQUIRY_PAGE83 for d_id %x (dtype:0x%x) failed with " 7064 "check condition. May enumerate as non-mpxio device", 7065 ptgt->tgt_d_id, plun->lun_type); 7066 7067 /* 7068 * If we let Daktari's SES be enumerated as a non-mpxio 7069 * device, there will be a discrepency in that the other 7070 * internal FC disks will get enumerated as mpxio devices. 7071 * Applications like luxadm expect this to be consistent. 7072 * 7073 * So, we put in a hack here to check if this is an SES device 7074 * and handle it here. 7075 */ 7076 if (plun->lun_type == DTYPE_ESI) { 7077 /* 7078 * Since, pkt_state is actually FC_PKT_SUCCESS 7079 * at this stage, we fake a failure here so that 7080 * fcp_handle_page83 will create a device path using 7081 * the WWN instead of the GUID which is not there anyway 7082 */ 7083 fpkt->pkt_state = FC_PKT_LOCAL_RJT; 7084 (void) fcp_handle_page83(fpkt, icmd, 1); 7085 return; 7086 } 7087 7088 mutex_enter(&ptgt->tgt_mutex); 7089 plun->lun_state &= ~(FCP_LUN_OFFLINE | 7090 FCP_LUN_MARK | FCP_LUN_BUSY); 7091 mutex_exit(&ptgt->tgt_mutex); 7092 7093 (void) fcp_call_finish_init(pptr, ptgt, 7094 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7095 icmd->ipkt_cause); 7096 fcp_icmd_free(pptr, icmd); 7097 return; 7098 } 7099 7100 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7101 int rval = DDI_FAILURE; 7102 7103 /* 7104 * handle cases where report lun isn't supported 7105 * by faking up our own REPORT_LUN response or 7106 * UNIT ATTENTION 7107 */ 7108 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7109 rval = fcp_check_reportlun(rsp, fpkt); 7110 7111 /* 7112 * fcp_check_reportlun might have modified the 7113 * FCP response. Copy it in again to get an updated 7114 * FCP response 7115 */ 7116 if (rval == DDI_SUCCESS && icmd->ipkt_nodma == 0) { 7117 rsp = &response; 7118 7119 FCP_CP_IN(fpkt->pkt_resp, rsp, 7120 fpkt->pkt_resp_acc, 7121 sizeof (struct fcp_rsp)); 7122 } 7123 } 7124 7125 if (rsp->fcp_u.fcp_status.scsi_status != STATUS_GOOD) { 7126 if (rval == DDI_SUCCESS) { 7127 (void) fcp_call_finish_init(pptr, ptgt, 7128 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7129 icmd->ipkt_cause); 7130 fcp_icmd_free(pptr, icmd); 7131 } else { 7132 fcp_retry_scsi_cmd(fpkt); 7133 } 7134 7135 return; 7136 } 7137 } else { 7138 if (icmd->ipkt_opcode == SCMD_REPORT_LUN) { 7139 mutex_enter(&ptgt->tgt_mutex); 7140 ptgt->tgt_state &= ~FCP_TGT_ILLREQ; 7141 mutex_exit(&ptgt->tgt_mutex); 7142 } 7143 } 7144 7145 ASSERT(rsp->fcp_u.fcp_status.scsi_status == STATUS_GOOD); 7146 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 7147 (void) ddi_dma_sync(fpkt->pkt_data_dma, 0, 0, 7148 DDI_DMA_SYNC_FORCPU); 7149 } 7150 7151 switch (icmd->ipkt_opcode) { 7152 case SCMD_INQUIRY: 7153 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_1); 7154 fcp_handle_inquiry(fpkt, icmd); 7155 break; 7156 7157 case SCMD_REPORT_LUN: 7158 FCP_TGT_TRACE(ptgt, icmd->ipkt_change_cnt, 7159 FCP_TGT_TRACE_22); 7160 fcp_handle_reportlun(fpkt, icmd); 7161 break; 7162 7163 case SCMD_INQUIRY_PAGE83: 7164 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_2); 7165 (void) fcp_handle_page83(fpkt, icmd, 0); 7166 break; 7167 7168 default: 7169 fcp_log(CE_WARN, NULL, "!Invalid SCSI opcode"); 7170 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7171 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7172 fcp_icmd_free(pptr, icmd); 7173 break; 7174 } 7175 } 7176 7177 7178 static void 7179 fcp_retry_scsi_cmd(fc_packet_t *fpkt) 7180 { 7181 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 7182 fpkt->pkt_ulp_private; 7183 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 7184 struct fcp_port *pptr = ptgt->tgt_port; 7185 7186 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 7187 fcp_is_retryable(icmd)) { 7188 mutex_enter(&pptr->port_mutex); 7189 if (!FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7190 mutex_exit(&pptr->port_mutex); 7191 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7192 fcp_trace, FCP_BUF_LEVEL_3, 0, 7193 "Retrying %s to %x; state=%x, reason=%x", 7194 (icmd->ipkt_opcode == SCMD_REPORT_LUN) ? 7195 "Report LUN" : "INQUIRY", ptgt->tgt_d_id, 7196 fpkt->pkt_state, fpkt->pkt_reason); 7197 7198 fcp_queue_ipkt(pptr, fpkt); 7199 } else { 7200 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7201 fcp_trace, FCP_BUF_LEVEL_3, 0, 7202 "fcp_retry_scsi_cmd,1: state change occured" 7203 " for D_ID=0x%x", ptgt->tgt_d_id); 7204 mutex_exit(&pptr->port_mutex); 7205 (void) fcp_call_finish_init(pptr, ptgt, 7206 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7207 icmd->ipkt_cause); 7208 fcp_icmd_free(pptr, icmd); 7209 } 7210 } else { 7211 fcp_print_error(fpkt); 7212 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7213 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7214 fcp_icmd_free(pptr, icmd); 7215 } 7216 } 7217 7218 /* 7219 * Function: fcp_handle_page83 7220 * 7221 * Description: Treats the response to INQUIRY_PAGE83. 7222 * 7223 * Argument: *fpkt FC packet used to convey the command. 7224 * *icmd Original fcp_ipkt structure. 7225 * ignore_page83_data 7226 * if it's 1, that means it's a special devices's 7227 * page83 response, it should be enumerated under mpxio 7228 * 7229 * Return Value: None 7230 */ 7231 static void 7232 fcp_handle_page83(fc_packet_t *fpkt, struct fcp_ipkt *icmd, 7233 int ignore_page83_data) 7234 { 7235 struct fcp_port *pptr; 7236 struct fcp_lun *plun; 7237 struct fcp_tgt *ptgt; 7238 uchar_t dev_id_page[SCMD_MAX_INQUIRY_PAGE83_SIZE]; 7239 int fail = 0; 7240 ddi_devid_t devid; 7241 char *guid = NULL; 7242 int ret; 7243 7244 ASSERT(icmd != NULL && fpkt != NULL); 7245 7246 pptr = icmd->ipkt_port; 7247 ptgt = icmd->ipkt_tgt; 7248 plun = icmd->ipkt_lun; 7249 7250 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 7251 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_7); 7252 7253 FCP_CP_IN(fpkt->pkt_data, dev_id_page, fpkt->pkt_data_acc, 7254 SCMD_MAX_INQUIRY_PAGE83_SIZE); 7255 7256 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7257 fcp_trace, FCP_BUF_LEVEL_5, 0, 7258 "fcp_handle_page83: port=%d, tgt D_ID=0x%x, " 7259 "dtype=0x%x, lun num=%x", 7260 pptr->port_instance, ptgt->tgt_d_id, 7261 dev_id_page[0], plun->lun_num); 7262 7263 ret = ddi_devid_scsi_encode( 7264 DEVID_SCSI_ENCODE_VERSION_LATEST, 7265 NULL, /* driver name */ 7266 (unsigned char *) &plun->lun_inq, /* standard inquiry */ 7267 sizeof (plun->lun_inq), /* size of standard inquiry */ 7268 NULL, /* page 80 data */ 7269 0, /* page 80 len */ 7270 dev_id_page, /* page 83 data */ 7271 SCMD_MAX_INQUIRY_PAGE83_SIZE, /* page 83 data len */ 7272 &devid); 7273 7274 if (ret == DDI_SUCCESS) { 7275 7276 guid = ddi_devid_to_guid(devid); 7277 7278 if (guid) { 7279 /* 7280 * Check our current guid. If it's non null 7281 * and it has changed, we need to copy it into 7282 * lun_old_guid since we might still need it. 7283 */ 7284 if (plun->lun_guid && 7285 strcmp(guid, plun->lun_guid)) { 7286 unsigned int len; 7287 7288 /* 7289 * If the guid of the LUN changes, 7290 * reconfiguration should be triggered 7291 * to reflect the changes. 7292 * i.e. we should offline the LUN with 7293 * the old guid, and online the LUN with 7294 * the new guid. 7295 */ 7296 plun->lun_state |= FCP_LUN_CHANGED; 7297 7298 if (plun->lun_old_guid) { 7299 kmem_free(plun->lun_old_guid, 7300 plun->lun_old_guid_size); 7301 } 7302 7303 len = plun->lun_guid_size; 7304 plun->lun_old_guid_size = len; 7305 7306 plun->lun_old_guid = kmem_zalloc(len, 7307 KM_NOSLEEP); 7308 7309 if (plun->lun_old_guid) { 7310 /* 7311 * The alloc was successful then 7312 * let's do the copy. 7313 */ 7314 bcopy(plun->lun_guid, 7315 plun->lun_old_guid, len); 7316 } else { 7317 fail = 1; 7318 plun->lun_old_guid_size = 0; 7319 } 7320 } 7321 if (!fail) { 7322 if (fcp_copy_guid_2_lun_block( 7323 plun, guid)) { 7324 fail = 1; 7325 } 7326 } 7327 ddi_devid_free_guid(guid); 7328 7329 } else { 7330 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7331 fcp_trace, FCP_BUF_LEVEL_2, 0, 7332 "fcp_handle_page83: unable to create " 7333 "GUID"); 7334 7335 /* couldn't create good guid from devid */ 7336 fail = 1; 7337 } 7338 ddi_devid_free(devid); 7339 7340 } else if (ret == DDI_NOT_WELL_FORMED) { 7341 /* NULL filled data for page 83 */ 7342 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7343 fcp_trace, FCP_BUF_LEVEL_2, 0, 7344 "fcp_handle_page83: retry GUID"); 7345 7346 icmd->ipkt_retries = 0; 7347 fcp_retry_scsi_cmd(fpkt); 7348 return; 7349 } else { 7350 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7351 fcp_trace, FCP_BUF_LEVEL_2, 0, 7352 "fcp_handle_page83: bad ddi_devid_scsi_encode %x", 7353 ret); 7354 /* 7355 * Since the page83 validation 7356 * introduced late, we are being 7357 * tolerant to the existing devices 7358 * that already found to be working 7359 * under mpxio, like A5200's SES device, 7360 * its page83 response will not be standard-compliant, 7361 * but we still want it to be enumerated under mpxio. 7362 */ 7363 if (fcp_symmetric_device_probe(plun) != 0) { 7364 fail = 1; 7365 } 7366 } 7367 7368 } else { 7369 /* bad packet state */ 7370 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_8); 7371 7372 /* 7373 * For some special devices (A5K SES and Daktari's SES devices), 7374 * they should be enumerated under mpxio 7375 * or "luxadm dis" will fail 7376 */ 7377 if (ignore_page83_data) { 7378 fail = 0; 7379 } else { 7380 fail = 1; 7381 } 7382 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7383 fcp_trace, FCP_BUF_LEVEL_2, 0, 7384 "!Devid page cmd failed. " 7385 "fpkt_state: %x fpkt_reason: %x", 7386 "ignore_page83: %d", 7387 fpkt->pkt_state, fpkt->pkt_reason, 7388 ignore_page83_data); 7389 } 7390 7391 mutex_enter(&pptr->port_mutex); 7392 mutex_enter(&plun->lun_mutex); 7393 /* 7394 * If lun_cip is not NULL, then we needn't update lun_mpxio to avoid 7395 * mismatch between lun_cip and lun_mpxio. 7396 */ 7397 if (plun->lun_cip == NULL) { 7398 /* 7399 * If we don't have a guid for this lun it's because we were 7400 * unable to glean one from the page 83 response. Set the 7401 * control flag to 0 here to make sure that we don't attempt to 7402 * enumerate it under mpxio. 7403 */ 7404 if (fail || pptr->port_mpxio == 0) { 7405 plun->lun_mpxio = 0; 7406 } else { 7407 plun->lun_mpxio = 1; 7408 } 7409 } 7410 mutex_exit(&plun->lun_mutex); 7411 mutex_exit(&pptr->port_mutex); 7412 7413 mutex_enter(&ptgt->tgt_mutex); 7414 plun->lun_state &= 7415 ~(FCP_LUN_OFFLINE | FCP_LUN_MARK | FCP_LUN_BUSY); 7416 mutex_exit(&ptgt->tgt_mutex); 7417 7418 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7419 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7420 7421 fcp_icmd_free(pptr, icmd); 7422 } 7423 7424 /* 7425 * Function: fcp_handle_inquiry 7426 * 7427 * Description: Called by fcp_scsi_callback to handle the response to an 7428 * INQUIRY request. 7429 * 7430 * Argument: *fpkt FC packet used to convey the command. 7431 * *icmd Original fcp_ipkt structure. 7432 * 7433 * Return Value: None 7434 */ 7435 static void 7436 fcp_handle_inquiry(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7437 { 7438 struct fcp_port *pptr; 7439 struct fcp_lun *plun; 7440 struct fcp_tgt *ptgt; 7441 uchar_t dtype; 7442 uchar_t pqual; 7443 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7444 7445 ASSERT(icmd != NULL && fpkt != NULL); 7446 7447 pptr = icmd->ipkt_port; 7448 ptgt = icmd->ipkt_tgt; 7449 plun = icmd->ipkt_lun; 7450 7451 FCP_CP_IN(fpkt->pkt_data, &plun->lun_inq, fpkt->pkt_data_acc, 7452 sizeof (struct scsi_inquiry)); 7453 7454 dtype = plun->lun_inq.inq_dtype & DTYPE_MASK; 7455 pqual = plun->lun_inq.inq_dtype >> 5; 7456 7457 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7458 fcp_trace, FCP_BUF_LEVEL_5, 0, 7459 "fcp_handle_inquiry: port=%d, tgt D_ID=0x%x, lun=0x%x, " 7460 "dtype=0x%x pqual: 0x%x", pptr->port_instance, ptgt->tgt_d_id, 7461 plun->lun_num, dtype, pqual); 7462 7463 if (pqual != 0) { 7464 /* 7465 * Non-zero peripheral qualifier 7466 */ 7467 fcp_log(CE_CONT, pptr->port_dip, 7468 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7469 "Device type=0x%x Peripheral qual=0x%x\n", 7470 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7471 7472 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7473 fcp_trace, FCP_BUF_LEVEL_5, 0, 7474 "!Target 0x%x lun 0x%x: Nonzero peripheral qualifier: " 7475 "Device type=0x%x Peripheral qual=0x%x\n", 7476 ptgt->tgt_d_id, plun->lun_num, dtype, pqual); 7477 7478 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_3); 7479 7480 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7481 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7482 fcp_icmd_free(pptr, icmd); 7483 return; 7484 } 7485 7486 /* 7487 * If the device is already initialized, check the dtype 7488 * for a change. If it has changed then update the flags 7489 * so the create_luns will offline the old device and 7490 * create the new device. Refer to bug: 4764752 7491 */ 7492 if ((plun->lun_state & FCP_LUN_INIT) && dtype != plun->lun_type) { 7493 plun->lun_state |= FCP_LUN_CHANGED; 7494 } 7495 plun->lun_type = plun->lun_inq.inq_dtype; 7496 7497 /* 7498 * This code is setting/initializing the throttling in the FCA 7499 * driver. 7500 */ 7501 mutex_enter(&pptr->port_mutex); 7502 if (!pptr->port_notify) { 7503 if (bcmp(plun->lun_inq.inq_pid, pid, strlen(pid)) == 0) { 7504 uint32_t cmd = 0; 7505 cmd = ((cmd & 0xFF | FC_NOTIFY_THROTTLE) | 7506 ((cmd & 0xFFFFFF00 >> 8) | 7507 FCP_SVE_THROTTLE << 8)); 7508 pptr->port_notify = 1; 7509 mutex_exit(&pptr->port_mutex); 7510 (void) fc_ulp_port_notify(pptr->port_fp_handle, cmd); 7511 mutex_enter(&pptr->port_mutex); 7512 } 7513 } 7514 7515 if (FCP_TGT_STATE_CHANGED(ptgt, icmd)) { 7516 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7517 fcp_trace, FCP_BUF_LEVEL_2, 0, 7518 "fcp_handle_inquiry,1:state change occured" 7519 " for D_ID=0x%x", ptgt->tgt_d_id); 7520 mutex_exit(&pptr->port_mutex); 7521 7522 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_5); 7523 (void) fcp_call_finish_init(pptr, ptgt, 7524 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7525 icmd->ipkt_cause); 7526 fcp_icmd_free(pptr, icmd); 7527 return; 7528 } 7529 ASSERT((ptgt->tgt_state & FCP_TGT_MARK) == 0); 7530 mutex_exit(&pptr->port_mutex); 7531 7532 /* Retrieve the rscn count (if a valid one exists) */ 7533 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7534 rscn_count = ((fc_ulp_rscn_info_t *) 7535 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))->ulp_rscn_count; 7536 } else { 7537 rscn_count = FC_INVALID_RSCN_COUNT; 7538 } 7539 7540 if (fcp_send_scsi(plun, SCMD_INQUIRY_PAGE83, 7541 SCMD_MAX_INQUIRY_PAGE83_SIZE, 7542 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7543 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7544 fcp_log(CE_WARN, NULL, "!failed to send page 83"); 7545 FCP_LUN_TRACE(plun, FCP_LUN_TRACE_6); 7546 (void) fcp_call_finish_init(pptr, ptgt, 7547 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7548 icmd->ipkt_cause); 7549 } 7550 7551 /* 7552 * Read Inquiry VPD Page 0x83 to uniquely 7553 * identify this logical unit. 7554 */ 7555 fcp_icmd_free(pptr, icmd); 7556 } 7557 7558 /* 7559 * Function: fcp_handle_reportlun 7560 * 7561 * Description: Called by fcp_scsi_callback to handle the response to a 7562 * REPORT_LUN request. 7563 * 7564 * Argument: *fpkt FC packet used to convey the command. 7565 * *icmd Original fcp_ipkt structure. 7566 * 7567 * Return Value: None 7568 */ 7569 static void 7570 fcp_handle_reportlun(fc_packet_t *fpkt, struct fcp_ipkt *icmd) 7571 { 7572 int i; 7573 int nluns_claimed; 7574 int nluns_bufmax; 7575 int len; 7576 uint16_t lun_num; 7577 uint32_t rscn_count = FC_INVALID_RSCN_COUNT; 7578 struct fcp_port *pptr; 7579 struct fcp_tgt *ptgt; 7580 struct fcp_lun *plun; 7581 struct fcp_reportlun_resp *report_lun; 7582 7583 pptr = icmd->ipkt_port; 7584 ptgt = icmd->ipkt_tgt; 7585 len = fpkt->pkt_datalen; 7586 7587 if ((len < FCP_LUN_HEADER) || 7588 ((report_lun = kmem_zalloc(len, KM_NOSLEEP)) == NULL)) { 7589 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7590 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7591 fcp_icmd_free(pptr, icmd); 7592 return; 7593 } 7594 7595 FCP_CP_IN(fpkt->pkt_data, report_lun, fpkt->pkt_data_acc, 7596 fpkt->pkt_datalen); 7597 7598 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7599 fcp_trace, FCP_BUF_LEVEL_5, 0, 7600 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x", 7601 pptr->port_instance, ptgt->tgt_d_id); 7602 7603 /* 7604 * Get the number of luns (which is supplied as LUNS * 8) the 7605 * device claims it has. 7606 */ 7607 nluns_claimed = BE_32(report_lun->num_lun) >> 3; 7608 7609 /* 7610 * Get the maximum number of luns the buffer submitted can hold. 7611 */ 7612 nluns_bufmax = (fpkt->pkt_datalen - FCP_LUN_HEADER) / FCP_LUN_SIZE; 7613 7614 /* 7615 * Due to limitations of certain hardware, we support only 16 bit LUNs 7616 */ 7617 if (nluns_claimed > FCP_MAX_LUNS_SUPPORTED) { 7618 kmem_free(report_lun, len); 7619 7620 fcp_log(CE_NOTE, pptr->port_dip, "!Can not support" 7621 " 0x%x number of LUNs for target=%x", nluns_claimed, 7622 ptgt->tgt_d_id); 7623 7624 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7625 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7626 fcp_icmd_free(pptr, icmd); 7627 return; 7628 } 7629 7630 /* 7631 * If there are more LUNs than we have allocated memory for, 7632 * allocate more space and send down yet another report lun if 7633 * the maximum number of attempts hasn't been reached. 7634 */ 7635 mutex_enter(&ptgt->tgt_mutex); 7636 7637 if ((nluns_claimed > nluns_bufmax) && 7638 (ptgt->tgt_report_lun_cnt < FCP_MAX_REPORTLUNS_ATTEMPTS)) { 7639 7640 struct fcp_lun *plun; 7641 7642 ptgt->tgt_report_lun_cnt++; 7643 plun = ptgt->tgt_lun; 7644 ASSERT(plun != NULL); 7645 mutex_exit(&ptgt->tgt_mutex); 7646 7647 kmem_free(report_lun, len); 7648 7649 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7650 fcp_trace, FCP_BUF_LEVEL_5, 0, 7651 "!Dynamically discovered %d LUNs for D_ID=%x", 7652 nluns_claimed, ptgt->tgt_d_id); 7653 7654 /* Retrieve the rscn count (if a valid one exists) */ 7655 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7656 rscn_count = ((fc_ulp_rscn_info_t *) 7657 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7658 ulp_rscn_count; 7659 } else { 7660 rscn_count = FC_INVALID_RSCN_COUNT; 7661 } 7662 7663 if (fcp_send_scsi(icmd->ipkt_lun, SCMD_REPORT_LUN, 7664 FCP_LUN_HEADER + (nluns_claimed * FCP_LUN_SIZE), 7665 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7666 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7667 (void) fcp_call_finish_init(pptr, ptgt, 7668 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7669 icmd->ipkt_cause); 7670 } 7671 7672 fcp_icmd_free(pptr, icmd); 7673 return; 7674 } 7675 7676 if (nluns_claimed > nluns_bufmax) { 7677 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7678 fcp_trace, FCP_BUF_LEVEL_5, 0, 7679 "Target=%x:%x:%x:%x:%x:%x:%x:%x" 7680 " Number of LUNs lost=%x", 7681 ptgt->tgt_port_wwn.raw_wwn[0], 7682 ptgt->tgt_port_wwn.raw_wwn[1], 7683 ptgt->tgt_port_wwn.raw_wwn[2], 7684 ptgt->tgt_port_wwn.raw_wwn[3], 7685 ptgt->tgt_port_wwn.raw_wwn[4], 7686 ptgt->tgt_port_wwn.raw_wwn[5], 7687 ptgt->tgt_port_wwn.raw_wwn[6], 7688 ptgt->tgt_port_wwn.raw_wwn[7], 7689 nluns_claimed - nluns_bufmax); 7690 7691 nluns_claimed = nluns_bufmax; 7692 } 7693 ptgt->tgt_lun_cnt = nluns_claimed; 7694 7695 /* 7696 * Identify missing LUNs and print warning messages 7697 */ 7698 for (plun = ptgt->tgt_lun; plun; plun = plun->lun_next) { 7699 int offline; 7700 int exists = 0; 7701 7702 offline = (plun->lun_state & FCP_LUN_OFFLINE) ? 1 : 0; 7703 7704 for (i = 0; i < nluns_claimed && exists == 0; i++) { 7705 uchar_t *lun_string; 7706 7707 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7708 7709 switch (lun_string[0] & 0xC0) { 7710 case FCP_LUN_ADDRESSING: 7711 case FCP_PD_ADDRESSING: 7712 case FCP_VOLUME_ADDRESSING: 7713 lun_num = ((lun_string[0] & 0x3F) << 8) | 7714 lun_string[1]; 7715 if (plun->lun_num == lun_num) { 7716 exists++; 7717 break; 7718 } 7719 break; 7720 7721 default: 7722 break; 7723 } 7724 } 7725 7726 if (!exists && !offline) { 7727 mutex_exit(&ptgt->tgt_mutex); 7728 7729 mutex_enter(&pptr->port_mutex); 7730 mutex_enter(&ptgt->tgt_mutex); 7731 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7732 /* 7733 * set disappear flag when device was connected 7734 */ 7735 if (!(plun->lun_state & 7736 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7737 plun->lun_state |= FCP_LUN_DISAPPEARED; 7738 } 7739 mutex_exit(&ptgt->tgt_mutex); 7740 mutex_exit(&pptr->port_mutex); 7741 if (!(plun->lun_state & 7742 FCP_LUN_DEVICE_NOT_CONNECTED)) { 7743 fcp_log(CE_NOTE, pptr->port_dip, 7744 "!Lun=%x for target=%x disappeared", 7745 plun->lun_num, ptgt->tgt_d_id); 7746 } 7747 mutex_enter(&ptgt->tgt_mutex); 7748 } else { 7749 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7750 fcp_trace, FCP_BUF_LEVEL_5, 0, 7751 "fcp_handle_reportlun,1: state change" 7752 " occured for D_ID=0x%x", ptgt->tgt_d_id); 7753 mutex_exit(&ptgt->tgt_mutex); 7754 mutex_exit(&pptr->port_mutex); 7755 kmem_free(report_lun, len); 7756 (void) fcp_call_finish_init(pptr, ptgt, 7757 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7758 icmd->ipkt_cause); 7759 fcp_icmd_free(pptr, icmd); 7760 return; 7761 } 7762 } else if (exists) { 7763 /* 7764 * clear FCP_LUN_DEVICE_NOT_CONNECTED when lun 0 7765 * actually exists in REPORT_LUN response 7766 */ 7767 if (plun->lun_state & FCP_LUN_DEVICE_NOT_CONNECTED) { 7768 plun->lun_state &= 7769 ~FCP_LUN_DEVICE_NOT_CONNECTED; 7770 } 7771 if (offline || plun->lun_num == 0) { 7772 if (plun->lun_state & FCP_LUN_DISAPPEARED) { 7773 plun->lun_state &= ~FCP_LUN_DISAPPEARED; 7774 mutex_exit(&ptgt->tgt_mutex); 7775 fcp_log(CE_NOTE, pptr->port_dip, 7776 "!Lun=%x for target=%x reappeared", 7777 plun->lun_num, ptgt->tgt_d_id); 7778 mutex_enter(&ptgt->tgt_mutex); 7779 } 7780 } 7781 } 7782 } 7783 7784 ptgt->tgt_tmp_cnt = nluns_claimed ? nluns_claimed : 1; 7785 mutex_exit(&ptgt->tgt_mutex); 7786 7787 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7788 fcp_trace, FCP_BUF_LEVEL_5, 0, 7789 "fcp_handle_reportlun: port=%d, tgt D_ID=0x%x, %d LUN(s)", 7790 pptr->port_instance, ptgt->tgt_d_id, nluns_claimed); 7791 7792 /* scan each lun */ 7793 for (i = 0; i < nluns_claimed; i++) { 7794 uchar_t *lun_string; 7795 7796 lun_string = (uchar_t *)&(report_lun->lun_string[i]); 7797 7798 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7799 fcp_trace, FCP_BUF_LEVEL_5, 0, 7800 "handle_reportlun: d_id=%x, LUN ind=%d, LUN=%d," 7801 " addr=0x%x", ptgt->tgt_d_id, i, lun_string[1], 7802 lun_string[0]); 7803 7804 switch (lun_string[0] & 0xC0) { 7805 case FCP_LUN_ADDRESSING: 7806 case FCP_PD_ADDRESSING: 7807 case FCP_VOLUME_ADDRESSING: 7808 lun_num = ((lun_string[0] & 0x3F) << 8) | lun_string[1]; 7809 7810 /* We will skip masked LUNs because of the blacklist. */ 7811 if (fcp_lun_blacklist != NULL) { 7812 mutex_enter(&ptgt->tgt_mutex); 7813 if (fcp_should_mask(&ptgt->tgt_port_wwn, 7814 lun_num) == TRUE) { 7815 ptgt->tgt_lun_cnt--; 7816 mutex_exit(&ptgt->tgt_mutex); 7817 break; 7818 } 7819 mutex_exit(&ptgt->tgt_mutex); 7820 } 7821 7822 /* see if this LUN is already allocated */ 7823 if ((plun = fcp_get_lun(ptgt, lun_num)) == NULL) { 7824 plun = fcp_alloc_lun(ptgt); 7825 if (plun == NULL) { 7826 fcp_log(CE_NOTE, pptr->port_dip, 7827 "!Lun allocation failed" 7828 " target=%x lun=%x", 7829 ptgt->tgt_d_id, lun_num); 7830 break; 7831 } 7832 } 7833 7834 mutex_enter(&plun->lun_tgt->tgt_mutex); 7835 /* convert to LUN */ 7836 plun->lun_addr.ent_addr_0 = 7837 BE_16(*(uint16_t *)&(lun_string[0])); 7838 plun->lun_addr.ent_addr_1 = 7839 BE_16(*(uint16_t *)&(lun_string[2])); 7840 plun->lun_addr.ent_addr_2 = 7841 BE_16(*(uint16_t *)&(lun_string[4])); 7842 plun->lun_addr.ent_addr_3 = 7843 BE_16(*(uint16_t *)&(lun_string[6])); 7844 7845 plun->lun_num = lun_num; 7846 plun->lun_state |= FCP_LUN_BUSY | FCP_LUN_MARK; 7847 plun->lun_state &= ~FCP_LUN_OFFLINE; 7848 mutex_exit(&plun->lun_tgt->tgt_mutex); 7849 7850 /* Retrieve the rscn count (if a valid one exists) */ 7851 if (icmd->ipkt_fpkt->pkt_ulp_rscn_infop != NULL) { 7852 rscn_count = ((fc_ulp_rscn_info_t *) 7853 (icmd->ipkt_fpkt->pkt_ulp_rscn_infop))-> 7854 ulp_rscn_count; 7855 } else { 7856 rscn_count = FC_INVALID_RSCN_COUNT; 7857 } 7858 7859 if (fcp_send_scsi(plun, SCMD_INQUIRY, SUN_INQSIZE, 7860 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 7861 icmd->ipkt_cause, rscn_count) != DDI_SUCCESS) { 7862 mutex_enter(&pptr->port_mutex); 7863 mutex_enter(&plun->lun_tgt->tgt_mutex); 7864 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 7865 fcp_log(CE_NOTE, pptr->port_dip, 7866 "!failed to send INQUIRY" 7867 " target=%x lun=%x", 7868 ptgt->tgt_d_id, plun->lun_num); 7869 } else { 7870 FCP_TRACE(fcp_logq, 7871 pptr->port_instbuf, fcp_trace, 7872 FCP_BUF_LEVEL_5, 0, 7873 "fcp_handle_reportlun,2: state" 7874 " change occured for D_ID=0x%x", 7875 ptgt->tgt_d_id); 7876 } 7877 mutex_exit(&plun->lun_tgt->tgt_mutex); 7878 mutex_exit(&pptr->port_mutex); 7879 } else { 7880 continue; 7881 } 7882 break; 7883 7884 default: 7885 fcp_log(CE_WARN, NULL, 7886 "!Unsupported LUN Addressing method %x " 7887 "in response to REPORT_LUN", lun_string[0]); 7888 break; 7889 } 7890 7891 /* 7892 * each time through this loop we should decrement 7893 * the tmp_cnt by one -- since we go through this loop 7894 * one time for each LUN, the tmp_cnt should never be <=0 7895 */ 7896 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7897 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7898 } 7899 7900 if (i == 0) { 7901 fcp_log(CE_WARN, pptr->port_dip, 7902 "!FCP: target=%x reported NO Luns", ptgt->tgt_d_id); 7903 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 7904 icmd->ipkt_change_cnt, icmd->ipkt_cause); 7905 } 7906 7907 kmem_free(report_lun, len); 7908 fcp_icmd_free(pptr, icmd); 7909 } 7910 7911 7912 /* 7913 * called internally to return a LUN given a target and a LUN number 7914 */ 7915 static struct fcp_lun * 7916 fcp_get_lun(struct fcp_tgt *ptgt, uint16_t lun_num) 7917 { 7918 struct fcp_lun *plun; 7919 7920 mutex_enter(&ptgt->tgt_mutex); 7921 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 7922 if (plun->lun_num == lun_num) { 7923 mutex_exit(&ptgt->tgt_mutex); 7924 return (plun); 7925 } 7926 } 7927 mutex_exit(&ptgt->tgt_mutex); 7928 7929 return (NULL); 7930 } 7931 7932 7933 /* 7934 * handle finishing one target for fcp_finish_init 7935 * 7936 * return true (non-zero) if we want finish_init to continue with the 7937 * next target 7938 * 7939 * called with the port mutex held 7940 */ 7941 /*ARGSUSED*/ 7942 static int 7943 fcp_finish_tgt(struct fcp_port *pptr, struct fcp_tgt *ptgt, 7944 int link_cnt, int tgt_cnt, int cause) 7945 { 7946 int rval = 1; 7947 ASSERT(pptr != NULL); 7948 ASSERT(ptgt != NULL); 7949 7950 FCP_TRACE(fcp_logq, pptr->port_instbuf, 7951 fcp_trace, FCP_BUF_LEVEL_5, 0, 7952 "finish_tgt: D_ID/state = 0x%x/0x%x", ptgt->tgt_d_id, 7953 ptgt->tgt_state); 7954 7955 ASSERT(mutex_owned(&pptr->port_mutex)); 7956 7957 if ((pptr->port_link_cnt != link_cnt) || 7958 (tgt_cnt && ptgt->tgt_change_cnt != tgt_cnt)) { 7959 /* 7960 * oh oh -- another link reset or target change 7961 * must have occurred while we are in here 7962 */ 7963 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_23); 7964 7965 return (0); 7966 } else { 7967 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_24); 7968 } 7969 7970 mutex_enter(&ptgt->tgt_mutex); 7971 7972 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 7973 /* 7974 * tgt is not offline -- is it marked (i.e. needs 7975 * to be offlined) ?? 7976 */ 7977 if (ptgt->tgt_state & FCP_TGT_MARK) { 7978 /* 7979 * this target not offline *and* 7980 * marked 7981 */ 7982 ptgt->tgt_state &= ~FCP_TGT_MARK; 7983 rval = fcp_offline_target(pptr, ptgt, link_cnt, 7984 tgt_cnt, 0, 0); 7985 } else { 7986 ptgt->tgt_state &= ~FCP_TGT_BUSY; 7987 7988 /* create the LUNs */ 7989 if (ptgt->tgt_node_state != FCP_TGT_NODE_ON_DEMAND) { 7990 ptgt->tgt_node_state = FCP_TGT_NODE_PRESENT; 7991 fcp_create_luns(ptgt, link_cnt, tgt_cnt, 7992 cause); 7993 ptgt->tgt_device_created = 1; 7994 } else { 7995 fcp_update_tgt_state(ptgt, FCP_RESET, 7996 FCP_LUN_BUSY); 7997 } 7998 } 7999 } 8000 8001 mutex_exit(&ptgt->tgt_mutex); 8002 8003 return (rval); 8004 } 8005 8006 8007 /* 8008 * this routine is called to finish port initialization 8009 * 8010 * Each port has a "temp" counter -- when a state change happens (e.g. 8011 * port online), the temp count is set to the number of devices in the map. 8012 * Then, as each device gets "discovered", the temp counter is decremented 8013 * by one. When this count reaches zero we know that all of the devices 8014 * in the map have been discovered (or an error has occurred), so we can 8015 * then finish initialization -- which is done by this routine (well, this 8016 * and fcp-finish_tgt()) 8017 * 8018 * acquires and releases the global mutex 8019 * 8020 * called with the port mutex owned 8021 */ 8022 static void 8023 fcp_finish_init(struct fcp_port *pptr) 8024 { 8025 #ifdef DEBUG 8026 bzero(pptr->port_finish_stack, sizeof (pptr->port_finish_stack)); 8027 pptr->port_finish_depth = getpcstack(pptr->port_finish_stack, 8028 FCP_STACK_DEPTH); 8029 #endif /* DEBUG */ 8030 8031 ASSERT(mutex_owned(&pptr->port_mutex)); 8032 8033 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8034 fcp_trace, FCP_BUF_LEVEL_2, 0, "finish_init:" 8035 " entering; ipkt count=%d", pptr->port_ipkt_cnt); 8036 8037 if ((pptr->port_state & FCP_STATE_ONLINING) && 8038 !(pptr->port_state & (FCP_STATE_SUSPENDED | 8039 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 8040 pptr->port_state &= ~FCP_STATE_ONLINING; 8041 pptr->port_state |= FCP_STATE_ONLINE; 8042 } 8043 8044 /* Wake up threads waiting on config done */ 8045 cv_broadcast(&pptr->port_config_cv); 8046 } 8047 8048 8049 /* 8050 * called from fcp_finish_init to create the LUNs for a target 8051 * 8052 * called with the port mutex owned 8053 */ 8054 static void 8055 fcp_create_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, int cause) 8056 { 8057 struct fcp_lun *plun; 8058 struct fcp_port *pptr; 8059 child_info_t *cip = NULL; 8060 8061 ASSERT(ptgt != NULL); 8062 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8063 8064 pptr = ptgt->tgt_port; 8065 8066 ASSERT(pptr != NULL); 8067 8068 /* scan all LUNs for this target */ 8069 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8070 if (plun->lun_state & FCP_LUN_OFFLINE) { 8071 continue; 8072 } 8073 8074 if (plun->lun_state & FCP_LUN_MARK) { 8075 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8076 fcp_trace, FCP_BUF_LEVEL_2, 0, 8077 "fcp_create_luns: offlining marked LUN!"); 8078 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, 0); 8079 continue; 8080 } 8081 8082 plun->lun_state &= ~FCP_LUN_BUSY; 8083 8084 /* 8085 * There are conditions in which FCP_LUN_INIT flag is cleared 8086 * but we have a valid plun->lun_cip. To cover this case also 8087 * CLEAR_BUSY whenever we have a valid lun_cip. 8088 */ 8089 if (plun->lun_mpxio && plun->lun_cip && 8090 (!fcp_pass_to_hp(pptr, plun, plun->lun_cip, 8091 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8092 0, 0))) { 8093 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8094 fcp_trace, FCP_BUF_LEVEL_2, 0, 8095 "fcp_create_luns: enable lun %p failed!", 8096 plun); 8097 } 8098 8099 if (plun->lun_state & FCP_LUN_INIT && 8100 !(plun->lun_state & FCP_LUN_CHANGED)) { 8101 continue; 8102 } 8103 8104 if (cause == FCP_CAUSE_USER_CREATE) { 8105 continue; 8106 } 8107 8108 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8109 fcp_trace, FCP_BUF_LEVEL_6, 0, 8110 "create_luns: passing ONLINE elem to HP thread"); 8111 8112 /* 8113 * If lun has changed, prepare for offlining the old path. 8114 * Do not offline the old path right now, since it may be 8115 * still opened. 8116 */ 8117 if (plun->lun_cip && (plun->lun_state & FCP_LUN_CHANGED)) { 8118 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8119 } 8120 8121 /* pass an ONLINE element to the hotplug thread */ 8122 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8123 link_cnt, tgt_cnt, NDI_ONLINE_ATTACH, 0)) { 8124 8125 /* 8126 * We can not synchronous attach (i.e pass 8127 * NDI_ONLINE_ATTACH) here as we might be 8128 * coming from an interrupt or callback 8129 * thread. 8130 */ 8131 if (!fcp_pass_to_hp(pptr, plun, cip, FCP_ONLINE, 8132 link_cnt, tgt_cnt, 0, 0)) { 8133 fcp_log(CE_CONT, pptr->port_dip, 8134 "Can not ONLINE LUN; D_ID=%x, LUN=%x\n", 8135 plun->lun_tgt->tgt_d_id, plun->lun_num); 8136 } 8137 } 8138 } 8139 } 8140 8141 8142 /* 8143 * function to online/offline devices 8144 */ 8145 static int 8146 fcp_trigger_lun(struct fcp_lun *plun, child_info_t *cip, int old_mpxio, 8147 int online, int lcount, int tcount, int flags) 8148 { 8149 int rval = NDI_FAILURE; 8150 int circ; 8151 child_info_t *ccip; 8152 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8153 int is_mpxio = pptr->port_mpxio; 8154 dev_info_t *cdip, *pdip; 8155 char *devname; 8156 8157 if ((old_mpxio != 0) && (plun->lun_mpxio != old_mpxio)) { 8158 /* 8159 * When this event gets serviced, lun_cip and lun_mpxio 8160 * has changed, so it should be invalidated now. 8161 */ 8162 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 8163 FCP_BUF_LEVEL_2, 0, "fcp_trigger_lun: lun_mpxio changed: " 8164 "plun: %p, cip: %p, what:%d", plun, cip, online); 8165 return (rval); 8166 } 8167 8168 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8169 fcp_trace, FCP_BUF_LEVEL_2, 0, 8170 "fcp_trigger_lun: plun=%p target=%x lun=%d cip=%p what=%x " 8171 "flags=%x mpxio=%x\n", 8172 plun, LUN_TGT->tgt_d_id, plun->lun_num, cip, online, flags, 8173 plun->lun_mpxio); 8174 8175 /* 8176 * lun_mpxio needs checking here because we can end up in a race 8177 * condition where this task has been dispatched while lun_mpxio is 8178 * set, but an earlier FCP_ONLINE task for the same LUN tried to 8179 * enable MPXIO for the LUN, but was unable to, and hence cleared 8180 * the flag. We rely on the serialization of the tasks here. We return 8181 * NDI_SUCCESS so any callers continue without reporting spurious 8182 * errors, and the still think we're an MPXIO LUN. 8183 */ 8184 8185 if (online == FCP_MPXIO_PATH_CLEAR_BUSY || 8186 online == FCP_MPXIO_PATH_SET_BUSY) { 8187 if (plun->lun_mpxio) { 8188 rval = fcp_update_mpxio_path(plun, cip, online); 8189 } else { 8190 rval = NDI_SUCCESS; 8191 } 8192 return (rval); 8193 } 8194 8195 /* 8196 * Explicit devfs_clean() due to ndi_devi_offline() not 8197 * executing devfs_clean() if parent lock is held. 8198 */ 8199 ASSERT(!servicing_interrupt()); 8200 if (online == FCP_OFFLINE) { 8201 if (plun->lun_mpxio == 0) { 8202 if (plun->lun_cip == cip) { 8203 cdip = DIP(plun->lun_cip); 8204 } else { 8205 cdip = DIP(cip); 8206 } 8207 } else if ((plun->lun_cip == cip) && plun->lun_cip) { 8208 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8209 } else if ((plun->lun_cip != cip) && cip) { 8210 /* 8211 * This means a DTYPE/GUID change, we shall get the 8212 * dip of the old cip instead of the current lun_cip. 8213 */ 8214 cdip = mdi_pi_get_client(PIP(cip)); 8215 } 8216 if (cdip) { 8217 if (i_ddi_devi_attached(cdip)) { 8218 pdip = ddi_get_parent(cdip); 8219 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP); 8220 ndi_devi_enter(pdip, &circ); 8221 (void) ddi_deviname(cdip, devname); 8222 ndi_devi_exit(pdip, circ); 8223 /* 8224 * Release parent lock before calling 8225 * devfs_clean(). 8226 */ 8227 rval = devfs_clean(pdip, devname + 1, 8228 DV_CLEAN_FORCE); 8229 kmem_free(devname, MAXNAMELEN + 1); 8230 /* 8231 * Return if devfs_clean() fails for 8232 * non-MPXIO case. 8233 * For MPXIO case, another path could be 8234 * offlined. 8235 */ 8236 if (rval && plun->lun_mpxio == 0) { 8237 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8238 fcp_trace, FCP_BUF_LEVEL_3, 0, 8239 "fcp_trigger_lun: devfs_clean " 8240 "failed rval=%x dip=%p", 8241 rval, pdip); 8242 return (NDI_FAILURE); 8243 } 8244 } 8245 } 8246 } 8247 8248 if (fc_ulp_busy_port(pptr->port_fp_handle) != 0) { 8249 return (NDI_FAILURE); 8250 } 8251 8252 if (is_mpxio) { 8253 mdi_devi_enter(pptr->port_dip, &circ); 8254 } else { 8255 ndi_devi_enter(pptr->port_dip, &circ); 8256 } 8257 8258 mutex_enter(&pptr->port_mutex); 8259 mutex_enter(&plun->lun_mutex); 8260 8261 if (online == FCP_ONLINE) { 8262 ccip = fcp_get_cip(plun, cip, lcount, tcount); 8263 if (ccip == NULL) { 8264 goto fail; 8265 } 8266 } else { 8267 if (fcp_is_child_present(plun, cip) != FC_SUCCESS) { 8268 goto fail; 8269 } 8270 ccip = cip; 8271 } 8272 8273 if (online == FCP_ONLINE) { 8274 rval = fcp_online_child(plun, ccip, lcount, tcount, flags, 8275 &circ); 8276 fc_ulp_log_device_event(pptr->port_fp_handle, 8277 FC_ULP_DEVICE_ONLINE); 8278 } else { 8279 rval = fcp_offline_child(plun, ccip, lcount, tcount, flags, 8280 &circ); 8281 fc_ulp_log_device_event(pptr->port_fp_handle, 8282 FC_ULP_DEVICE_OFFLINE); 8283 } 8284 8285 fail: mutex_exit(&plun->lun_mutex); 8286 mutex_exit(&pptr->port_mutex); 8287 8288 if (is_mpxio) { 8289 mdi_devi_exit(pptr->port_dip, circ); 8290 } else { 8291 ndi_devi_exit(pptr->port_dip, circ); 8292 } 8293 8294 fc_ulp_idle_port(pptr->port_fp_handle); 8295 8296 return (rval); 8297 } 8298 8299 8300 /* 8301 * take a target offline by taking all of its LUNs offline 8302 */ 8303 /*ARGSUSED*/ 8304 static int 8305 fcp_offline_target(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8306 int link_cnt, int tgt_cnt, int nowait, int flags) 8307 { 8308 struct fcp_tgt_elem *elem; 8309 8310 ASSERT(mutex_owned(&pptr->port_mutex)); 8311 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8312 8313 ASSERT(!(ptgt->tgt_state & FCP_TGT_OFFLINE)); 8314 8315 if (link_cnt != pptr->port_link_cnt || (tgt_cnt && tgt_cnt != 8316 ptgt->tgt_change_cnt)) { 8317 mutex_exit(&ptgt->tgt_mutex); 8318 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_25); 8319 mutex_enter(&ptgt->tgt_mutex); 8320 8321 return (0); 8322 } 8323 8324 ptgt->tgt_pd_handle = NULL; 8325 mutex_exit(&ptgt->tgt_mutex); 8326 FCP_TGT_TRACE(ptgt, tgt_cnt, FCP_TGT_TRACE_26); 8327 mutex_enter(&ptgt->tgt_mutex); 8328 8329 tgt_cnt = tgt_cnt ? tgt_cnt : ptgt->tgt_change_cnt; 8330 8331 if (ptgt->tgt_tcap && 8332 (elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8333 elem->flags = flags; 8334 elem->time = fcp_watchdog_time; 8335 if (nowait == 0) { 8336 elem->time += fcp_offline_delay; 8337 } 8338 elem->ptgt = ptgt; 8339 elem->link_cnt = link_cnt; 8340 elem->tgt_cnt = tgt_cnt; 8341 elem->next = pptr->port_offline_tgts; 8342 pptr->port_offline_tgts = elem; 8343 } else { 8344 fcp_offline_target_now(pptr, ptgt, link_cnt, tgt_cnt, flags); 8345 } 8346 8347 return (1); 8348 } 8349 8350 8351 static void 8352 fcp_offline_target_now(struct fcp_port *pptr, struct fcp_tgt *ptgt, 8353 int link_cnt, int tgt_cnt, int flags) 8354 { 8355 ASSERT(mutex_owned(&pptr->port_mutex)); 8356 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8357 8358 fc_ulp_enable_relogin(pptr->port_fp_handle, &ptgt->tgt_port_wwn); 8359 ptgt->tgt_state = FCP_TGT_OFFLINE; 8360 ptgt->tgt_pd_handle = NULL; 8361 fcp_offline_tgt_luns(ptgt, link_cnt, tgt_cnt, flags); 8362 } 8363 8364 8365 static void 8366 fcp_offline_tgt_luns(struct fcp_tgt *ptgt, int link_cnt, int tgt_cnt, 8367 int flags) 8368 { 8369 struct fcp_lun *plun; 8370 8371 ASSERT(mutex_owned(&ptgt->tgt_port->port_mutex)); 8372 ASSERT(mutex_owned(&ptgt->tgt_mutex)); 8373 8374 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 8375 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 8376 fcp_offline_lun(plun, link_cnt, tgt_cnt, 1, flags); 8377 } 8378 } 8379 } 8380 8381 8382 /* 8383 * take a LUN offline 8384 * 8385 * enters and leaves with the target mutex held, releasing it in the process 8386 * 8387 * allocates memory in non-sleep mode 8388 */ 8389 static void 8390 fcp_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8391 int nowait, int flags) 8392 { 8393 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 8394 struct fcp_lun_elem *elem; 8395 8396 ASSERT(plun != NULL); 8397 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8398 8399 if (nowait) { 8400 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8401 return; 8402 } 8403 8404 if ((elem = kmem_zalloc(sizeof (*elem), KM_NOSLEEP)) != NULL) { 8405 elem->flags = flags; 8406 elem->time = fcp_watchdog_time; 8407 if (nowait == 0) { 8408 elem->time += fcp_offline_delay; 8409 } 8410 elem->plun = plun; 8411 elem->link_cnt = link_cnt; 8412 elem->tgt_cnt = plun->lun_tgt->tgt_change_cnt; 8413 elem->next = pptr->port_offline_luns; 8414 pptr->port_offline_luns = elem; 8415 } else { 8416 fcp_offline_lun_now(plun, link_cnt, tgt_cnt, flags); 8417 } 8418 } 8419 8420 8421 static void 8422 fcp_prepare_offline_lun(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 8423 { 8424 struct fcp_pkt *head = NULL; 8425 8426 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8427 8428 mutex_exit(&LUN_TGT->tgt_mutex); 8429 8430 head = fcp_scan_commands(plun); 8431 if (head != NULL) { 8432 fcp_abort_commands(head, LUN_PORT); 8433 } 8434 8435 mutex_enter(&LUN_TGT->tgt_mutex); 8436 8437 if (plun->lun_cip && plun->lun_mpxio) { 8438 /* 8439 * Intimate MPxIO lun busy is cleared 8440 */ 8441 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, 8442 FCP_MPXIO_PATH_CLEAR_BUSY, link_cnt, tgt_cnt, 8443 0, 0)) { 8444 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8445 "Can not ENABLE LUN; D_ID=%x, LUN=%x", 8446 LUN_TGT->tgt_d_id, plun->lun_num); 8447 } 8448 /* 8449 * Intimate MPxIO that the lun is now marked for offline 8450 */ 8451 mutex_exit(&LUN_TGT->tgt_mutex); 8452 (void) mdi_pi_disable_path(PIP(plun->lun_cip), DRIVER_DISABLE); 8453 mutex_enter(&LUN_TGT->tgt_mutex); 8454 } 8455 } 8456 8457 static void 8458 fcp_offline_lun_now(struct fcp_lun *plun, int link_cnt, int tgt_cnt, 8459 int flags) 8460 { 8461 ASSERT(mutex_owned(&LUN_TGT->tgt_mutex)); 8462 8463 mutex_exit(&LUN_TGT->tgt_mutex); 8464 fcp_update_offline_flags(plun); 8465 mutex_enter(&LUN_TGT->tgt_mutex); 8466 8467 fcp_prepare_offline_lun(plun, link_cnt, tgt_cnt); 8468 8469 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 8470 fcp_trace, FCP_BUF_LEVEL_4, 0, 8471 "offline_lun: passing OFFLINE elem to HP thread"); 8472 8473 if (plun->lun_cip) { 8474 fcp_log(CE_NOTE, LUN_PORT->port_dip, 8475 "!offlining lun=%x (trace=%x), target=%x (trace=%x)", 8476 plun->lun_num, plun->lun_trace, LUN_TGT->tgt_d_id, 8477 LUN_TGT->tgt_trace); 8478 8479 if (!fcp_pass_to_hp(LUN_PORT, plun, plun->lun_cip, FCP_OFFLINE, 8480 link_cnt, tgt_cnt, flags, 0)) { 8481 fcp_log(CE_CONT, LUN_PORT->port_dip, 8482 "Can not OFFLINE LUN; D_ID=%x, LUN=%x\n", 8483 LUN_TGT->tgt_d_id, plun->lun_num); 8484 } 8485 } 8486 } 8487 8488 static void 8489 fcp_scan_offline_luns(struct fcp_port *pptr) 8490 { 8491 struct fcp_lun_elem *elem; 8492 struct fcp_lun_elem *prev; 8493 struct fcp_lun_elem *next; 8494 8495 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8496 8497 prev = NULL; 8498 elem = pptr->port_offline_luns; 8499 while (elem) { 8500 next = elem->next; 8501 if (elem->time <= fcp_watchdog_time) { 8502 int changed = 1; 8503 struct fcp_tgt *ptgt = elem->plun->lun_tgt; 8504 8505 mutex_enter(&ptgt->tgt_mutex); 8506 if (pptr->port_link_cnt == elem->link_cnt && 8507 ptgt->tgt_change_cnt == elem->tgt_cnt) { 8508 changed = 0; 8509 } 8510 8511 if (!changed && 8512 !(elem->plun->lun_state & FCP_TGT_OFFLINE)) { 8513 fcp_offline_lun_now(elem->plun, 8514 elem->link_cnt, elem->tgt_cnt, elem->flags); 8515 } 8516 mutex_exit(&ptgt->tgt_mutex); 8517 8518 kmem_free(elem, sizeof (*elem)); 8519 8520 if (prev) { 8521 prev->next = next; 8522 } else { 8523 pptr->port_offline_luns = next; 8524 } 8525 } else { 8526 prev = elem; 8527 } 8528 elem = next; 8529 } 8530 } 8531 8532 8533 static void 8534 fcp_scan_offline_tgts(struct fcp_port *pptr) 8535 { 8536 struct fcp_tgt_elem *elem; 8537 struct fcp_tgt_elem *prev; 8538 struct fcp_tgt_elem *next; 8539 8540 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 8541 8542 prev = NULL; 8543 elem = pptr->port_offline_tgts; 8544 while (elem) { 8545 next = elem->next; 8546 if (elem->time <= fcp_watchdog_time) { 8547 int outdated = 1; 8548 struct fcp_tgt *ptgt = elem->ptgt; 8549 8550 mutex_enter(&ptgt->tgt_mutex); 8551 8552 if (ptgt->tgt_change_cnt == elem->tgt_cnt) { 8553 /* No change on tgt since elem was created. */ 8554 outdated = 0; 8555 } else if (ptgt->tgt_change_cnt == elem->tgt_cnt + 1 && 8556 pptr->port_link_cnt == elem->link_cnt + 1 && 8557 ptgt->tgt_statec_cause == FCP_CAUSE_LINK_DOWN) { 8558 /* 8559 * Exactly one thing happened to the target 8560 * inbetween: the local port went offline. 8561 * For fp the remote port is already gone so 8562 * it will not tell us again to offline the 8563 * target. We must offline it now. 8564 */ 8565 outdated = 0; 8566 } 8567 8568 if (!outdated && !(ptgt->tgt_state & 8569 FCP_TGT_OFFLINE)) { 8570 fcp_offline_target_now(pptr, 8571 ptgt, elem->link_cnt, elem->tgt_cnt, 8572 elem->flags); 8573 } 8574 8575 mutex_exit(&ptgt->tgt_mutex); 8576 8577 kmem_free(elem, sizeof (*elem)); 8578 8579 if (prev) { 8580 prev->next = next; 8581 } else { 8582 pptr->port_offline_tgts = next; 8583 } 8584 } else { 8585 prev = elem; 8586 } 8587 elem = next; 8588 } 8589 } 8590 8591 8592 static void 8593 fcp_update_offline_flags(struct fcp_lun *plun) 8594 { 8595 struct fcp_port *pptr = LUN_PORT; 8596 ASSERT(plun != NULL); 8597 8598 mutex_enter(&LUN_TGT->tgt_mutex); 8599 plun->lun_state |= FCP_LUN_OFFLINE; 8600 plun->lun_state &= ~(FCP_LUN_INIT | FCP_LUN_BUSY | FCP_LUN_MARK); 8601 8602 mutex_enter(&plun->lun_mutex); 8603 if (plun->lun_cip && plun->lun_state & FCP_SCSI_LUN_TGT_INIT) { 8604 dev_info_t *cdip = NULL; 8605 8606 mutex_exit(&LUN_TGT->tgt_mutex); 8607 8608 if (plun->lun_mpxio == 0) { 8609 cdip = DIP(plun->lun_cip); 8610 } else if (plun->lun_cip) { 8611 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 8612 } 8613 8614 mutex_exit(&plun->lun_mutex); 8615 if (cdip) { 8616 (void) ndi_event_retrieve_cookie( 8617 pptr->port_ndi_event_hdl, cdip, FCAL_REMOVE_EVENT, 8618 &fcp_remove_eid, NDI_EVENT_NOPASS); 8619 (void) ndi_event_run_callbacks( 8620 pptr->port_ndi_event_hdl, cdip, 8621 fcp_remove_eid, NULL); 8622 } 8623 } else { 8624 mutex_exit(&plun->lun_mutex); 8625 mutex_exit(&LUN_TGT->tgt_mutex); 8626 } 8627 } 8628 8629 8630 /* 8631 * Scan all of the command pkts for this port, moving pkts that 8632 * match our LUN onto our own list (headed by "head") 8633 */ 8634 static struct fcp_pkt * 8635 fcp_scan_commands(struct fcp_lun *plun) 8636 { 8637 struct fcp_port *pptr = LUN_PORT; 8638 8639 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8640 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8641 struct fcp_pkt *pcmd = NULL; /* the previous command */ 8642 8643 struct fcp_pkt *head = NULL; /* head of our list */ 8644 struct fcp_pkt *tail = NULL; /* tail of our list */ 8645 8646 int cmds_found = 0; 8647 8648 mutex_enter(&pptr->port_pkt_mutex); 8649 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 8650 struct fcp_lun *tlun = 8651 ADDR2LUN(&cmd->cmd_pkt->pkt_address); 8652 8653 ncmd = cmd->cmd_next; /* set next command */ 8654 8655 /* 8656 * if this pkt is for a different LUN or the 8657 * command is sent down, skip it. 8658 */ 8659 if (tlun != plun || cmd->cmd_state == FCP_PKT_ISSUED || 8660 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)) { 8661 pcmd = cmd; 8662 continue; 8663 } 8664 cmds_found++; 8665 if (pcmd != NULL) { 8666 ASSERT(pptr->port_pkt_head != cmd); 8667 pcmd->cmd_next = cmd->cmd_next; 8668 } else { 8669 ASSERT(cmd == pptr->port_pkt_head); 8670 pptr->port_pkt_head = cmd->cmd_next; 8671 } 8672 8673 if (cmd == pptr->port_pkt_tail) { 8674 pptr->port_pkt_tail = pcmd; 8675 if (pcmd) { 8676 pcmd->cmd_next = NULL; 8677 } 8678 } 8679 8680 if (head == NULL) { 8681 head = tail = cmd; 8682 } else { 8683 ASSERT(tail != NULL); 8684 8685 tail->cmd_next = cmd; 8686 tail = cmd; 8687 } 8688 cmd->cmd_next = NULL; 8689 } 8690 mutex_exit(&pptr->port_pkt_mutex); 8691 8692 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8693 fcp_trace, FCP_BUF_LEVEL_8, 0, 8694 "scan commands: %d cmd(s) found", cmds_found); 8695 8696 return (head); 8697 } 8698 8699 8700 /* 8701 * Abort all the commands in the command queue 8702 */ 8703 static void 8704 fcp_abort_commands(struct fcp_pkt *head, struct fcp_port *pptr) 8705 { 8706 struct fcp_pkt *cmd = NULL; /* pkt cmd ptr */ 8707 struct fcp_pkt *ncmd = NULL; /* next pkt ptr */ 8708 8709 ASSERT(mutex_owned(&pptr->port_mutex)); 8710 8711 /* scan through the pkts and invalid them */ 8712 for (cmd = head; cmd != NULL; cmd = ncmd) { 8713 struct scsi_pkt *pkt = cmd->cmd_pkt; 8714 8715 ncmd = cmd->cmd_next; 8716 ASSERT(pkt != NULL); 8717 8718 /* 8719 * The lun is going to be marked offline. Indicate 8720 * the target driver not to requeue or retry this command 8721 * as the device is going to be offlined pretty soon. 8722 */ 8723 pkt->pkt_reason = CMD_DEV_GONE; 8724 pkt->pkt_statistics = 0; 8725 pkt->pkt_state = 0; 8726 8727 /* reset cmd flags/state */ 8728 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 8729 cmd->cmd_state = FCP_PKT_IDLE; 8730 8731 /* 8732 * ensure we have a packet completion routine, 8733 * then call it. 8734 */ 8735 ASSERT(pkt->pkt_comp != NULL); 8736 8737 mutex_exit(&pptr->port_mutex); 8738 fcp_post_callback(cmd); 8739 mutex_enter(&pptr->port_mutex); 8740 } 8741 } 8742 8743 8744 /* 8745 * the pkt_comp callback for command packets 8746 */ 8747 static void 8748 fcp_cmd_callback(fc_packet_t *fpkt) 8749 { 8750 struct fcp_pkt *cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 8751 struct scsi_pkt *pkt = cmd->cmd_pkt; 8752 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8753 8754 ASSERT(cmd->cmd_state != FCP_PKT_IDLE); 8755 8756 if (cmd->cmd_state == FCP_PKT_IDLE) { 8757 cmn_err(CE_PANIC, "Packet already completed %p", 8758 (void *)cmd); 8759 } 8760 8761 /* 8762 * Watch thread should be freeing the packet, ignore the pkt. 8763 */ 8764 if (cmd->cmd_state == FCP_PKT_ABORTING) { 8765 fcp_log(CE_CONT, pptr->port_dip, 8766 "!FCP: Pkt completed while aborting\n"); 8767 return; 8768 } 8769 cmd->cmd_state = FCP_PKT_IDLE; 8770 8771 fcp_complete_pkt(fpkt); 8772 8773 #ifdef DEBUG 8774 mutex_enter(&pptr->port_pkt_mutex); 8775 pptr->port_npkts--; 8776 mutex_exit(&pptr->port_pkt_mutex); 8777 #endif /* DEBUG */ 8778 8779 fcp_post_callback(cmd); 8780 } 8781 8782 8783 static void 8784 fcp_complete_pkt(fc_packet_t *fpkt) 8785 { 8786 int error = 0; 8787 struct fcp_pkt *cmd = (struct fcp_pkt *) 8788 fpkt->pkt_ulp_private; 8789 struct scsi_pkt *pkt = cmd->cmd_pkt; 8790 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 8791 struct fcp_lun *plun; 8792 struct fcp_tgt *ptgt; 8793 struct fcp_rsp *rsp; 8794 struct scsi_address save; 8795 8796 #ifdef DEBUG 8797 save = pkt->pkt_address; 8798 #endif /* DEBUG */ 8799 8800 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 8801 8802 if (fpkt->pkt_state == FC_PKT_SUCCESS) { 8803 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8804 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 8805 sizeof (struct fcp_rsp)); 8806 } 8807 8808 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | 8809 STATE_SENT_CMD | STATE_GOT_STATUS; 8810 8811 pkt->pkt_resid = 0; 8812 8813 if (fpkt->pkt_datalen) { 8814 pkt->pkt_state |= STATE_XFERRED_DATA; 8815 if (fpkt->pkt_data_resid) { 8816 error++; 8817 } 8818 } 8819 8820 if ((pkt->pkt_scbp != NULL) && ((*(pkt->pkt_scbp) = 8821 rsp->fcp_u.fcp_status.scsi_status) != STATUS_GOOD)) { 8822 /* 8823 * The next two checks make sure that if there 8824 * is no sense data or a valid response and 8825 * the command came back with check condition, 8826 * the command should be retried. 8827 */ 8828 if (!rsp->fcp_u.fcp_status.rsp_len_set && 8829 !rsp->fcp_u.fcp_status.sense_len_set) { 8830 pkt->pkt_state &= ~STATE_XFERRED_DATA; 8831 pkt->pkt_resid = cmd->cmd_dmacount; 8832 } 8833 } 8834 8835 if ((error | rsp->fcp_u.i_fcp_status | rsp->fcp_resid) == 0) { 8836 return; 8837 } 8838 8839 plun = ADDR2LUN(&pkt->pkt_address); 8840 ptgt = plun->lun_tgt; 8841 ASSERT(ptgt != NULL); 8842 8843 /* 8844 * Update the transfer resid, if appropriate 8845 */ 8846 if (rsp->fcp_u.fcp_status.resid_over || 8847 rsp->fcp_u.fcp_status.resid_under) { 8848 pkt->pkt_resid = rsp->fcp_resid; 8849 } 8850 8851 /* 8852 * First see if we got a FCP protocol error. 8853 */ 8854 if (rsp->fcp_u.fcp_status.rsp_len_set) { 8855 struct fcp_rsp_info *bep; 8856 bep = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 8857 sizeof (struct fcp_rsp)); 8858 8859 if (fcp_validate_fcp_response(rsp, pptr) != 8860 FC_SUCCESS) { 8861 pkt->pkt_reason = CMD_CMPLT; 8862 *(pkt->pkt_scbp) = STATUS_CHECK; 8863 8864 fcp_log(CE_WARN, pptr->port_dip, 8865 "!SCSI command to d_id=0x%x lun=0x%x" 8866 " failed, Bad FCP response values:" 8867 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8868 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8869 ptgt->tgt_d_id, plun->lun_num, 8870 rsp->reserved_0, rsp->reserved_1, 8871 rsp->fcp_u.fcp_status.reserved_0, 8872 rsp->fcp_u.fcp_status.reserved_1, 8873 rsp->fcp_response_len, rsp->fcp_sense_len); 8874 8875 return; 8876 } 8877 8878 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8879 FCP_CP_IN(fpkt->pkt_resp + 8880 sizeof (struct fcp_rsp), bep, 8881 fpkt->pkt_resp_acc, 8882 sizeof (struct fcp_rsp_info)); 8883 } 8884 8885 if (bep->rsp_code != FCP_NO_FAILURE) { 8886 child_info_t *cip; 8887 8888 pkt->pkt_reason = CMD_TRAN_ERR; 8889 8890 mutex_enter(&plun->lun_mutex); 8891 cip = plun->lun_cip; 8892 mutex_exit(&plun->lun_mutex); 8893 8894 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8895 fcp_trace, FCP_BUF_LEVEL_2, 0, 8896 "FCP response error on cmd=%p" 8897 " target=0x%x, cip=%p", cmd, 8898 ptgt->tgt_d_id, cip); 8899 } 8900 } 8901 8902 /* 8903 * See if we got a SCSI error with sense data 8904 */ 8905 if (rsp->fcp_u.fcp_status.sense_len_set) { 8906 uchar_t rqlen; 8907 caddr_t sense_from; 8908 child_info_t *cip; 8909 timeout_id_t tid; 8910 struct scsi_arq_status *arq; 8911 struct scsi_extended_sense *sense_to; 8912 8913 arq = (struct scsi_arq_status *)pkt->pkt_scbp; 8914 sense_to = &arq->sts_sensedata; 8915 8916 rqlen = (uchar_t)min(rsp->fcp_sense_len, 8917 sizeof (struct scsi_extended_sense)); 8918 8919 sense_from = (caddr_t)fpkt->pkt_resp + 8920 sizeof (struct fcp_rsp) + rsp->fcp_response_len; 8921 8922 if (fcp_validate_fcp_response(rsp, pptr) != 8923 FC_SUCCESS) { 8924 pkt->pkt_reason = CMD_CMPLT; 8925 *(pkt->pkt_scbp) = STATUS_CHECK; 8926 8927 fcp_log(CE_WARN, pptr->port_dip, 8928 "!SCSI command to d_id=0x%x lun=0x%x" 8929 " failed, Bad FCP response values:" 8930 " rsvd1=%x, rsvd2=%x, sts-rsvd1=%x," 8931 " sts-rsvd2=%x, rsplen=%x, senselen=%x", 8932 ptgt->tgt_d_id, plun->lun_num, 8933 rsp->reserved_0, rsp->reserved_1, 8934 rsp->fcp_u.fcp_status.reserved_0, 8935 rsp->fcp_u.fcp_status.reserved_1, 8936 rsp->fcp_response_len, rsp->fcp_sense_len); 8937 8938 return; 8939 } 8940 8941 /* 8942 * copy in sense information 8943 */ 8944 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 8945 FCP_CP_IN(sense_from, sense_to, 8946 fpkt->pkt_resp_acc, rqlen); 8947 } else { 8948 bcopy(sense_from, sense_to, rqlen); 8949 } 8950 8951 if ((FCP_SENSE_REPORTLUN_CHANGED(sense_to)) || 8952 (FCP_SENSE_NO_LUN(sense_to))) { 8953 mutex_enter(&ptgt->tgt_mutex); 8954 if (ptgt->tgt_tid == NULL) { 8955 /* 8956 * Kick off rediscovery 8957 */ 8958 tid = timeout(fcp_reconfigure_luns, 8959 (caddr_t)ptgt, drv_usectohz(1)); 8960 8961 ptgt->tgt_tid = tid; 8962 ptgt->tgt_state |= FCP_TGT_BUSY; 8963 } 8964 mutex_exit(&ptgt->tgt_mutex); 8965 if (FCP_SENSE_REPORTLUN_CHANGED(sense_to)) { 8966 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8967 fcp_trace, FCP_BUF_LEVEL_3, 0, 8968 "!FCP: Report Lun Has Changed" 8969 " target=%x", ptgt->tgt_d_id); 8970 } else if (FCP_SENSE_NO_LUN(sense_to)) { 8971 FCP_TRACE(fcp_logq, pptr->port_instbuf, 8972 fcp_trace, FCP_BUF_LEVEL_3, 0, 8973 "!FCP: LU Not Supported" 8974 " target=%x", ptgt->tgt_d_id); 8975 } 8976 } 8977 ASSERT(pkt->pkt_scbp != NULL); 8978 8979 pkt->pkt_state |= STATE_ARQ_DONE; 8980 8981 arq->sts_rqpkt_resid = SENSE_LENGTH - rqlen; 8982 8983 *((uchar_t *)&arq->sts_rqpkt_status) = STATUS_GOOD; 8984 arq->sts_rqpkt_reason = 0; 8985 arq->sts_rqpkt_statistics = 0; 8986 8987 arq->sts_rqpkt_state = STATE_GOT_BUS | 8988 STATE_GOT_TARGET | STATE_SENT_CMD | 8989 STATE_GOT_STATUS | STATE_ARQ_DONE | 8990 STATE_XFERRED_DATA; 8991 8992 mutex_enter(&plun->lun_mutex); 8993 cip = plun->lun_cip; 8994 mutex_exit(&plun->lun_mutex); 8995 8996 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 8997 fcp_trace, FCP_BUF_LEVEL_8, 0, 8998 "SCSI Check condition on cmd=%p target=0x%x" 8999 " LUN=%p, cmd=%x SCSI status=%x, es key=%x" 9000 " ASC=%x ASCQ=%x", cmd, ptgt->tgt_d_id, cip, 9001 cmd->cmd_fcp_cmd.fcp_cdb[0], 9002 rsp->fcp_u.fcp_status.scsi_status, 9003 sense_to->es_key, sense_to->es_add_code, 9004 sense_to->es_qual_code); 9005 } 9006 } else { 9007 plun = ADDR2LUN(&pkt->pkt_address); 9008 ptgt = plun->lun_tgt; 9009 ASSERT(ptgt != NULL); 9010 9011 /* 9012 * Work harder to translate errors into target driver 9013 * understandable ones. Note with despair that the target 9014 * drivers don't decode pkt_state and pkt_reason exhaustively 9015 * They resort to using the big hammer most often, which 9016 * may not get fixed in the life time of this driver. 9017 */ 9018 pkt->pkt_state = 0; 9019 pkt->pkt_statistics = 0; 9020 9021 switch (fpkt->pkt_state) { 9022 case FC_PKT_TRAN_ERROR: 9023 switch (fpkt->pkt_reason) { 9024 case FC_REASON_OVERRUN: 9025 pkt->pkt_reason = CMD_CMD_OVR; 9026 pkt->pkt_statistics |= STAT_ABORTED; 9027 break; 9028 9029 case FC_REASON_XCHG_BSY: { 9030 caddr_t ptr; 9031 9032 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9033 9034 ptr = (caddr_t)pkt->pkt_scbp; 9035 if (ptr) { 9036 *ptr = STATUS_BUSY; 9037 } 9038 break; 9039 } 9040 9041 case FC_REASON_ABORTED: 9042 pkt->pkt_reason = CMD_TRAN_ERR; 9043 pkt->pkt_statistics |= STAT_ABORTED; 9044 break; 9045 9046 case FC_REASON_ABORT_FAILED: 9047 pkt->pkt_reason = CMD_ABORT_FAIL; 9048 break; 9049 9050 case FC_REASON_NO_SEQ_INIT: 9051 case FC_REASON_CRC_ERROR: 9052 pkt->pkt_reason = CMD_TRAN_ERR; 9053 pkt->pkt_statistics |= STAT_ABORTED; 9054 break; 9055 default: 9056 pkt->pkt_reason = CMD_TRAN_ERR; 9057 break; 9058 } 9059 break; 9060 9061 case FC_PKT_PORT_OFFLINE: { 9062 dev_info_t *cdip = NULL; 9063 caddr_t ptr; 9064 9065 if (fpkt->pkt_reason == FC_REASON_LOGIN_REQUIRED) { 9066 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9067 fcp_trace, FCP_BUF_LEVEL_8, 0, 9068 "SCSI cmd; LOGIN REQUIRED from FCA for %x", 9069 ptgt->tgt_d_id); 9070 } 9071 9072 mutex_enter(&plun->lun_mutex); 9073 if (plun->lun_mpxio == 0) { 9074 cdip = DIP(plun->lun_cip); 9075 } else if (plun->lun_cip) { 9076 cdip = mdi_pi_get_client(PIP(plun->lun_cip)); 9077 } 9078 9079 mutex_exit(&plun->lun_mutex); 9080 9081 if (cdip) { 9082 (void) ndi_event_retrieve_cookie( 9083 pptr->port_ndi_event_hdl, cdip, 9084 FCAL_REMOVE_EVENT, &fcp_remove_eid, 9085 NDI_EVENT_NOPASS); 9086 (void) ndi_event_run_callbacks( 9087 pptr->port_ndi_event_hdl, cdip, 9088 fcp_remove_eid, NULL); 9089 } 9090 9091 /* 9092 * If the link goes off-line for a lip, 9093 * this will cause a error to the ST SG 9094 * SGEN drivers. By setting BUSY we will 9095 * give the drivers the chance to retry 9096 * before it blows of the job. ST will 9097 * remember how many times it has retried. 9098 */ 9099 9100 if ((plun->lun_type == DTYPE_SEQUENTIAL) || 9101 (plun->lun_type == DTYPE_CHANGER)) { 9102 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9103 ptr = (caddr_t)pkt->pkt_scbp; 9104 if (ptr) { 9105 *ptr = STATUS_BUSY; 9106 } 9107 } else { 9108 pkt->pkt_reason = CMD_TRAN_ERR; 9109 pkt->pkt_statistics |= STAT_BUS_RESET; 9110 } 9111 break; 9112 } 9113 9114 case FC_PKT_TRAN_BSY: 9115 /* 9116 * Use the ssd Qfull handling here. 9117 */ 9118 *pkt->pkt_scbp = STATUS_INTERMEDIATE; 9119 pkt->pkt_state = STATE_GOT_BUS; 9120 break; 9121 9122 case FC_PKT_TIMEOUT: 9123 pkt->pkt_reason = CMD_TIMEOUT; 9124 if (fpkt->pkt_reason == FC_REASON_ABORT_FAILED) { 9125 pkt->pkt_statistics |= STAT_TIMEOUT; 9126 } else { 9127 pkt->pkt_statistics |= STAT_ABORTED; 9128 } 9129 break; 9130 9131 case FC_PKT_LOCAL_RJT: 9132 switch (fpkt->pkt_reason) { 9133 case FC_REASON_OFFLINE: { 9134 dev_info_t *cdip = NULL; 9135 9136 mutex_enter(&plun->lun_mutex); 9137 if (plun->lun_mpxio == 0) { 9138 cdip = DIP(plun->lun_cip); 9139 } else if (plun->lun_cip) { 9140 cdip = mdi_pi_get_client( 9141 PIP(plun->lun_cip)); 9142 } 9143 mutex_exit(&plun->lun_mutex); 9144 9145 if (cdip) { 9146 (void) ndi_event_retrieve_cookie( 9147 pptr->port_ndi_event_hdl, cdip, 9148 FCAL_REMOVE_EVENT, 9149 &fcp_remove_eid, 9150 NDI_EVENT_NOPASS); 9151 (void) ndi_event_run_callbacks( 9152 pptr->port_ndi_event_hdl, 9153 cdip, fcp_remove_eid, NULL); 9154 } 9155 9156 pkt->pkt_reason = CMD_TRAN_ERR; 9157 pkt->pkt_statistics |= STAT_BUS_RESET; 9158 9159 break; 9160 } 9161 9162 case FC_REASON_NOMEM: 9163 case FC_REASON_QFULL: { 9164 caddr_t ptr; 9165 9166 pkt->pkt_reason = CMD_CMPLT; /* Lie */ 9167 ptr = (caddr_t)pkt->pkt_scbp; 9168 if (ptr) { 9169 *ptr = STATUS_BUSY; 9170 } 9171 break; 9172 } 9173 9174 case FC_REASON_DMA_ERROR: 9175 pkt->pkt_reason = CMD_DMA_DERR; 9176 pkt->pkt_statistics |= STAT_ABORTED; 9177 break; 9178 9179 case FC_REASON_CRC_ERROR: 9180 case FC_REASON_UNDERRUN: { 9181 uchar_t status; 9182 /* 9183 * Work around for Bugid: 4240945. 9184 * IB on A5k doesn't set the Underrun bit 9185 * in the fcp status, when it is transferring 9186 * less than requested amount of data. Work 9187 * around the ses problem to keep luxadm 9188 * happy till ibfirmware is fixed. 9189 */ 9190 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 9191 FCP_CP_IN(fpkt->pkt_resp, rsp, 9192 fpkt->pkt_resp_acc, 9193 sizeof (struct fcp_rsp)); 9194 } 9195 status = rsp->fcp_u.fcp_status.scsi_status; 9196 if (((plun->lun_type & DTYPE_MASK) == 9197 DTYPE_ESI) && (status == STATUS_GOOD)) { 9198 pkt->pkt_reason = CMD_CMPLT; 9199 *pkt->pkt_scbp = status; 9200 pkt->pkt_resid = 0; 9201 } else { 9202 pkt->pkt_reason = CMD_TRAN_ERR; 9203 pkt->pkt_statistics |= STAT_ABORTED; 9204 } 9205 break; 9206 } 9207 9208 case FC_REASON_NO_CONNECTION: 9209 case FC_REASON_UNSUPPORTED: 9210 case FC_REASON_ILLEGAL_REQ: 9211 case FC_REASON_BAD_SID: 9212 case FC_REASON_DIAG_BUSY: 9213 case FC_REASON_FCAL_OPN_FAIL: 9214 case FC_REASON_BAD_XID: 9215 default: 9216 pkt->pkt_reason = CMD_TRAN_ERR; 9217 pkt->pkt_statistics |= STAT_ABORTED; 9218 break; 9219 9220 } 9221 break; 9222 9223 case FC_PKT_NPORT_RJT: 9224 case FC_PKT_FABRIC_RJT: 9225 case FC_PKT_NPORT_BSY: 9226 case FC_PKT_FABRIC_BSY: 9227 default: 9228 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9229 fcp_trace, FCP_BUF_LEVEL_8, 0, 9230 "FC Status 0x%x, reason 0x%x", 9231 fpkt->pkt_state, fpkt->pkt_reason); 9232 pkt->pkt_reason = CMD_TRAN_ERR; 9233 pkt->pkt_statistics |= STAT_ABORTED; 9234 break; 9235 } 9236 9237 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9238 fcp_trace, FCP_BUF_LEVEL_9, 0, 9239 "!FC error on cmd=%p target=0x%x: pkt state=0x%x " 9240 " pkt reason=0x%x", cmd, ptgt->tgt_d_id, fpkt->pkt_state, 9241 fpkt->pkt_reason); 9242 } 9243 9244 ASSERT(save.a_hba_tran == pkt->pkt_address.a_hba_tran); 9245 } 9246 9247 9248 static int 9249 fcp_validate_fcp_response(struct fcp_rsp *rsp, struct fcp_port *pptr) 9250 { 9251 if (rsp->reserved_0 || rsp->reserved_1 || 9252 rsp->fcp_u.fcp_status.reserved_0 || 9253 rsp->fcp_u.fcp_status.reserved_1) { 9254 /* 9255 * These reserved fields should ideally be zero. FCP-2 does say 9256 * that the recipient need not check for reserved fields to be 9257 * zero. If they are not zero, we will not make a fuss about it 9258 * - just log it (in debug to both trace buffer and messages 9259 * file and to trace buffer only in non-debug) and move on. 9260 * 9261 * Non-zero reserved fields were seen with minnows. 9262 * 9263 * qlc takes care of some of this but we cannot assume that all 9264 * FCAs will do so. 9265 */ 9266 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 9267 FCP_BUF_LEVEL_5, 0, 9268 "Got fcp response packet with non-zero reserved fields " 9269 "rsp->reserved_0:0x%x, rsp_reserved_1:0x%x, " 9270 "status.reserved_0:0x%x, status.reserved_1:0x%x", 9271 rsp->reserved_0, rsp->reserved_1, 9272 rsp->fcp_u.fcp_status.reserved_0, 9273 rsp->fcp_u.fcp_status.reserved_1); 9274 } 9275 9276 if (rsp->fcp_u.fcp_status.rsp_len_set && (rsp->fcp_response_len > 9277 (FCP_MAX_RSP_IU_SIZE - sizeof (struct fcp_rsp)))) { 9278 return (FC_FAILURE); 9279 } 9280 9281 if (rsp->fcp_u.fcp_status.sense_len_set && rsp->fcp_sense_len > 9282 (FCP_MAX_RSP_IU_SIZE - rsp->fcp_response_len - 9283 sizeof (struct fcp_rsp))) { 9284 return (FC_FAILURE); 9285 } 9286 9287 return (FC_SUCCESS); 9288 } 9289 9290 9291 /* 9292 * This is called when there is a change the in device state. The case we're 9293 * handling here is, if the d_id s does not match, offline this tgt and online 9294 * a new tgt with the new d_id. called from fcp_handle_devices with 9295 * port_mutex held. 9296 */ 9297 static int 9298 fcp_device_changed(struct fcp_port *pptr, struct fcp_tgt *ptgt, 9299 fc_portmap_t *map_entry, int link_cnt, int tgt_cnt, int cause) 9300 { 9301 ASSERT(mutex_owned(&pptr->port_mutex)); 9302 9303 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9304 fcp_trace, FCP_BUF_LEVEL_3, 0, 9305 "Starting fcp_device_changed..."); 9306 9307 /* 9308 * The two cases where the port_device_changed is called is 9309 * either it changes it's d_id or it's hard address. 9310 */ 9311 if ((ptgt->tgt_d_id != map_entry->map_did.port_id) || 9312 (FC_TOP_EXTERNAL(pptr->port_topology) && 9313 (ptgt->tgt_hard_addr != map_entry->map_hard_addr.hard_addr))) { 9314 9315 /* offline this target */ 9316 mutex_enter(&ptgt->tgt_mutex); 9317 if (!(ptgt->tgt_state & FCP_TGT_OFFLINE)) { 9318 (void) fcp_offline_target(pptr, ptgt, link_cnt, 9319 0, 1, NDI_DEVI_REMOVE); 9320 } 9321 mutex_exit(&ptgt->tgt_mutex); 9322 9323 fcp_log(CE_NOTE, pptr->port_dip, 9324 "Change in target properties: Old D_ID=%x New D_ID=%x" 9325 " Old HA=%x New HA=%x", ptgt->tgt_d_id, 9326 map_entry->map_did.port_id, ptgt->tgt_hard_addr, 9327 map_entry->map_hard_addr.hard_addr); 9328 } 9329 9330 return (fcp_handle_mapflags(pptr, ptgt, map_entry, 9331 link_cnt, tgt_cnt, cause)); 9332 } 9333 9334 /* 9335 * Function: fcp_alloc_lun 9336 * 9337 * Description: Creates a new lun structure and adds it to the list 9338 * of luns of the target. 9339 * 9340 * Argument: ptgt Target the lun will belong to. 9341 * 9342 * Return Value: NULL Failed 9343 * Not NULL Succeeded 9344 * 9345 * Context: Kernel context 9346 */ 9347 static struct fcp_lun * 9348 fcp_alloc_lun(struct fcp_tgt *ptgt) 9349 { 9350 struct fcp_lun *plun; 9351 9352 plun = kmem_zalloc(sizeof (struct fcp_lun), KM_NOSLEEP); 9353 if (plun != NULL) { 9354 /* 9355 * Initialize the mutex before putting in the target list 9356 * especially before releasing the target mutex. 9357 */ 9358 mutex_init(&plun->lun_mutex, NULL, MUTEX_DRIVER, NULL); 9359 plun->lun_tgt = ptgt; 9360 9361 mutex_enter(&ptgt->tgt_mutex); 9362 plun->lun_next = ptgt->tgt_lun; 9363 ptgt->tgt_lun = plun; 9364 plun->lun_old_guid = NULL; 9365 plun->lun_old_guid_size = 0; 9366 mutex_exit(&ptgt->tgt_mutex); 9367 } 9368 9369 return (plun); 9370 } 9371 9372 /* 9373 * Function: fcp_dealloc_lun 9374 * 9375 * Description: Frees the LUN structure passed by the caller. 9376 * 9377 * Argument: plun LUN structure to free. 9378 * 9379 * Return Value: None 9380 * 9381 * Context: Kernel context. 9382 */ 9383 static void 9384 fcp_dealloc_lun(struct fcp_lun *plun) 9385 { 9386 mutex_enter(&plun->lun_mutex); 9387 if (plun->lun_cip) { 9388 fcp_remove_child(plun); 9389 } 9390 mutex_exit(&plun->lun_mutex); 9391 9392 mutex_destroy(&plun->lun_mutex); 9393 if (plun->lun_guid) { 9394 kmem_free(plun->lun_guid, plun->lun_guid_size); 9395 } 9396 if (plun->lun_old_guid) { 9397 kmem_free(plun->lun_old_guid, plun->lun_old_guid_size); 9398 } 9399 kmem_free(plun, sizeof (*plun)); 9400 } 9401 9402 /* 9403 * Function: fcp_alloc_tgt 9404 * 9405 * Description: Creates a new target structure and adds it to the port 9406 * hash list. 9407 * 9408 * Argument: pptr fcp port structure 9409 * *map_entry entry describing the target to create 9410 * link_cnt Link state change counter 9411 * 9412 * Return Value: NULL Failed 9413 * Not NULL Succeeded 9414 * 9415 * Context: Kernel context. 9416 */ 9417 static struct fcp_tgt * 9418 fcp_alloc_tgt(struct fcp_port *pptr, fc_portmap_t *map_entry, int link_cnt) 9419 { 9420 int hash; 9421 uchar_t *wwn; 9422 struct fcp_tgt *ptgt; 9423 9424 ptgt = kmem_zalloc(sizeof (*ptgt), KM_NOSLEEP); 9425 if (ptgt != NULL) { 9426 mutex_enter(&pptr->port_mutex); 9427 if (link_cnt != pptr->port_link_cnt) { 9428 /* 9429 * oh oh -- another link reset 9430 * in progress -- give up 9431 */ 9432 mutex_exit(&pptr->port_mutex); 9433 kmem_free(ptgt, sizeof (*ptgt)); 9434 ptgt = NULL; 9435 } else { 9436 /* 9437 * initialize the mutex before putting in the port 9438 * wwn list, especially before releasing the port 9439 * mutex. 9440 */ 9441 mutex_init(&ptgt->tgt_mutex, NULL, MUTEX_DRIVER, NULL); 9442 9443 /* add new target entry to the port's hash list */ 9444 wwn = (uchar_t *)&map_entry->map_pwwn; 9445 hash = FCP_HASH(wwn); 9446 9447 ptgt->tgt_next = pptr->port_tgt_hash_table[hash]; 9448 pptr->port_tgt_hash_table[hash] = ptgt; 9449 9450 /* save cross-ptr */ 9451 ptgt->tgt_port = pptr; 9452 9453 ptgt->tgt_change_cnt = 1; 9454 9455 /* initialize the target manual_config_only flag */ 9456 if (fcp_enable_auto_configuration) { 9457 ptgt->tgt_manual_config_only = 0; 9458 } else { 9459 ptgt->tgt_manual_config_only = 1; 9460 } 9461 9462 mutex_exit(&pptr->port_mutex); 9463 } 9464 } 9465 9466 return (ptgt); 9467 } 9468 9469 /* 9470 * Function: fcp_dealloc_tgt 9471 * 9472 * Description: Frees the target structure passed by the caller. 9473 * 9474 * Argument: ptgt Target structure to free. 9475 * 9476 * Return Value: None 9477 * 9478 * Context: Kernel context. 9479 */ 9480 static void 9481 fcp_dealloc_tgt(struct fcp_tgt *ptgt) 9482 { 9483 mutex_destroy(&ptgt->tgt_mutex); 9484 kmem_free(ptgt, sizeof (*ptgt)); 9485 } 9486 9487 9488 /* 9489 * Handle STATUS_QFULL and STATUS_BUSY by performing delayed retry 9490 * 9491 * Device discovery commands will not be retried for-ever as 9492 * this will have repercussions on other devices that need to 9493 * be submitted to the hotplug thread. After a quick glance 9494 * at the SCSI-3 spec, it was found that the spec doesn't 9495 * mandate a forever retry, rather recommends a delayed retry. 9496 * 9497 * Since Photon IB is single threaded, STATUS_BUSY is common 9498 * in a 4+initiator environment. Make sure the total time 9499 * spent on retries (including command timeout) does not 9500 * 60 seconds 9501 */ 9502 static void 9503 fcp_queue_ipkt(struct fcp_port *pptr, fc_packet_t *fpkt) 9504 { 9505 struct fcp_ipkt *icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9506 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 9507 9508 mutex_enter(&pptr->port_mutex); 9509 mutex_enter(&ptgt->tgt_mutex); 9510 if (FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 9511 FCP_TRACE(fcp_logq, pptr->port_instbuf, 9512 fcp_trace, FCP_BUF_LEVEL_2, 0, 9513 "fcp_queue_ipkt,1:state change occured" 9514 " for D_ID=0x%x", ptgt->tgt_d_id); 9515 mutex_exit(&ptgt->tgt_mutex); 9516 mutex_exit(&pptr->port_mutex); 9517 (void) fcp_call_finish_init(pptr, ptgt, icmd->ipkt_link_cnt, 9518 icmd->ipkt_change_cnt, icmd->ipkt_cause); 9519 fcp_icmd_free(pptr, icmd); 9520 return; 9521 } 9522 mutex_exit(&ptgt->tgt_mutex); 9523 9524 icmd->ipkt_restart = fcp_watchdog_time + icmd->ipkt_retries++; 9525 9526 if (pptr->port_ipkt_list != NULL) { 9527 /* add pkt to front of doubly-linked list */ 9528 pptr->port_ipkt_list->ipkt_prev = icmd; 9529 icmd->ipkt_next = pptr->port_ipkt_list; 9530 pptr->port_ipkt_list = icmd; 9531 icmd->ipkt_prev = NULL; 9532 } else { 9533 /* this is the first/only pkt on the list */ 9534 pptr->port_ipkt_list = icmd; 9535 icmd->ipkt_next = NULL; 9536 icmd->ipkt_prev = NULL; 9537 } 9538 mutex_exit(&pptr->port_mutex); 9539 } 9540 9541 /* 9542 * Function: fcp_transport 9543 * 9544 * Description: This function submits the Fibre Channel packet to the transort 9545 * layer by calling fc_ulp_transport(). If fc_ulp_transport() 9546 * fails the submission, the treatment depends on the value of 9547 * the variable internal. 9548 * 9549 * Argument: port_handle fp/fctl port handle. 9550 * *fpkt Packet to submit to the transport layer. 9551 * internal Not zero when it's an internal packet. 9552 * 9553 * Return Value: FC_TRAN_BUSY 9554 * FC_STATEC_BUSY 9555 * FC_OFFLINE 9556 * FC_LOGINREQ 9557 * FC_DEVICE_BUSY 9558 * FC_SUCCESS 9559 */ 9560 static int 9561 fcp_transport(opaque_t port_handle, fc_packet_t *fpkt, int internal) 9562 { 9563 int rval; 9564 9565 rval = fc_ulp_transport(port_handle, fpkt); 9566 if (rval == FC_SUCCESS) { 9567 return (rval); 9568 } 9569 9570 /* 9571 * LUN isn't marked BUSY or OFFLINE, so we got here to transport 9572 * a command, if the underlying modules see that there is a state 9573 * change, or if a port is OFFLINE, that means, that state change 9574 * hasn't reached FCP yet, so re-queue the command for deferred 9575 * submission. 9576 */ 9577 if ((rval == FC_STATEC_BUSY) || (rval == FC_OFFLINE) || 9578 (rval == FC_LOGINREQ) || (rval == FC_DEVICE_BUSY) || 9579 (rval == FC_DEVICE_BUSY_NEW_RSCN) || (rval == FC_TRAN_BUSY)) { 9580 /* 9581 * Defer packet re-submission. Life hang is possible on 9582 * internal commands if the port driver sends FC_STATEC_BUSY 9583 * for ever, but that shouldn't happen in a good environment. 9584 * Limiting re-transport for internal commands is probably a 9585 * good idea.. 9586 * A race condition can happen when a port sees barrage of 9587 * link transitions offline to online. If the FCTL has 9588 * returned FC_STATEC_BUSY or FC_OFFLINE then none of the 9589 * internal commands should be queued to do the discovery. 9590 * The race condition is when an online comes and FCP starts 9591 * its internal discovery and the link goes offline. It is 9592 * possible that the statec_callback has not reached FCP 9593 * and FCP is carrying on with its internal discovery. 9594 * FC_STATEC_BUSY or FC_OFFLINE will be the first indication 9595 * that the link has gone offline. At this point FCP should 9596 * drop all the internal commands and wait for the 9597 * statec_callback. It will be facilitated by incrementing 9598 * port_link_cnt. 9599 * 9600 * For external commands, the (FC)pkt_timeout is decremented 9601 * by the QUEUE Delay added by our driver, Care is taken to 9602 * ensure that it doesn't become zero (zero means no timeout) 9603 * If the time expires right inside driver queue itself, 9604 * the watch thread will return it to the original caller 9605 * indicating that the command has timed-out. 9606 */ 9607 if (internal) { 9608 char *op; 9609 struct fcp_ipkt *icmd; 9610 9611 icmd = (struct fcp_ipkt *)fpkt->pkt_ulp_private; 9612 switch (icmd->ipkt_opcode) { 9613 case SCMD_REPORT_LUN: 9614 op = "REPORT LUN"; 9615 break; 9616 9617 case SCMD_INQUIRY: 9618 op = "INQUIRY"; 9619 break; 9620 9621 case SCMD_INQUIRY_PAGE83: 9622 op = "INQUIRY-83"; 9623 break; 9624 9625 default: 9626 op = "Internal SCSI COMMAND"; 9627 break; 9628 } 9629 9630 if (fcp_handle_ipkt_errors(icmd->ipkt_port, 9631 icmd->ipkt_tgt, icmd, rval, op) == DDI_SUCCESS) { 9632 rval = FC_SUCCESS; 9633 } 9634 } else { 9635 struct fcp_pkt *cmd; 9636 struct fcp_port *pptr; 9637 9638 cmd = (struct fcp_pkt *)fpkt->pkt_ulp_private; 9639 cmd->cmd_state = FCP_PKT_IDLE; 9640 pptr = ADDR2FCP(&cmd->cmd_pkt->pkt_address); 9641 9642 if (cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) { 9643 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 9644 fcp_trace, FCP_BUF_LEVEL_9, 0, 9645 "fcp_transport: xport busy for pkt %p", 9646 cmd->cmd_pkt); 9647 rval = FC_TRAN_BUSY; 9648 } else { 9649 fcp_queue_pkt(pptr, cmd); 9650 rval = FC_SUCCESS; 9651 } 9652 } 9653 } 9654 9655 return (rval); 9656 } 9657 9658 /*VARARGS3*/ 9659 static void 9660 fcp_log(int level, dev_info_t *dip, const char *fmt, ...) 9661 { 9662 char buf[256]; 9663 va_list ap; 9664 9665 if (dip == NULL) { 9666 dip = fcp_global_dip; 9667 } 9668 9669 va_start(ap, fmt); 9670 (void) vsprintf(buf, fmt, ap); 9671 va_end(ap); 9672 9673 scsi_log(dip, "fcp", level, buf); 9674 } 9675 9676 /* 9677 * This function retries NS registry of FC4 type. 9678 * It assumes that fcp_mutex is held. 9679 * The function does nothing if topology is not fabric 9680 * So, the topology has to be set before this function can be called 9681 */ 9682 static void 9683 fcp_retry_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9684 { 9685 int rval; 9686 9687 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 9688 9689 if (((pptr->port_state & FCP_STATE_NS_REG_FAILED) == 0) || 9690 ((pptr->port_topology != FC_TOP_FABRIC) && 9691 (pptr->port_topology != FC_TOP_PUBLIC_LOOP))) { 9692 if (pptr->port_state & FCP_STATE_NS_REG_FAILED) { 9693 pptr->port_state &= ~FCP_STATE_NS_REG_FAILED; 9694 } 9695 return; 9696 } 9697 mutex_exit(&pptr->port_mutex); 9698 rval = fcp_do_ns_registry(pptr, s_id); 9699 mutex_enter(&pptr->port_mutex); 9700 9701 if (rval == 0) { 9702 /* Registry successful. Reset flag */ 9703 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 9704 } 9705 } 9706 9707 /* 9708 * This function registers the ULP with the switch by calling transport i/f 9709 */ 9710 static int 9711 fcp_do_ns_registry(struct fcp_port *pptr, uint32_t s_id) 9712 { 9713 fc_ns_cmd_t ns_cmd; 9714 ns_rfc_type_t rfc; 9715 uint32_t types[8]; 9716 9717 /* 9718 * Prepare the Name server structure to 9719 * register with the transport in case of 9720 * Fabric configuration. 9721 */ 9722 bzero(&rfc, sizeof (rfc)); 9723 bzero(types, sizeof (types)); 9724 9725 types[FC4_TYPE_WORD_POS(FC_TYPE_SCSI_FCP)] = 9726 (1 << FC4_TYPE_BIT_POS(FC_TYPE_SCSI_FCP)); 9727 9728 rfc.rfc_port_id.port_id = s_id; 9729 bcopy(types, rfc.rfc_types, sizeof (types)); 9730 9731 ns_cmd.ns_flags = 0; 9732 ns_cmd.ns_cmd = NS_RFT_ID; 9733 ns_cmd.ns_req_len = sizeof (rfc); 9734 ns_cmd.ns_req_payload = (caddr_t)&rfc; 9735 ns_cmd.ns_resp_len = 0; 9736 ns_cmd.ns_resp_payload = NULL; 9737 9738 /* 9739 * Perform the Name Server Registration for SCSI_FCP FC4 Type. 9740 */ 9741 if (fc_ulp_port_ns(pptr->port_fp_handle, NULL, &ns_cmd)) { 9742 fcp_log(CE_WARN, pptr->port_dip, 9743 "!ns_registry: failed name server registration"); 9744 return (1); 9745 } 9746 9747 return (0); 9748 } 9749 9750 /* 9751 * Function: fcp_handle_port_attach 9752 * 9753 * Description: This function is called from fcp_port_attach() to attach a 9754 * new port. This routine does the following: 9755 * 9756 * 1) Allocates an fcp_port structure and initializes it. 9757 * 2) Tries to register the new FC-4 (FCP) capablity with the name 9758 * server. 9759 * 3) Kicks off the enumeration of the targets/luns visible 9760 * through this new port. That is done by calling 9761 * fcp_statec_callback() if the port is online. 9762 * 9763 * Argument: ulph fp/fctl port handle. 9764 * *pinfo Port information. 9765 * s_id Port ID. 9766 * instance Device instance number for the local port 9767 * (returned by ddi_get_instance()). 9768 * 9769 * Return Value: DDI_SUCCESS 9770 * DDI_FAILURE 9771 * 9772 * Context: User and Kernel context. 9773 */ 9774 /*ARGSUSED*/ 9775 int 9776 fcp_handle_port_attach(opaque_t ulph, fc_ulp_port_info_t *pinfo, 9777 uint32_t s_id, int instance) 9778 { 9779 int res = DDI_FAILURE; 9780 scsi_hba_tran_t *tran; 9781 int mutex_initted = FALSE; 9782 int hba_attached = FALSE; 9783 int soft_state_linked = FALSE; 9784 int event_bind = FALSE; 9785 struct fcp_port *pptr; 9786 fc_portmap_t *tmp_list = NULL; 9787 uint32_t max_cnt, alloc_cnt; 9788 uchar_t *boot_wwn = NULL; 9789 uint_t nbytes; 9790 int manual_cfg; 9791 9792 /* 9793 * this port instance attaching for the first time (or after 9794 * being detached before) 9795 */ 9796 FCP_TRACE(fcp_logq, "fcp", fcp_trace, 9797 FCP_BUF_LEVEL_3, 0, "port attach: for port %d", instance); 9798 9799 if (ddi_soft_state_zalloc(fcp_softstate, instance) != DDI_SUCCESS) { 9800 cmn_err(CE_WARN, "fcp: Softstate struct alloc failed" 9801 "parent dip: %p; instance: %d", (void *)pinfo->port_dip, 9802 instance); 9803 return (res); 9804 } 9805 9806 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 9807 /* this shouldn't happen */ 9808 ddi_soft_state_free(fcp_softstate, instance); 9809 cmn_err(CE_WARN, "fcp: bad soft state"); 9810 return (res); 9811 } 9812 9813 (void) sprintf(pptr->port_instbuf, "fcp(%d)", instance); 9814 9815 /* 9816 * Make a copy of ulp_port_info as fctl allocates 9817 * a temp struct. 9818 */ 9819 (void) fcp_cp_pinfo(pptr, pinfo); 9820 9821 /* 9822 * Check for manual_configuration_only property. 9823 * Enable manual configurtion if the property is 9824 * set to 1, otherwise disable manual configuration. 9825 */ 9826 if ((manual_cfg = ddi_prop_get_int(DDI_DEV_T_ANY, pptr->port_dip, 9827 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 9828 MANUAL_CFG_ONLY, 9829 -1)) != -1) { 9830 if (manual_cfg == 1) { 9831 char *pathname; 9832 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 9833 (void) ddi_pathname(pptr->port_dip, pathname); 9834 cmn_err(CE_NOTE, 9835 "%s (%s%d) %s is enabled via %s.conf.", 9836 pathname, 9837 ddi_driver_name(pptr->port_dip), 9838 ddi_get_instance(pptr->port_dip), 9839 MANUAL_CFG_ONLY, 9840 ddi_driver_name(pptr->port_dip)); 9841 fcp_enable_auto_configuration = 0; 9842 kmem_free(pathname, MAXPATHLEN); 9843 } 9844 } 9845 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9846 pptr->port_link_cnt = 1; 9847 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_link_cnt)); 9848 pptr->port_id = s_id; 9849 pptr->port_instance = instance; 9850 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9851 pptr->port_state = FCP_STATE_INIT; 9852 if (pinfo->port_acc_attr == NULL) { 9853 /* 9854 * The corresponding FCA doesn't support DMA at all 9855 */ 9856 pptr->port_state |= FCP_STATE_FCA_IS_NODMA; 9857 } 9858 9859 _NOTE(NOW_VISIBLE_TO_OTHER_THREADS(pptr->port_state)); 9860 9861 if (!(pptr->port_state & FCP_STATE_FCA_IS_NODMA)) { 9862 /* 9863 * If FCA supports DMA in SCSI data phase, we need preallocate 9864 * dma cookie, so stash the cookie size 9865 */ 9866 pptr->port_dmacookie_sz = sizeof (ddi_dma_cookie_t) * 9867 pptr->port_data_dma_attr.dma_attr_sgllen; 9868 } 9869 9870 /* 9871 * The two mutexes of fcp_port are initialized. The variable 9872 * mutex_initted is incremented to remember that fact. That variable 9873 * is checked when the routine fails and the mutexes have to be 9874 * destroyed. 9875 */ 9876 mutex_init(&pptr->port_mutex, NULL, MUTEX_DRIVER, NULL); 9877 mutex_init(&pptr->port_pkt_mutex, NULL, MUTEX_DRIVER, NULL); 9878 mutex_initted++; 9879 9880 /* 9881 * The SCSI tran structure is allocate and initialized now. 9882 */ 9883 if ((tran = scsi_hba_tran_alloc(pptr->port_dip, 0)) == NULL) { 9884 fcp_log(CE_WARN, pptr->port_dip, 9885 "!fcp%d: scsi_hba_tran_alloc failed", instance); 9886 goto fail; 9887 } 9888 9889 /* link in the transport structure then fill it in */ 9890 pptr->port_tran = tran; 9891 tran->tran_hba_private = pptr; 9892 tran->tran_tgt_init = fcp_scsi_tgt_init; 9893 tran->tran_tgt_probe = NULL; 9894 tran->tran_tgt_free = fcp_scsi_tgt_free; 9895 tran->tran_start = fcp_scsi_start; 9896 tran->tran_reset = fcp_scsi_reset; 9897 tran->tran_abort = fcp_scsi_abort; 9898 tran->tran_getcap = fcp_scsi_getcap; 9899 tran->tran_setcap = fcp_scsi_setcap; 9900 tran->tran_init_pkt = NULL; 9901 tran->tran_destroy_pkt = NULL; 9902 tran->tran_dmafree = NULL; 9903 tran->tran_sync_pkt = NULL; 9904 tran->tran_reset_notify = fcp_scsi_reset_notify; 9905 tran->tran_get_bus_addr = fcp_scsi_get_bus_addr; 9906 tran->tran_get_name = fcp_scsi_get_name; 9907 tran->tran_clear_aca = NULL; 9908 tran->tran_clear_task_set = NULL; 9909 tran->tran_terminate_task = NULL; 9910 tran->tran_get_eventcookie = fcp_scsi_bus_get_eventcookie; 9911 tran->tran_add_eventcall = fcp_scsi_bus_add_eventcall; 9912 tran->tran_remove_eventcall = fcp_scsi_bus_remove_eventcall; 9913 tran->tran_post_event = fcp_scsi_bus_post_event; 9914 tran->tran_quiesce = NULL; 9915 tran->tran_unquiesce = NULL; 9916 tran->tran_bus_reset = NULL; 9917 tran->tran_bus_config = fcp_scsi_bus_config; 9918 tran->tran_bus_unconfig = fcp_scsi_bus_unconfig; 9919 tran->tran_bus_power = NULL; 9920 tran->tran_interconnect_type = INTERCONNECT_FABRIC; 9921 9922 tran->tran_pkt_constructor = fcp_kmem_cache_constructor; 9923 tran->tran_pkt_destructor = fcp_kmem_cache_destructor; 9924 tran->tran_setup_pkt = fcp_pkt_setup; 9925 tran->tran_teardown_pkt = fcp_pkt_teardown; 9926 tran->tran_hba_len = pptr->port_priv_pkt_len + 9927 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz; 9928 if (pptr->port_state & FCP_STATE_FCA_IS_NODMA) { 9929 /* 9930 * If FCA don't support DMA, then we use different vectors to 9931 * minimize the effects on DMA code flow path 9932 */ 9933 tran->tran_start = fcp_pseudo_start; 9934 tran->tran_init_pkt = fcp_pseudo_init_pkt; 9935 tran->tran_destroy_pkt = fcp_pseudo_destroy_pkt; 9936 tran->tran_sync_pkt = fcp_pseudo_sync_pkt; 9937 tran->tran_dmafree = fcp_pseudo_dmafree; 9938 tran->tran_setup_pkt = NULL; 9939 tran->tran_teardown_pkt = NULL; 9940 tran->tran_pkt_constructor = NULL; 9941 tran->tran_pkt_destructor = NULL; 9942 pptr->port_data_dma_attr = pseudo_fca_dma_attr; 9943 } 9944 9945 /* 9946 * Allocate an ndi event handle 9947 */ 9948 pptr->port_ndi_event_defs = (ndi_event_definition_t *) 9949 kmem_zalloc(sizeof (fcp_ndi_event_defs), KM_SLEEP); 9950 9951 bcopy(fcp_ndi_event_defs, pptr->port_ndi_event_defs, 9952 sizeof (fcp_ndi_event_defs)); 9953 9954 (void) ndi_event_alloc_hdl(pptr->port_dip, NULL, 9955 &pptr->port_ndi_event_hdl, NDI_SLEEP); 9956 9957 pptr->port_ndi_events.ndi_events_version = NDI_EVENTS_REV1; 9958 pptr->port_ndi_events.ndi_n_events = FCP_N_NDI_EVENTS; 9959 pptr->port_ndi_events.ndi_event_defs = pptr->port_ndi_event_defs; 9960 9961 if (DEVI_IS_ATTACHING(pptr->port_dip) && 9962 (ndi_event_bind_set(pptr->port_ndi_event_hdl, 9963 &pptr->port_ndi_events, NDI_SLEEP) != NDI_SUCCESS)) { 9964 goto fail; 9965 } 9966 event_bind++; /* Checked in fail case */ 9967 9968 if (scsi_hba_attach_setup(pptr->port_dip, &pptr->port_data_dma_attr, 9969 tran, SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB) 9970 != DDI_SUCCESS) { 9971 fcp_log(CE_WARN, pptr->port_dip, 9972 "!fcp%d: scsi_hba_attach_setup failed", instance); 9973 goto fail; 9974 } 9975 hba_attached++; /* Checked in fail case */ 9976 9977 pptr->port_mpxio = 0; 9978 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, pptr->port_dip, 0) == 9979 MDI_SUCCESS) { 9980 pptr->port_mpxio++; 9981 } 9982 9983 /* 9984 * The following code is putting the new port structure in the global 9985 * list of ports and, if it is the first port to attach, it start the 9986 * fcp_watchdog_tick. 9987 * 9988 * Why put this new port in the global before we are done attaching it? 9989 * We are actually making the structure globally known before we are 9990 * done attaching it. The reason for that is: because of the code that 9991 * follows. At this point the resources to handle the port are 9992 * allocated. This function is now going to do the following: 9993 * 9994 * 1) It is going to try to register with the name server advertizing 9995 * the new FCP capability of the port. 9996 * 2) It is going to play the role of the fp/fctl layer by building 9997 * a list of worlwide names reachable through this port and call 9998 * itself on fcp_statec_callback(). That requires the port to 9999 * be part of the global list. 10000 */ 10001 mutex_enter(&fcp_global_mutex); 10002 if (fcp_port_head == NULL) { 10003 fcp_read_blacklist(pinfo->port_dip, &fcp_lun_blacklist); 10004 } 10005 pptr->port_next = fcp_port_head; 10006 fcp_port_head = pptr; 10007 soft_state_linked++; 10008 10009 if (fcp_watchdog_init++ == 0) { 10010 fcp_watchdog_tick = drv_sectohz(fcp_watchdog_timeout); 10011 fcp_watchdog_id = timeout(fcp_watch, NULL, 10012 fcp_watchdog_tick); 10013 } 10014 mutex_exit(&fcp_global_mutex); 10015 10016 /* 10017 * Here an attempt is made to register with the name server, the new 10018 * FCP capability. That is done using an RTF_ID to the name server. 10019 * It is done synchronously. The function fcp_do_ns_registry() 10020 * doesn't return till the name server responded. 10021 * On failures, just ignore it for now and it will get retried during 10022 * state change callbacks. We'll set a flag to show this failure 10023 */ 10024 if (fcp_do_ns_registry(pptr, s_id)) { 10025 mutex_enter(&pptr->port_mutex); 10026 pptr->port_state |= FCP_STATE_NS_REG_FAILED; 10027 mutex_exit(&pptr->port_mutex); 10028 } else { 10029 mutex_enter(&pptr->port_mutex); 10030 pptr->port_state &= ~(FCP_STATE_NS_REG_FAILED); 10031 mutex_exit(&pptr->port_mutex); 10032 } 10033 10034 /* 10035 * Lookup for boot WWN property 10036 */ 10037 if (modrootloaded != 1) { 10038 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, 10039 ddi_get_parent(pinfo->port_dip), 10040 DDI_PROP_DONTPASS, OBP_BOOT_WWN, 10041 &boot_wwn, &nbytes) == DDI_PROP_SUCCESS) && 10042 (nbytes == FC_WWN_SIZE)) { 10043 bcopy(boot_wwn, pptr->port_boot_wwn, FC_WWN_SIZE); 10044 } 10045 if (boot_wwn) { 10046 ddi_prop_free(boot_wwn); 10047 } 10048 } 10049 10050 /* 10051 * Handle various topologies and link states. 10052 */ 10053 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 10054 case FC_STATE_OFFLINE: 10055 10056 /* 10057 * we're attaching a port where the link is offline 10058 * 10059 * Wait for ONLINE, at which time a state 10060 * change will cause a statec_callback 10061 * 10062 * in the mean time, do not do anything 10063 */ 10064 res = DDI_SUCCESS; 10065 pptr->port_state |= FCP_STATE_OFFLINE; 10066 break; 10067 10068 case FC_STATE_ONLINE: { 10069 if (pptr->port_topology == FC_TOP_UNKNOWN) { 10070 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 10071 res = DDI_SUCCESS; 10072 break; 10073 } 10074 /* 10075 * discover devices and create nodes (a private 10076 * loop or point-to-point) 10077 */ 10078 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 10079 10080 /* 10081 * At this point we are going to build a list of all the ports 10082 * that can be reached through this local port. It looks like 10083 * we cannot handle more than FCP_MAX_DEVICES per local port 10084 * (128). 10085 */ 10086 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 10087 sizeof (fc_portmap_t) * FCP_MAX_DEVICES, 10088 KM_NOSLEEP)) == NULL) { 10089 fcp_log(CE_WARN, pptr->port_dip, 10090 "!fcp%d: failed to allocate portmap", 10091 instance); 10092 goto fail; 10093 } 10094 10095 /* 10096 * fc_ulp_getportmap() is going to provide us with the list of 10097 * remote ports in the buffer we just allocated. The way the 10098 * list is going to be retrieved depends on the topology. 10099 * However, if we are connected to a Fabric, a name server 10100 * request may be sent to get the list of FCP capable ports. 10101 * It should be noted that is the case the request is 10102 * synchronous. This means we are stuck here till the name 10103 * server replies. A lot of things can change during that time 10104 * and including, may be, being called on 10105 * fcp_statec_callback() for different reasons. I'm not sure 10106 * the code can handle that. 10107 */ 10108 max_cnt = FCP_MAX_DEVICES; 10109 alloc_cnt = FCP_MAX_DEVICES; 10110 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 10111 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 10112 FC_SUCCESS) { 10113 caddr_t msg; 10114 10115 (void) fc_ulp_error(res, &msg); 10116 10117 /* 10118 * this just means the transport is 10119 * busy perhaps building a portmap so, 10120 * for now, succeed this port attach 10121 * when the transport has a new map, 10122 * it'll send us a state change then 10123 */ 10124 fcp_log(CE_WARN, pptr->port_dip, 10125 "!failed to get port map : %s", msg); 10126 10127 res = DDI_SUCCESS; 10128 break; /* go return result */ 10129 } 10130 if (max_cnt > alloc_cnt) { 10131 alloc_cnt = max_cnt; 10132 } 10133 10134 /* 10135 * We are now going to call fcp_statec_callback() ourselves. 10136 * By issuing this call we are trying to kick off the enumera- 10137 * tion process. 10138 */ 10139 /* 10140 * let the state change callback do the SCSI device 10141 * discovery and create the devinfos 10142 */ 10143 fcp_statec_callback(ulph, pptr->port_fp_handle, 10144 pptr->port_phys_state, pptr->port_topology, tmp_list, 10145 max_cnt, pptr->port_id); 10146 10147 res = DDI_SUCCESS; 10148 break; 10149 } 10150 10151 default: 10152 /* unknown port state */ 10153 fcp_log(CE_WARN, pptr->port_dip, 10154 "!fcp%d: invalid port state at attach=0x%x", 10155 instance, pptr->port_phys_state); 10156 10157 mutex_enter(&pptr->port_mutex); 10158 pptr->port_phys_state = FCP_STATE_OFFLINE; 10159 mutex_exit(&pptr->port_mutex); 10160 10161 res = DDI_SUCCESS; 10162 break; 10163 } 10164 10165 /* free temp list if used */ 10166 if (tmp_list != NULL) { 10167 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10168 } 10169 10170 /* note the attach time */ 10171 pptr->port_attach_time = ddi_get_lbolt64(); 10172 10173 /* all done */ 10174 return (res); 10175 10176 /* a failure we have to clean up after */ 10177 fail: 10178 fcp_log(CE_WARN, pptr->port_dip, "!failed to attach to port"); 10179 10180 if (soft_state_linked) { 10181 /* remove this fcp_port from the linked list */ 10182 (void) fcp_soft_state_unlink(pptr); 10183 } 10184 10185 /* unbind and free event set */ 10186 if (pptr->port_ndi_event_hdl) { 10187 if (event_bind) { 10188 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10189 &pptr->port_ndi_events, NDI_SLEEP); 10190 } 10191 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10192 } 10193 10194 if (pptr->port_ndi_event_defs) { 10195 (void) kmem_free(pptr->port_ndi_event_defs, 10196 sizeof (fcp_ndi_event_defs)); 10197 } 10198 10199 /* 10200 * Clean up mpxio stuff 10201 */ 10202 if (pptr->port_mpxio) { 10203 (void) mdi_phci_unregister(pptr->port_dip, 0); 10204 pptr->port_mpxio--; 10205 } 10206 10207 /* undo SCSI HBA setup */ 10208 if (hba_attached) { 10209 (void) scsi_hba_detach(pptr->port_dip); 10210 } 10211 if (pptr->port_tran != NULL) { 10212 scsi_hba_tran_free(pptr->port_tran); 10213 } 10214 10215 mutex_enter(&fcp_global_mutex); 10216 10217 /* 10218 * We check soft_state_linked, because it is incremented right before 10219 * we call increment fcp_watchdog_init. Therefore, we know if 10220 * soft_state_linked is still FALSE, we do not want to decrement 10221 * fcp_watchdog_init or possibly call untimeout. 10222 */ 10223 10224 if (soft_state_linked) { 10225 if (--fcp_watchdog_init == 0) { 10226 timeout_id_t tid = fcp_watchdog_id; 10227 10228 mutex_exit(&fcp_global_mutex); 10229 (void) untimeout(tid); 10230 } else { 10231 mutex_exit(&fcp_global_mutex); 10232 } 10233 } else { 10234 mutex_exit(&fcp_global_mutex); 10235 } 10236 10237 if (mutex_initted) { 10238 mutex_destroy(&pptr->port_mutex); 10239 mutex_destroy(&pptr->port_pkt_mutex); 10240 } 10241 10242 if (tmp_list != NULL) { 10243 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 10244 } 10245 10246 /* this makes pptr invalid */ 10247 ddi_soft_state_free(fcp_softstate, instance); 10248 10249 return (DDI_FAILURE); 10250 } 10251 10252 10253 static int 10254 fcp_handle_port_detach(struct fcp_port *pptr, int flag, int instance) 10255 { 10256 int count = 0; 10257 10258 mutex_enter(&pptr->port_mutex); 10259 10260 /* 10261 * if the port is powered down or suspended, nothing else 10262 * to do; just return. 10263 */ 10264 if (flag != FCP_STATE_DETACHING) { 10265 if (pptr->port_state & (FCP_STATE_POWER_DOWN | 10266 FCP_STATE_SUSPENDED)) { 10267 pptr->port_state |= flag; 10268 mutex_exit(&pptr->port_mutex); 10269 return (FC_SUCCESS); 10270 } 10271 } 10272 10273 if (pptr->port_state & FCP_STATE_IN_MDI) { 10274 mutex_exit(&pptr->port_mutex); 10275 return (FC_FAILURE); 10276 } 10277 10278 FCP_TRACE(fcp_logq, pptr->port_instbuf, 10279 fcp_trace, FCP_BUF_LEVEL_2, 0, 10280 "fcp_handle_port_detach: port is detaching"); 10281 10282 pptr->port_state |= flag; 10283 10284 /* 10285 * Wait for any ongoing reconfig/ipkt to complete, that 10286 * ensures the freeing to targets/luns is safe. 10287 * No more ref to this port should happen from statec/ioctl 10288 * after that as it was removed from the global port list. 10289 */ 10290 while (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10291 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10292 /* 10293 * Let's give sufficient time for reconfig/ipkt 10294 * to complete. 10295 */ 10296 if (count++ >= FCP_ICMD_DEADLINE) { 10297 break; 10298 } 10299 mutex_exit(&pptr->port_mutex); 10300 delay(drv_sectohz(1)); 10301 mutex_enter(&pptr->port_mutex); 10302 } 10303 10304 /* 10305 * if the driver is still busy then fail to 10306 * suspend/power down. 10307 */ 10308 if (pptr->port_tmp_cnt || pptr->port_ipkt_cnt || 10309 (pptr->port_state & FCP_STATE_IN_WATCHDOG)) { 10310 pptr->port_state &= ~flag; 10311 mutex_exit(&pptr->port_mutex); 10312 return (FC_FAILURE); 10313 } 10314 10315 if (flag == FCP_STATE_DETACHING) { 10316 pptr = fcp_soft_state_unlink(pptr); 10317 ASSERT(pptr != NULL); 10318 } 10319 10320 pptr->port_link_cnt++; 10321 pptr->port_state |= FCP_STATE_OFFLINE; 10322 pptr->port_state &= ~(FCP_STATE_ONLINING | FCP_STATE_ONLINE); 10323 10324 fcp_update_state(pptr, (FCP_LUN_BUSY | FCP_LUN_MARK), 10325 FCP_CAUSE_LINK_DOWN); 10326 mutex_exit(&pptr->port_mutex); 10327 10328 /* kill watch dog timer if we're the last */ 10329 mutex_enter(&fcp_global_mutex); 10330 if (--fcp_watchdog_init == 0) { 10331 timeout_id_t tid = fcp_watchdog_id; 10332 mutex_exit(&fcp_global_mutex); 10333 (void) untimeout(tid); 10334 } else { 10335 mutex_exit(&fcp_global_mutex); 10336 } 10337 10338 /* clean up the port structures */ 10339 if (flag == FCP_STATE_DETACHING) { 10340 fcp_cleanup_port(pptr, instance); 10341 } 10342 10343 return (FC_SUCCESS); 10344 } 10345 10346 10347 static void 10348 fcp_cleanup_port(struct fcp_port *pptr, int instance) 10349 { 10350 ASSERT(pptr != NULL); 10351 10352 /* unbind and free event set */ 10353 if (pptr->port_ndi_event_hdl) { 10354 (void) ndi_event_unbind_set(pptr->port_ndi_event_hdl, 10355 &pptr->port_ndi_events, NDI_SLEEP); 10356 (void) ndi_event_free_hdl(pptr->port_ndi_event_hdl); 10357 } 10358 10359 if (pptr->port_ndi_event_defs) { 10360 (void) kmem_free(pptr->port_ndi_event_defs, 10361 sizeof (fcp_ndi_event_defs)); 10362 } 10363 10364 /* free the lun/target structures and devinfos */ 10365 fcp_free_targets(pptr); 10366 10367 /* 10368 * Clean up mpxio stuff 10369 */ 10370 if (pptr->port_mpxio) { 10371 (void) mdi_phci_unregister(pptr->port_dip, 0); 10372 pptr->port_mpxio--; 10373 } 10374 10375 /* clean up SCSA stuff */ 10376 (void) scsi_hba_detach(pptr->port_dip); 10377 if (pptr->port_tran != NULL) { 10378 scsi_hba_tran_free(pptr->port_tran); 10379 } 10380 10381 #ifdef KSTATS_CODE 10382 /* clean up kstats */ 10383 if (pptr->fcp_ksp != NULL) { 10384 kstat_delete(pptr->fcp_ksp); 10385 } 10386 #endif 10387 10388 /* clean up soft state mutexes/condition variables */ 10389 mutex_destroy(&pptr->port_mutex); 10390 mutex_destroy(&pptr->port_pkt_mutex); 10391 10392 /* all done with soft state */ 10393 ddi_soft_state_free(fcp_softstate, instance); 10394 } 10395 10396 /* 10397 * Function: fcp_kmem_cache_constructor 10398 * 10399 * Description: This function allocates and initializes the resources required 10400 * to build a scsi_pkt structure the target driver. The result 10401 * of the allocation and initialization will be cached in the 10402 * memory cache. As DMA resources may be allocated here, that 10403 * means DMA resources will be tied up in the cache manager. 10404 * This is a tradeoff that has been made for performance reasons. 10405 * 10406 * Argument: *buf Memory to preinitialize. 10407 * *arg FCP port structure (fcp_port). 10408 * kmflags Value passed to kmem_cache_alloc() and 10409 * propagated to the constructor. 10410 * 10411 * Return Value: 0 Allocation/Initialization was successful. 10412 * -1 Allocation or Initialization failed. 10413 * 10414 * 10415 * If the returned value is 0, the buffer is initialized like this: 10416 * 10417 * +================================+ 10418 * +----> | struct scsi_pkt | 10419 * | | | 10420 * | +--- | pkt_ha_private | 10421 * | | | | 10422 * | | +================================+ 10423 * | | 10424 * | | +================================+ 10425 * | +--> | struct fcp_pkt | <---------+ 10426 * | | | | 10427 * +----- | cmd_pkt | | 10428 * | cmd_fp_pkt | ---+ | 10429 * +-------->| cmd_fcp_rsp[] | | | 10430 * | +--->| cmd_fcp_cmd[] | | | 10431 * | | |--------------------------------| | | 10432 * | | | struct fc_packet | <--+ | 10433 * | | | | | 10434 * | | | pkt_ulp_private | ----------+ 10435 * | | | pkt_fca_private | -----+ 10436 * | | | pkt_data_cookie | ---+ | 10437 * | | | pkt_cmdlen | | | 10438 * | |(a) | pkt_rsplen | | | 10439 * | +----| .......... pkt_cmd ........... | ---|-|---------------+ 10440 * | (b) | pkt_cmd_cookie | ---|-|----------+ | 10441 * +---------| .......... pkt_resp .......... | ---|-|------+ | | 10442 * | pkt_resp_cookie | ---|-|--+ | | | 10443 * | pkt_cmd_dma | | | | | | | 10444 * | pkt_cmd_acc | | | | | | | 10445 * +================================+ | | | | | | 10446 * | dma_cookies | <--+ | | | | | 10447 * | | | | | | | 10448 * +================================+ | | | | | 10449 * | fca_private | <----+ | | | | 10450 * | | | | | | 10451 * +================================+ | | | | 10452 * | | | | 10453 * | | | | 10454 * +================================+ (d) | | | | 10455 * | fcp_resp cookies | <-------+ | | | 10456 * | | | | | 10457 * +================================+ | | | 10458 * | | | 10459 * +================================+ (d) | | | 10460 * | fcp_resp | <-----------+ | | 10461 * | (DMA resources associated) | | | 10462 * +================================+ | | 10463 * | | 10464 * | | 10465 * | | 10466 * +================================+ (c) | | 10467 * | fcp_cmd cookies | <---------------+ | 10468 * | | | 10469 * +================================+ | 10470 * | 10471 * +================================+ (c) | 10472 * | fcp_cmd | <--------------------+ 10473 * | (DMA resources associated) | 10474 * +================================+ 10475 * 10476 * (a) Only if DMA is NOT used for the FCP_CMD buffer. 10477 * (b) Only if DMA is NOT used for the FCP_RESP buffer 10478 * (c) Only if DMA is used for the FCP_CMD buffer. 10479 * (d) Only if DMA is used for the FCP_RESP buffer 10480 */ 10481 static int 10482 fcp_kmem_cache_constructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran, 10483 int kmflags) 10484 { 10485 struct fcp_pkt *cmd; 10486 struct fcp_port *pptr; 10487 fc_packet_t *fpkt; 10488 10489 pptr = (struct fcp_port *)tran->tran_hba_private; 10490 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 10491 bzero(cmd, tran->tran_hba_len); 10492 10493 cmd->cmd_pkt = pkt; 10494 pkt->pkt_cdbp = cmd->cmd_fcp_cmd.fcp_cdb; 10495 fpkt = (fc_packet_t *)&cmd->cmd_fc_packet; 10496 cmd->cmd_fp_pkt = fpkt; 10497 10498 cmd->cmd_pkt->pkt_ha_private = (opaque_t)cmd; 10499 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 10500 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 10501 sizeof (struct fcp_pkt) + pptr->port_dmacookie_sz); 10502 10503 fpkt->pkt_data_cookie = (ddi_dma_cookie_t *)((caddr_t)cmd + 10504 sizeof (struct fcp_pkt)); 10505 10506 fpkt->pkt_cmdlen = sizeof (struct fcp_cmd); 10507 fpkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 10508 10509 if (pptr->port_fcp_dma == FC_NO_DVMA_SPACE) { 10510 /* 10511 * The underlying HBA doesn't want to DMA the fcp_cmd or 10512 * fcp_resp. The transfer of information will be done by 10513 * bcopy. 10514 * The naming of the flags (that is actually a value) is 10515 * unfortunate. FC_NO_DVMA_SPACE doesn't mean "NO VIRTUAL 10516 * DMA" but instead "NO DMA". 10517 */ 10518 fpkt->pkt_resp_acc = fpkt->pkt_cmd_acc = NULL; 10519 fpkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 10520 fpkt->pkt_resp = cmd->cmd_fcp_rsp; 10521 } else { 10522 /* 10523 * The underlying HBA will dma the fcp_cmd buffer and fcp_resp 10524 * buffer. A buffer is allocated for each one the ddi_dma_* 10525 * interfaces. 10526 */ 10527 if (fcp_alloc_cmd_resp(pptr, fpkt, kmflags) != FC_SUCCESS) { 10528 return (-1); 10529 } 10530 } 10531 10532 return (0); 10533 } 10534 10535 /* 10536 * Function: fcp_kmem_cache_destructor 10537 * 10538 * Description: Called by the destructor of the cache managed by SCSA. 10539 * All the resources pre-allocated in fcp_pkt_constructor 10540 * and the data also pre-initialized in fcp_pkt_constructor 10541 * are freed and uninitialized here. 10542 * 10543 * Argument: *buf Memory to uninitialize. 10544 * *arg FCP port structure (fcp_port). 10545 * 10546 * Return Value: None 10547 * 10548 * Context: kernel 10549 */ 10550 static void 10551 fcp_kmem_cache_destructor(struct scsi_pkt *pkt, scsi_hba_tran_t *tran) 10552 { 10553 struct fcp_pkt *cmd; 10554 struct fcp_port *pptr; 10555 10556 pptr = (struct fcp_port *)(tran->tran_hba_private); 10557 cmd = pkt->pkt_ha_private; 10558 10559 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 10560 /* 10561 * If DMA was used to transfer the FCP_CMD and FCP_RESP, the 10562 * buffer and DMA resources allocated to do so are released. 10563 */ 10564 fcp_free_cmd_resp(pptr, cmd->cmd_fp_pkt); 10565 } 10566 } 10567 10568 /* 10569 * Function: fcp_alloc_cmd_resp 10570 * 10571 * Description: This function allocated an FCP_CMD and FCP_RESP buffer that 10572 * will be DMAed by the HBA. The buffer is allocated applying 10573 * the DMA requirements for the HBA. The buffers allocated will 10574 * also be bound. DMA resources are allocated in the process. 10575 * They will be released by fcp_free_cmd_resp(). 10576 * 10577 * Argument: *pptr FCP port. 10578 * *fpkt fc packet for which the cmd and resp packet should be 10579 * allocated. 10580 * flags Allocation flags. 10581 * 10582 * Return Value: FC_FAILURE 10583 * FC_SUCCESS 10584 * 10585 * Context: User or Kernel context only if flags == KM_SLEEP. 10586 * Interrupt context if the KM_SLEEP is not specified. 10587 */ 10588 static int 10589 fcp_alloc_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt, int flags) 10590 { 10591 int rval; 10592 int cmd_len; 10593 int resp_len; 10594 ulong_t real_len; 10595 int (*cb) (caddr_t); 10596 ddi_dma_cookie_t pkt_cookie; 10597 ddi_dma_cookie_t *cp; 10598 uint32_t cnt; 10599 10600 cb = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 10601 10602 cmd_len = fpkt->pkt_cmdlen; 10603 resp_len = fpkt->pkt_rsplen; 10604 10605 ASSERT(fpkt->pkt_cmd_dma == NULL); 10606 10607 /* Allocation of a DMA handle used in subsequent calls. */ 10608 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_cmd_dma_attr, 10609 cb, NULL, &fpkt->pkt_cmd_dma) != DDI_SUCCESS) { 10610 return (FC_FAILURE); 10611 } 10612 10613 /* A buffer is allocated that satisfies the DMA requirements. */ 10614 rval = ddi_dma_mem_alloc(fpkt->pkt_cmd_dma, cmd_len, 10615 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10616 (caddr_t *)&fpkt->pkt_cmd, &real_len, &fpkt->pkt_cmd_acc); 10617 10618 if (rval != DDI_SUCCESS) { 10619 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10620 return (FC_FAILURE); 10621 } 10622 10623 if (real_len < cmd_len) { 10624 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10625 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10626 return (FC_FAILURE); 10627 } 10628 10629 /* The buffer allocated is DMA bound. */ 10630 rval = ddi_dma_addr_bind_handle(fpkt->pkt_cmd_dma, NULL, 10631 fpkt->pkt_cmd, real_len, DDI_DMA_WRITE | DDI_DMA_CONSISTENT, 10632 cb, NULL, &pkt_cookie, &fpkt->pkt_cmd_cookie_cnt); 10633 10634 if (rval != DDI_DMA_MAPPED) { 10635 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10636 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10637 return (FC_FAILURE); 10638 } 10639 10640 if (fpkt->pkt_cmd_cookie_cnt > 10641 pptr->port_cmd_dma_attr.dma_attr_sgllen) { 10642 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10643 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10644 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10645 return (FC_FAILURE); 10646 } 10647 10648 ASSERT(fpkt->pkt_cmd_cookie_cnt != 0); 10649 10650 /* 10651 * The buffer where the scatter/gather list is going to be built is 10652 * allocated. 10653 */ 10654 cp = fpkt->pkt_cmd_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10655 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie), 10656 KM_NOSLEEP); 10657 10658 if (cp == NULL) { 10659 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10660 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10661 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10662 return (FC_FAILURE); 10663 } 10664 10665 /* 10666 * The scatter/gather list for the buffer we just allocated is built 10667 * here. 10668 */ 10669 *cp = pkt_cookie; 10670 cp++; 10671 10672 for (cnt = 1; cnt < fpkt->pkt_cmd_cookie_cnt; cnt++, cp++) { 10673 ddi_dma_nextcookie(fpkt->pkt_cmd_dma, 10674 &pkt_cookie); 10675 *cp = pkt_cookie; 10676 } 10677 10678 ASSERT(fpkt->pkt_resp_dma == NULL); 10679 if (ddi_dma_alloc_handle(pptr->port_dip, &pptr->port_resp_dma_attr, 10680 cb, NULL, &fpkt->pkt_resp_dma) != DDI_SUCCESS) { 10681 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10682 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10683 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10684 return (FC_FAILURE); 10685 } 10686 10687 rval = ddi_dma_mem_alloc(fpkt->pkt_resp_dma, resp_len, 10688 &pptr->port_dma_acc_attr, DDI_DMA_CONSISTENT, cb, NULL, 10689 (caddr_t *)&fpkt->pkt_resp, &real_len, 10690 &fpkt->pkt_resp_acc); 10691 10692 if (rval != DDI_SUCCESS) { 10693 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10694 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10695 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10696 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10697 kmem_free(fpkt->pkt_cmd_cookie, 10698 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10699 return (FC_FAILURE); 10700 } 10701 10702 if (real_len < resp_len) { 10703 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10704 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10705 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10706 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10707 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10708 kmem_free(fpkt->pkt_cmd_cookie, 10709 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10710 return (FC_FAILURE); 10711 } 10712 10713 rval = ddi_dma_addr_bind_handle(fpkt->pkt_resp_dma, NULL, 10714 fpkt->pkt_resp, real_len, DDI_DMA_READ | DDI_DMA_CONSISTENT, 10715 cb, NULL, &pkt_cookie, &fpkt->pkt_resp_cookie_cnt); 10716 10717 if (rval != DDI_DMA_MAPPED) { 10718 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10719 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10720 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10721 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10722 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10723 kmem_free(fpkt->pkt_cmd_cookie, 10724 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10725 return (FC_FAILURE); 10726 } 10727 10728 if (fpkt->pkt_resp_cookie_cnt > 10729 pptr->port_resp_dma_attr.dma_attr_sgllen) { 10730 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10731 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10732 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10733 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10734 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10735 kmem_free(fpkt->pkt_cmd_cookie, 10736 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10737 return (FC_FAILURE); 10738 } 10739 10740 ASSERT(fpkt->pkt_resp_cookie_cnt != 0); 10741 10742 cp = fpkt->pkt_resp_cookie = (ddi_dma_cookie_t *)kmem_alloc( 10743 fpkt->pkt_resp_cookie_cnt * sizeof (pkt_cookie), 10744 KM_NOSLEEP); 10745 10746 if (cp == NULL) { 10747 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10748 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10749 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10750 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10751 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10752 kmem_free(fpkt->pkt_cmd_cookie, 10753 fpkt->pkt_cmd_cookie_cnt * sizeof (pkt_cookie)); 10754 return (FC_FAILURE); 10755 } 10756 10757 *cp = pkt_cookie; 10758 cp++; 10759 10760 for (cnt = 1; cnt < fpkt->pkt_resp_cookie_cnt; cnt++, cp++) { 10761 ddi_dma_nextcookie(fpkt->pkt_resp_dma, 10762 &pkt_cookie); 10763 *cp = pkt_cookie; 10764 } 10765 10766 return (FC_SUCCESS); 10767 } 10768 10769 /* 10770 * Function: fcp_free_cmd_resp 10771 * 10772 * Description: This function releases the FCP_CMD and FCP_RESP buffer 10773 * allocated by fcp_alloc_cmd_resp() and all the resources 10774 * associated with them. That includes the DMA resources and the 10775 * buffer allocated for the cookies of each one of them. 10776 * 10777 * Argument: *pptr FCP port context. 10778 * *fpkt fc packet containing the cmd and resp packet 10779 * to be released. 10780 * 10781 * Return Value: None 10782 * 10783 * Context: Interrupt, User and Kernel context. 10784 */ 10785 /* ARGSUSED */ 10786 static void 10787 fcp_free_cmd_resp(struct fcp_port *pptr, fc_packet_t *fpkt) 10788 { 10789 ASSERT(fpkt->pkt_resp_dma != NULL && fpkt->pkt_cmd_dma != NULL); 10790 10791 if (fpkt->pkt_resp_dma) { 10792 (void) ddi_dma_unbind_handle(fpkt->pkt_resp_dma); 10793 ddi_dma_mem_free(&fpkt->pkt_resp_acc); 10794 ddi_dma_free_handle(&fpkt->pkt_resp_dma); 10795 } 10796 10797 if (fpkt->pkt_resp_cookie) { 10798 kmem_free(fpkt->pkt_resp_cookie, 10799 fpkt->pkt_resp_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10800 fpkt->pkt_resp_cookie = NULL; 10801 } 10802 10803 if (fpkt->pkt_cmd_dma) { 10804 (void) ddi_dma_unbind_handle(fpkt->pkt_cmd_dma); 10805 ddi_dma_mem_free(&fpkt->pkt_cmd_acc); 10806 ddi_dma_free_handle(&fpkt->pkt_cmd_dma); 10807 } 10808 10809 if (fpkt->pkt_cmd_cookie) { 10810 kmem_free(fpkt->pkt_cmd_cookie, 10811 fpkt->pkt_cmd_cookie_cnt * sizeof (ddi_dma_cookie_t)); 10812 fpkt->pkt_cmd_cookie = NULL; 10813 } 10814 } 10815 10816 10817 /* 10818 * called by the transport to do our own target initialization 10819 * 10820 * can acquire and release the global mutex 10821 */ 10822 /* ARGSUSED */ 10823 static int 10824 fcp_phys_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10825 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10826 { 10827 uchar_t *bytes; 10828 uint_t nbytes; 10829 uint16_t lun_num; 10830 struct fcp_tgt *ptgt; 10831 struct fcp_lun *plun; 10832 struct fcp_port *pptr = (struct fcp_port *) 10833 hba_tran->tran_hba_private; 10834 10835 ASSERT(pptr != NULL); 10836 10837 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10838 FCP_BUF_LEVEL_8, 0, 10839 "fcp_phys_tgt_init: called for %s (instance %d)", 10840 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 10841 10842 /* get our port WWN property */ 10843 bytes = NULL; 10844 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10845 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10846 (nbytes != FC_WWN_SIZE)) { 10847 /* no port WWN property */ 10848 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10849 FCP_BUF_LEVEL_8, 0, 10850 "fcp_phys_tgt_init: Returning DDI_NOT_WELL_FORMED" 10851 " for %s (instance %d): bytes=%p nbytes=%x", 10852 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip), bytes, 10853 nbytes); 10854 10855 if (bytes != NULL) { 10856 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10857 } 10858 10859 return (DDI_NOT_WELL_FORMED); 10860 } 10861 ASSERT(bytes != NULL); 10862 10863 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10864 LUN_PROP, 0xFFFF); 10865 if (lun_num == 0xFFFF) { 10866 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10867 FCP_BUF_LEVEL_8, 0, 10868 "fcp_phys_tgt_init: Returning DDI_FAILURE:lun" 10869 " for %s (instance %d)", ddi_get_name(tgt_dip), 10870 ddi_get_instance(tgt_dip)); 10871 10872 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10873 return (DDI_NOT_WELL_FORMED); 10874 } 10875 10876 mutex_enter(&pptr->port_mutex); 10877 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10878 mutex_exit(&pptr->port_mutex); 10879 FCP_DTRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 10880 FCP_BUF_LEVEL_8, 0, 10881 "fcp_phys_tgt_init: Returning DDI_FAILURE: No Lun" 10882 " for %s (instance %d)", ddi_get_name(tgt_dip), 10883 ddi_get_instance(tgt_dip)); 10884 10885 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10886 return (DDI_FAILURE); 10887 } 10888 10889 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10890 FC_WWN_SIZE) == 0); 10891 ASSERT(plun->lun_num == lun_num); 10892 10893 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10894 10895 ptgt = plun->lun_tgt; 10896 10897 mutex_enter(&ptgt->tgt_mutex); 10898 plun->lun_tgt_count++; 10899 scsi_device_hba_private_set(sd, plun); 10900 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10901 plun->lun_sd = sd; 10902 mutex_exit(&ptgt->tgt_mutex); 10903 mutex_exit(&pptr->port_mutex); 10904 10905 return (DDI_SUCCESS); 10906 } 10907 10908 /*ARGSUSED*/ 10909 static int 10910 fcp_virt_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 10911 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 10912 { 10913 uchar_t *bytes; 10914 uint_t nbytes; 10915 uint16_t lun_num; 10916 struct fcp_tgt *ptgt; 10917 struct fcp_lun *plun; 10918 struct fcp_port *pptr = (struct fcp_port *) 10919 hba_tran->tran_hba_private; 10920 child_info_t *cip; 10921 10922 ASSERT(pptr != NULL); 10923 10924 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10925 fcp_trace, FCP_BUF_LEVEL_8, 0, 10926 "fcp_virt_tgt_init: called for %s (instance %d) (hba_dip %p)," 10927 " (tgt_dip %p)", ddi_get_name(tgt_dip), 10928 ddi_get_instance(tgt_dip), hba_dip, tgt_dip); 10929 10930 cip = (child_info_t *)sd->sd_pathinfo; 10931 if (cip == NULL) { 10932 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10933 fcp_trace, FCP_BUF_LEVEL_8, 0, 10934 "fcp_virt_tgt_init: Returning DDI_NOT_WELL_FORMED" 10935 " for %s (instance %d)", ddi_get_name(tgt_dip), 10936 ddi_get_instance(tgt_dip)); 10937 10938 return (DDI_NOT_WELL_FORMED); 10939 } 10940 10941 /* get our port WWN property */ 10942 bytes = NULL; 10943 if ((scsi_device_prop_lookup_byte_array(sd, SCSI_DEVICE_PROP_PATH, 10944 PORT_WWN_PROP, &bytes, &nbytes) != DDI_PROP_SUCCESS) || 10945 (nbytes != FC_WWN_SIZE)) { 10946 if (bytes) { 10947 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10948 } 10949 return (DDI_NOT_WELL_FORMED); 10950 } 10951 10952 ASSERT(bytes != NULL); 10953 10954 lun_num = scsi_device_prop_get_int(sd, SCSI_DEVICE_PROP_PATH, 10955 LUN_PROP, 0xFFFF); 10956 if (lun_num == 0xFFFF) { 10957 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10958 fcp_trace, FCP_BUF_LEVEL_8, 0, 10959 "fcp_virt_tgt_init: Returning DDI_FAILURE:lun" 10960 " for %s (instance %d)", ddi_get_name(tgt_dip), 10961 ddi_get_instance(tgt_dip)); 10962 10963 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10964 return (DDI_NOT_WELL_FORMED); 10965 } 10966 10967 mutex_enter(&pptr->port_mutex); 10968 if ((plun = fcp_lookup_lun(pptr, bytes, lun_num)) == NULL) { 10969 mutex_exit(&pptr->port_mutex); 10970 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 10971 fcp_trace, FCP_BUF_LEVEL_8, 0, 10972 "fcp_virt_tgt_init: Returning DDI_FAILURE: No Lun" 10973 " for %s (instance %d)", ddi_get_name(tgt_dip), 10974 ddi_get_instance(tgt_dip)); 10975 10976 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10977 return (DDI_FAILURE); 10978 } 10979 10980 ASSERT(bcmp(plun->lun_tgt->tgt_port_wwn.raw_wwn, bytes, 10981 FC_WWN_SIZE) == 0); 10982 ASSERT(plun->lun_num == lun_num); 10983 10984 scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, bytes); 10985 10986 ptgt = plun->lun_tgt; 10987 10988 mutex_enter(&ptgt->tgt_mutex); 10989 plun->lun_tgt_count++; 10990 scsi_device_hba_private_set(sd, plun); 10991 plun->lun_state |= FCP_SCSI_LUN_TGT_INIT; 10992 plun->lun_sd = sd; 10993 mutex_exit(&ptgt->tgt_mutex); 10994 mutex_exit(&pptr->port_mutex); 10995 10996 return (DDI_SUCCESS); 10997 } 10998 10999 11000 /* 11001 * called by the transport to do our own target initialization 11002 * 11003 * can acquire and release the global mutex 11004 */ 11005 /* ARGSUSED */ 11006 static int 11007 fcp_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11008 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11009 { 11010 struct fcp_port *pptr = (struct fcp_port *) 11011 hba_tran->tran_hba_private; 11012 int rval; 11013 11014 ASSERT(pptr != NULL); 11015 11016 /* 11017 * Child node is getting initialized. Look at the mpxio component 11018 * type on the child device to see if this device is mpxio managed 11019 * or not. 11020 */ 11021 if (mdi_component_is_client(tgt_dip, NULL) == MDI_SUCCESS) { 11022 rval = fcp_virt_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11023 } else { 11024 rval = fcp_phys_tgt_init(hba_dip, tgt_dip, hba_tran, sd); 11025 } 11026 11027 return (rval); 11028 } 11029 11030 11031 /* ARGSUSED */ 11032 static void 11033 fcp_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 11034 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 11035 { 11036 struct fcp_lun *plun = scsi_device_hba_private_get(sd); 11037 struct fcp_tgt *ptgt; 11038 11039 FCP_DTRACE(fcp_logq, LUN_PORT->port_instbuf, 11040 fcp_trace, FCP_BUF_LEVEL_8, 0, 11041 "fcp_scsi_tgt_free: called for tran %s%d, dev %s%d", 11042 ddi_get_name(hba_dip), ddi_get_instance(hba_dip), 11043 ddi_get_name(tgt_dip), ddi_get_instance(tgt_dip)); 11044 11045 if (plun == NULL) { 11046 return; 11047 } 11048 ptgt = plun->lun_tgt; 11049 11050 ASSERT(ptgt != NULL); 11051 11052 mutex_enter(&ptgt->tgt_mutex); 11053 ASSERT(plun->lun_tgt_count > 0); 11054 11055 if (--plun->lun_tgt_count == 0) { 11056 plun->lun_state &= ~FCP_SCSI_LUN_TGT_INIT; 11057 } 11058 plun->lun_sd = NULL; 11059 mutex_exit(&ptgt->tgt_mutex); 11060 } 11061 11062 /* 11063 * Function: fcp_scsi_start 11064 * 11065 * Description: This function is called by the target driver to request a 11066 * command to be sent. 11067 * 11068 * Argument: *ap SCSI address of the device. 11069 * *pkt SCSI packet containing the cmd to send. 11070 * 11071 * Return Value: TRAN_ACCEPT 11072 * TRAN_BUSY 11073 * TRAN_BADPKT 11074 * TRAN_FATAL_ERROR 11075 */ 11076 static int 11077 fcp_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 11078 { 11079 struct fcp_port *pptr = ADDR2FCP(ap); 11080 struct fcp_lun *plun = ADDR2LUN(ap); 11081 struct fcp_pkt *cmd = PKT2CMD(pkt); 11082 struct fcp_tgt *ptgt = plun->lun_tgt; 11083 int rval; 11084 11085 /* ensure command isn't already issued */ 11086 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 11087 11088 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11089 fcp_trace, FCP_BUF_LEVEL_9, 0, 11090 "fcp_transport Invoked for %x", plun->lun_tgt->tgt_d_id); 11091 11092 /* 11093 * It is strange that we enter the fcp_port mutex and the target 11094 * mutex to check the lun state (which has a mutex of its own). 11095 */ 11096 mutex_enter(&pptr->port_mutex); 11097 mutex_enter(&ptgt->tgt_mutex); 11098 11099 /* 11100 * If the device is offline and is not in the process of coming 11101 * online, fail the request. 11102 */ 11103 11104 if ((plun->lun_state & FCP_LUN_OFFLINE) && 11105 !(plun->lun_state & FCP_LUN_ONLINING)) { 11106 mutex_exit(&ptgt->tgt_mutex); 11107 mutex_exit(&pptr->port_mutex); 11108 11109 if (cmd->cmd_fp_pkt->pkt_pd == NULL) { 11110 pkt->pkt_reason = CMD_DEV_GONE; 11111 } 11112 11113 return (TRAN_FATAL_ERROR); 11114 } 11115 cmd->cmd_fp_pkt->pkt_timeout = pkt->pkt_time; 11116 11117 /* 11118 * If we are suspended, kernel is trying to dump, so don't 11119 * block, fail or defer requests - send them down right away. 11120 * NOTE: If we are in panic (i.e. trying to dump), we can't 11121 * assume we have been suspended. There is hardware such as 11122 * the v880 that doesn't do PM. Thus, the check for 11123 * ddi_in_panic. 11124 * 11125 * If FCP_STATE_IN_CB_DEVC is set, devices are in the process 11126 * of changing. So, if we can queue the packet, do it. Eventually, 11127 * either the device will have gone away or changed and we can fail 11128 * the request, or we can proceed if the device didn't change. 11129 * 11130 * If the pd in the target or the packet is NULL it's probably 11131 * because the device has gone away, we allow the request to be 11132 * put on the internal queue here in case the device comes back within 11133 * the offline timeout. fctl will fix up the pd's if the tgt_pd_handle 11134 * has gone NULL, while fcp deals cases where pkt_pd is NULL. pkt_pd 11135 * could be NULL because the device was disappearing during or since 11136 * packet initialization. 11137 */ 11138 11139 if (((plun->lun_state & FCP_LUN_BUSY) && (!(pptr->port_state & 11140 FCP_STATE_SUSPENDED)) && !ddi_in_panic()) || 11141 (pptr->port_state & (FCP_STATE_ONLINING | FCP_STATE_IN_CB_DEVC)) || 11142 (ptgt->tgt_pd_handle == NULL) || 11143 (cmd->cmd_fp_pkt->pkt_pd == NULL)) { 11144 /* 11145 * If ((LUN is busy AND 11146 * LUN not suspended AND 11147 * The system is not in panic state) OR 11148 * (The port is coming up)) 11149 * 11150 * We check to see if the any of the flags FLAG_NOINTR or 11151 * FLAG_NOQUEUE is set. If one of them is set the value 11152 * returned will be TRAN_BUSY. If not, the request is queued. 11153 */ 11154 mutex_exit(&ptgt->tgt_mutex); 11155 mutex_exit(&pptr->port_mutex); 11156 11157 /* see if using interrupts is allowed (so queueing'll work) */ 11158 if (pkt->pkt_flags & FLAG_NOINTR) { 11159 pkt->pkt_resid = 0; 11160 return (TRAN_BUSY); 11161 } 11162 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11163 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11164 fcp_trace, FCP_BUF_LEVEL_9, 0, 11165 "fcp_scsi_start: lun busy for pkt %p", pkt); 11166 return (TRAN_BUSY); 11167 } 11168 #ifdef DEBUG 11169 mutex_enter(&pptr->port_pkt_mutex); 11170 pptr->port_npkts++; 11171 mutex_exit(&pptr->port_pkt_mutex); 11172 #endif /* DEBUG */ 11173 11174 /* got queue up the pkt for later */ 11175 fcp_queue_pkt(pptr, cmd); 11176 return (TRAN_ACCEPT); 11177 } 11178 cmd->cmd_state = FCP_PKT_ISSUED; 11179 11180 mutex_exit(&ptgt->tgt_mutex); 11181 mutex_exit(&pptr->port_mutex); 11182 11183 /* 11184 * Now that we released the mutexes, what was protected by them can 11185 * change. 11186 */ 11187 11188 /* 11189 * If there is a reconfiguration in progress, wait for it to complete. 11190 */ 11191 fcp_reconfig_wait(pptr); 11192 11193 cmd->cmd_timeout = pkt->pkt_time ? fcp_watchdog_time + 11194 pkt->pkt_time : 0; 11195 11196 /* prepare the packet */ 11197 11198 fcp_prepare_pkt(pptr, cmd, plun); 11199 11200 if (cmd->cmd_pkt->pkt_time) { 11201 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11202 } else { 11203 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11204 } 11205 11206 /* 11207 * if interrupts aren't allowed (e.g. at dump time) then we'll 11208 * have to do polled I/O 11209 */ 11210 if (pkt->pkt_flags & FLAG_NOINTR) { 11211 cmd->cmd_state &= ~FCP_PKT_ISSUED; 11212 return (fcp_dopoll(pptr, cmd)); 11213 } 11214 11215 #ifdef DEBUG 11216 mutex_enter(&pptr->port_pkt_mutex); 11217 pptr->port_npkts++; 11218 mutex_exit(&pptr->port_pkt_mutex); 11219 #endif /* DEBUG */ 11220 11221 rval = fcp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt, 0); 11222 if (rval == FC_SUCCESS) { 11223 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11224 fcp_trace, FCP_BUF_LEVEL_9, 0, 11225 "fcp_transport success for %x", plun->lun_tgt->tgt_d_id); 11226 return (TRAN_ACCEPT); 11227 } 11228 11229 cmd->cmd_state = FCP_PKT_IDLE; 11230 11231 #ifdef DEBUG 11232 mutex_enter(&pptr->port_pkt_mutex); 11233 pptr->port_npkts--; 11234 mutex_exit(&pptr->port_pkt_mutex); 11235 #endif /* DEBUG */ 11236 11237 /* 11238 * For lack of clearer definitions, choose 11239 * between TRAN_BUSY and TRAN_FATAL_ERROR. 11240 */ 11241 11242 if (rval == FC_TRAN_BUSY) { 11243 pkt->pkt_resid = 0; 11244 rval = TRAN_BUSY; 11245 } else { 11246 mutex_enter(&ptgt->tgt_mutex); 11247 if (plun->lun_state & FCP_LUN_OFFLINE) { 11248 child_info_t *cip; 11249 11250 mutex_enter(&plun->lun_mutex); 11251 cip = plun->lun_cip; 11252 mutex_exit(&plun->lun_mutex); 11253 11254 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11255 fcp_trace, FCP_BUF_LEVEL_6, 0, 11256 "fcp_transport failed 2 for %x: %x; dip=%p", 11257 plun->lun_tgt->tgt_d_id, rval, cip); 11258 11259 rval = TRAN_FATAL_ERROR; 11260 } else { 11261 if (pkt->pkt_flags & FLAG_NOQUEUE) { 11262 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 11263 fcp_trace, FCP_BUF_LEVEL_9, 0, 11264 "fcp_scsi_start: FC_BUSY for pkt %p", 11265 pkt); 11266 rval = TRAN_BUSY; 11267 } else { 11268 rval = TRAN_ACCEPT; 11269 fcp_queue_pkt(pptr, cmd); 11270 } 11271 } 11272 mutex_exit(&ptgt->tgt_mutex); 11273 } 11274 11275 return (rval); 11276 } 11277 11278 /* 11279 * called by the transport to abort a packet 11280 */ 11281 /*ARGSUSED*/ 11282 static int 11283 fcp_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 11284 { 11285 int tgt_cnt; 11286 struct fcp_port *pptr = ADDR2FCP(ap); 11287 struct fcp_lun *plun = ADDR2LUN(ap); 11288 struct fcp_tgt *ptgt = plun->lun_tgt; 11289 11290 if (pkt == NULL) { 11291 if (ptgt) { 11292 mutex_enter(&ptgt->tgt_mutex); 11293 tgt_cnt = ptgt->tgt_change_cnt; 11294 mutex_exit(&ptgt->tgt_mutex); 11295 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 11296 return (TRUE); 11297 } 11298 } 11299 return (FALSE); 11300 } 11301 11302 11303 /* 11304 * Perform reset 11305 */ 11306 int 11307 fcp_scsi_reset(struct scsi_address *ap, int level) 11308 { 11309 int rval = 0; 11310 struct fcp_port *pptr = ADDR2FCP(ap); 11311 struct fcp_lun *plun = ADDR2LUN(ap); 11312 struct fcp_tgt *ptgt = plun->lun_tgt; 11313 11314 if (level == RESET_ALL) { 11315 if (fcp_linkreset(pptr, ap, KM_NOSLEEP) == FC_SUCCESS) { 11316 rval = 1; 11317 } 11318 } else if (level == RESET_TARGET || level == RESET_LUN) { 11319 /* 11320 * If we are in the middle of discovery, return 11321 * SUCCESS as this target will be rediscovered 11322 * anyway 11323 */ 11324 mutex_enter(&ptgt->tgt_mutex); 11325 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11326 mutex_exit(&ptgt->tgt_mutex); 11327 return (1); 11328 } 11329 mutex_exit(&ptgt->tgt_mutex); 11330 11331 if (fcp_reset_target(ap, level) == FC_SUCCESS) { 11332 rval = 1; 11333 } 11334 } 11335 return (rval); 11336 } 11337 11338 11339 /* 11340 * called by the framework to get a SCSI capability 11341 */ 11342 static int 11343 fcp_scsi_getcap(struct scsi_address *ap, char *cap, int whom) 11344 { 11345 return (fcp_commoncap(ap, cap, 0, whom, 0)); 11346 } 11347 11348 11349 /* 11350 * called by the framework to set a SCSI capability 11351 */ 11352 static int 11353 fcp_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) 11354 { 11355 return (fcp_commoncap(ap, cap, value, whom, 1)); 11356 } 11357 11358 /* 11359 * Function: fcp_pkt_setup 11360 * 11361 * Description: This function sets up the scsi_pkt structure passed by the 11362 * caller. This function assumes fcp_pkt_constructor has been 11363 * called previously for the packet passed by the caller. If 11364 * successful this call will have the following results: 11365 * 11366 * - The resources needed that will be constant through out 11367 * the whole transaction are allocated. 11368 * - The fields that will be constant through out the whole 11369 * transaction are initialized. 11370 * - The scsi packet will be linked to the LUN structure 11371 * addressed by the transaction. 11372 * 11373 * Argument: 11374 * *pkt Pointer to a scsi_pkt structure. 11375 * callback 11376 * arg 11377 * 11378 * Return Value: 0 Success 11379 * !0 Failure 11380 * 11381 * Context: Kernel context or interrupt context 11382 */ 11383 /* ARGSUSED */ 11384 static int 11385 fcp_pkt_setup(struct scsi_pkt *pkt, 11386 int (*callback)(caddr_t arg), 11387 caddr_t arg) 11388 { 11389 struct fcp_pkt *cmd; 11390 struct fcp_port *pptr; 11391 struct fcp_lun *plun; 11392 struct fcp_tgt *ptgt; 11393 int kf; 11394 fc_packet_t *fpkt; 11395 fc_frame_hdr_t *hp; 11396 11397 pptr = ADDR2FCP(&pkt->pkt_address); 11398 plun = ADDR2LUN(&pkt->pkt_address); 11399 ptgt = plun->lun_tgt; 11400 11401 cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11402 fpkt = cmd->cmd_fp_pkt; 11403 11404 /* 11405 * this request is for dma allocation only 11406 */ 11407 /* 11408 * First step of fcp_scsi_init_pkt: pkt allocation 11409 * We determine if the caller is willing to wait for the 11410 * resources. 11411 */ 11412 kf = (callback == SLEEP_FUNC) ? KM_SLEEP: KM_NOSLEEP; 11413 11414 /* 11415 * Selective zeroing of the pkt. 11416 */ 11417 cmd->cmd_back = NULL; 11418 cmd->cmd_next = NULL; 11419 11420 /* 11421 * Zero out fcp command 11422 */ 11423 bzero(&cmd->cmd_fcp_cmd, sizeof (cmd->cmd_fcp_cmd)); 11424 11425 cmd->cmd_state = FCP_PKT_IDLE; 11426 11427 fpkt = cmd->cmd_fp_pkt; 11428 fpkt->pkt_data_acc = NULL; 11429 11430 /* 11431 * When port_state is FCP_STATE_OFFLINE, remote_port (tgt_pd_handle) 11432 * could be destroyed. We need fail pkt_setup. 11433 */ 11434 if (pptr->port_state & FCP_STATE_OFFLINE) { 11435 return (-1); 11436 } 11437 11438 mutex_enter(&ptgt->tgt_mutex); 11439 fpkt->pkt_pd = ptgt->tgt_pd_handle; 11440 11441 if (fc_ulp_init_packet(pptr->port_fp_handle, fpkt, kf) 11442 != FC_SUCCESS) { 11443 mutex_exit(&ptgt->tgt_mutex); 11444 return (-1); 11445 } 11446 11447 mutex_exit(&ptgt->tgt_mutex); 11448 11449 /* Fill in the Fabric Channel Header */ 11450 hp = &fpkt->pkt_cmd_fhdr; 11451 hp->r_ctl = R_CTL_COMMAND; 11452 hp->rsvd = 0; 11453 hp->type = FC_TYPE_SCSI_FCP; 11454 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 11455 hp->seq_id = 0; 11456 hp->df_ctl = 0; 11457 hp->seq_cnt = 0; 11458 hp->ox_id = 0xffff; 11459 hp->rx_id = 0xffff; 11460 hp->ro = 0; 11461 11462 /* 11463 * A doubly linked list (cmd_forw, cmd_back) is built 11464 * out of every allocated packet on a per-lun basis 11465 * 11466 * The packets are maintained in the list so as to satisfy 11467 * scsi_abort() requests. At present (which is unlikely to 11468 * change in the future) nobody performs a real scsi_abort 11469 * in the SCSI target drivers (as they don't keep the packets 11470 * after doing scsi_transport - so they don't know how to 11471 * abort a packet other than sending a NULL to abort all 11472 * outstanding packets) 11473 */ 11474 mutex_enter(&plun->lun_mutex); 11475 if ((cmd->cmd_forw = plun->lun_pkt_head) != NULL) { 11476 plun->lun_pkt_head->cmd_back = cmd; 11477 } else { 11478 plun->lun_pkt_tail = cmd; 11479 } 11480 plun->lun_pkt_head = cmd; 11481 mutex_exit(&plun->lun_mutex); 11482 return (0); 11483 } 11484 11485 /* 11486 * Function: fcp_pkt_teardown 11487 * 11488 * Description: This function releases a scsi_pkt structure and all the 11489 * resources attached to it. 11490 * 11491 * Argument: *pkt Pointer to a scsi_pkt structure. 11492 * 11493 * Return Value: None 11494 * 11495 * Context: User, Kernel or Interrupt context. 11496 */ 11497 static void 11498 fcp_pkt_teardown(struct scsi_pkt *pkt) 11499 { 11500 struct fcp_port *pptr = ADDR2FCP(&pkt->pkt_address); 11501 struct fcp_lun *plun = ADDR2LUN(&pkt->pkt_address); 11502 struct fcp_pkt *cmd = (struct fcp_pkt *)pkt->pkt_ha_private; 11503 11504 /* 11505 * Remove the packet from the per-lun list 11506 */ 11507 mutex_enter(&plun->lun_mutex); 11508 if (cmd->cmd_back) { 11509 ASSERT(cmd != plun->lun_pkt_head); 11510 cmd->cmd_back->cmd_forw = cmd->cmd_forw; 11511 } else { 11512 ASSERT(cmd == plun->lun_pkt_head); 11513 plun->lun_pkt_head = cmd->cmd_forw; 11514 } 11515 11516 if (cmd->cmd_forw) { 11517 cmd->cmd_forw->cmd_back = cmd->cmd_back; 11518 } else { 11519 ASSERT(cmd == plun->lun_pkt_tail); 11520 plun->lun_pkt_tail = cmd->cmd_back; 11521 } 11522 11523 mutex_exit(&plun->lun_mutex); 11524 11525 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt); 11526 } 11527 11528 /* 11529 * Routine for reset notification setup, to register or cancel. 11530 * This function is called by SCSA 11531 */ 11532 /*ARGSUSED*/ 11533 static int 11534 fcp_scsi_reset_notify(struct scsi_address *ap, int flag, 11535 void (*callback)(caddr_t), caddr_t arg) 11536 { 11537 struct fcp_port *pptr = ADDR2FCP(ap); 11538 11539 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 11540 &pptr->port_mutex, &pptr->port_reset_notify_listf)); 11541 } 11542 11543 11544 static int 11545 fcp_scsi_bus_get_eventcookie(dev_info_t *dip, dev_info_t *rdip, char *name, 11546 ddi_eventcookie_t *event_cookiep) 11547 { 11548 struct fcp_port *pptr = fcp_dip2port(dip); 11549 11550 if (pptr == NULL) { 11551 return (DDI_FAILURE); 11552 } 11553 11554 return (ndi_event_retrieve_cookie(pptr->port_ndi_event_hdl, rdip, name, 11555 event_cookiep, NDI_EVENT_NOPASS)); 11556 } 11557 11558 11559 static int 11560 fcp_scsi_bus_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 11561 ddi_eventcookie_t eventid, void (*callback)(), void *arg, 11562 ddi_callback_id_t *cb_id) 11563 { 11564 struct fcp_port *pptr = fcp_dip2port(dip); 11565 11566 if (pptr == NULL) { 11567 return (DDI_FAILURE); 11568 } 11569 11570 return (ndi_event_add_callback(pptr->port_ndi_event_hdl, rdip, 11571 eventid, callback, arg, NDI_SLEEP, cb_id)); 11572 } 11573 11574 11575 static int 11576 fcp_scsi_bus_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 11577 { 11578 11579 struct fcp_port *pptr = fcp_dip2port(dip); 11580 11581 if (pptr == NULL) { 11582 return (DDI_FAILURE); 11583 } 11584 return (ndi_event_remove_callback(pptr->port_ndi_event_hdl, cb_id)); 11585 } 11586 11587 11588 /* 11589 * called by the transport to post an event 11590 */ 11591 static int 11592 fcp_scsi_bus_post_event(dev_info_t *dip, dev_info_t *rdip, 11593 ddi_eventcookie_t eventid, void *impldata) 11594 { 11595 struct fcp_port *pptr = fcp_dip2port(dip); 11596 11597 if (pptr == NULL) { 11598 return (DDI_FAILURE); 11599 } 11600 11601 return (ndi_event_run_callbacks(pptr->port_ndi_event_hdl, rdip, 11602 eventid, impldata)); 11603 } 11604 11605 11606 /* 11607 * A target in in many cases in Fibre Channel has a one to one relation 11608 * with a port identifier (which is also known as D_ID and also as AL_PA 11609 * in private Loop) On Fibre Channel-to-SCSI bridge boxes a target reset 11610 * will most likely result in resetting all LUNs (which means a reset will 11611 * occur on all the SCSI devices connected at the other end of the bridge) 11612 * That is the latest favorite topic for discussion, for, one can debate as 11613 * hot as one likes and come up with arguably a best solution to one's 11614 * satisfaction 11615 * 11616 * To stay on track and not digress much, here are the problems stated 11617 * briefly: 11618 * 11619 * SCSA doesn't define RESET_LUN, It defines RESET_TARGET, but the 11620 * target drivers use RESET_TARGET even if their instance is on a 11621 * LUN. Doesn't that sound a bit broken ? 11622 * 11623 * FCP SCSI (the current spec) only defines RESET TARGET in the 11624 * control fields of an FCP_CMND structure. It should have been 11625 * fixed right there, giving flexibility to the initiators to 11626 * minimize havoc that could be caused by resetting a target. 11627 */ 11628 static int 11629 fcp_reset_target(struct scsi_address *ap, int level) 11630 { 11631 int rval = FC_FAILURE; 11632 char lun_id[25]; 11633 struct fcp_port *pptr = ADDR2FCP(ap); 11634 struct fcp_lun *plun = ADDR2LUN(ap); 11635 struct fcp_tgt *ptgt = plun->lun_tgt; 11636 struct scsi_pkt *pkt; 11637 struct fcp_pkt *cmd; 11638 struct fcp_rsp *rsp; 11639 uint32_t tgt_cnt; 11640 struct fcp_rsp_info *rsp_info; 11641 struct fcp_reset_elem *p; 11642 int bval; 11643 11644 if ((p = kmem_alloc(sizeof (struct fcp_reset_elem), 11645 KM_NOSLEEP)) == NULL) { 11646 return (rval); 11647 } 11648 11649 mutex_enter(&ptgt->tgt_mutex); 11650 if (level == RESET_TARGET) { 11651 if (ptgt->tgt_state & (FCP_TGT_OFFLINE | FCP_TGT_BUSY)) { 11652 mutex_exit(&ptgt->tgt_mutex); 11653 kmem_free(p, sizeof (struct fcp_reset_elem)); 11654 return (rval); 11655 } 11656 fcp_update_tgt_state(ptgt, FCP_SET, FCP_LUN_BUSY); 11657 (void) strcpy(lun_id, " "); 11658 } else { 11659 if (plun->lun_state & (FCP_LUN_OFFLINE | FCP_LUN_BUSY)) { 11660 mutex_exit(&ptgt->tgt_mutex); 11661 kmem_free(p, sizeof (struct fcp_reset_elem)); 11662 return (rval); 11663 } 11664 fcp_update_lun_state(plun, FCP_SET, FCP_LUN_BUSY); 11665 11666 (void) sprintf(lun_id, ", LUN=%d", plun->lun_num); 11667 } 11668 tgt_cnt = ptgt->tgt_change_cnt; 11669 11670 mutex_exit(&ptgt->tgt_mutex); 11671 11672 if ((pkt = scsi_init_pkt(ap, NULL, NULL, 0, 0, 11673 0, 0, NULL, 0)) == NULL) { 11674 kmem_free(p, sizeof (struct fcp_reset_elem)); 11675 mutex_enter(&ptgt->tgt_mutex); 11676 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11677 mutex_exit(&ptgt->tgt_mutex); 11678 return (rval); 11679 } 11680 pkt->pkt_time = FCP_POLL_TIMEOUT; 11681 11682 /* fill in cmd part of packet */ 11683 cmd = PKT2CMD(pkt); 11684 if (level == RESET_TARGET) { 11685 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_tgt = 1; 11686 } else { 11687 cmd->cmd_fcp_cmd.fcp_cntl.cntl_reset_lun = 1; 11688 } 11689 cmd->cmd_fp_pkt->pkt_comp = NULL; 11690 cmd->cmd_pkt->pkt_flags |= FLAG_NOINTR; 11691 11692 /* prepare a packet for transport */ 11693 fcp_prepare_pkt(pptr, cmd, plun); 11694 11695 if (cmd->cmd_pkt->pkt_time) { 11696 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 11697 } else { 11698 cmd->cmd_fp_pkt->pkt_timeout = 5 * 60 * 60; 11699 } 11700 11701 (void) fc_ulp_busy_port(pptr->port_fp_handle); 11702 bval = fcp_dopoll(pptr, cmd); 11703 fc_ulp_idle_port(pptr->port_fp_handle); 11704 11705 /* submit the packet */ 11706 if (bval == TRAN_ACCEPT) { 11707 int error = 3; 11708 11709 rsp = (struct fcp_rsp *)cmd->cmd_fcp_rsp; 11710 rsp_info = (struct fcp_rsp_info *)(cmd->cmd_fcp_rsp + 11711 sizeof (struct fcp_rsp)); 11712 11713 if (rsp->fcp_u.fcp_status.rsp_len_set) { 11714 if (fcp_validate_fcp_response(rsp, pptr) == 11715 FC_SUCCESS) { 11716 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 11717 FCP_CP_IN(cmd->cmd_fp_pkt->pkt_resp + 11718 sizeof (struct fcp_rsp), rsp_info, 11719 cmd->cmd_fp_pkt->pkt_resp_acc, 11720 sizeof (struct fcp_rsp_info)); 11721 } 11722 if (rsp_info->rsp_code == FCP_NO_FAILURE) { 11723 rval = FC_SUCCESS; 11724 error = 0; 11725 } else { 11726 error = 1; 11727 } 11728 } else { 11729 error = 2; 11730 } 11731 } 11732 11733 switch (error) { 11734 case 0: 11735 fcp_log(CE_WARN, pptr->port_dip, 11736 "!FCP: WWN 0x%08x%08x %s reset successfully", 11737 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11738 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11739 break; 11740 11741 case 1: 11742 fcp_log(CE_WARN, pptr->port_dip, 11743 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11744 " response code=%x", 11745 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11746 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11747 rsp_info->rsp_code); 11748 break; 11749 11750 case 2: 11751 fcp_log(CE_WARN, pptr->port_dip, 11752 "!FCP: Reset to WWN 0x%08x%08x %s failed," 11753 " Bad FCP response values: rsvd1=%x," 11754 " rsvd2=%x, sts-rsvd1=%x, sts-rsvd2=%x," 11755 " rsplen=%x, senselen=%x", 11756 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11757 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id, 11758 rsp->reserved_0, rsp->reserved_1, 11759 rsp->fcp_u.fcp_status.reserved_0, 11760 rsp->fcp_u.fcp_status.reserved_1, 11761 rsp->fcp_response_len, rsp->fcp_sense_len); 11762 break; 11763 11764 default: 11765 fcp_log(CE_WARN, pptr->port_dip, 11766 "!FCP: Reset to WWN 0x%08x%08x %s failed", 11767 *((int *)&ptgt->tgt_port_wwn.raw_wwn[0]), 11768 *((int *)&ptgt->tgt_port_wwn.raw_wwn[4]), lun_id); 11769 break; 11770 } 11771 } 11772 scsi_destroy_pkt(pkt); 11773 11774 if (rval == FC_FAILURE) { 11775 mutex_enter(&ptgt->tgt_mutex); 11776 if (level == RESET_TARGET) { 11777 fcp_update_tgt_state(ptgt, FCP_RESET, FCP_LUN_BUSY); 11778 } else { 11779 fcp_update_lun_state(plun, FCP_RESET, FCP_LUN_BUSY); 11780 } 11781 mutex_exit(&ptgt->tgt_mutex); 11782 kmem_free(p, sizeof (struct fcp_reset_elem)); 11783 return (rval); 11784 } 11785 11786 mutex_enter(&pptr->port_mutex); 11787 if (level == RESET_TARGET) { 11788 p->tgt = ptgt; 11789 p->lun = NULL; 11790 } else { 11791 p->tgt = NULL; 11792 p->lun = plun; 11793 } 11794 p->tgt = ptgt; 11795 p->tgt_cnt = tgt_cnt; 11796 p->timeout = fcp_watchdog_time + FCP_RESET_DELAY; 11797 p->next = pptr->port_reset_list; 11798 pptr->port_reset_list = p; 11799 11800 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11801 fcp_trace, FCP_BUF_LEVEL_3, 0, 11802 "Notify ssd of the reset to reinstate the reservations"); 11803 11804 scsi_hba_reset_notify_callback(&pptr->port_mutex, 11805 &pptr->port_reset_notify_listf); 11806 11807 mutex_exit(&pptr->port_mutex); 11808 11809 return (rval); 11810 } 11811 11812 11813 /* 11814 * called by fcp_getcap and fcp_setcap to get and set (respectively) 11815 * SCSI capabilities 11816 */ 11817 /* ARGSUSED */ 11818 static int 11819 fcp_commoncap(struct scsi_address *ap, char *cap, 11820 int val, int tgtonly, int doset) 11821 { 11822 struct fcp_port *pptr = ADDR2FCP(ap); 11823 struct fcp_lun *plun = ADDR2LUN(ap); 11824 struct fcp_tgt *ptgt = plun->lun_tgt; 11825 int cidx; 11826 int rval = FALSE; 11827 11828 if (cap == (char *)0) { 11829 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11830 fcp_trace, FCP_BUF_LEVEL_3, 0, 11831 "fcp_commoncap: invalid arg"); 11832 return (rval); 11833 } 11834 11835 if ((cidx = scsi_hba_lookup_capstr(cap)) == -1) { 11836 return (UNDEFINED); 11837 } 11838 11839 /* 11840 * Process setcap request. 11841 */ 11842 if (doset) { 11843 /* 11844 * At present, we can only set binary (0/1) values 11845 */ 11846 switch (cidx) { 11847 case SCSI_CAP_ARQ: 11848 if (val == 0) { 11849 rval = FALSE; 11850 } else { 11851 rval = TRUE; 11852 } 11853 break; 11854 11855 case SCSI_CAP_LUN_RESET: 11856 if (val) { 11857 plun->lun_cap |= FCP_LUN_CAP_RESET; 11858 } else { 11859 plun->lun_cap &= ~FCP_LUN_CAP_RESET; 11860 } 11861 rval = TRUE; 11862 break; 11863 11864 case SCSI_CAP_SECTOR_SIZE: 11865 rval = TRUE; 11866 break; 11867 default: 11868 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11869 fcp_trace, FCP_BUF_LEVEL_4, 0, 11870 "fcp_setcap: unsupported %d", cidx); 11871 rval = UNDEFINED; 11872 break; 11873 } 11874 11875 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11876 fcp_trace, FCP_BUF_LEVEL_5, 0, 11877 "set cap: cap=%s, val/tgtonly/doset/rval = " 11878 "0x%x/0x%x/0x%x/%d", 11879 cap, val, tgtonly, doset, rval); 11880 11881 } else { 11882 /* 11883 * Process getcap request. 11884 */ 11885 switch (cidx) { 11886 case SCSI_CAP_DMA_MAX: 11887 rval = (int)pptr->port_data_dma_attr.dma_attr_maxxfer; 11888 11889 /* 11890 * Need to make an adjustment qlc is uint_t 64 11891 * st is int, so we will make the adjustment here 11892 * being as nobody wants to touch this. 11893 * It still leaves the max single block length 11894 * of 2 gig. This should last . 11895 */ 11896 11897 if (rval == -1) { 11898 rval = MAX_INT_DMA; 11899 } 11900 11901 break; 11902 11903 case SCSI_CAP_INITIATOR_ID: 11904 rval = pptr->port_id; 11905 break; 11906 11907 case SCSI_CAP_ARQ: 11908 case SCSI_CAP_RESET_NOTIFICATION: 11909 case SCSI_CAP_TAGGED_QING: 11910 rval = TRUE; 11911 break; 11912 11913 case SCSI_CAP_SCSI_VERSION: 11914 rval = 3; 11915 break; 11916 11917 case SCSI_CAP_INTERCONNECT_TYPE: 11918 if (FC_TOP_EXTERNAL(pptr->port_topology) || 11919 (ptgt->tgt_hard_addr == 0)) { 11920 rval = INTERCONNECT_FABRIC; 11921 } else { 11922 rval = INTERCONNECT_FIBRE; 11923 } 11924 break; 11925 11926 case SCSI_CAP_LUN_RESET: 11927 rval = ((plun->lun_cap & FCP_LUN_CAP_RESET) != 0) ? 11928 TRUE : FALSE; 11929 break; 11930 11931 default: 11932 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11933 fcp_trace, FCP_BUF_LEVEL_4, 0, 11934 "fcp_getcap: unsupported %d", cidx); 11935 rval = UNDEFINED; 11936 break; 11937 } 11938 11939 FCP_TRACE(fcp_logq, pptr->port_instbuf, 11940 fcp_trace, FCP_BUF_LEVEL_8, 0, 11941 "get cap: cap=%s, val/tgtonly/doset/rval = " 11942 "0x%x/0x%x/0x%x/%d", 11943 cap, val, tgtonly, doset, rval); 11944 } 11945 11946 return (rval); 11947 } 11948 11949 /* 11950 * called by the transport to get the port-wwn and lun 11951 * properties of this device, and to create a "name" based on them 11952 * 11953 * these properties don't exist on sun4m 11954 * 11955 * return 1 for success else return 0 11956 */ 11957 /* ARGSUSED */ 11958 static int 11959 fcp_scsi_get_name(struct scsi_device *sd, char *name, int len) 11960 { 11961 int i; 11962 int *lun; 11963 int numChars; 11964 uint_t nlun; 11965 uint_t count; 11966 uint_t nbytes; 11967 uchar_t *bytes; 11968 uint16_t lun_num; 11969 uint32_t tgt_id; 11970 char **conf_wwn; 11971 char tbuf[(FC_WWN_SIZE << 1) + 1]; 11972 uchar_t barray[FC_WWN_SIZE]; 11973 dev_info_t *tgt_dip; 11974 struct fcp_tgt *ptgt; 11975 struct fcp_port *pptr; 11976 struct fcp_lun *plun; 11977 11978 ASSERT(sd != NULL); 11979 ASSERT(name != NULL); 11980 11981 tgt_dip = sd->sd_dev; 11982 pptr = ddi_get_soft_state(fcp_softstate, 11983 ddi_get_instance(ddi_get_parent(tgt_dip))); 11984 if (pptr == NULL) { 11985 return (0); 11986 } 11987 11988 ASSERT(tgt_dip != NULL); 11989 11990 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, sd->sd_dev, 11991 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 11992 LUN_PROP, &lun, &nlun) != DDI_SUCCESS) { 11993 name[0] = '\0'; 11994 return (0); 11995 } 11996 11997 if (nlun == 0) { 11998 ddi_prop_free(lun); 11999 return (0); 12000 } 12001 12002 lun_num = lun[0]; 12003 ddi_prop_free(lun); 12004 12005 /* 12006 * Lookup for .conf WWN property 12007 */ 12008 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, tgt_dip, 12009 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, CONF_WWN_PROP, 12010 &conf_wwn, &count) == DDI_PROP_SUCCESS) { 12011 ASSERT(count >= 1); 12012 12013 fcp_ascii_to_wwn(conf_wwn[0], barray, FC_WWN_SIZE); 12014 ddi_prop_free(conf_wwn); 12015 mutex_enter(&pptr->port_mutex); 12016 if ((plun = fcp_lookup_lun(pptr, barray, lun_num)) == NULL) { 12017 mutex_exit(&pptr->port_mutex); 12018 return (0); 12019 } 12020 ptgt = plun->lun_tgt; 12021 mutex_exit(&pptr->port_mutex); 12022 12023 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 12024 tgt_dip, PORT_WWN_PROP, barray, FC_WWN_SIZE); 12025 12026 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12027 ptgt->tgt_hard_addr != 0) { 12028 tgt_id = (uint32_t)fcp_alpa_to_switch[ 12029 ptgt->tgt_hard_addr]; 12030 } else { 12031 tgt_id = ptgt->tgt_d_id; 12032 } 12033 12034 (void) ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, 12035 TARGET_PROP, tgt_id); 12036 } 12037 12038 /* get the our port-wwn property */ 12039 bytes = NULL; 12040 if ((ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, tgt_dip, 12041 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12042 &nbytes) != DDI_PROP_SUCCESS) || nbytes != FC_WWN_SIZE) { 12043 if (bytes != NULL) { 12044 ddi_prop_free(bytes); 12045 } 12046 return (0); 12047 } 12048 12049 for (i = 0; i < FC_WWN_SIZE; i++) { 12050 (void) sprintf(&tbuf[i << 1], "%02x", *(bytes + i)); 12051 } 12052 12053 /* Stick in the address of the form "wWWN,LUN" */ 12054 numChars = snprintf(name, len, "w%s,%x", tbuf, lun_num); 12055 12056 ASSERT(numChars < len); 12057 if (numChars >= len) { 12058 fcp_log(CE_WARN, pptr->port_dip, 12059 "!fcp_scsi_get_name: " 12060 "name parameter length too small, it needs to be %d", 12061 numChars+1); 12062 } 12063 12064 ddi_prop_free(bytes); 12065 12066 return (1); 12067 } 12068 12069 12070 /* 12071 * called by the transport to get the SCSI target id value, returning 12072 * it in "name" 12073 * 12074 * this isn't needed/used on sun4m 12075 * 12076 * return 1 for success else return 0 12077 */ 12078 /* ARGSUSED */ 12079 static int 12080 fcp_scsi_get_bus_addr(struct scsi_device *sd, char *name, int len) 12081 { 12082 struct fcp_lun *plun = ADDR2LUN(&sd->sd_address); 12083 struct fcp_tgt *ptgt; 12084 int numChars; 12085 12086 if (plun == NULL) { 12087 return (0); 12088 } 12089 12090 if ((ptgt = plun->lun_tgt) == NULL) { 12091 return (0); 12092 } 12093 12094 numChars = snprintf(name, len, "%x", ptgt->tgt_d_id); 12095 12096 ASSERT(numChars < len); 12097 if (numChars >= len) { 12098 fcp_log(CE_WARN, NULL, 12099 "!fcp_scsi_get_bus_addr: " 12100 "name parameter length too small, it needs to be %d", 12101 numChars+1); 12102 } 12103 12104 return (1); 12105 } 12106 12107 12108 /* 12109 * called internally to reset the link where the specified port lives 12110 */ 12111 static int 12112 fcp_linkreset(struct fcp_port *pptr, struct scsi_address *ap, int sleep) 12113 { 12114 la_wwn_t wwn; 12115 struct fcp_lun *plun; 12116 struct fcp_tgt *ptgt; 12117 12118 /* disable restart of lip if we're suspended */ 12119 mutex_enter(&pptr->port_mutex); 12120 12121 if (pptr->port_state & (FCP_STATE_SUSPENDED | 12122 FCP_STATE_POWER_DOWN)) { 12123 mutex_exit(&pptr->port_mutex); 12124 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12125 fcp_trace, FCP_BUF_LEVEL_2, 0, 12126 "fcp_linkreset, fcp%d: link reset " 12127 "disabled due to DDI_SUSPEND", 12128 ddi_get_instance(pptr->port_dip)); 12129 return (FC_FAILURE); 12130 } 12131 12132 if (pptr->port_state & (FCP_STATE_OFFLINE | FCP_STATE_ONLINING)) { 12133 mutex_exit(&pptr->port_mutex); 12134 return (FC_SUCCESS); 12135 } 12136 12137 FCP_DTRACE(fcp_logq, pptr->port_instbuf, 12138 fcp_trace, FCP_BUF_LEVEL_8, 0, "Forcing link reset"); 12139 12140 /* 12141 * If ap == NULL assume local link reset. 12142 */ 12143 if (FC_TOP_EXTERNAL(pptr->port_topology) && (ap != NULL)) { 12144 plun = ADDR2LUN(ap); 12145 ptgt = plun->lun_tgt; 12146 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &wwn, sizeof (wwn)); 12147 } else { 12148 bzero((caddr_t)&wwn, sizeof (wwn)); 12149 } 12150 mutex_exit(&pptr->port_mutex); 12151 12152 return (fc_ulp_linkreset(pptr->port_fp_handle, &wwn, sleep)); 12153 } 12154 12155 12156 /* 12157 * called from fcp_port_attach() to resume a port 12158 * return DDI_* success/failure status 12159 * acquires and releases the global mutex 12160 * acquires and releases the port mutex 12161 */ 12162 /*ARGSUSED*/ 12163 12164 static int 12165 fcp_handle_port_resume(opaque_t ulph, fc_ulp_port_info_t *pinfo, 12166 uint32_t s_id, fc_attach_cmd_t cmd, int instance) 12167 { 12168 int res = DDI_FAILURE; /* default result */ 12169 struct fcp_port *pptr; /* port state ptr */ 12170 uint32_t alloc_cnt; 12171 uint32_t max_cnt; 12172 fc_portmap_t *tmp_list = NULL; 12173 12174 FCP_DTRACE(fcp_logq, "fcp", fcp_trace, 12175 FCP_BUF_LEVEL_8, 0, "port resume: for port %d", 12176 instance); 12177 12178 if ((pptr = ddi_get_soft_state(fcp_softstate, instance)) == NULL) { 12179 cmn_err(CE_WARN, "fcp: bad soft state"); 12180 return (res); 12181 } 12182 12183 mutex_enter(&pptr->port_mutex); 12184 switch (cmd) { 12185 case FC_CMD_RESUME: 12186 ASSERT((pptr->port_state & FCP_STATE_POWER_DOWN) == 0); 12187 pptr->port_state &= ~FCP_STATE_SUSPENDED; 12188 break; 12189 12190 case FC_CMD_POWER_UP: 12191 /* 12192 * If the port is DDI_SUSPENded, defer rediscovery 12193 * until DDI_RESUME occurs 12194 */ 12195 if (pptr->port_state & FCP_STATE_SUSPENDED) { 12196 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12197 mutex_exit(&pptr->port_mutex); 12198 return (DDI_SUCCESS); 12199 } 12200 pptr->port_state &= ~FCP_STATE_POWER_DOWN; 12201 } 12202 pptr->port_id = s_id; 12203 pptr->port_state = FCP_STATE_INIT; 12204 mutex_exit(&pptr->port_mutex); 12205 12206 /* 12207 * Make a copy of ulp_port_info as fctl allocates 12208 * a temp struct. 12209 */ 12210 (void) fcp_cp_pinfo(pptr, pinfo); 12211 12212 mutex_enter(&fcp_global_mutex); 12213 if (fcp_watchdog_init++ == 0) { 12214 fcp_watchdog_tick = drv_sectohz(fcp_watchdog_timeout); 12215 fcp_watchdog_id = timeout(fcp_watch, 12216 NULL, fcp_watchdog_tick); 12217 } 12218 mutex_exit(&fcp_global_mutex); 12219 12220 /* 12221 * Handle various topologies and link states. 12222 */ 12223 switch (FC_PORT_STATE_MASK(pptr->port_phys_state)) { 12224 case FC_STATE_OFFLINE: 12225 /* 12226 * Wait for ONLINE, at which time a state 12227 * change will cause a statec_callback 12228 */ 12229 res = DDI_SUCCESS; 12230 break; 12231 12232 case FC_STATE_ONLINE: 12233 12234 if (pptr->port_topology == FC_TOP_UNKNOWN) { 12235 (void) fcp_linkreset(pptr, NULL, KM_NOSLEEP); 12236 res = DDI_SUCCESS; 12237 break; 12238 } 12239 12240 if (FC_TOP_EXTERNAL(pptr->port_topology) && 12241 !fcp_enable_auto_configuration) { 12242 tmp_list = fcp_construct_map(pptr, &alloc_cnt); 12243 if (tmp_list == NULL) { 12244 if (!alloc_cnt) { 12245 res = DDI_SUCCESS; 12246 } 12247 break; 12248 } 12249 max_cnt = alloc_cnt; 12250 } else { 12251 ASSERT(pptr->port_topology != FC_TOP_UNKNOWN); 12252 12253 alloc_cnt = FCP_MAX_DEVICES; 12254 12255 if ((tmp_list = (fc_portmap_t *)kmem_zalloc( 12256 (sizeof (fc_portmap_t)) * alloc_cnt, 12257 KM_NOSLEEP)) == NULL) { 12258 fcp_log(CE_WARN, pptr->port_dip, 12259 "!fcp%d: failed to allocate portmap", 12260 instance); 12261 break; 12262 } 12263 12264 max_cnt = alloc_cnt; 12265 if ((res = fc_ulp_getportmap(pptr->port_fp_handle, 12266 &tmp_list, &max_cnt, FC_ULP_PLOGI_PRESERVE)) != 12267 FC_SUCCESS) { 12268 caddr_t msg; 12269 12270 (void) fc_ulp_error(res, &msg); 12271 12272 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12273 fcp_trace, FCP_BUF_LEVEL_2, 0, 12274 "resume failed getportmap: reason=0x%x", 12275 res); 12276 12277 fcp_log(CE_WARN, pptr->port_dip, 12278 "!failed to get port map : %s", msg); 12279 break; 12280 } 12281 if (max_cnt > alloc_cnt) { 12282 alloc_cnt = max_cnt; 12283 } 12284 } 12285 12286 /* 12287 * do the SCSI device discovery and create 12288 * the devinfos 12289 */ 12290 fcp_statec_callback(ulph, pptr->port_fp_handle, 12291 pptr->port_phys_state, pptr->port_topology, tmp_list, 12292 max_cnt, pptr->port_id); 12293 12294 res = DDI_SUCCESS; 12295 break; 12296 12297 default: 12298 fcp_log(CE_WARN, pptr->port_dip, 12299 "!fcp%d: invalid port state at attach=0x%x", 12300 instance, pptr->port_phys_state); 12301 12302 mutex_enter(&pptr->port_mutex); 12303 pptr->port_phys_state = FCP_STATE_OFFLINE; 12304 mutex_exit(&pptr->port_mutex); 12305 res = DDI_SUCCESS; 12306 12307 break; 12308 } 12309 12310 if (tmp_list != NULL) { 12311 kmem_free(tmp_list, sizeof (fc_portmap_t) * alloc_cnt); 12312 } 12313 12314 return (res); 12315 } 12316 12317 12318 static void 12319 fcp_cp_pinfo(struct fcp_port *pptr, fc_ulp_port_info_t *pinfo) 12320 { 12321 pptr->port_fp_modlinkage = *pinfo->port_linkage; 12322 pptr->port_dip = pinfo->port_dip; 12323 pptr->port_fp_handle = pinfo->port_handle; 12324 if (pinfo->port_acc_attr != NULL) { 12325 /* 12326 * FCA supports DMA 12327 */ 12328 pptr->port_data_dma_attr = *pinfo->port_data_dma_attr; 12329 pptr->port_cmd_dma_attr = *pinfo->port_cmd_dma_attr; 12330 pptr->port_resp_dma_attr = *pinfo->port_resp_dma_attr; 12331 pptr->port_dma_acc_attr = *pinfo->port_acc_attr; 12332 } 12333 pptr->port_priv_pkt_len = pinfo->port_fca_pkt_size; 12334 pptr->port_max_exch = pinfo->port_fca_max_exch; 12335 pptr->port_phys_state = pinfo->port_state; 12336 pptr->port_topology = pinfo->port_flags; 12337 pptr->port_reset_action = pinfo->port_reset_action; 12338 pptr->port_cmds_dma_flags = pinfo->port_dma_behavior; 12339 pptr->port_fcp_dma = pinfo->port_fcp_dma; 12340 bcopy(&pinfo->port_nwwn, &pptr->port_nwwn, sizeof (la_wwn_t)); 12341 bcopy(&pinfo->port_pwwn, &pptr->port_pwwn, sizeof (la_wwn_t)); 12342 12343 /* Clear FMA caps to avoid fm-capability ereport */ 12344 if (pptr->port_cmd_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12345 pptr->port_cmd_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12346 if (pptr->port_data_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12347 pptr->port_data_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12348 if (pptr->port_resp_dma_attr.dma_attr_flags & DDI_DMA_FLAGERR) 12349 pptr->port_resp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; 12350 } 12351 12352 /* 12353 * If the elements wait field is set to 1 then 12354 * another thread is waiting for the operation to complete. Once 12355 * it is complete, the waiting thread is signaled and the element is 12356 * freed by the waiting thread. If the elements wait field is set to 0 12357 * the element is freed. 12358 */ 12359 static void 12360 fcp_process_elem(struct fcp_hp_elem *elem, int result) 12361 { 12362 ASSERT(elem != NULL); 12363 mutex_enter(&elem->mutex); 12364 elem->result = result; 12365 if (elem->wait) { 12366 elem->wait = 0; 12367 cv_signal(&elem->cv); 12368 mutex_exit(&elem->mutex); 12369 } else { 12370 mutex_exit(&elem->mutex); 12371 cv_destroy(&elem->cv); 12372 mutex_destroy(&elem->mutex); 12373 kmem_free(elem, sizeof (struct fcp_hp_elem)); 12374 } 12375 } 12376 12377 /* 12378 * This function is invoked from the taskq thread to allocate 12379 * devinfo nodes and to online/offline them. 12380 */ 12381 static void 12382 fcp_hp_task(void *arg) 12383 { 12384 struct fcp_hp_elem *elem = (struct fcp_hp_elem *)arg; 12385 struct fcp_lun *plun = elem->lun; 12386 struct fcp_port *pptr = elem->port; 12387 int result; 12388 12389 ASSERT(elem->what == FCP_ONLINE || 12390 elem->what == FCP_OFFLINE || 12391 elem->what == FCP_MPXIO_PATH_CLEAR_BUSY || 12392 elem->what == FCP_MPXIO_PATH_SET_BUSY); 12393 12394 mutex_enter(&pptr->port_mutex); 12395 mutex_enter(&plun->lun_mutex); 12396 if (((elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) && 12397 plun->lun_event_count != elem->event_cnt) || 12398 pptr->port_state & (FCP_STATE_SUSPENDED | 12399 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 12400 mutex_exit(&plun->lun_mutex); 12401 mutex_exit(&pptr->port_mutex); 12402 fcp_process_elem(elem, NDI_FAILURE); 12403 return; 12404 } 12405 mutex_exit(&plun->lun_mutex); 12406 mutex_exit(&pptr->port_mutex); 12407 12408 result = fcp_trigger_lun(plun, elem->cip, elem->old_lun_mpxio, 12409 elem->what, elem->link_cnt, elem->tgt_cnt, elem->flags); 12410 fcp_process_elem(elem, result); 12411 } 12412 12413 12414 static child_info_t * 12415 fcp_get_cip(struct fcp_lun *plun, child_info_t *cip, int lcount, 12416 int tcount) 12417 { 12418 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12419 12420 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 12421 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 12422 12423 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12424 /* 12425 * Child has not been created yet. Create the child device 12426 * based on the per-Lun flags. 12427 */ 12428 if (pptr->port_mpxio == 0 || plun->lun_mpxio == 0) { 12429 plun->lun_cip = 12430 CIP(fcp_create_dip(plun, lcount, tcount)); 12431 plun->lun_mpxio = 0; 12432 } else { 12433 plun->lun_cip = 12434 CIP(fcp_create_pip(plun, lcount, tcount)); 12435 plun->lun_mpxio = 1; 12436 } 12437 } else { 12438 plun->lun_cip = cip; 12439 } 12440 12441 return (plun->lun_cip); 12442 } 12443 12444 12445 static int 12446 fcp_is_dip_present(struct fcp_lun *plun, dev_info_t *cdip) 12447 { 12448 int rval = FC_FAILURE; 12449 dev_info_t *pdip; 12450 struct dev_info *dip; 12451 int circular; 12452 12453 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12454 12455 pdip = plun->lun_tgt->tgt_port->port_dip; 12456 12457 if (plun->lun_cip == NULL) { 12458 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 12459 fcp_trace, FCP_BUF_LEVEL_3, 0, 12460 "fcp_is_dip_present: plun->lun_cip is NULL: " 12461 "plun: %p lun state: %x num: %d target state: %x", 12462 plun, plun->lun_state, plun->lun_num, 12463 plun->lun_tgt->tgt_port->port_state); 12464 return (rval); 12465 } 12466 ndi_devi_enter(pdip, &circular); 12467 dip = DEVI(pdip)->devi_child; 12468 while (dip) { 12469 if (dip == DEVI(cdip)) { 12470 rval = FC_SUCCESS; 12471 break; 12472 } 12473 dip = dip->devi_sibling; 12474 } 12475 ndi_devi_exit(pdip, circular); 12476 return (rval); 12477 } 12478 12479 static int 12480 fcp_is_child_present(struct fcp_lun *plun, child_info_t *cip) 12481 { 12482 int rval = FC_FAILURE; 12483 12484 ASSERT(plun != NULL); 12485 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12486 12487 if (plun->lun_mpxio == 0) { 12488 rval = fcp_is_dip_present(plun, DIP(cip)); 12489 } else { 12490 rval = fcp_is_pip_present(plun, PIP(cip)); 12491 } 12492 12493 return (rval); 12494 } 12495 12496 /* 12497 * Function: fcp_create_dip 12498 * 12499 * Description: Creates a dev_info_t structure for the LUN specified by the 12500 * caller. 12501 * 12502 * Argument: plun Lun structure 12503 * link_cnt Link state count. 12504 * tgt_cnt Target state change count. 12505 * 12506 * Return Value: NULL if it failed 12507 * dev_info_t structure address if it succeeded 12508 * 12509 * Context: Kernel context 12510 */ 12511 static dev_info_t * 12512 fcp_create_dip(struct fcp_lun *plun, int link_cnt, int tgt_cnt) 12513 { 12514 int failure = 0; 12515 uint32_t tgt_id; 12516 uint64_t sam_lun; 12517 struct fcp_tgt *ptgt = plun->lun_tgt; 12518 struct fcp_port *pptr = ptgt->tgt_port; 12519 dev_info_t *pdip = pptr->port_dip; 12520 dev_info_t *cdip = NULL; 12521 dev_info_t *old_dip = DIP(plun->lun_cip); 12522 char *nname = NULL; 12523 char **compatible = NULL; 12524 int ncompatible; 12525 char *scsi_binding_set; 12526 char t_pwwn[17]; 12527 12528 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12529 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12530 12531 /* get the 'scsi-binding-set' property */ 12532 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, 12533 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set", 12534 &scsi_binding_set) != DDI_PROP_SUCCESS) { 12535 scsi_binding_set = NULL; 12536 } 12537 12538 /* determine the node name and compatible */ 12539 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12540 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12541 if (scsi_binding_set) { 12542 ddi_prop_free(scsi_binding_set); 12543 } 12544 12545 if (nname == NULL) { 12546 #ifdef DEBUG 12547 cmn_err(CE_WARN, "%s%d: no driver for " 12548 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12549 " compatible: %s", 12550 ddi_driver_name(pdip), ddi_get_instance(pdip), 12551 ptgt->tgt_port_wwn.raw_wwn[0], 12552 ptgt->tgt_port_wwn.raw_wwn[1], 12553 ptgt->tgt_port_wwn.raw_wwn[2], 12554 ptgt->tgt_port_wwn.raw_wwn[3], 12555 ptgt->tgt_port_wwn.raw_wwn[4], 12556 ptgt->tgt_port_wwn.raw_wwn[5], 12557 ptgt->tgt_port_wwn.raw_wwn[6], 12558 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12559 *compatible); 12560 #endif /* DEBUG */ 12561 failure++; 12562 goto end_of_fcp_create_dip; 12563 } 12564 12565 cdip = fcp_find_existing_dip(plun, pdip, nname); 12566 12567 /* 12568 * if the old_dip does not match the cdip, that means there is 12569 * some property change. since we'll be using the cdip, we need 12570 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12571 * then the dtype for the device has been updated. Offline the 12572 * the old device and create a new device with the new device type 12573 * Refer to bug: 4764752 12574 */ 12575 if (old_dip && (cdip != old_dip || 12576 plun->lun_state & FCP_LUN_CHANGED)) { 12577 plun->lun_state &= ~(FCP_LUN_INIT); 12578 mutex_exit(&plun->lun_mutex); 12579 mutex_exit(&pptr->port_mutex); 12580 12581 mutex_enter(&ptgt->tgt_mutex); 12582 (void) fcp_pass_to_hp(pptr, plun, CIP(old_dip), FCP_OFFLINE, 12583 link_cnt, tgt_cnt, NDI_DEVI_REMOVE, 0); 12584 mutex_exit(&ptgt->tgt_mutex); 12585 12586 #ifdef DEBUG 12587 if (cdip != NULL) { 12588 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12589 fcp_trace, FCP_BUF_LEVEL_2, 0, 12590 "Old dip=%p; New dip=%p don't match", old_dip, 12591 cdip); 12592 } else { 12593 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12594 fcp_trace, FCP_BUF_LEVEL_2, 0, 12595 "Old dip=%p; New dip=NULL don't match", old_dip); 12596 } 12597 #endif 12598 12599 mutex_enter(&pptr->port_mutex); 12600 mutex_enter(&plun->lun_mutex); 12601 } 12602 12603 if (cdip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12604 plun->lun_state &= ~(FCP_LUN_CHANGED); 12605 if (ndi_devi_alloc(pptr->port_dip, nname, 12606 DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { 12607 failure++; 12608 goto end_of_fcp_create_dip; 12609 } 12610 } 12611 12612 /* 12613 * Previously all the properties for the devinfo were destroyed here 12614 * with a call to ndi_prop_remove_all(). Since this may cause loss of 12615 * the devid property (and other properties established by the target 12616 * driver or framework) which the code does not always recreate, this 12617 * call was removed. 12618 * This opens a theoretical possibility that we may return with a 12619 * stale devid on the node if the scsi entity behind the fibre channel 12620 * lun has changed. 12621 */ 12622 12623 /* decorate the node with compatible */ 12624 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip, 12625 "compatible", compatible, ncompatible) != DDI_PROP_SUCCESS) { 12626 failure++; 12627 goto end_of_fcp_create_dip; 12628 } 12629 12630 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, NODE_WWN_PROP, 12631 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12632 failure++; 12633 goto end_of_fcp_create_dip; 12634 } 12635 12636 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE, cdip, PORT_WWN_PROP, 12637 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) != DDI_PROP_SUCCESS) { 12638 failure++; 12639 goto end_of_fcp_create_dip; 12640 } 12641 12642 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12643 t_pwwn[16] = '\0'; 12644 if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, TGT_PORT_PROP, t_pwwn) 12645 != DDI_PROP_SUCCESS) { 12646 failure++; 12647 goto end_of_fcp_create_dip; 12648 } 12649 12650 /* 12651 * If there is no hard address - We might have to deal with 12652 * that by using WWN - Having said that it is important to 12653 * recognize this problem early so ssd can be informed of 12654 * the right interconnect type. 12655 */ 12656 if (!FC_TOP_EXTERNAL(pptr->port_topology) && ptgt->tgt_hard_addr != 0) { 12657 tgt_id = (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12658 } else { 12659 tgt_id = ptgt->tgt_d_id; 12660 } 12661 12662 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, TARGET_PROP, 12663 tgt_id) != DDI_PROP_SUCCESS) { 12664 failure++; 12665 goto end_of_fcp_create_dip; 12666 } 12667 12668 if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, LUN_PROP, 12669 (int)plun->lun_num) != DDI_PROP_SUCCESS) { 12670 failure++; 12671 goto end_of_fcp_create_dip; 12672 } 12673 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12674 if (ndi_prop_update_int64(DDI_DEV_T_NONE, cdip, SAM_LUN_PROP, 12675 sam_lun) != DDI_PROP_SUCCESS) { 12676 failure++; 12677 goto end_of_fcp_create_dip; 12678 } 12679 12680 end_of_fcp_create_dip: 12681 scsi_hba_nodename_compatible_free(nname, compatible); 12682 12683 if (cdip != NULL && failure) { 12684 (void) ndi_prop_remove_all(cdip); 12685 (void) ndi_devi_free(cdip); 12686 cdip = NULL; 12687 } 12688 12689 return (cdip); 12690 } 12691 12692 /* 12693 * Function: fcp_create_pip 12694 * 12695 * Description: Creates a Path Id for the LUN specified by the caller. 12696 * 12697 * Argument: plun Lun structure 12698 * link_cnt Link state count. 12699 * tgt_cnt Target state count. 12700 * 12701 * Return Value: NULL if it failed 12702 * mdi_pathinfo_t structure address if it succeeded 12703 * 12704 * Context: Kernel context 12705 */ 12706 static mdi_pathinfo_t * 12707 fcp_create_pip(struct fcp_lun *plun, int lcount, int tcount) 12708 { 12709 int i; 12710 char buf[MAXNAMELEN]; 12711 char uaddr[MAXNAMELEN]; 12712 int failure = 0; 12713 uint32_t tgt_id; 12714 uint64_t sam_lun; 12715 struct fcp_tgt *ptgt = plun->lun_tgt; 12716 struct fcp_port *pptr = ptgt->tgt_port; 12717 dev_info_t *pdip = pptr->port_dip; 12718 mdi_pathinfo_t *pip = NULL; 12719 mdi_pathinfo_t *old_pip = PIP(plun->lun_cip); 12720 char *nname = NULL; 12721 char **compatible = NULL; 12722 int ncompatible; 12723 char *scsi_binding_set; 12724 char t_pwwn[17]; 12725 12726 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 12727 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 12728 12729 scsi_binding_set = "vhci"; 12730 12731 /* determine the node name and compatible */ 12732 scsi_hba_nodename_compatible_get(&plun->lun_inq, scsi_binding_set, 12733 plun->lun_inq.inq_dtype, NULL, &nname, &compatible, &ncompatible); 12734 12735 if (nname == NULL) { 12736 #ifdef DEBUG 12737 cmn_err(CE_WARN, "fcp_create_dip: %s%d: no driver for " 12738 "device @w%02x%02x%02x%02x%02x%02x%02x%02x,%d:" 12739 " compatible: %s", 12740 ddi_driver_name(pdip), ddi_get_instance(pdip), 12741 ptgt->tgt_port_wwn.raw_wwn[0], 12742 ptgt->tgt_port_wwn.raw_wwn[1], 12743 ptgt->tgt_port_wwn.raw_wwn[2], 12744 ptgt->tgt_port_wwn.raw_wwn[3], 12745 ptgt->tgt_port_wwn.raw_wwn[4], 12746 ptgt->tgt_port_wwn.raw_wwn[5], 12747 ptgt->tgt_port_wwn.raw_wwn[6], 12748 ptgt->tgt_port_wwn.raw_wwn[7], plun->lun_num, 12749 *compatible); 12750 #endif /* DEBUG */ 12751 failure++; 12752 goto end_of_fcp_create_pip; 12753 } 12754 12755 pip = fcp_find_existing_pip(plun, pdip); 12756 12757 /* 12758 * if the old_dip does not match the cdip, that means there is 12759 * some property change. since we'll be using the cdip, we need 12760 * to offline the old_dip. If the state contains FCP_LUN_CHANGED 12761 * then the dtype for the device has been updated. Offline the 12762 * the old device and create a new device with the new device type 12763 * Refer to bug: 4764752 12764 */ 12765 if (old_pip && (pip != old_pip || 12766 plun->lun_state & FCP_LUN_CHANGED)) { 12767 plun->lun_state &= ~(FCP_LUN_INIT); 12768 mutex_exit(&plun->lun_mutex); 12769 mutex_exit(&pptr->port_mutex); 12770 12771 mutex_enter(&ptgt->tgt_mutex); 12772 (void) fcp_pass_to_hp(pptr, plun, CIP(old_pip), 12773 FCP_OFFLINE, lcount, tcount, 12774 NDI_DEVI_REMOVE, 0); 12775 mutex_exit(&ptgt->tgt_mutex); 12776 12777 if (pip != NULL) { 12778 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12779 fcp_trace, FCP_BUF_LEVEL_2, 0, 12780 "Old pip=%p; New pip=%p don't match", 12781 old_pip, pip); 12782 } else { 12783 FCP_TRACE(fcp_logq, pptr->port_instbuf, 12784 fcp_trace, FCP_BUF_LEVEL_2, 0, 12785 "Old pip=%p; New pip=NULL don't match", 12786 old_pip); 12787 } 12788 12789 mutex_enter(&pptr->port_mutex); 12790 mutex_enter(&plun->lun_mutex); 12791 } 12792 12793 /* 12794 * Since FC_WWN_SIZE is 8 bytes and its not like the 12795 * lun_guid_size which is dependent on the target, I don't 12796 * believe the same trancation happens here UNLESS the standards 12797 * change the FC_WWN_SIZE value to something larger than 12798 * MAXNAMELEN(currently 255 bytes). 12799 */ 12800 12801 for (i = 0; i < FC_WWN_SIZE; i++) { 12802 (void) sprintf(&buf[i << 1], "%02x", 12803 ptgt->tgt_port_wwn.raw_wwn[i]); 12804 } 12805 12806 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", 12807 buf, plun->lun_num); 12808 12809 if (pip == NULL || plun->lun_state & FCP_LUN_CHANGED) { 12810 /* 12811 * Release the locks before calling into 12812 * mdi_pi_alloc_compatible() since this can result in a 12813 * callback into fcp which can result in a deadlock 12814 * (see bug # 4870272). 12815 * 12816 * Basically, what we are trying to avoid is the scenario where 12817 * one thread does ndi_devi_enter() and tries to grab 12818 * fcp_mutex and another does it the other way round. 12819 * 12820 * But before we do that, make sure that nobody releases the 12821 * port in the meantime. We can do this by setting a flag. 12822 */ 12823 plun->lun_state &= ~(FCP_LUN_CHANGED); 12824 pptr->port_state |= FCP_STATE_IN_MDI; 12825 mutex_exit(&plun->lun_mutex); 12826 mutex_exit(&pptr->port_mutex); 12827 if (mdi_pi_alloc_compatible(pdip, nname, plun->lun_guid, 12828 uaddr, compatible, ncompatible, 0, &pip) != MDI_SUCCESS) { 12829 fcp_log(CE_WARN, pptr->port_dip, 12830 "!path alloc failed:0x%x", plun); 12831 mutex_enter(&pptr->port_mutex); 12832 mutex_enter(&plun->lun_mutex); 12833 pptr->port_state &= ~FCP_STATE_IN_MDI; 12834 failure++; 12835 goto end_of_fcp_create_pip; 12836 } 12837 mutex_enter(&pptr->port_mutex); 12838 mutex_enter(&plun->lun_mutex); 12839 pptr->port_state &= ~FCP_STATE_IN_MDI; 12840 } else { 12841 (void) mdi_prop_remove(pip, NULL); 12842 } 12843 12844 mdi_pi_set_phci_private(pip, (caddr_t)plun); 12845 12846 if (mdi_prop_update_byte_array(pip, NODE_WWN_PROP, 12847 ptgt->tgt_node_wwn.raw_wwn, FC_WWN_SIZE) 12848 != DDI_PROP_SUCCESS) { 12849 failure++; 12850 goto end_of_fcp_create_pip; 12851 } 12852 12853 if (mdi_prop_update_byte_array(pip, PORT_WWN_PROP, 12854 ptgt->tgt_port_wwn.raw_wwn, FC_WWN_SIZE) 12855 != DDI_PROP_SUCCESS) { 12856 failure++; 12857 goto end_of_fcp_create_pip; 12858 } 12859 12860 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, t_pwwn); 12861 t_pwwn[16] = '\0'; 12862 if (mdi_prop_update_string(pip, TGT_PORT_PROP, t_pwwn) 12863 != DDI_PROP_SUCCESS) { 12864 failure++; 12865 goto end_of_fcp_create_pip; 12866 } 12867 12868 /* 12869 * If there is no hard address - We might have to deal with 12870 * that by using WWN - Having said that it is important to 12871 * recognize this problem early so ssd can be informed of 12872 * the right interconnect type. 12873 */ 12874 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 12875 ptgt->tgt_hard_addr != 0) { 12876 tgt_id = (uint32_t) 12877 fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 12878 } else { 12879 tgt_id = ptgt->tgt_d_id; 12880 } 12881 12882 if (mdi_prop_update_int(pip, TARGET_PROP, tgt_id) 12883 != DDI_PROP_SUCCESS) { 12884 failure++; 12885 goto end_of_fcp_create_pip; 12886 } 12887 12888 if (mdi_prop_update_int(pip, LUN_PROP, (int)plun->lun_num) 12889 != DDI_PROP_SUCCESS) { 12890 failure++; 12891 goto end_of_fcp_create_pip; 12892 } 12893 bcopy(&plun->lun_addr, &sam_lun, FCP_LUN_SIZE); 12894 if (mdi_prop_update_int64(pip, SAM_LUN_PROP, sam_lun) 12895 != DDI_PROP_SUCCESS) { 12896 failure++; 12897 goto end_of_fcp_create_pip; 12898 } 12899 12900 end_of_fcp_create_pip: 12901 scsi_hba_nodename_compatible_free(nname, compatible); 12902 12903 if (pip != NULL && failure) { 12904 (void) mdi_prop_remove(pip, NULL); 12905 mutex_exit(&plun->lun_mutex); 12906 mutex_exit(&pptr->port_mutex); 12907 (void) mdi_pi_free(pip, 0); 12908 mutex_enter(&pptr->port_mutex); 12909 mutex_enter(&plun->lun_mutex); 12910 pip = NULL; 12911 } 12912 12913 return (pip); 12914 } 12915 12916 static dev_info_t * 12917 fcp_find_existing_dip(struct fcp_lun *plun, dev_info_t *pdip, caddr_t name) 12918 { 12919 uint_t nbytes; 12920 uchar_t *bytes; 12921 uint_t nwords; 12922 uint32_t tgt_id; 12923 int *words; 12924 dev_info_t *cdip; 12925 dev_info_t *ndip; 12926 struct fcp_tgt *ptgt = plun->lun_tgt; 12927 struct fcp_port *pptr = ptgt->tgt_port; 12928 int circular; 12929 12930 ndi_devi_enter(pdip, &circular); 12931 12932 ndip = (dev_info_t *)DEVI(pdip)->devi_child; 12933 while ((cdip = ndip) != NULL) { 12934 ndip = (dev_info_t *)DEVI(cdip)->devi_sibling; 12935 12936 if (strcmp(DEVI(cdip)->devi_node_name, name)) { 12937 continue; 12938 } 12939 12940 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12941 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, NODE_WWN_PROP, &bytes, 12942 &nbytes) != DDI_PROP_SUCCESS) { 12943 continue; 12944 } 12945 12946 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12947 if (bytes != NULL) { 12948 ddi_prop_free(bytes); 12949 } 12950 continue; 12951 } 12952 ASSERT(bytes != NULL); 12953 12954 if (bcmp(bytes, ptgt->tgt_node_wwn.raw_wwn, nbytes) != 0) { 12955 ddi_prop_free(bytes); 12956 continue; 12957 } 12958 12959 ddi_prop_free(bytes); 12960 12961 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, cdip, 12962 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, PORT_WWN_PROP, &bytes, 12963 &nbytes) != DDI_PROP_SUCCESS) { 12964 continue; 12965 } 12966 12967 if (nbytes != FC_WWN_SIZE || bytes == NULL) { 12968 if (bytes != NULL) { 12969 ddi_prop_free(bytes); 12970 } 12971 continue; 12972 } 12973 ASSERT(bytes != NULL); 12974 12975 if (bcmp(bytes, ptgt->tgt_port_wwn.raw_wwn, nbytes) != 0) { 12976 ddi_prop_free(bytes); 12977 continue; 12978 } 12979 12980 ddi_prop_free(bytes); 12981 12982 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 12983 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, TARGET_PROP, &words, 12984 &nwords) != DDI_PROP_SUCCESS) { 12985 continue; 12986 } 12987 12988 if (nwords != 1 || words == NULL) { 12989 if (words != NULL) { 12990 ddi_prop_free(words); 12991 } 12992 continue; 12993 } 12994 ASSERT(words != NULL); 12995 12996 /* 12997 * If there is no hard address - We might have to deal with 12998 * that by using WWN - Having said that it is important to 12999 * recognize this problem early so ssd can be informed of 13000 * the right interconnect type. 13001 */ 13002 if (!FC_TOP_EXTERNAL(pptr->port_topology) && 13003 ptgt->tgt_hard_addr != 0) { 13004 tgt_id = 13005 (uint32_t)fcp_alpa_to_switch[ptgt->tgt_hard_addr]; 13006 } else { 13007 tgt_id = ptgt->tgt_d_id; 13008 } 13009 13010 if (tgt_id != (uint32_t)*words) { 13011 ddi_prop_free(words); 13012 continue; 13013 } 13014 ddi_prop_free(words); 13015 13016 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 13017 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, LUN_PROP, &words, 13018 &nwords) != DDI_PROP_SUCCESS) { 13019 continue; 13020 } 13021 13022 if (nwords != 1 || words == NULL) { 13023 if (words != NULL) { 13024 ddi_prop_free(words); 13025 } 13026 continue; 13027 } 13028 ASSERT(words != NULL); 13029 13030 if (plun->lun_num == (uint16_t)*words) { 13031 ddi_prop_free(words); 13032 break; 13033 } 13034 ddi_prop_free(words); 13035 } 13036 ndi_devi_exit(pdip, circular); 13037 13038 return (cdip); 13039 } 13040 13041 13042 static int 13043 fcp_is_pip_present(struct fcp_lun *plun, mdi_pathinfo_t *pip) 13044 { 13045 dev_info_t *pdip; 13046 char buf[MAXNAMELEN]; 13047 char uaddr[MAXNAMELEN]; 13048 int rval = FC_FAILURE; 13049 13050 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13051 13052 pdip = plun->lun_tgt->tgt_port->port_dip; 13053 13054 /* 13055 * Check if pip (and not plun->lun_cip) is NULL. plun->lun_cip can be 13056 * non-NULL even when the LUN is not there as in the case when a LUN is 13057 * configured and then deleted on the device end (for T3/T4 case). In 13058 * such cases, pip will be NULL. 13059 * 13060 * If the device generates an RSCN, it will end up getting offlined when 13061 * it disappeared and a new LUN will get created when it is rediscovered 13062 * on the device. If we check for lun_cip here, the LUN will not end 13063 * up getting onlined since this function will end up returning a 13064 * FC_SUCCESS. 13065 * 13066 * The behavior is different on other devices. For instance, on a HDS, 13067 * there was no RSCN generated by the device but the next I/O generated 13068 * a check condition and rediscovery got triggered that way. So, in 13069 * such cases, this path will not be exercised 13070 */ 13071 if (pip == NULL) { 13072 FCP_TRACE(fcp_logq, LUN_PORT->port_instbuf, 13073 fcp_trace, FCP_BUF_LEVEL_4, 0, 13074 "fcp_is_pip_present: plun->lun_cip is NULL: " 13075 "plun: %p lun state: %x num: %d target state: %x", 13076 plun, plun->lun_state, plun->lun_num, 13077 plun->lun_tgt->tgt_port->port_state); 13078 return (rval); 13079 } 13080 13081 fcp_wwn_to_ascii(plun->lun_tgt->tgt_port_wwn.raw_wwn, buf); 13082 13083 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13084 13085 if (plun->lun_old_guid) { 13086 if (mdi_pi_find(pdip, plun->lun_old_guid, uaddr) == pip) { 13087 rval = FC_SUCCESS; 13088 } 13089 } else { 13090 if (mdi_pi_find(pdip, plun->lun_guid, uaddr) == pip) { 13091 rval = FC_SUCCESS; 13092 } 13093 } 13094 return (rval); 13095 } 13096 13097 static mdi_pathinfo_t * 13098 fcp_find_existing_pip(struct fcp_lun *plun, dev_info_t *pdip) 13099 { 13100 char buf[MAXNAMELEN]; 13101 char uaddr[MAXNAMELEN]; 13102 mdi_pathinfo_t *pip; 13103 struct fcp_tgt *ptgt = plun->lun_tgt; 13104 struct fcp_port *pptr = ptgt->tgt_port; 13105 13106 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13107 13108 fcp_wwn_to_ascii(ptgt->tgt_port_wwn.raw_wwn, buf); 13109 (void) snprintf(uaddr, MAXNAMELEN, "w%s,%x", buf, plun->lun_num); 13110 13111 pip = mdi_pi_find(pdip, plun->lun_guid, uaddr); 13112 13113 return (pip); 13114 } 13115 13116 13117 static int 13118 fcp_online_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13119 int tcount, int flags, int *circ) 13120 { 13121 int rval; 13122 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13123 struct fcp_tgt *ptgt = plun->lun_tgt; 13124 dev_info_t *cdip = NULL; 13125 13126 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13127 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13128 13129 if (plun->lun_cip == NULL) { 13130 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13131 fcp_trace, FCP_BUF_LEVEL_3, 0, 13132 "fcp_online_child: plun->lun_cip is NULL: " 13133 "plun: %p state: %x num: %d target state: %x", 13134 plun, plun->lun_state, plun->lun_num, 13135 plun->lun_tgt->tgt_port->port_state); 13136 return (NDI_FAILURE); 13137 } 13138 again: 13139 if (plun->lun_mpxio == 0) { 13140 cdip = DIP(cip); 13141 mutex_exit(&plun->lun_mutex); 13142 mutex_exit(&pptr->port_mutex); 13143 13144 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13145 fcp_trace, FCP_BUF_LEVEL_3, 0, 13146 "!Invoking ndi_devi_online for %s: target=%x lun=%x", 13147 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13148 13149 /* 13150 * We could check for FCP_LUN_INIT here but chances 13151 * of getting here when it's already in FCP_LUN_INIT 13152 * is rare and a duplicate ndi_devi_online wouldn't 13153 * hurt either (as the node would already have been 13154 * in CF2) 13155 */ 13156 if (!i_ddi_devi_attached(ddi_get_parent(cdip))) { 13157 rval = ndi_devi_bind_driver(cdip, flags); 13158 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13159 fcp_trace, FCP_BUF_LEVEL_3, 0, 13160 "!Invoking ndi_devi_bind_driver: rval=%d", rval); 13161 } else { 13162 rval = ndi_devi_online(cdip, flags); 13163 } 13164 13165 /* 13166 * We log the message into trace buffer if the device 13167 * is "ses" and into syslog for any other device 13168 * type. This is to prevent the ndi_devi_online failure 13169 * message that appears for V880/A5K ses devices. 13170 */ 13171 if (rval == NDI_SUCCESS) { 13172 mutex_enter(&ptgt->tgt_mutex); 13173 plun->lun_state |= FCP_LUN_INIT; 13174 mutex_exit(&ptgt->tgt_mutex); 13175 } else if (strncmp(ddi_node_name(cdip), "ses", 3) != 0) { 13176 fcp_log(CE_NOTE, pptr->port_dip, 13177 "!ndi_devi_online:" 13178 " failed for %s: target=%x lun=%x %x", 13179 ddi_get_name(cdip), ptgt->tgt_d_id, 13180 plun->lun_num, rval); 13181 } else { 13182 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13183 fcp_trace, FCP_BUF_LEVEL_3, 0, 13184 " !ndi_devi_online:" 13185 " failed for %s: target=%x lun=%x %x", 13186 ddi_get_name(cdip), ptgt->tgt_d_id, 13187 plun->lun_num, rval); 13188 } 13189 } else { 13190 cdip = mdi_pi_get_client(PIP(cip)); 13191 mutex_exit(&plun->lun_mutex); 13192 mutex_exit(&pptr->port_mutex); 13193 13194 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13195 fcp_trace, FCP_BUF_LEVEL_3, 0, 13196 "!Invoking mdi_pi_online for %s: target=%x lun=%x", 13197 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13198 13199 /* 13200 * Hold path and exit phci to avoid deadlock with power 13201 * management code during mdi_pi_online. 13202 */ 13203 mdi_hold_path(PIP(cip)); 13204 mdi_devi_exit_phci(pptr->port_dip, *circ); 13205 13206 rval = mdi_pi_online(PIP(cip), flags); 13207 13208 mdi_devi_enter_phci(pptr->port_dip, circ); 13209 mdi_rele_path(PIP(cip)); 13210 13211 if (rval == MDI_SUCCESS) { 13212 mutex_enter(&ptgt->tgt_mutex); 13213 plun->lun_state |= FCP_LUN_INIT; 13214 mutex_exit(&ptgt->tgt_mutex); 13215 13216 /* 13217 * Clear MPxIO path permanent disable in case 13218 * fcp hotplug dropped the offline event. 13219 */ 13220 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13221 13222 } else if (rval == MDI_NOT_SUPPORTED) { 13223 child_info_t *old_cip = cip; 13224 13225 /* 13226 * MPxIO does not support this device yet. 13227 * Enumerate in legacy mode. 13228 */ 13229 mutex_enter(&pptr->port_mutex); 13230 mutex_enter(&plun->lun_mutex); 13231 plun->lun_mpxio = 0; 13232 plun->lun_cip = NULL; 13233 cdip = fcp_create_dip(plun, lcount, tcount); 13234 plun->lun_cip = cip = CIP(cdip); 13235 if (cip == NULL) { 13236 fcp_log(CE_WARN, pptr->port_dip, 13237 "!fcp_online_child: " 13238 "Create devinfo failed for LU=%p", plun); 13239 mutex_exit(&plun->lun_mutex); 13240 13241 mutex_enter(&ptgt->tgt_mutex); 13242 plun->lun_state |= FCP_LUN_OFFLINE; 13243 mutex_exit(&ptgt->tgt_mutex); 13244 13245 mutex_exit(&pptr->port_mutex); 13246 13247 /* 13248 * free the mdi_pathinfo node 13249 */ 13250 (void) mdi_pi_free(PIP(old_cip), 0); 13251 } else { 13252 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13253 fcp_trace, FCP_BUF_LEVEL_3, 0, 13254 "fcp_online_child: creating devinfo " 13255 "node 0x%p for plun 0x%p", 13256 cip, plun); 13257 mutex_exit(&plun->lun_mutex); 13258 mutex_exit(&pptr->port_mutex); 13259 /* 13260 * free the mdi_pathinfo node 13261 */ 13262 (void) mdi_pi_free(PIP(old_cip), 0); 13263 mutex_enter(&pptr->port_mutex); 13264 mutex_enter(&plun->lun_mutex); 13265 goto again; 13266 } 13267 } else { 13268 if (cdip) { 13269 fcp_log(CE_NOTE, pptr->port_dip, 13270 "!fcp_online_child: mdi_pi_online:" 13271 " failed for %s: target=%x lun=%x %x", 13272 ddi_get_name(cdip), ptgt->tgt_d_id, 13273 plun->lun_num, rval); 13274 } 13275 } 13276 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13277 } 13278 13279 if (rval == NDI_SUCCESS) { 13280 if (cdip) { 13281 (void) ndi_event_retrieve_cookie( 13282 pptr->port_ndi_event_hdl, cdip, FCAL_INSERT_EVENT, 13283 &fcp_insert_eid, NDI_EVENT_NOPASS); 13284 (void) ndi_event_run_callbacks(pptr->port_ndi_event_hdl, 13285 cdip, fcp_insert_eid, NULL); 13286 } 13287 } 13288 mutex_enter(&pptr->port_mutex); 13289 mutex_enter(&plun->lun_mutex); 13290 return (rval); 13291 } 13292 13293 /* ARGSUSED */ 13294 static int 13295 fcp_offline_child(struct fcp_lun *plun, child_info_t *cip, int lcount, 13296 int tcount, int flags, int *circ) 13297 { 13298 int rval; 13299 int lun_mpxio; 13300 struct fcp_port *pptr = plun->lun_tgt->tgt_port; 13301 struct fcp_tgt *ptgt = plun->lun_tgt; 13302 dev_info_t *cdip; 13303 13304 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13305 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 13306 13307 if (plun->lun_cip == NULL) { 13308 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13309 fcp_trace, FCP_BUF_LEVEL_3, 0, 13310 "fcp_offline_child: plun->lun_cip is NULL: " 13311 "plun: %p lun state: %x num: %d target state: %x", 13312 plun, plun->lun_state, plun->lun_num, 13313 plun->lun_tgt->tgt_port->port_state); 13314 return (NDI_FAILURE); 13315 } 13316 13317 /* 13318 * We will use this value twice. Make a copy to be sure we use 13319 * the same value in both places. 13320 */ 13321 lun_mpxio = plun->lun_mpxio; 13322 13323 if (lun_mpxio == 0) { 13324 cdip = DIP(cip); 13325 mutex_exit(&plun->lun_mutex); 13326 mutex_exit(&pptr->port_mutex); 13327 rval = ndi_devi_offline(DIP(cip), flags); 13328 if (rval != NDI_SUCCESS) { 13329 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13330 fcp_trace, FCP_BUF_LEVEL_3, 0, 13331 "fcp_offline_child: ndi_devi_offline failed " 13332 "rval=%x cip=%p", rval, cip); 13333 } 13334 } else { 13335 cdip = mdi_pi_get_client(PIP(cip)); 13336 mutex_exit(&plun->lun_mutex); 13337 mutex_exit(&pptr->port_mutex); 13338 13339 /* 13340 * Exit phci to avoid deadlock with power management code 13341 * during mdi_pi_offline 13342 */ 13343 mdi_hold_path(PIP(cip)); 13344 mdi_devi_exit_phci(pptr->port_dip, *circ); 13345 13346 rval = mdi_pi_offline(PIP(cip), flags); 13347 13348 mdi_devi_enter_phci(pptr->port_dip, circ); 13349 mdi_rele_path(PIP(cip)); 13350 13351 rval = (rval == MDI_SUCCESS) ? NDI_SUCCESS : NDI_FAILURE; 13352 } 13353 13354 mutex_enter(&ptgt->tgt_mutex); 13355 plun->lun_state &= ~FCP_LUN_INIT; 13356 mutex_exit(&ptgt->tgt_mutex); 13357 13358 if (rval == NDI_SUCCESS) { 13359 cdip = NULL; 13360 if (flags & NDI_DEVI_REMOVE) { 13361 mutex_enter(&plun->lun_mutex); 13362 /* 13363 * If the guid of the LUN changes, lun_cip will not 13364 * equal to cip, and after offlining the LUN with the 13365 * old guid, we should keep lun_cip since it's the cip 13366 * of the LUN with the new guid. 13367 * Otherwise remove our reference to child node. 13368 * 13369 * This must be done before the child node is freed, 13370 * otherwise other threads could see a stale lun_cip 13371 * pointer. 13372 */ 13373 if (plun->lun_cip == cip) { 13374 plun->lun_cip = NULL; 13375 } 13376 if (plun->lun_old_guid) { 13377 kmem_free(plun->lun_old_guid, 13378 plun->lun_old_guid_size); 13379 plun->lun_old_guid = NULL; 13380 plun->lun_old_guid_size = 0; 13381 } 13382 mutex_exit(&plun->lun_mutex); 13383 } 13384 } 13385 13386 if (lun_mpxio != 0) { 13387 if (rval == NDI_SUCCESS) { 13388 /* 13389 * Clear MPxIO path permanent disable as the path is 13390 * already offlined. 13391 */ 13392 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE); 13393 13394 if (flags & NDI_DEVI_REMOVE) { 13395 (void) mdi_pi_free(PIP(cip), 0); 13396 } 13397 } else { 13398 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13399 fcp_trace, FCP_BUF_LEVEL_3, 0, 13400 "fcp_offline_child: mdi_pi_offline failed " 13401 "rval=%x cip=%p", rval, cip); 13402 } 13403 } 13404 13405 mutex_enter(&pptr->port_mutex); 13406 mutex_enter(&plun->lun_mutex); 13407 13408 if (cdip) { 13409 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13410 fcp_trace, FCP_BUF_LEVEL_3, 0, "!%s failed for %s:" 13411 " target=%x lun=%x", "ndi_offline", 13412 ddi_get_name(cdip), ptgt->tgt_d_id, plun->lun_num); 13413 } 13414 13415 return (rval); 13416 } 13417 13418 static void 13419 fcp_remove_child(struct fcp_lun *plun) 13420 { 13421 child_info_t *cip; 13422 int circ; 13423 13424 ASSERT(MUTEX_HELD(&plun->lun_mutex)); 13425 13426 if (fcp_is_child_present(plun, plun->lun_cip) == FC_SUCCESS) { 13427 if (plun->lun_mpxio == 0) { 13428 (void) ndi_prop_remove_all(DIP(plun->lun_cip)); 13429 (void) ndi_devi_free(DIP(plun->lun_cip)); 13430 plun->lun_cip = NULL; 13431 } else { 13432 /* 13433 * Clear reference to the child node in the lun. 13434 * This must be done before freeing it with mdi_pi_free 13435 * and with lun_mutex held so that other threads always 13436 * see either valid lun_cip or NULL when holding 13437 * lun_mutex. We keep a copy in cip. 13438 */ 13439 cip = plun->lun_cip; 13440 plun->lun_cip = NULL; 13441 13442 mutex_exit(&plun->lun_mutex); 13443 mutex_exit(&plun->lun_tgt->tgt_mutex); 13444 mutex_exit(&plun->lun_tgt->tgt_port->port_mutex); 13445 13446 mdi_devi_enter( 13447 plun->lun_tgt->tgt_port->port_dip, &circ); 13448 13449 /* 13450 * Exit phci to avoid deadlock with power management 13451 * code during mdi_pi_offline 13452 */ 13453 mdi_hold_path(PIP(cip)); 13454 mdi_devi_exit_phci( 13455 plun->lun_tgt->tgt_port->port_dip, circ); 13456 (void) mdi_pi_offline(PIP(cip), 13457 NDI_DEVI_REMOVE); 13458 mdi_devi_enter_phci( 13459 plun->lun_tgt->tgt_port->port_dip, &circ); 13460 mdi_rele_path(PIP(cip)); 13461 13462 mdi_devi_exit( 13463 plun->lun_tgt->tgt_port->port_dip, circ); 13464 13465 FCP_TRACE(fcp_logq, 13466 plun->lun_tgt->tgt_port->port_instbuf, 13467 fcp_trace, FCP_BUF_LEVEL_3, 0, 13468 "lun=%p pip freed %p", plun, cip); 13469 13470 (void) mdi_prop_remove(PIP(cip), NULL); 13471 (void) mdi_pi_free(PIP(cip), 0); 13472 13473 mutex_enter(&plun->lun_tgt->tgt_port->port_mutex); 13474 mutex_enter(&plun->lun_tgt->tgt_mutex); 13475 mutex_enter(&plun->lun_mutex); 13476 } 13477 } else { 13478 plun->lun_cip = NULL; 13479 } 13480 } 13481 13482 /* 13483 * called when a timeout occurs 13484 * 13485 * can be scheduled during an attach or resume (if not already running) 13486 * 13487 * one timeout is set up for all ports 13488 * 13489 * acquires and releases the global mutex 13490 */ 13491 /*ARGSUSED*/ 13492 static void 13493 fcp_watch(void *arg) 13494 { 13495 struct fcp_port *pptr; 13496 struct fcp_ipkt *icmd; 13497 struct fcp_ipkt *nicmd; 13498 struct fcp_pkt *cmd; 13499 struct fcp_pkt *ncmd; 13500 struct fcp_pkt *tail; 13501 struct fcp_pkt *pcmd; 13502 struct fcp_pkt *save_head; 13503 struct fcp_port *save_port; 13504 13505 /* increment global watchdog time */ 13506 fcp_watchdog_time += fcp_watchdog_timeout; 13507 13508 mutex_enter(&fcp_global_mutex); 13509 13510 /* scan each port in our list */ 13511 for (pptr = fcp_port_head; pptr != NULL; pptr = pptr->port_next) { 13512 save_port = fcp_port_head; 13513 pptr->port_state |= FCP_STATE_IN_WATCHDOG; 13514 mutex_exit(&fcp_global_mutex); 13515 13516 mutex_enter(&pptr->port_mutex); 13517 if (pptr->port_ipkt_list == NULL && 13518 (pptr->port_state & (FCP_STATE_SUSPENDED | 13519 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN))) { 13520 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13521 mutex_exit(&pptr->port_mutex); 13522 mutex_enter(&fcp_global_mutex); 13523 goto end_of_watchdog; 13524 } 13525 13526 /* 13527 * We check if a list of targets need to be offlined. 13528 */ 13529 if (pptr->port_offline_tgts) { 13530 fcp_scan_offline_tgts(pptr); 13531 } 13532 13533 /* 13534 * We check if a list of luns need to be offlined. 13535 */ 13536 if (pptr->port_offline_luns) { 13537 fcp_scan_offline_luns(pptr); 13538 } 13539 13540 /* 13541 * We check if a list of targets or luns need to be reset. 13542 */ 13543 if (pptr->port_reset_list) { 13544 fcp_check_reset_delay(pptr); 13545 } 13546 13547 mutex_exit(&pptr->port_mutex); 13548 13549 /* 13550 * This is where the pending commands (pkt) are checked for 13551 * timeout. 13552 */ 13553 mutex_enter(&pptr->port_pkt_mutex); 13554 tail = pptr->port_pkt_tail; 13555 13556 for (pcmd = NULL, cmd = pptr->port_pkt_head; 13557 cmd != NULL; cmd = ncmd) { 13558 ncmd = cmd->cmd_next; 13559 /* 13560 * If a command is in this queue the bit CFLAG_IN_QUEUE 13561 * must be set. 13562 */ 13563 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 13564 /* 13565 * FCP_INVALID_TIMEOUT will be set for those 13566 * command that need to be failed. Mostly those 13567 * cmds that could not be queued down for the 13568 * "timeout" value. cmd->cmd_timeout is used 13569 * to try and requeue the command regularly. 13570 */ 13571 if (cmd->cmd_timeout >= fcp_watchdog_time) { 13572 /* 13573 * This command hasn't timed out yet. Let's 13574 * go to the next one. 13575 */ 13576 pcmd = cmd; 13577 goto end_of_loop; 13578 } 13579 13580 if (cmd == pptr->port_pkt_head) { 13581 ASSERT(pcmd == NULL); 13582 pptr->port_pkt_head = cmd->cmd_next; 13583 } else { 13584 ASSERT(pcmd != NULL); 13585 pcmd->cmd_next = cmd->cmd_next; 13586 } 13587 13588 if (cmd == pptr->port_pkt_tail) { 13589 ASSERT(cmd->cmd_next == NULL); 13590 pptr->port_pkt_tail = pcmd; 13591 if (pcmd) { 13592 pcmd->cmd_next = NULL; 13593 } 13594 } 13595 cmd->cmd_next = NULL; 13596 13597 /* 13598 * save the current head before dropping the 13599 * mutex - If the head doesn't remain the 13600 * same after re acquiring the mutex, just 13601 * bail out and revisit on next tick. 13602 * 13603 * PS: The tail pointer can change as the commands 13604 * get requeued after failure to retransport 13605 */ 13606 save_head = pptr->port_pkt_head; 13607 mutex_exit(&pptr->port_pkt_mutex); 13608 13609 if (cmd->cmd_fp_pkt->pkt_timeout == 13610 FCP_INVALID_TIMEOUT) { 13611 struct scsi_pkt *pkt = cmd->cmd_pkt; 13612 struct fcp_lun *plun; 13613 struct fcp_tgt *ptgt; 13614 13615 plun = ADDR2LUN(&pkt->pkt_address); 13616 ptgt = plun->lun_tgt; 13617 13618 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13619 fcp_trace, FCP_BUF_LEVEL_2, 0, 13620 "SCSI cmd 0x%x to D_ID=%x timed out", 13621 pkt->pkt_cdbp[0], ptgt->tgt_d_id); 13622 13623 cmd->cmd_state == FCP_PKT_ABORTING ? 13624 fcp_fail_cmd(cmd, CMD_RESET, 13625 STAT_DEV_RESET) : fcp_fail_cmd(cmd, 13626 CMD_TIMEOUT, STAT_ABORTED); 13627 } else { 13628 fcp_retransport_cmd(pptr, cmd); 13629 } 13630 mutex_enter(&pptr->port_pkt_mutex); 13631 if (save_head && save_head != pptr->port_pkt_head) { 13632 /* 13633 * Looks like linked list got changed (mostly 13634 * happens when an an OFFLINE LUN code starts 13635 * returning overflow queue commands in 13636 * parallel. So bail out and revisit during 13637 * next tick 13638 */ 13639 break; 13640 } 13641 end_of_loop: 13642 /* 13643 * Scan only upto the previously known tail pointer 13644 * to avoid excessive processing - lots of new packets 13645 * could have been added to the tail or the old ones 13646 * re-queued. 13647 */ 13648 if (cmd == tail) { 13649 break; 13650 } 13651 } 13652 mutex_exit(&pptr->port_pkt_mutex); 13653 13654 mutex_enter(&pptr->port_mutex); 13655 for (icmd = pptr->port_ipkt_list; icmd != NULL; icmd = nicmd) { 13656 struct fcp_tgt *ptgt = icmd->ipkt_tgt; 13657 13658 nicmd = icmd->ipkt_next; 13659 if ((icmd->ipkt_restart != 0) && 13660 (icmd->ipkt_restart >= fcp_watchdog_time)) { 13661 /* packet has not timed out */ 13662 continue; 13663 } 13664 13665 /* time for packet re-transport */ 13666 if (icmd == pptr->port_ipkt_list) { 13667 pptr->port_ipkt_list = icmd->ipkt_next; 13668 if (pptr->port_ipkt_list) { 13669 pptr->port_ipkt_list->ipkt_prev = 13670 NULL; 13671 } 13672 } else { 13673 icmd->ipkt_prev->ipkt_next = icmd->ipkt_next; 13674 if (icmd->ipkt_next) { 13675 icmd->ipkt_next->ipkt_prev = 13676 icmd->ipkt_prev; 13677 } 13678 } 13679 icmd->ipkt_next = NULL; 13680 icmd->ipkt_prev = NULL; 13681 mutex_exit(&pptr->port_mutex); 13682 13683 if (fcp_is_retryable(icmd)) { 13684 fc_ulp_rscn_info_t *rscnp = 13685 (fc_ulp_rscn_info_t *)icmd->ipkt_fpkt-> 13686 pkt_ulp_rscn_infop; 13687 13688 FCP_TRACE(fcp_logq, pptr->port_instbuf, 13689 fcp_trace, FCP_BUF_LEVEL_2, 0, 13690 "%x to D_ID=%x Retrying..", 13691 icmd->ipkt_opcode, 13692 icmd->ipkt_fpkt->pkt_cmd_fhdr.d_id); 13693 13694 /* 13695 * Update the RSCN count in the packet 13696 * before resending. 13697 */ 13698 13699 if (rscnp != NULL) { 13700 rscnp->ulp_rscn_count = 13701 fc_ulp_get_rscn_count(pptr-> 13702 port_fp_handle); 13703 } 13704 13705 mutex_enter(&pptr->port_mutex); 13706 mutex_enter(&ptgt->tgt_mutex); 13707 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 13708 mutex_exit(&ptgt->tgt_mutex); 13709 mutex_exit(&pptr->port_mutex); 13710 switch (icmd->ipkt_opcode) { 13711 int rval; 13712 case LA_ELS_PLOGI: 13713 if ((rval = fc_ulp_login( 13714 pptr->port_fp_handle, 13715 &icmd->ipkt_fpkt, 1)) == 13716 FC_SUCCESS) { 13717 mutex_enter( 13718 &pptr->port_mutex); 13719 continue; 13720 } 13721 if (fcp_handle_ipkt_errors( 13722 pptr, ptgt, icmd, rval, 13723 "PLOGI") == DDI_SUCCESS) { 13724 mutex_enter( 13725 &pptr->port_mutex); 13726 continue; 13727 } 13728 break; 13729 13730 case LA_ELS_PRLI: 13731 if ((rval = fc_ulp_issue_els( 13732 pptr->port_fp_handle, 13733 icmd->ipkt_fpkt)) == 13734 FC_SUCCESS) { 13735 mutex_enter( 13736 &pptr->port_mutex); 13737 continue; 13738 } 13739 if (fcp_handle_ipkt_errors( 13740 pptr, ptgt, icmd, rval, 13741 "PRLI") == DDI_SUCCESS) { 13742 mutex_enter( 13743 &pptr->port_mutex); 13744 continue; 13745 } 13746 break; 13747 13748 default: 13749 if ((rval = fcp_transport( 13750 pptr->port_fp_handle, 13751 icmd->ipkt_fpkt, 1)) == 13752 FC_SUCCESS) { 13753 mutex_enter( 13754 &pptr->port_mutex); 13755 continue; 13756 } 13757 if (fcp_handle_ipkt_errors( 13758 pptr, ptgt, icmd, rval, 13759 "PRLI") == DDI_SUCCESS) { 13760 mutex_enter( 13761 &pptr->port_mutex); 13762 continue; 13763 } 13764 break; 13765 } 13766 } else { 13767 mutex_exit(&ptgt->tgt_mutex); 13768 mutex_exit(&pptr->port_mutex); 13769 } 13770 } else { 13771 fcp_print_error(icmd->ipkt_fpkt); 13772 } 13773 13774 (void) fcp_call_finish_init(pptr, ptgt, 13775 icmd->ipkt_link_cnt, icmd->ipkt_change_cnt, 13776 icmd->ipkt_cause); 13777 fcp_icmd_free(pptr, icmd); 13778 mutex_enter(&pptr->port_mutex); 13779 } 13780 13781 pptr->port_state &= ~FCP_STATE_IN_WATCHDOG; 13782 mutex_exit(&pptr->port_mutex); 13783 mutex_enter(&fcp_global_mutex); 13784 13785 end_of_watchdog: 13786 /* 13787 * Bail out early before getting into trouble 13788 */ 13789 if (save_port != fcp_port_head) { 13790 break; 13791 } 13792 } 13793 13794 if (fcp_watchdog_init > 0) { 13795 /* reschedule timeout to go again */ 13796 fcp_watchdog_id = 13797 timeout(fcp_watch, NULL, fcp_watchdog_tick); 13798 } 13799 mutex_exit(&fcp_global_mutex); 13800 } 13801 13802 13803 static void 13804 fcp_check_reset_delay(struct fcp_port *pptr) 13805 { 13806 uint32_t tgt_cnt; 13807 int level; 13808 struct fcp_tgt *ptgt; 13809 struct fcp_lun *plun; 13810 struct fcp_reset_elem *cur = NULL; 13811 struct fcp_reset_elem *next = NULL; 13812 struct fcp_reset_elem *prev = NULL; 13813 13814 ASSERT(mutex_owned(&pptr->port_mutex)); 13815 13816 next = pptr->port_reset_list; 13817 while ((cur = next) != NULL) { 13818 next = cur->next; 13819 13820 if (cur->timeout < fcp_watchdog_time) { 13821 prev = cur; 13822 continue; 13823 } 13824 13825 ptgt = cur->tgt; 13826 plun = cur->lun; 13827 tgt_cnt = cur->tgt_cnt; 13828 13829 if (ptgt) { 13830 level = RESET_TARGET; 13831 } else { 13832 ASSERT(plun != NULL); 13833 level = RESET_LUN; 13834 ptgt = plun->lun_tgt; 13835 } 13836 if (prev) { 13837 prev->next = next; 13838 } else { 13839 /* 13840 * Because we drop port mutex while doing aborts for 13841 * packets, we can't rely on reset_list pointing to 13842 * our head 13843 */ 13844 if (cur == pptr->port_reset_list) { 13845 pptr->port_reset_list = next; 13846 } else { 13847 struct fcp_reset_elem *which; 13848 13849 which = pptr->port_reset_list; 13850 while (which && which->next != cur) { 13851 which = which->next; 13852 } 13853 ASSERT(which != NULL); 13854 13855 which->next = next; 13856 prev = which; 13857 } 13858 } 13859 13860 kmem_free(cur, sizeof (*cur)); 13861 13862 if (tgt_cnt == ptgt->tgt_change_cnt) { 13863 mutex_enter(&ptgt->tgt_mutex); 13864 if (level == RESET_TARGET) { 13865 fcp_update_tgt_state(ptgt, 13866 FCP_RESET, FCP_LUN_BUSY); 13867 } else { 13868 fcp_update_lun_state(plun, 13869 FCP_RESET, FCP_LUN_BUSY); 13870 } 13871 mutex_exit(&ptgt->tgt_mutex); 13872 13873 mutex_exit(&pptr->port_mutex); 13874 fcp_abort_all(pptr, ptgt, plun, tgt_cnt); 13875 mutex_enter(&pptr->port_mutex); 13876 } 13877 } 13878 } 13879 13880 13881 static void 13882 fcp_abort_all(struct fcp_port *pptr, struct fcp_tgt *ttgt, 13883 struct fcp_lun *rlun, int tgt_cnt) 13884 { 13885 int rval; 13886 struct fcp_lun *tlun, *nlun; 13887 struct fcp_pkt *pcmd = NULL, *ncmd = NULL, 13888 *cmd = NULL, *head = NULL, 13889 *tail = NULL; 13890 13891 mutex_enter(&pptr->port_pkt_mutex); 13892 for (cmd = pptr->port_pkt_head; cmd != NULL; cmd = ncmd) { 13893 struct fcp_lun *plun = ADDR2LUN(&cmd->cmd_pkt->pkt_address); 13894 struct fcp_tgt *ptgt = plun->lun_tgt; 13895 13896 ncmd = cmd->cmd_next; 13897 13898 if (ptgt != ttgt && plun != rlun) { 13899 pcmd = cmd; 13900 continue; 13901 } 13902 13903 if (pcmd != NULL) { 13904 ASSERT(pptr->port_pkt_head != cmd); 13905 pcmd->cmd_next = ncmd; 13906 } else { 13907 ASSERT(cmd == pptr->port_pkt_head); 13908 pptr->port_pkt_head = ncmd; 13909 } 13910 if (pptr->port_pkt_tail == cmd) { 13911 ASSERT(cmd->cmd_next == NULL); 13912 pptr->port_pkt_tail = pcmd; 13913 if (pcmd != NULL) { 13914 pcmd->cmd_next = NULL; 13915 } 13916 } 13917 13918 if (head == NULL) { 13919 head = tail = cmd; 13920 } else { 13921 ASSERT(tail != NULL); 13922 tail->cmd_next = cmd; 13923 tail = cmd; 13924 } 13925 cmd->cmd_next = NULL; 13926 } 13927 mutex_exit(&pptr->port_pkt_mutex); 13928 13929 for (cmd = head; cmd != NULL; cmd = ncmd) { 13930 struct scsi_pkt *pkt = cmd->cmd_pkt; 13931 13932 ncmd = cmd->cmd_next; 13933 ASSERT(pkt != NULL); 13934 13935 mutex_enter(&pptr->port_mutex); 13936 if (ttgt->tgt_change_cnt == tgt_cnt) { 13937 mutex_exit(&pptr->port_mutex); 13938 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 13939 pkt->pkt_reason = CMD_RESET; 13940 pkt->pkt_statistics |= STAT_DEV_RESET; 13941 cmd->cmd_state = FCP_PKT_IDLE; 13942 fcp_post_callback(cmd); 13943 } else { 13944 mutex_exit(&pptr->port_mutex); 13945 } 13946 } 13947 13948 /* 13949 * If the FCA will return all the commands in its queue then our 13950 * work is easy, just return. 13951 */ 13952 13953 if (pptr->port_reset_action == FC_RESET_RETURN_ALL) { 13954 return; 13955 } 13956 13957 /* 13958 * For RESET_LUN get hold of target pointer 13959 */ 13960 if (ttgt == NULL) { 13961 ASSERT(rlun != NULL); 13962 13963 ttgt = rlun->lun_tgt; 13964 13965 ASSERT(ttgt != NULL); 13966 } 13967 13968 /* 13969 * There are some severe race conditions here. 13970 * While we are trying to abort the pkt, it might be completing 13971 * so mark it aborted and if the abort does not succeed then 13972 * handle it in the watch thread. 13973 */ 13974 mutex_enter(&ttgt->tgt_mutex); 13975 nlun = ttgt->tgt_lun; 13976 mutex_exit(&ttgt->tgt_mutex); 13977 while ((tlun = nlun) != NULL) { 13978 int restart = 0; 13979 if (rlun && rlun != tlun) { 13980 mutex_enter(&ttgt->tgt_mutex); 13981 nlun = tlun->lun_next; 13982 mutex_exit(&ttgt->tgt_mutex); 13983 continue; 13984 } 13985 mutex_enter(&tlun->lun_mutex); 13986 cmd = tlun->lun_pkt_head; 13987 while (cmd != NULL) { 13988 if (cmd->cmd_state == FCP_PKT_ISSUED) { 13989 struct scsi_pkt *pkt; 13990 13991 restart = 1; 13992 cmd->cmd_state = FCP_PKT_ABORTING; 13993 mutex_exit(&tlun->lun_mutex); 13994 rval = fc_ulp_abort(pptr->port_fp_handle, 13995 cmd->cmd_fp_pkt, KM_SLEEP); 13996 if (rval == FC_SUCCESS) { 13997 pkt = cmd->cmd_pkt; 13998 pkt->pkt_reason = CMD_RESET; 13999 pkt->pkt_statistics |= STAT_DEV_RESET; 14000 cmd->cmd_state = FCP_PKT_IDLE; 14001 fcp_post_callback(cmd); 14002 } else { 14003 caddr_t msg; 14004 14005 (void) fc_ulp_error(rval, &msg); 14006 14007 /* 14008 * This part is tricky. The abort 14009 * failed and now the command could 14010 * be completing. The cmd_state == 14011 * FCP_PKT_ABORTING should save 14012 * us in fcp_cmd_callback. If we 14013 * are already aborting ignore the 14014 * command in fcp_cmd_callback. 14015 * Here we leave this packet for 20 14016 * sec to be aborted in the 14017 * fcp_watch thread. 14018 */ 14019 fcp_log(CE_WARN, pptr->port_dip, 14020 "!Abort failed after reset %s", 14021 msg); 14022 14023 cmd->cmd_timeout = 14024 fcp_watchdog_time + 14025 cmd->cmd_pkt->pkt_time + 14026 FCP_FAILED_DELAY; 14027 14028 cmd->cmd_fp_pkt->pkt_timeout = 14029 FCP_INVALID_TIMEOUT; 14030 /* 14031 * This is a hack, cmd is put in the 14032 * overflow queue so that it can be 14033 * timed out finally 14034 */ 14035 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14036 14037 mutex_enter(&pptr->port_pkt_mutex); 14038 if (pptr->port_pkt_head) { 14039 ASSERT(pptr->port_pkt_tail 14040 != NULL); 14041 pptr->port_pkt_tail->cmd_next 14042 = cmd; 14043 pptr->port_pkt_tail = cmd; 14044 } else { 14045 ASSERT(pptr->port_pkt_tail 14046 == NULL); 14047 pptr->port_pkt_head = 14048 pptr->port_pkt_tail 14049 = cmd; 14050 } 14051 cmd->cmd_next = NULL; 14052 mutex_exit(&pptr->port_pkt_mutex); 14053 } 14054 mutex_enter(&tlun->lun_mutex); 14055 cmd = tlun->lun_pkt_head; 14056 } else { 14057 cmd = cmd->cmd_forw; 14058 } 14059 } 14060 mutex_exit(&tlun->lun_mutex); 14061 14062 mutex_enter(&ttgt->tgt_mutex); 14063 restart == 1 ? (nlun = ttgt->tgt_lun) : (nlun = tlun->lun_next); 14064 mutex_exit(&ttgt->tgt_mutex); 14065 14066 mutex_enter(&pptr->port_mutex); 14067 if (tgt_cnt != ttgt->tgt_change_cnt) { 14068 mutex_exit(&pptr->port_mutex); 14069 return; 14070 } else { 14071 mutex_exit(&pptr->port_mutex); 14072 } 14073 } 14074 } 14075 14076 14077 /* 14078 * unlink the soft state, returning the soft state found (if any) 14079 * 14080 * acquires and releases the global mutex 14081 */ 14082 struct fcp_port * 14083 fcp_soft_state_unlink(struct fcp_port *pptr) 14084 { 14085 struct fcp_port *hptr; /* ptr index */ 14086 struct fcp_port *tptr; /* prev hptr */ 14087 14088 mutex_enter(&fcp_global_mutex); 14089 for (hptr = fcp_port_head, tptr = NULL; 14090 hptr != NULL; 14091 tptr = hptr, hptr = hptr->port_next) { 14092 if (hptr == pptr) { 14093 /* we found a match -- remove this item */ 14094 if (tptr == NULL) { 14095 /* we're at the head of the list */ 14096 fcp_port_head = hptr->port_next; 14097 } else { 14098 tptr->port_next = hptr->port_next; 14099 } 14100 break; /* success */ 14101 } 14102 } 14103 if (fcp_port_head == NULL) { 14104 fcp_cleanup_blacklist(&fcp_lun_blacklist); 14105 } 14106 mutex_exit(&fcp_global_mutex); 14107 return (hptr); 14108 } 14109 14110 14111 /* 14112 * called by fcp_scsi_hba_tgt_init to find a LUN given a 14113 * WWN and a LUN number 14114 */ 14115 /* ARGSUSED */ 14116 static struct fcp_lun * 14117 fcp_lookup_lun(struct fcp_port *pptr, uchar_t *wwn, uint16_t lun) 14118 { 14119 int hash; 14120 struct fcp_tgt *ptgt; 14121 struct fcp_lun *plun; 14122 14123 ASSERT(mutex_owned(&pptr->port_mutex)); 14124 14125 hash = FCP_HASH(wwn); 14126 for (ptgt = pptr->port_tgt_hash_table[hash]; ptgt != NULL; 14127 ptgt = ptgt->tgt_next) { 14128 if (bcmp((caddr_t)wwn, (caddr_t)&ptgt->tgt_port_wwn.raw_wwn[0], 14129 sizeof (ptgt->tgt_port_wwn)) == 0) { 14130 mutex_enter(&ptgt->tgt_mutex); 14131 for (plun = ptgt->tgt_lun; 14132 plun != NULL; 14133 plun = plun->lun_next) { 14134 if (plun->lun_num == lun) { 14135 mutex_exit(&ptgt->tgt_mutex); 14136 return (plun); 14137 } 14138 } 14139 mutex_exit(&ptgt->tgt_mutex); 14140 return (NULL); 14141 } 14142 } 14143 return (NULL); 14144 } 14145 14146 /* 14147 * Function: fcp_prepare_pkt 14148 * 14149 * Description: This function prepares the SCSI cmd pkt, passed by the caller, 14150 * for fcp_start(). It binds the data or partially maps it. 14151 * Builds the FCP header and starts the initialization of the 14152 * Fibre Channel header. 14153 * 14154 * Argument: *pptr FCP port. 14155 * *cmd FCP packet. 14156 * *plun LUN the command will be sent to. 14157 * 14158 * Context: User, Kernel and Interrupt context. 14159 */ 14160 static void 14161 fcp_prepare_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd, 14162 struct fcp_lun *plun) 14163 { 14164 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 14165 struct fcp_tgt *ptgt = plun->lun_tgt; 14166 struct fcp_cmd *fcmd = &cmd->cmd_fcp_cmd; 14167 14168 ASSERT(cmd->cmd_pkt->pkt_comp || 14169 (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR)); 14170 14171 if (cmd->cmd_pkt->pkt_numcookies) { 14172 if (cmd->cmd_pkt->pkt_dma_flags & DDI_DMA_READ) { 14173 fcmd->fcp_cntl.cntl_read_data = 1; 14174 fcmd->fcp_cntl.cntl_write_data = 0; 14175 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 14176 } else { 14177 fcmd->fcp_cntl.cntl_read_data = 0; 14178 fcmd->fcp_cntl.cntl_write_data = 1; 14179 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 14180 } 14181 14182 fpkt->pkt_data_cookie = cmd->cmd_pkt->pkt_cookies; 14183 14184 fpkt->pkt_data_cookie_cnt = cmd->cmd_pkt->pkt_numcookies; 14185 ASSERT(fpkt->pkt_data_cookie_cnt <= 14186 pptr->port_data_dma_attr.dma_attr_sgllen); 14187 14188 cmd->cmd_dmacount = cmd->cmd_pkt->pkt_dma_len; 14189 14190 /* FCA needs pkt_datalen to be set */ 14191 fpkt->pkt_datalen = cmd->cmd_dmacount; 14192 fcmd->fcp_data_len = cmd->cmd_dmacount; 14193 } else { 14194 fcmd->fcp_cntl.cntl_read_data = 0; 14195 fcmd->fcp_cntl.cntl_write_data = 0; 14196 fpkt->pkt_tran_type = FC_PKT_EXCHANGE; 14197 fpkt->pkt_datalen = 0; 14198 fcmd->fcp_data_len = 0; 14199 } 14200 14201 /* set up the Tagged Queuing type */ 14202 if (cmd->cmd_pkt->pkt_flags & FLAG_HTAG) { 14203 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 14204 } else if (cmd->cmd_pkt->pkt_flags & FLAG_OTAG) { 14205 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 14206 } else if (cmd->cmd_pkt->pkt_flags & FLAG_STAG) { 14207 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 14208 } else { 14209 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 14210 } 14211 14212 fcmd->fcp_ent_addr = plun->lun_addr; 14213 14214 if (pptr->port_fcp_dma != FC_NO_DVMA_SPACE) { 14215 FCP_CP_OUT((uint8_t *)fcmd, fpkt->pkt_cmd, 14216 fpkt->pkt_cmd_acc, sizeof (struct fcp_cmd)); 14217 } else { 14218 ASSERT(fpkt->pkt_cmd_dma == NULL && fpkt->pkt_resp_dma == NULL); 14219 } 14220 14221 cmd->cmd_pkt->pkt_reason = CMD_CMPLT; 14222 cmd->cmd_pkt->pkt_state = 0; 14223 cmd->cmd_pkt->pkt_statistics = 0; 14224 cmd->cmd_pkt->pkt_resid = 0; 14225 14226 cmd->cmd_fp_pkt->pkt_data_dma = cmd->cmd_pkt->pkt_handle; 14227 14228 if (cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) { 14229 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 14230 fpkt->pkt_comp = NULL; 14231 } else { 14232 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 14233 if (cmd->cmd_pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 14234 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 14235 } 14236 fpkt->pkt_comp = fcp_cmd_callback; 14237 } 14238 14239 mutex_enter(&pptr->port_mutex); 14240 if (pptr->port_state & FCP_STATE_SUSPENDED) { 14241 fpkt->pkt_tran_flags |= FC_TRAN_DUMPING; 14242 } 14243 mutex_exit(&pptr->port_mutex); 14244 14245 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 14246 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 14247 14248 /* 14249 * Save a few kernel cycles here 14250 */ 14251 #ifndef __lock_lint 14252 fpkt->pkt_fca_device = ptgt->tgt_fca_dev; 14253 #endif /* __lock_lint */ 14254 } 14255 14256 static void 14257 fcp_post_callback(struct fcp_pkt *cmd) 14258 { 14259 scsi_hba_pkt_comp(cmd->cmd_pkt); 14260 } 14261 14262 14263 /* 14264 * called to do polled I/O by fcp_start() 14265 * 14266 * return a transport status value, i.e. TRAN_ACCECPT for success 14267 */ 14268 static int 14269 fcp_dopoll(struct fcp_port *pptr, struct fcp_pkt *cmd) 14270 { 14271 int rval; 14272 14273 #ifdef DEBUG 14274 mutex_enter(&pptr->port_pkt_mutex); 14275 pptr->port_npkts++; 14276 mutex_exit(&pptr->port_pkt_mutex); 14277 #endif /* DEBUG */ 14278 14279 if (cmd->cmd_fp_pkt->pkt_timeout) { 14280 cmd->cmd_fp_pkt->pkt_timeout = cmd->cmd_pkt->pkt_time; 14281 } else { 14282 cmd->cmd_fp_pkt->pkt_timeout = FCP_POLL_TIMEOUT; 14283 } 14284 14285 ASSERT(cmd->cmd_fp_pkt->pkt_comp == NULL); 14286 14287 cmd->cmd_state = FCP_PKT_ISSUED; 14288 14289 rval = fc_ulp_transport(pptr->port_fp_handle, cmd->cmd_fp_pkt); 14290 14291 #ifdef DEBUG 14292 mutex_enter(&pptr->port_pkt_mutex); 14293 pptr->port_npkts--; 14294 mutex_exit(&pptr->port_pkt_mutex); 14295 #endif /* DEBUG */ 14296 14297 cmd->cmd_state = FCP_PKT_IDLE; 14298 14299 switch (rval) { 14300 case FC_SUCCESS: 14301 if (cmd->cmd_fp_pkt->pkt_state == FC_PKT_SUCCESS) { 14302 fcp_complete_pkt(cmd->cmd_fp_pkt); 14303 rval = TRAN_ACCEPT; 14304 } else { 14305 rval = TRAN_FATAL_ERROR; 14306 } 14307 break; 14308 14309 case FC_TRAN_BUSY: 14310 rval = TRAN_BUSY; 14311 cmd->cmd_pkt->pkt_resid = 0; 14312 break; 14313 14314 case FC_BADPACKET: 14315 rval = TRAN_BADPKT; 14316 break; 14317 14318 default: 14319 rval = TRAN_FATAL_ERROR; 14320 break; 14321 } 14322 14323 return (rval); 14324 } 14325 14326 14327 /* 14328 * called by some of the following transport-called routines to convert 14329 * a supplied dip ptr to a port struct ptr (i.e. to the soft state) 14330 */ 14331 static struct fcp_port * 14332 fcp_dip2port(dev_info_t *dip) 14333 { 14334 int instance; 14335 14336 instance = ddi_get_instance(dip); 14337 return (ddi_get_soft_state(fcp_softstate, instance)); 14338 } 14339 14340 14341 /* 14342 * called internally to return a LUN given a dip 14343 */ 14344 struct fcp_lun * 14345 fcp_get_lun_from_cip(struct fcp_port *pptr, child_info_t *cip) 14346 { 14347 struct fcp_tgt *ptgt; 14348 struct fcp_lun *plun; 14349 int i; 14350 14351 14352 ASSERT(mutex_owned(&pptr->port_mutex)); 14353 14354 for (i = 0; i < FCP_NUM_HASH; i++) { 14355 for (ptgt = pptr->port_tgt_hash_table[i]; 14356 ptgt != NULL; 14357 ptgt = ptgt->tgt_next) { 14358 mutex_enter(&ptgt->tgt_mutex); 14359 for (plun = ptgt->tgt_lun; plun != NULL; 14360 plun = plun->lun_next) { 14361 mutex_enter(&plun->lun_mutex); 14362 if (plun->lun_cip == cip) { 14363 mutex_exit(&plun->lun_mutex); 14364 mutex_exit(&ptgt->tgt_mutex); 14365 return (plun); /* match found */ 14366 } 14367 mutex_exit(&plun->lun_mutex); 14368 } 14369 mutex_exit(&ptgt->tgt_mutex); 14370 } 14371 } 14372 return (NULL); /* no LUN found */ 14373 } 14374 14375 /* 14376 * pass an element to the hotplug list, kick the hotplug thread 14377 * and wait for the element to get processed by the hotplug thread. 14378 * on return the element is freed. 14379 * 14380 * return zero success and non-zero on failure 14381 * 14382 * acquires/releases the target mutex 14383 * 14384 */ 14385 static int 14386 fcp_pass_to_hp_and_wait(struct fcp_port *pptr, struct fcp_lun *plun, 14387 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags) 14388 { 14389 struct fcp_hp_elem *elem; 14390 int rval; 14391 14392 mutex_enter(&plun->lun_tgt->tgt_mutex); 14393 if ((elem = fcp_pass_to_hp(pptr, plun, cip, 14394 what, link_cnt, tgt_cnt, flags, 1)) == NULL) { 14395 mutex_exit(&plun->lun_tgt->tgt_mutex); 14396 fcp_log(CE_CONT, pptr->port_dip, 14397 "Can not pass_to_hp: what: %d; D_ID=%x, LUN=%x\n", 14398 what, plun->lun_tgt->tgt_d_id, plun->lun_num); 14399 return (NDI_FAILURE); 14400 } 14401 mutex_exit(&plun->lun_tgt->tgt_mutex); 14402 mutex_enter(&elem->mutex); 14403 if (elem->wait) { 14404 while (elem->wait) { 14405 cv_wait(&elem->cv, &elem->mutex); 14406 } 14407 } 14408 rval = (elem->result); 14409 mutex_exit(&elem->mutex); 14410 mutex_destroy(&elem->mutex); 14411 cv_destroy(&elem->cv); 14412 kmem_free(elem, sizeof (struct fcp_hp_elem)); 14413 return (rval); 14414 } 14415 14416 /* 14417 * pass an element to the hotplug list, and then 14418 * kick the hotplug thread 14419 * 14420 * return Boolean success, i.e. non-zero if all goes well, else zero on error 14421 * 14422 * acquires/releases the hotplug mutex 14423 * 14424 * called with the target mutex owned 14425 * 14426 * memory acquired in NOSLEEP mode 14427 * NOTE: if wait is set to 1 then the caller is responsible for waiting on 14428 * for the hp daemon to process the request and is responsible for 14429 * freeing the element 14430 */ 14431 static struct fcp_hp_elem * 14432 fcp_pass_to_hp(struct fcp_port *pptr, struct fcp_lun *plun, 14433 child_info_t *cip, int what, int link_cnt, int tgt_cnt, int flags, int wait) 14434 { 14435 struct fcp_hp_elem *elem; 14436 dev_info_t *pdip; 14437 14438 ASSERT(pptr != NULL); 14439 ASSERT(plun != NULL); 14440 ASSERT(plun->lun_tgt != NULL); 14441 ASSERT(mutex_owned(&plun->lun_tgt->tgt_mutex)); 14442 14443 /* create space for a hotplug element */ 14444 if ((elem = kmem_zalloc(sizeof (struct fcp_hp_elem), KM_NOSLEEP)) 14445 == NULL) { 14446 fcp_log(CE_WARN, NULL, 14447 "!can't allocate memory for hotplug element"); 14448 return (NULL); 14449 } 14450 14451 /* fill in hotplug element */ 14452 elem->port = pptr; 14453 elem->lun = plun; 14454 elem->cip = cip; 14455 elem->old_lun_mpxio = plun->lun_mpxio; 14456 elem->what = what; 14457 elem->flags = flags; 14458 elem->link_cnt = link_cnt; 14459 elem->tgt_cnt = tgt_cnt; 14460 elem->wait = wait; 14461 mutex_init(&elem->mutex, NULL, MUTEX_DRIVER, NULL); 14462 cv_init(&elem->cv, NULL, CV_DRIVER, NULL); 14463 14464 /* schedule the hotplug task */ 14465 pdip = pptr->port_dip; 14466 mutex_enter(&plun->lun_mutex); 14467 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14468 plun->lun_event_count++; 14469 elem->event_cnt = plun->lun_event_count; 14470 } 14471 mutex_exit(&plun->lun_mutex); 14472 if (taskq_dispatch(DEVI(pdip)->devi_taskq, fcp_hp_task, 14473 (void *)elem, KM_NOSLEEP) == NULL) { 14474 mutex_enter(&plun->lun_mutex); 14475 if (elem->what == FCP_ONLINE || elem->what == FCP_OFFLINE) { 14476 plun->lun_event_count--; 14477 } 14478 mutex_exit(&plun->lun_mutex); 14479 kmem_free(elem, sizeof (*elem)); 14480 return (0); 14481 } 14482 14483 return (elem); 14484 } 14485 14486 14487 static void 14488 fcp_retransport_cmd(struct fcp_port *pptr, struct fcp_pkt *cmd) 14489 { 14490 int rval; 14491 struct scsi_address *ap; 14492 struct fcp_lun *plun; 14493 struct fcp_tgt *ptgt; 14494 fc_packet_t *fpkt; 14495 14496 ap = &cmd->cmd_pkt->pkt_address; 14497 plun = ADDR2LUN(ap); 14498 ptgt = plun->lun_tgt; 14499 14500 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14501 14502 cmd->cmd_state = FCP_PKT_IDLE; 14503 14504 mutex_enter(&pptr->port_mutex); 14505 mutex_enter(&ptgt->tgt_mutex); 14506 if (((plun->lun_state & (FCP_LUN_BUSY | FCP_LUN_OFFLINE)) == 0) && 14507 (!(pptr->port_state & FCP_STATE_ONLINING))) { 14508 fc_ulp_rscn_info_t *rscnp; 14509 14510 cmd->cmd_state = FCP_PKT_ISSUED; 14511 14512 /* 14513 * It is possible for pkt_pd to be NULL if tgt_pd_handle was 14514 * originally NULL, hence we try to set it to the pd pointed 14515 * to by the SCSI device we're trying to get to. 14516 */ 14517 14518 fpkt = cmd->cmd_fp_pkt; 14519 if ((fpkt->pkt_pd == NULL) && (ptgt->tgt_pd_handle != NULL)) { 14520 fpkt->pkt_pd = ptgt->tgt_pd_handle; 14521 /* 14522 * We need to notify the transport that we now have a 14523 * reference to the remote port handle. 14524 */ 14525 fc_ulp_hold_remote_port(ptgt->tgt_pd_handle); 14526 } 14527 14528 mutex_exit(&ptgt->tgt_mutex); 14529 mutex_exit(&pptr->port_mutex); 14530 14531 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOINTR) == 0); 14532 14533 /* prepare the packet */ 14534 14535 fcp_prepare_pkt(pptr, cmd, plun); 14536 14537 rscnp = (fc_ulp_rscn_info_t *)cmd->cmd_fp_pkt-> 14538 pkt_ulp_rscn_infop; 14539 14540 cmd->cmd_timeout = cmd->cmd_pkt->pkt_time ? 14541 fcp_watchdog_time + cmd->cmd_pkt->pkt_time : 0; 14542 14543 if (rscnp != NULL) { 14544 rscnp->ulp_rscn_count = 14545 fc_ulp_get_rscn_count(pptr-> 14546 port_fp_handle); 14547 } 14548 14549 rval = fcp_transport(pptr->port_fp_handle, 14550 cmd->cmd_fp_pkt, 0); 14551 14552 if (rval == FC_SUCCESS) { 14553 return; 14554 } 14555 cmd->cmd_state &= ~FCP_PKT_ISSUED; 14556 } else { 14557 mutex_exit(&ptgt->tgt_mutex); 14558 mutex_exit(&pptr->port_mutex); 14559 } 14560 14561 fcp_queue_pkt(pptr, cmd); 14562 } 14563 14564 14565 static void 14566 fcp_fail_cmd(struct fcp_pkt *cmd, uchar_t reason, uint_t statistics) 14567 { 14568 ASSERT(cmd->cmd_flags & CFLAG_IN_QUEUE); 14569 14570 cmd->cmd_flags &= ~CFLAG_IN_QUEUE; 14571 cmd->cmd_state = FCP_PKT_IDLE; 14572 14573 cmd->cmd_pkt->pkt_reason = reason; 14574 cmd->cmd_pkt->pkt_state = 0; 14575 cmd->cmd_pkt->pkt_statistics = statistics; 14576 14577 fcp_post_callback(cmd); 14578 } 14579 14580 /* 14581 * Function: fcp_queue_pkt 14582 * 14583 * Description: This function queues the packet passed by the caller into 14584 * the list of packets of the FCP port. 14585 * 14586 * Argument: *pptr FCP port. 14587 * *cmd FCP packet to queue. 14588 * 14589 * Return Value: None 14590 * 14591 * Context: User, Kernel and Interrupt context. 14592 */ 14593 static void 14594 fcp_queue_pkt(struct fcp_port *pptr, struct fcp_pkt *cmd) 14595 { 14596 ASSERT((cmd->cmd_pkt->pkt_flags & FLAG_NOQUEUE) == NULL); 14597 14598 mutex_enter(&pptr->port_pkt_mutex); 14599 cmd->cmd_flags |= CFLAG_IN_QUEUE; 14600 ASSERT(cmd->cmd_state != FCP_PKT_ISSUED); 14601 cmd->cmd_timeout = fcp_watchdog_time + FCP_QUEUE_DELAY; 14602 14603 /* 14604 * zero pkt_time means hang around for ever 14605 */ 14606 if (cmd->cmd_pkt->pkt_time) { 14607 if (cmd->cmd_fp_pkt->pkt_timeout > FCP_QUEUE_DELAY) { 14608 cmd->cmd_fp_pkt->pkt_timeout -= FCP_QUEUE_DELAY; 14609 } else { 14610 /* 14611 * Indicate the watch thread to fail the 14612 * command by setting it to highest value 14613 */ 14614 cmd->cmd_timeout = fcp_watchdog_time; 14615 cmd->cmd_fp_pkt->pkt_timeout = FCP_INVALID_TIMEOUT; 14616 } 14617 } 14618 14619 if (pptr->port_pkt_head) { 14620 ASSERT(pptr->port_pkt_tail != NULL); 14621 14622 pptr->port_pkt_tail->cmd_next = cmd; 14623 pptr->port_pkt_tail = cmd; 14624 } else { 14625 ASSERT(pptr->port_pkt_tail == NULL); 14626 14627 pptr->port_pkt_head = pptr->port_pkt_tail = cmd; 14628 } 14629 cmd->cmd_next = NULL; 14630 mutex_exit(&pptr->port_pkt_mutex); 14631 } 14632 14633 /* 14634 * Function: fcp_update_targets 14635 * 14636 * Description: This function applies the specified change of state to all 14637 * the targets listed. The operation applied is 'set'. 14638 * 14639 * Argument: *pptr FCP port. 14640 * *dev_list Array of fc_portmap_t structures. 14641 * count Length of dev_list. 14642 * state State bits to update. 14643 * cause Reason for the update. 14644 * 14645 * Return Value: None 14646 * 14647 * Context: User, Kernel and Interrupt context. 14648 * The mutex pptr->port_mutex must be held. 14649 */ 14650 static void 14651 fcp_update_targets(struct fcp_port *pptr, fc_portmap_t *dev_list, 14652 uint32_t count, uint32_t state, int cause) 14653 { 14654 fc_portmap_t *map_entry; 14655 struct fcp_tgt *ptgt; 14656 14657 ASSERT(MUTEX_HELD(&pptr->port_mutex)); 14658 14659 while (count--) { 14660 map_entry = &(dev_list[count]); 14661 ptgt = fcp_lookup_target(pptr, 14662 (uchar_t *)&(map_entry->map_pwwn)); 14663 if (ptgt == NULL) { 14664 continue; 14665 } 14666 14667 mutex_enter(&ptgt->tgt_mutex); 14668 ptgt->tgt_trace = 0; 14669 ptgt->tgt_change_cnt++; 14670 ptgt->tgt_statec_cause = cause; 14671 ptgt->tgt_tmp_cnt = 1; 14672 fcp_update_tgt_state(ptgt, FCP_SET, state); 14673 mutex_exit(&ptgt->tgt_mutex); 14674 } 14675 } 14676 14677 static int 14678 fcp_call_finish_init(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14679 int lcount, int tcount, int cause) 14680 { 14681 int rval; 14682 14683 mutex_enter(&pptr->port_mutex); 14684 rval = fcp_call_finish_init_held(pptr, ptgt, lcount, tcount, cause); 14685 mutex_exit(&pptr->port_mutex); 14686 14687 return (rval); 14688 } 14689 14690 14691 static int 14692 fcp_call_finish_init_held(struct fcp_port *pptr, struct fcp_tgt *ptgt, 14693 int lcount, int tcount, int cause) 14694 { 14695 int finish_init = 0; 14696 int finish_tgt = 0; 14697 int do_finish_init = 0; 14698 int rval = FCP_NO_CHANGE; 14699 14700 if (cause == FCP_CAUSE_LINK_CHANGE || 14701 cause == FCP_CAUSE_LINK_DOWN) { 14702 do_finish_init = 1; 14703 } 14704 14705 if (ptgt != NULL) { 14706 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14707 FCP_BUF_LEVEL_2, 0, 14708 "link_cnt: %d,%d; tgt_cnt: %d,%d; tmp_cnt: %d,%d;" 14709 " cause = %d, d_id = 0x%x, tgt_done = %d", 14710 pptr->port_link_cnt, lcount, ptgt->tgt_change_cnt, tcount, 14711 pptr->port_tmp_cnt, ptgt->tgt_tmp_cnt, cause, 14712 ptgt->tgt_d_id, ptgt->tgt_done); 14713 14714 mutex_enter(&ptgt->tgt_mutex); 14715 14716 if (tcount && (ptgt->tgt_change_cnt != tcount)) { 14717 rval = FCP_DEV_CHANGE; 14718 if (do_finish_init && ptgt->tgt_done == 0) { 14719 ptgt->tgt_done++; 14720 finish_init = 1; 14721 } 14722 } else { 14723 if (--ptgt->tgt_tmp_cnt <= 0) { 14724 ptgt->tgt_tmp_cnt = 0; 14725 finish_tgt = 1; 14726 14727 if (do_finish_init) { 14728 finish_init = 1; 14729 } 14730 } 14731 } 14732 mutex_exit(&ptgt->tgt_mutex); 14733 } else { 14734 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 14735 FCP_BUF_LEVEL_2, 0, 14736 "Call Finish Init for NO target"); 14737 14738 if (do_finish_init) { 14739 finish_init = 1; 14740 } 14741 } 14742 14743 if (finish_tgt) { 14744 ASSERT(ptgt != NULL); 14745 14746 mutex_enter(&ptgt->tgt_mutex); 14747 #ifdef DEBUG 14748 bzero(ptgt->tgt_tmp_cnt_stack, 14749 sizeof (ptgt->tgt_tmp_cnt_stack)); 14750 14751 ptgt->tgt_tmp_cnt_depth = getpcstack(ptgt->tgt_tmp_cnt_stack, 14752 FCP_STACK_DEPTH); 14753 #endif /* DEBUG */ 14754 mutex_exit(&ptgt->tgt_mutex); 14755 14756 (void) fcp_finish_tgt(pptr, ptgt, lcount, tcount, cause); 14757 } 14758 14759 if (finish_init && lcount == pptr->port_link_cnt) { 14760 ASSERT(pptr->port_tmp_cnt > 0); 14761 if (--pptr->port_tmp_cnt == 0) { 14762 fcp_finish_init(pptr); 14763 } 14764 } else if (lcount != pptr->port_link_cnt) { 14765 FCP_TRACE(fcp_logq, pptr->port_instbuf, 14766 fcp_trace, FCP_BUF_LEVEL_2, 0, 14767 "fcp_call_finish_init_held,1: state change occured" 14768 " for D_ID=0x%x", (ptgt) ? ptgt->tgt_d_id : 0); 14769 } 14770 14771 return (rval); 14772 } 14773 14774 static void 14775 fcp_reconfigure_luns(void * tgt_handle) 14776 { 14777 uint32_t dev_cnt; 14778 fc_portmap_t *devlist; 14779 struct fcp_tgt *ptgt = (struct fcp_tgt *)tgt_handle; 14780 struct fcp_port *pptr = ptgt->tgt_port; 14781 14782 /* 14783 * If the timer that fires this off got canceled too late, the 14784 * target could have been destroyed. 14785 */ 14786 14787 if (ptgt->tgt_tid == NULL) { 14788 return; 14789 } 14790 14791 devlist = kmem_zalloc(sizeof (*devlist), KM_NOSLEEP); 14792 if (devlist == NULL) { 14793 fcp_log(CE_WARN, pptr->port_dip, 14794 "!fcp%d: failed to allocate for portmap", 14795 pptr->port_instance); 14796 return; 14797 } 14798 14799 dev_cnt = 1; 14800 devlist->map_pd = ptgt->tgt_pd_handle; 14801 devlist->map_hard_addr.hard_addr = ptgt->tgt_hard_addr; 14802 devlist->map_did.port_id = ptgt->tgt_d_id; 14803 14804 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], &devlist->map_nwwn, FC_WWN_SIZE); 14805 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], &devlist->map_pwwn, FC_WWN_SIZE); 14806 14807 devlist->map_state = PORT_DEVICE_LOGGED_IN; 14808 devlist->map_type = PORT_DEVICE_REPORTLUN_CHANGED; 14809 devlist->map_flags = 0; 14810 14811 fcp_statec_callback(NULL, pptr->port_fp_handle, FC_STATE_DEVICE_CHANGE, 14812 pptr->port_topology, devlist, dev_cnt, pptr->port_id); 14813 14814 /* 14815 * Clear the tgt_tid after no more references to 14816 * the fcp_tgt 14817 */ 14818 mutex_enter(&ptgt->tgt_mutex); 14819 ptgt->tgt_tid = NULL; 14820 mutex_exit(&ptgt->tgt_mutex); 14821 14822 kmem_free(devlist, sizeof (*devlist)); 14823 } 14824 14825 14826 static void 14827 fcp_free_targets(struct fcp_port *pptr) 14828 { 14829 int i; 14830 struct fcp_tgt *ptgt; 14831 14832 mutex_enter(&pptr->port_mutex); 14833 for (i = 0; i < FCP_NUM_HASH; i++) { 14834 ptgt = pptr->port_tgt_hash_table[i]; 14835 while (ptgt != NULL) { 14836 struct fcp_tgt *next_tgt = ptgt->tgt_next; 14837 14838 fcp_free_target(ptgt); 14839 ptgt = next_tgt; 14840 } 14841 } 14842 mutex_exit(&pptr->port_mutex); 14843 } 14844 14845 14846 static void 14847 fcp_free_target(struct fcp_tgt *ptgt) 14848 { 14849 struct fcp_lun *plun; 14850 timeout_id_t tid; 14851 14852 mutex_enter(&ptgt->tgt_mutex); 14853 tid = ptgt->tgt_tid; 14854 14855 /* 14856 * Cancel any pending timeouts for this target. 14857 */ 14858 14859 if (tid != NULL) { 14860 /* 14861 * Set tgt_tid to NULL first to avoid a race in the callback. 14862 * If tgt_tid is NULL, the callback will simply return. 14863 */ 14864 ptgt->tgt_tid = NULL; 14865 mutex_exit(&ptgt->tgt_mutex); 14866 (void) untimeout(tid); 14867 mutex_enter(&ptgt->tgt_mutex); 14868 } 14869 14870 plun = ptgt->tgt_lun; 14871 while (plun != NULL) { 14872 struct fcp_lun *next_lun = plun->lun_next; 14873 14874 fcp_dealloc_lun(plun); 14875 plun = next_lun; 14876 } 14877 14878 mutex_exit(&ptgt->tgt_mutex); 14879 fcp_dealloc_tgt(ptgt); 14880 } 14881 14882 /* 14883 * Function: fcp_is_retryable 14884 * 14885 * Description: Indicates if the internal packet is retryable. 14886 * 14887 * Argument: *icmd FCP internal packet. 14888 * 14889 * Return Value: 0 Not retryable 14890 * 1 Retryable 14891 * 14892 * Context: User, Kernel and Interrupt context 14893 */ 14894 static int 14895 fcp_is_retryable(struct fcp_ipkt *icmd) 14896 { 14897 if (icmd->ipkt_port->port_state & (FCP_STATE_SUSPENDED | 14898 FCP_STATE_DETACHING | FCP_STATE_POWER_DOWN)) { 14899 return (0); 14900 } 14901 14902 return (((fcp_watchdog_time + icmd->ipkt_fpkt->pkt_timeout) < 14903 icmd->ipkt_port->port_deadline) ? 1 : 0); 14904 } 14905 14906 /* 14907 * Function: fcp_create_on_demand 14908 * 14909 * Argument: *pptr FCP port. 14910 * *pwwn Port WWN. 14911 * 14912 * Return Value: 0 Success 14913 * EIO 14914 * ENOMEM 14915 * EBUSY 14916 * EINVAL 14917 * 14918 * Context: User and Kernel context 14919 */ 14920 static int 14921 fcp_create_on_demand(struct fcp_port *pptr, uchar_t *pwwn) 14922 { 14923 int wait_ms; 14924 int tcount; 14925 int lcount; 14926 int ret; 14927 int error; 14928 int rval = EIO; 14929 int ntries; 14930 fc_portmap_t *devlist; 14931 opaque_t pd; 14932 struct fcp_lun *plun; 14933 struct fcp_tgt *ptgt; 14934 int old_manual = 0; 14935 14936 /* Allocates the fc_portmap_t structure. */ 14937 devlist = kmem_zalloc(sizeof (*devlist), KM_SLEEP); 14938 14939 /* 14940 * If FC_INVALID_RSCN_COUNT is non-zero, we will have to init as shown 14941 * in the commented statement below: 14942 * 14943 * devlist->map_rscn_info.ulp_rscn_count = FC_INVALID_RSCN_COUNT; 14944 * 14945 * Below, the deadline for the discovery process is set. 14946 */ 14947 mutex_enter(&pptr->port_mutex); 14948 pptr->port_deadline = fcp_watchdog_time + FCP_ICMD_DEADLINE; 14949 mutex_exit(&pptr->port_mutex); 14950 14951 /* 14952 * We try to find the remote port based on the WWN provided by the 14953 * caller. We actually ask fp/fctl if it has it. 14954 */ 14955 pd = fc_ulp_get_remote_port(pptr->port_fp_handle, 14956 (la_wwn_t *)pwwn, &error, 1); 14957 14958 if (pd == NULL) { 14959 kmem_free(devlist, sizeof (*devlist)); 14960 return (rval); 14961 } 14962 14963 /* 14964 * The remote port was found. We ask fp/fctl to update our 14965 * fc_portmap_t structure. 14966 */ 14967 ret = fc_ulp_pwwn_to_portmap(pptr->port_fp_handle, 14968 (la_wwn_t *)pwwn, devlist); 14969 if (ret != FC_SUCCESS) { 14970 kmem_free(devlist, sizeof (*devlist)); 14971 return (rval); 14972 } 14973 14974 /* 14975 * The map flag field is set to indicates that the creation is being 14976 * done at the user request (Ioclt probably luxadm or cfgadm). 14977 */ 14978 devlist->map_type = PORT_DEVICE_USER_CREATE; 14979 14980 mutex_enter(&pptr->port_mutex); 14981 14982 /* 14983 * We check to see if fcp already has a target that describes the 14984 * device being created. If not it is created. 14985 */ 14986 ptgt = fcp_lookup_target(pptr, pwwn); 14987 if (ptgt == NULL) { 14988 lcount = pptr->port_link_cnt; 14989 mutex_exit(&pptr->port_mutex); 14990 14991 ptgt = fcp_alloc_tgt(pptr, devlist, lcount); 14992 if (ptgt == NULL) { 14993 fcp_log(CE_WARN, pptr->port_dip, 14994 "!FC target allocation failed"); 14995 return (ENOMEM); 14996 } 14997 14998 mutex_enter(&pptr->port_mutex); 14999 } 15000 15001 mutex_enter(&ptgt->tgt_mutex); 15002 ptgt->tgt_statec_cause = FCP_CAUSE_USER_CREATE; 15003 ptgt->tgt_tmp_cnt = 1; 15004 ptgt->tgt_device_created = 0; 15005 /* 15006 * If fabric and auto config is set but the target was 15007 * manually unconfigured then reset to the manual_config_only to 15008 * 0 so the device will get configured. 15009 */ 15010 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15011 fcp_enable_auto_configuration && 15012 ptgt->tgt_manual_config_only == 1) { 15013 old_manual = 1; 15014 ptgt->tgt_manual_config_only = 0; 15015 } 15016 mutex_exit(&ptgt->tgt_mutex); 15017 15018 fcp_update_targets(pptr, devlist, 1, 15019 FCP_LUN_BUSY | FCP_LUN_MARK, FCP_CAUSE_USER_CREATE); 15020 15021 lcount = pptr->port_link_cnt; 15022 tcount = ptgt->tgt_change_cnt; 15023 15024 if (fcp_handle_mapflags(pptr, ptgt, devlist, lcount, 15025 tcount, FCP_CAUSE_USER_CREATE) == TRUE) { 15026 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15027 fcp_enable_auto_configuration && old_manual) { 15028 mutex_enter(&ptgt->tgt_mutex); 15029 ptgt->tgt_manual_config_only = 1; 15030 mutex_exit(&ptgt->tgt_mutex); 15031 } 15032 15033 if (pptr->port_link_cnt != lcount || 15034 ptgt->tgt_change_cnt != tcount) { 15035 rval = EBUSY; 15036 } 15037 mutex_exit(&pptr->port_mutex); 15038 15039 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15040 FCP_BUF_LEVEL_3, 0, 15041 "fcp_create_on_demand: mapflags ptgt=%x, " 15042 "lcount=%x::port_link_cnt=%x, " 15043 "tcount=%x: tgt_change_cnt=%x, rval=%x", 15044 ptgt, lcount, pptr->port_link_cnt, 15045 tcount, ptgt->tgt_change_cnt, rval); 15046 return (rval); 15047 } 15048 15049 /* 15050 * Due to lack of synchronization mechanisms, we perform 15051 * periodic monitoring of our request; Because requests 15052 * get dropped when another one supercedes (either because 15053 * of a link change or a target change), it is difficult to 15054 * provide a clean synchronization mechanism (such as a 15055 * semaphore or a conditional variable) without exhaustively 15056 * rewriting the mainline discovery code of this driver. 15057 */ 15058 wait_ms = 500; 15059 15060 ntries = fcp_max_target_retries; 15061 15062 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15063 FCP_BUF_LEVEL_3, 0, 15064 "fcp_create_on_demand(1): ntries=%x, ptgt=%x, " 15065 "lcount=%x::port_link_cnt=%x, " 15066 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15067 "tgt_tmp_cnt =%x", 15068 ntries, ptgt, lcount, pptr->port_link_cnt, 15069 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15070 ptgt->tgt_tmp_cnt); 15071 15072 mutex_enter(&ptgt->tgt_mutex); 15073 while (ntries-- != 0 && pptr->port_link_cnt == lcount && 15074 ptgt->tgt_change_cnt == tcount && ptgt->tgt_device_created == 0) { 15075 mutex_exit(&ptgt->tgt_mutex); 15076 mutex_exit(&pptr->port_mutex); 15077 15078 delay(drv_usectohz(wait_ms * 1000)); 15079 15080 mutex_enter(&pptr->port_mutex); 15081 mutex_enter(&ptgt->tgt_mutex); 15082 } 15083 15084 15085 if (pptr->port_link_cnt != lcount || ptgt->tgt_change_cnt != tcount) { 15086 rval = EBUSY; 15087 } else { 15088 if (ptgt->tgt_tmp_cnt == 0 && ptgt->tgt_node_state == 15089 FCP_TGT_NODE_PRESENT) { 15090 rval = 0; 15091 } 15092 } 15093 15094 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15095 FCP_BUF_LEVEL_3, 0, 15096 "fcp_create_on_demand(2): ntries=%x, ptgt=%x, " 15097 "lcount=%x::port_link_cnt=%x, " 15098 "tcount=%x::tgt_change_cnt=%x, rval=%x, tgt_device_created=%x " 15099 "tgt_tmp_cnt =%x", 15100 ntries, ptgt, lcount, pptr->port_link_cnt, 15101 tcount, ptgt->tgt_change_cnt, rval, ptgt->tgt_device_created, 15102 ptgt->tgt_tmp_cnt); 15103 15104 if (rval) { 15105 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15106 fcp_enable_auto_configuration && old_manual) { 15107 ptgt->tgt_manual_config_only = 1; 15108 } 15109 mutex_exit(&ptgt->tgt_mutex); 15110 mutex_exit(&pptr->port_mutex); 15111 kmem_free(devlist, sizeof (*devlist)); 15112 15113 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15114 FCP_BUF_LEVEL_3, 0, 15115 "fcp_create_on_demand(3): ntries=%x, ptgt=%x, " 15116 "lcount=%x::port_link_cnt=%x, " 15117 "tcount=%x::tgt_change_cnt=%x, rval=%x, " 15118 "tgt_device_created=%x, tgt D_ID=%x", 15119 ntries, ptgt, lcount, pptr->port_link_cnt, 15120 tcount, ptgt->tgt_change_cnt, rval, 15121 ptgt->tgt_device_created, ptgt->tgt_d_id); 15122 return (rval); 15123 } 15124 15125 if ((plun = ptgt->tgt_lun) != NULL) { 15126 tcount = plun->lun_tgt->tgt_change_cnt; 15127 } else { 15128 rval = EINVAL; 15129 } 15130 lcount = pptr->port_link_cnt; 15131 15132 /* 15133 * Configuring the target with no LUNs will fail. We 15134 * should reset the node state so that it is not 15135 * automatically configured when the LUNs are added 15136 * to this target. 15137 */ 15138 if (ptgt->tgt_lun_cnt == 0) { 15139 ptgt->tgt_node_state = FCP_TGT_NODE_NONE; 15140 } 15141 mutex_exit(&ptgt->tgt_mutex); 15142 mutex_exit(&pptr->port_mutex); 15143 15144 while (plun) { 15145 child_info_t *cip; 15146 15147 mutex_enter(&plun->lun_mutex); 15148 cip = plun->lun_cip; 15149 mutex_exit(&plun->lun_mutex); 15150 15151 mutex_enter(&ptgt->tgt_mutex); 15152 if (!(plun->lun_state & FCP_LUN_OFFLINE)) { 15153 mutex_exit(&ptgt->tgt_mutex); 15154 15155 rval = fcp_pass_to_hp_and_wait(pptr, plun, cip, 15156 FCP_ONLINE, lcount, tcount, 15157 NDI_ONLINE_ATTACH); 15158 if (rval != NDI_SUCCESS) { 15159 FCP_TRACE(fcp_logq, 15160 pptr->port_instbuf, fcp_trace, 15161 FCP_BUF_LEVEL_3, 0, 15162 "fcp_create_on_demand: " 15163 "pass_to_hp_and_wait failed " 15164 "rval=%x", rval); 15165 rval = EIO; 15166 } else { 15167 mutex_enter(&LUN_TGT->tgt_mutex); 15168 plun->lun_state &= ~(FCP_LUN_OFFLINE | 15169 FCP_LUN_BUSY); 15170 mutex_exit(&LUN_TGT->tgt_mutex); 15171 } 15172 mutex_enter(&ptgt->tgt_mutex); 15173 } 15174 15175 plun = plun->lun_next; 15176 mutex_exit(&ptgt->tgt_mutex); 15177 } 15178 15179 kmem_free(devlist, sizeof (*devlist)); 15180 15181 if (FC_TOP_EXTERNAL(pptr->port_topology) && 15182 fcp_enable_auto_configuration && old_manual) { 15183 mutex_enter(&ptgt->tgt_mutex); 15184 /* if successful then set manual to 0 */ 15185 if (rval == 0) { 15186 ptgt->tgt_manual_config_only = 0; 15187 } else { 15188 /* reset to 1 so the user has to do the config */ 15189 ptgt->tgt_manual_config_only = 1; 15190 } 15191 mutex_exit(&ptgt->tgt_mutex); 15192 } 15193 15194 return (rval); 15195 } 15196 15197 15198 static void 15199 fcp_ascii_to_wwn(caddr_t string, uchar_t bytes[], unsigned int byte_len) 15200 { 15201 int count; 15202 uchar_t byte; 15203 15204 count = 0; 15205 while (*string) { 15206 byte = FCP_ATOB(*string); string++; 15207 byte = byte << 4 | FCP_ATOB(*string); string++; 15208 bytes[count++] = byte; 15209 15210 if (count >= byte_len) { 15211 break; 15212 } 15213 } 15214 } 15215 15216 static void 15217 fcp_wwn_to_ascii(uchar_t wwn[], char *string) 15218 { 15219 int i; 15220 15221 for (i = 0; i < FC_WWN_SIZE; i++) { 15222 (void) sprintf(string + (i * 2), 15223 "%02x", wwn[i]); 15224 } 15225 15226 } 15227 15228 static void 15229 fcp_print_error(fc_packet_t *fpkt) 15230 { 15231 struct fcp_ipkt *icmd = (struct fcp_ipkt *) 15232 fpkt->pkt_ulp_private; 15233 struct fcp_port *pptr; 15234 struct fcp_tgt *ptgt; 15235 struct fcp_lun *plun; 15236 caddr_t buf; 15237 int scsi_cmd = 0; 15238 15239 ptgt = icmd->ipkt_tgt; 15240 plun = icmd->ipkt_lun; 15241 pptr = ptgt->tgt_port; 15242 15243 buf = kmem_zalloc(256, KM_NOSLEEP); 15244 if (buf == NULL) { 15245 return; 15246 } 15247 15248 switch (icmd->ipkt_opcode) { 15249 case SCMD_REPORT_LUN: 15250 (void) sprintf(buf, "!REPORT LUN to D_ID=0x%%x" 15251 " lun=0x%%x failed"); 15252 scsi_cmd++; 15253 break; 15254 15255 case SCMD_INQUIRY_PAGE83: 15256 (void) sprintf(buf, "!INQUIRY-83 to D_ID=0x%%x" 15257 " lun=0x%%x failed"); 15258 scsi_cmd++; 15259 break; 15260 15261 case SCMD_INQUIRY: 15262 (void) sprintf(buf, "!INQUIRY to D_ID=0x%%x" 15263 " lun=0x%%x failed"); 15264 scsi_cmd++; 15265 break; 15266 15267 case LA_ELS_PLOGI: 15268 (void) sprintf(buf, "!PLOGI to D_ID=0x%%x failed"); 15269 break; 15270 15271 case LA_ELS_PRLI: 15272 (void) sprintf(buf, "!PRLI to D_ID=0x%%x failed"); 15273 break; 15274 } 15275 15276 if (scsi_cmd && fpkt->pkt_state == FC_PKT_SUCCESS) { 15277 struct fcp_rsp response, *rsp; 15278 uchar_t asc, ascq; 15279 caddr_t sense_key = NULL; 15280 struct fcp_rsp_info fcp_rsp_err, *bep; 15281 15282 if (icmd->ipkt_nodma) { 15283 rsp = (struct fcp_rsp *)fpkt->pkt_resp; 15284 bep = (struct fcp_rsp_info *)((caddr_t)rsp + 15285 sizeof (struct fcp_rsp)); 15286 } else { 15287 rsp = &response; 15288 bep = &fcp_rsp_err; 15289 15290 FCP_CP_IN(fpkt->pkt_resp, rsp, fpkt->pkt_resp_acc, 15291 sizeof (struct fcp_rsp)); 15292 15293 FCP_CP_IN(fpkt->pkt_resp + sizeof (struct fcp_rsp), 15294 bep, fpkt->pkt_resp_acc, 15295 sizeof (struct fcp_rsp_info)); 15296 } 15297 15298 15299 if (fcp_validate_fcp_response(rsp, pptr) != FC_SUCCESS) { 15300 (void) sprintf(buf + strlen(buf), 15301 " : Bad FCP response values rsvd1=%%x, rsvd2=%%x," 15302 " sts-rsvd1=%%x, sts-rsvd2=%%x, rsplen=%%x," 15303 " senselen=%%x. Giving up"); 15304 15305 fcp_log(CE_WARN, pptr->port_dip, buf, 15306 ptgt->tgt_d_id, plun->lun_num, rsp->reserved_0, 15307 rsp->reserved_1, rsp->fcp_u.fcp_status.reserved_0, 15308 rsp->fcp_u.fcp_status.reserved_1, 15309 rsp->fcp_response_len, rsp->fcp_sense_len); 15310 15311 kmem_free(buf, 256); 15312 return; 15313 } 15314 15315 if (rsp->fcp_u.fcp_status.rsp_len_set && 15316 bep->rsp_code != FCP_NO_FAILURE) { 15317 (void) sprintf(buf + strlen(buf), 15318 " FCP Response code = 0x%x", bep->rsp_code); 15319 } 15320 15321 if (rsp->fcp_u.fcp_status.scsi_status & STATUS_CHECK) { 15322 struct scsi_extended_sense sense_info, *sense_ptr; 15323 15324 if (icmd->ipkt_nodma) { 15325 sense_ptr = (struct scsi_extended_sense *) 15326 ((caddr_t)fpkt->pkt_resp + 15327 sizeof (struct fcp_rsp) + 15328 rsp->fcp_response_len); 15329 } else { 15330 sense_ptr = &sense_info; 15331 15332 FCP_CP_IN(fpkt->pkt_resp + 15333 sizeof (struct fcp_rsp) + 15334 rsp->fcp_response_len, &sense_info, 15335 fpkt->pkt_resp_acc, 15336 sizeof (struct scsi_extended_sense)); 15337 } 15338 15339 if (sense_ptr->es_key < NUM_SENSE_KEYS + 15340 NUM_IMPL_SENSE_KEYS) { 15341 sense_key = sense_keys[sense_ptr->es_key]; 15342 } else { 15343 sense_key = "Undefined"; 15344 } 15345 15346 asc = sense_ptr->es_add_code; 15347 ascq = sense_ptr->es_qual_code; 15348 15349 (void) sprintf(buf + strlen(buf), 15350 ": sense key=%%s, ASC=%%x," " ASCQ=%%x." 15351 " Giving up"); 15352 15353 fcp_log(CE_WARN, pptr->port_dip, buf, 15354 ptgt->tgt_d_id, plun->lun_num, sense_key, 15355 asc, ascq); 15356 } else { 15357 (void) sprintf(buf + strlen(buf), 15358 " : SCSI status=%%x. Giving up"); 15359 15360 fcp_log(CE_WARN, pptr->port_dip, buf, 15361 ptgt->tgt_d_id, plun->lun_num, 15362 rsp->fcp_u.fcp_status.scsi_status); 15363 } 15364 } else { 15365 caddr_t state, reason, action, expln; 15366 15367 (void) fc_ulp_pkt_error(fpkt, &state, &reason, 15368 &action, &expln); 15369 15370 (void) sprintf(buf + strlen(buf), ": State:%%s," 15371 " Reason:%%s. Giving up"); 15372 15373 if (scsi_cmd) { 15374 fcp_log(CE_WARN, pptr->port_dip, buf, 15375 ptgt->tgt_d_id, plun->lun_num, state, reason); 15376 } else { 15377 fcp_log(CE_WARN, pptr->port_dip, buf, 15378 ptgt->tgt_d_id, state, reason); 15379 } 15380 } 15381 15382 kmem_free(buf, 256); 15383 } 15384 15385 15386 static int 15387 fcp_handle_ipkt_errors(struct fcp_port *pptr, struct fcp_tgt *ptgt, 15388 struct fcp_ipkt *icmd, int rval, caddr_t op) 15389 { 15390 int ret = DDI_FAILURE; 15391 char *error; 15392 15393 switch (rval) { 15394 case FC_DEVICE_BUSY_NEW_RSCN: 15395 /* 15396 * This means that there was a new RSCN that the transport 15397 * knows about (which the ULP *may* know about too) but the 15398 * pkt that was sent down was related to an older RSCN. So, we 15399 * are just going to reset the retry count and deadline and 15400 * continue to retry. The idea is that transport is currently 15401 * working on the new RSCN and will soon let the ULPs know 15402 * about it and when it does the existing logic will kick in 15403 * where it will change the tcount to indicate that something 15404 * changed on the target. So, rediscovery will start and there 15405 * will not be an infinite retry. 15406 * 15407 * For a full flow of how the RSCN info is transferred back and 15408 * forth, see fp.c 15409 */ 15410 icmd->ipkt_retries = 0; 15411 icmd->ipkt_port->port_deadline = fcp_watchdog_time + 15412 FCP_ICMD_DEADLINE; 15413 15414 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15415 FCP_BUF_LEVEL_3, 0, 15416 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15417 rval, ptgt->tgt_d_id); 15418 /* FALLTHROUGH */ 15419 15420 case FC_STATEC_BUSY: 15421 case FC_DEVICE_BUSY: 15422 case FC_PBUSY: 15423 case FC_FBUSY: 15424 case FC_TRAN_BUSY: 15425 case FC_OFFLINE: 15426 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15427 FCP_BUF_LEVEL_3, 0, 15428 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15429 rval, ptgt->tgt_d_id); 15430 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15431 fcp_is_retryable(icmd)) { 15432 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15433 ret = DDI_SUCCESS; 15434 } 15435 break; 15436 15437 case FC_LOGINREQ: 15438 /* 15439 * FC_LOGINREQ used to be handled just like all the cases 15440 * above. It has been changed to handled a PRLI that fails 15441 * with FC_LOGINREQ different than other ipkts that fail 15442 * with FC_LOGINREQ. If a PRLI fails with FC_LOGINREQ it is 15443 * a simple matter to turn it into a PLOGI instead, so that's 15444 * exactly what we do here. 15445 */ 15446 if (icmd->ipkt_opcode == LA_ELS_PRLI) { 15447 ret = fcp_send_els(icmd->ipkt_port, icmd->ipkt_tgt, 15448 icmd, LA_ELS_PLOGI, icmd->ipkt_link_cnt, 15449 icmd->ipkt_change_cnt, icmd->ipkt_cause); 15450 } else { 15451 FCP_TRACE(fcp_logq, pptr->port_instbuf, fcp_trace, 15452 FCP_BUF_LEVEL_3, 0, 15453 "fcp_handle_ipkt_errors: rval=%x for D_ID=%x", 15454 rval, ptgt->tgt_d_id); 15455 if (icmd->ipkt_retries < FCP_MAX_RETRIES && 15456 fcp_is_retryable(icmd)) { 15457 fcp_queue_ipkt(pptr, icmd->ipkt_fpkt); 15458 ret = DDI_SUCCESS; 15459 } 15460 } 15461 break; 15462 15463 default: 15464 mutex_enter(&pptr->port_mutex); 15465 mutex_enter(&ptgt->tgt_mutex); 15466 if (!FCP_STATE_CHANGED(pptr, ptgt, icmd)) { 15467 mutex_exit(&ptgt->tgt_mutex); 15468 mutex_exit(&pptr->port_mutex); 15469 15470 (void) fc_ulp_error(rval, &error); 15471 fcp_log(CE_WARN, pptr->port_dip, 15472 "!Failed to send %s to D_ID=%x error=%s", 15473 op, ptgt->tgt_d_id, error); 15474 } else { 15475 FCP_TRACE(fcp_logq, pptr->port_instbuf, 15476 fcp_trace, FCP_BUF_LEVEL_2, 0, 15477 "fcp_handle_ipkt_errors,1: state change occured" 15478 " for D_ID=0x%x", ptgt->tgt_d_id); 15479 mutex_exit(&ptgt->tgt_mutex); 15480 mutex_exit(&pptr->port_mutex); 15481 } 15482 break; 15483 } 15484 15485 return (ret); 15486 } 15487 15488 15489 /* 15490 * Check of outstanding commands on any LUN for this target 15491 */ 15492 static int 15493 fcp_outstanding_lun_cmds(struct fcp_tgt *ptgt) 15494 { 15495 struct fcp_lun *plun; 15496 struct fcp_pkt *cmd; 15497 15498 for (plun = ptgt->tgt_lun; plun != NULL; plun = plun->lun_next) { 15499 mutex_enter(&plun->lun_mutex); 15500 for (cmd = plun->lun_pkt_head; cmd != NULL; 15501 cmd = cmd->cmd_forw) { 15502 if (cmd->cmd_state == FCP_PKT_ISSUED) { 15503 mutex_exit(&plun->lun_mutex); 15504 return (FC_SUCCESS); 15505 } 15506 } 15507 mutex_exit(&plun->lun_mutex); 15508 } 15509 15510 return (FC_FAILURE); 15511 } 15512 15513 static fc_portmap_t * 15514 fcp_construct_map(struct fcp_port *pptr, uint32_t *dev_cnt) 15515 { 15516 int i; 15517 fc_portmap_t *devlist; 15518 fc_portmap_t *devptr = NULL; 15519 struct fcp_tgt *ptgt; 15520 15521 mutex_enter(&pptr->port_mutex); 15522 for (i = 0, *dev_cnt = 0; i < FCP_NUM_HASH; i++) { 15523 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15524 ptgt = ptgt->tgt_next) { 15525 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15526 ++*dev_cnt; 15527 } 15528 } 15529 } 15530 15531 devptr = devlist = kmem_zalloc(sizeof (*devlist) * *dev_cnt, 15532 KM_NOSLEEP); 15533 if (devlist == NULL) { 15534 mutex_exit(&pptr->port_mutex); 15535 fcp_log(CE_WARN, pptr->port_dip, 15536 "!fcp%d: failed to allocate for portmap for construct map", 15537 pptr->port_instance); 15538 return (devptr); 15539 } 15540 15541 for (i = 0; i < FCP_NUM_HASH; i++) { 15542 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15543 ptgt = ptgt->tgt_next) { 15544 if (!(ptgt->tgt_state & FCP_TGT_ORPHAN)) { 15545 int ret; 15546 15547 ret = fc_ulp_pwwn_to_portmap( 15548 pptr->port_fp_handle, 15549 (la_wwn_t *)&ptgt->tgt_port_wwn.raw_wwn[0], 15550 devlist); 15551 15552 if (ret == FC_SUCCESS) { 15553 devlist++; 15554 continue; 15555 } 15556 15557 devlist->map_pd = NULL; 15558 devlist->map_did.port_id = ptgt->tgt_d_id; 15559 devlist->map_hard_addr.hard_addr = 15560 ptgt->tgt_hard_addr; 15561 15562 devlist->map_state = PORT_DEVICE_INVALID; 15563 devlist->map_type = PORT_DEVICE_OLD; 15564 15565 bcopy(&ptgt->tgt_node_wwn.raw_wwn[0], 15566 &devlist->map_nwwn, FC_WWN_SIZE); 15567 15568 bcopy(&ptgt->tgt_port_wwn.raw_wwn[0], 15569 &devlist->map_pwwn, FC_WWN_SIZE); 15570 15571 devlist++; 15572 } 15573 } 15574 } 15575 15576 mutex_exit(&pptr->port_mutex); 15577 15578 return (devptr); 15579 } 15580 /* 15581 * Inimate MPxIO that the lun is busy and cannot accept regular IO 15582 */ 15583 static void 15584 fcp_update_mpxio_path_verifybusy(struct fcp_port *pptr) 15585 { 15586 int i; 15587 struct fcp_tgt *ptgt; 15588 struct fcp_lun *plun; 15589 15590 for (i = 0; i < FCP_NUM_HASH; i++) { 15591 for (ptgt = pptr->port_tgt_hash_table[i]; ptgt != NULL; 15592 ptgt = ptgt->tgt_next) { 15593 mutex_enter(&ptgt->tgt_mutex); 15594 for (plun = ptgt->tgt_lun; plun != NULL; 15595 plun = plun->lun_next) { 15596 if (plun->lun_mpxio && 15597 plun->lun_state & FCP_LUN_BUSY) { 15598 if (!fcp_pass_to_hp(pptr, plun, 15599 plun->lun_cip, 15600 FCP_MPXIO_PATH_SET_BUSY, 15601 pptr->port_link_cnt, 15602 ptgt->tgt_change_cnt, 0, 0)) { 15603 FCP_TRACE(fcp_logq, 15604 pptr->port_instbuf, 15605 fcp_trace, 15606 FCP_BUF_LEVEL_2, 0, 15607 "path_verifybusy: " 15608 "disable lun %p failed!", 15609 plun); 15610 } 15611 } 15612 } 15613 mutex_exit(&ptgt->tgt_mutex); 15614 } 15615 } 15616 } 15617 15618 static int 15619 fcp_update_mpxio_path(struct fcp_lun *plun, child_info_t *cip, int what) 15620 { 15621 dev_info_t *cdip = NULL; 15622 dev_info_t *pdip = NULL; 15623 15624 ASSERT(plun); 15625 15626 mutex_enter(&plun->lun_mutex); 15627 if (fcp_is_child_present(plun, cip) == FC_FAILURE) { 15628 mutex_exit(&plun->lun_mutex); 15629 return (NDI_FAILURE); 15630 } 15631 mutex_exit(&plun->lun_mutex); 15632 cdip = mdi_pi_get_client(PIP(cip)); 15633 pdip = mdi_pi_get_phci(PIP(cip)); 15634 15635 ASSERT(cdip != NULL); 15636 ASSERT(pdip != NULL); 15637 15638 if (what == FCP_MPXIO_PATH_CLEAR_BUSY) { 15639 /* LUN ready for IO */ 15640 (void) mdi_pi_enable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15641 } else { 15642 /* LUN busy to accept IO */ 15643 (void) mdi_pi_disable_path(PIP(cip), DRIVER_DISABLE_TRANSIENT); 15644 } 15645 return (NDI_SUCCESS); 15646 } 15647 15648 /* 15649 * Caller must free the returned string of MAXPATHLEN len 15650 * If the device is offline (-1 instance number) NULL 15651 * will be returned. 15652 */ 15653 static char * 15654 fcp_get_lun_path(struct fcp_lun *plun) { 15655 dev_info_t *dip = NULL; 15656 char *path = NULL; 15657 mdi_pathinfo_t *pip = NULL; 15658 15659 if (plun == NULL) { 15660 return (NULL); 15661 } 15662 15663 mutex_enter(&plun->lun_mutex); 15664 if (plun->lun_mpxio == 0) { 15665 dip = DIP(plun->lun_cip); 15666 mutex_exit(&plun->lun_mutex); 15667 } else { 15668 /* 15669 * lun_cip must be accessed with lun_mutex held. Here 15670 * plun->lun_cip either points to a valid node or it is NULL. 15671 * Make a copy so that we can release lun_mutex. 15672 */ 15673 pip = PIP(plun->lun_cip); 15674 15675 /* 15676 * Increase ref count on the path so that we can release 15677 * lun_mutex and still be sure that the pathinfo node (and thus 15678 * also the client) is not deallocated. If pip is NULL, this 15679 * has no effect. 15680 */ 15681 mdi_hold_path(pip); 15682 15683 mutex_exit(&plun->lun_mutex); 15684 15685 /* Get the client. If pip is NULL, we get NULL. */ 15686 dip = mdi_pi_get_client(pip); 15687 } 15688 15689 if (dip == NULL) 15690 goto out; 15691 if (ddi_get_instance(dip) < 0) 15692 goto out; 15693 15694 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 15695 if (path == NULL) 15696 goto out; 15697 15698 (void) ddi_pathname(dip, path); 15699 15700 /* Clean up. */ 15701 out: 15702 if (pip != NULL) 15703 mdi_rele_path(pip); 15704 15705 /* 15706 * In reality, the user wants a fully valid path (one they can open) 15707 * but this string is lacking the mount point, and the minor node. 15708 * It would be nice if we could "figure these out" somehow 15709 * and fill them in. Otherwise, the userland code has to understand 15710 * driver specific details of which minor node is the "best" or 15711 * "right" one to expose. (Ex: which slice is the whole disk, or 15712 * which tape doesn't rewind) 15713 */ 15714 return (path); 15715 } 15716 15717 static int 15718 fcp_scsi_bus_config(dev_info_t *parent, uint_t flag, 15719 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 15720 { 15721 int64_t reset_delay; 15722 int rval, retry = 0; 15723 struct fcp_port *pptr = fcp_dip2port(parent); 15724 15725 reset_delay = (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15726 (ddi_get_lbolt64() - pptr->port_attach_time); 15727 if (reset_delay < 0) { 15728 reset_delay = 0; 15729 } 15730 15731 if (fcp_bus_config_debug) { 15732 flag |= NDI_DEVI_DEBUG; 15733 } 15734 15735 switch (op) { 15736 case BUS_CONFIG_ONE: 15737 /* 15738 * Retry the command since we need to ensure 15739 * the fabric devices are available for root 15740 */ 15741 while (retry++ < fcp_max_bus_config_retries) { 15742 rval = (ndi_busop_bus_config(parent, 15743 flag | NDI_MDI_FALLBACK, op, 15744 arg, childp, (clock_t)reset_delay)); 15745 if (rval == 0) { 15746 return (rval); 15747 } 15748 } 15749 15750 /* 15751 * drain taskq to make sure nodes are created and then 15752 * try again. 15753 */ 15754 taskq_wait(DEVI(parent)->devi_taskq); 15755 return (ndi_busop_bus_config(parent, flag | NDI_MDI_FALLBACK, 15756 op, arg, childp, 0)); 15757 15758 case BUS_CONFIG_DRIVER: 15759 case BUS_CONFIG_ALL: { 15760 /* 15761 * delay till all devices report in (port_tmp_cnt == 0) 15762 * or FCP_INIT_WAIT_TIMEOUT 15763 */ 15764 mutex_enter(&pptr->port_mutex); 15765 while ((reset_delay > 0) && pptr->port_tmp_cnt) { 15766 (void) cv_timedwait(&pptr->port_config_cv, 15767 &pptr->port_mutex, 15768 ddi_get_lbolt() + (clock_t)reset_delay); 15769 reset_delay = 15770 (int64_t)(USEC_TO_TICK(FCP_INIT_WAIT_TIMEOUT)) - 15771 (ddi_get_lbolt64() - pptr->port_attach_time); 15772 } 15773 mutex_exit(&pptr->port_mutex); 15774 /* drain taskq to make sure nodes are created */ 15775 taskq_wait(DEVI(parent)->devi_taskq); 15776 return (ndi_busop_bus_config(parent, flag, op, 15777 arg, childp, 0)); 15778 } 15779 15780 default: 15781 return (NDI_FAILURE); 15782 } 15783 /*NOTREACHED*/ 15784 } 15785 15786 static int 15787 fcp_scsi_bus_unconfig(dev_info_t *parent, uint_t flag, 15788 ddi_bus_config_op_t op, void *arg) 15789 { 15790 if (fcp_bus_config_debug) { 15791 flag |= NDI_DEVI_DEBUG; 15792 } 15793 15794 return (ndi_busop_bus_unconfig(parent, flag, op, arg)); 15795 } 15796 15797 15798 /* 15799 * Routine to copy GUID into the lun structure. 15800 * returns 0 if copy was successful and 1 if encountered a 15801 * failure and did not copy the guid. 15802 */ 15803 static int 15804 fcp_copy_guid_2_lun_block(struct fcp_lun *plun, char *guidp) 15805 { 15806 15807 int retval = 0; 15808 15809 /* add one for the null terminator */ 15810 const unsigned int len = strlen(guidp) + 1; 15811 15812 if ((guidp == NULL) || (plun == NULL)) { 15813 return (1); 15814 } 15815 15816 /* 15817 * if the plun->lun_guid already has been allocated, 15818 * then check the size. if the size is exact, reuse 15819 * it....if not free it an allocate the required size. 15820 * The reallocation should NOT typically happen 15821 * unless the GUIDs reported changes between passes. 15822 * We free up and alloc again even if the 15823 * size was more than required. This is due to the 15824 * fact that the field lun_guid_size - serves 15825 * dual role of indicating the size of the wwn 15826 * size and ALSO the allocation size. 15827 */ 15828 if (plun->lun_guid) { 15829 if (plun->lun_guid_size != len) { 15830 /* 15831 * free the allocated memory and 15832 * initialize the field 15833 * lun_guid_size to 0. 15834 */ 15835 kmem_free(plun->lun_guid, plun->lun_guid_size); 15836 plun->lun_guid = NULL; 15837 plun->lun_guid_size = 0; 15838 } 15839 } 15840 /* 15841 * alloc only if not already done. 15842 */ 15843 if (plun->lun_guid == NULL) { 15844 plun->lun_guid = kmem_zalloc(len, KM_NOSLEEP); 15845 if (plun->lun_guid == NULL) { 15846 cmn_err(CE_WARN, "fcp_copy_guid_2_lun_block:" 15847 "Unable to allocate" 15848 "Memory for GUID!!! size %d", len); 15849 retval = 1; 15850 } else { 15851 plun->lun_guid_size = len; 15852 } 15853 } 15854 if (plun->lun_guid) { 15855 /* 15856 * now copy the GUID 15857 */ 15858 bcopy(guidp, plun->lun_guid, plun->lun_guid_size); 15859 } 15860 return (retval); 15861 } 15862 15863 /* 15864 * fcp_reconfig_wait 15865 * 15866 * Wait for a rediscovery/reconfiguration to complete before continuing. 15867 */ 15868 15869 static void 15870 fcp_reconfig_wait(struct fcp_port *pptr) 15871 { 15872 clock_t reconfig_start, wait_timeout; 15873 15874 /* 15875 * Quick check. If pptr->port_tmp_cnt is 0, there is no 15876 * reconfiguration in progress. 15877 */ 15878 15879 mutex_enter(&pptr->port_mutex); 15880 if (pptr->port_tmp_cnt == 0) { 15881 mutex_exit(&pptr->port_mutex); 15882 return; 15883 } 15884 mutex_exit(&pptr->port_mutex); 15885 15886 /* 15887 * If we cause a reconfig by raising power, delay until all devices 15888 * report in (port_tmp_cnt returns to 0) 15889 */ 15890 15891 reconfig_start = ddi_get_lbolt(); 15892 wait_timeout = drv_usectohz(FCP_INIT_WAIT_TIMEOUT); 15893 15894 mutex_enter(&pptr->port_mutex); 15895 15896 while (((ddi_get_lbolt() - reconfig_start) < wait_timeout) && 15897 pptr->port_tmp_cnt) { 15898 15899 (void) cv_timedwait(&pptr->port_config_cv, &pptr->port_mutex, 15900 reconfig_start + wait_timeout); 15901 } 15902 15903 mutex_exit(&pptr->port_mutex); 15904 15905 /* 15906 * Even if fcp_tmp_count isn't 0, continue without error. The port 15907 * we want may still be ok. If not, it will error out later 15908 */ 15909 } 15910 15911 /* 15912 * Read masking info from fp.conf and construct the global fcp_lun_blacklist. 15913 * We rely on the fcp_global_mutex to provide protection against changes to 15914 * the fcp_lun_blacklist. 15915 * 15916 * You can describe a list of target port WWNs and LUN numbers which will 15917 * not be configured. LUN numbers will be interpreted as decimal. White 15918 * spaces and ',' can be used in the list of LUN numbers. 15919 * 15920 * To prevent LUNs 1 and 2 from being configured for target 15921 * port 510000f010fd92a1 and target port 510000e012079df1, set: 15922 * 15923 * pwwn-lun-blacklist= 15924 * "510000f010fd92a1,1,2", 15925 * "510000e012079df1,1,2"; 15926 */ 15927 static void 15928 fcp_read_blacklist(dev_info_t *dip, 15929 struct fcp_black_list_entry **pplun_blacklist) { 15930 char **prop_array = NULL; 15931 char *curr_pwwn = NULL; 15932 char *curr_lun = NULL; 15933 uint32_t prop_item = 0; 15934 int idx = 0; 15935 int len = 0; 15936 15937 ASSERT(mutex_owned(&fcp_global_mutex)); 15938 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, 15939 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 15940 LUN_BLACKLIST_PROP, &prop_array, &prop_item) != DDI_PROP_SUCCESS) { 15941 return; 15942 } 15943 15944 for (idx = 0; idx < prop_item; idx++) { 15945 15946 curr_pwwn = prop_array[idx]; 15947 while (*curr_pwwn == ' ') { 15948 curr_pwwn++; 15949 } 15950 if (strlen(curr_pwwn) <= (sizeof (la_wwn_t) * 2 + 1)) { 15951 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15952 ", please check.", curr_pwwn); 15953 continue; 15954 } 15955 if ((*(curr_pwwn + sizeof (la_wwn_t) * 2) != ' ') && 15956 (*(curr_pwwn + sizeof (la_wwn_t) * 2) != ',')) { 15957 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the blacklist" 15958 ", please check.", curr_pwwn); 15959 continue; 15960 } 15961 for (len = 0; len < sizeof (la_wwn_t) * 2; len++) { 15962 if (isxdigit(curr_pwwn[len]) != TRUE) { 15963 fcp_log(CE_WARN, NULL, "Invalid WWN %s in the " 15964 "blacklist, please check.", curr_pwwn); 15965 break; 15966 } 15967 } 15968 if (len != sizeof (la_wwn_t) * 2) { 15969 continue; 15970 } 15971 15972 curr_lun = curr_pwwn + sizeof (la_wwn_t) * 2 + 1; 15973 *(curr_lun - 1) = '\0'; 15974 fcp_mask_pwwn_lun(curr_pwwn, curr_lun, pplun_blacklist); 15975 } 15976 15977 ddi_prop_free(prop_array); 15978 } 15979 15980 /* 15981 * Get the masking info about one remote target port designated by wwn. 15982 * Lun ids could be separated by ',' or white spaces. 15983 */ 15984 static void 15985 fcp_mask_pwwn_lun(char *curr_pwwn, char *curr_lun, 15986 struct fcp_black_list_entry **pplun_blacklist) { 15987 int idx = 0; 15988 uint32_t offset = 0; 15989 unsigned long lun_id = 0; 15990 char lunid_buf[16]; 15991 char *pend = NULL; 15992 int illegal_digit = 0; 15993 15994 while (offset < strlen(curr_lun)) { 15995 while ((curr_lun[offset + idx] != ',') && 15996 (curr_lun[offset + idx] != '\0') && 15997 (curr_lun[offset + idx] != ' ')) { 15998 if (isdigit(curr_lun[offset + idx]) == 0) { 15999 illegal_digit++; 16000 } 16001 idx++; 16002 } 16003 if (illegal_digit > 0) { 16004 offset += (idx+1); /* To the start of next lun */ 16005 idx = 0; 16006 illegal_digit = 0; 16007 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16008 "the blacklist, please check digits.", 16009 curr_lun, curr_pwwn); 16010 continue; 16011 } 16012 if (idx >= (sizeof (lunid_buf) / sizeof (lunid_buf[0]))) { 16013 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16014 "the blacklist, please check the length of LUN#.", 16015 curr_lun, curr_pwwn); 16016 break; 16017 } 16018 if (idx == 0) { /* ignore ' ' or ',' or '\0' */ 16019 offset++; 16020 continue; 16021 } 16022 16023 bcopy(curr_lun + offset, lunid_buf, idx); 16024 lunid_buf[idx] = '\0'; 16025 if (ddi_strtoul(lunid_buf, &pend, 10, &lun_id) == 0) { 16026 fcp_add_one_mask(curr_pwwn, lun_id, pplun_blacklist); 16027 } else { 16028 fcp_log(CE_WARN, NULL, "Invalid LUN %s for WWN %s in " 16029 "the blacklist, please check %s.", 16030 curr_lun, curr_pwwn, lunid_buf); 16031 } 16032 offset += (idx+1); /* To the start of next lun */ 16033 idx = 0; 16034 } 16035 } 16036 16037 /* 16038 * Add one masking record 16039 */ 16040 static void 16041 fcp_add_one_mask(char *curr_pwwn, uint32_t lun_id, 16042 struct fcp_black_list_entry **pplun_blacklist) { 16043 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16044 struct fcp_black_list_entry *new_entry = NULL; 16045 la_wwn_t wwn; 16046 16047 fcp_ascii_to_wwn(curr_pwwn, wwn.raw_wwn, sizeof (la_wwn_t)); 16048 while (tmp_entry) { 16049 if ((bcmp(&tmp_entry->wwn, &wwn, 16050 sizeof (la_wwn_t)) == 0) && (tmp_entry->lun == lun_id)) { 16051 return; 16052 } 16053 16054 tmp_entry = tmp_entry->next; 16055 } 16056 16057 /* add to black list */ 16058 new_entry = (struct fcp_black_list_entry *)kmem_zalloc 16059 (sizeof (struct fcp_black_list_entry), KM_SLEEP); 16060 bcopy(&wwn, &new_entry->wwn, sizeof (la_wwn_t)); 16061 new_entry->lun = lun_id; 16062 new_entry->masked = 0; 16063 new_entry->next = *pplun_blacklist; 16064 *pplun_blacklist = new_entry; 16065 } 16066 16067 /* 16068 * Check if we should mask the specified lun of this fcp_tgt 16069 */ 16070 static int 16071 fcp_should_mask(la_wwn_t *wwn, uint32_t lun_id) { 16072 struct fcp_black_list_entry *remote_port; 16073 16074 remote_port = fcp_lun_blacklist; 16075 while (remote_port != NULL) { 16076 if (bcmp(wwn, &remote_port->wwn, sizeof (la_wwn_t)) == 0) { 16077 if (remote_port->lun == lun_id) { 16078 remote_port->masked++; 16079 if (remote_port->masked == 1) { 16080 fcp_log(CE_NOTE, NULL, "LUN %d of port " 16081 "%02x%02x%02x%02x%02x%02x%02x%02x " 16082 "is masked due to black listing.\n", 16083 lun_id, wwn->raw_wwn[0], 16084 wwn->raw_wwn[1], wwn->raw_wwn[2], 16085 wwn->raw_wwn[3], wwn->raw_wwn[4], 16086 wwn->raw_wwn[5], wwn->raw_wwn[6], 16087 wwn->raw_wwn[7]); 16088 } 16089 return (TRUE); 16090 } 16091 } 16092 remote_port = remote_port->next; 16093 } 16094 return (FALSE); 16095 } 16096 16097 /* 16098 * Release all allocated resources 16099 */ 16100 static void 16101 fcp_cleanup_blacklist(struct fcp_black_list_entry **pplun_blacklist) { 16102 struct fcp_black_list_entry *tmp_entry = *pplun_blacklist; 16103 struct fcp_black_list_entry *current_entry = NULL; 16104 16105 ASSERT(mutex_owned(&fcp_global_mutex)); 16106 /* 16107 * Traverse all luns 16108 */ 16109 while (tmp_entry) { 16110 current_entry = tmp_entry; 16111 tmp_entry = tmp_entry->next; 16112 kmem_free(current_entry, sizeof (struct fcp_black_list_entry)); 16113 } 16114 *pplun_blacklist = NULL; 16115 } 16116 16117 /* 16118 * In fcp module, 16119 * pkt@scsi_pkt, cmd@fcp_pkt, icmd@fcp_ipkt, fpkt@fc_packet, pptr@fcp_port 16120 */ 16121 static struct scsi_pkt * 16122 fcp_pseudo_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 16123 struct buf *bp, int cmdlen, int statuslen, int tgtlen, 16124 int flags, int (*callback)(), caddr_t arg) 16125 { 16126 fcp_port_t *pptr = ADDR2FCP(ap); 16127 fcp_pkt_t *cmd = NULL; 16128 fc_frame_hdr_t *hp; 16129 16130 /* 16131 * First step: get the packet 16132 */ 16133 if (pkt == NULL) { 16134 pkt = scsi_hba_pkt_alloc(pptr->port_dip, ap, cmdlen, statuslen, 16135 tgtlen, sizeof (fcp_pkt_t) + pptr->port_priv_pkt_len, 16136 callback, arg); 16137 if (pkt == NULL) { 16138 return (NULL); 16139 } 16140 16141 /* 16142 * All fields in scsi_pkt will be initialized properly or 16143 * set to zero. We need do nothing for scsi_pkt. 16144 */ 16145 /* 16146 * But it's our responsibility to link other related data 16147 * structures. Their initialization will be done, just 16148 * before the scsi_pkt will be sent to FCA. 16149 */ 16150 cmd = PKT2CMD(pkt); 16151 cmd->cmd_pkt = pkt; 16152 cmd->cmd_fp_pkt = &cmd->cmd_fc_packet; 16153 /* 16154 * fc_packet_t 16155 */ 16156 cmd->cmd_fp_pkt->pkt_ulp_private = (opaque_t)cmd; 16157 cmd->cmd_fp_pkt->pkt_fca_private = (opaque_t)((caddr_t)cmd + 16158 sizeof (struct fcp_pkt)); 16159 cmd->cmd_fp_pkt->pkt_cmd = (caddr_t)&cmd->cmd_fcp_cmd; 16160 cmd->cmd_fp_pkt->pkt_cmdlen = sizeof (struct fcp_cmd); 16161 cmd->cmd_fp_pkt->pkt_resp = cmd->cmd_fcp_rsp; 16162 cmd->cmd_fp_pkt->pkt_rsplen = FCP_MAX_RSP_IU_SIZE; 16163 /* 16164 * Fill in the Fabric Channel Header 16165 */ 16166 hp = &cmd->cmd_fp_pkt->pkt_cmd_fhdr; 16167 hp->r_ctl = R_CTL_COMMAND; 16168 hp->rsvd = 0; 16169 hp->type = FC_TYPE_SCSI_FCP; 16170 hp->f_ctl = F_CTL_SEQ_INITIATIVE | F_CTL_FIRST_SEQ; 16171 hp->seq_id = 0; 16172 hp->df_ctl = 0; 16173 hp->seq_cnt = 0; 16174 hp->ox_id = 0xffff; 16175 hp->rx_id = 0xffff; 16176 hp->ro = 0; 16177 } else { 16178 /* 16179 * We need think if we should reset any elements in 16180 * related data structures. 16181 */ 16182 FCP_TRACE(fcp_logq, pptr->port_instbuf, 16183 fcp_trace, FCP_BUF_LEVEL_6, 0, 16184 "reusing pkt, flags %d", flags); 16185 cmd = PKT2CMD(pkt); 16186 if (cmd->cmd_fp_pkt->pkt_pd) { 16187 cmd->cmd_fp_pkt->pkt_pd = NULL; 16188 } 16189 } 16190 16191 /* 16192 * Second step: dma allocation/move 16193 */ 16194 if (bp && bp->b_bcount != 0) { 16195 /* 16196 * Mark if it's read or write 16197 */ 16198 if (bp->b_flags & B_READ) { 16199 cmd->cmd_flags |= CFLAG_IS_READ; 16200 } else { 16201 cmd->cmd_flags &= ~CFLAG_IS_READ; 16202 } 16203 16204 bp_mapin(bp); 16205 cmd->cmd_fp_pkt->pkt_data = bp->b_un.b_addr; 16206 cmd->cmd_fp_pkt->pkt_datalen = bp->b_bcount; 16207 cmd->cmd_fp_pkt->pkt_data_resid = 0; 16208 } else { 16209 /* 16210 * It seldom happens, except when CLUSTER or SCSI_VHCI wants 16211 * to send zero-length read/write. 16212 */ 16213 cmd->cmd_fp_pkt->pkt_data = NULL; 16214 cmd->cmd_fp_pkt->pkt_datalen = 0; 16215 } 16216 16217 return (pkt); 16218 } 16219 16220 static void 16221 fcp_pseudo_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16222 { 16223 fcp_port_t *pptr = ADDR2FCP(ap); 16224 16225 /* 16226 * First we let FCA to uninitilize private part. 16227 */ 16228 (void) fc_ulp_uninit_packet(pptr->port_fp_handle, 16229 PKT2CMD(pkt)->cmd_fp_pkt); 16230 16231 /* 16232 * Then we uninitialize fc_packet. 16233 */ 16234 16235 /* 16236 * Thirdly, we uninitializae fcp_pkt. 16237 */ 16238 16239 /* 16240 * In the end, we free scsi_pkt. 16241 */ 16242 scsi_hba_pkt_free(ap, pkt); 16243 } 16244 16245 static int 16246 fcp_pseudo_start(struct scsi_address *ap, struct scsi_pkt *pkt) 16247 { 16248 fcp_port_t *pptr = ADDR2FCP(ap); 16249 fcp_lun_t *plun = ADDR2LUN(ap); 16250 fcp_tgt_t *ptgt = plun->lun_tgt; 16251 fcp_pkt_t *cmd = PKT2CMD(pkt); 16252 fcp_cmd_t *fcmd = &cmd->cmd_fcp_cmd; 16253 fc_packet_t *fpkt = cmd->cmd_fp_pkt; 16254 int rval; 16255 16256 fpkt->pkt_pd = ptgt->tgt_pd_handle; 16257 (void) fc_ulp_init_packet(pptr->port_fp_handle, cmd->cmd_fp_pkt, 1); 16258 16259 /* 16260 * Firstly, we need initialize fcp_pkt_t 16261 * Secondly, we need initialize fcp_cmd_t. 16262 */ 16263 bcopy(pkt->pkt_cdbp, fcmd->fcp_cdb, pkt->pkt_cdblen); 16264 fcmd->fcp_data_len = fpkt->pkt_datalen; 16265 fcmd->fcp_ent_addr = plun->lun_addr; 16266 if (pkt->pkt_flags & FLAG_HTAG) { 16267 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_HEAD_OF_Q; 16268 } else if (pkt->pkt_flags & FLAG_OTAG) { 16269 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_ORDERED; 16270 } else if (pkt->pkt_flags & FLAG_STAG) { 16271 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_SIMPLE; 16272 } else { 16273 fcmd->fcp_cntl.cntl_qtype = FCP_QTYPE_UNTAGGED; 16274 } 16275 16276 if (cmd->cmd_flags & CFLAG_IS_READ) { 16277 fcmd->fcp_cntl.cntl_read_data = 1; 16278 fcmd->fcp_cntl.cntl_write_data = 0; 16279 } else { 16280 fcmd->fcp_cntl.cntl_read_data = 0; 16281 fcmd->fcp_cntl.cntl_write_data = 1; 16282 } 16283 16284 /* 16285 * Then we need initialize fc_packet_t too. 16286 */ 16287 fpkt->pkt_timeout = pkt->pkt_time + 2; 16288 fpkt->pkt_cmd_fhdr.d_id = ptgt->tgt_d_id; 16289 fpkt->pkt_cmd_fhdr.s_id = pptr->port_id; 16290 if (cmd->cmd_flags & CFLAG_IS_READ) { 16291 fpkt->pkt_tran_type = FC_PKT_FCP_READ; 16292 } else { 16293 fpkt->pkt_tran_type = FC_PKT_FCP_WRITE; 16294 } 16295 16296 if (pkt->pkt_flags & FLAG_NOINTR) { 16297 fpkt->pkt_comp = NULL; 16298 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_NO_INTR); 16299 } else { 16300 fpkt->pkt_comp = fcp_cmd_callback; 16301 fpkt->pkt_tran_flags = (FC_TRAN_CLASS3 | FC_TRAN_INTR); 16302 if (pkt->pkt_flags & FLAG_IMMEDIATE_CB) { 16303 fpkt->pkt_tran_flags |= FC_TRAN_IMMEDIATE_CB; 16304 } 16305 } 16306 16307 /* 16308 * Lastly, we need initialize scsi_pkt 16309 */ 16310 pkt->pkt_reason = CMD_CMPLT; 16311 pkt->pkt_state = 0; 16312 pkt->pkt_statistics = 0; 16313 pkt->pkt_resid = 0; 16314 16315 /* 16316 * if interrupts aren't allowed (e.g. at dump time) then we'll 16317 * have to do polled I/O 16318 */ 16319 if (pkt->pkt_flags & FLAG_NOINTR) { 16320 return (fcp_dopoll(pptr, cmd)); 16321 } 16322 16323 cmd->cmd_state = FCP_PKT_ISSUED; 16324 rval = fcp_transport(pptr->port_fp_handle, fpkt, 0); 16325 if (rval == FC_SUCCESS) { 16326 return (TRAN_ACCEPT); 16327 } 16328 16329 /* 16330 * Need more consideration 16331 * 16332 * pkt->pkt_flags & FLAG_NOQUEUE could abort other pkt 16333 */ 16334 cmd->cmd_state = FCP_PKT_IDLE; 16335 if (rval == FC_TRAN_BUSY) { 16336 return (TRAN_BUSY); 16337 } else { 16338 return (TRAN_FATAL_ERROR); 16339 } 16340 } 16341 16342 /* 16343 * scsi_poll will always call tran_sync_pkt for pseudo FC-HBAs 16344 * SCSA will initialize it to scsi_sync_cache_pkt for physical FC-HBAs 16345 */ 16346 static void 16347 fcp_pseudo_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 16348 { 16349 FCP_TRACE(fcp_logq, "fcp_pseudo_sync_pkt", fcp_trace, 16350 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16351 } 16352 16353 /* 16354 * scsi_dmafree will always call tran_dmafree, when STATE_ARQ_DONE 16355 */ 16356 static void 16357 fcp_pseudo_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) 16358 { 16359 FCP_TRACE(fcp_logq, "fcp_pseudo_dmafree", fcp_trace, 16360 FCP_BUF_LEVEL_2, 0, "ap-%p, scsi_pkt-%p", ap, pkt); 16361 } --- EOF ---