^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * virtio_pmem.c: Virtio pmem Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Discovers persistent memory range information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * from host and registers the virtual pmem device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * with libnvdimm core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "virtio_pmem.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "nd.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static struct virtio_device_id id_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) { VIRTIO_ID_PMEM, VIRTIO_DEV_ANY_ID },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) { 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Initialize virt queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int init_vq(struct virtio_pmem *vpmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* single vq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) vpmem->req_vq = virtio_find_single_vq(vpmem->vdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) virtio_pmem_host_ack, "flush_queue");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (IS_ERR(vpmem->req_vq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return PTR_ERR(vpmem->req_vq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) spin_lock_init(&vpmem->pmem_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) INIT_LIST_HEAD(&vpmem->req_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int virtio_pmem_probe(struct virtio_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct nd_region_desc ndr_desc = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int nid = dev_to_node(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct nd_region *nd_region;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct virtio_pmem *vpmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) if (!vdev->config->get) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) dev_err(&vdev->dev, "%s failure: config access disabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) vpmem = devm_kzalloc(&vdev->dev, sizeof(*vpmem), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (!vpmem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) vpmem->vdev = vdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) vdev->priv = vpmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) err = init_vq(vpmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dev_err(&vdev->dev, "failed to initialize virtio pmem vq's\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) goto out_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) start, &vpmem->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) virtio_cread_le(vpmem->vdev, struct virtio_pmem_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) size, &vpmem->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) res.start = vpmem->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) res.end = vpmem->start + vpmem->size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) vpmem->nd_desc.provider_name = "virtio-pmem";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) vpmem->nd_desc.module = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) vpmem->nvdimm_bus = nvdimm_bus_register(&vdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) &vpmem->nd_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!vpmem->nvdimm_bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) dev_err(&vdev->dev, "failed to register device with nvdimm_bus\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) goto out_vq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) dev_set_drvdata(&vdev->dev, vpmem->nvdimm_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ndr_desc.res = &res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ndr_desc.numa_node = nid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ndr_desc.flush = async_pmem_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) nd_region = nvdimm_pmem_region_create(vpmem->nvdimm_bus, &ndr_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!nd_region) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev_err(&vdev->dev, "failed to create nvdimm region\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) err = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) goto out_nd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) nd_region->provider_data = dev_to_virtio(nd_region->dev.parent->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) out_nd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) nvdimm_bus_unregister(vpmem->nvdimm_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) out_vq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) vdev->config->del_vqs(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static void virtio_pmem_remove(struct virtio_device *vdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct nvdimm_bus *nvdimm_bus = dev_get_drvdata(&vdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) nvdimm_bus_unregister(nvdimm_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) vdev->config->del_vqs(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) vdev->config->reset(vdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct virtio_driver virtio_pmem_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .driver.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .driver.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .id_table = id_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .probe = virtio_pmem_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .remove = virtio_pmem_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) module_virtio_driver(virtio_pmem_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) MODULE_DEVICE_TABLE(virtio, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) MODULE_DESCRIPTION("Virtio pmem driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) MODULE_LICENSE("GPL");