Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 19 Mar 2024 15:57:39 +0000 (08:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 19 Mar 2024 15:57:39 +0000 (08:57 -0700)
Pull virtio updates from Michael Tsirkin:

 - Per vq sizes in vdpa

 - Info query for block devices support in vdpa

 - DMA sync callbacks in vduse

 - Fixes, cleanups

* tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: (35 commits)
  virtio_net: rename free_old_xmit_skbs to free_old_xmit
  virtio_net: unify the code for recycling the xmit ptr
  virtio-net: add cond_resched() to the command waiting loop
  virtio-net: convert rx mode setting to use workqueue
  virtio: packed: fix unmap leak for indirect desc table
  vDPA: report virtio-blk flush info to user space
  vDPA: report virtio-block read-only info to user space
  vDPA: report virtio-block write zeroes configuration to user space
  vDPA: report virtio-block discarding configuration to user space
  vDPA: report virtio-block topology info to user space
  vDPA: report virtio-block MQ info to user space
  vDPA: report virtio-block max segments in a request to user space
  vDPA: report virtio-block block-size to user space
  vDPA: report virtio-block max segment size to user space
  vDPA: report virtio-block capacity to user space
  virtio: make virtio_bus const
  vdpa: make vdpa_bus const
  vDPA/ifcvf: implement vdpa_config_ops.get_vq_num_min
  vDPA/ifcvf: get_max_vq_size to return max size
  virtio_vdpa: create vqs with the actual size
  ...

24 files changed:
drivers/net/virtio_net.c
drivers/vdpa/alibaba/eni_vdpa.c
drivers/vdpa/ifcvf/ifcvf_base.c
drivers/vdpa/ifcvf/ifcvf_base.h
drivers/vdpa/ifcvf/ifcvf_main.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/pds/aux_drv.c
drivers/vdpa/pds/vdpa_dev.c
drivers/vdpa/pds/vdpa_dev.h
drivers/vdpa/vdpa.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vdpa/vdpa_user/iova_domain.c
drivers/vdpa/vdpa_user/iova_domain.h
drivers/vdpa/vdpa_user/vduse_dev.c
drivers/vdpa/virtio_pci/vp_vdpa.c
drivers/vhost/net.c
drivers/vhost/vdpa.c
drivers/virtio/virtio.c
drivers/virtio/virtio_ring.c
drivers/virtio/virtio_vdpa.c
include/linux/vdpa.h
include/uapi/linux/vdpa.h
include/uapi/linux/vhost.h
include/uapi/linux/virtio_pci.h

index d7ce4a1011ea2585bca21ab3fb86978f7fee364d..c22d1118a13333702c41d0b11148eb067700965b 100644 (file)
@@ -80,6 +80,11 @@ struct virtnet_stat_desc {
        size_t offset;
 };
 
+struct virtnet_sq_free_stats {
+       u64 packets;
+       u64 bytes;
+};
+
 struct virtnet_sq_stats {
        struct u64_stats_sync syncp;
        u64_stats_t packets;
@@ -304,6 +309,12 @@ struct virtnet_info {
        /* Work struct for config space updates */
        struct work_struct config_work;
 
+       /* Work struct for setting rx mode */
+       struct work_struct rx_mode_work;
+
+       /* OK to queue work setting RX mode? */
+       bool rx_mode_work_enabled;
+
        /* Does the affinity hint is set for virtqueues? */
        bool affinity_hint_set;
 
@@ -366,6 +377,31 @@ static struct xdp_frame *ptr_to_xdp(void *ptr)
        return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
 }
 
+static void __free_old_xmit(struct send_queue *sq, bool in_napi,
+                           struct virtnet_sq_free_stats *stats)
+{
+       unsigned int len;
+       void *ptr;
+
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               ++stats->packets;
+
+               if (!is_xdp_frame(ptr)) {
+                       struct sk_buff *skb = ptr;
+
+                       pr_debug("Sent skb %p\n", skb);
+
+                       stats->bytes += skb->len;
+                       napi_consume_skb(skb, in_napi);
+               } else {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+                       stats->bytes += xdp_get_frame_len(frame);
+                       xdp_return_frame(frame);
+               }
+       }
+}
+
 /* Converting between virtqueue no. and kernel tx/rx queue no.
  * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
  */
@@ -447,6 +483,20 @@ static void disable_delayed_refill(struct virtnet_info *vi)
        spin_unlock_bh(&vi->refill_lock);
 }
 
+static void enable_rx_mode_work(struct virtnet_info *vi)
+{
+       rtnl_lock();
+       vi->rx_mode_work_enabled = true;
+       rtnl_unlock();
+}
+
+static void disable_rx_mode_work(struct virtnet_info *vi)
+{
+       rtnl_lock();
+       vi->rx_mode_work_enabled = false;
+       rtnl_unlock();
+}
+
 static void virtqueue_napi_schedule(struct napi_struct *napi,
                                    struct virtqueue *vq)
 {
@@ -776,39 +826,21 @@ static void virtnet_rq_unmap_free_buf(struct virtqueue *vq, void *buf)
        virtnet_rq_free_buf(vi, rq, buf);
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
+static void free_old_xmit(struct send_queue *sq, bool in_napi)
 {
-       unsigned int len;
-       unsigned int packets = 0;
-       unsigned int bytes = 0;
-       void *ptr;
-
-       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               if (likely(!is_xdp_frame(ptr))) {
-                       struct sk_buff *skb = ptr;
-
-                       pr_debug("Sent skb %p\n", skb);
+       struct virtnet_sq_free_stats stats = {0};
 
-                       bytes += skb->len;
-                       napi_consume_skb(skb, in_napi);
-               } else {
-                       struct xdp_frame *frame = ptr_to_xdp(ptr);
-
-                       bytes += xdp_get_frame_len(frame);
-                       xdp_return_frame(frame);
-               }
-               packets++;
-       }
+       __free_old_xmit(sq, in_napi, &stats);
 
        /* Avoid overhead when no packets have been processed
         * happens when called speculatively from start_xmit.
         */
-       if (!packets)
+       if (!stats.packets)
                return;
 
        u64_stats_update_begin(&sq->stats.syncp);
-       u64_stats_add(&sq->stats.bytes, bytes);
-       u64_stats_add(&sq->stats.packets, packets);
+       u64_stats_add(&sq->stats.bytes, stats.bytes);
+       u64_stats_add(&sq->stats.packets, stats.packets);
        u64_stats_update_end(&sq->stats.syncp);
 }
 
@@ -848,7 +880,7 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
                                virtqueue_napi_schedule(&sq->napi, sq->vq);
                } else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
-                       free_old_xmit_skbs(sq, false);
+                       free_old_xmit(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_subqueue(dev, qnum);
                                virtqueue_disable_cb(sq->vq);
@@ -947,15 +979,12 @@ static int virtnet_xdp_xmit(struct net_device *dev,
                            int n, struct xdp_frame **frames, u32 flags)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       struct virtnet_sq_free_stats stats = {0};
        struct receive_queue *rq = vi->rq;
        struct bpf_prog *xdp_prog;
        struct send_queue *sq;
-       unsigned int len;
-       int packets = 0;
-       int bytes = 0;
        int nxmit = 0;
        int kicks = 0;
-       void *ptr;
        int ret;
        int i;
 
@@ -974,20 +1003,7 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
 
        /* Free up any pending old buffers before queueing new ones. */
-       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               if (likely(is_xdp_frame(ptr))) {
-                       struct xdp_frame *frame = ptr_to_xdp(ptr);
-
-                       bytes += xdp_get_frame_len(frame);
-                       xdp_return_frame(frame);
-               } else {
-                       struct sk_buff *skb = ptr;
-
-                       bytes += skb->len;
-                       napi_consume_skb(skb, false);
-               }
-               packets++;
-       }
+       __free_old_xmit(sq, false, &stats);
 
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
@@ -1007,8 +1023,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
 out:
        u64_stats_update_begin(&sq->stats.syncp);
-       u64_stats_add(&sq->stats.bytes, bytes);
-       u64_stats_add(&sq->stats.packets, packets);
+       u64_stats_add(&sq->stats.bytes, stats.bytes);
+       u64_stats_add(&sq->stats.packets, stats.packets);
        u64_stats_add(&sq->stats.xdp_tx, n);
        u64_stats_add(&sq->stats.xdp_tx_drops, n - nxmit);
        u64_stats_add(&sq->stats.kicks, kicks);
@@ -2160,7 +2176,7 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
 
                do {
                        virtqueue_disable_cb(sq->vq);
-                       free_old_xmit_skbs(sq, true);
+                       free_old_xmit(sq, true);
                } while (unlikely(!virtqueue_enable_cb_delayed(sq->vq)));
 
                if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
@@ -2308,7 +2324,7 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
        txq = netdev_get_tx_queue(vi->dev, index);
        __netif_tx_lock(txq, raw_smp_processor_id());
        virtqueue_disable_cb(sq->vq);
-       free_old_xmit_skbs(sq, true);
+       free_old_xmit(sq, true);
 
        if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
                netif_tx_wake_queue(txq);
@@ -2398,7 +2414,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (use_napi)
                        virtqueue_disable_cb(sq->vq);
 
-               free_old_xmit_skbs(sq, false);
+               free_old_xmit(sq, false);
 
        } while (use_napi && kick &&
               unlikely(!virtqueue_enable_cb_delayed(sq->vq)));
@@ -2550,8 +2566,10 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
         * into the hypervisor, so the request should be handled immediately.
         */
        while (!virtqueue_get_buf(vi->cvq, &tmp) &&
-              !virtqueue_is_broken(vi->cvq))
+              !virtqueue_is_broken(vi->cvq)) {
+               cond_resched();
                cpu_relax();
+       }
 
        return vi->ctrl->status == VIRTIO_NET_OK;
 }
@@ -2706,9 +2724,11 @@ static int virtnet_close(struct net_device *dev)
        return 0;
 }
 
-static void virtnet_set_rx_mode(struct net_device *dev)
+static void virtnet_rx_mode_work(struct work_struct *work)
 {
-       struct virtnet_info *vi = netdev_priv(dev);
+       struct virtnet_info *vi =
+               container_of(work, struct virtnet_info, rx_mode_work);
+       struct net_device *dev = vi->dev;
        struct scatterlist sg[2];
        struct virtio_net_ctrl_mac *mac_data;
        struct netdev_hw_addr *ha;
@@ -2721,6 +2741,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
                return;
 
+       rtnl_lock();
+
        vi->ctrl->promisc = ((dev->flags & IFF_PROMISC) != 0);
        vi->ctrl->allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
 
@@ -2738,14 +2760,19 @@ static void virtnet_set_rx_mode(struct net_device *dev)
                dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
                         vi->ctrl->allmulti ? "en" : "dis");
 
+       netif_addr_lock_bh(dev);
+
        uc_count = netdev_uc_count(dev);
        mc_count = netdev_mc_count(dev);
        /* MAC filter - use one buffer for both lists */
        buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) +
                      (2 * sizeof(mac_data->entries)), GFP_ATOMIC);
        mac_data = buf;
-       if (!buf)
+       if (!buf) {
+               netif_addr_unlock_bh(dev);
+               rtnl_unlock();
                return;
+       }
 
        sg_init_table(sg, 2);
 
@@ -2766,6 +2793,8 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        netdev_for_each_mc_addr(ha, dev)
                memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN);
 
+       netif_addr_unlock_bh(dev);
+
        sg_set_buf(&sg[1], mac_data,
                   sizeof(mac_data->entries) + (mc_count * ETH_ALEN));
 
@@ -2773,9 +2802,19 @@ static void virtnet_set_rx_mode(struct net_device *dev)
                                  VIRTIO_NET_CTRL_MAC_TABLE_SET, sg))
                dev_warn(&dev->dev, "Failed to set MAC filter table.\n");
 
+       rtnl_unlock();
+
        kfree(buf);
 }
 
+static void virtnet_set_rx_mode(struct net_device *dev)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+
+       if (vi->rx_mode_work_enabled)
+               schedule_work(&vi->rx_mode_work);
+}
+
 static int virtnet_vlan_rx_add_vid(struct net_device *dev,
                                   __be16 proto, u16 vid)
 {
@@ -3856,6 +3895,8 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
 
        /* Make sure no work handler is accessing the device */
        flush_work(&vi->config_work);
+       disable_rx_mode_work(vi);
+       flush_work(&vi->rx_mode_work);
 
        netif_tx_lock_bh(vi->dev);
        netif_device_detach(vi->dev);
@@ -3878,6 +3919,7 @@ static int virtnet_restore_up(struct virtio_device *vdev)
        virtio_device_ready(vdev);
 
        enable_delayed_refill(vi);
+       enable_rx_mode_work(vi);
 
        if (netif_running(vi->dev)) {
                err = virtnet_open(vi->dev);
@@ -4676,6 +4718,7 @@ static int virtnet_probe(struct virtio_device *vdev)
        vdev->priv = vi;
 
        INIT_WORK(&vi->config_work, virtnet_config_changed_work);
+       INIT_WORK(&vi->rx_mode_work, virtnet_rx_mode_work);
        spin_lock_init(&vi->refill_lock);
 
        if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) {
@@ -4798,6 +4841,8 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
+       enable_rx_mode_work(vi);
+
        /* serialize netdev register + virtio_device_ready() with ndo_open() */
        rtnl_lock();
 
@@ -4895,6 +4940,8 @@ static void virtnet_remove(struct virtio_device *vdev)
 
        /* Make sure no work handler is accessing the device. */
        flush_work(&vi->config_work);
+       disable_rx_mode_work(vi);
+       flush_work(&vi->rx_mode_work);
 
        unregister_netdev(vi->dev);
 
index cce3d1837104c34f0bf331db33d5a81f64c0a6e7..ad7f3447fe90ccfc6720b2a2e79abbf3986b3391 100644 (file)
@@ -254,6 +254,13 @@ static u16 eni_vdpa_get_vq_num_min(struct vdpa_device *vdpa)
        return vp_legacy_get_queue_size(ldev, 0);
 }
 
+static u16 eni_vdpa_get_vq_size(struct vdpa_device *vdpa, u16 qid)
+{
+       struct virtio_pci_legacy_device *ldev = vdpa_to_ldev(vdpa);
+
+       return vp_legacy_get_queue_size(ldev, qid);
+}
+
 static int eni_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 qid,
                                struct vdpa_vq_state *state)
 {
@@ -416,6 +423,7 @@ static const struct vdpa_config_ops eni_vdpa_ops = {
        .reset          = eni_vdpa_reset,
        .get_vq_num_max = eni_vdpa_get_vq_num_max,
        .get_vq_num_min = eni_vdpa_get_vq_num_min,
+       .get_vq_size    = eni_vdpa_get_vq_size,
        .get_vq_state   = eni_vdpa_get_vq_state,
        .set_vq_state   = eni_vdpa_set_vq_state,
        .set_vq_cb      = eni_vdpa_set_vq_cb,
index 060f837a4f9f762018fd29d52bcb10c91a9436aa..472daa588a9d214aa1518530255afdc9a1919e1f 100644 (file)
@@ -69,20 +69,19 @@ static int ifcvf_read_config_range(struct pci_dev *dev,
        return 0;
 }
 
-static u16 ifcvf_get_vq_size(struct ifcvf_hw *hw, u16 qid)
+u16 ifcvf_get_vq_size(struct ifcvf_hw *hw, u16 qid)
 {
        u16 queue_size;
 
+       if (qid >= hw->nr_vring)
+               return 0;
+
        vp_iowrite16(qid, &hw->common_cfg->queue_select);
        queue_size = vp_ioread16(&hw->common_cfg->queue_size);
 
        return queue_size;
 }
 
-/* This function returns the max allowed safe size for
- * all virtqueues. It is the minimal size that can be
- * suppprted by all virtqueues.
- */
 u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw)
 {
        u16 queue_size, max_size, qid;
@@ -94,7 +93,7 @@ u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw)
                if (!queue_size)
                        continue;
 
-               max_size = min(queue_size, max_size);
+               max_size = max(queue_size, max_size);
        }
 
        return max_size;
index b57849c643f611fc271d894eb24075f99a0c6fed..0f347717021a2eb2d827e11b59e11f9cafb43f5e 100644 (file)
@@ -28,6 +28,7 @@
 #define IFCVF_PCI_MAX_RESOURCE 6
 
 #define IFCVF_LM_BAR                   4
+#define IFCVF_MIN_VQ_SIZE              64
 
 #define IFCVF_ERR(pdev, fmt, ...)      dev_err(&pdev->dev, fmt, ##__VA_ARGS__)
 #define IFCVF_DBG(pdev, fmt, ...)      dev_dbg(&pdev->dev, fmt, ##__VA_ARGS__)
@@ -131,4 +132,5 @@ void ifcvf_set_vq_ready(struct ifcvf_hw *hw, u16 qid, bool ready);
 void ifcvf_set_driver_features(struct ifcvf_hw *hw, u64 features);
 u64 ifcvf_get_driver_features(struct ifcvf_hw *hw);
 u16 ifcvf_get_max_vq_size(struct ifcvf_hw *hw);
+u16 ifcvf_get_vq_size(struct ifcvf_hw *hw, u16 qid);
 #endif /* _IFCVF_H_ */
index e98fa8100f3cc796f2f3b543cadd7f9a694313c7..80d0a046088589a989072d0f2dbe92339a7e9674 100644 (file)
@@ -456,6 +456,11 @@ static u16 ifcvf_vdpa_get_vq_num_max(struct vdpa_device *vdpa_dev)
        return ifcvf_get_max_vq_size(vf);
 }
 
+static u16 ifcvf_vdpa_get_vq_num_min(struct vdpa_device *vdpa_dev)
+{
+       return IFCVF_MIN_VQ_SIZE;
+}
+
 static int ifcvf_vdpa_get_vq_state(struct vdpa_device *vdpa_dev, u16 qid,
                                   struct vdpa_vq_state *state)
 {
@@ -597,6 +602,14 @@ static int ifcvf_vdpa_get_vq_irq(struct vdpa_device *vdpa_dev,
                return -EINVAL;
 }
 
+static u16 ifcvf_vdpa_get_vq_size(struct vdpa_device *vdpa_dev,
+                            u16 qid)
+{
+       struct ifcvf_hw *vf = vdpa_to_vf(vdpa_dev);
+
+       return ifcvf_get_vq_size(vf, qid);
+}
+
 static struct vdpa_notification_area ifcvf_get_vq_notification(struct vdpa_device *vdpa_dev,
                                                               u16 idx)
 {
@@ -624,6 +637,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
        .set_status     = ifcvf_vdpa_set_status,
        .reset          = ifcvf_vdpa_reset,
        .get_vq_num_max = ifcvf_vdpa_get_vq_num_max,
+       .get_vq_num_min = ifcvf_vdpa_get_vq_num_min,
        .get_vq_state   = ifcvf_vdpa_get_vq_state,
        .set_vq_state   = ifcvf_vdpa_set_vq_state,
        .set_vq_cb      = ifcvf_vdpa_set_vq_cb,
@@ -632,6 +646,7 @@ static const struct vdpa_config_ops ifc_vdpa_ops = {
        .set_vq_num     = ifcvf_vdpa_set_vq_num,
        .set_vq_address = ifcvf_vdpa_set_vq_address,
        .get_vq_irq     = ifcvf_vdpa_get_vq_irq,
+       .get_vq_size    = ifcvf_vdpa_get_vq_size,
        .kick_vq        = ifcvf_vdpa_kick_vq,
        .get_generation = ifcvf_vdpa_get_generation,
        .get_device_id  = ifcvf_vdpa_get_device_id,
index 778821bab7d93e3393440656306e60cfae52d096..ecfc16151d61913408b1ce838b6774bdb1bfe1da 100644 (file)
@@ -151,8 +151,6 @@ static void teardown_driver(struct mlx5_vdpa_net *ndev);
 
 static bool mlx5_vdpa_debug;
 
-#define MLX5_CVQ_MAX_ENT 16
-
 #define MLX5_LOG_VIO_FLAG(_feature)                                                                \
        do {                                                                                       \
                if (features & BIT_ULL(_feature))                                                  \
@@ -2276,9 +2274,16 @@ static void mlx5_vdpa_set_vq_num(struct vdpa_device *vdev, u16 idx, u32 num)
        struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
        struct mlx5_vdpa_virtqueue *mvq;
 
-       if (!is_index_valid(mvdev, idx) || is_ctrl_vq_idx(mvdev, idx))
+       if (!is_index_valid(mvdev, idx))
                return;
 
+        if (is_ctrl_vq_idx(mvdev, idx)) {
+                struct mlx5_control_vq *cvq = &mvdev->cvq;
+
+                cvq->vring.vring.num = num;
+                return;
+        }
+
        mvq = &ndev->vqs[idx];
        mvq->num_ent = num;
 }
@@ -2963,7 +2968,7 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev)
                u16 idx = cvq->vring.last_avail_idx;
 
                err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
-                                       MLX5_CVQ_MAX_ENT, false,
+                                       cvq->vring.vring.num, false,
                                        (struct vring_desc *)(uintptr_t)cvq->desc_addr,
                                        (struct vring_avail *)(uintptr_t)cvq->driver_addr,
                                        (struct vring_used *)(uintptr_t)cvq->device_addr);
index 186e9ee22eb1126127a829f221d67dd76e8b3252..f57330cf90246dd30b9ec9b6fac91a613fee6c0f 100644 (file)
@@ -93,8 +93,8 @@ static void pds_vdpa_remove(struct auxiliary_device *aux_dev)
        struct device *dev = &aux_dev->dev;
 
        vdpa_mgmtdev_unregister(&vdpa_aux->vdpa_mdev);
+       pds_vdpa_release_irqs(vdpa_aux->pdsv);
        vp_modern_remove(&vdpa_aux->vd_mdev);
-       pci_free_irq_vectors(vdpa_aux->padev->vf_pdev);
 
        pds_vdpa_debugfs_del_vdpadev(vdpa_aux);
        kfree(vdpa_aux);
index 25c0fe5ec3d5dfacdb53fa31a709851adb118942..301d95e085960d6d132f7bab59f930e38fbc8f88 100644 (file)
@@ -426,12 +426,18 @@ err_release:
        return err;
 }
 
-static void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
+void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv)
 {
-       struct pci_dev *pdev = pdsv->vdpa_aux->padev->vf_pdev;
-       struct pds_vdpa_aux *vdpa_aux = pdsv->vdpa_aux;
+       struct pds_vdpa_aux *vdpa_aux;
+       struct pci_dev *pdev;
        int qid;
 
+       if (!pdsv)
+               return;
+
+       pdev = pdsv->vdpa_aux->padev->vf_pdev;
+       vdpa_aux = pdsv->vdpa_aux;
+
        if (!vdpa_aux->nintrs)
                return;
 
@@ -612,6 +618,7 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
        struct device *dma_dev;
        struct pci_dev *pdev;
        struct device *dev;
+       u8 status;
        int err;
        int i;
 
@@ -638,6 +645,13 @@ static int pds_vdpa_dev_add(struct vdpa_mgmt_dev *mdev, const char *name,
        dma_dev = &pdev->dev;
        pdsv->vdpa_dev.dma_dev = dma_dev;
 
+       status = pds_vdpa_get_status(&pdsv->vdpa_dev);
+       if (status == 0xff) {
+               dev_err(dev, "Broken PCI - status %#x\n", status);
+               err = -ENXIO;
+               goto err_unmap;
+       }
+
        pdsv->supported_features = mgmt->supported_features;
 
        if (add_config->mask & BIT_ULL(VDPA_ATTR_DEV_FEATURES)) {
index d984ba24a7dae13d928e4402139d9c906845e90a..84bdb45871ff07db13a56affc213d72511fd440d 100644 (file)
@@ -46,5 +46,6 @@ struct pds_vdpa_device {
 
 #define PDS_VDPA_PACKED_INVERT_IDX     0x8000
 
+void pds_vdpa_release_irqs(struct pds_vdpa_device *pdsv);
 int pds_vdpa_get_mgmt_info(struct pds_vdpa_aux *vdpa_aux);
 #endif /* _VDPA_DEV_H_ */
index d0695680b282ec7812983a7bd37cd9729dfa0126..b246067e074bc0718ad49ad582b3ad9e382c9af0 100644 (file)
@@ -115,7 +115,7 @@ static const struct attribute_group vdpa_dev_group = {
 };
 __ATTRIBUTE_GROUPS(vdpa_dev);
 
-static struct bus_type vdpa_bus = {
+static const struct bus_type vdpa_bus = {
        .name  = "vdpa",
        .dev_groups = vdpa_dev_groups,
        .match = vdpa_dev_match,
@@ -944,6 +944,215 @@ static int vdpa_dev_net_config_fill(struct vdpa_device *vdev, struct sk_buff *ms
        return vdpa_dev_net_mq_config_fill(msg, features_device, &config);
 }
 
+static int
+vdpa_dev_blk_capacity_config_fill(struct sk_buff *msg,
+                                 const struct virtio_blk_config *config)
+{
+       u64 val_u64;
+
+       val_u64 = __virtio64_to_cpu(true, config->capacity);
+
+       return nla_put_u64_64bit(msg, VDPA_ATTR_DEV_BLK_CFG_CAPACITY,
+                                val_u64, VDPA_ATTR_PAD);
+}
+
+static int
+vdpa_dev_blk_seg_size_config_fill(struct sk_buff *msg, u64 features,
+                                 const struct virtio_blk_config *config)
+{
+       u32 val_u32;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_SIZE_MAX)) == 0)
+               return 0;
+
+       val_u32 = __virtio32_to_cpu(true, config->size_max);
+
+       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE, val_u32);
+}
+
+/* fill the block size*/
+static int
+vdpa_dev_blk_block_size_config_fill(struct sk_buff *msg, u64 features,
+                                   const struct virtio_blk_config *config)
+{
+       u32 val_u32;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_BLK_SIZE)) == 0)
+               return 0;
+
+       val_u32 = __virtio32_to_cpu(true, config->blk_size);
+
+       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_BLK_SIZE, val_u32);
+}
+
+static int
+vdpa_dev_blk_seg_max_config_fill(struct sk_buff *msg, u64 features,
+                                const struct virtio_blk_config *config)
+{
+       u32 val_u32;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_SEG_MAX)) == 0)
+               return 0;
+
+       val_u32 = __virtio32_to_cpu(true, config->seg_max);
+
+       return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SEG_MAX, val_u32);
+}
+
+static int vdpa_dev_blk_mq_config_fill(struct sk_buff *msg, u64 features,
+                                      const struct virtio_blk_config *config)
+{
+       u16 val_u16;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_MQ)) == 0)
+               return 0;
+
+       val_u16 = __virtio16_to_cpu(true, config->num_queues);
+
+       return nla_put_u16(msg, VDPA_ATTR_DEV_BLK_CFG_NUM_QUEUES, val_u16);
+}
+
+static int vdpa_dev_blk_topology_config_fill(struct sk_buff *msg, u64 features,
+                                      const struct virtio_blk_config *config)
+{
+       u16 min_io_size;
+       u32 opt_io_size;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_TOPOLOGY)) == 0)
+               return 0;
+
+       min_io_size = __virtio16_to_cpu(true, config->min_io_size);
+       opt_io_size = __virtio32_to_cpu(true, config->opt_io_size);
+
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_PHY_BLK_EXP,
+           config->physical_block_exp))
+               return -EMSGSIZE;
+
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_ALIGN_OFFSET,
+           config->alignment_offset))
+               return -EMSGSIZE;
+
+       if (nla_put_u16(msg, VDPA_ATTR_DEV_BLK_CFG_MIN_IO_SIZE, min_io_size))
+               return -EMSGSIZE;
+
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_OPT_IO_SIZE, opt_io_size))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int vdpa_dev_blk_discard_config_fill(struct sk_buff *msg, u64 features,
+                                      const struct virtio_blk_config *config)
+{
+       u32 val_u32;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_DISCARD)) == 0)
+               return 0;
+
+       val_u32 = __virtio32_to_cpu(true, config->max_discard_sectors);
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_MAX_DISCARD_SEC, val_u32))
+               return -EMSGSIZE;
+
+       val_u32 = __virtio32_to_cpu(true, config->max_discard_seg);
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_MAX_DISCARD_SEG, val_u32))
+               return -EMSGSIZE;
+
+       val_u32 = __virtio32_to_cpu(true, config->discard_sector_alignment);
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_DISCARD_SEC_ALIGN, val_u32))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int
+vdpa_dev_blk_write_zeroes_config_fill(struct sk_buff *msg, u64 features,
+                                    const struct virtio_blk_config *config)
+{
+       u32 val_u32;
+
+       if ((features & BIT_ULL(VIRTIO_BLK_F_WRITE_ZEROES)) == 0)
+               return 0;
+
+       val_u32 = __virtio32_to_cpu(true, config->max_write_zeroes_sectors);
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEC, val_u32))
+               return -EMSGSIZE;
+
+       val_u32 = __virtio32_to_cpu(true, config->max_write_zeroes_seg);
+       if (nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEG, val_u32))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int vdpa_dev_blk_ro_config_fill(struct sk_buff *msg, u64 features)
+{
+       u8 ro;
+
+       ro = ((features & BIT_ULL(VIRTIO_BLK_F_RO)) == 0) ? 0 : 1;
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_READ_ONLY, ro))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int vdpa_dev_blk_flush_config_fill(struct sk_buff *msg, u64 features)
+{
+       u8 flush;
+
+       flush = ((features & BIT_ULL(VIRTIO_BLK_F_FLUSH)) == 0) ? 0 : 1;
+       if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_FLUSH, flush))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
+static int vdpa_dev_blk_config_fill(struct vdpa_device *vdev,
+                                   struct sk_buff *msg)
+{
+       struct virtio_blk_config config = {};
+       u64 features_device;
+
+       vdev->config->get_config(vdev, 0, &config, sizeof(config));
+
+       features_device = vdev->config->get_device_features(vdev);
+
+       if (nla_put_u64_64bit(msg, VDPA_ATTR_DEV_FEATURES, features_device,
+                             VDPA_ATTR_PAD))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_capacity_config_fill(msg, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_seg_size_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_block_size_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_seg_max_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_mq_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_topology_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_discard_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_write_zeroes_config_fill(msg, features_device, &config))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_ro_config_fill(msg, features_device))
+               return -EMSGSIZE;
+
+       if (vdpa_dev_blk_flush_config_fill(msg, features_device))
+               return -EMSGSIZE;
+
+       return 0;
+}
+
 static int
 vdpa_dev_config_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid, u32 seq,
                     int flags, struct netlink_ext_ack *extack)
@@ -988,6 +1197,9 @@ vdpa_dev_config_fill(struct vdpa_device *vdev, struct sk_buff *msg, u32 portid,
        case VIRTIO_ID_NET:
                err = vdpa_dev_net_config_fill(vdev, msg);
                break;
+       case VIRTIO_ID_BLOCK:
+               err = vdpa_dev_blk_config_fill(vdev, msg);
+               break;
        default:
                err = -EOPNOTSUPP;
                break;
index be2925d0d28368e8959a9696f2d1c92ba4eb7fd8..8ffea8430f95fec128759fbcca2698dbdabf4179 100644 (file)
@@ -160,7 +160,7 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim, u32 flags)
                }
        }
 
-       vdpasim->running = true;
+       vdpasim->running = false;
        spin_unlock(&vdpasim->iommu_lock);
 
        vdpasim->features = 0;
@@ -311,6 +311,17 @@ static void vdpasim_set_vq_num(struct vdpa_device *vdpa, u16 idx, u32 num)
        vq->num = num;
 }
 
+static u16 vdpasim_get_vq_size(struct vdpa_device *vdpa, u16 idx)
+{
+       struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
+       struct vdpasim_virtqueue *vq = &vdpasim->vqs[idx];
+
+       if (vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK)
+               return vq->num;
+       else
+               return VDPASIM_QUEUE_MAX;
+}
+
 static void vdpasim_kick_vq(struct vdpa_device *vdpa, u16 idx)
 {
        struct vdpasim *vdpasim = vdpa_to_sim(vdpa);
@@ -483,6 +494,7 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
 
        mutex_lock(&vdpasim->mutex);
        vdpasim->status = status;
+       vdpasim->running = (status & VIRTIO_CONFIG_S_DRIVER_OK) != 0;
        mutex_unlock(&vdpasim->mutex);
 }
 
@@ -774,6 +786,7 @@ static const struct vdpa_config_ops vdpasim_config_ops = {
        .get_driver_features    = vdpasim_get_driver_features,
        .set_config_cb          = vdpasim_set_config_cb,
        .get_vq_num_max         = vdpasim_get_vq_num_max,
+       .get_vq_size            = vdpasim_get_vq_size,
        .get_device_id          = vdpasim_get_device_id,
        .get_vendor_id          = vdpasim_get_vendor_id,
        .get_status             = vdpasim_get_status,
index 5e4a77b9bae6bea6402626b3ad00134d67aa31d2..791d38d6284c562b21f1eec662a95bdf2b4c2d12 100644 (file)
@@ -373,6 +373,26 @@ static void vduse_domain_free_iova(struct iova_domain *iovad,
        free_iova_fast(iovad, iova >> shift, iova_len);
 }
 
+void vduse_domain_sync_single_for_device(struct vduse_iova_domain *domain,
+                                     dma_addr_t dma_addr, size_t size,
+                                     enum dma_data_direction dir)
+{
+       read_lock(&domain->bounce_lock);
+       if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
+               vduse_domain_bounce(domain, dma_addr, size, DMA_TO_DEVICE);
+       read_unlock(&domain->bounce_lock);
+}
+
+void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,
+                                     dma_addr_t dma_addr, size_t size,
+                                     enum dma_data_direction dir)
+{
+       read_lock(&domain->bounce_lock);
+       if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+               vduse_domain_bounce(domain, dma_addr, size, DMA_FROM_DEVICE);
+       read_unlock(&domain->bounce_lock);
+}
+
 dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
                                 struct page *page, unsigned long offset,
                                 size_t size, enum dma_data_direction dir,
@@ -393,7 +413,8 @@ dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
        if (vduse_domain_map_bounce_page(domain, (u64)iova, (u64)size, pa))
                goto err_unlock;
 
-       if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
+       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+           (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
                vduse_domain_bounce(domain, iova, size, DMA_TO_DEVICE);
 
        read_unlock(&domain->bounce_lock);
@@ -411,9 +432,9 @@ void vduse_domain_unmap_page(struct vduse_iova_domain *domain,
                             enum dma_data_direction dir, unsigned long attrs)
 {
        struct iova_domain *iovad = &domain->stream_iovad;
-
        read_lock(&domain->bounce_lock);
-       if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
+       if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
+           (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
                vduse_domain_bounce(domain, dma_addr, size, DMA_FROM_DEVICE);
 
        vduse_domain_unmap_bounce_page(domain, (u64)dma_addr, (u64)size);
index 173e979b84a937c6d67254430ddb392843f3f6cb..f92f22a7267d70f46d008723ecb40f36c841c1f2 100644 (file)
@@ -44,6 +44,14 @@ int vduse_domain_set_map(struct vduse_iova_domain *domain,
 void vduse_domain_clear_map(struct vduse_iova_domain *domain,
                            struct vhost_iotlb *iotlb);
 
+void vduse_domain_sync_single_for_device(struct vduse_iova_domain *domain,
+                                     dma_addr_t dma_addr, size_t size,
+                                     enum dma_data_direction dir);
+
+void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,
+                                     dma_addr_t dma_addr, size_t size,
+                                     enum dma_data_direction dir);
+
 dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
                                 struct page *page, unsigned long offset,
                                 size_t size, enum dma_data_direction dir,
index 1d24da79c39956ae59400ac6ec4406494ba8c655..73c89701fc9d403183387e69b3b62e1e8e90db05 100644 (file)
@@ -541,6 +541,17 @@ static void vduse_vdpa_set_vq_num(struct vdpa_device *vdpa, u16 idx, u32 num)
        vq->num = num;
 }
 
+static u16 vduse_vdpa_get_vq_size(struct vdpa_device *vdpa, u16 idx)
+{
+       struct vduse_dev *dev = vdpa_to_vduse(vdpa);
+       struct vduse_virtqueue *vq = dev->vqs[idx];
+
+       if (vq->num)
+               return vq->num;
+       else
+               return vq->num_max;
+}
+
 static void vduse_vdpa_set_vq_ready(struct vdpa_device *vdpa,
                                        u16 idx, bool ready)
 {
@@ -773,6 +784,7 @@ static const struct vdpa_config_ops vduse_vdpa_config_ops = {
        .kick_vq                = vduse_vdpa_kick_vq,
        .set_vq_cb              = vduse_vdpa_set_vq_cb,
        .set_vq_num             = vduse_vdpa_set_vq_num,
+       .get_vq_size            = vduse_vdpa_get_vq_size,
        .set_vq_ready           = vduse_vdpa_set_vq_ready,
        .get_vq_ready           = vduse_vdpa_get_vq_ready,
        .set_vq_state           = vduse_vdpa_set_vq_state,
@@ -798,6 +810,26 @@ static const struct vdpa_config_ops vduse_vdpa_config_ops = {
        .free                   = vduse_vdpa_free,
 };
 
+static void vduse_dev_sync_single_for_device(struct device *dev,
+                                            dma_addr_t dma_addr, size_t size,
+                                            enum dma_data_direction dir)
+{
+       struct vduse_dev *vdev = dev_to_vduse(dev);
+       struct vduse_iova_domain *domain = vdev->domain;
+
+       vduse_domain_sync_single_for_device(domain, dma_addr, size, dir);
+}
+
+static void vduse_dev_sync_single_for_cpu(struct device *dev,
+                                            dma_addr_t dma_addr, size_t size,
+                                            enum dma_data_direction dir)
+{
+       struct vduse_dev *vdev = dev_to_vduse(dev);
+       struct vduse_iova_domain *domain = vdev->domain;
+
+       vduse_domain_sync_single_for_cpu(domain, dma_addr, size, dir);
+}
+
 static dma_addr_t vduse_dev_map_page(struct device *dev, struct page *page,
                                     unsigned long offset, size_t size,
                                     enum dma_data_direction dir,
@@ -858,6 +890,8 @@ static size_t vduse_dev_max_mapping_size(struct device *dev)
 }
 
 static const struct dma_map_ops vduse_dev_dma_ops = {
+       .sync_single_for_device = vduse_dev_sync_single_for_device,
+       .sync_single_for_cpu = vduse_dev_sync_single_for_cpu,
        .map_page = vduse_dev_map_page,
        .unmap_page = vduse_dev_unmap_page,
        .alloc = vduse_dev_alloc_coherent,
index 281287fae89f137e18e09d5c259115f3af1fcb4f..df5f4a3bccb57ab63ae14be32c3a30692eeb8ac0 100644 (file)
@@ -328,6 +328,13 @@ static void vp_vdpa_set_vq_num(struct vdpa_device *vdpa, u16 qid,
        vp_modern_set_queue_size(mdev, qid, num);
 }
 
+static u16 vp_vdpa_get_vq_size(struct vdpa_device *vdpa, u16 qid)
+{
+       struct virtio_pci_modern_device *mdev = vdpa_to_mdev(vdpa);
+
+       return vp_modern_get_queue_size(mdev, qid);
+}
+
 static int vp_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 qid,
                                  u64 desc_area, u64 driver_area,
                                  u64 device_area)
@@ -449,6 +456,7 @@ static const struct vdpa_config_ops vp_vdpa_ops = {
        .set_vq_ready   = vp_vdpa_set_vq_ready,
        .get_vq_ready   = vp_vdpa_get_vq_ready,
        .set_vq_num     = vp_vdpa_set_vq_num,
+       .get_vq_size    = vp_vdpa_get_vq_size,
        .set_vq_address = vp_vdpa_set_vq_address,
        .kick_vq        = vp_vdpa_kick_vq,
        .get_generation = vp_vdpa_get_generation,
index 4b2fcb228a0a7930e19390cc21149b3f9a696e7e..c64ded183f8dd8eb13442185f5780de737b0edda 100644 (file)
@@ -697,6 +697,9 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq,
        hdr = buf;
        gso = &hdr->gso;
 
+       if (!sock_hlen)
+               memset(buf, 0, pad);
+
        if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
            vhost16_to_cpu(vq, gso->csum_start) +
            vhost16_to_cpu(vq, gso->csum_offset) + 2 >
index bc4a51e4638b46c79345f2be89dc7639b81ee28a..ba52d128aeb76bc1d52b375707f12875915bc7e6 100644 (file)
@@ -595,6 +595,9 @@ static long vhost_vdpa_suspend(struct vhost_vdpa *v)
        const struct vdpa_config_ops *ops = vdpa->config;
        int ret;
 
+       if (!(ops->get_status(vdpa) & VIRTIO_CONFIG_S_DRIVER_OK))
+               return 0;
+
        if (!ops->suspend)
                return -EOPNOTSUPP;
 
@@ -615,6 +618,9 @@ static long vhost_vdpa_resume(struct vhost_vdpa *v)
        const struct vdpa_config_ops *ops = vdpa->config;
        int ret;
 
+       if (!(ops->get_status(vdpa) & VIRTIO_CONFIG_S_DRIVER_OK))
+               return 0;
+
        if (!ops->resume)
                return -EOPNOTSUPP;
 
@@ -681,6 +687,14 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
                if (!ops->set_group_asid)
                        return -EOPNOTSUPP;
                return ops->set_group_asid(vdpa, idx, s.num);
+       case VHOST_VDPA_GET_VRING_SIZE:
+               if (!ops->get_vq_size)
+                       return -EOPNOTSUPP;
+               s.index = idx;
+               s.num = ops->get_vq_size(vdpa, idx);
+               if (copy_to_user(argp, &s, sizeof(s)))
+                       return -EFAULT;
+               return 0;
        case VHOST_GET_VRING_BASE:
                r = ops->get_vq_state(v->vdpa, idx, &vq_state);
                if (r)
index f4080692b3513bd67a6d946c355c2cfbd7496ecd..f173587893cb34cadbfb4c6e548c158522c7749d 100644 (file)
@@ -353,7 +353,7 @@ static void virtio_dev_remove(struct device *_d)
        of_node_put(dev->dev.of_node);
 }
 
-static struct bus_type virtio_bus = {
+static const struct bus_type virtio_bus = {
        .name  = "virtio",
        .match = virtio_dev_match,
        .dev_groups = virtio_dev_groups,
@@ -510,8 +510,10 @@ int virtio_device_freeze(struct virtio_device *dev)
 
        if (drv && drv->freeze) {
                ret = drv->freeze(dev);
-               if (ret)
+               if (ret) {
+                       virtio_config_enable(dev);
                        return ret;
+               }
        }
 
        if (dev->config->destroy_avq)
index 49299b1f9ec746bcfae28186c7644092c4849fd8..6f7e5010a6735daf093952bad0025f0acd356253 100644 (file)
@@ -1340,7 +1340,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
                                sizeof(struct vring_packed_desc));
        vq->packed.vring.desc[head].id = cpu_to_le16(id);
 
-       if (vq->do_unmap) {
+       if (vq->use_dma_api) {
                vq->packed.desc_extra[id].addr = addr;
                vq->packed.desc_extra[id].len = total_sg *
                                sizeof(struct vring_packed_desc);
@@ -1481,7 +1481,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
                        desc[i].len = cpu_to_le32(sg->length);
                        desc[i].id = cpu_to_le16(id);
 
-                       if (unlikely(vq->do_unmap)) {
+                       if (unlikely(vq->use_dma_api)) {
                                vq->packed.desc_extra[curr].addr = addr;
                                vq->packed.desc_extra[curr].len = sg->length;
                                vq->packed.desc_extra[curr].flags =
@@ -1615,7 +1615,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq,
        vq->free_head = id;
        vq->vq.num_free += state->num;
 
-       if (unlikely(vq->do_unmap)) {
+       if (unlikely(vq->use_dma_api)) {
                curr = id;
                for (i = 0; i < state->num; i++) {
                        vring_unmap_extra_packed(vq,
index 8d63e5923d245b2eef2c7a51e9456b96b9636ca4..e803db0da307a8fe1b75c8f7f5ad9c8c99393d4b 100644 (file)
@@ -183,8 +183,11 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index,
        info = kmalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return ERR_PTR(-ENOMEM);
+       if (ops->get_vq_size)
+               max_num = ops->get_vq_size(vdpa, index);
+       else
+               max_num = ops->get_vq_num_max(vdpa);
 
-       max_num = ops->get_vq_num_max(vdpa);
        if (max_num == 0) {
                err = -ENOENT;
                goto error_new_virtqueue;
index db15ac07f8a6a453bfbe35df555eea6efc83e0d8..7977ca03ac7ade72c028a40ef994260b0719c2f8 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/interrupt.h>
 #include <linux/vhost_iotlb.h>
 #include <linux/virtio_net.h>
+#include <linux/virtio_blk.h>
 #include <linux/if_ether.h>
 
 /**
@@ -195,6 +196,10 @@ struct vdpa_map_file {
  *                             @idx: virtqueue index
  *                             Returns int: irq number of a virtqueue,
  *                             negative number if no irq assigned.
+ * @get_vq_size:               Get the size of a specific virtqueue (optional)
+ *                             @vdev: vdpa device
+ *                             @idx: virtqueue index
+ *                             Return u16: the size of the virtqueue
  * @get_vq_align:              Get the virtqueue align requirement
  *                             for the device
  *                             @vdev: vdpa device
@@ -386,6 +391,7 @@ struct vdpa_config_ops {
        (*get_vq_notification)(struct vdpa_device *vdev, u16 idx);
        /* vq irq is not expected to be changed once DRIVER_OK is set */
        int (*get_vq_irq)(struct vdpa_device *vdev, u16 idx);
+       u16 (*get_vq_size)(struct vdpa_device *vdev, u16 idx);
 
        /* Device ops */
        u32 (*get_vq_align)(struct vdpa_device *vdev);
index 54b649ab0f22b6c6d4aad09cca3141db505be496..43c51698195ceb0619e5b2787428be675b007a7f 100644 (file)
@@ -56,6 +56,23 @@ enum vdpa_attr {
        /* virtio features that are provisioned to the vDPA device */
        VDPA_ATTR_DEV_FEATURES,                 /* u64 */
 
+       VDPA_ATTR_DEV_BLK_CFG_CAPACITY,         /* u64 */
+       VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE,         /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_BLK_SIZE,         /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_SEG_MAX,          /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_NUM_QUEUES,       /* u16 */
+       VDPA_ATTR_DEV_BLK_CFG_PHY_BLK_EXP,      /* u8 */
+       VDPA_ATTR_DEV_BLK_CFG_ALIGN_OFFSET,     /* u8 */
+       VDPA_ATTR_DEV_BLK_CFG_MIN_IO_SIZE,      /* u16 */
+       VDPA_ATTR_DEV_BLK_CFG_OPT_IO_SIZE,      /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_MAX_DISCARD_SEC,  /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_MAX_DISCARD_SEG,  /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_DISCARD_SEC_ALIGN,/* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEC,     /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEG,     /* u32 */
+       VDPA_ATTR_DEV_BLK_CFG_READ_ONLY,                /* u8 */
+       VDPA_ATTR_DEV_BLK_CFG_FLUSH,            /* u8 */
+
        /* new attributes must be added above here */
        VDPA_ATTR_MAX,
 };
index 649560c685f13b73feaafb96b64c351b6eec2c25..bea6973906134656d84299958258205932c23e04 100644 (file)
  */
 #define VHOST_VDPA_GET_VRING_DESC_GROUP        _IOWR(VHOST_VIRTIO, 0x7F,       \
                                              struct vhost_vring_state)
+
+/* Get the queue size of a specific virtqueue.
+ * userspace set the vring index in vhost_vring_state.index
+ * kernel set the queue size in vhost_vring_state.num
+ */
+#define VHOST_VDPA_GET_VRING_SIZE      _IOWR(VHOST_VIRTIO, 0x80,       \
+                                             struct vhost_vring_state)
 #endif
index ef3810dee7efac5d337d55db03131cb4796f4358..a8208492e82279525385924995a5b93943f1f6d0 100644 (file)
@@ -240,7 +240,7 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ           0x5
 #define VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO            0x6
 
-struct __packed virtio_admin_cmd_hdr {
+struct virtio_admin_cmd_hdr {
        __le16 opcode;
        /*
         * 1 - SR-IOV
@@ -252,20 +252,20 @@ struct __packed virtio_admin_cmd_hdr {
        __le64 group_member_id;
 };
 
-struct __packed virtio_admin_cmd_status {
+struct virtio_admin_cmd_status {
        __le16 status;
        __le16 status_qualifier;
        /* Unused, reserved for future extensions. */
        __u8 reserved2[4];
 };
 
-struct __packed virtio_admin_cmd_legacy_wr_data {
+struct virtio_admin_cmd_legacy_wr_data {
        __u8 offset; /* Starting offset of the register(s) to write. */
        __u8 reserved[7];
        __u8 registers[];
 };
 
-struct __packed virtio_admin_cmd_legacy_rd_data {
+struct virtio_admin_cmd_legacy_rd_data {
        __u8 offset; /* Starting offset of the register(s) to read. */
 };
 
@@ -275,7 +275,7 @@ struct __packed virtio_admin_cmd_legacy_rd_data {
 
 #define VIRTIO_ADMIN_CMD_MAX_NOTIFY_INFO 4
 
-struct __packed virtio_admin_cmd_notify_info_data {
+struct virtio_admin_cmd_notify_info_data {
        __u8 flags; /* 0 = end of list, 1 = owner device, 2 = member device */
        __u8 bar; /* BAR of the member or the owner device */
        __u8 padding[6];