Commit d95fcdf4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 0815d5cc 5da7137d
Loading
Loading
Loading
Loading
+99 −52
Original line number Diff line number Diff line
@@ -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);

			bytes += skb->len;
			napi_consume_skb(skb, in_napi);
		} else {
			struct xdp_frame *frame = ptr_to_xdp(ptr);
	struct virtnet_sq_free_stats stats = {0};

			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);

+8 −0
Original line number Diff line number Diff line
@@ -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,
+5 −6
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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_ */
+15 −0
Original line number Diff line number Diff line
@@ -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,
Loading