These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / net / virtio_net.c
index 7fbca37..f94ab78 100644 (file)
@@ -40,12 +40,12 @@ module_param(gso, bool, 0444);
 #define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
 #define GOOD_COPY_LEN  128
 
-/* Weight used for the RX packet size EWMA. The average packet size is used to
- * determine the packet buffer size when refilling RX rings. As the entire RX
- * ring may be refilled at once, the weight is chosen so that the EWMA will be
- * insensitive to short-term, transient changes in packet size.
+/* RX packet size EWMA. The average packet size is used to determine the packet
+ * buffer size when refilling RX rings. As the entire RX ring may be refilled
+ * at once, the weight is chosen so that the EWMA will be insensitive to short-
+ * term, transient changes in packet size.
  */
-#define RECEIVE_AVG_WEIGHT 64
+DECLARE_EWMA(pkt_len, 1, 64)
 
 /* Minimum alignment for mergeable packet buffers. */
 #define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
@@ -85,7 +85,7 @@ struct receive_queue {
        struct page *pages;
 
        /* Average packet length for mergeable receive buffers. */
-       struct ewma mrg_avg_pkt_len;
+       struct ewma_pkt_len mrg_avg_pkt_len;
 
        /* Page frag for packet buffer allocation. */
        struct page_frag alloc_frag;
@@ -140,6 +140,12 @@ struct virtnet_info {
 
        /* CPU hot plug notifier */
        struct notifier_block nb;
+
+       /* Control VQ buffers: protected by the rtnl lock */
+       struct virtio_net_ctrl_hdr ctrl_hdr;
+       virtio_net_ctrl_ack ctrl_status;
+       u8 ctrl_promisc;
+       u8 ctrl_allmulti;
 };
 
 struct padded_vnet_hdr {
@@ -407,7 +413,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
                }
        }
 
-       ewma_add(&rq->mrg_avg_pkt_len, head_skb->len);
+       ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len);
        return head_skb;
 
 err_skb:
@@ -518,7 +524,7 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
 
        skb_mark_napi_id(skb, &rq->napi);
 
-       netif_receive_skb(skb);
+       napi_gro_receive(&rq->napi, skb);
        return;
 
 frame_err:
@@ -540,7 +546,7 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
        skb_put(skb, GOOD_PACKET_LEN);
 
        hdr = skb_vnet_hdr(skb);
-       sg_init_table(rq->sg, MAX_SKB_FRAGS + 2);
+       sg_init_table(rq->sg, 2);
        sg_set_buf(rq->sg, hdr, vi->hdr_len);
        skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
 
@@ -600,12 +606,12 @@ static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq,
        return err;
 }
 
-static unsigned int get_mergeable_buf_len(struct ewma *avg_pkt_len)
+static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len)
 {
        const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
        unsigned int len;
 
-       len = hdr_len + clamp_t(unsigned int, ewma_read(avg_pkt_len),
+       len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
                        GOOD_PACKET_LEN, PAGE_SIZE - hdr_len);
        return ALIGN(len, MERGEABLE_BUFFER_ALIGN);
 }
@@ -756,7 +762,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
        /* Out of packets? */
        if (received < budget) {
                r = virtqueue_enable_cb_prepare(rq->vq);
-               napi_complete(napi);
+               napi_complete_done(napi, received);
                if (unlikely(virtqueue_poll(rq->vq, r)) &&
                    napi_schedule_prep(napi)) {
                        virtqueue_disable_cb(rq->vq);
@@ -893,7 +899,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
        if (vi->mergeable_rx_bufs)
                hdr->num_buffers = 0;
 
-       sg_init_table(sq->sg, MAX_SKB_FRAGS + 2);
+       sg_init_table(sq->sg, skb_shinfo(skb)->nr_frags + (can_push ? 1 : 2));
        if (can_push) {
                __skb_push(skb, hdr_len);
                num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len);
@@ -976,31 +982,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
                                 struct scatterlist *out)
 {
        struct scatterlist *sgs[4], hdr, stat;
-       struct virtio_net_ctrl_hdr ctrl;
-       virtio_net_ctrl_ack status = ~0;
        unsigned out_num = 0, tmp;
 
        /* Caller should know better */
        BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
 
-       ctrl.class = class;
-       ctrl.cmd = cmd;
+       vi->ctrl_status = ~0;
+       vi->ctrl_hdr.class = class;
+       vi->ctrl_hdr.cmd = cmd;
        /* Add header */
-       sg_init_one(&hdr, &ctrl, sizeof(ctrl));
+       sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr));
        sgs[out_num++] = &hdr;
 
        if (out)
                sgs[out_num++] = out;
 
        /* Add return status. */
-       sg_init_one(&stat, &status, sizeof(status));
+       sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status));
        sgs[out_num] = &stat;
 
        BUG_ON(out_num + 1 > ARRAY_SIZE(sgs));
        virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC);
 
        if (unlikely(!virtqueue_kick(vi->cvq)))
-               return status == VIRTIO_NET_OK;
+               return vi->ctrl_status == VIRTIO_NET_OK;
 
        /* Spin for a response, the kick causes an ioport write, trapping
         * into the hypervisor, so the request should be handled immediately.
@@ -1009,7 +1014,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
               !virtqueue_is_broken(vi->cvq))
                cpu_relax();
 
-       return status == VIRTIO_NET_OK;
+       return vi->ctrl_status == VIRTIO_NET_OK;
 }
 
 static int virtnet_set_mac_address(struct net_device *dev, void *p)
@@ -1151,7 +1156,6 @@ static void virtnet_set_rx_mode(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
        struct scatterlist sg[2];
-       u8 promisc, allmulti;
        struct virtio_net_ctrl_mac *mac_data;
        struct netdev_hw_addr *ha;
        int uc_count;
@@ -1163,22 +1167,22 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
                return;
 
-       promisc = ((dev->flags & IFF_PROMISC) != 0);
-       allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
+       vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0);
+       vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
 
-       sg_init_one(sg, &promisc, sizeof(promisc));
+       sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_PROMISC, sg))
                dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
-                        promisc ? "en" : "dis");
+                        vi->ctrl_promisc ? "en" : "dis");
 
-       sg_init_one(sg, &allmulti, sizeof(allmulti));
+       sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
                dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
-                        allmulti ? "en" : "dis");
+                        vi->ctrl_allmulti ? "en" : "dis");
 
        uc_count = netdev_uc_count(dev);
        mc_count = netdev_mc_count(dev);
@@ -1615,7 +1619,7 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
                napi_hash_add(&vi->rq[i].napi);
 
                sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
-               ewma_init(&vi->rq[i].mrg_avg_pkt_len, 1, RECEIVE_AVG_WEIGHT);
+               ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len);
                sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg));
        }
 
@@ -1658,7 +1662,7 @@ static ssize_t mergeable_rx_buffer_size_show(struct netdev_rx_queue *queue,
 {
        struct virtnet_info *vi = netdev_priv(queue->dev);
        unsigned int queue_index = get_netdev_rx_queue_index(queue);
-       struct ewma *avg;
+       struct ewma_pkt_len *avg;
 
        BUG_ON(queue_index >= vi->max_queue_pairs);
        avg = &vi->rq[queue_index].mrg_avg_pkt_len;
@@ -1756,9 +1760,9 @@ static int virtnet_probe(struct virtio_device *vdev)
        /* Do we support "hardware" checksums? */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
                /* This opens up the world of extra features. */
-               dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+               dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
                if (csum)
-                       dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+                       dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
 
                if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
                        dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO