aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2013-07-15 17:02:21 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2013-09-03 16:40:28 -0400
commitf0b50732a979c55c2d15fe8ec4503fa5b3260c53 (patch)
tree101ace3b9ee8aaa678818f833157411799810865
parent224042742582c9938788b81165180c876e997a07 (diff)
NVMe: Separate controller init from disk discovery
This combines the controller initialization into one function, removing IO queue setup from namespace discovery, and creates symetric functions for device removal. The controller start and shutdown functions can now be called from resume/suspend context as well as probe/remove. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
-rw-r--r--drivers/block/nvme-core.c77
1 files changed, 47 insertions, 30 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index 95e28b6bcd09..1595ffba8a66 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1827,10 +1827,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
1827 dma_addr_t dma_addr; 1827 dma_addr_t dma_addr;
1828 int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12; 1828 int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
1829 1829
1830 res = nvme_setup_io_queues(dev);
1831 if (res)
1832 return res;
1833
1834 mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr, 1830 mem = dma_alloc_coherent(&dev->pci_dev->dev, 8192, &dma_addr,
1835 GFP_KERNEL); 1831 GFP_KERNEL);
1836 if (!mem) 1832 if (!mem)
@@ -1936,27 +1932,29 @@ static void nvme_dev_unmap(struct nvme_dev *dev)
1936 pci_disable_device(dev->pci_dev); 1932 pci_disable_device(dev->pci_dev);
1937} 1933}
1938 1934
1939static int nvme_dev_remove(struct nvme_dev *dev) 1935static void nvme_dev_shutdown(struct nvme_dev *dev)
1940{ 1936{
1941 struct nvme_ns *ns, *next;
1942 int i; 1937 int i;
1943 1938
1944 for (i = dev->queue_count - 1; i >= 0; i--) 1939 for (i = dev->queue_count - 1; i >= 0; i--)
1945 nvme_disable_queue(dev, i); 1940 nvme_disable_queue(dev, i);
1946 1941
1947 spin_lock(&dev_list_lock); 1942 spin_lock(&dev_list_lock);
1948 list_del(&dev->node); 1943 list_del_init(&dev->node);
1949 spin_unlock(&dev_list_lock); 1944 spin_unlock(&dev_list_lock);
1950 1945
1946 nvme_dev_unmap(dev);
1947}
1948
1949static void nvme_dev_remove(struct nvme_dev *dev)
1950{
1951 struct nvme_ns *ns, *next;
1952
1951 list_for_each_entry_safe(ns, next, &dev->namespaces, list) { 1953 list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
1952 list_del(&ns->list); 1954 list_del(&ns->list);
1953 del_gendisk(ns->disk); 1955 del_gendisk(ns->disk);
1954 nvme_ns_free(ns); 1956 nvme_ns_free(ns);
1955 } 1957 }
1956
1957 nvme_free_queues(dev);
1958
1959 return 0;
1960} 1958}
1961 1959
1962static int nvme_setup_prp_pools(struct nvme_dev *dev) 1960static int nvme_setup_prp_pools(struct nvme_dev *dev)
@@ -2016,7 +2014,8 @@ static void nvme_free_dev(struct kref *kref)
2016{ 2014{
2017 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref); 2015 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
2018 nvme_dev_remove(dev); 2016 nvme_dev_remove(dev);
2019 nvme_dev_unmap(dev); 2017 nvme_dev_shutdown(dev);
2018 nvme_free_queues(dev);
2020 nvme_release_instance(dev); 2019 nvme_release_instance(dev);
2021 nvme_release_prp_pools(dev); 2020 nvme_release_prp_pools(dev);
2022 kfree(dev->queues); 2021 kfree(dev->queues);
@@ -2059,6 +2058,37 @@ static const struct file_operations nvme_dev_fops = {
2059 .compat_ioctl = nvme_dev_ioctl, 2058 .compat_ioctl = nvme_dev_ioctl,
2060}; 2059};
2061 2060
2061static int nvme_dev_start(struct nvme_dev *dev)
2062{
2063 int result;
2064
2065 result = nvme_dev_map(dev);
2066 if (result)
2067 return result;
2068
2069 result = nvme_configure_admin_queue(dev);
2070 if (result)
2071 goto unmap;
2072
2073 spin_lock(&dev_list_lock);
2074 list_add(&dev->node, &dev_list);
2075 spin_unlock(&dev_list_lock);
2076
2077 result = nvme_setup_io_queues(dev);
2078 if (result)
2079 goto disable;
2080
2081 return 0;
2082
2083 disable:
2084 spin_lock(&dev_list_lock);
2085 list_del_init(&dev->node);
2086 spin_unlock(&dev_list_lock);
2087 unmap:
2088 nvme_dev_unmap(dev);
2089 return result;
2090}
2091
2062static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) 2092static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2063{ 2093{
2064 int result = -ENOMEM; 2094 int result = -ENOMEM;
@@ -2086,21 +2116,13 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2086 if (result) 2116 if (result)
2087 goto release; 2117 goto release;
2088 2118
2089 result = nvme_dev_map(dev); 2119 result = nvme_dev_start(dev);
2090 if (result) 2120 if (result)
2091 goto release_pools; 2121 goto release_pools;
2092 2122
2093 result = nvme_configure_admin_queue(dev);
2094 if (result)
2095 goto unmap;
2096
2097 spin_lock(&dev_list_lock);
2098 list_add(&dev->node, &dev_list);
2099 spin_unlock(&dev_list_lock);
2100
2101 result = nvme_dev_add(dev); 2123 result = nvme_dev_add(dev);
2102 if (result && result != -EBUSY) 2124 if (result && result != -EBUSY)
2103 goto delete; 2125 goto shutdown;
2104 2126
2105 scnprintf(dev->name, sizeof(dev->name), "nvme%d", dev->instance); 2127 scnprintf(dev->name, sizeof(dev->name), "nvme%d", dev->instance);
2106 dev->miscdev.minor = MISC_DYNAMIC_MINOR; 2128 dev->miscdev.minor = MISC_DYNAMIC_MINOR;
@@ -2116,15 +2138,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2116 2138
2117 remove: 2139 remove:
2118 nvme_dev_remove(dev); 2140 nvme_dev_remove(dev);
2119 delete: 2141 shutdown:
2120 spin_lock(&dev_list_lock); 2142 nvme_dev_shutdown(dev);
2121 list_del(&dev->node);
2122 spin_unlock(&dev_list_lock);
2123
2124 nvme_free_queues(dev);
2125 unmap:
2126 nvme_dev_unmap(dev);
2127 release_pools: 2143 release_pools:
2144 nvme_free_queues(dev);
2128 nvme_release_prp_pools(dev); 2145 nvme_release_prp_pools(dev);
2129 release: 2146 release:
2130 nvme_release_instance(dev); 2147 nvme_release_instance(dev);