Skip to content

Commit

Permalink
vdpa_sim: move buffer allocation in the devices
Browse files Browse the repository at this point in the history
Currently, the vdpa_sim core does not use the buffer, but only
allocates it.

The buffer is used by devices differently, and some future devices
may not use it. So let's move all its management inside the devices.

Add a new `free` device callback called to clean up the resources
allocated by the device.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Message-Id: <20230407133658.66339-2-sgarzare@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
Stefano Garzarella authored and Michael S. Tsirkin committed Apr 21, 2023
1 parent 5b250fa commit 112f23c
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 21 deletions.
7 changes: 2 additions & 5 deletions drivers/vdpa/vdpa_sim/vdpa_sim.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,6 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr,
for (i = 0; i < vdpasim->dev_attr.nas; i++)
vhost_iotlb_init(&vdpasim->iommu[i], max_iotlb_entries, 0);

vdpasim->buffer = kvmalloc(dev_attr->buffer_size, GFP_KERNEL);
if (!vdpasim->buffer)
goto err_iommu;

for (i = 0; i < dev_attr->nvqs; i++)
vringh_set_iotlb(&vdpasim->vqs[i].vring, &vdpasim->iommu[0],
&vdpasim->iommu_lock);
Expand Down Expand Up @@ -714,7 +710,8 @@ static void vdpasim_free(struct vdpa_device *vdpa)
vringh_kiov_cleanup(&vdpasim->vqs[i].in_iov);
}

kvfree(vdpasim->buffer);
vdpasim->dev_attr.free(vdpasim);

for (i = 0; i < vdpasim->dev_attr.nas; i++)
vhost_iotlb_reset(&vdpasim->iommu[i]);
kfree(vdpasim->iommu);
Expand Down
3 changes: 1 addition & 2 deletions drivers/vdpa/vdpa_sim/vdpa_sim.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct vdpasim_dev_attr {
u64 supported_features;
size_t alloc_size;
size_t config_size;
size_t buffer_size;
int nvqs;
u32 id;
u32 ngroups;
Expand All @@ -51,6 +50,7 @@ struct vdpasim_dev_attr {
int (*get_stats)(struct vdpasim *vdpasim, u16 idx,
struct sk_buff *msg,
struct netlink_ext_ack *extack);
void (*free)(struct vdpasim *vdpasim);
};

/* State of each vdpasim device */
Expand All @@ -67,7 +67,6 @@ struct vdpasim {
void *config;
struct vhost_iotlb *iommu;
bool *iommu_pt;
void *buffer;
u32 status;
u32 generation;
u64 features;
Expand Down
40 changes: 33 additions & 7 deletions drivers/vdpa/vdpa_sim/vdpa_sim_blk.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
#define VDPASIM_BLK_AS_NUM 1
#define VDPASIM_BLK_GROUP_NUM 1

struct vdpasim_blk {
struct vdpasim vdpasim;
void *buffer;
};

static struct vdpasim_blk *sim_to_blk(struct vdpasim *vdpasim)
{
return container_of(vdpasim, struct vdpasim_blk, vdpasim);
}

static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim";

static bool vdpasim_blk_check_range(struct vdpasim *vdpasim, u64 start_sector,
Expand Down Expand Up @@ -78,6 +88,7 @@ static bool vdpasim_blk_check_range(struct vdpasim *vdpasim, u64 start_sector,
static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
struct vdpasim_virtqueue *vq)
{
struct vdpasim_blk *blk = sim_to_blk(vdpasim);
size_t pushed = 0, to_pull, to_push;
struct virtio_blk_outhdr hdr;
bool handled = false;
Expand Down Expand Up @@ -144,8 +155,7 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
}

bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov,
vdpasim->buffer + offset,
to_push);
blk->buffer + offset, to_push);
if (bytes < 0) {
dev_dbg(&vdpasim->vdpa.dev,
"vringh_iov_push_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
Expand All @@ -166,8 +176,7 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
}

bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov,
vdpasim->buffer + offset,
to_pull);
blk->buffer + offset, to_pull);
if (bytes < 0) {
dev_dbg(&vdpasim->vdpa.dev,
"vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n",
Expand Down Expand Up @@ -247,7 +256,7 @@ static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim,
}

if (type == VIRTIO_BLK_T_WRITE_ZEROES) {
memset(vdpasim->buffer + offset, 0,
memset(blk->buffer + offset, 0,
num_sectors << SECTOR_SHIFT);
}

Expand Down Expand Up @@ -353,6 +362,13 @@ static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config)

}

static void vdpasim_blk_free(struct vdpasim *vdpasim)
{
struct vdpasim_blk *blk = sim_to_blk(vdpasim);

kvfree(blk->buffer);
}

static void vdpasim_blk_mgmtdev_release(struct device *dev)
{
}
Expand All @@ -366,6 +382,7 @@ static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
const struct vdpa_dev_set_config *config)
{
struct vdpasim_dev_attr dev_attr = {};
struct vdpasim_blk *blk;
struct vdpasim *simdev;
int ret;

Expand All @@ -376,16 +393,25 @@ static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
dev_attr.nvqs = VDPASIM_BLK_VQ_NUM;
dev_attr.ngroups = VDPASIM_BLK_GROUP_NUM;
dev_attr.nas = VDPASIM_BLK_AS_NUM;
dev_attr.alloc_size = sizeof(struct vdpasim);
dev_attr.alloc_size = sizeof(struct vdpasim_blk);
dev_attr.config_size = sizeof(struct virtio_blk_config);
dev_attr.get_config = vdpasim_blk_get_config;
dev_attr.work_fn = vdpasim_blk_work;
dev_attr.buffer_size = VDPASIM_BLK_CAPACITY << SECTOR_SHIFT;
dev_attr.free = vdpasim_blk_free;

simdev = vdpasim_create(&dev_attr, config);
if (IS_ERR(simdev))
return PTR_ERR(simdev);

blk = sim_to_blk(simdev);

blk->buffer = kvmalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT,
GFP_KERNEL);
if (!blk->buffer) {
ret = -ENOMEM;
goto put_dev;
}

ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_BLK_VQ_NUM);
if (ret)
goto put_dev;
Expand Down
28 changes: 21 additions & 7 deletions drivers/vdpa/vdpa_sim/vdpa_sim_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct vdpasim_net{
struct vdpasim_dataq_stats tx_stats;
struct vdpasim_dataq_stats rx_stats;
struct vdpasim_cq_stats cq_stats;
void *buffer;
};

static struct vdpasim_net *sim_to_net(struct vdpasim *vdpasim)
Expand Down Expand Up @@ -87,14 +88,15 @@ static bool receive_filter(struct vdpasim *vdpasim, size_t len)
size_t hdr_len = modern ? sizeof(struct virtio_net_hdr_v1) :
sizeof(struct virtio_net_hdr);
struct virtio_net_config *vio_config = vdpasim->config;
struct vdpasim_net *net = sim_to_net(vdpasim);

if (len < ETH_ALEN + hdr_len)
return false;

if (is_broadcast_ether_addr(vdpasim->buffer + hdr_len) ||
is_multicast_ether_addr(vdpasim->buffer + hdr_len))
if (is_broadcast_ether_addr(net->buffer + hdr_len) ||
is_multicast_ether_addr(net->buffer + hdr_len))
return true;
if (!strncmp(vdpasim->buffer + hdr_len, vio_config->mac, ETH_ALEN))
if (!strncmp(net->buffer + hdr_len, vio_config->mac, ETH_ALEN))
return true;

return false;
Expand Down Expand Up @@ -225,8 +227,7 @@ static void vdpasim_net_work(struct vdpasim *vdpasim)

++tx_pkts;
read = vringh_iov_pull_iotlb(&txq->vring, &txq->out_iov,
vdpasim->buffer,
PAGE_SIZE);
net->buffer, PAGE_SIZE);

tx_bytes += read;

Expand All @@ -245,7 +246,7 @@ static void vdpasim_net_work(struct vdpasim *vdpasim)
}

write = vringh_iov_push_iotlb(&rxq->vring, &rxq->in_iov,
vdpasim->buffer, read);
net->buffer, read);
if (write <= 0) {
++rx_errors;
break;
Expand Down Expand Up @@ -427,6 +428,13 @@ static void vdpasim_net_setup_config(struct vdpasim *vdpasim,
vio_config->mtu = cpu_to_vdpasim16(vdpasim, 1500);
}

static void vdpasim_net_free(struct vdpasim *vdpasim)
{
struct vdpasim_net *net = sim_to_net(vdpasim);

kvfree(net->buffer);
}

static void vdpasim_net_mgmtdev_release(struct device *dev)
{
}
Expand Down Expand Up @@ -456,7 +464,7 @@ static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
dev_attr.get_config = vdpasim_net_get_config;
dev_attr.work_fn = vdpasim_net_work;
dev_attr.get_stats = vdpasim_net_get_stats;
dev_attr.buffer_size = PAGE_SIZE;
dev_attr.free = vdpasim_net_free;

simdev = vdpasim_create(&dev_attr, config);
if (IS_ERR(simdev))
Expand All @@ -470,6 +478,12 @@ static int vdpasim_net_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
u64_stats_init(&net->rx_stats.syncp);
u64_stats_init(&net->cq_stats.syncp);

net->buffer = kvmalloc(PAGE_SIZE, GFP_KERNEL);
if (!net->buffer) {
ret = -ENOMEM;
goto reg_err;
}

/*
* Initialization must be completed before this call, since it can
* connect the device to the vDPA bus, so requests can arrive after
Expand Down

0 comments on commit 112f23c

Please sign in to comment.