- x86: Discard .note.gnu.property sections
- nvme: Skip block device creation for inactive namespaces
- nvme: Convert NVMe doc to reST, and various minor fixes
This commit is contained in:
Tom Rini 2021-06-23 08:46:26 -04:00
commit fcf3981161
9 changed files with 77 additions and 49 deletions

View file

@ -914,6 +914,14 @@ S: Maintained
T: git https://source.denx.de/u-boot/custodians/u-boot-nios.git T: git https://source.denx.de/u-boot/custodians/u-boot-nios.git
F: arch/nios2/ F: arch/nios2/
NVMe
M: Bin Meng <bmeng.cn@gmail.com>
S: Maintained
F: drivers/nvme/
F: cmd/nvme.c
F: include/nvme.h
F: doc/develop/driver-model/nvme.rst
ONENAND ONENAND
#M: Lukasz Majewski <l.majewski@majess.pl> #M: Lukasz Majewski <l.majewski@majess.pl>
S: Orphaned (Since 2017-01) S: Orphaned (Since 2017-01)

View file

@ -107,4 +107,5 @@ SECTIONS
/DISCARD/ : { *(.plt*) } /DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) } /DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.note.gnu.property) }
} }

View file

@ -82,6 +82,7 @@ SECTIONS
/DISCARD/ : { *(.plt*) } /DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) } /DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.note.gnu.property) }
#if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT) #if defined(CONFIG_SPL_X86_16BIT_INIT) || defined(CONFIG_TPL_X86_16BIT_INIT)
/* /*

View file

@ -105,6 +105,7 @@ SECTIONS
/DISCARD/ : { *(.plt*) } /DISCARD/ : { *(.plt*) }
/DISCARD/ : { *(.interp*) } /DISCARD/ : { *(.interp*) }
/DISCARD/ : { *(.gnu*) } /DISCARD/ : { *(.gnu*) }
/DISCARD/ : { *(.note.gnu.property) }
#ifdef CONFIG_X86_16BIT_INIT #ifdef CONFIG_X86_16BIT_INIT
/* /*

View file

@ -19,6 +19,7 @@ subsystems
i2c-howto i2c-howto
livetree livetree
migration migration
nvme
of-plat of-plat
pci-info pci-info
pmic-framework pmic-framework

View file

@ -1,10 +1,12 @@
# SPDX-License-Identifier: GPL-2.0+ .. SPDX-License-Identifier: GPL-2.0+
# .. Copyright (C) 2017 NXP Semiconductors
# Copyright (C) 2017 NXP Semiconductors .. Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
# Copyright (C) 2017 Bin Meng <bmeng.cn@gmail.com>
NVMe Support
============
What is NVMe What is NVMe
============ ------------
NVM Express (NVMe) is a register level interface that allows host software to NVM Express (NVMe) is a register level interface that allows host software to
communicate with a non-volatile memory subsystem. This interface is optimized communicate with a non-volatile memory subsystem. This interface is optimized
@ -48,6 +50,8 @@ identified.
To list all of the NVMe hard disks, try: To list all of the NVMe hard disks, try:
.. code-block:: none
=> nvme info => nvme info
Device 0: Vendor: 0x8086 Rev: 8DV10131 Prod: CVFT535600LS400BGN Device 0: Vendor: 0x8086 Rev: 8DV10131 Prod: CVFT535600LS400BGN
Type: Hard Disk Type: Hard Disk
@ -55,10 +59,14 @@ To list all of the NVMe hard disks, try:
and print out detailed information for controller and namespaces via: and print out detailed information for controller and namespaces via:
.. code-block:: none
=> nvme detail => nvme detail
Raw block read/write to can be done via the 'nvme read/write' commands: Raw block read/write to can be done via the 'nvme read/write' commands:
.. code-block:: none
=> nvme read a0000000 0 11000 => nvme read a0000000 0 11000
=> tftp 80000000 /tftpboot/kernel.itb => tftp 80000000 /tftpboot/kernel.itb
@ -66,6 +74,8 @@ Raw block read/write to can be done via the 'nvme read/write' commands:
Of course, file system command can be used on the NVMe hard disk as well: Of course, file system command can be used on the NVMe hard disk as well:
.. code-block:: none
=> fatls nvme 0:1 => fatls nvme 0:1
32376967 kernel.itb 32376967 kernel.itb
22929408 100m 22929408 100m
@ -81,4 +91,7 @@ QEMU supports NVMe emulation and we can test NVMe driver with QEMU x86 running
U-Boot. Please see README.x86 for how to build u-boot.rom image for QEMU x86. U-Boot. Please see README.x86 for how to build u-boot.rom image for QEMU x86.
Example command line to call QEMU x86 below with emulated NVMe device: Example command line to call QEMU x86 below with emulated NVMe device:
$ ./qemu-system-i386 -drive file=nvme.img,if=none,id=drv0 -device nvme,drive=drv0,serial=QEMUNVME0001 -bios u-boot.rom
.. code-block:: bash
$ ./qemu-system-i386 -drive file=nvme.img,if=none,id=drv0 -device nvme,drive=drv0,serial=QEMUNVME0001 -bios u-boot.rom

View file

@ -5,39 +5,9 @@
*/ */
#include <common.h> #include <common.h>
#include <blk.h>
#include <errno.h>
#include <dm.h> #include <dm.h>
#include <dm/device.h>
#include "nvme.h"
static int nvme_uclass_post_probe(struct udevice *udev)
{
char name[20];
struct udevice *ns_udev;
int i, ret;
struct nvme_dev *ndev = dev_get_priv(udev);
/* Create a blk device for each namespace */
for (i = 0; i < ndev->nn; i++) {
/*
* Encode the namespace id to the device name so that
* we can extract it when doing the probe.
*/
sprintf(name, "blk#%d", i);
/* The real blksz and size will be set by nvme_blk_probe() */
ret = blk_create_devicef(udev, "nvme-blk", name, IF_TYPE_NVME,
-1, 512, 0, &ns_udev);
if (ret)
return ret;
}
return 0;
}
UCLASS_DRIVER(nvme) = { UCLASS_DRIVER(nvme) = {
.name = "nvme", .name = "nvme",
.id = UCLASS_NVME, .id = UCLASS_NVME,
.post_probe = nvme_uclass_post_probe,
}; };

View file

@ -81,7 +81,7 @@ static int nvme_setup_prps(struct nvme_dev *dev, u64 *prp2,
u64 *prp_pool; u64 *prp_pool;
int length = total_len; int length = total_len;
int i, nprps; int i, nprps;
u32 prps_per_page = (page_size >> 3) - 1; u32 prps_per_page = page_size >> 3;
u32 num_pages; u32 num_pages;
length -= (page_size - offset); length -= (page_size - offset);
@ -157,7 +157,7 @@ static u16 nvme_read_completion_status(struct nvme_queue *nvmeq, u16 index)
invalidate_dcache_range(start, stop); invalidate_dcache_range(start, stop);
return le16_to_cpu(readw(&(nvmeq->cqes[index].status))); return readw(&(nvmeq->cqes[index].status));
} }
/** /**
@ -221,7 +221,7 @@ static int nvme_submit_sync_cmd(struct nvme_queue *nvmeq,
} }
if (result) if (result)
*result = le32_to_cpu(readl(&(nvmeq->cqes[head].result))); *result = readl(&(nvmeq->cqes[head].result));
if (++head == nvmeq->q_depth) { if (++head == nvmeq->q_depth) {
head = 0; head = 0;
@ -304,7 +304,7 @@ static int nvme_enable_ctrl(struct nvme_dev *dev)
{ {
dev->ctrl_config &= ~NVME_CC_SHN_MASK; dev->ctrl_config &= ~NVME_CC_SHN_MASK;
dev->ctrl_config |= NVME_CC_ENABLE; dev->ctrl_config |= NVME_CC_ENABLE;
writel(cpu_to_le32(dev->ctrl_config), &dev->bar->cc); writel(dev->ctrl_config, &dev->bar->cc);
return nvme_wait_ready(dev, true); return nvme_wait_ready(dev, true);
} }
@ -313,7 +313,7 @@ static int nvme_disable_ctrl(struct nvme_dev *dev)
{ {
dev->ctrl_config &= ~NVME_CC_SHN_MASK; dev->ctrl_config &= ~NVME_CC_SHN_MASK;
dev->ctrl_config &= ~NVME_CC_ENABLE; dev->ctrl_config &= ~NVME_CC_ENABLE;
writel(cpu_to_le32(dev->ctrl_config), &dev->bar->cc); writel(dev->ctrl_config, &dev->bar->cc);
return nvme_wait_ready(dev, false); return nvme_wait_ready(dev, false);
} }
@ -387,7 +387,6 @@ static int nvme_configure_admin_queue(struct nvme_dev *dev)
aqa = nvmeq->q_depth - 1; aqa = nvmeq->q_depth - 1;
aqa |= aqa << 16; aqa |= aqa << 16;
aqa |= aqa << 16;
dev->page_size = 1 << page_shift; dev->page_size = 1 << page_shift;
@ -706,10 +705,9 @@ static int nvme_blk_probe(struct udevice *udev)
if (!id) if (!id)
return -ENOMEM; return -ENOMEM;
memset(ns, 0, sizeof(*ns));
ns->dev = ndev; ns->dev = ndev;
/* extract the namespace id from the block device name */ /* extract the namespace id from the block device name */
ns->ns_id = trailing_strtol(udev->name) + 1; ns->ns_id = trailing_strtol(udev->name);
if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) { if (nvme_identify(ndev, ns->ns_id, 0, (dma_addr_t)(long)id)) {
free(id); free(id);
return -EIO; return -EIO;
@ -719,11 +717,9 @@ static int nvme_blk_probe(struct udevice *udev)
flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK; flbas = id->flbas & NVME_NS_FLBAS_LBA_MASK;
ns->flbas = flbas; ns->flbas = flbas;
ns->lba_shift = id->lbaf[flbas].ds; ns->lba_shift = id->lbaf[flbas].ds;
ns->mode_select_num_blocks = le64_to_cpu(id->nsze);
ns->mode_select_block_len = 1 << ns->lba_shift;
list_add(&ns->list, &ndev->namespaces); list_add(&ns->list, &ndev->namespaces);
desc->lba = ns->mode_select_num_blocks; desc->lba = le64_to_cpu(id->nsze);
desc->log2blksz = ns->lba_shift; desc->log2blksz = ns->lba_shift;
desc->blksz = 1 << ns->lba_shift; desc->blksz = 1 << ns->lba_shift;
desc->bdev = udev; desc->bdev = udev;
@ -835,6 +831,7 @@ static int nvme_probe(struct udevice *udev)
{ {
int ret; int ret;
struct nvme_dev *ndev = dev_get_priv(udev); struct nvme_dev *ndev = dev_get_priv(udev);
struct nvme_id_ns *id;
ndev->instance = trailing_strtol(udev->name); ndev->instance = trailing_strtol(udev->name);
@ -879,8 +876,46 @@ static int nvme_probe(struct udevice *udev)
nvme_get_info_from_identify(ndev); nvme_get_info_from_identify(ndev);
/* Create a blk device for each namespace */
id = memalign(ndev->page_size, sizeof(struct nvme_id_ns));
if (!id) {
ret = -ENOMEM;
goto free_queue;
}
for (int i = 1; i <= ndev->nn; i++) {
struct udevice *ns_udev;
char name[20];
memset(id, 0, sizeof(*id));
if (nvme_identify(ndev, i, 0, (dma_addr_t)(long)id)) {
ret = -EIO;
goto free_id;
}
/* skip inactive namespace */
if (!id->nsze)
continue;
/*
* Encode the namespace id to the device name so that
* we can extract it when doing the probe.
*/
sprintf(name, "blk#%d", i);
/* The real blksz and size will be set by nvme_blk_probe() */
ret = blk_create_devicef(udev, "nvme-blk", name, IF_TYPE_NVME,
-1, 512, 0, &ns_udev);
if (ret)
goto free_id;
}
free(id);
return 0; return 0;
free_id:
free(id);
free_queue: free_queue:
free((void *)ndev->queues); free((void *)ndev->queues);
free_nvme: free_nvme:

View file

@ -633,8 +633,6 @@ struct nvme_ns {
int devnum; int devnum;
int lba_shift; int lba_shift;
u8 flbas; u8 flbas;
u64 mode_select_num_blocks;
u32 mode_select_block_len;
}; };
#endif /* __DRIVER_NVME_H__ */ #endif /* __DRIVER_NVME_H__ */