diff options
author | Bryan O'Sullivan <bos@pathscale.com> | 2006-09-28 12:00:16 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-28 14:16:59 -0400 |
commit | 7227aac47deac20daa0073a1ebbf608b4f2f8d94 (patch) | |
tree | 63cd3ed2aefe30012ea538515b1dd8bbdc908989 /drivers | |
parent | 957670a57eb63b932b09b444ad44192ad9ee9382 (diff) |
IB/ipath: Clean up module exit code
Signed-off-by: Bryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 289 |
1 files changed, 128 insertions, 161 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 68fc9b5a4ad8..12cefa658f3b 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -517,33 +517,146 @@ bail: | |||
517 | return ret; | 517 | return ret; |
518 | } | 518 | } |
519 | 519 | ||
520 | static void __devexit ipath_remove_one(struct pci_dev *pdev) | 520 | static void __devexit cleanup_device(struct ipath_devdata *dd) |
521 | { | 521 | { |
522 | struct ipath_devdata *dd; | 522 | int port; |
523 | 523 | ||
524 | ipath_cdbg(VERBOSE, "removing, pdev=%p\n", pdev); | 524 | ipath_shutdown_device(dd); |
525 | if (!pdev) | ||
526 | return; | ||
527 | 525 | ||
528 | dd = pci_get_drvdata(pdev); | 526 | if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) { |
527 | /* can't do anything more with chip; needs re-init */ | ||
528 | *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT; | ||
529 | if (dd->ipath_kregbase) { | ||
530 | /* | ||
531 | * if we haven't already cleaned up before these are | ||
532 | * to ensure any register reads/writes "fail" until | ||
533 | * re-init | ||
534 | */ | ||
535 | dd->ipath_kregbase = NULL; | ||
536 | dd->ipath_uregbase = 0; | ||
537 | dd->ipath_sregbase = 0; | ||
538 | dd->ipath_cregbase = 0; | ||
539 | dd->ipath_kregsize = 0; | ||
540 | } | ||
541 | ipath_disable_wc(dd); | ||
542 | } | ||
529 | 543 | ||
530 | if (dd->verbs_dev) { | 544 | if (dd->ipath_pioavailregs_dma) { |
531 | ipath_unregister_ib_device(dd->verbs_dev); | 545 | dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, |
532 | dd->verbs_dev = NULL; | 546 | (void *) dd->ipath_pioavailregs_dma, |
547 | dd->ipath_pioavailregs_phys); | ||
548 | dd->ipath_pioavailregs_dma = NULL; | ||
549 | } | ||
550 | if (dd->ipath_dummy_hdrq) { | ||
551 | dma_free_coherent(&dd->pcidev->dev, | ||
552 | dd->ipath_pd[0]->port_rcvhdrq_size, | ||
553 | dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys); | ||
554 | dd->ipath_dummy_hdrq = NULL; | ||
555 | } | ||
556 | |||
557 | if (dd->ipath_pageshadow) { | ||
558 | struct page **tmpp = dd->ipath_pageshadow; | ||
559 | dma_addr_t *tmpd = dd->ipath_physshadow; | ||
560 | int i, cnt = 0; | ||
561 | |||
562 | ipath_cdbg(VERBOSE, "Unlocking any expTID pages still " | ||
563 | "locked\n"); | ||
564 | for (port = 0; port < dd->ipath_cfgports; port++) { | ||
565 | int port_tidbase = port * dd->ipath_rcvtidcnt; | ||
566 | int maxtid = port_tidbase + dd->ipath_rcvtidcnt; | ||
567 | for (i = port_tidbase; i < maxtid; i++) { | ||
568 | if (!tmpp[i]) | ||
569 | continue; | ||
570 | pci_unmap_page(dd->pcidev, tmpd[i], | ||
571 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
572 | ipath_release_user_pages(&tmpp[i], 1); | ||
573 | tmpp[i] = NULL; | ||
574 | cnt++; | ||
575 | } | ||
576 | } | ||
577 | if (cnt) { | ||
578 | ipath_stats.sps_pageunlocks += cnt; | ||
579 | ipath_cdbg(VERBOSE, "There were still %u expTID " | ||
580 | "entries locked\n", cnt); | ||
581 | } | ||
582 | if (ipath_stats.sps_pagelocks || | ||
583 | ipath_stats.sps_pageunlocks) | ||
584 | ipath_cdbg(VERBOSE, "%llu pages locked, %llu " | ||
585 | "unlocked via ipath_m{un}lock\n", | ||
586 | (unsigned long long) | ||
587 | ipath_stats.sps_pagelocks, | ||
588 | (unsigned long long) | ||
589 | ipath_stats.sps_pageunlocks); | ||
590 | |||
591 | ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n", | ||
592 | dd->ipath_pageshadow); | ||
593 | vfree(dd->ipath_pageshadow); | ||
594 | dd->ipath_pageshadow = NULL; | ||
533 | } | 595 | } |
534 | 596 | ||
597 | /* | ||
598 | * free any resources still in use (usually just kernel ports) | ||
599 | * at unload; we do for portcnt, not cfgports, because cfgports | ||
600 | * could have changed while we were loaded. | ||
601 | */ | ||
602 | for (port = 0; port < dd->ipath_portcnt; port++) { | ||
603 | struct ipath_portdata *pd = dd->ipath_pd[port]; | ||
604 | dd->ipath_pd[port] = NULL; | ||
605 | ipath_free_pddata(dd, pd); | ||
606 | } | ||
607 | kfree(dd->ipath_pd); | ||
608 | /* | ||
609 | * debuggability, in case some cleanup path tries to use it | ||
610 | * after this | ||
611 | */ | ||
612 | dd->ipath_pd = NULL; | ||
613 | } | ||
614 | |||
615 | static void __devexit ipath_remove_one(struct pci_dev *pdev) | ||
616 | { | ||
617 | struct ipath_devdata *dd = pci_get_drvdata(pdev); | ||
618 | |||
619 | ipath_cdbg(VERBOSE, "removing, pdev=%p, dd=%p\n", pdev, dd); | ||
620 | |||
621 | if (dd->verbs_dev) | ||
622 | ipath_unregister_ib_device(dd->verbs_dev); | ||
623 | |||
535 | ipath_diag_remove(dd); | 624 | ipath_diag_remove(dd); |
536 | ipath_user_remove(dd); | 625 | ipath_user_remove(dd); |
537 | ipathfs_remove_device(dd); | 626 | ipathfs_remove_device(dd); |
538 | ipath_device_remove_group(&pdev->dev, dd); | 627 | ipath_device_remove_group(&pdev->dev, dd); |
628 | |||
539 | ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " | 629 | ipath_cdbg(VERBOSE, "Releasing pci memory regions, dd %p, " |
540 | "unit %u\n", dd, (u32) dd->ipath_unit); | 630 | "unit %u\n", dd, (u32) dd->ipath_unit); |
541 | if (dd->ipath_kregbase) { | 631 | |
542 | ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n", | 632 | cleanup_device(dd); |
543 | dd->ipath_kregbase); | 633 | |
544 | iounmap((volatile void __iomem *) dd->ipath_kregbase); | 634 | /* |
545 | dd->ipath_kregbase = NULL; | 635 | * turn off rcv, send, and interrupts for all ports, all drivers |
546 | } | 636 | * should also hard reset the chip here? |
637 | * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs | ||
638 | * for all versions of the driver, if they were allocated | ||
639 | */ | ||
640 | if (pdev->irq) { | ||
641 | ipath_cdbg(VERBOSE, | ||
642 | "unit %u free_irq of irq %x\n", | ||
643 | dd->ipath_unit, pdev->irq); | ||
644 | free_irq(pdev->irq, dd); | ||
645 | } else | ||
646 | ipath_dbg("irq is 0, not doing free_irq " | ||
647 | "for unit %u\n", dd->ipath_unit); | ||
648 | /* | ||
649 | * we check for NULL here, because it's outside | ||
650 | * the kregbase check, and we need to call it | ||
651 | * after the free_irq. Thus it's possible that | ||
652 | * the function pointers were never initialized. | ||
653 | */ | ||
654 | if (dd->ipath_f_cleanup) | ||
655 | /* clean up chip-specific stuff */ | ||
656 | dd->ipath_f_cleanup(dd); | ||
657 | |||
658 | ipath_cdbg(VERBOSE, "Unmapping kregbase %p\n", dd->ipath_kregbase); | ||
659 | iounmap((volatile void __iomem *) dd->ipath_kregbase); | ||
547 | pci_release_regions(pdev); | 660 | pci_release_regions(pdev); |
548 | ipath_cdbg(VERBOSE, "calling pci_disable_device\n"); | 661 | ipath_cdbg(VERBOSE, "calling pci_disable_device\n"); |
549 | pci_disable_device(pdev); | 662 | pci_disable_device(pdev); |
@@ -1917,158 +2030,12 @@ bail: | |||
1917 | return ret; | 2030 | return ret; |
1918 | } | 2031 | } |
1919 | 2032 | ||
1920 | static void cleanup_device(struct ipath_devdata *dd) | ||
1921 | { | ||
1922 | int port; | ||
1923 | |||
1924 | ipath_shutdown_device(dd); | ||
1925 | |||
1926 | if (*dd->ipath_statusp & IPATH_STATUS_CHIP_PRESENT) { | ||
1927 | /* can't do anything more with chip; needs re-init */ | ||
1928 | *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT; | ||
1929 | if (dd->ipath_kregbase) { | ||
1930 | /* | ||
1931 | * if we haven't already cleaned up before these are | ||
1932 | * to ensure any register reads/writes "fail" until | ||
1933 | * re-init | ||
1934 | */ | ||
1935 | dd->ipath_kregbase = NULL; | ||
1936 | dd->ipath_uregbase = 0; | ||
1937 | dd->ipath_sregbase = 0; | ||
1938 | dd->ipath_cregbase = 0; | ||
1939 | dd->ipath_kregsize = 0; | ||
1940 | } | ||
1941 | ipath_disable_wc(dd); | ||
1942 | } | ||
1943 | |||
1944 | if (dd->ipath_pioavailregs_dma) { | ||
1945 | dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE, | ||
1946 | (void *) dd->ipath_pioavailregs_dma, | ||
1947 | dd->ipath_pioavailregs_phys); | ||
1948 | dd->ipath_pioavailregs_dma = NULL; | ||
1949 | } | ||
1950 | if (dd->ipath_dummy_hdrq) { | ||
1951 | dma_free_coherent(&dd->pcidev->dev, | ||
1952 | dd->ipath_pd[0]->port_rcvhdrq_size, | ||
1953 | dd->ipath_dummy_hdrq, dd->ipath_dummy_hdrq_phys); | ||
1954 | dd->ipath_dummy_hdrq = NULL; | ||
1955 | } | ||
1956 | |||
1957 | if (dd->ipath_pageshadow) { | ||
1958 | struct page **tmpp = dd->ipath_pageshadow; | ||
1959 | dma_addr_t *tmpd = dd->ipath_physshadow; | ||
1960 | int i, cnt = 0; | ||
1961 | |||
1962 | ipath_cdbg(VERBOSE, "Unlocking any expTID pages still " | ||
1963 | "locked\n"); | ||
1964 | for (port = 0; port < dd->ipath_cfgports; port++) { | ||
1965 | int port_tidbase = port * dd->ipath_rcvtidcnt; | ||
1966 | int maxtid = port_tidbase + dd->ipath_rcvtidcnt; | ||
1967 | for (i = port_tidbase; i < maxtid; i++) { | ||
1968 | if (!tmpp[i]) | ||
1969 | continue; | ||
1970 | pci_unmap_page(dd->pcidev, tmpd[i], | ||
1971 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | ||
1972 | ipath_release_user_pages(&tmpp[i], 1); | ||
1973 | tmpp[i] = NULL; | ||
1974 | cnt++; | ||
1975 | } | ||
1976 | } | ||
1977 | if (cnt) { | ||
1978 | ipath_stats.sps_pageunlocks += cnt; | ||
1979 | ipath_cdbg(VERBOSE, "There were still %u expTID " | ||
1980 | "entries locked\n", cnt); | ||
1981 | } | ||
1982 | if (ipath_stats.sps_pagelocks || | ||
1983 | ipath_stats.sps_pageunlocks) | ||
1984 | ipath_cdbg(VERBOSE, "%llu pages locked, %llu " | ||
1985 | "unlocked via ipath_m{un}lock\n", | ||
1986 | (unsigned long long) | ||
1987 | ipath_stats.sps_pagelocks, | ||
1988 | (unsigned long long) | ||
1989 | ipath_stats.sps_pageunlocks); | ||
1990 | |||
1991 | ipath_cdbg(VERBOSE, "Free shadow page tid array at %p\n", | ||
1992 | dd->ipath_pageshadow); | ||
1993 | vfree(dd->ipath_pageshadow); | ||
1994 | dd->ipath_pageshadow = NULL; | ||
1995 | } | ||
1996 | |||
1997 | /* | ||
1998 | * free any resources still in use (usually just kernel ports) | ||
1999 | * at unload; we do for portcnt, not cfgports, because cfgports | ||
2000 | * could have changed while we were loaded. | ||
2001 | */ | ||
2002 | for (port = 0; port < dd->ipath_portcnt; port++) { | ||
2003 | struct ipath_portdata *pd = dd->ipath_pd[port]; | ||
2004 | dd->ipath_pd[port] = NULL; | ||
2005 | ipath_free_pddata(dd, pd); | ||
2006 | } | ||
2007 | kfree(dd->ipath_pd); | ||
2008 | /* | ||
2009 | * debuggability, in case some cleanup path tries to use it | ||
2010 | * after this | ||
2011 | */ | ||
2012 | dd->ipath_pd = NULL; | ||
2013 | } | ||
2014 | |||
2015 | static void __exit infinipath_cleanup(void) | 2033 | static void __exit infinipath_cleanup(void) |
2016 | { | 2034 | { |
2017 | struct ipath_devdata *dd, *tmp; | ||
2018 | unsigned long flags; | ||
2019 | |||
2020 | ipath_diagpkt_remove(); | ||
2021 | |||
2022 | ipath_exit_ipathfs(); | 2035 | ipath_exit_ipathfs(); |
2023 | 2036 | ||
2024 | ipath_driver_remove_group(&ipath_driver.driver); | 2037 | ipath_driver_remove_group(&ipath_driver.driver); |
2025 | 2038 | ||
2026 | spin_lock_irqsave(&ipath_devs_lock, flags); | ||
2027 | |||
2028 | /* | ||
2029 | * turn off rcv, send, and interrupts for all ports, all drivers | ||
2030 | * should also hard reset the chip here? | ||
2031 | * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs | ||
2032 | * for all versions of the driver, if they were allocated | ||
2033 | */ | ||
2034 | list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { | ||
2035 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | ||
2036 | |||
2037 | if (dd->verbs_dev) { | ||
2038 | ipath_unregister_ib_device(dd->verbs_dev); | ||
2039 | dd->verbs_dev = NULL; | ||
2040 | } | ||
2041 | |||
2042 | if (dd->ipath_kregbase) | ||
2043 | cleanup_device(dd); | ||
2044 | |||
2045 | if (dd->pcidev) { | ||
2046 | if (dd->pcidev->irq) { | ||
2047 | ipath_cdbg(VERBOSE, | ||
2048 | "unit %u free_irq of irq %x\n", | ||
2049 | dd->ipath_unit, dd->pcidev->irq); | ||
2050 | free_irq(dd->pcidev->irq, dd); | ||
2051 | } else | ||
2052 | ipath_dbg("irq is 0, not doing free_irq " | ||
2053 | "for unit %u\n", dd->ipath_unit); | ||
2054 | |||
2055 | /* | ||
2056 | * we check for NULL here, because it's outside | ||
2057 | * the kregbase check, and we need to call it | ||
2058 | * after the free_irq. Thus it's possible that | ||
2059 | * the function pointers were never initialized. | ||
2060 | */ | ||
2061 | if (dd->ipath_f_cleanup) | ||
2062 | /* clean up chip-specific stuff */ | ||
2063 | dd->ipath_f_cleanup(dd); | ||
2064 | |||
2065 | dd->pcidev = NULL; | ||
2066 | } | ||
2067 | spin_lock_irqsave(&ipath_devs_lock, flags); | ||
2068 | } | ||
2069 | |||
2070 | spin_unlock_irqrestore(&ipath_devs_lock, flags); | ||
2071 | |||
2072 | ipath_cdbg(VERBOSE, "Unregistering pci driver\n"); | 2039 | ipath_cdbg(VERBOSE, "Unregistering pci driver\n"); |
2073 | pci_unregister_driver(&ipath_driver); | 2040 | pci_unregister_driver(&ipath_driver); |
2074 | 2041 | ||