Spdk/lib/nvme/nvme_quirks.c
Jim Harris b90d7b5b43 nvme: add admin queue size quirk for Hyper-V
Hyper-V NVMe SSD controllers require admin queue
size to be even multiples of a page. Add quirk to
adjust the admin queue size if user overrides the
default value to something other than an even
multiple.

As part of this change, set the quirks earlier
when constructing a pcie controller, so that the
quirks value can be used in the generic
nvme_ctrlr_construct() function.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Change-Id: I417cd3cdc7e3ba512ec412f4876b0e0b7432341c
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14220
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com>
2022-09-01 08:31:46 +00:00

147 lines
4.9 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "nvme_internal.h"
struct nvme_quirk {
struct spdk_pci_id id;
uint64_t flags;
};
static const struct nvme_quirk nvme_quirks[] = {
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x0953, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_READ_LATENCY |
NVME_INTEL_QUIRK_WRITE_LATENCY |
NVME_INTEL_QUIRK_STRIPING |
NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE |
NVME_QUIRK_DELAY_BEFORE_INIT |
NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x0A53, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_READ_LATENCY |
NVME_INTEL_QUIRK_WRITE_LATENCY |
NVME_INTEL_QUIRK_STRIPING |
NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE |
NVME_QUIRK_DELAY_BEFORE_INIT |
NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x0A54, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_READ_LATENCY |
NVME_INTEL_QUIRK_WRITE_LATENCY |
NVME_INTEL_QUIRK_STRIPING |
NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE |
NVME_QUIRK_DELAY_BEFORE_INIT |
NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x0A55, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_READ_LATENCY |
NVME_INTEL_QUIRK_WRITE_LATENCY |
NVME_INTEL_QUIRK_STRIPING |
NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE |
NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x0B60, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_READ_LATENCY |
NVME_INTEL_QUIRK_WRITE_LATENCY |
NVME_INTEL_QUIRK_STRIPING |
NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE |
NVME_QUIRK_NO_SGL_FOR_DSM
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_MEMBLAZE, 0x0540, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_DELAY_BEFORE_CHK_RDY
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_SAMSUNG, 0xa821, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_DELAY_BEFORE_CHK_RDY
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_SAMSUNG, 0xa822, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_DELAY_BEFORE_CHK_RDY
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_VIRTUALBOX, 0x4e56, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_DELAY_AFTER_QUEUE_ALLOC
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x5845, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_INTEL_QUIRK_NO_LOG_PAGES |
NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_REDHAT, 0x0010, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_MAXIMUM_PCI_ACCESS_WIDTH
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_CNEXLABS, 0x1f1f, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_IDENTIFY_CNS |
NVME_QUIRK_OCSSD
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_VMWARE, 0x07f0, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_SHST_COMPLETE
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x2700, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_OACS_SECURITY
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_INTEL, 0x4140, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_MDTS_EXCLUDE_MD
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_HUAWEI, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_NOT_USE_SGL
},
{ {SPDK_PCI_CLASS_NVME, SPDK_PCI_VID_MICROSOFT, 0xb111, SPDK_PCI_ANY_ID, SPDK_PCI_ANY_ID},
NVME_QUIRK_MINIMUM_ADMIN_QUEUE_SIZE
},
{ {0x000000, 0x0000, 0x0000, 0x0000, 0x0000}, 0}
};
/* Compare each field. SPDK_PCI_ANY_ID in s1 matches everything */
static bool
pci_id_match(const struct spdk_pci_id *s1, const struct spdk_pci_id *s2)
{
if ((s1->class_id == SPDK_PCI_CLASS_ANY_ID || s1->class_id == s2->class_id) &&
(s1->vendor_id == SPDK_PCI_ANY_ID || s1->vendor_id == s2->vendor_id) &&
(s1->device_id == SPDK_PCI_ANY_ID || s1->device_id == s2->device_id) &&
(s1->subvendor_id == SPDK_PCI_ANY_ID || s1->subvendor_id == s2->subvendor_id) &&
(s1->subdevice_id == SPDK_PCI_ANY_ID || s1->subdevice_id == s2->subdevice_id)) {
return true;
}
return false;
}
uint64_t
nvme_get_quirks(const struct spdk_pci_id *id)
{
const struct nvme_quirk *quirk = nvme_quirks;
SPDK_DEBUGLOG(nvme, "Searching for %04x:%04x [%04x:%04x]...\n",
id->vendor_id, id->device_id,
id->subvendor_id, id->subdevice_id);
while (quirk->id.vendor_id) {
if (pci_id_match(&quirk->id, id)) {
SPDK_DEBUGLOG(nvme, "Matched quirk %04x:%04x [%04x:%04x]:\n",
quirk->id.vendor_id, quirk->id.device_id,
quirk->id.subvendor_id, quirk->id.subdevice_id);
#define PRINT_QUIRK(quirk_flag) \
do { \
if (quirk->flags & (quirk_flag)) { \
SPDK_DEBUGLOG(nvme, "Quirk enabled: %s\n", #quirk_flag); \
} \
} while (0)
PRINT_QUIRK(NVME_INTEL_QUIRK_READ_LATENCY);
PRINT_QUIRK(NVME_INTEL_QUIRK_WRITE_LATENCY);
PRINT_QUIRK(NVME_QUIRK_DELAY_BEFORE_CHK_RDY);
PRINT_QUIRK(NVME_INTEL_QUIRK_STRIPING);
PRINT_QUIRK(NVME_QUIRK_DELAY_AFTER_QUEUE_ALLOC);
PRINT_QUIRK(NVME_QUIRK_READ_ZERO_AFTER_DEALLOCATE);
PRINT_QUIRK(NVME_QUIRK_IDENTIFY_CNS);
PRINT_QUIRK(NVME_QUIRK_OCSSD);
return quirk->flags;
}
quirk++;
}
SPDK_DEBUGLOG(nvme, "No quirks found.\n");
return 0;
}