Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 22:49:12 +0000 (14:49 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Feb 2013 22:49:12 +0000 (14:49 -0800)
Pull virtio updates from Rusty Russell:
 "All trivial, thanks to the stuff which didn't quite make it time"

* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  virtio_console: Initialize guest_connected=true for rproc_serial
  virtio: use module_virtio_driver.
  virtio: Add module driver macro for virtio drivers.
  virtio_console: Use virtio device index to generate port name
  virtio: make pci_device_id const
  virtio: make config_ops const
  virtio-mmio: fix wrong comment about register offset
  virtio_console: Let unconnected rproc device receive data.

1  2 
drivers/char/virtio_console.c
drivers/net/virtio_net.c
drivers/s390/kvm/kvm_virtio.c

@@@ -61,9 -61,6 +61,6 @@@ struct ports_driver_data 
        /* List of all the devices we're handling */
        struct list_head portdevs;
  
-       /* Number of devices this driver is handling */
-       unsigned int index;
        /*
         * This is used to keep track of the number of hvc consoles
         * spawned by this driver.  This number is given as the first
@@@ -169,9 -166,6 +166,6 @@@ struct ports_device 
        /* Array of per-port IO virtqueues */
        struct virtqueue **in_vqs, **out_vqs;
  
-       /* Used for numbering devices for sysfs and debugfs */
-       unsigned int drv_index;
        /* Major number for this device.  Ports will be created as minors. */
        int chr_major;
  };
@@@ -1415,7 -1409,7 +1409,7 @@@ static int add_port(struct ports_devic
        }
        port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
                                  devt, port, "vport%up%u",
-                                 port->portdev->drv_index, id);
+                                 port->portdev->vdev->index, id);
        if (IS_ERR(port->dev)) {
                err = PTR_ERR(port->dev);
                dev_err(&port->portdev->vdev->dev,
                 * rproc_serial does not want the console port, only
                 * the generic port implementation.
                 */
-               port->host_connected = true;
+               port->host_connected = port->guest_connected = true;
        else if (!use_multiport(port->portdev)) {
                /*
                 * If we're not using multiport support,
                 * inspect a port's state at any time
                 */
                sprintf(debugfs_name, "vport%up%u",
-                       port->portdev->drv_index, id);
+                       port->portdev->vdev->index, id);
                port->debugfs_file = debugfs_create_file(debugfs_name, 0444,
                                                         pdrvdata.debugfs_dir,
                                                         port,
@@@ -1958,16 -1952,12 +1952,12 @@@ static int virtcons_probe(struct virtio
        portdev->vdev = vdev;
        vdev->priv = portdev;
  
-       spin_lock_irq(&pdrvdata_lock);
-       portdev->drv_index = pdrvdata.index++;
-       spin_unlock_irq(&pdrvdata_lock);
        portdev->chr_major = register_chrdev(0, "virtio-portsdev",
                                             &portdev_fops);
        if (portdev->chr_major < 0) {
                dev_err(&vdev->dev,
                        "Error %d registering chrdev for device %u\n",
-                       portdev->chr_major, portdev->drv_index);
+                       portdev->chr_major, vdev->index);
                err = portdev->chr_major;
                goto free;
        }
@@@ -2062,8 -2052,7 +2052,8 @@@ static void virtcons_remove(struct virt
        /* Disable interrupts for vqs */
        vdev->config->reset(vdev);
        /* Finish up work that's lined up */
 -      cancel_work_sync(&portdev->control_work);
 +      if (use_multiport(portdev))
 +              cancel_work_sync(&portdev->control_work);
  
        list_for_each_entry_safe(port, port2, &portdev->ports, list)
                unplug_port(port);
diff --combined drivers/net/virtio_net.c
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/scatterlist.h>
  #include <linux/if_vlan.h>
  #include <linux/slab.h>
 +#include <linux/cpu.h>
  
  static int napi_weight = 128;
  module_param(napi_weight, int, 0444);
@@@ -124,12 -123,6 +124,12 @@@ struct virtnet_info 
  
        /* Does the affinity hint is set for virtqueues? */
        bool affinity_hint_set;
 +
 +      /* Per-cpu variable to show the mapping from CPU to virtqueue */
 +      int __percpu *vq_index;
 +
 +      /* CPU hot plug notifier */
 +      struct notifier_block nb;
  };
  
  struct skb_vnet_hdr {
@@@ -227,7 -220,6 +227,7 @@@ static void set_skb_frag(struct sk_buf
        skb->len += size;
        skb->truesize += PAGE_SIZE;
        skb_shinfo(skb)->nr_frags++;
 +      skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
        *len -= size;
  }
  
@@@ -761,77 -753,19 +761,77 @@@ static netdev_tx_t start_xmit(struct sk
        return NETDEV_TX_OK;
  }
  
 +/*
 + * Send command via the control virtqueue and check status.  Commands
 + * supported by the hypervisor, as indicated by feature bits, should
 + * never fail unless improperly formated.
 + */
 +static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
 +                               struct scatterlist *data, int out, int in)
 +{
 +      struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
 +      struct virtio_net_ctrl_hdr ctrl;
 +      virtio_net_ctrl_ack status = ~0;
 +      unsigned int tmp;
 +      int i;
 +
 +      /* Caller should know better */
 +      BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
 +              (out + in > VIRTNET_SEND_COMMAND_SG_MAX));
 +
 +      out++; /* Add header */
 +      in++; /* Add return status */
 +
 +      ctrl.class = class;
 +      ctrl.cmd = cmd;
 +
 +      sg_init_table(sg, out + in);
 +
 +      sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
 +      for_each_sg(data, s, out + in - 2, i)
 +              sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
 +      sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
 +
 +      BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
 +
 +      virtqueue_kick(vi->cvq);
 +
 +      /* Spin for a response, the kick causes an ioport write, trapping
 +       * into the hypervisor, so the request should be handled immediately.
 +       */
 +      while (!virtqueue_get_buf(vi->cvq, &tmp))
 +              cpu_relax();
 +
 +      return status == VIRTIO_NET_OK;
 +}
 +
  static int virtnet_set_mac_address(struct net_device *dev, void *p)
  {
        struct virtnet_info *vi = netdev_priv(dev);
        struct virtio_device *vdev = vi->vdev;
        int ret;
 +      struct sockaddr *addr = p;
 +      struct scatterlist sg;
  
 -      ret = eth_mac_addr(dev, p);
 +      ret = eth_prepare_mac_addr_change(dev, p);
        if (ret)
                return ret;
  
 -      if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
 +      if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) {
 +              sg_init_one(&sg, addr->sa_data, dev->addr_len);
 +              if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC,
 +                                        VIRTIO_NET_CTRL_MAC_ADDR_SET,
 +                                        &sg, 1, 0)) {
 +                      dev_warn(&vdev->dev,
 +                               "Failed to set mac address by vq command.\n");
 +                      return -EINVAL;
 +              }
 +      } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) {
                vdev->config->set(vdev, offsetof(struct virtio_net_config, mac),
 -                                dev->dev_addr, dev->addr_len);
 +                                addr->sa_data, dev->addr_len);
 +      }
 +
 +      eth_commit_mac_addr_change(dev, p);
  
        return 0;
  }
@@@ -885,6 -819,51 +885,6 @@@ static void virtnet_netpoll(struct net_
  }
  #endif
  
 -/*
 - * Send command via the control virtqueue and check status.  Commands
 - * supported by the hypervisor, as indicated by feature bits, should
 - * never fail unless improperly formated.
 - */
 -static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
 -                               struct scatterlist *data, int out, int in)
 -{
 -      struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
 -      struct virtio_net_ctrl_hdr ctrl;
 -      virtio_net_ctrl_ack status = ~0;
 -      unsigned int tmp;
 -      int i;
 -
 -      /* Caller should know better */
 -      BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ||
 -              (out + in > VIRTNET_SEND_COMMAND_SG_MAX));
 -
 -      out++; /* Add header */
 -      in++; /* Add return status */
 -
 -      ctrl.class = class;
 -      ctrl.cmd = cmd;
 -
 -      sg_init_table(sg, out + in);
 -
 -      sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
 -      for_each_sg(data, s, out + in - 2, i)
 -              sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
 -      sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
 -
 -      BUG_ON(virtqueue_add_buf(vi->cvq, sg, out, in, vi, GFP_ATOMIC) < 0);
 -
 -      virtqueue_kick(vi->cvq);
 -
 -      /*
 -       * Spin for a response, the kick causes an ioport write, trapping
 -       * into the hypervisor, so the request should be handled immediately.
 -       */
 -      while (!virtqueue_get_buf(vi->cvq, &tmp))
 -              cpu_relax();
 -
 -      return status == VIRTIO_NET_OK;
 -}
 -
  static void virtnet_ack_link_announce(struct virtnet_info *vi)
  {
        rtnl_lock();
@@@ -973,8 -952,10 +973,8 @@@ static void virtnet_set_rx_mode(struct 
        buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) +
                      (2 * sizeof(mac_data->entries)), GFP_ATOMIC);
        mac_data = buf;
 -      if (!buf) {
 -              dev_warn(&dev->dev, "No memory for MAC address buffer\n");
 +      if (!buf)
                return;
 -      }
  
        sg_init_table(sg, 2);
  
@@@ -1032,75 -1013,32 +1032,75 @@@ static int virtnet_vlan_rx_kill_vid(str
        return 0;
  }
  
 -static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
 +static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu)
  {
        int i;
 +      int cpu;
 +
 +      if (vi->affinity_hint_set) {
 +              for (i = 0; i < vi->max_queue_pairs; i++) {
 +                      virtqueue_set_affinity(vi->rq[i].vq, -1);
 +                      virtqueue_set_affinity(vi->sq[i].vq, -1);
 +              }
 +
 +              vi->affinity_hint_set = false;
 +      }
 +
 +      i = 0;
 +      for_each_online_cpu(cpu) {
 +              if (cpu == hcpu) {
 +                      *per_cpu_ptr(vi->vq_index, cpu) = -1;
 +              } else {
 +                      *per_cpu_ptr(vi->vq_index, cpu) =
 +                              ++i % vi->curr_queue_pairs;
 +              }
 +      }
 +}
 +
 +static void virtnet_set_affinity(struct virtnet_info *vi)
 +{
 +      int i;
 +      int cpu;
  
        /* In multiqueue mode, when the number of cpu is equal to the number of
         * queue pairs, we let the queue pairs to be private to one cpu by
         * setting the affinity hint to eliminate the contention.
         */
 -      if ((vi->curr_queue_pairs == 1 ||
 -           vi->max_queue_pairs != num_online_cpus()) && set) {
 -              if (vi->affinity_hint_set)
 -                      set = false;
 -              else
 -                      return;
 +      if (vi->curr_queue_pairs == 1 ||
 +          vi->max_queue_pairs != num_online_cpus()) {
 +              virtnet_clean_affinity(vi, -1);
 +              return;
        }
  
 -      for (i = 0; i < vi->max_queue_pairs; i++) {
 -              int cpu = set ? i : -1;
 +      i = 0;
 +      for_each_online_cpu(cpu) {
                virtqueue_set_affinity(vi->rq[i].vq, cpu);
                virtqueue_set_affinity(vi->sq[i].vq, cpu);
 +              *per_cpu_ptr(vi->vq_index, cpu) = i;
 +              i++;
        }
  
 -      if (set)
 -              vi->affinity_hint_set = true;
 -      else
 -              vi->affinity_hint_set = false;
 +      vi->affinity_hint_set = true;
 +}
 +
 +static int virtnet_cpu_callback(struct notifier_block *nfb,
 +                              unsigned long action, void *hcpu)
 +{
 +      struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb);
 +
 +      switch(action & ~CPU_TASKS_FROZEN) {
 +      case CPU_ONLINE:
 +      case CPU_DOWN_FAILED:
 +      case CPU_DEAD:
 +              virtnet_set_affinity(vi);
 +              break;
 +      case CPU_DOWN_PREPARE:
 +              virtnet_clean_affinity(vi, (long)hcpu);
 +              break;
 +      default:
 +              break;
 +      }
 +      return NOTIFY_OK;
  }
  
  static void virtnet_get_ringparam(struct net_device *dev,
@@@ -1144,15 -1082,13 +1144,15 @@@ static int virtnet_set_channels(struct 
        if (queue_pairs > vi->max_queue_pairs)
                return -EINVAL;
  
 +      get_online_cpus();
        err = virtnet_set_queues(vi, queue_pairs);
        if (!err) {
                netif_set_real_num_tx_queues(dev, queue_pairs);
                netif_set_real_num_rx_queues(dev, queue_pairs);
  
 -              virtnet_set_affinity(vi, true);
 +              virtnet_set_affinity(vi);
        }
 +      put_online_cpus();
  
        return err;
  }
@@@ -1191,19 -1127,12 +1191,19 @@@ static int virtnet_change_mtu(struct ne
  
  /* To avoid contending a lock hold by a vcpu who would exit to host, select the
   * txq based on the processor id.
 - * TODO: handle cpu hotplug.
   */
  static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
  {
 -      int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
 -                smp_processor_id();
 +      int txq;
 +      struct virtnet_info *vi = netdev_priv(dev);
 +
 +      if (skb_rx_queue_recorded(skb)) {
 +              txq = skb_get_rx_queue(skb);
 +      } else {
 +              txq = *__this_cpu_ptr(vi->vq_index);
 +              if (txq == -1)
 +                      txq = 0;
 +      }
  
        while (unlikely(txq >= dev->real_num_tx_queues))
                txq -= dev->real_num_tx_queues;
@@@ -1319,7 -1248,7 +1319,7 @@@ static void virtnet_del_vqs(struct virt
  {
        struct virtio_device *vdev = vi->vdev;
  
 -      virtnet_set_affinity(vi, false);
 +      virtnet_clean_affinity(vi, -1);
  
        vdev->config->del_vqs(vdev);
  
@@@ -1442,10 -1371,7 +1442,10 @@@ static int init_vqs(struct virtnet_inf
        if (ret)
                goto err_free;
  
 -      virtnet_set_affinity(vi, true);
 +      get_online_cpus();
 +      virtnet_set_affinity(vi);
 +      put_online_cpus();
 +
        return 0;
  
  err_free:
@@@ -1527,10 -1453,6 +1527,10 @@@ static int virtnet_probe(struct virtio_
        if (vi->stats == NULL)
                goto free;
  
 +      vi->vq_index = alloc_percpu(int);
 +      if (vi->vq_index == NULL)
 +              goto free_stats;
 +
        mutex_init(&vi->config_lock);
        vi->config_enable = true;
        INIT_WORK(&vi->config_work, virtnet_config_changed_work);
        /* Allocate/initialize the rx/tx queues, and invoke find_vqs */
        err = init_vqs(vi);
        if (err)
 -              goto free_stats;
 +              goto free_index;
  
        netif_set_real_num_tx_queues(dev, 1);
        netif_set_real_num_rx_queues(dev, 1);
                }
        }
  
 +      vi->nb.notifier_call = &virtnet_cpu_callback;
 +      err = register_hotcpu_notifier(&vi->nb);
 +      if (err) {
 +              pr_debug("virtio_net: registering cpu notifier failed\n");
 +              goto free_recv_bufs;
 +      }
 +
        /* Assume link up if device can't report link status,
           otherwise get link status from config. */
        if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
@@@ -1605,8 -1520,6 +1605,8 @@@ free_recv_bufs
  free_vqs:
        cancel_delayed_work_sync(&vi->refill);
        virtnet_del_vqs(vi);
 +free_index:
 +      free_percpu(vi->vq_index);
  free_stats:
        free_percpu(vi->stats);
  free:
@@@ -1630,8 -1543,6 +1630,8 @@@ static void virtnet_remove(struct virti
  {
        struct virtnet_info *vi = vdev->priv;
  
 +      unregister_hotcpu_notifier(&vi->nb);
 +
        /* Prevent config work handler from accessing the device. */
        mutex_lock(&vi->config_lock);
        vi->config_enable = false;
  
        flush_work(&vi->config_work);
  
 +      free_percpu(vi->vq_index);
        free_percpu(vi->stats);
        free_netdev(vi->dev);
  }
@@@ -1718,7 -1628,6 +1718,7 @@@ static unsigned int features[] = 
        VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
        VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
        VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
 +      VIRTIO_NET_F_CTRL_MAC_ADDR,
  };
  
  static struct virtio_driver virtio_net_driver = {
  #endif
  };
  
- static int __init init(void)
- {
-       return register_virtio_driver(&virtio_net_driver);
- }
- static void __exit fini(void)
- {
-       unregister_virtio_driver(&virtio_net_driver);
- }
- module_init(init);
- module_exit(fini);
+ module_virtio_driver(virtio_net_driver);
  
  MODULE_DEVICE_TABLE(virtio, id_table);
  MODULE_DESCRIPTION("Virtio network driver");
@@@ -275,7 -275,7 +275,7 @@@ static const char *kvm_bus_name(struct 
  /*
   * The config ops structure as defined by virtio config
   */
- static struct virtio_config_ops kvm_vq_configspace_ops = {
+ static const struct virtio_config_ops kvm_vq_configspace_ops = {
        .get_features = kvm_get_features,
        .finalize_features = kvm_finalize_features,
        .get = kvm_get,
@@@ -421,26 -421,6 +421,26 @@@ static void kvm_extint_handler(struct e
        }
  }
  
 +/*
 + * For s390-virtio, we expect a page above main storage containing
 + * the virtio configuration. Try to actually load from this area
 + * in order to figure out if the host provides this page.
 + */
 +static int __init test_devices_support(unsigned long addr)
 +{
 +      int ret = -EIO;
 +
 +      asm volatile(
 +              "0:     lura    0,%1\n"
 +              "1:     xgr     %0,%0\n"
 +              "2:\n"
 +              EX_TABLE(0b,2b)
 +              EX_TABLE(1b,2b)
 +              : "+d" (ret)
 +              : "a" (addr)
 +              : "0", "cc");
 +      return ret;
 +}
  /*
   * Init function for virtio
   * devices are in a single page above top of "normal" mem
@@@ -452,23 -432,21 +452,23 @@@ static int __init kvm_devices_init(void
        if (!MACHINE_IS_KVM)
                return -ENODEV;
  
 +      if (test_devices_support(real_memory_size) < 0)
 +              return -ENODEV;
 +
 +      rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
 +      if (rc)
 +              return rc;
 +
 +      kvm_devices = (void *) real_memory_size;
 +
        kvm_root = root_device_register("kvm_s390");
        if (IS_ERR(kvm_root)) {
                rc = PTR_ERR(kvm_root);
                printk(KERN_ERR "Could not register kvm_s390 root device");
 +              vmem_remove_mapping(real_memory_size, PAGE_SIZE);
                return rc;
        }
  
 -      rc = vmem_add_mapping(real_memory_size, PAGE_SIZE);
 -      if (rc) {
 -              root_device_unregister(kvm_root);
 -              return rc;
 -      }
 -
 -      kvm_devices = (void *) real_memory_size;
 -
        INIT_WORK(&hotplug_work, hotplug_devices);
  
        service_subclass_irq_register();