Zhikang and Tom, Sorry for entering the list like this, however I wanted to reply to this topic from my work account. I attempted to email Zhikang separately however the email was bounced back.
I needed to make some changes in order to get Zhikang's work running on our Macchiattobin board with a Samsung 960 EVO NVMe drive. I wanted to make this patchset accessible so it could be included in the next submission to mainline it. No reason to duplicate work. Since this is just a patchset for the RFC I will only leave it here for whomever integrates the NVMe support, or if additional users want to test against it. -Jon
From f1ab1f30fe52bea7dc5c647b0570d73d907b8d90 Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 08:54:09 +0200 Subject: [PATCH 1/6] nvme: Only support CONFIG_BLK There is no reason to support devices that don't work with CONFIG_BLK. If needed the other drivers should be fixed. Signed-off-by: Jon Nettleton <[email protected]> --- common/nvme.c | 33 --------------------------- drivers/block/Kconfig | 1 + drivers/block/nvme.c | 63 --------------------------------------------------- drivers/block/nvme.h | 2 -- include/nvme.h | 10 +------- 5 files changed, 2 insertions(+), 107 deletions(-) diff --git a/common/nvme.c b/common/nvme.c index ed3250f43f..cdbfa665a0 100644 --- a/common/nvme.c +++ b/common/nvme.c @@ -21,7 +21,6 @@ struct blk_desc *nvme_get_dev(int dev) } #endif -#ifdef CONFIG_BLK struct udevice *udev; static unsigned long nvme_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst) @@ -34,19 +33,6 @@ static unsigned long nvme_bwrite(struct udevice *dev, lbaint_t start, { return nvme_write(dev, start, blkcnt, buffer); } -#else -static unsigned long nvme_bread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) -{ - return nvme_read(block_dev->devnum, start, blkcnt, dst); -} - -static unsigned long nvme_bwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - return nvme_write(block_dev->devnum, start, blkcnt, buffer); -} -#endif int __nvme_initialize(void) { @@ -54,25 +40,15 @@ int __nvme_initialize(void) int i; for (i = 0; i < CONFIG_SYS_NVME_MAX_DEVICE; i++) { -#ifdef CONFIG_BLK rc = init_nvme(udev); if (!rc) rc = scan_nvme(udev); -#else - rc = init_nvme(i); - if (!rc) - rc = scan_nvme(i); -#endif if (!rc && nvme_dev_desc[i].lba > 0) { nvme_dev_desc[i].if_type = IF_TYPE_NVME; nvme_dev_desc[i].devnum = i; nvme_dev_desc[i].part_type = PART_TYPE_UNKNOWN; nvme_dev_desc[i].type = DEV_TYPE_HARDDISK; -#ifndef CONFIG_BLK - nvme_dev_desc[i].block_read = nvme_bread; - nvme_dev_desc[i].block_write = nvme_bwrite; -#endif part_init(&nvme_dev_desc[i]); ret = i; @@ -88,7 +64,6 @@ int __nvme_initialize(void) } int nvme_initialize(void) __attribute__((weak, alias("__nvme_initialize"))); -#ifdef CONFIG_BLK static void nvme_name(char *str, int cardnum) { sprintf(str, "nvme#%u", cardnum); @@ -117,11 +92,3 @@ U_BOOT_DRIVER(nvme) = { .priv_auto_alloc_size = sizeof(struct nvme_ns), }; U_BOOT_PCI_DEVICE(nvme, nvme_supported); -#else -U_BOOT_LEGACY_BLK(nvme) = { - .if_typename = "nvme", - .if_type = IF_TYPE_NVME, - .max_devs = CONFIG_SYS_NVME_MAX_DEVICE, - .desc = nvme_dev_desc, -}; -#endif diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 129208f980..de1a3a50c1 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -63,6 +63,7 @@ endmenu config NVME bool "Support NVMe devices" depends on PCI + depends on BLK help This option enables supporting for all NVMe devices. It supports the basic functions before using NVMe devices diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 2e06477206..80fbd27d95 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -549,13 +549,8 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev) if (ctrl->mdts) dev->max_transfer_shift = (ctrl->mdts + shift); -#ifdef CONFIG_BLK dm_pci_read_config16(dev->pdev, PCI_VENDOR_ID, &vendor); dm_pci_read_config16(dev->pdev, PCI_DEVICE_ID, &device); -#else - pci_read_config_word(dev->pci_dev, PCI_VENDOR_ID, &vendor); - pci_read_config_word(dev->pci_dev, PCI_DEVICE_ID, &device); -#endif if ((vendor == PCI_VENDOR_ID_INTEL) && (device == 0x0953) && ctrl->vs[3]) { unsigned int max_transfer_shift; @@ -571,22 +566,14 @@ static int nvme_get_info_from_identify(struct nvme_dev *dev) return 0; } -#ifdef CONFIG_BLK int init_nvme(struct udevice *udev) -#else -int init_nvme(int devnum) -#endif { static int init_done; pci_dev_t pci_dev; int ret; -#ifdef CONFIG_BLK struct nvme_ns *ns = dev_get_priv(udev); struct nvme_dev *dev = ns->dev; int devnum = trailing_strtol(udev->name); -#else - struct nvme_dev *dev; -#endif u32 val; u64 cap; @@ -611,15 +598,9 @@ int init_nvme(int devnum) dev->instance = nvme_info.idx - 1; INIT_LIST_HEAD(&dev->namespaces); -#ifdef CONFIG_BLK dev->pdev = udev; dev->bar = dm_pci_map_bar(udev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); -#else - dev->pci_dev = pci_dev; - dev->bar = pci_map_bar(dev->pci_dev, PCI_BASE_ADDRESS_0, - PCI_REGION_MEM); -#endif if (readl(&dev->bar->csts) == -1) { ret = -ENODEV; printf("Error: nvme%d: Out of Memory!\n", nvme_info.idx - 1); @@ -644,25 +625,13 @@ int init_nvme(int devnum) /* Try to enable I/O accesses and bus-mastering */ val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; -#ifdef CONFIG_BLK dm_pci_write_config32(udev, PCI_COMMAND, val); -#else - pci_write_config_dword(dev->pci_dev, PCI_COMMAND, val); -#endif /* Print a debug message with the IO base address */ -#ifdef CONFIG_BLK dm_pci_read_config32(udev, PCI_BASE_ADDRESS_0, &val); -#else - pci_read_config_dword(dev->pci_dev, PCI_BASE_ADDRESS_0, &val); -#endif /* Make sure it worked */ -#ifdef CONFIG_BLK dm_pci_read_config32(udev, PCI_COMMAND, &val); -#else - pci_read_config_dword(dev->pci_dev, PCI_COMMAND, &val); -#endif if (!(val & PCI_COMMAND_MEMORY)) { printf("Can't enable I/O memory\n"); ret = -ENOSPC; @@ -732,18 +701,11 @@ static struct nvme_ns *find_ns_by_devnum(int devnum) return NULL; } -#ifdef CONFIG_BLK int scan_nvme(struct udevice *udev) { struct nvme_ns *ns = dev_get_priv(udev); struct nvme_dev *dev = ns->dev; int devnum = trailing_strtol(udev->name); -#else -int scan_nvme(int devnum) -{ - struct nvme_ns *ns; - struct nvme_dev *dev; -#endif int ret; u8 flbas; u16 vendor; @@ -783,15 +745,10 @@ int scan_nvme(int devnum) nvme_dev_desc[devnum].lba = ns->mode_select_num_blocks; nvme_dev_desc[devnum].log2blksz = ns->lba_shift; nvme_dev_desc[devnum].blksz = 1 << ns->lba_shift; -#ifdef CONFIG_BLK nvme_dev_desc[devnum].bdev = dev->pdev; dm_pci_read_config16(dev->pdev, PCI_VENDOR_ID, &vendor); udev->priv = ns; udev->uclass_platdata = (void *)&nvme_dev_desc[devnum]; -#else - nvme_dev_desc[devnum].priv = (void *)ns; - pci_read_config_word(dev->pci_dev, PCI_VENDOR_ID, &vendor); -#endif sprintf(vendor_c, "0x%.4x", vendor); memcpy(nvme_dev_desc[devnum].product, dev->serial, sizeof(dev->serial)); @@ -895,13 +852,9 @@ static void print_metadata_cap(u8 mc, int devnum) int nvme_print_info(int devnum) { -#ifdef CONFIG_BLK struct udevice *udev; blk_get_device(IF_TYPE_NVME, devnum, &udev); struct nvme_ns *ns = dev_get_priv(udev); -#else - struct nvme_ns *ns = nvme_dev_desc[devnum].priv; -#endif if (!ns) { printf("Can not find device %d\n", devnum); return -EINVAL; @@ -927,20 +880,12 @@ int nvme_print_info(int devnum) return 0; } -#ifdef CONFIG_BLK ulong nvme_write(struct udevice *udev, ulong blknr, lbaint_t blkcnt, const void *buffer) { struct nvme_ns *ns = dev_get_priv(udev); struct nvme_dev *dev = ns->dev; int devnum = ns->devnum; -#else -ulong nvme_write(int devnum, ulong blknr, lbaint_t blkcnt, - const void *buffer) -{ - struct nvme_ns *ns = nvme_dev_desc[devnum].priv; - struct nvme_dev *dev = ns->dev; -#endif struct nvme_command c; int status; u64 prp2; @@ -987,20 +932,12 @@ ulong nvme_write(int devnum, ulong blknr, lbaint_t blkcnt, return (total_len - temp_len) >> nvme_dev_desc[devnum].log2blksz; } -#ifdef CONFIG_BLK ulong nvme_read(struct udevice *udev, ulong blknr, lbaint_t blkcnt, void *buffer) { struct nvme_ns *ns = dev_get_priv(udev); struct nvme_dev *dev = ns->dev; int devnum = ns->devnum; -#else -ulong nvme_read(int devnum, ulong blknr, lbaint_t blkcnt, - void *buffer) -{ - struct nvme_ns *ns = nvme_dev_desc[devnum].priv; - struct nvme_dev *dev = ns->dev; -#endif struct nvme_command c; int status; u64 prp2; diff --git a/drivers/block/nvme.h b/drivers/block/nvme.h index 9345f90a1c..f0fad95b7b 100644 --- a/drivers/block/nvme.h +++ b/drivers/block/nvme.h @@ -61,9 +61,7 @@ struct nvme_dev { struct nvme_queue **queues; u32 __iomem *dbs; unsigned int cardnum; -#ifdef CONFIG_BLK struct udevice *pdev; -#endif pci_dev_t pci_dev; int instance; uint8_t *hw_addr; diff --git a/include/nvme.h b/include/nvme.h index 3f8f94f462..e13de19163 100644 --- a/include/nvme.h +++ b/include/nvme.h @@ -7,22 +7,14 @@ #ifndef __NVME_H__ #define __NVME_H__ #include <part.h> +#include <pci.h> -#ifdef CONFIG_BLK int init_nvme(struct udevice *udev); int scan_nvme(struct udevice *udev); ulong nvme_read(struct udevice *udev, ulong blknr, lbaint_t blkcnt, void *buffer); ulong nvme_write(struct udevice *udev, ulong blknr, lbaint_t blkcnt, const void *buffer); -#else -int init_nvme(int devnum); -int scan_nvme(int devnum); -ulong nvme_read(int devnum, ulong blknr, lbaint_t blkcnt, - void *buffer); -ulong nvme_write(int devnum, ulong blknr, lbaint_t blkcnt, - const void *buffer); -#endif int nvme_print_info(int devnum); int nvme_initialize(void); int __nvme_initialize(void); -- 2.11.1 From 5de8da9db30a54db6239f0947d61ef92043aac30 Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 09:00:48 +0200 Subject: [PATCH 2/6] NVMe: correctly identify NVMe Device. IF_TYPE_NVME is not an unknown device any longer. Signed-off-by: Jon Nettleton <[email protected]> --- disk/part.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/disk/part.c b/disk/part.c index 983104e349..8a5d29923c 100644 --- a/disk/part.c +++ b/disk/part.c @@ -271,6 +271,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc) case IF_TYPE_HOST: puts("HOST"); break; + case IF_TYPE_NVME: + puts("NVME"); + break; default: puts ("UNKNOWN"); break; -- 2.11.1 From 81c8d7935b345bd9fb659e2a368bf1dab6325212 Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 09:04:08 +0200 Subject: [PATCH 3/6] NVMe: Only increment device if probing is successful Any time along the init process we should make sure and decrement the nvme id if we fail. Otherwise constant probing will keep incrementing the device counter. Signed-off-by: Jon Nettleton <[email protected]> --- drivers/block/nvme.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 80fbd27d95..39eb066b6d 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -585,13 +585,13 @@ int init_nvme(struct udevice *udev) pci_dev = pci_find_devices(nvme_supported, nvme_info.idx++); if (pci_dev == -1) { printf("Error: can't find pci device \"nvme%d\"\n", - nvme_info.idx - 1); + --nvme_info.idx); return -ENODEV; } dev = malloc(sizeof(*dev)); if (dev == NULL) { - printf("Error: nvme%d: Out of Memory!\n", nvme_info.idx - 1); + printf("Error: nvme%d: Out of Memory!\n", --nvme_info.idx); return -ENOMEM; } memset(dev, 0, sizeof(*dev)); @@ -603,7 +603,7 @@ int init_nvme(struct udevice *udev) PCI_REGION_MEM); if (readl(&dev->bar->csts) == -1) { ret = -ENODEV; - printf("Error: nvme%d: Out of Memory!\n", nvme_info.idx - 1); + printf("Error: nvme%d: Out of Memory!\n", --nvme_info.idx); goto free_nvme; } -- 2.11.1 From eca9727cc11832e9e1e8ecab174189242424bb5d Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 09:06:11 +0200 Subject: [PATCH 4/6] NVMe: fix number of blocks detection. NVMe should use the nsze value from the queried device. This will reflect the total number of blocks of the device and fixes detecting my Samsung 960 EVO 256GB. Original: Capacity: 40386.6 MB = 39.4 GB (82711872 x 512) Fixed: Capacity: 238475.1 MB = 232.8 GB (488397168 x 512) Signed-off-by: Jon Nettleton <[email protected]> --- drivers/block/nvme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 39eb066b6d..6d2437503b 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -739,7 +739,7 @@ int scan_nvme(struct udevice *udev) flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK; ns->flbas = flbas; ns->lba_shift = id->lbaf[flbas].ds; - ns->mode_select_num_blocks = le64_to_cpu(id->nuse); + ns->mode_select_num_blocks = le64_to_cpu(id->nsze); ns->mode_select_block_len = 1 << ns->lba_shift; list_add(&ns->list, &dev->namespaces); nvme_dev_desc[devnum].lba = ns->mode_select_num_blocks; -- 2.11.1 From 92637e5499af333913284a9d8324b7ad861b7c54 Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 09:10:22 +0200 Subject: [PATCH 5/6] NVMe: Detect devices that are class Storage Express This adds support to detect the catchall PCI class for NVMe devices. It allows the drivers to work with most NVMe devices that don't need specific detection due to quirks etc. Tested against a Samsung 960 EVO drive. Signed-off-by: Jon Nettleton <[email protected]> --- common/nvme.c | 2 ++ drivers/block/nvme.c | 6 +++++- include/pci_ids.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/common/nvme.c b/common/nvme.c index cdbfa665a0..253e5bb7c2 100644 --- a/common/nvme.c +++ b/common/nvme.c @@ -12,8 +12,10 @@ struct blk_desc nvme_dev_desc[CONFIG_SYS_NVME_MAX_DEVICE]; struct pci_device_id nvme_supported[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953) }, + { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, {} }; + #ifdef CONFIG_PARTITIONS struct blk_desc *nvme_get_dev(int dev) { diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 6d2437503b..26d6400a22 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -582,7 +582,11 @@ int init_nvme(struct udevice *udev) return 0; } - pci_dev = pci_find_devices(nvme_supported, nvme_info.idx++); + pci_dev = pci_find_class(PCI_CLASS_STORAGE_EXPRESS, nvme_info.idx++); + if (pci_dev == -1) { + pci_dev = pci_find_devices(nvme_supported, nvme_info.idx); + } + if (pci_dev == -1) { printf("Error: can't find pci device \"nvme%d\"\n", --nvme_info.idx); diff --git a/include/pci_ids.h b/include/pci_ids.h index ab6aa58adb..fdda679cc0 100644 --- a/include/pci_ids.h +++ b/include/pci_ids.h @@ -21,6 +21,7 @@ #define PCI_CLASS_STORAGE_SATA 0x0106 #define PCI_CLASS_STORAGE_SATA_AHCI 0x010601 #define PCI_CLASS_STORAGE_SAS 0x0107 +#define PCI_CLASS_STORAGE_EXPRESS 0x010802 #define PCI_CLASS_STORAGE_OTHER 0x0180 #define PCI_BASE_CLASS_NETWORK 0x02 -- 2.11.1 From 98bcf3c2dbc0b611e4895b391bce7903597ecf3a Mon Sep 17 00:00:00 2001 From: Jon Nettleton <[email protected]> Date: Fri, 28 Jul 2017 09:13:56 +0200 Subject: [PATCH 6/6] NVMe: match printf types to make GCC 6 happy. This mistyping was making gcc 6 unhappy, so fix it up. Signed-off-by: Jon Nettleton <[email protected]> --- cmd/nvme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nvme.c b/cmd/nvme.c index 5c8bf42bc9..49864baf4e 100644 --- a/cmd/nvme.c +++ b/cmd/nvme.c @@ -77,7 +77,7 @@ static int do_nvme_read(cmd_tbl_t *cmdtp, int flag, int argc, ulong n; lbaint_t blk = simple_strtoul(argv[2], NULL, 16); - printf("\nNVME read: device %d block # %ld, count %ld ... ", + printf("\nNVME read: device %d block # %llu, count %lu ... ", nvme_curr_device, blk, cnt); time = get_timer(0); @@ -108,7 +108,7 @@ static int do_nvme_write(cmd_tbl_t *cmdtp, int flag, int argc, ulong n; lbaint_t blk = simple_strtoul(argv[2], NULL, 16); - printf("\nNVME write: device %d block # %ld, count %ld ... ", + printf("\nNVME write: device %d block # %llu, count %lu ... ", nvme_curr_device, blk, cnt); time = get_timer(0); -- 2.11.1
_______________________________________________ U-Boot mailing list [email protected] https://lists.denx.de/listinfo/u-boot

