Message ID | 20220117092921.1573-4-longpeng2@huawei.com (mailing list archive) |
---|---|
State | RFC |
Headers | show |
Series | vdpa: add two ioctl commands to support generic vDPA | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
在 2022/1/17 下午5:29, Longpeng(Mike) 写道: > From: Longpeng <longpeng2@huawei.com> > > Introduces the control virtqueue support for vdpasim_net, based on > Jason's RFC [1]. > > [1] https://patchwork.kernel.org/project/kvm/patch/20200924032125.18619-25-jasowang@redhat.com/ I'd expect to implement the receive filter as well[1]. This gives us a chance to test this. Thanks [1] https://lkml.org/lkml/2020/9/23/1269 > > Signed-off-by: Longpeng <longpeng2@huawei.com> > --- > drivers/vdpa/vdpa_sim/vdpa_sim_net.c | 83 +++++++++++++++++++++++++++- > 1 file changed, 81 insertions(+), 2 deletions(-) > > diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c > index 76dd24abc791..e9e388fd3cff 100644 > --- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c > +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c > @@ -26,9 +26,85 @@ > #define DRV_LICENSE "GPL v2" > > #define VDPASIM_NET_FEATURES (VDPASIM_FEATURES | \ > - (1ULL << VIRTIO_NET_F_MAC)) > + (1ULL << VIRTIO_NET_F_MAC) | \ > + (1ULL << VIRTIO_NET_F_CTRL_VQ) | \ > + (1ULL << VIRTIO_NET_F_CTRL_MAC_ADDR)) > > -#define VDPASIM_NET_VQ_NUM 2 > +#define VDPASIM_NET_VQ_NUM 3 > + > +virtio_net_ctrl_ack vdpasim_net_handle_ctrl_mac(struct vdpasim *vdpasim, > + u8 cmd) > +{ > + struct vdpasim_virtqueue *cvq = &vdpasim->vqs[2]; > + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; > + struct virtio_net_config *config = vdpasim->config; > + size_t read; > + > + switch (cmd) { > + case VIRTIO_NET_CTRL_MAC_ADDR_SET: > + read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->out_iov, > + (void *)config->mac, ETH_ALEN); > + if (read == ETH_ALEN) > + status = VIRTIO_NET_OK; > + break; > + default: > + break; > + } > + > + return status; > +} > + > +static void vdpasim_net_handle_cvq(struct vdpasim *vdpasim) > +{ > + struct vdpasim_virtqueue *cvq = &vdpasim->vqs[2]; > + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; > + struct virtio_net_ctrl_hdr ctrl; > + size_t read, write; > + int err; > + > + if (!(vdpasim->features & (1ULL << VIRTIO_NET_F_CTRL_VQ))) > + return; > + > + if (!cvq->ready) > + return; > + > + while (true) { > + err = vringh_getdesc_iotlb(&cvq->vring, &cvq->out_iov, &cvq->in_iov, > + &cvq->head, GFP_ATOMIC); > + if (err <= 0) > + break; > + > + read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->in_iov, &ctrl, > + sizeof(ctrl)); > + if (read != sizeof(ctrl)) > + break; > + > + switch (ctrl.class) { > + case VIRTIO_NET_CTRL_MAC: > + status = vdpasim_net_handle_ctrl_mac(vdpasim, ctrl.cmd); > + break; > + default: > + break; > + } > + > + /* Make sure data is wrote before advancing index */ > + smp_wmb(); > + > + write = vringh_iov_push_iotlb(&cvq->vring, &cvq->out_iov, > + &status, sizeof (status)); > + vringh_complete_iotlb(&cvq->vring, cvq->head, write); > + vringh_kiov_cleanup(&cvq->in_iov); > + vringh_kiov_cleanup(&cvq->out_iov); > + > + /* Make sure used is visible before rasing the interrupt. */ > + smp_wmb(); > + > + local_bh_disable(); > + if (vringh_need_notify_iotlb(&cvq->vring) > 0) > + vringh_notify(&cvq->vring); > + local_bh_enable(); > + } > +} > > static void vdpasim_net_work(struct work_struct *work) > { > @@ -42,6 +118,9 @@ static void vdpasim_net_work(struct work_struct *work) > > spin_lock(&vdpasim->lock); > > + /* process ctrl vq first */ > + vdpasim_net_handle_cvq(vdpasim); > + > if (!(vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK)) > goto out; >
diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c index 76dd24abc791..e9e388fd3cff 100644 --- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c +++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c @@ -26,9 +26,85 @@ #define DRV_LICENSE "GPL v2" #define VDPASIM_NET_FEATURES (VDPASIM_FEATURES | \ - (1ULL << VIRTIO_NET_F_MAC)) + (1ULL << VIRTIO_NET_F_MAC) | \ + (1ULL << VIRTIO_NET_F_CTRL_VQ) | \ + (1ULL << VIRTIO_NET_F_CTRL_MAC_ADDR)) -#define VDPASIM_NET_VQ_NUM 2 +#define VDPASIM_NET_VQ_NUM 3 + +virtio_net_ctrl_ack vdpasim_net_handle_ctrl_mac(struct vdpasim *vdpasim, + u8 cmd) +{ + struct vdpasim_virtqueue *cvq = &vdpasim->vqs[2]; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + struct virtio_net_config *config = vdpasim->config; + size_t read; + + switch (cmd) { + case VIRTIO_NET_CTRL_MAC_ADDR_SET: + read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->out_iov, + (void *)config->mac, ETH_ALEN); + if (read == ETH_ALEN) + status = VIRTIO_NET_OK; + break; + default: + break; + } + + return status; +} + +static void vdpasim_net_handle_cvq(struct vdpasim *vdpasim) +{ + struct vdpasim_virtqueue *cvq = &vdpasim->vqs[2]; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + struct virtio_net_ctrl_hdr ctrl; + size_t read, write; + int err; + + if (!(vdpasim->features & (1ULL << VIRTIO_NET_F_CTRL_VQ))) + return; + + if (!cvq->ready) + return; + + while (true) { + err = vringh_getdesc_iotlb(&cvq->vring, &cvq->out_iov, &cvq->in_iov, + &cvq->head, GFP_ATOMIC); + if (err <= 0) + break; + + read = vringh_iov_pull_iotlb(&cvq->vring, &cvq->in_iov, &ctrl, + sizeof(ctrl)); + if (read != sizeof(ctrl)) + break; + + switch (ctrl.class) { + case VIRTIO_NET_CTRL_MAC: + status = vdpasim_net_handle_ctrl_mac(vdpasim, ctrl.cmd); + break; + default: + break; + } + + /* Make sure data is wrote before advancing index */ + smp_wmb(); + + write = vringh_iov_push_iotlb(&cvq->vring, &cvq->out_iov, + &status, sizeof (status)); + vringh_complete_iotlb(&cvq->vring, cvq->head, write); + vringh_kiov_cleanup(&cvq->in_iov); + vringh_kiov_cleanup(&cvq->out_iov); + + /* Make sure used is visible before rasing the interrupt. */ + smp_wmb(); + + local_bh_disable(); + if (vringh_need_notify_iotlb(&cvq->vring) > 0) + vringh_notify(&cvq->vring); + local_bh_enable(); + } +} static void vdpasim_net_work(struct work_struct *work) { @@ -42,6 +118,9 @@ static void vdpasim_net_work(struct work_struct *work) spin_lock(&vdpasim->lock); + /* process ctrl vq first */ + vdpasim_net_handle_cvq(vdpasim); + if (!(vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK)) goto out;