diff options
Diffstat (limited to 'drivers/message/fusion/mptfc.c')
| -rw-r--r-- | drivers/message/fusion/mptfc.c | 203 | 
1 files changed, 141 insertions, 62 deletions
| diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index b102c7666d0e..c3a3499bce2a 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
| @@ -93,10 +93,11 @@ static int mptfcDoneCtx = -1; | |||
| 93 | static int mptfcTaskCtx = -1; | 93 | static int mptfcTaskCtx = -1; | 
| 94 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ | 94 | static int mptfcInternalCtx = -1; /* Used only for internal commands */ | 
| 95 | 95 | ||
| 96 | int mptfc_slave_alloc(struct scsi_device *device); | 96 | static int mptfc_target_alloc(struct scsi_target *starget); | 
| 97 | static int mptfc_slave_alloc(struct scsi_device *sdev); | ||
| 97 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, | 98 | static int mptfc_qcmd(struct scsi_cmnd *SCpnt, | 
| 98 | void (*done)(struct scsi_cmnd *)); | 99 | void (*done)(struct scsi_cmnd *)); | 
| 99 | 100 | static void mptfc_target_destroy(struct scsi_target *starget); | |
| 100 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); | 101 | static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); | 
| 101 | static void __devexit mptfc_remove(struct pci_dev *pdev); | 102 | static void __devexit mptfc_remove(struct pci_dev *pdev); | 
| 102 | 103 | ||
| @@ -107,10 +108,10 @@ static struct scsi_host_template mptfc_driver_template = { | |||
| 107 | .name = "MPT FC Host", | 108 | .name = "MPT FC Host", | 
| 108 | .info = mptscsih_info, | 109 | .info = mptscsih_info, | 
| 109 | .queuecommand = mptfc_qcmd, | 110 | .queuecommand = mptfc_qcmd, | 
| 110 | .target_alloc = mptscsih_target_alloc, | 111 | .target_alloc = mptfc_target_alloc, | 
| 111 | .slave_alloc = mptfc_slave_alloc, | 112 | .slave_alloc = mptfc_slave_alloc, | 
| 112 | .slave_configure = mptscsih_slave_configure, | 113 | .slave_configure = mptscsih_slave_configure, | 
| 113 | .target_destroy = mptscsih_target_destroy, | 114 | .target_destroy = mptfc_target_destroy, | 
| 114 | .slave_destroy = mptscsih_slave_destroy, | 115 | .slave_destroy = mptscsih_slave_destroy, | 
| 115 | .change_queue_depth = mptscsih_change_queue_depth, | 116 | .change_queue_depth = mptscsih_change_queue_depth, | 
| 116 | .eh_abort_handler = mptscsih_abort, | 117 | .eh_abort_handler = mptscsih_abort, | 
| @@ -348,14 +349,33 @@ mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid) | |||
| 348 | } | 349 | } | 
| 349 | 350 | ||
| 350 | static void | 351 | static void | 
| 352 | mptfc_remap_sdev(struct scsi_device *sdev, void *arg) | ||
| 353 | { | ||
| 354 | VirtDevice *vdev; | ||
| 355 | VirtTarget *vtarget; | ||
| 356 | struct scsi_target *starget; | ||
| 357 | |||
| 358 | starget = scsi_target(sdev); | ||
| 359 | if (starget->hostdata == arg) { | ||
| 360 | vtarget = arg; | ||
| 361 | vdev = sdev->hostdata; | ||
| 362 | if (vdev) { | ||
| 363 | vdev->bus_id = vtarget->bus_id; | ||
| 364 | vdev->target_id = vtarget->target_id; | ||
| 365 | } | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | static void | ||
| 351 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | 370 | mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | 
| 352 | { | 371 | { | 
| 353 | struct fc_rport_identifiers rport_ids; | 372 | struct fc_rport_identifiers rport_ids; | 
| 354 | struct fc_rport *rport; | 373 | struct fc_rport *rport; | 
| 355 | struct mptfc_rport_info *ri; | 374 | struct mptfc_rport_info *ri; | 
| 356 | int match = 0; | 375 | int new_ri = 1; | 
| 357 | u64 port_name; | 376 | u64 pn; | 
| 358 | unsigned long flags; | 377 | unsigned long flags; | 
| 378 | VirtTarget *vtarget; | ||
| 359 | 379 | ||
| 360 | if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) | 380 | if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0) | 
| 361 | return; | 381 | return; | 
| @@ -363,14 +383,14 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | |||
| 363 | /* scan list looking for a match */ | 383 | /* scan list looking for a match */ | 
| 364 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | 384 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | 
| 365 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 385 | list_for_each_entry(ri, &ioc->fc_rports, list) { | 
| 366 | port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | 386 | pn = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low; | 
| 367 | if (port_name == rport_ids.port_name) { /* match */ | 387 | if (pn == rport_ids.port_name) { /* match */ | 
| 368 | list_move_tail(&ri->list, &ioc->fc_rports); | 388 | list_move_tail(&ri->list, &ioc->fc_rports); | 
| 369 | match = 1; | 389 | new_ri = 0; | 
| 370 | break; | 390 | break; | 
| 371 | } | 391 | } | 
| 372 | } | 392 | } | 
| 373 | if (!match) { /* allocate one */ | 393 | if (new_ri) { /* allocate one */ | 
| 374 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | 394 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | 
| 375 | ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); | 395 | ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL); | 
| 376 | if (!ri) | 396 | if (!ri) | 
| @@ -382,40 +402,43 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | |||
| 382 | ri->pg0 = *pg0; /* add/update pg0 data */ | 402 | ri->pg0 = *pg0; /* add/update pg0 data */ | 
| 383 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; | 403 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING; | 
| 384 | 404 | ||
| 405 | /* MPT_RPORT_INFO_FLAGS_REGISTERED - rport not previously deleted */ | ||
| 385 | if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { | 406 | if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) { | 
| 386 | ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; | 407 | ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED; | 
| 387 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | 408 | spin_unlock_irqrestore(&ioc->fc_rport_lock, flags); | 
| 388 | rport = fc_remote_port_add(ioc->sh,channel, &rport_ids); | 409 | rport = fc_remote_port_add(ioc->sh, channel, &rport_ids); | 
| 389 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | 410 | spin_lock_irqsave(&ioc->fc_rport_lock, flags); | 
| 390 | if (rport) { | 411 | if (rport) { | 
| 391 | if (*((struct mptfc_rport_info **)rport->dd_data) != ri) { | 412 | ri->rport = rport; | 
| 392 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; | 413 | if (new_ri) /* may have been reset by user */ | 
| 393 | ri->vdev = NULL; | 414 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | 
| 394 | ri->rport = rport; | 415 | *((struct mptfc_rport_info **)rport->dd_data) = ri; | 
| 395 | *((struct mptfc_rport_info **)rport->dd_data) = ri; | ||
| 396 | } | ||
| 397 | rport->dev_loss_tmo = mptfc_dev_loss_tmo; | ||
| 398 | /* | 416 | /* | 
| 399 | * if already mapped, remap here. If not mapped, | 417 | * if already mapped, remap here. If not mapped, | 
| 400 | * slave_alloc will allocate vdev and map | 418 | * target_alloc will allocate vtarget and map, | 
| 419 | * slave_alloc will fill in vdev from vtarget. | ||
| 401 | */ | 420 | */ | 
| 402 | if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) { | 421 | if (ri->starget) { | 
| 403 | ri->vdev->target_id = ri->pg0.CurrentTargetID; | 422 | vtarget = ri->starget->hostdata; | 
| 404 | ri->vdev->bus_id = ri->pg0.CurrentBus; | 423 | if (vtarget) { | 
| 405 | ri->vdev->vtarget->target_id = ri->vdev->target_id; | 424 | vtarget->target_id = pg0->CurrentTargetID; | 
| 406 | ri->vdev->vtarget->bus_id = ri->vdev->bus_id; | 425 | vtarget->bus_id = pg0->CurrentBus; | 
| 426 | starget_for_each_device(ri->starget, | ||
| 427 | vtarget,mptfc_remap_sdev); | ||
| 428 | } | ||
| 429 | ri->remap_needed = 0; | ||
| 407 | } | 430 | } | 
| 408 | #ifdef MPT_DEBUG | 431 | dfcprintk ((MYIOC_s_INFO_FMT | 
| 409 | printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " | 432 | "mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, " | 
| 410 | "rport tid %d, tmo %d\n", | 433 | "rport tid %d, tmo %d\n", | 
| 411 | ioc->sh->host_no, | 434 | ioc->name, | 
| 435 | oc->sh->host_no, | ||
| 412 | pg0->PortIdentifier, | 436 | pg0->PortIdentifier, | 
| 413 | pg0->WWNN, | 437 | pg0->WWNN, | 
| 414 | pg0->WWPN, | 438 | pg0->WWPN, | 
| 415 | pg0->CurrentTargetID, | 439 | pg0->CurrentTargetID, | 
| 416 | ri->rport->scsi_target_id, | 440 | ri->rport->scsi_target_id, | 
| 417 | ri->rport->dev_loss_tmo); | 441 | ri->rport->dev_loss_tmo)); | 
| 418 | #endif | ||
| 419 | } else { | 442 | } else { | 
| 420 | list_del(&ri->list); | 443 | list_del(&ri->list); | 
| 421 | kfree(ri); | 444 | kfree(ri); | 
| @@ -427,6 +450,65 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) | |||
| 427 | } | 450 | } | 
| 428 | 451 | ||
| 429 | /* | 452 | /* | 
| 453 | * OS entry point to allow for host driver to free allocated memory | ||
| 454 | * Called if no device present or device being unloaded | ||
| 455 | */ | ||
| 456 | static void | ||
| 457 | mptfc_target_destroy(struct scsi_target *starget) | ||
| 458 | { | ||
| 459 | struct fc_rport *rport; | ||
| 460 | struct mptfc_rport_info *ri; | ||
| 461 | |||
| 462 | rport = starget_to_rport(starget); | ||
| 463 | if (rport) { | ||
| 464 | ri = *((struct mptfc_rport_info **)rport->dd_data); | ||
| 465 | if (ri) /* better be! */ | ||
| 466 | ri->starget = NULL; | ||
| 467 | } | ||
| 468 | if (starget->hostdata) | ||
| 469 | kfree(starget->hostdata); | ||
| 470 | starget->hostdata = NULL; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | ||
| 474 | * OS entry point to allow host driver to alloc memory | ||
| 475 | * for each scsi target. Called once per device the bus scan. | ||
| 476 | * Return non-zero if allocation fails. | ||
| 477 | */ | ||
| 478 | static int | ||
| 479 | mptfc_target_alloc(struct scsi_target *starget) | ||
| 480 | { | ||
| 481 | VirtTarget *vtarget; | ||
| 482 | struct fc_rport *rport; | ||
| 483 | struct mptfc_rport_info *ri; | ||
| 484 | int rc; | ||
| 485 | |||
| 486 | vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); | ||
| 487 | if (!vtarget) | ||
| 488 | return -ENOMEM; | ||
| 489 | starget->hostdata = vtarget; | ||
| 490 | |||
| 491 | rc = -ENODEV; | ||
| 492 | rport = starget_to_rport(starget); | ||
| 493 | if (rport) { | ||
| 494 | ri = *((struct mptfc_rport_info **)rport->dd_data); | ||
| 495 | if (ri) { /* better be! */ | ||
| 496 | vtarget->target_id = ri->pg0.CurrentTargetID; | ||
| 497 | vtarget->bus_id = ri->pg0.CurrentBus; | ||
| 498 | ri->starget = starget; | ||
| 499 | ri->remap_needed = 0; | ||
| 500 | rc = 0; | ||
| 501 | } | ||
| 502 | } | ||
| 503 | if (rc != 0) { | ||
| 504 | kfree(vtarget); | ||
| 505 | starget->hostdata = NULL; | ||
| 506 | } | ||
| 507 | |||
| 508 | return rc; | ||
| 509 | } | ||
| 510 | |||
| 511 | /* | ||
| 430 | * OS entry point to allow host driver to alloc memory | 512 | * OS entry point to allow host driver to alloc memory | 
| 431 | * for each scsi device. Called once per device the bus scan. | 513 | * for each scsi device. Called once per device the bus scan. | 
| 432 | * Return non-zero if allocation fails. | 514 | * Return non-zero if allocation fails. | 
| @@ -440,7 +522,6 @@ mptfc_slave_alloc(struct scsi_device *sdev) | |||
| 440 | VirtDevice *vdev; | 522 | VirtDevice *vdev; | 
| 441 | struct scsi_target *starget; | 523 | struct scsi_target *starget; | 
| 442 | struct fc_rport *rport; | 524 | struct fc_rport *rport; | 
| 443 | struct mptfc_rport_info *ri; | ||
| 444 | unsigned long flags; | 525 | unsigned long flags; | 
| 445 | 526 | ||
| 446 | 527 | ||
| @@ -451,55 +532,44 @@ mptfc_slave_alloc(struct scsi_device *sdev) | |||
| 451 | 532 | ||
| 452 | hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | 533 | hd = (MPT_SCSI_HOST *)sdev->host->hostdata; | 
| 453 | 534 | ||
| 454 | vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); | 535 | vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); | 
| 455 | if (!vdev) { | 536 | if (!vdev) { | 
| 456 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | 537 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | 
| 457 | hd->ioc->name, sizeof(VirtDevice)); | 538 | hd->ioc->name, sizeof(VirtDevice)); | 
| 458 | return -ENOMEM; | 539 | return -ENOMEM; | 
| 459 | } | 540 | } | 
| 460 | memset(vdev, 0, sizeof(VirtDevice)); | ||
| 461 | 541 | ||
| 462 | spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); | 542 | spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags); | 
| 463 | 543 | ||
| 464 | if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) { | ||
| 465 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | ||
| 466 | kfree(vdev); | ||
| 467 | return -ENODEV; | ||
| 468 | } | ||
| 469 | |||
| 470 | sdev->hostdata = vdev; | 544 | sdev->hostdata = vdev; | 
| 471 | starget = scsi_target(sdev); | 545 | starget = scsi_target(sdev); | 
| 472 | vtarget = starget->hostdata; | 546 | vtarget = starget->hostdata; | 
| 547 | |||
| 473 | if (vtarget->num_luns == 0) { | 548 | if (vtarget->num_luns == 0) { | 
| 549 | vtarget->ioc_id = hd->ioc->id; | ||
| 474 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | | 550 | vtarget->tflags = MPT_TARGET_FLAGS_Q_YES | | 
| 475 | MPT_TARGET_FLAGS_VALID_INQUIRY; | 551 | MPT_TARGET_FLAGS_VALID_INQUIRY; | 
| 476 | hd->Targets[sdev->id] = vtarget; | 552 | hd->Targets[sdev->id] = vtarget; | 
| 477 | } | 553 | } | 
| 478 | 554 | ||
| 479 | vtarget->target_id = vdev->target_id; | ||
| 480 | vtarget->bus_id = vdev->bus_id; | ||
| 481 | |||
| 482 | vdev->vtarget = vtarget; | 555 | vdev->vtarget = vtarget; | 
| 483 | vdev->ioc_id = hd->ioc->id; | 556 | vdev->ioc_id = hd->ioc->id; | 
| 484 | vdev->lun = sdev->lun; | 557 | vdev->lun = sdev->lun; | 
| 485 | vdev->target_id = ri->pg0.CurrentTargetID; | 558 | vdev->target_id = vtarget->target_id; | 
| 486 | vdev->bus_id = ri->pg0.CurrentBus; | 559 | vdev->bus_id = vtarget->bus_id; | 
| 487 | |||
| 488 | ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV; | ||
| 489 | ri->vdev = vdev; | ||
| 490 | 560 | ||
| 491 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | 561 | spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags); | 
| 492 | 562 | ||
| 493 | vtarget->num_luns++; | 563 | vtarget->num_luns++; | 
| 494 | 564 | ||
| 495 | #ifdef MPT_DEBUG | 565 | dfcprintk ((MYIOC_s_INFO_FMT | 
| 496 | printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " | 566 | "mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, " | 
| 497 | "CurrentTargetID %d, %x %llx %llx\n", | 567 | "CurrentTargetID %d, %x %llx %llx\n", | 
| 498 | sdev->host->host_no, | 568 | ioc->name, | 
| 499 | vtarget->num_luns, | 569 | sdev->host->host_no, | 
| 500 | sdev->id, ri->pg0.CurrentTargetID, | 570 | vtarget->num_luns, | 
| 501 | ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN); | 571 | sdev->id, ri->pg0.CurrentTargetID, | 
| 502 | #endif | 572 | ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN)); | 
| 503 | 573 | ||
| 504 | return 0; | 574 | return 0; | 
| 505 | } | 575 | } | 
| @@ -507,6 +577,7 @@ mptfc_slave_alloc(struct scsi_device *sdev) | |||
| 507 | static int | 577 | static int | 
| 508 | mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | 578 | mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | 
| 509 | { | 579 | { | 
| 580 | struct mptfc_rport_info *ri; | ||
| 510 | struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); | 581 | struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); | 
| 511 | int err; | 582 | int err; | 
| 512 | 583 | ||
| @@ -516,6 +587,10 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 516 | done(SCpnt); | 587 | done(SCpnt); | 
| 517 | return 0; | 588 | return 0; | 
| 518 | } | 589 | } | 
| 590 | ri = *((struct mptfc_rport_info **)rport->dd_data); | ||
| 591 | if (unlikely(ri->remap_needed)) | ||
| 592 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 593 | |||
| 519 | return mptscsih_qcmd(SCpnt,done); | 594 | return mptscsih_qcmd(SCpnt,done); | 
| 520 | } | 595 | } | 
| 521 | 596 | ||
| @@ -591,16 +666,20 @@ mptfc_rescan_devices(void *arg) | |||
| 591 | 666 | ||
| 592 | ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| | 667 | ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| | 
| 593 | MPT_RPORT_INFO_FLAGS_MISSING); | 668 | MPT_RPORT_INFO_FLAGS_MISSING); | 
| 669 | ri->remap_needed = 1; | ||
| 594 | fc_remote_port_delete(ri->rport); | 670 | fc_remote_port_delete(ri->rport); | 
| 595 | /* | 671 | /* | 
| 596 | * remote port not really deleted 'cause | 672 | * remote port not really deleted 'cause | 
| 597 | * binding is by WWPN and driver only | 673 | * binding is by WWPN and driver only | 
| 598 | * registers FCP_TARGETs | 674 | * registers FCP_TARGETs but cannot trust | 
| 675 | * data structures. | ||
| 599 | */ | 676 | */ | 
| 600 | #ifdef MPT_DEBUG | 677 | ri->rport = NULL; | 
| 601 | printk ("mptfc_rescan.%d: %llx deleted\n", | 678 | dfcprintk ((MYIOC_s_INFO_FMT | 
| 602 | ioc->sh->host_no, ri->pg0.WWPN); | 679 | "mptfc_rescan.%d: %llx deleted\n", | 
| 603 | #endif | 680 | ioc->name, | 
| 681 | ioc->sh->host_no, | ||
| 682 | ri->pg0.WWPN)); | ||
| 604 | } | 683 | } | 
| 605 | } | 684 | } | 
| 606 | spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); | 685 | spin_unlock_irqrestore(&ioc->fc_rport_lock,flags); | 
| @@ -872,9 +951,8 @@ mptfc_init(void) | |||
| 872 | } | 951 | } | 
| 873 | 952 | ||
| 874 | error = pci_register_driver(&mptfc_driver); | 953 | error = pci_register_driver(&mptfc_driver); | 
| 875 | if (error) { | 954 | if (error) | 
| 876 | fc_release_transport(mptfc_transport_template); | 955 | fc_release_transport(mptfc_transport_template); | 
| 877 | } | ||
| 878 | 956 | ||
| 879 | return error; | 957 | return error; | 
| 880 | } | 958 | } | 
| @@ -885,7 +963,8 @@ mptfc_init(void) | |||
| 885 | * @pdev: Pointer to pci_dev structure | 963 | * @pdev: Pointer to pci_dev structure | 
| 886 | * | 964 | * | 
| 887 | */ | 965 | */ | 
| 888 | static void __devexit mptfc_remove(struct pci_dev *pdev) | 966 | static void __devexit | 
| 967 | mptfc_remove(struct pci_dev *pdev) | ||
| 889 | { | 968 | { | 
| 890 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 969 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | 
| 891 | struct mptfc_rport_info *p, *n; | 970 | struct mptfc_rport_info *p, *n; | 
