Skip to content
Permalink
Browse files
nvme: add platform driver registration
After the common code is detached from the PCI specific
ones, add a parallel part for platform_driver registration.

Keep it in the same file for the moment to allow rebasing,
it can be split into multiple modules later on.

This is completely untested and probably does not work.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
  • Loading branch information
arndb authored and svenpeter42 committed Jun 8, 2021
1 parent 3930f77 commit bdb3ab66d08f3e95705b1e4403be6d9d9740a78e
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 5 deletions.
@@ -3,10 +3,17 @@ config NVME_CORE
tristate
select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY

config NVME_MMIO
tristate
select NVME_CORE
help
This is the common code shared by the PCIe driver (BLK_DEV_NVME)
and the platform driver used for on-chip implementations.

config BLK_DEV_NVME
tristate "NVM Express block device"
tristate "NVM Express block device using PCIe"
depends on PCI && BLOCK
select NVME_CORE
select NVME_MMIO
help
The NVM Express driver is for solid state drives directly
connected to the PCI or PCI Express bus. If you know you
@@ -15,6 +22,19 @@ config BLK_DEV_NVME
To compile this driver as a module, choose M here: the
module will be called nvme.

config BLK_DEV_NVME_PLATFORM
tristate "NVM Express block device integrated on SoC"
depends on OF && BLOCK
select NVME_MMIO
help
NVM Express devices can be integrated into a System-on-Chip
(SoC) platform without a discoverable PCIe bus.
The NVMe platform driver supports such devices using
a device tree description.

To compile this driver as a module, choose M here: the
module will be called nvme.

config NVME_MULTIPATH
bool "NVMe multipath support"
depends on NVME_CORE
@@ -3,7 +3,7 @@
ccflags-y += -I$(src)

obj-$(CONFIG_NVME_CORE) += nvme-core.o
obj-$(CONFIG_BLK_DEV_NVME) += nvme.o
obj-$(CONFIG_NVME_MMIO) += nvme.o
obj-$(CONFIG_NVME_FABRICS) += nvme-fabrics.o
obj-$(CONFIG_NVME_RDMA) += nvme-rdma.o
obj-$(CONFIG_NVME_FC) += nvme-fc.o
@@ -149,6 +149,11 @@ enum nvme_quirks {
* 48 bits.
*/
NVME_QUIRK_DMA_ADDRESS_BITS_48 = (1 << 16),

/*
* MMIO based hardware that is not on a PCI bus
*/
NVME_QUIRK_PLATFORM_DEVICE = (1 << 17),
};

/*
@@ -19,6 +19,7 @@
#include <linux/mutex.h>
#include <linux/once.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
#include <linux/t10-pi.h>
#include <linux/types.h>
@@ -185,7 +186,11 @@ static inline struct nvme_dev *to_nvme_dev(struct nvme_ctrl *ctrl)

static inline struct pci_dev *nvme_pci_dev(struct nvme_dev *dev)
{
return to_pci_dev(dev->dev);
if (IS_ENABLED(CONFIG_BLK_DEV_NVME) &&
!(dev->ctrl.quirks & NVME_QUIRK_PLATFORM_DEVICE))
return to_pci_dev(dev->dev);

return NULL;
}

/*
@@ -2911,6 +2916,108 @@ static void nvme_remove(struct nvme_dev *dev)
nvme_release_prp_pools(dev);
}

#if IS_ENABLED(CONFIG_BLK_DEV_NVME_PLATFORM)
static const struct nvme_ctrl_ops nvme_platform_ctrl_ops = {
.name = "platform",
.module = THIS_MODULE,
.flags = NVME_F_METADATA_SUPPORTED,
.reg_read32 = nvme_reg_read32,
.reg_write32 = nvme_reg_write32,
.reg_read64 = nvme_reg_read64,
.free_ctrl = nvme_free_ctrl,
.submit_async_event = nvme_submit_async_event,
.get_address = nvme_get_address,
};

static void nvme_platform_async_probe(void *data, async_cookie_t cookie)
{
struct nvme_dev *dev = data;

flush_work(&dev->ctrl.reset_work);
flush_work(&dev->ctrl.scan_work);
nvme_put_ctrl(&dev->ctrl);
}

static int nvme_platform_probe(struct platform_device *pdev)
{
int result;
struct nvme_dev *dev;
struct resource *res;

dev = nvme_dev_alloc(&pdev->dev);
if (!dev)
return -ENOMEM;

platform_set_drvdata(pdev, dev);
dev->bar = devm_platform_ioremap_resource(pdev, 0);
result = PTR_ERR_OR_ZERO(dev->bar);
if (result)
goto out;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
result = ENXIO;
goto out_unmap;
}

dev->bar_mapped_size = resource_size(res);
dev->dbs = dev->bar + NVME_REG_DBS;

dev->platform_irq = platform_get_irq(pdev, 0);
if (dev->platform_irq < 0) {
result = dev->platform_irq;
goto out_unmap;
}

result = nvme_init_ctrl(&dev->ctrl, &pdev->dev, &nvme_platform_ctrl_ops,
NVME_QUIRK_SINGLE_VECTOR |
NVME_QUIRK_PLATFORM_DEVICE);
if (result)
goto out_unmap;

nvme_reset_ctrl(&dev->ctrl);
async_schedule(nvme_platform_async_probe, dev);

return 0;

out_unmap:
devm_iounmap(&pdev->dev, dev->bar);
out:
nvme_dev_free(dev);
return result;
}

static int nvme_platform_remove(struct platform_device *pdev)
{
struct nvme_dev *dev = platform_get_drvdata(pdev);

nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING);
platform_set_drvdata(pdev, NULL);

nvme_remove(dev);

nvme_uninit_ctrl(&dev->ctrl);

return 0;
}

struct of_device_id nvme_of_device_ids[] = {
{ .compatible = "generic-nvmexpress", },
{},
};

struct platform_driver nvme_platform_driver = {
.driver = {
.name = "nvme-platform",
.owner = THIS_MODULE,
.of_match_table = nvme_of_device_ids,
},
.probe = nvme_platform_probe,
.remove = nvme_platform_remove,
};
#endif

#if IS_ENABLED(CONFIG_BLK_DEV_NVME)
static const struct nvme_ctrl_ops nvme_pci_ctrl_ops = {
.name = "pcie",
.module = THIS_MODULE,
@@ -3405,20 +3512,45 @@ static struct pci_driver nvme_driver = {
.sriov_configure = pci_sriov_configure_simple,
.err_handler = &nvme_pci_err_handler,
};
#endif

static int __init nvme_init(void)
{
int ret;

BUILD_BUG_ON(sizeof(struct nvme_create_cq) != 64);
BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2);

return pci_register_driver(&nvme_driver);
#if IS_ENABLED(CONFIG_BLK_DEV_NVME)
ret = pci_register_driver(&nvme_driver);
if (ret)
return ret;
#endif

#if IS_ENABLED(CONFIG_BLK_DEV_NVME_PLATFORM)
ret = platform_driver_register(&nvme_platform_driver);
#endif

#if IS_ENABLED(CONFIG_BLK_DEV_NVME)
if (ret)
pci_unregister_driver(&nvme_driver);
#endif

return ret;
}

static void __exit nvme_exit(void)
{
#if IS_ENABLED(CONFIG_BLK_DEV_NVME)
pci_unregister_driver(&nvme_driver);
#endif

#if IS_ENABLED(CONFIG_BLK_DEV_NVME_PLATFORM)
platform_driver_unregister(&nvme_platform_driver);
#endif

flush_workqueue(nvme_wq);
}

0 comments on commit bdb3ab6

Please sign in to comment.