diff options
Diffstat (limited to 'drivers/message/fusion/mptfc.c')
| -rw-r--r-- | drivers/message/fusion/mptfc.c | 394 |
1 files changed, 380 insertions, 14 deletions
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 856487741ef4..74714e5bcf03 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
| @@ -169,13 +169,6 @@ static struct fc_function_template mptfc_transport_functions = { | |||
| 169 | 169 | ||
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | /* FIXME! values controlling firmware RESCAN event | ||
| 173 | * need to be set low to allow dev_loss_tmo to | ||
| 174 | * work as expected. Currently, firmware doesn't | ||
| 175 | * notify driver of RESCAN event until some number | ||
| 176 | * of seconds elapse. This value can be set via | ||
| 177 | * lsiutil. | ||
| 178 | */ | ||
| 179 | static void | 172 | static void |
| 180 | mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) | 173 | mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) |
| 181 | { | 174 | { |
| @@ -587,15 +580,266 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
| 587 | #ifdef DMPT_DEBUG_FC | 580 | #ifdef DMPT_DEBUG_FC |
| 588 | if (unlikely(err)) { | 581 | if (unlikely(err)) { |
| 589 | dfcprintk ((MYIOC_s_INFO_FMT | 582 | dfcprintk ((MYIOC_s_INFO_FMT |
| 590 | "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n", | 583 | "mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n", |
| 591 | ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, | 584 | ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name, |
| 592 | ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, | 585 | ((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no, |
| 593 | SCpnt->device->id,SCpnt->device->lun)); | 586 | SCpnt->device->id,SCpnt->device->lun,err)); |
| 594 | } | 587 | } |
| 595 | #endif | 588 | #endif |
| 596 | return err; | 589 | return err; |
| 597 | } | 590 | } |
| 598 | 591 | ||
| 592 | /* | ||
| 593 | * mptfc_GetFcPortPage0 - Fetch FCPort config Page0. | ||
| 594 | * @ioc: Pointer to MPT_ADAPTER structure | ||
| 595 | * @portnum: IOC Port number | ||
| 596 | * | ||
| 597 | * Return: 0 for success | ||
| 598 | * -ENOMEM if no memory available | ||
| 599 | * -EPERM if not allowed due to ISR context | ||
| 600 | * -EAGAIN if no msg frames currently available | ||
| 601 | * -EFAULT for non-successful reply or no reply (timeout) | ||
| 602 | * -EINVAL portnum arg out of range (hardwired to two elements) | ||
| 603 | */ | ||
| 604 | static int | ||
| 605 | mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | ||
| 606 | { | ||
| 607 | ConfigPageHeader_t hdr; | ||
| 608 | CONFIGPARMS cfg; | ||
| 609 | FCPortPage0_t *ppage0_alloc; | ||
| 610 | FCPortPage0_t *pp0dest; | ||
| 611 | dma_addr_t page0_dma; | ||
| 612 | int data_sz; | ||
| 613 | int copy_sz; | ||
| 614 | int rc; | ||
| 615 | int count = 400; | ||
| 616 | |||
| 617 | if (portnum > 1) | ||
| 618 | return -EINVAL; | ||
| 619 | |||
| 620 | /* Get FCPort Page 0 header */ | ||
| 621 | hdr.PageVersion = 0; | ||
| 622 | hdr.PageLength = 0; | ||
| 623 | hdr.PageNumber = 0; | ||
| 624 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | ||
| 625 | cfg.cfghdr.hdr = &hdr; | ||
| 626 | cfg.physAddr = -1; | ||
| 627 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 628 | cfg.dir = 0; | ||
| 629 | cfg.pageAddr = portnum; | ||
| 630 | cfg.timeout = 0; | ||
| 631 | |||
| 632 | if ((rc = mpt_config(ioc, &cfg)) != 0) | ||
| 633 | return rc; | ||
| 634 | |||
| 635 | if (hdr.PageLength == 0) | ||
| 636 | return 0; | ||
| 637 | |||
| 638 | data_sz = hdr.PageLength * 4; | ||
| 639 | rc = -ENOMEM; | ||
| 640 | ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma); | ||
| 641 | if (ppage0_alloc) { | ||
| 642 | |||
| 643 | try_again: | ||
| 644 | memset((u8 *)ppage0_alloc, 0, data_sz); | ||
| 645 | cfg.physAddr = page0_dma; | ||
| 646 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 647 | |||
| 648 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | ||
| 649 | /* save the data */ | ||
| 650 | pp0dest = &ioc->fc_port_page0[portnum]; | ||
| 651 | copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz); | ||
| 652 | memcpy(pp0dest, ppage0_alloc, copy_sz); | ||
| 653 | |||
| 654 | /* | ||
| 655 | * Normalize endianness of structure data, | ||
| 656 | * by byte-swapping all > 1 byte fields! | ||
| 657 | */ | ||
| 658 | pp0dest->Flags = le32_to_cpu(pp0dest->Flags); | ||
| 659 | pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier); | ||
| 660 | pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low); | ||
| 661 | pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High); | ||
| 662 | pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low); | ||
| 663 | pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High); | ||
| 664 | pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass); | ||
| 665 | pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds); | ||
| 666 | pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed); | ||
| 667 | pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize); | ||
| 668 | pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low); | ||
| 669 | pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High); | ||
| 670 | pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low); | ||
| 671 | pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High); | ||
| 672 | pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount); | ||
| 673 | pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators); | ||
| 674 | |||
| 675 | /* | ||
| 676 | * if still doing discovery, | ||
| 677 | * hang loose a while until finished | ||
| 678 | */ | ||
| 679 | if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { | ||
| 680 | if (count-- > 0) { | ||
| 681 | msleep(100); | ||
| 682 | goto try_again; | ||
| 683 | } | ||
| 684 | printk(MYIOC_s_INFO_FMT "Firmware discovery not" | ||
| 685 | " complete.\n", | ||
| 686 | ioc->name); | ||
| 687 | } | ||
| 688 | } | ||
| 689 | |||
| 690 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); | ||
| 691 | } | ||
| 692 | |||
| 693 | return rc; | ||
| 694 | } | ||
| 695 | |||
| 696 | static int | ||
| 697 | mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum) | ||
| 698 | { | ||
| 699 | ConfigPageHeader_t hdr; | ||
| 700 | CONFIGPARMS cfg; | ||
| 701 | int rc; | ||
| 702 | |||
| 703 | if (portnum > 1) | ||
| 704 | return -EINVAL; | ||
| 705 | |||
| 706 | if (!(ioc->fc_data.fc_port_page1[portnum].data)) | ||
| 707 | return -EINVAL; | ||
| 708 | |||
| 709 | /* get fcport page 1 header */ | ||
| 710 | hdr.PageVersion = 0; | ||
| 711 | hdr.PageLength = 0; | ||
| 712 | hdr.PageNumber = 1; | ||
| 713 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | ||
| 714 | cfg.cfghdr.hdr = &hdr; | ||
| 715 | cfg.physAddr = -1; | ||
| 716 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 717 | cfg.dir = 0; | ||
| 718 | cfg.pageAddr = portnum; | ||
| 719 | cfg.timeout = 0; | ||
| 720 | |||
| 721 | if ((rc = mpt_config(ioc, &cfg)) != 0) | ||
| 722 | return rc; | ||
| 723 | |||
| 724 | if (hdr.PageLength == 0) | ||
| 725 | return -ENODEV; | ||
| 726 | |||
| 727 | if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz) | ||
| 728 | return -EINVAL; | ||
| 729 | |||
| 730 | cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma; | ||
| 731 | cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; | ||
| 732 | cfg.dir = 1; | ||
| 733 | |||
| 734 | rc = mpt_config(ioc, &cfg); | ||
| 735 | |||
| 736 | return rc; | ||
| 737 | } | ||
| 738 | |||
| 739 | static int | ||
| 740 | mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum) | ||
| 741 | { | ||
| 742 | ConfigPageHeader_t hdr; | ||
| 743 | CONFIGPARMS cfg; | ||
| 744 | FCPortPage1_t *page1_alloc; | ||
| 745 | dma_addr_t page1_dma; | ||
| 746 | int data_sz; | ||
| 747 | int rc; | ||
| 748 | |||
| 749 | if (portnum > 1) | ||
| 750 | return -EINVAL; | ||
| 751 | |||
| 752 | /* get fcport page 1 header */ | ||
| 753 | hdr.PageVersion = 0; | ||
| 754 | hdr.PageLength = 0; | ||
| 755 | hdr.PageNumber = 1; | ||
| 756 | hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT; | ||
| 757 | cfg.cfghdr.hdr = &hdr; | ||
| 758 | cfg.physAddr = -1; | ||
| 759 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
| 760 | cfg.dir = 0; | ||
| 761 | cfg.pageAddr = portnum; | ||
| 762 | cfg.timeout = 0; | ||
| 763 | |||
| 764 | if ((rc = mpt_config(ioc, &cfg)) != 0) | ||
| 765 | return rc; | ||
| 766 | |||
| 767 | if (hdr.PageLength == 0) | ||
| 768 | return -ENODEV; | ||
| 769 | |||
| 770 | start_over: | ||
| 771 | |||
| 772 | if (ioc->fc_data.fc_port_page1[portnum].data == NULL) { | ||
| 773 | data_sz = hdr.PageLength * 4; | ||
| 774 | if (data_sz < sizeof(FCPortPage1_t)) | ||
| 775 | data_sz = sizeof(FCPortPage1_t); | ||
| 776 | |||
| 777 | page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev, | ||
| 778 | data_sz, | ||
| 779 | &page1_dma); | ||
| 780 | if (!page1_alloc) | ||
| 781 | return -ENOMEM; | ||
| 782 | } | ||
| 783 | else { | ||
| 784 | page1_alloc = ioc->fc_data.fc_port_page1[portnum].data; | ||
| 785 | page1_dma = ioc->fc_data.fc_port_page1[portnum].dma; | ||
| 786 | data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz; | ||
| 787 | if (hdr.PageLength * 4 > data_sz) { | ||
| 788 | ioc->fc_data.fc_port_page1[portnum].data = NULL; | ||
| 789 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) | ||
| 790 | page1_alloc, page1_dma); | ||
| 791 | goto start_over; | ||
| 792 | } | ||
| 793 | } | ||
| 794 | |||
| 795 | memset(page1_alloc,0,data_sz); | ||
| 796 | |||
| 797 | cfg.physAddr = page1_dma; | ||
| 798 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
| 799 | |||
| 800 | if ((rc = mpt_config(ioc, &cfg)) == 0) { | ||
| 801 | ioc->fc_data.fc_port_page1[portnum].data = page1_alloc; | ||
| 802 | ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz; | ||
| 803 | ioc->fc_data.fc_port_page1[portnum].dma = page1_dma; | ||
| 804 | } | ||
| 805 | else { | ||
| 806 | ioc->fc_data.fc_port_page1[portnum].data = NULL; | ||
| 807 | pci_free_consistent(ioc->pcidev, data_sz, (u8 *) | ||
| 808 | page1_alloc, page1_dma); | ||
| 809 | } | ||
| 810 | |||
| 811 | return rc; | ||
| 812 | } | ||
| 813 | |||
| 814 | static void | ||
| 815 | mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc) | ||
| 816 | { | ||
| 817 | int ii; | ||
| 818 | FCPortPage1_t *pp1; | ||
| 819 | |||
| 820 | #define MPTFC_FW_DEVICE_TIMEOUT (1) | ||
| 821 | #define MPTFC_FW_IO_PEND_TIMEOUT (1) | ||
| 822 | #define ON_FLAGS (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY) | ||
| 823 | #define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS) | ||
| 824 | |||
| 825 | for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) { | ||
| 826 | if (mptfc_GetFcPortPage1(ioc, ii) != 0) | ||
| 827 | continue; | ||
| 828 | pp1 = ioc->fc_data.fc_port_page1[ii].data; | ||
| 829 | if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT) | ||
| 830 | && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT) | ||
| 831 | && ((pp1->Flags & ON_FLAGS) == ON_FLAGS) | ||
| 832 | && ((pp1->Flags & OFF_FLAGS) == 0)) | ||
| 833 | continue; | ||
| 834 | pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT; | ||
| 835 | pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT; | ||
| 836 | pp1->Flags &= ~OFF_FLAGS; | ||
| 837 | pp1->Flags |= ON_FLAGS; | ||
| 838 | mptfc_WriteFcPortPage1(ioc, ii); | ||
| 839 | } | ||
| 840 | } | ||
| 841 | |||
| 842 | |||
| 599 | static void | 843 | static void |
| 600 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | 844 | mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) |
| 601 | { | 845 | { |
| @@ -629,6 +873,31 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) | |||
| 629 | } | 873 | } |
| 630 | 874 | ||
| 631 | static void | 875 | static void |
| 876 | mptfc_setup_reset(void *arg) | ||
| 877 | { | ||
| 878 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | ||
| 879 | u64 pn; | ||
| 880 | struct mptfc_rport_info *ri; | ||
| 881 | |||
| 882 | /* reset about to happen, delete (block) all rports */ | ||
| 883 | list_for_each_entry(ri, &ioc->fc_rports, list) { | ||
| 884 | if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { | ||
| 885 | ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED; | ||
| 886 | fc_remote_port_delete(ri->rport); /* won't sleep */ | ||
| 887 | ri->rport = NULL; | ||
| 888 | |||
| 889 | pn = (u64)ri->pg0.WWPN.High << 32 | | ||
| 890 | (u64)ri->pg0.WWPN.Low; | ||
| 891 | dfcprintk ((MYIOC_s_INFO_FMT | ||
| 892 | "mptfc_setup_reset.%d: %llx deleted\n", | ||
| 893 | ioc->name, | ||
| 894 | ioc->sh->host_no, | ||
| 895 | (unsigned long long)pn)); | ||
| 896 | } | ||
| 897 | } | ||
| 898 | } | ||
| 899 | |||
| 900 | static void | ||
| 632 | mptfc_rescan_devices(void *arg) | 901 | mptfc_rescan_devices(void *arg) |
| 633 | { | 902 | { |
| 634 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | 903 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; |
| @@ -651,7 +920,7 @@ mptfc_rescan_devices(void *arg) | |||
| 651 | * will reregister existing rports | 920 | * will reregister existing rports |
| 652 | */ | 921 | */ |
| 653 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | 922 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { |
| 654 | (void) mptbase_GetFcPortPage0(ioc, ii); | 923 | (void) mptfc_GetFcPortPage0(ioc, ii); |
| 655 | mptfc_init_host_attr(ioc,ii); /* refresh */ | 924 | mptfc_init_host_attr(ioc,ii); /* refresh */ |
| 656 | mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); | 925 | mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); |
| 657 | } | 926 | } |
| @@ -753,7 +1022,9 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 753 | goto out_mptfc_probe; | 1022 | goto out_mptfc_probe; |
| 754 | } | 1023 | } |
| 755 | 1024 | ||
| 1025 | spin_lock_init(&ioc->fc_rescan_work_lock); | ||
| 756 | INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); | 1026 | INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc); |
| 1027 | INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc); | ||
| 757 | 1028 | ||
| 758 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 1029 | spin_lock_irqsave(&ioc->FreeQlock, flags); |
| 759 | 1030 | ||
| @@ -889,6 +1160,15 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 889 | goto out_mptfc_probe; | 1160 | goto out_mptfc_probe; |
| 890 | 1161 | ||
| 891 | /* | 1162 | /* |
| 1163 | * Pre-fetch FC port WWN and stuff... | ||
| 1164 | * (FCPortPage0_t stuff) | ||
| 1165 | */ | ||
| 1166 | for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { | ||
| 1167 | (void) mptfc_GetFcPortPage0(ioc, ii); | ||
| 1168 | } | ||
| 1169 | mptfc_SetFcPortPage1_defaults(ioc); | ||
| 1170 | |||
| 1171 | /* | ||
| 892 | * scan for rports - | 1172 | * scan for rports - |
| 893 | * by doing it via the workqueue, some locking is eliminated | 1173 | * by doing it via the workqueue, some locking is eliminated |
| 894 | */ | 1174 | */ |
| @@ -917,6 +1197,81 @@ static struct pci_driver mptfc_driver = { | |||
| 917 | #endif | 1197 | #endif |
| 918 | }; | 1198 | }; |
| 919 | 1199 | ||
| 1200 | static int | ||
| 1201 | mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | ||
| 1202 | { | ||
| 1203 | MPT_SCSI_HOST *hd; | ||
| 1204 | u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; | ||
| 1205 | unsigned long flags; | ||
| 1206 | int rc=1; | ||
| 1207 | |||
| 1208 | devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | ||
| 1209 | ioc->name, event)); | ||
| 1210 | |||
| 1211 | if (ioc->sh == NULL || | ||
| 1212 | ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) | ||
| 1213 | return 1; | ||
| 1214 | |||
| 1215 | switch (event) { | ||
| 1216 | case MPI_EVENT_RESCAN: | ||
| 1217 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 1218 | if (ioc->fc_rescan_work_q) { | ||
| 1219 | if (ioc->fc_rescan_work_count++ == 0) { | ||
| 1220 | queue_work(ioc->fc_rescan_work_q, | ||
| 1221 | &ioc->fc_rescan_work); | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 1225 | break; | ||
| 1226 | default: | ||
| 1227 | rc = mptscsih_event_process(ioc,pEvReply); | ||
| 1228 | break; | ||
| 1229 | } | ||
| 1230 | return rc; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | static int | ||
| 1234 | mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | ||
| 1235 | { | ||
| 1236 | int rc; | ||
| 1237 | unsigned long flags; | ||
| 1238 | |||
| 1239 | rc = mptscsih_ioc_reset(ioc,reset_phase); | ||
| 1240 | if (rc == 0) | ||
| 1241 | return rc; | ||
| 1242 | |||
| 1243 | |||
| 1244 | dtmprintk((KERN_WARNING MYNAM | ||
| 1245 | ": IOC %s_reset routed to FC host driver!\n", | ||
| 1246 | reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | ||
| 1247 | reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); | ||
| 1248 | |||
| 1249 | if (reset_phase == MPT_IOC_SETUP_RESET) { | ||
| 1250 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 1251 | if (ioc->fc_rescan_work_q) { | ||
| 1252 | queue_work(ioc->fc_rescan_work_q, | ||
| 1253 | &ioc->fc_setup_reset_work); | ||
| 1254 | } | ||
| 1255 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | else if (reset_phase == MPT_IOC_PRE_RESET) { | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | else { /* MPT_IOC_POST_RESET */ | ||
| 1262 | mptfc_SetFcPortPage1_defaults(ioc); | ||
| 1263 | spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); | ||
| 1264 | if (ioc->fc_rescan_work_q) { | ||
| 1265 | if (ioc->fc_rescan_work_count++ == 0) { | ||
| 1266 | queue_work(ioc->fc_rescan_work_q, | ||
| 1267 | &ioc->fc_rescan_work); | ||
| 1268 | } | ||
| 1269 | } | ||
| 1270 | spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); | ||
| 1271 | } | ||
| 1272 | return 1; | ||
| 1273 | } | ||
| 1274 | |||
| 920 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1275 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
| 921 | /** | 1276 | /** |
| 922 | * mptfc_init - Register MPT adapter(s) as SCSI host(s) with | 1277 | * mptfc_init - Register MPT adapter(s) as SCSI host(s) with |
| @@ -931,8 +1286,8 @@ mptfc_init(void) | |||
| 931 | 1286 | ||
| 932 | show_mptmod_ver(my_NAME, my_VERSION); | 1287 | show_mptmod_ver(my_NAME, my_VERSION); |
| 933 | 1288 | ||
| 934 | /* sanity check module parameter */ | 1289 | /* sanity check module parameters */ |
| 935 | if (mptfc_dev_loss_tmo == 0) | 1290 | if (mptfc_dev_loss_tmo <= 0) |
| 936 | mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; | 1291 | mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO; |
| 937 | 1292 | ||
| 938 | mptfc_transport_template = | 1293 | mptfc_transport_template = |
| @@ -945,12 +1300,12 @@ mptfc_init(void) | |||
| 945 | mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); | 1300 | mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER); |
| 946 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); | 1301 | mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER); |
| 947 | 1302 | ||
| 948 | if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) { | 1303 | if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) { |
| 949 | devtverboseprintk((KERN_INFO MYNAM | 1304 | devtverboseprintk((KERN_INFO MYNAM |
| 950 | ": Registered for IOC event notifications\n")); | 1305 | ": Registered for IOC event notifications\n")); |
| 951 | } | 1306 | } |
| 952 | 1307 | ||
| 953 | if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) { | 1308 | if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) { |
| 954 | dprintk((KERN_INFO MYNAM | 1309 | dprintk((KERN_INFO MYNAM |
| 955 | ": Registered for IOC reset notifications\n")); | 1310 | ": Registered for IOC reset notifications\n")); |
| 956 | } | 1311 | } |
| @@ -975,6 +1330,7 @@ mptfc_remove(struct pci_dev *pdev) | |||
| 975 | struct mptfc_rport_info *p, *n; | 1330 | struct mptfc_rport_info *p, *n; |
| 976 | struct workqueue_struct *work_q; | 1331 | struct workqueue_struct *work_q; |
| 977 | unsigned long flags; | 1332 | unsigned long flags; |
| 1333 | int ii; | ||
| 978 | 1334 | ||
| 979 | /* destroy workqueue */ | 1335 | /* destroy workqueue */ |
| 980 | if ((work_q=ioc->fc_rescan_work_q)) { | 1336 | if ((work_q=ioc->fc_rescan_work_q)) { |
| @@ -991,6 +1347,16 @@ mptfc_remove(struct pci_dev *pdev) | |||
| 991 | kfree(p); | 1347 | kfree(p); |
| 992 | } | 1348 | } |
| 993 | 1349 | ||
| 1350 | for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) { | ||
| 1351 | if (ioc->fc_data.fc_port_page1[ii].data) { | ||
| 1352 | pci_free_consistent(ioc->pcidev, | ||
| 1353 | ioc->fc_data.fc_port_page1[ii].pg_sz, | ||
| 1354 | (u8 *) ioc->fc_data.fc_port_page1[ii].data, | ||
| 1355 | ioc->fc_data.fc_port_page1[ii].dma); | ||
| 1356 | ioc->fc_data.fc_port_page1[ii].data = NULL; | ||
| 1357 | } | ||
| 1358 | } | ||
| 1359 | |||
| 994 | mptscsih_remove(pdev); | 1360 | mptscsih_remove(pdev); |
| 995 | } | 1361 | } |
| 996 | 1362 | ||
