virtio_pmem: set device ready in probe()

The NVDIMM region could be available before the virtio_device_ready()
that is called by virtio_dev_probe(). This means the driver tries to
use device before DRIVER_OK which violates the spec, fixing this by
set device ready before the nvdimm_pmem_region_create().

Note that this means the virtio_pmem_host_ack() could be triggered
before the creation of the nd region, this is safe since the pmem_lock
has been initialized and whether or not any available buffer is added
before is validated by virtio_pmem_host_ack().

Fixes 6e84200c0a ("virtio-pmem: Add virtio pmem driver")
Acked-by: Pankaj Gupta <pankaj.gupta@amd.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Message-Id: <20220628083430.61856-2-jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Jason Wang 2022-06-28 16:34:30 +08:00 committed by Michael S. Tsirkin
parent 020e1aede7
commit 5d66322b2b
1 changed files with 7 additions and 0 deletions

View File

@ -84,6 +84,12 @@ static int virtio_pmem_probe(struct virtio_device *vdev)
ndr_desc.provider_data = vdev; ndr_desc.provider_data = vdev;
set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags); set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
set_bit(ND_REGION_ASYNC, &ndr_desc.flags); set_bit(ND_REGION_ASYNC, &ndr_desc.flags);
/*
* The NVDIMM region could be available before the
* virtio_device_ready() that is called by
* virtio_dev_probe(), so we set device ready here.
*/
virtio_device_ready(vdev);
nd_region = nvdimm_pmem_region_create(vpmem->nvdimm_bus, &ndr_desc); nd_region = nvdimm_pmem_region_create(vpmem->nvdimm_bus, &ndr_desc);
if (!nd_region) { if (!nd_region) {
dev_err(&vdev->dev, "failed to create nvdimm region\n"); dev_err(&vdev->dev, "failed to create nvdimm region\n");
@ -92,6 +98,7 @@ static int virtio_pmem_probe(struct virtio_device *vdev)
} }
return 0; return 0;
out_nd: out_nd:
virtio_reset_device(vdev);
nvdimm_bus_unregister(vpmem->nvdimm_bus); nvdimm_bus_unregister(vpmem->nvdimm_bus);
out_vq: out_vq:
vdev->config->del_vqs(vdev); vdev->config->del_vqs(vdev);