mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
- 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:
commit
fcf3981161
9 changed files with 77 additions and 49 deletions
|
@ -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)
|
||||||
|
|
|
@ -107,4 +107,5 @@ SECTIONS
|
||||||
/DISCARD/ : { *(.plt*) }
|
/DISCARD/ : { *(.plt*) }
|
||||||
/DISCARD/ : { *(.interp*) }
|
/DISCARD/ : { *(.interp*) }
|
||||||
/DISCARD/ : { *(.gnu*) }
|
/DISCARD/ : { *(.gnu*) }
|
||||||
|
/DISCARD/ : { *(.note.gnu.property) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
Loading…
Reference in a new issue