]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/virtio_net.c
virtio: Tweak virtio_net defines
[linux-2.6-omap-h63xx.git] / drivers / net / virtio_net.c
index 5413dbf3d4ac25ab688bb1a965ccf981f230addc..73f01db59ab9e4c351d0efd9a0c3a7b7e928838d 100644 (file)
 #include <linux/virtio_net.h>
 #include <linux/scatterlist.h>
 
+static int csum = 1, gso = 1;
+module_param(csum, bool, 0444);
+module_param(gso, bool, 0444);
+
 /* FIXME: MTU in config. */
 #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
 
@@ -52,13 +56,12 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
        sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
 }
 
-static bool skb_xmit_done(struct virtqueue *rvq)
+static void skb_xmit_done(struct virtqueue *rvq)
 {
        struct virtnet_info *vi = rvq->vdev->priv;
 
        /* In case we were waiting for output buffers. */
        netif_wake_queue(vi->dev);
-       return true;
 }
 
 static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -83,28 +86,16 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
 
        if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
                pr_debug("Needs csum!\n");
-               skb->ip_summed = CHECKSUM_PARTIAL;
-               skb->csum_start = hdr->csum_start;
-               skb->csum_offset = hdr->csum_offset;
-               if (skb->csum_start > skb->len - 2
-                   || skb->csum_offset > skb->len - 2) {
-                       if (net_ratelimit())
-                               printk(KERN_WARNING "%s: csum=%u/%u len=%u\n",
-                                      dev->name, skb->csum_start,
-                                      skb->csum_offset, skb->len);
+               if (!skb_partial_csum_set(skb,hdr->csum_start,hdr->csum_offset))
                        goto frame_err;
-               }
        }
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                pr_debug("GSO!\n");
-               switch (hdr->gso_type) {
+               switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
                case VIRTIO_NET_HDR_GSO_TCPV4:
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
                        break;
-               case VIRTIO_NET_HDR_GSO_TCPV4_ECN:
-                       skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN;
-                       break;
                case VIRTIO_NET_HDR_GSO_UDP:
                        skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
                        break;
@@ -118,6 +109,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
                        goto frame_err;
                }
 
+               if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
+                       skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
+
                skb_shinfo(skb)->gso_size = hdr->gso_size;
                if (skb_shinfo(skb)->gso_size == 0) {
                        if (net_ratelimit())
@@ -170,12 +164,14 @@ static void try_fill_recv(struct virtnet_info *vi)
        vi->rvq->vq_ops->kick(vi->rvq);
 }
 
-static bool skb_recv_done(struct virtqueue *rvq)
+static void skb_recv_done(struct virtqueue *rvq)
 {
        struct virtnet_info *vi = rvq->vdev->priv;
-       netif_rx_schedule(vi->dev, &vi->napi);
-       /* Suppress further interrupts. */
-       return false;
+       /* Schedule NAPI, Suppress further interrupts if successful. */
+       if (netif_rx_schedule_prep(vi->dev, &vi->napi)) {
+               rvq->vq_ops->disable_cb(rvq);
+               __netif_rx_schedule(vi->dev, &vi->napi);
+       }
 }
 
 static int virtnet_poll(struct napi_struct *napi, int budget)
@@ -201,7 +197,7 @@ again:
        /* Out of packets? */
        if (received < budget) {
                netif_rx_complete(vi->dev, napi);
-               if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
+               if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
                    && netif_rx_reschedule(vi->dev, napi))
                        goto again;
        }
@@ -250,10 +246,9 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
 
        if (skb_is_gso(skb)) {
+               hdr->hdr_len = skb_transport_header(skb) - skb->data;
                hdr->gso_size = skb_shinfo(skb)->gso_size;
-               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
-                       hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
-               else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
                        hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
                else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
                        hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
@@ -261,9 +256,11 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
                        hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
                else
                        BUG();
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
+                       hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
        } else {
                hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
-               hdr->gso_size = 0;
+               hdr->gso_size = hdr->hdr_len = 0;
        }
 
        vnet_hdr_to_sg(sg, skb);
@@ -320,10 +317,8 @@ static int virtnet_close(struct net_device *dev)
 static int virtnet_probe(struct virtio_device *vdev)
 {
        int err;
-       unsigned int len;
        struct net_device *dev;
        struct virtnet_info *vi;
-       void *token;
 
        /* Allocate ourselves a network device with room for our info */
        dev = alloc_etherdev(sizeof(struct virtnet_info));
@@ -339,25 +334,20 @@ static int virtnet_probe(struct virtio_device *vdev)
        SET_NETDEV_DEV(dev, &vdev->dev);
 
        /* Do we support "hardware" checksums? */
-       token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_F, &len);
-       if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_NO_CSUM)) {
+       if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) {
                /* This opens up the world of extra features. */
                dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
-               if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4))
-                       dev->features |= NETIF_F_TSO;
-               if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_UFO))
-                       dev->features |= NETIF_F_UFO;
-               if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4_ECN))
-                       dev->features |= NETIF_F_TSO_ECN;
-               if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO6))
-                       dev->features |= NETIF_F_TSO6;
+               if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) {
+                       dev->features |= NETIF_F_TSO | NETIF_F_UFO
+                               | NETIF_F_TSO_ECN | NETIF_F_TSO6;
+               }
        }
 
        /* Configuration may specify what MAC to use.  Otherwise random. */
-       token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_MAC_F, &len);
-       if (token) {
-               dev->addr_len = len;
-               vdev->config->get(vdev, token, dev->dev_addr, len);
+       if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) {
+               vdev->config->get(vdev,
+                                 offsetof(struct virtio_net_config, mac),
+                                 dev->dev_addr, dev->addr_len);
        } else
                random_ether_addr(dev->dev_addr);
 
@@ -368,13 +358,13 @@ static int virtnet_probe(struct virtio_device *vdev)
        vi->vdev = vdev;
 
        /* We expect two virtqueues, receive then send. */
-       vi->rvq = vdev->config->find_vq(vdev, skb_recv_done);
+       vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
        if (IS_ERR(vi->rvq)) {
                err = PTR_ERR(vi->rvq);
                goto free;
        }
 
-       vi->svq = vdev->config->find_vq(vdev, skb_xmit_done);
+       vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done);
        if (IS_ERR(vi->svq)) {
                err = PTR_ERR(vi->svq);
                goto free_recv;