1 /* 2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18 /** 19 * bfad_im.c Linux driver IM module. 20 */ 21 22 #include <linux/slab.h> 23 #include "bfad_drv.h" 24 #include "bfad_im.h" 25 #include "bfad_trcmod.h" 26 #include "bfa_cb_ioim_macros.h" 27 #include <fcb/bfa_fcb_fcpim.h> 28 29 BFA_TRC_FILE(LDRV, IM); 30 31 DEFINE_IDR(bfad_im_port_index); 32 struct scsi_transport_template *bfad_im_scsi_transport_template; 33 static void bfad_im_itnim_work_handler(struct work_struct *work); 34 static int bfad_im_queuecommand(struct scsi_cmnd *cmnd, 35 void (*done)(struct scsi_cmnd *)); 36 static int bfad_im_slave_alloc(struct scsi_device *sdev); 37 38 void 39 bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio, 40 enum bfi_ioim_status io_status, u8 scsi_status, 41 int sns_len, u8 *sns_info, s32 residue) 42 { 43 struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; 44 struct bfad_s *bfad = drv; 45 struct bfad_itnim_data_s *itnim_data; 46 struct bfad_itnim_s *itnim; 47 u8 host_status = DID_OK; 48 49 switch (io_status) { 50 case BFI_IOIM_STS_OK: 51 bfa_trc(bfad, scsi_status); 52 scsi_set_resid(cmnd, 0); 53 54 if (sns_len > 0) { 55 bfa_trc(bfad, sns_len); 56 if (sns_len > SCSI_SENSE_BUFFERSIZE) 57 sns_len = SCSI_SENSE_BUFFERSIZE; 58 memcpy(cmnd->sense_buffer, sns_info, sns_len); 59 } 60 if (residue > 0) { 61 bfa_trc(bfad, residue); 62 scsi_set_resid(cmnd, residue); 63 if (!sns_len && (scsi_status == SAM_STAT_GOOD) && 64 (scsi_bufflen(cmnd) - residue) < 65 cmnd->underflow) { 66 bfa_trc(bfad, 0); 67 host_status = DID_ERROR; 68 } 69 } 70 cmnd->result = ScsiResult(host_status, scsi_status); 71 72 break; 73 74 case BFI_IOIM_STS_ABORTED: 75 case BFI_IOIM_STS_TIMEDOUT: 76 case BFI_IOIM_STS_PATHTOV: 77 default: 78 cmnd->result = ScsiResult(DID_ERROR, 0); 79 } 80 81 /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ 82 if (cmnd->device->host != NULL) 83 scsi_dma_unmap(cmnd); 84 85 cmnd->host_scribble = NULL; 86 bfa_trc(bfad, cmnd->result); 87 88 itnim_data = cmnd->device->hostdata; 89 if (itnim_data) { 90 itnim = itnim_data->itnim; 91 if (!cmnd->result && itnim && 92 (bfa_lun_queue_depth > cmnd->device->queue_depth)) { 93 /* Queue depth adjustment for good status completion */ 94 bfad_os_ramp_up_qdepth(itnim, cmnd->device); 95 } else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) { 96 /* qfull handling */ 97 bfad_os_handle_qfull(itnim, cmnd->device); 98 } 99 } 100 101 cmnd->scsi_done(cmnd); 102 } 103 104 void 105 bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio) 106 { 107 struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; 108 struct bfad_itnim_data_s *itnim_data; 109 struct bfad_itnim_s *itnim; 110 111 cmnd->result = ScsiResult(DID_OK, SCSI_STATUS_GOOD); 112 113 /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ 114 if (cmnd->device->host != NULL) 115 scsi_dma_unmap(cmnd); 116 117 cmnd->host_scribble = NULL; 118 119 /* Queue depth adjustment */ 120 if (bfa_lun_queue_depth > cmnd->device->queue_depth) { 121 itnim_data = cmnd->device->hostdata; 122 if (itnim_data) { 123 itnim = itnim_data->itnim; 124 if (itnim) 125 bfad_os_ramp_up_qdepth(itnim, cmnd->device); 126 } 127 } 128 129 cmnd->scsi_done(cmnd); 130 } 131 132 void 133 bfa_cb_ioim_abort(void *drv, struct bfad_ioim_s *dio) 134 { 135 struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; 136 struct bfad_s *bfad = drv; 137 138 cmnd->result = ScsiResult(DID_ERROR, 0); 139 140 /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ 141 if (cmnd->device->host != NULL) 142 scsi_dma_unmap(cmnd); 143 144 bfa_trc(bfad, cmnd->result); 145 cmnd->host_scribble = NULL; 146 } 147 148 void 149 bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, 150 enum bfi_tskim_status tsk_status) 151 { 152 struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dtsk; 153 wait_queue_head_t *wq; 154 155 cmnd->SCp.Status |= tsk_status << 1; 156 set_bit(IO_DONE_BIT, (unsigned long *)&cmnd->SCp.Status); 157 wq = (wait_queue_head_t *) cmnd->SCp.ptr; 158 cmnd->SCp.ptr = NULL; 159 160 if (wq) 161 wake_up(wq); 162 } 163 164 void 165 bfa_cb_ioim_resfree(void *drv) 166 { 167 } 168 169 /** 170 * Scsi_Host_template SCSI host template 171 */ 172 /** 173 * Scsi_Host template entry, returns BFAD PCI info. 174 */ 175 static const char * 176 bfad_im_info(struct Scsi_Host *shost) 177 { 178 static char bfa_buf[256]; 179 struct bfad_im_port_s *im_port = 180 (struct bfad_im_port_s *) shost->hostdata[0]; 181 struct bfad_s *bfad = im_port->bfad; 182 char model[BFA_ADAPTER_MODEL_NAME_LEN]; 183 184 bfa_get_adapter_model(&bfad->bfa, model); 185 186 memset(bfa_buf, 0, sizeof(bfa_buf)); 187 snprintf(bfa_buf, sizeof(bfa_buf), 188 "Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s", 189 model, bfad->pci_name, BFAD_DRIVER_VERSION); 190 return bfa_buf; 191 } 192 193 /** 194 * Scsi_Host template entry, aborts the specified SCSI command. 195 * 196 * Returns: SUCCESS or FAILED. 197 */ 198 static int 199 bfad_im_abort_handler(struct scsi_cmnd *cmnd) 200 { 201 struct Scsi_Host *shost = cmnd->device->host; 202 struct bfad_im_port_s *im_port = 203 (struct bfad_im_port_s *) shost->hostdata[0]; 204 struct bfad_s *bfad = im_port->bfad; 205 struct bfa_ioim_s *hal_io; 206 unsigned long flags; 207 u32 timeout; 208 int rc = FAILED; 209 210 spin_lock_irqsave(&bfad->bfad_lock, flags); 211 hal_io = (struct bfa_ioim_s *) cmnd->host_scribble; 212 if (!hal_io) { 213 /* IO has been completed, retrun success */ 214 rc = SUCCESS; 215 goto out; 216 } 217 if (hal_io->dio != (struct bfad_ioim_s *) cmnd) { 218 rc = FAILED; 219 goto out; 220 } 221 222 bfa_trc(bfad, hal_io->iotag); 223 bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT, 224 im_port->shost->host_no, cmnd, hal_io->iotag); 225 bfa_ioim_abort(hal_io); 226 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 227 228 /* Need to wait until the command get aborted */ 229 timeout = 10; 230 while ((struct bfa_ioim_s *) cmnd->host_scribble == hal_io) { 231 set_current_state(TASK_UNINTERRUPTIBLE); 232 schedule_timeout(timeout); 233 if (timeout < 4 * HZ) 234 timeout *= 2; 235 } 236 237 cmnd->scsi_done(cmnd); 238 bfa_trc(bfad, hal_io->iotag); 239 bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP, 240 im_port->shost->host_no, cmnd, hal_io->iotag); 241 return SUCCESS; 242 out: 243 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 244 return rc; 245 } 246 247 static bfa_status_t 248 bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd, 249 struct bfad_itnim_s *itnim) 250 { 251 struct bfa_tskim_s *tskim; 252 struct bfa_itnim_s *bfa_itnim; 253 bfa_status_t rc = BFA_STATUS_OK; 254 255 bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); 256 tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd); 257 if (!tskim) { 258 BFA_DEV_PRINTF(bfad, BFA_ERR, 259 "target reset, fail to allocate tskim\n"); 260 rc = BFA_STATUS_FAILED; 261 goto out; 262 } 263 264 /* 265 * Set host_scribble to NULL to avoid aborting a task command if 266 * happens. 267 */ 268 cmnd->host_scribble = NULL; 269 cmnd->SCp.Status = 0; 270 bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); 271 bfa_tskim_start(tskim, bfa_itnim, (lun_t)0, 272 FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO); 273 out: 274 return rc; 275 } 276 277 /** 278 * Scsi_Host template entry, resets a LUN and abort its all commands. 279 * 280 * Returns: SUCCESS or FAILED. 281 * 282 */ 283 static int 284 bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) 285 { 286 struct Scsi_Host *shost = cmnd->device->host; 287 struct bfad_im_port_s *im_port = 288 (struct bfad_im_port_s *) shost->hostdata[0]; 289 struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata; 290 struct bfad_s *bfad = im_port->bfad; 291 struct bfa_tskim_s *tskim; 292 struct bfad_itnim_s *itnim; 293 struct bfa_itnim_s *bfa_itnim; 294 DECLARE_WAIT_QUEUE_HEAD(wq); 295 int rc = SUCCESS; 296 unsigned long flags; 297 enum bfi_tskim_status task_status; 298 299 spin_lock_irqsave(&bfad->bfad_lock, flags); 300 itnim = itnim_data->itnim; 301 if (!itnim) { 302 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 303 rc = FAILED; 304 goto out; 305 } 306 307 tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd); 308 if (!tskim) { 309 BFA_DEV_PRINTF(bfad, BFA_ERR, 310 "LUN reset, fail to allocate tskim"); 311 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 312 rc = FAILED; 313 goto out; 314 } 315 316 /** 317 * Set host_scribble to NULL to avoid aborting a task command 318 * if happens. 319 */ 320 cmnd->host_scribble = NULL; 321 cmnd->SCp.ptr = (char *)&wq; 322 cmnd->SCp.Status = 0; 323 bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); 324 bfa_tskim_start(tskim, bfa_itnim, 325 bfad_int_to_lun(cmnd->device->lun), 326 FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO); 327 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 328 329 wait_event(wq, test_bit(IO_DONE_BIT, 330 (unsigned long *)&cmnd->SCp.Status)); 331 332 task_status = cmnd->SCp.Status >> 1; 333 if (task_status != BFI_TSKIM_STS_OK) { 334 BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n", 335 task_status); 336 rc = FAILED; 337 } 338 339 out: 340 return rc; 341 } 342 343 /** 344 * Scsi_Host template entry, resets the bus and abort all commands. 345 */ 346 static int 347 bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) 348 { 349 struct Scsi_Host *shost = cmnd->device->host; 350 struct bfad_im_port_s *im_port = 351 (struct bfad_im_port_s *) shost->hostdata[0]; 352 struct bfad_s *bfad = im_port->bfad; 353 struct bfad_itnim_s *itnim; 354 unsigned long flags; 355 u32 i, rc, err_cnt = 0; 356 DECLARE_WAIT_QUEUE_HEAD(wq); 357 enum bfi_tskim_status task_status; 358 359 spin_lock_irqsave(&bfad->bfad_lock, flags); 360 for (i = 0; i < MAX_FCP_TARGET; i++) { 361 itnim = bfad_os_get_itnim(im_port, i); 362 if (itnim) { 363 cmnd->SCp.ptr = (char *)&wq; 364 rc = bfad_im_target_reset_send(bfad, cmnd, itnim); 365 if (rc != BFA_STATUS_OK) { 366 err_cnt++; 367 continue; 368 } 369 370 /* wait target reset to complete */ 371 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 372 wait_event(wq, test_bit(IO_DONE_BIT, 373 (unsigned long *)&cmnd->SCp.Status)); 374 spin_lock_irqsave(&bfad->bfad_lock, flags); 375 376 task_status = cmnd->SCp.Status >> 1; 377 if (task_status != BFI_TSKIM_STS_OK) { 378 BFA_DEV_PRINTF(bfad, BFA_ERR, 379 "target reset failure," 380 " status: %d\n", task_status); 381 err_cnt++; 382 } 383 } 384 } 385 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 386 387 if (err_cnt) 388 return FAILED; 389 390 return SUCCESS; 391 } 392 393 /** 394 * Scsi_Host template entry slave_destroy. 395 */ 396 static void 397 bfad_im_slave_destroy(struct scsi_device *sdev) 398 { 399 sdev->hostdata = NULL; 400 return; 401 } 402 403 /** 404 * BFA FCS itnim callbacks 405 */ 406 407 /** 408 * BFA FCS itnim alloc callback, after successful PRLI 409 * Context: Interrupt 410 */ 411 void 412 bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, 413 struct bfad_itnim_s **itnim_drv) 414 { 415 *itnim_drv = kzalloc(sizeof(struct bfad_itnim_s), GFP_ATOMIC); 416 if (*itnim_drv == NULL) 417 return; 418 419 (*itnim_drv)->im = bfad->im; 420 *itnim = &(*itnim_drv)->fcs_itnim; 421 (*itnim_drv)->state = ITNIM_STATE_NONE; 422 423 /* 424 * Initiaze the itnim_work 425 */ 426 INIT_WORK(&(*itnim_drv)->itnim_work, bfad_im_itnim_work_handler); 427 bfad->bfad_flags |= BFAD_RPORT_ONLINE; 428 } 429 430 /** 431 * BFA FCS itnim free callback. 432 * Context: Interrupt. bfad_lock is held 433 */ 434 void 435 bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv) 436 { 437 struct bfad_port_s *port; 438 wwn_t wwpn; 439 u32 fcid; 440 char wwpn_str[32], fcid_str[16]; 441 442 /* online to free state transtion should not happen */ 443 bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE); 444 445 itnim_drv->queue_work = 1; 446 /* offline request is not yet done, use the same request to free */ 447 if (itnim_drv->state == ITNIM_STATE_OFFLINE_PENDING) 448 itnim_drv->queue_work = 0; 449 450 itnim_drv->state = ITNIM_STATE_FREE; 451 port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); 452 itnim_drv->im_port = port->im_port; 453 wwpn = bfa_fcs_itnim_get_pwwn(&itnim_drv->fcs_itnim); 454 fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim); 455 wwn2str(wwpn_str, wwpn); 456 fcid2str(fcid_str, fcid); 457 bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE, 458 port->im_port->shost->host_no, 459 fcid_str, wwpn_str); 460 bfad_os_itnim_process(itnim_drv); 461 } 462 463 /** 464 * BFA FCS itnim online callback. 465 * Context: Interrupt. bfad_lock is held 466 */ 467 void 468 bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv) 469 { 470 struct bfad_port_s *port; 471 472 itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim); 473 port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); 474 itnim_drv->state = ITNIM_STATE_ONLINE; 475 itnim_drv->queue_work = 1; 476 itnim_drv->im_port = port->im_port; 477 bfad_os_itnim_process(itnim_drv); 478 } 479 480 /** 481 * BFA FCS itnim offline callback. 482 * Context: Interrupt. bfad_lock is held 483 */ 484 void 485 bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv) 486 { 487 struct bfad_port_s *port; 488 struct bfad_s *bfad; 489 490 port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); 491 bfad = port->bfad; 492 if ((bfad->pport.flags & BFAD_PORT_DELETE) || 493 (port->flags & BFAD_PORT_DELETE)) { 494 itnim_drv->state = ITNIM_STATE_OFFLINE; 495 return; 496 } 497 itnim_drv->im_port = port->im_port; 498 itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING; 499 itnim_drv->queue_work = 1; 500 bfad_os_itnim_process(itnim_drv); 501 } 502 503 /** 504 * BFA FCS itnim timeout callback. 505 * Context: Interrupt. bfad_lock is held 506 */ 507 void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim) 508 { 509 itnim->state = ITNIM_STATE_TIMEOUT; 510 } 511 512 /** 513 * Allocate a Scsi_Host for a port. 514 */ 515 int 516 bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port) 517 { 518 int error = 1; 519 520 if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) { 521 printk(KERN_WARNING "idr_pre_get failure\n"); 522 goto out; 523 } 524 525 error = idr_get_new(&bfad_im_port_index, im_port, 526 &im_port->idr_id); 527 if (error) { 528 printk(KERN_WARNING "idr_get_new failure\n"); 529 goto out; 530 } 531 532 im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad); 533 if (!im_port->shost) { 534 error = 1; 535 goto out_free_idr; 536 } 537 538 im_port->shost->hostdata[0] = (unsigned long)im_port; 539 im_port->shost->unique_id = im_port->idr_id; 540 im_port->shost->this_id = -1; 541 im_port->shost->max_id = MAX_FCP_TARGET; 542 im_port->shost->max_lun = MAX_FCP_LUN; 543 im_port->shost->max_cmd_len = 16; 544 im_port->shost->can_queue = bfad->cfg_data.ioc_queue_depth; 545 im_port->shost->transportt = bfad_im_scsi_transport_template; 546 547 error = bfad_os_scsi_add_host(im_port->shost, im_port, bfad); 548 if (error) { 549 printk(KERN_WARNING "bfad_os_scsi_add_host failure %d\n", 550 error); 551 goto out_fc_rel; 552 } 553 554 /* setup host fixed attribute if the lk supports */ 555 bfad_os_fc_host_init(im_port); 556 557 return 0; 558 559 out_fc_rel: 560 scsi_host_put(im_port->shost); 561 out_free_idr: 562 idr_remove(&bfad_im_port_index, im_port->idr_id); 563 out: 564 return error; 565 } 566 567 void 568 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) 569 { 570 unsigned long flags; 571 572 bfa_trc(bfad, bfad->inst_no); 573 bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE, 574 im_port->shost->host_no); 575 576 fc_remove_host(im_port->shost); 577 578 scsi_remove_host(im_port->shost); 579 scsi_host_put(im_port->shost); 580 581 spin_lock_irqsave(&bfad->bfad_lock, flags); 582 idr_remove(&bfad_im_port_index, im_port->idr_id); 583 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 584 } 585 586 static void 587 bfad_im_port_delete_handler(struct work_struct *work) 588 { 589 struct bfad_im_port_s *im_port = 590 container_of(work, struct bfad_im_port_s, port_delete_work); 591 592 bfad_im_scsi_host_free(im_port->bfad, im_port); 593 bfad_im_port_clean(im_port); 594 kfree(im_port); 595 } 596 597 bfa_status_t 598 bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port) 599 { 600 int rc = BFA_STATUS_OK; 601 struct bfad_im_port_s *im_port; 602 603 im_port = kzalloc(sizeof(struct bfad_im_port_s), GFP_ATOMIC); 604 if (im_port == NULL) { 605 rc = BFA_STATUS_ENOMEM; 606 goto ext; 607 } 608 port->im_port = im_port; 609 im_port->port = port; 610 im_port->bfad = bfad; 611 612 INIT_WORK(&im_port->port_delete_work, bfad_im_port_delete_handler); 613 INIT_LIST_HEAD(&im_port->itnim_mapped_list); 614 INIT_LIST_HEAD(&im_port->binding_list); 615 616 ext: 617 return rc; 618 } 619 620 void 621 bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port) 622 { 623 struct bfad_im_port_s *im_port = port->im_port; 624 625 queue_work(bfad->im->drv_workq, 626 &im_port->port_delete_work); 627 } 628 629 void 630 bfad_im_port_clean(struct bfad_im_port_s *im_port) 631 { 632 struct bfad_fcp_binding *bp, *bp_new; 633 unsigned long flags; 634 struct bfad_s *bfad = im_port->bfad; 635 636 spin_lock_irqsave(&bfad->bfad_lock, flags); 637 list_for_each_entry_safe(bp, bp_new, &im_port->binding_list, 638 list_entry) { 639 list_del(&bp->list_entry); 640 kfree(bp); 641 } 642 643 /* the itnim_mapped_list must be empty at this time */ 644 bfa_assert(list_empty(&im_port->itnim_mapped_list)); 645 646 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 647 } 648 649 void 650 bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port) 651 { 652 } 653 654 void 655 bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port) 656 { 657 } 658 659 bfa_status_t 660 bfad_im_probe(struct bfad_s *bfad) 661 { 662 struct bfad_im_s *im; 663 bfa_status_t rc = BFA_STATUS_OK; 664 665 im = kzalloc(sizeof(struct bfad_im_s), GFP_KERNEL); 666 if (im == NULL) { 667 rc = BFA_STATUS_ENOMEM; 668 goto ext; 669 } 670 671 bfad->im = im; 672 im->bfad = bfad; 673 674 if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) { 675 kfree(im); 676 rc = BFA_STATUS_FAILED; 677 } 678 679 ext: 680 return rc; 681 } 682 683 void 684 bfad_im_probe_undo(struct bfad_s *bfad) 685 { 686 if (bfad->im) { 687 bfad_os_destroy_workq(bfad->im); 688 kfree(bfad->im); 689 bfad->im = NULL; 690 } 691 } 692 693 694 695 696 int 697 bfad_os_scsi_add_host(struct Scsi_Host *shost, struct bfad_im_port_s *im_port, 698 struct bfad_s *bfad) 699 { 700 struct device *dev; 701 702 if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE) 703 dev = &bfad->pcidev->dev; 704 else 705 dev = &bfad->pport.im_port->shost->shost_gendev; 706 707 return scsi_add_host(shost, dev); 708 } 709 710 struct Scsi_Host * 711 bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) 712 { 713 struct scsi_host_template *sht; 714 715 if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE) 716 sht = &bfad_im_scsi_host_template; 717 else 718 sht = &bfad_im_vport_template; 719 720 sht->sg_tablesize = bfad->cfg_data.io_max_sge; 721 722 return scsi_host_alloc(sht, sizeof(unsigned long)); 723 } 724 725 void 726 bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) 727 { 728 flush_workqueue(bfad->im->drv_workq); 729 bfad_im_scsi_host_free(im_port->bfad, im_port); 730 bfad_im_port_clean(im_port); 731 kfree(im_port); 732 } 733 734 void 735 bfad_os_destroy_workq(struct bfad_im_s *im) 736 { 737 if (im && im->drv_workq) { 738 destroy_workqueue(im->drv_workq); 739 im->drv_workq = NULL; 740 } 741 } 742 743 bfa_status_t 744 bfad_os_thread_workq(struct bfad_s *bfad) 745 { 746 struct bfad_im_s *im = bfad->im; 747 748 bfa_trc(bfad, 0); 749 snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d", 750 bfad->inst_no); 751 im->drv_workq = create_singlethread_workqueue(im->drv_workq_name); 752 if (!im->drv_workq) 753 return BFA_STATUS_FAILED; 754 755 return BFA_STATUS_OK; 756 } 757 758 /** 759 * Scsi_Host template entry. 760 * 761 * Description: 762 * OS entry point to adjust the queue_depths on a per-device basis. 763 * Called once per device during the bus scan. 764 * Return non-zero if fails. 765 */ 766 static int 767 bfad_im_slave_configure(struct scsi_device *sdev) 768 { 769 if (sdev->tagged_supported) 770 scsi_activate_tcq(sdev, bfa_lun_queue_depth); 771 else 772 scsi_deactivate_tcq(sdev, bfa_lun_queue_depth); 773 774 return 0; 775 } 776 777 struct scsi_host_template bfad_im_scsi_host_template = { 778 .module = THIS_MODULE, 779 .name = BFAD_DRIVER_NAME, 780 .info = bfad_im_info, 781 .queuecommand = bfad_im_queuecommand, 782 .eh_abort_handler = bfad_im_abort_handler, 783 .eh_device_reset_handler = bfad_im_reset_lun_handler, 784 .eh_bus_reset_handler = bfad_im_reset_bus_handler, 785 786 .slave_alloc = bfad_im_slave_alloc, 787 .slave_configure = bfad_im_slave_configure, 788 .slave_destroy = bfad_im_slave_destroy, 789 790 .this_id = -1, 791 .sg_tablesize = BFAD_IO_MAX_SGE, 792 .cmd_per_lun = 3, 793 .use_clustering = ENABLE_CLUSTERING, 794 .shost_attrs = bfad_im_host_attrs, 795 .max_sectors = 0xFFFF, 796 }; 797 798 struct scsi_host_template bfad_im_vport_template = { 799 .module = THIS_MODULE, 800 .name = BFAD_DRIVER_NAME, 801 .info = bfad_im_info, 802 .queuecommand = bfad_im_queuecommand, 803 .eh_abort_handler = bfad_im_abort_handler, 804 .eh_device_reset_handler = bfad_im_reset_lun_handler, 805 .eh_bus_reset_handler = bfad_im_reset_bus_handler, 806 807 .slave_alloc = bfad_im_slave_alloc, 808 .slave_configure = bfad_im_slave_configure, 809 .slave_destroy = bfad_im_slave_destroy, 810 811 .this_id = -1, 812 .sg_tablesize = BFAD_IO_MAX_SGE, 813 .cmd_per_lun = 3, 814 .use_clustering = ENABLE_CLUSTERING, 815 .shost_attrs = bfad_im_vport_attrs, 816 .max_sectors = 0xFFFF, 817 }; 818 819 void 820 bfad_im_probe_post(struct bfad_im_s *im) 821 { 822 flush_workqueue(im->drv_workq); 823 } 824 825 bfa_status_t 826 bfad_im_module_init(void) 827 { 828 bfad_im_scsi_transport_template = 829 fc_attach_transport(&bfad_im_fc_function_template); 830 if (!bfad_im_scsi_transport_template) 831 return BFA_STATUS_ENOMEM; 832 833 return BFA_STATUS_OK; 834 } 835 836 void 837 bfad_im_module_exit(void) 838 { 839 if (bfad_im_scsi_transport_template) 840 fc_release_transport(bfad_im_scsi_transport_template); 841 } 842 843 void 844 bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv) 845 { 846 struct bfad_im_s *im = itnim_drv->im; 847 848 if (itnim_drv->queue_work) 849 queue_work(im->drv_workq, &itnim_drv->itnim_work); 850 } 851 852 void 853 bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) 854 { 855 struct scsi_device *tmp_sdev; 856 857 if (((jiffies - itnim->last_ramp_up_time) > 858 BFA_QUEUE_FULL_RAMP_UP_TIME * HZ) && 859 ((jiffies - itnim->last_queue_full_time) > 860 BFA_QUEUE_FULL_RAMP_UP_TIME * HZ)) { 861 shost_for_each_device(tmp_sdev, sdev->host) { 862 if (bfa_lun_queue_depth > tmp_sdev->queue_depth) { 863 if (tmp_sdev->id != sdev->id) 864 continue; 865 if (tmp_sdev->ordered_tags) 866 scsi_adjust_queue_depth(tmp_sdev, 867 MSG_ORDERED_TAG, 868 tmp_sdev->queue_depth + 1); 869 else 870 scsi_adjust_queue_depth(tmp_sdev, 871 MSG_SIMPLE_TAG, 872 tmp_sdev->queue_depth + 1); 873 874 itnim->last_ramp_up_time = jiffies; 875 } 876 } 877 } 878 } 879 880 void 881 bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) 882 { 883 struct scsi_device *tmp_sdev; 884 885 itnim->last_queue_full_time = jiffies; 886 887 shost_for_each_device(tmp_sdev, sdev->host) { 888 if (tmp_sdev->id != sdev->id) 889 continue; 890 scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1); 891 } 892 } 893 894 895 896 897 struct bfad_itnim_s * 898 bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id) 899 { 900 struct bfad_itnim_s *itnim = NULL; 901 902 /* Search the mapped list for this target ID */ 903 list_for_each_entry(itnim, &im_port->itnim_mapped_list, list_entry) { 904 if (id == itnim->scsi_tgt_id) 905 return itnim; 906 } 907 908 return NULL; 909 } 910 911 /** 912 * Scsi_Host template entry slave_alloc 913 */ 914 static int 915 bfad_im_slave_alloc(struct scsi_device *sdev) 916 { 917 struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 918 919 if (!rport || fc_remote_port_chkready(rport)) 920 return -ENXIO; 921 922 sdev->hostdata = rport->dd_data; 923 924 return 0; 925 } 926 927 void 928 bfad_os_fc_host_init(struct bfad_im_port_s *im_port) 929 { 930 struct Scsi_Host *host = im_port->shost; 931 struct bfad_s *bfad = im_port->bfad; 932 struct bfad_port_s *port = im_port->port; 933 struct bfa_pport_attr_s pattr; 934 char model[BFA_ADAPTER_MODEL_NAME_LEN]; 935 char fw_ver[BFA_VERSION_LEN]; 936 937 fc_host_node_name(host) = 938 bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port))); 939 fc_host_port_name(host) = 940 bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port))); 941 942 fc_host_supported_classes(host) = FC_COS_CLASS3; 943 944 memset(fc_host_supported_fc4s(host), 0, 945 sizeof(fc_host_supported_fc4s(host))); 946 if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM)) 947 /* For FCP type 0x08 */ 948 fc_host_supported_fc4s(host)[2] = 1; 949 if (bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IPFC) 950 /* For LLC/SNAP type 0x05 */ 951 fc_host_supported_fc4s(host)[3] = 0x20; 952 /* For fibre channel services type 0x20 */ 953 fc_host_supported_fc4s(host)[7] = 1; 954 955 bfa_get_adapter_model(&bfad->bfa, model); 956 bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver); 957 sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s", 958 model, fw_ver, BFAD_DRIVER_VERSION); 959 960 fc_host_supported_speeds(host) = 0; 961 fc_host_supported_speeds(host) |= 962 FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | 963 FC_PORTSPEED_1GBIT; 964 965 bfa_fcport_get_attr(&bfad->bfa, &pattr); 966 fc_host_maxframe_size(host) = pattr.pport_cfg.maxfrsize; 967 } 968 969 static void 970 bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim) 971 { 972 struct fc_rport_identifiers rport_ids; 973 struct fc_rport *fc_rport; 974 struct bfad_itnim_data_s *itnim_data; 975 976 rport_ids.node_name = 977 bfa_os_htonll(bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim)); 978 rport_ids.port_name = 979 bfa_os_htonll(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim)); 980 rport_ids.port_id = 981 bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim)); 982 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 983 984 itnim->fc_rport = fc_rport = 985 fc_remote_port_add(im_port->shost, 0, &rport_ids); 986 987 if (!fc_rport) 988 return; 989 990 fc_rport->maxframe_size = 991 bfa_fcs_itnim_get_maxfrsize(&itnim->fcs_itnim); 992 fc_rport->supported_classes = bfa_fcs_itnim_get_cos(&itnim->fcs_itnim); 993 994 itnim_data = fc_rport->dd_data; 995 itnim_data->itnim = itnim; 996 997 rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; 998 999 if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) 1000 fc_remote_port_rolechg(fc_rport, rport_ids.roles); 1001 1002 if ((fc_rport->scsi_target_id != -1) 1003 && (fc_rport->scsi_target_id < MAX_FCP_TARGET)) 1004 itnim->scsi_tgt_id = fc_rport->scsi_target_id; 1005 1006 return; 1007 } 1008 1009 /** 1010 * Work queue handler using FC transport service 1011 * Context: kernel 1012 */ 1013 static void 1014 bfad_im_itnim_work_handler(struct work_struct *work) 1015 { 1016 struct bfad_itnim_s *itnim = container_of(work, struct bfad_itnim_s, 1017 itnim_work); 1018 struct bfad_im_s *im = itnim->im; 1019 struct bfad_s *bfad = im->bfad; 1020 struct bfad_im_port_s *im_port; 1021 unsigned long flags; 1022 struct fc_rport *fc_rport; 1023 wwn_t wwpn; 1024 u32 fcid; 1025 char wwpn_str[32], fcid_str[16]; 1026 1027 spin_lock_irqsave(&bfad->bfad_lock, flags); 1028 im_port = itnim->im_port; 1029 bfa_trc(bfad, itnim->state); 1030 switch (itnim->state) { 1031 case ITNIM_STATE_ONLINE: 1032 if (!itnim->fc_rport) { 1033 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1034 bfad_im_fc_rport_add(im_port, itnim); 1035 spin_lock_irqsave(&bfad->bfad_lock, flags); 1036 wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); 1037 fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); 1038 wwn2str(wwpn_str, wwpn); 1039 fcid2str(fcid_str, fcid); 1040 list_add_tail(&itnim->list_entry, 1041 &im_port->itnim_mapped_list); 1042 bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE, 1043 im_port->shost->host_no, 1044 itnim->scsi_tgt_id, 1045 fcid_str, wwpn_str); 1046 } else { 1047 printk(KERN_WARNING 1048 "%s: itnim %llx is already in online state\n", 1049 __func__, 1050 bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim)); 1051 } 1052 1053 break; 1054 case ITNIM_STATE_OFFLINE_PENDING: 1055 itnim->state = ITNIM_STATE_OFFLINE; 1056 if (itnim->fc_rport) { 1057 fc_rport = itnim->fc_rport; 1058 ((struct bfad_itnim_data_s *) 1059 fc_rport->dd_data)->itnim = NULL; 1060 itnim->fc_rport = NULL; 1061 if (!(im_port->port->flags & BFAD_PORT_DELETE)) { 1062 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1063 fc_rport->dev_loss_tmo = 1064 bfa_fcpim_path_tov_get(&bfad->bfa) + 1; 1065 fc_remote_port_delete(fc_rport); 1066 spin_lock_irqsave(&bfad->bfad_lock, flags); 1067 } 1068 wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); 1069 fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); 1070 wwn2str(wwpn_str, wwpn); 1071 fcid2str(fcid_str, fcid); 1072 list_del(&itnim->list_entry); 1073 bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE, 1074 im_port->shost->host_no, 1075 itnim->scsi_tgt_id, 1076 fcid_str, wwpn_str); 1077 } 1078 break; 1079 case ITNIM_STATE_FREE: 1080 if (itnim->fc_rport) { 1081 fc_rport = itnim->fc_rport; 1082 ((struct bfad_itnim_data_s *) 1083 fc_rport->dd_data)->itnim = NULL; 1084 itnim->fc_rport = NULL; 1085 if (!(im_port->port->flags & BFAD_PORT_DELETE)) { 1086 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1087 fc_rport->dev_loss_tmo = 1088 bfa_fcpim_path_tov_get(&bfad->bfa) + 1; 1089 fc_remote_port_delete(fc_rport); 1090 spin_lock_irqsave(&bfad->bfad_lock, flags); 1091 } 1092 list_del(&itnim->list_entry); 1093 } 1094 1095 kfree(itnim); 1096 break; 1097 default: 1098 bfa_assert(0); 1099 break; 1100 } 1101 1102 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1103 } 1104 1105 /** 1106 * Scsi_Host template entry, queue a SCSI command to the BFAD. 1107 */ 1108 static int 1109 bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) 1110 { 1111 struct bfad_im_port_s *im_port = 1112 (struct bfad_im_port_s *) cmnd->device->host->hostdata[0]; 1113 struct bfad_s *bfad = im_port->bfad; 1114 struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata; 1115 struct bfad_itnim_s *itnim; 1116 struct bfa_ioim_s *hal_io; 1117 unsigned long flags; 1118 int rc; 1119 s16 sg_cnt = 0; 1120 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); 1121 1122 rc = fc_remote_port_chkready(rport); 1123 if (rc) { 1124 cmnd->result = rc; 1125 done(cmnd); 1126 return 0; 1127 } 1128 1129 sg_cnt = scsi_dma_map(cmnd); 1130 1131 if (sg_cnt < 0) 1132 return SCSI_MLQUEUE_HOST_BUSY; 1133 1134 cmnd->scsi_done = done; 1135 1136 spin_lock_irqsave(&bfad->bfad_lock, flags); 1137 if (!(bfad->bfad_flags & BFAD_HAL_START_DONE)) { 1138 printk(KERN_WARNING 1139 "bfad%d, queuecommand %p %x failed, BFA stopped\n", 1140 bfad->inst_no, cmnd, cmnd->cmnd[0]); 1141 cmnd->result = ScsiResult(DID_NO_CONNECT, 0); 1142 goto out_fail_cmd; 1143 } 1144 1145 itnim = itnim_data->itnim; 1146 if (!itnim) { 1147 cmnd->result = ScsiResult(DID_IMM_RETRY, 0); 1148 goto out_fail_cmd; 1149 } 1150 1151 hal_io = bfa_ioim_alloc(&bfad->bfa, (struct bfad_ioim_s *) cmnd, 1152 itnim->bfa_itnim, sg_cnt); 1153 if (!hal_io) { 1154 printk(KERN_WARNING "hal_io failure\n"); 1155 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1156 scsi_dma_unmap(cmnd); 1157 return SCSI_MLQUEUE_HOST_BUSY; 1158 } 1159 1160 cmnd->host_scribble = (char *)hal_io; 1161 bfa_trc_fp(bfad, hal_io->iotag); 1162 bfa_ioim_start(hal_io); 1163 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1164 1165 return 0; 1166 1167 out_fail_cmd: 1168 spin_unlock_irqrestore(&bfad->bfad_lock, flags); 1169 scsi_dma_unmap(cmnd); 1170 if (done) 1171 done(cmnd); 1172 1173 return 0; 1174 } 1175 1176 void 1177 bfad_os_rport_online_wait(struct bfad_s *bfad) 1178 { 1179 int i; 1180 int rport_delay = 10; 1181 1182 for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE) 1183 && i < bfa_linkup_delay; i++) 1184 schedule_timeout_uninterruptible(HZ); 1185 1186 if (bfad->bfad_flags & BFAD_PORT_ONLINE) { 1187 rport_delay = rport_delay < bfa_linkup_delay ? 1188 rport_delay : bfa_linkup_delay; 1189 for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE) 1190 && i < rport_delay; i++) 1191 schedule_timeout_uninterruptible(HZ); 1192 1193 if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) 1194 schedule_timeout_uninterruptible(rport_delay * HZ); 1195 } 1196 } 1197 1198 int 1199 bfad_os_get_linkup_delay(struct bfad_s *bfad) 1200 { 1201 1202 u8 nwwns = 0; 1203 wwn_t *wwns; 1204 int ldelay; 1205 1206 /* 1207 * Querying for the boot target port wwns 1208 * -- read from boot information in flash. 1209 * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30 1210 * else => local boot machine set bfa_linkup_delay = 10 1211 */ 1212 1213 bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, &wwns); 1214 1215 if (nwwns > 0) { 1216 /* If boot over SAN; linkup_delay = 30sec */ 1217 ldelay = 30; 1218 } else { 1219 /* If local boot; linkup_delay = 10sec */ 1220 ldelay = 0; 1221 } 1222 1223 return ldelay; 1224 } 1225 1226 1227