mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
vdpa: Enable user to query vdpa device info
Enable user to query vdpa device information. $ vdpa dev add mgmtdev vdpasim_net name foo2 Show the newly created vdpa device by its name: $ vdpa dev show foo2 foo2: type network mgmtdev vdpasim_net vendor_id 0 max_vqs 2 max_vq_size 256 $ vdpa dev show foo2 -jp { "dev": { "foo2": { "type": "network", "mgmtdev": "vdpasim_net", "vendor_id": 0, "max_vqs": 2, "max_vq_size": 256 } } } Signed-off-by: Parav Pandit <parav@nvidia.com> Reviewed-by: Eli Cohen <elic@nvidia.com> Reviewed-by: Jason Wang <jasowang@redhat.com> Link: https://lore.kernel.org/r/20210105103203.82508-6-parav@nvidia.com Including a memory leak fix: Link: https://lore.kernel.org/r/20210217060614.59561-1-parav@nvidia.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
903f7bcaed
commit
bc0d90ee02
@ -478,6 +478,131 @@ dev_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
vdpa_dev_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags, struct netlink_ext_ack *extack)
|
||||
{
|
||||
u16 max_vq_size;
|
||||
u32 device_id;
|
||||
u32 vendor_id;
|
||||
void *hdr;
|
||||
int err;
|
||||
|
||||
hdr = genlmsg_put(msg, portid, seq, &vdpa_nl_family, flags, VDPA_CMD_DEV_NEW);
|
||||
if (!hdr)
|
||||
return -EMSGSIZE;
|
||||
|
||||
err = vdpa_nl_mgmtdev_handle_fill(msg, vdev->mdev);
|
||||
if (err)
|
||||
goto msg_err;
|
||||
|
||||
device_id = vdev->config->get_device_id(vdev);
|
||||
vendor_id = vdev->config->get_vendor_id(vdev);
|
||||
max_vq_size = vdev->config->get_vq_num_max(vdev);
|
||||
|
||||
err = -EMSGSIZE;
|
||||
if (nla_put_string(msg, VDPA_ATTR_DEV_NAME, dev_name(&vdev->dev)))
|
||||
goto msg_err;
|
||||
if (nla_put_u32(msg, VDPA_ATTR_DEV_ID, device_id))
|
||||
goto msg_err;
|
||||
if (nla_put_u32(msg, VDPA_ATTR_DEV_VENDOR_ID, vendor_id))
|
||||
goto msg_err;
|
||||
if (nla_put_u32(msg, VDPA_ATTR_DEV_MAX_VQS, vdev->nvqs))
|
||||
goto msg_err;
|
||||
if (nla_put_u16(msg, VDPA_ATTR_DEV_MAX_VQ_SIZE, max_vq_size))
|
||||
goto msg_err;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return 0;
|
||||
|
||||
msg_err:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int vdpa_nl_cmd_dev_get_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct vdpa_device *vdev;
|
||||
struct sk_buff *msg;
|
||||
const char *devname;
|
||||
struct device *dev;
|
||||
int err;
|
||||
|
||||
if (!info->attrs[VDPA_ATTR_DEV_NAME])
|
||||
return -EINVAL;
|
||||
devname = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]);
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&vdpa_dev_mutex);
|
||||
dev = bus_find_device(&vdpa_bus, NULL, devname, vdpa_name_match);
|
||||
if (!dev) {
|
||||
NL_SET_ERR_MSG_MOD(info->extack, "device not found");
|
||||
err = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
vdev = container_of(dev, struct vdpa_device, dev);
|
||||
if (!vdev->mdev) {
|
||||
err = -EINVAL;
|
||||
goto mdev_err;
|
||||
}
|
||||
err = vdpa_dev_fill(vdev, msg, info->snd_portid, info->snd_seq, 0, info->extack);
|
||||
if (!err)
|
||||
err = genlmsg_reply(msg, info);
|
||||
mdev_err:
|
||||
put_device(dev);
|
||||
err:
|
||||
mutex_unlock(&vdpa_dev_mutex);
|
||||
if (err)
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct vdpa_dev_dump_info {
|
||||
struct sk_buff *msg;
|
||||
struct netlink_callback *cb;
|
||||
int start_idx;
|
||||
int idx;
|
||||
};
|
||||
|
||||
static int vdpa_dev_dump(struct device *dev, void *data)
|
||||
{
|
||||
struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev);
|
||||
struct vdpa_dev_dump_info *info = data;
|
||||
int err;
|
||||
|
||||
if (!vdev->mdev)
|
||||
return 0;
|
||||
if (info->idx < info->start_idx) {
|
||||
info->idx++;
|
||||
return 0;
|
||||
}
|
||||
err = vdpa_dev_fill(vdev, info->msg, NETLINK_CB(info->cb->skb).portid,
|
||||
info->cb->nlh->nlmsg_seq, NLM_F_MULTI, info->cb->extack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
info->idx++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vdpa_nl_cmd_dev_get_dumpit(struct sk_buff *msg, struct netlink_callback *cb)
|
||||
{
|
||||
struct vdpa_dev_dump_info info;
|
||||
|
||||
info.msg = msg;
|
||||
info.cb = cb;
|
||||
info.start_idx = cb->args[0];
|
||||
info.idx = 0;
|
||||
|
||||
mutex_lock(&vdpa_dev_mutex);
|
||||
bus_for_each_dev(&vdpa_bus, NULL, &info, vdpa_dev_dump);
|
||||
mutex_unlock(&vdpa_dev_mutex);
|
||||
cb->args[0] = info.idx;
|
||||
return msg->len;
|
||||
}
|
||||
|
||||
static const struct nla_policy vdpa_nl_policy[VDPA_ATTR_MAX + 1] = {
|
||||
[VDPA_ATTR_MGMTDEV_BUS_NAME] = { .type = NLA_NUL_STRING },
|
||||
[VDPA_ATTR_MGMTDEV_DEV_NAME] = { .type = NLA_STRING },
|
||||
@ -503,6 +628,12 @@ static const struct genl_ops vdpa_nl_ops[] = {
|
||||
.doit = vdpa_nl_cmd_dev_del_set_doit,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = VDPA_CMD_DEV_GET,
|
||||
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
|
||||
.doit = vdpa_nl_cmd_dev_get_doit,
|
||||
.dumpit = vdpa_nl_cmd_dev_get_dumpit,
|
||||
},
|
||||
};
|
||||
|
||||
static struct genl_family vdpa_nl_family __ro_after_init = {
|
||||
|
@ -16,6 +16,7 @@ enum vdpa_command {
|
||||
VDPA_CMD_MGMTDEV_GET, /* can dump */
|
||||
VDPA_CMD_DEV_NEW,
|
||||
VDPA_CMD_DEV_DEL,
|
||||
VDPA_CMD_DEV_GET, /* can dump */
|
||||
};
|
||||
|
||||
enum vdpa_attr {
|
||||
@ -27,6 +28,10 @@ enum vdpa_attr {
|
||||
VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */
|
||||
|
||||
VDPA_ATTR_DEV_NAME, /* string */
|
||||
VDPA_ATTR_DEV_ID, /* u32 */
|
||||
VDPA_ATTR_DEV_VENDOR_ID, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQS, /* u32 */
|
||||
VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */
|
||||
|
||||
/* new attributes must be added above here */
|
||||
VDPA_ATTR_MAX,
|
||||
|
Loading…
Reference in New Issue
Block a user