diff options
author | Jens Axboe <axboe@fb.com> | 2017-04-25 07:03:14 +0300 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2017-04-25 07:03:14 +0300 |
commit | d9fd363a6cbfae24ffaa00ac6fd3ce8e271acaf1 (patch) | |
tree | 9139831824ebe9cf77d1bf836b558ee2061c0483 /drivers/nvme | |
parent | a44f53faf4674d84cba79f7ee574584e18ab8744 (diff) | |
parent | 8f9cedc76fc7d9bc916127f8fe1287a249891d40 (diff) | |
download | linux-d9fd363a6cbfae24ffaa00ac6fd3ce8e271acaf1.tar.xz |
Merge branch 'master' into for-4.12/post-merge
Diffstat (limited to 'drivers/nvme')
-rw-r--r-- | drivers/nvme/host/core.c | 23 | ||||
-rw-r--r-- | drivers/nvme/host/fc.c | 2 | ||||
-rw-r--r-- | drivers/nvme/host/nvme.h | 5 | ||||
-rw-r--r-- | drivers/nvme/host/pci.c | 26 | ||||
-rw-r--r-- | drivers/nvme/host/rdma.c | 2 | ||||
-rw-r--r-- | drivers/nvme/target/loop.c | 2 |
6 files changed, 48 insertions, 12 deletions
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 263946b23628..bf6729b1d8bf 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1374,6 +1374,14 @@ static void nvme_configure_apst(struct nvme_ctrl *ctrl) table->entries[state] = target; /* + * Don't allow transitions to the deepest state + * if it's quirked off. + */ + if (state == ctrl->npss && + (ctrl->quirks & NVME_QUIRK_NO_DEEPEST_PS)) + continue; + + /* * Is this state a useful non-operational state for * higher-power states to autonomously transition to? */ @@ -1445,16 +1453,15 @@ struct nvme_core_quirk_entry { }; static const struct nvme_core_quirk_entry core_quirks[] = { - /* - * Seen on a Samsung "SM951 NVMe SAMSUNG 256GB": using APST causes - * the controller to go out to lunch. It dies when the watchdog - * timer reads CSTS and gets 0xffffffff. - */ { - .vid = 0x144d, - .fr = "BXW75D0Q", + /* + * This Toshiba device seems to die using any APST states. See: + * https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1678184/comments/11 + */ + .vid = 0x1179, + .mn = "THNSF5256GPUK TOSHIBA", .quirks = NVME_QUIRK_NO_APST, - }, + } }; /* match is null-terminated but idstr is space-padded. */ diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 596b3a453b54..ecc1048de837 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2056,7 +2056,7 @@ nvme_fc_configure_admin_queue(struct nvme_fc_ctrl *ctrl) } ctrl->ctrl.sqsize = - min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize); + min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize); error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap); if (error) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index c6ef6c30e2f0..29c708ca9621 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -71,6 +71,11 @@ enum nvme_quirks { * APST should not be used. */ NVME_QUIRK_NO_APST = (1 << 4), + + /* + * The deepest sleep state should not be used. + */ + NVME_QUIRK_NO_DEEPEST_PS = (1 << 5), }; /* diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 212f7e0db84f..c8541c3dcd19 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -19,6 +19,7 @@ #include <linux/blk-mq-pci.h> #include <linux/cpu.h> #include <linux/delay.h> +#include <linux/dmi.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/genhd.h> @@ -2070,10 +2071,31 @@ static int nvme_dev_map(struct nvme_dev *dev) return -ENODEV; } +static unsigned long check_dell_samsung_bug(struct pci_dev *pdev) +{ + if (pdev->vendor == 0x144d && pdev->device == 0xa802) { + /* + * Several Samsung devices seem to drop off the PCIe bus + * randomly when APST is on and uses the deepest sleep state. + * This has been observed on a Samsung "SM951 NVMe SAMSUNG + * 256GB", a "PM951 NVMe SAMSUNG 512GB", and a "Samsung SSD + * 950 PRO 256GB", but it seems to be restricted to two Dell + * laptops. + */ + if (dmi_match(DMI_SYS_VENDOR, "Dell Inc.") && + (dmi_match(DMI_PRODUCT_NAME, "XPS 15 9550") || + dmi_match(DMI_PRODUCT_NAME, "Precision 5510"))) + return NVME_QUIRK_NO_DEEPEST_PS; + } + + return 0; +} + static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int node, result = -ENOMEM; struct nvme_dev *dev; + unsigned long quirks = id->driver_data; node = dev_to_node(&pdev->dev); if (node == NUMA_NO_NODE) @@ -2105,8 +2127,10 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (result) goto put_pci; + quirks |= check_dell_samsung_bug(pdev); + result = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_pci_ctrl_ops, - id->driver_data); + quirks); if (result) goto release_pools; diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 53b611f9ba5d..29cf88ac3f61 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1599,7 +1599,7 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl) } ctrl->ctrl.sqsize = - min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize); + min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize); error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap); if (error) diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c index 8260ee1f8e48..304f1c87c160 100644 --- a/drivers/nvme/target/loop.c +++ b/drivers/nvme/target/loop.c @@ -405,7 +405,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl) } ctrl->ctrl.sqsize = - min_t(int, NVME_CAP_MQES(ctrl->cap) + 1, ctrl->ctrl.sqsize); + min_t(int, NVME_CAP_MQES(ctrl->cap), ctrl->ctrl.sqsize); error = nvme_enable_ctrl(&ctrl->ctrl, ctrl->cap); if (error) |