From patchwork Wed Jul 1 16:29:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nastya Vicodin X-Patchwork-Id: 240631 List-Id: U-Boot discussion From: vicooodin at gmail.com (Anastasiia Lukianenko) Date: Wed, 1 Jul 2020 19:29:55 +0300 Subject: [PATCH 13/17] xen: pvblock: Enumerate virtual block devices In-Reply-To: <20200701162959.9814-1-vicooodin@gmail.com> References: <20200701162959.9814-1-vicooodin@gmail.com> Message-ID: <20200701162959.9814-14-vicooodin@gmail.com> From: Anastasiia Lukianenko Enumerate Xen virtual block devices found in XenStore and instantiate pvblock devices. Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Anastasiia Lukianenko Reviewed-by: Simon Glass --- drivers/xen/pvblock.c | 112 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c index 057add9753..6ce0ae97c3 100644 --- a/drivers/xen/pvblock.c +++ b/drivers/xen/pvblock.c @@ -7,6 +7,10 @@ #include #include #include +#include +#include + +#include #define DRV_NAME "pvblock" #define DRV_NAME_BLK "pvblock_blk" @@ -15,6 +19,10 @@ struct blkfront_dev { char dummy; }; +struct blkfront_platdata { + unsigned int devid; +}; + static int init_blkfront(unsigned int devid, struct blkfront_dev *dev) { return 0; @@ -38,15 +46,40 @@ ulong pvblock_blk_write(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt, static int pvblock_blk_bind(struct udevice *udev) { + struct blk_desc *desc = dev_get_uclass_platdata(udev); + int devnum; + + desc->if_type = IF_TYPE_PVBLOCK; + /* + * Initialize the devnum to -ENODEV. This is to make sure that + * blk_next_free_devnum() works as expected, since the default + * value 0 is a valid devnum. + */ + desc->devnum = -ENODEV; + devnum = blk_next_free_devnum(IF_TYPE_PVBLOCK); + if (devnum < 0) + return devnum; + desc->devnum = devnum; + desc->part_type = PART_TYPE_UNKNOWN; + desc->bdev = udev; + + strncpy(desc->vendor, "Xen", sizeof(desc->vendor)); + strncpy(desc->revision, "1", sizeof(desc->revision)); + strncpy(desc->product, "Virtual disk", sizeof(desc->product)); + return 0; } static int pvblock_blk_probe(struct udevice *udev) { struct blkfront_dev *blk_dev = dev_get_priv(udev); - int ret; + struct blkfront_platdata *platdata = dev_get_platdata(udev); + int ret, devid; - ret = init_blkfront(0, blk_dev); + devid = platdata->devid; + free(platdata); + + ret = init_blkfront(devid, blk_dev); if (ret < 0) return ret; return 0; @@ -80,6 +113,68 @@ U_BOOT_DRIVER(pvblock_blk) = { * Para-virtual block device class *******************************************************************************/ +typedef int (*enum_vbd_callback)(struct udevice *parent, unsigned int devid); + +static int on_new_vbd(struct udevice *parent, unsigned int devid) +{ + struct driver_info info; + struct udevice *udev; + struct blkfront_platdata *platdata; + int ret; + + debug("New " DRV_NAME_BLK ", device ID %d\n", devid); + + platdata = malloc(sizeof(struct blkfront_platdata)); + if (!platdata) { + printf("Failed to allocate platform data\n"); + return -ENOMEM; + } + + platdata->devid = devid; + + info.name = DRV_NAME_BLK; + info.platdata = platdata; + + ret = device_bind_by_name(parent, false, &info, &udev); + if (ret < 0) { + printf("Failed to bind " DRV_NAME_BLK " to device with ID %d, ret: %d\n", + devid, ret); + free(platdata); + } + return ret; +} + +static int xenbus_enumerate_vbd(struct udevice *udev, enum_vbd_callback clb) +{ + char **dirs, *msg; + int i, ret; + + msg = xenbus_ls(XBT_NIL, "device/vbd", &dirs); + if (msg) { + printf("Failed to read device/vbd directory: %s\n", msg); + free(msg); + return -ENODEV; + } + + for (i = 0; dirs[i]; i++) { + int devid; + + sscanf(dirs[i], "%d", &devid); + ret = clb(udev, devid); + if (ret < 0) + goto fail; + + free(dirs[i]); + } + ret = 0; + +fail: + for (; dirs[i]; i++) + free(dirs[i]); + free(dirs); + return ret; +} + void pvblock_init(void) { struct driver_info info; @@ -106,6 +201,19 @@ void pvblock_init(void) static int pvblock_probe(struct udevice *udev) { + struct uclass *uc; + int ret; + + if (xenbus_enumerate_vbd(udev, on_new_vbd) < 0) + return -ENODEV; + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + uclass_foreach_dev_probe(UCLASS_BLK, udev) { + if (_ret) + return _ret; + }; return 0; }