0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "virtio_pmem.h"
0010 #include "nd.h"
0011
0012 static struct virtio_device_id id_table[] = {
0013 { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
0014 { 0 },
0015 };
0016
0017
0018 static int init_vq(struct virtio_pmem *vpmem)
0019 {
0020
0021 vpmem->req_vq = virtio_find_single_vq(vpmem->vdev,
0022 virtio_pmem_host_ack, "flush_queue");
0023 if (IS_ERR(vpmem->req_vq))
0024 return PTR_ERR(vpmem->req_vq);
0025
0026 spin_lock_init(&vpmem->pmem_lock);
0027 INIT_LIST_HEAD(&vpmem->req_list);
0028
0029 return 0;
0030 };
0031
0032 static int virtio_pmem_probe(struct virtio_device *vdev)
0033 {
0034 struct nd_region_desc ndr_desc = {};
0035 int nid = dev_to_node(&vdev->dev);
0036 struct nd_region *nd_region;
0037 struct virtio_pmem *vpmem;
0038 struct resource res;
0039 int err = 0;
0040
0041 if (!vdev->config->get) {
0042 dev_err(&vdev->dev, "%s failure: config access disabled\n",
0043 __func__);
0044 return -EINVAL;
0045 }
0046
0047 vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem), GFP_KERNEL);
0048 if (!vpmem) {
0049 err = -ENOMEM;
0050 goto out_err;
0051 }
0052
0053 vpmem->vdev = vdev;
0054 vdev->priv = vpmem;
0055 err = init_vq(vpmem);
0056 if (err) {
0057 dev_err(&vdev->dev, "failed to initialize virtio pmem vq's\n");
0058 goto out_err;
0059 }
0060
0061 virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
0062 start, &vpmem->start);
0063 virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
0064 size, &vpmem->size);
0065
0066 res.start = vpmem->start;
0067 res.end = vpmem->start + vpmem->size - 1;
0068 vpmem->nd_desc.provider_name = "virtio-pmem";
0069 vpmem->nd_desc.module = THIS_MODULE;
0070
0071 vpmem->nvdimm_bus = nvdimm_bus_register(&vdev->dev,
0072 &vpmem->nd_desc);
0073 if (!vpmem->nvdimm_bus) {
0074 dev_err(&vdev->dev, "failed to register device with nvdimm_bus\n");
0075 err = -ENXIO;
0076 goto out_vq;
0077 }
0078
0079 dev_set_drvdata(&vdev->dev, vpmem->nvdimm_bus);
0080
0081 ndr_desc.res = &res;
0082 ndr_desc.numa_node = nid;
0083 ndr_desc.flush = async_pmem_flush;
0084 ndr_desc.provider_data = vdev;
0085 set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
0086 set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
0087
0088
0089
0090
0091
0092 virtio_device_ready(vdev);
0093 nd_region = nvdimm_pmem_region_create(vpmem->nvdimm_bus, &ndr_desc);
0094 if (!nd_region) {
0095 dev_err(&vdev->dev, "failed to create nvdimm region\n");
0096 err = -ENXIO;
0097 goto out_nd;
0098 }
0099 return 0;
0100 out_nd:
0101 virtio_reset_device(vdev);
0102 nvdimm_bus_unregister(vpmem->nvdimm_bus);
0103 out_vq:
0104 vdev->config->del_vqs(vdev);
0105 out_err:
0106 return err;
0107 }
0108
0109 static void virtio_pmem_remove(struct virtio_device *vdev)
0110 {
0111 struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
0112
0113 nvdimm_bus_unregister(nvdimm_bus);
0114 vdev->config->del_vqs(vdev);
0115 virtio_reset_device(vdev);
0116 }
0117
0118 static struct virtio_driver virtio_pmem_driver = {
0119 .driver.name = KBUILD_MODNAME,
0120 .driver.owner = THIS_MODULE,
0121 .id_table = id_table,
0122 .probe = virtio_pmem_probe,
0123 .remove = virtio_pmem_remove,
0124 };
0125
0126 module_virtio_driver(virtio_pmem_driver);
0127 MODULE_DEVICE_TABLE(virtio, id_table);
0128 MODULE_DESCRIPTION("Virtio pmem driver");
0129 MODULE_LICENSE("GPL");