NVMe: Only release requested regions
[linux-2.6-block.git] / drivers / nvme / host / pci.c
index 0f093f14d3482394630b66c8586da5beb455d8c4..befac5b19490ee91e13dec00c471931005b871b7 100644 (file)
@@ -1394,7 +1394,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        struct pci_dev *pdev = to_pci_dev(dev->dev);
        int result, i, vecs, nr_io_queues, size;
 
-       nr_io_queues = num_possible_cpus();
+       nr_io_queues = num_online_cpus();
        result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
        if (result < 0)
                return result;
@@ -1551,12 +1551,12 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
 
 static void nvme_disable_io_queues(struct nvme_dev *dev)
 {
-       int pass;
+       int pass, queues = dev->online_queues - 1;
        unsigned long timeout;
        u8 opcode = nvme_admin_delete_sq;
 
        for (pass = 0; pass < 2; pass++) {
-               int sent = 0, i = dev->queue_count - 1;
+               int sent = 0, i = queues;
 
                reinit_completion(&dev->ioq_wait);
  retry:
@@ -1679,9 +1679,14 @@ static int nvme_pci_enable(struct nvme_dev *dev)
 
 static void nvme_dev_unmap(struct nvme_dev *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       int bars;
+
        if (dev->bar)
                iounmap(dev->bar);
-       pci_release_regions(to_pci_dev(dev->dev));
+
+       bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       pci_release_selected_regions(pdev, bars);
 }
 
 static void nvme_pci_disable(struct nvme_dev *dev)
@@ -1857,7 +1862,7 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work)
 
        nvme_kill_queues(&dev->ctrl);
        if (pci_get_drvdata(pdev))
-               pci_stop_and_remove_bus_device_locked(pdev);
+               device_release_driver(&pdev->dev);
        nvme_put_ctrl(&dev->ctrl);
 }
 
@@ -1924,7 +1929,7 @@ static int nvme_dev_map(struct nvme_dev *dev)
 
        return 0;
   release:
-       pci_release_regions(pdev);
+       pci_release_selected_regions(pdev, bars);
        return -ENODEV;
 }
 
@@ -2017,6 +2022,10 @@ static void nvme_remove(struct pci_dev *pdev)
        nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
 
        pci_set_drvdata(pdev, NULL);
+
+       if (!pci_device_is_present(pdev))
+               nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD);
+
        flush_work(&dev->reset_work);
        nvme_uninit_ctrl(&dev->ctrl);
        nvme_dev_disable(dev, true);
@@ -2060,14 +2069,17 @@ static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev,
         * shutdown the controller to quiesce. The controller will be restarted
         * after the slot reset through driver's slot_reset callback.
         */
-       dev_warn(dev->ctrl.device, "error detected: state:%d\n", state);
        switch (state) {
        case pci_channel_io_normal:
                return PCI_ERS_RESULT_CAN_RECOVER;
        case pci_channel_io_frozen:
+               dev_warn(dev->ctrl.device,
+                       "frozen state error detected, reset controller\n");
                nvme_dev_disable(dev, false);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
+               dev_warn(dev->ctrl.device,
+                       "failure state error detected, request disconnect\n");
                return PCI_ERS_RESULT_DISCONNECT;
        }
        return PCI_ERS_RESULT_NEED_RESET;
@@ -2102,6 +2114,12 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0x0953),
                .driver_data = NVME_QUIRK_STRIPE_SIZE |
                                NVME_QUIRK_DISCARD_ZEROES, },
+       { PCI_VDEVICE(INTEL, 0x0a53),
+               .driver_data = NVME_QUIRK_STRIPE_SIZE |
+                               NVME_QUIRK_DISCARD_ZEROES, },
+       { PCI_VDEVICE(INTEL, 0x0a54),
+               .driver_data = NVME_QUIRK_STRIPE_SIZE |
+                               NVME_QUIRK_DISCARD_ZEROES, },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },