aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2013-02-19 12:17:58 -0500
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2013-04-16 15:43:55 -0400
commit5e82e952f04681c10f35e02ee0a4a43ec027137a (patch)
treeac827583d123873bf5fbfdeb2b6b68389a1322af
parent1c9b52651dad0ff1fa71fc6205c86d972f25bcc0 (diff)
NVMe: Add a character device for each nvme device
Registers a miscellaneous device for each nvme controller probed. This creates character device files as /dev/nvmeN, where N is the device instance, and supports nvme admin ioctl commands so devices without namespaces can be managed. Signed-off-by: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
-rw-r--r--drivers/block/nvme-core.c74
-rw-r--r--include/linux/nvme.h5
2 files changed, 69 insertions, 10 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index dbd2103533c1..40908a06bd5e 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -1647,6 +1647,56 @@ static void nvme_release_instance(struct nvme_dev *dev)
1647 spin_unlock(&dev_list_lock); 1647 spin_unlock(&dev_list_lock);
1648} 1648}
1649 1649
1650static void nvme_free_dev(struct kref *kref)
1651{
1652 struct nvme_dev *dev = container_of(kref, struct nvme_dev, kref);
1653 nvme_dev_remove(dev);
1654 pci_disable_msix(dev->pci_dev);
1655 iounmap(dev->bar);
1656 nvme_release_instance(dev);
1657 nvme_release_prp_pools(dev);
1658 pci_disable_device(dev->pci_dev);
1659 pci_release_regions(dev->pci_dev);
1660 kfree(dev->queues);
1661 kfree(dev->entry);
1662 kfree(dev);
1663}
1664
1665static int nvme_dev_open(struct inode *inode, struct file *f)
1666{
1667 struct nvme_dev *dev = container_of(f->private_data, struct nvme_dev,
1668 miscdev);
1669 kref_get(&dev->kref);
1670 f->private_data = dev;
1671 return 0;
1672}
1673
1674static int nvme_dev_release(struct inode *inode, struct file *f)
1675{
1676 struct nvme_dev *dev = f->private_data;
1677 kref_put(&dev->kref, nvme_free_dev);
1678 return 0;
1679}
1680
1681static long nvme_dev_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
1682{
1683 struct nvme_dev *dev = f->private_data;
1684 switch (cmd) {
1685 case NVME_IOCTL_ADMIN_CMD:
1686 return nvme_user_admin_cmd(dev, (void __user *)arg);
1687 default:
1688 return -ENOTTY;
1689 }
1690}
1691
1692static const struct file_operations nvme_dev_fops = {
1693 .owner = THIS_MODULE,
1694 .open = nvme_dev_open,
1695 .release = nvme_dev_release,
1696 .unlocked_ioctl = nvme_dev_ioctl,
1697 .compat_ioctl = nvme_dev_ioctl,
1698};
1699
1650static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id) 1700static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1651{ 1701{
1652 int bars, result = -ENOMEM; 1702 int bars, result = -ENOMEM;
@@ -1705,8 +1755,20 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1705 if (result) 1755 if (result)
1706 goto delete; 1756 goto delete;
1707 1757
1758 scnprintf(dev->name, sizeof(dev->name), "nvme%d", dev->instance);
1759 dev->miscdev.minor = MISC_DYNAMIC_MINOR;
1760 dev->miscdev.parent = &pdev->dev;
1761 dev->miscdev.name = dev->name;
1762 dev->miscdev.fops = &nvme_dev_fops;
1763 result = misc_register(&dev->miscdev);
1764 if (result)
1765 goto remove;
1766
1767 kref_init(&dev->kref);
1708 return 0; 1768 return 0;
1709 1769
1770 remove:
1771 nvme_dev_remove(dev);
1710 delete: 1772 delete:
1711 spin_lock(&dev_list_lock); 1773 spin_lock(&dev_list_lock);
1712 list_del(&dev->node); 1774 list_del(&dev->node);
@@ -1732,16 +1794,8 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1732static void nvme_remove(struct pci_dev *pdev) 1794static void nvme_remove(struct pci_dev *pdev)
1733{ 1795{
1734 struct nvme_dev *dev = pci_get_drvdata(pdev); 1796 struct nvme_dev *dev = pci_get_drvdata(pdev);
1735 nvme_dev_remove(dev); 1797 misc_deregister(&dev->miscdev);
1736 pci_disable_msix(pdev); 1798 kref_put(&dev->kref, nvme_free_dev);
1737 iounmap(dev->bar);
1738 nvme_release_instance(dev);
1739 nvme_release_prp_pools(dev);
1740 pci_disable_device(pdev);
1741 pci_release_regions(pdev);
1742 kfree(dev->queues);
1743 kfree(dev->entry);
1744 kfree(dev);
1745} 1799}
1746 1800
1747/* These functions are yet to be implemented */ 1801/* These functions are yet to be implemented */
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 7ae7ecfc0947..9b6fba872f47 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -507,6 +507,8 @@ struct nvme_admin_cmd {
507 507
508#ifdef __KERNEL__ 508#ifdef __KERNEL__
509#include <linux/pci.h> 509#include <linux/pci.h>
510#include <linux/miscdevice.h>
511#include <linux/kref.h>
510 512
511#define NVME_IO_TIMEOUT (5 * HZ) 513#define NVME_IO_TIMEOUT (5 * HZ)
512 514
@@ -527,6 +529,9 @@ struct nvme_dev {
527 struct msix_entry *entry; 529 struct msix_entry *entry;
528 struct nvme_bar __iomem *bar; 530 struct nvme_bar __iomem *bar;
529 struct list_head namespaces; 531 struct list_head namespaces;
532 struct kref kref;
533 struct miscdevice miscdev;
534 char name[12];
530 char serial[20]; 535 char serial[20];
531 char model[40]; 536 char model[40];
532 char firmware_rev[8]; 537 char firmware_rev[8];