* Re: [RFC PATCH v3 2/3] virtio_net: Extend virtio to use VF datapath when available
From: Jakub Kicinski @ 2018-02-17 3:04 UTC (permalink / raw)
To: Sridhar Samudrala
Cc: alexander.h.duyck, Or Gerlitz, mst, netdev, virtualization,
loseweigh, davem
In-Reply-To: <1518804682-16881-3-git-send-email-sridhar.samudrala@intel.com>
On Fri, 16 Feb 2018 10:11:21 -0800, Sridhar Samudrala wrote:
> This patch enables virtio_net to switch over to a VF datapath when a VF
> netdev is present with the same MAC address. It allows live migration
> of a VM with a direct attached VF without the need to setup a bond/team
> between a VF and virtio net device in the guest.
>
> The hypervisor needs to enable only one datapath at any time so that
> packets don't get looped back to the VM over the other datapath. When a VF
> is plugged, the virtio datapath link state can be marked as down. The
> hypervisor needs to unplug the VF device from the guest on the source host
> and reset the MAC filter of the VF to initiate failover of datapath to
> virtio before starting the migration. After the migration is completed,
> the destination hypervisor sets the MAC filter on the VF and plugs it back
> to the guest to switch over to VF datapath.
>
> When BACKUP feature is enabled, an additional netdev(bypass netdev) is
> created that acts as a master device and tracks the state of the 2 lower
> netdevs. The original virtio_net netdev is marked as 'backup' netdev and a
> passthru device with the same MAC is registered as 'active' netdev.
>
> This patch is based on the discussion initiated by Jesse on this thread.
> https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
>
> Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> +static void
> +virtnet_bypass_get_stats(struct net_device *dev,
> + struct rtnl_link_stats64 *stats)
> +{
> + struct virtnet_bypass_info *vbi = netdev_priv(dev);
> + const struct rtnl_link_stats64 *new;
> + struct rtnl_link_stats64 temp;
> + struct net_device *child_netdev;
> +
> + spin_lock(&vbi->stats_lock);
> + memcpy(stats, &vbi->bypass_stats, sizeof(*stats));
> +
> + rcu_read_lock();
> +
> + child_netdev = rcu_dereference(vbi->active_netdev);
> + if (child_netdev) {
> + new = dev_get_stats(child_netdev, &temp);
> + virtnet_bypass_fold_stats(stats, new, &vbi->active_stats);
> + memcpy(&vbi->active_stats, new, sizeof(*new));
> + }
> +
> + child_netdev = rcu_dereference(vbi->backup_netdev);
> + if (child_netdev) {
> + new = dev_get_stats(child_netdev, &temp);
> + virtnet_bypass_fold_stats(stats, new, &vbi->backup_stats);
> + memcpy(&vbi->backup_stats, new, sizeof(*new));
> + }
> +
> + rcu_read_unlock();
> +
> + memcpy(&vbi->bypass_stats, stats, sizeof(*stats));
> + spin_unlock(&vbi->stats_lock);
> +}
> +
> +static int virtnet_bypass_change_mtu(struct net_device *dev, int new_mtu)
> +{
> + struct virtnet_bypass_info *vbi = netdev_priv(dev);
> + struct net_device *child_netdev;
> + int ret = 0;
> +
> + child_netdev = rcu_dereference(vbi->active_netdev);
> + if (child_netdev) {
> + ret = dev_set_mtu(child_netdev, new_mtu);
> + if (ret)
> + return ret;
> + }
> +
> + child_netdev = rcu_dereference(vbi->backup_netdev);
> + if (child_netdev) {
> + ret = dev_set_mtu(child_netdev, new_mtu);
> + if (ret)
> + netdev_err(child_netdev,
> + "Unexpected failure to set mtu to %d\n",
> + new_mtu);
You should probably unwind if set fails on one of the legs.
> + }
> +
> + dev->mtu = new_mtu;
> + return 0;
> +}
nit: stats, mtu, all those mundane things are implemented in team
already. If we had this as kernel-internal team mode we wouldn't
have to reimplement them... You probably did investigate that
option, for my edification, would you mind saying what the
challenges/downsides were?
> +static struct net_device *
> +get_virtnet_bypass_bymac(struct net *net, const u8 *mac)
> +{
> + struct net_device *dev;
> +
> + ASSERT_RTNL();
> +
> + for_each_netdev(net, dev) {
> + if (dev->netdev_ops != &virtnet_bypass_netdev_ops)
> + continue; /* not a virtnet_bypass device */
Is there anything inherently wrong with enslaving another virtio dev
now? I was expecting something like a hash map to map MAC addr ->
master and then one can check if dev is already enslaved to that master.
Just a random thought, I'm probably missing something...
> + if (ether_addr_equal(mac, dev->perm_addr))
> + return dev;
> + }
> +
> + return NULL;
> +}
> +
> +static struct net_device *
> +get_virtnet_bypass_byref(struct net_device *child_netdev)
> +{
> + struct net *net = dev_net(child_netdev);
> + struct net_device *dev;
> +
> + ASSERT_RTNL();
> +
> + for_each_netdev(net, dev) {
> + struct virtnet_bypass_info *vbi;
> +
> + if (dev->netdev_ops != &virtnet_bypass_netdev_ops)
> + continue; /* not a virtnet_bypass device */
> +
> + vbi = netdev_priv(dev);
> +
> + if ((rtnl_dereference(vbi->active_netdev) == child_netdev) ||
> + (rtnl_dereference(vbi->backup_netdev) == child_netdev))
nit: parens not needed
> + return dev; /* a match */
> + }
> +
> + return NULL;
> +}
> +static int virtnet_bypass_create(struct virtnet_info *vi)
> +{
> + struct net_device *backup_netdev = vi->dev;
> + struct device *dev = &vi->vdev->dev;
> + struct net_device *bypass_netdev;
> + int res;
> +
> + /* Alloc at least 2 queues, for now we are going with 16 assuming
> + * that most devices being bonded won't have too many queues.
> + */
> + bypass_netdev = alloc_etherdev_mq(sizeof(struct virtnet_bypass_info),
> + 16);
> + if (!bypass_netdev) {
> + dev_err(dev, "Unable to allocate bypass_netdev!\n");
> + return -ENOMEM;
> + }
Maybe it's just me but referring to master as bypass seems slightly
confusing. I know you don't like team and bond, but perhaps we can
come up with a better name? For me bypass device is the other leg,
i.e. the VF, not the master. Perhaps others disagree.
> + dev_net_set(bypass_netdev, dev_net(backup_netdev));
> + SET_NETDEV_DEV(bypass_netdev, dev);
> +
> + bypass_netdev->netdev_ops = &virtnet_bypass_netdev_ops;
> + bypass_netdev->ethtool_ops = &virtnet_bypass_ethtool_ops;
Thanks!
^ permalink raw reply
* Re: [RFC PATCH v3 0/3] Enable virtio_net to act as a backup for a passthru device
From: Jakub Kicinski @ 2018-02-17 2:38 UTC (permalink / raw)
To: Sridhar Samudrala
Cc: alexander.h.duyck, virtio-dev, mst, netdev, virtualization,
loseweigh, davem
In-Reply-To: <1518804682-16881-1-git-send-email-sridhar.samudrala@intel.com>
On Fri, 16 Feb 2018 10:11:19 -0800, Sridhar Samudrala wrote:
> Ppatch 2 is in response to the community request for a 3 netdev
> solution. However, it creates some issues we'll get into in a moment.
> It extends virtio_net to use alternate datapath when available and
> registered. When BACKUP feature is enabled, virtio_net driver creates
> an additional 'bypass' netdev that acts as a master device and controls
> 2 slave devices. The original virtio_net netdev is registered as
> 'backup' netdev and a passthru/vf device with the same MAC gets
> registered as 'active' netdev. Both 'bypass' and 'backup' netdevs are
> associated with the same 'pci' device. The user accesses the network
> interface via 'bypass' netdev. The 'bypass' netdev chooses 'active' netdev
> as default for transmits when it is available with link up and running.
Thank you do doing this.
> We noticed a couple of issues with this approach during testing.
> - As both 'bypass' and 'backup' netdevs are associated with the same
> virtio pci device, udev tries to rename both of them with the same name
> and the 2nd rename will fail. This would be OK as long as the first netdev
> to be renamed is the 'bypass' netdev, but the order in which udev gets
> to rename the 2 netdevs is not reliable.
Out of curiosity - why do you link the master netdev to the virtio
struct device?
FWIW two solutions that immediately come to mind is to export "backup"
as phys_port_name of the backup virtio link and/or assign a name to the
master like you are doing already. I think team uses team%d and bond
uses bond%d, soft naming of master devices seems quite natural in this
case.
IMHO phys_port_name == "backup" if BACKUP bit is set on slave virtio
link is quite neat.
> - When the 'active' netdev is unplugged OR not present on a destination
> system after live migration, the user will see 2 virtio_net netdevs.
That's necessary and expected, all configuration applies to the master
so master must exist.
^ permalink raw reply
* Re: [PATCH v21 1/5] xbitmap: Introduce xbitmap
From: Matthew Wilcox @ 2018-02-16 21:58 UTC (permalink / raw)
To: Andy Shevchenko
Cc: yang.zhang.wz, kvm, Michael S. Tsirkin, Tetsuo Handa,
liliang.opensource, qemu-devel, virtualization, linux-mm,
aarcange, virtio-dev, Matthew Wilcox, nilal, riel, cornelia.huck,
mhocko, quan.xu0, Linux Kernel Mailing List, amit.shah,
Paolo Bonzini, Andrew Morton, mgorman
In-Reply-To: <CAHp75Vd_tt0bV_OqAOwc=_uWrsF2zP9pMSbxPw_AxF_s9zj-pw@mail.gmail.com>
On Fri, Feb 16, 2018 at 11:45:51PM +0200, Andy Shevchenko wrote:
> Now, the question about test case. Why do you heavily use BUG_ON?
> Isn't resulting statistics enough?
No. If any of those tests fail, we want to stop dead. They'll lead to
horrendous bugs throughout the kernel if they're wrong. I think more of
the in-kernel test suite should stop dead instead of printing a warning.
Would you want to boot a machine which has a known bug in the page cache,
for example?
^ permalink raw reply
* Re: [PATCH v21 1/5] xbitmap: Introduce xbitmap
From: Andy Shevchenko @ 2018-02-16 21:45 UTC (permalink / raw)
To: Matthew Wilcox
Cc: yang.zhang.wz, kvm, Michael S. Tsirkin, Tetsuo Handa,
liliang.opensource, qemu-devel, virtualization, linux-mm,
aarcange, virtio-dev, Matthew Wilcox, nilal, riel, cornelia.huck,
mhocko, quan.xu0, Linux Kernel Mailing List, amit.shah,
Paolo Bonzini, Andrew Morton, mgorman
In-Reply-To: <20180216183032.GA7439@bombadil.infradead.org>
On Fri, Feb 16, 2018 at 8:30 PM, Matthew Wilcox <willy@infradead.org> wrote:
> On Fri, Feb 16, 2018 at 07:44:50PM +0200, Andy Shevchenko wrote:
>> On Tue, Jan 9, 2018 at 1:10 PM, Wei Wang <wei.w.wang@intel.com> wrote:
>> > From: Matthew Wilcox <mawilcox@microsoft.com>
>> >
>> > The eXtensible Bitmap is a sparse bitmap representation which is
>> > efficient for set bits which tend to cluster. It supports up to
>> > 'unsigned long' worth of bits.
>>
>> > lib/xbitmap.c | 444 +++++++++++++++++++++++++++++++
>>
>> Please, split tests to a separate module.
>
> Hah, I just did this two days ago! I didn't publish it yet, but I also made
> it compile both in userspace and as a kernel module.
>
> It's the top two commits here:
>
> http://git.infradead.org/users/willy/linux-dax.git/shortlog/refs/heads/xarray-2018-02-12
>
Thanks!
> Note this is a complete rewrite compared to the version presented here; it
> sits on top of the XArray and no longer has a preload interface. It has a
> superset of the IDA functionality.
Noted.
Now, the question about test case. Why do you heavily use BUG_ON?
Isn't resulting statistics enough?
See how other lib/test_* modules do.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v21 1/5] xbitmap: Introduce xbitmap
From: Matthew Wilcox @ 2018-02-16 18:30 UTC (permalink / raw)
To: Andy Shevchenko
Cc: yang.zhang.wz, kvm, Michael S. Tsirkin, Tetsuo Handa,
liliang.opensource, qemu-devel, virtualization, linux-mm,
aarcange, virtio-dev, Matthew Wilcox, nilal, riel, cornelia.huck,
mhocko, quan.xu0, Linux Kernel Mailing List, amit.shah,
Paolo Bonzini, Andrew Morton, mgorman
In-Reply-To: <CAHp75Ve-1-TOVJUZ4anhwkkeq-RhpSg3EmN3N0r09rj6sFrQZQ@mail.gmail.com>
On Fri, Feb 16, 2018 at 07:44:50PM +0200, Andy Shevchenko wrote:
> On Tue, Jan 9, 2018 at 1:10 PM, Wei Wang <wei.w.wang@intel.com> wrote:
> > From: Matthew Wilcox <mawilcox@microsoft.com>
> >
> > The eXtensible Bitmap is a sparse bitmap representation which is
> > efficient for set bits which tend to cluster. It supports up to
> > 'unsigned long' worth of bits.
>
> > lib/xbitmap.c | 444 +++++++++++++++++++++++++++++++
>
> Please, split tests to a separate module.
Hah, I just did this two days ago! I didn't publish it yet, but I also made
it compile both in userspace and as a kernel module.
It's the top two commits here:
http://git.infradead.org/users/willy/linux-dax.git/shortlog/refs/heads/xarray-2018-02-12
Note this is a complete rewrite compared to the version presented here; it
sits on top of the XArray and no longer has a preload interface. It has a
superset of the IDA functionality.
^ permalink raw reply
* [RFC PATCH v3 3/3] virtio_net: Enable alternate datapath without creating an additional netdev
From: Sridhar Samudrala @ 2018-02-16 18:11 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh
In-Reply-To: <1518804682-16881-1-git-send-email-sridhar.samudrala@intel.com>
This patch addresses the issues that were seen with the 3 netdev model by
avoiding the creation of an additional netdev. Instead the bypass state
information is tracked in the original netdev and a different set of
ndo_ops and ethtool_ops are used when BACKUP feature is enabled.
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/virtio_net.c | 283 +++++++++++++++++------------------------------
1 file changed, 101 insertions(+), 182 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 14679806c1b1..c85b2949f151 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -154,7 +154,7 @@ struct virtnet_bypass_info {
struct net_device __rcu *active_netdev;
/* virtio_net netdev */
- struct net_device __rcu *backup_netdev;
+ struct net_device *backup_netdev;
/* active netdev stats */
struct rtnl_link_stats64 active_stats;
@@ -229,8 +229,8 @@ struct virtnet_info {
unsigned long guest_offloads;
- /* upper netdev created when BACKUP feature enabled */
- struct net_device *bypass_netdev;
+ /* bypass state maintained when BACKUP feature is enabled */
+ struct virtnet_bypass_info *vbi;
};
struct padded_vnet_hdr {
@@ -2285,6 +2285,22 @@ static bool virtnet_bypass_xmit_ready(struct net_device *dev)
return netif_running(dev) && netif_carrier_ok(dev);
}
+static bool virtnet_bypass_active_ready(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
+ struct net_device *active;
+
+ if (!vbi)
+ return false;
+
+ active = rcu_dereference(vbi->active_netdev);
+ if (!active || !virtnet_bypass_xmit_ready(active))
+ return false;
+
+ return true;
+}
+
static void virtnet_config_changed_work(struct work_struct *work)
{
struct virtnet_info *vi =
@@ -2312,7 +2328,7 @@ static void virtnet_config_changed_work(struct work_struct *work)
virtnet_update_settings(vi);
netif_carrier_on(vi->dev);
netif_tx_wake_all_queues(vi->dev);
- } else {
+ } else if (!virtnet_bypass_active_ready(vi->dev)) {
netif_carrier_off(vi->dev);
netif_tx_stop_all_queues(vi->dev);
}
@@ -2501,7 +2517,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
if (vi->has_cvq) {
vi->cvq = vqs[total_vqs - 1];
- if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
+ if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN) &&
+ !virtio_has_feature(vi->vdev, VIRTIO_NET_F_BACKUP))
vi->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
}
@@ -2690,62 +2707,54 @@ virtnet_bypass_child_open(struct net_device *dev,
static int virtnet_bypass_open(struct net_device *dev)
{
- struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *child_netdev;
-
- netif_carrier_off(dev);
- netif_tx_wake_all_queues(dev);
+ int err;
child_netdev = rtnl_dereference(vbi->active_netdev);
if (child_netdev)
virtnet_bypass_child_open(dev, child_netdev);
- child_netdev = rtnl_dereference(vbi->backup_netdev);
- if (child_netdev)
- virtnet_bypass_child_open(dev, child_netdev);
+ err = virtnet_open(dev);
+ if (err < 0) {
+ dev_close(child_netdev);
+ return err;
+ }
return 0;
}
static int virtnet_bypass_close(struct net_device *dev)
{
- struct virtnet_bypass_info *vi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *child_netdev;
- netif_tx_disable(dev);
+ virtnet_close(dev);
- child_netdev = rtnl_dereference(vi->active_netdev);
- if (child_netdev)
- dev_close(child_netdev);
+ if (!vbi)
+ goto done;
- child_netdev = rtnl_dereference(vi->backup_netdev);
+ child_netdev = rtnl_dereference(vbi->active_netdev);
if (child_netdev)
dev_close(child_netdev);
+done:
return 0;
}
-static netdev_tx_t
-virtnet_bypass_drop_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- atomic_long_inc(&dev->tx_dropped);
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
-}
-
static netdev_tx_t
virtnet_bypass_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *xmit_dev;
/* Try xmit via active netdev followed by backup netdev */
xmit_dev = rcu_dereference_bh(vbi->active_netdev);
- if (!xmit_dev || !virtnet_bypass_xmit_ready(xmit_dev)) {
- xmit_dev = rcu_dereference_bh(vbi->backup_netdev);
- if (!xmit_dev || !virtnet_bypass_xmit_ready(xmit_dev))
- return virtnet_bypass_drop_xmit(skb, dev);
- }
+ if (!xmit_dev || !virtnet_bypass_xmit_ready(xmit_dev))
+ return start_xmit(skb, dev);
skb->dev = xmit_dev;
skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
@@ -2810,7 +2819,8 @@ static void
virtnet_bypass_get_stats(struct net_device *dev,
struct rtnl_link_stats64 *stats)
{
- struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
const struct rtnl_link_stats64 *new;
struct rtnl_link_stats64 temp;
struct net_device *child_netdev;
@@ -2827,12 +2837,10 @@ virtnet_bypass_get_stats(struct net_device *dev,
memcpy(&vbi->active_stats, new, sizeof(*new));
}
- child_netdev = rcu_dereference(vbi->backup_netdev);
- if (child_netdev) {
- new = dev_get_stats(child_netdev, &temp);
- virtnet_bypass_fold_stats(stats, new, &vbi->backup_stats);
- memcpy(&vbi->backup_stats, new, sizeof(*new));
- }
+ memset(&temp, 0, sizeof(temp));
+ virtnet_stats(vbi->backup_netdev, &temp);
+ virtnet_bypass_fold_stats(stats, &temp, &vbi->backup_stats);
+ memcpy(&vbi->backup_stats, &temp, sizeof(temp));
rcu_read_unlock();
@@ -2842,7 +2850,8 @@ virtnet_bypass_get_stats(struct net_device *dev,
static int virtnet_bypass_change_mtu(struct net_device *dev, int new_mtu)
{
- struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *child_netdev;
int ret = 0;
@@ -2853,15 +2862,6 @@ static int virtnet_bypass_change_mtu(struct net_device *dev, int new_mtu)
return ret;
}
- child_netdev = rcu_dereference(vbi->backup_netdev);
- if (child_netdev) {
- ret = dev_set_mtu(child_netdev, new_mtu);
- if (ret)
- netdev_err(child_netdev,
- "Unexpected failure to set mtu to %d\n",
- new_mtu);
- }
-
dev->mtu = new_mtu;
return 0;
}
@@ -2881,20 +2881,13 @@ static int
virtnet_bypass_ethtool_get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *cmd)
{
- struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *child_netdev;
child_netdev = rtnl_dereference(vbi->active_netdev);
- if (!child_netdev || !virtnet_bypass_xmit_ready(child_netdev)) {
- child_netdev = rtnl_dereference(vbi->backup_netdev);
- if (!child_netdev || !virtnet_bypass_xmit_ready(child_netdev)) {
- cmd->base.duplex = DUPLEX_UNKNOWN;
- cmd->base.port = PORT_OTHER;
- cmd->base.speed = SPEED_UNKNOWN;
-
- return 0;
- }
- }
+ if (!child_netdev || !virtnet_bypass_xmit_ready(child_netdev))
+ return virtnet_get_link_ksettings(dev, cmd);
return __ethtool_get_link_ksettings(child_netdev, cmd);
}
@@ -2944,14 +2937,15 @@ get_virtnet_bypass_byref(struct net_device *child_netdev)
for_each_netdev(net, dev) {
struct virtnet_bypass_info *vbi;
+ struct virtnet_info *vi;
if (dev->netdev_ops != &virtnet_bypass_netdev_ops)
continue; /* not a virtnet_bypass device */
- vbi = netdev_priv(dev);
+ vi = netdev_priv(dev);
+ vbi = vi->vbi;
- if ((rtnl_dereference(vbi->active_netdev) == child_netdev) ||
- (rtnl_dereference(vbi->backup_netdev) == child_netdev))
+ if (rtnl_dereference(vbi->active_netdev) == child_netdev)
return dev; /* a match */
}
@@ -2974,9 +2968,9 @@ static rx_handler_result_t virtnet_bypass_handle_frame(struct sk_buff **pskb)
static int virtnet_bypass_register_child(struct net_device *child_netdev)
{
+ struct net_device *dev, *active;
struct virtnet_bypass_info *vbi;
- struct net_device *dev;
- bool backup;
+ struct virtnet_info *vi;
int ret;
if (child_netdev->addr_len != ETH_ALEN)
@@ -2991,14 +2985,14 @@ static int virtnet_bypass_register_child(struct net_device *child_netdev)
if (!dev)
return NOTIFY_DONE;
- vbi = netdev_priv(dev);
- backup = (child_netdev->dev.parent == dev->dev.parent);
- if (backup ? rtnl_dereference(vbi->backup_netdev) :
- rtnl_dereference(vbi->active_netdev)) {
+ vi = netdev_priv(dev);
+ vbi = vi->vbi;
+
+ active = rtnl_dereference(vbi->active_netdev);
+ if (active) {
netdev_info(dev,
"%s attempting to join bypass dev when %s already present\n",
- child_netdev->name,
- backup ? "backup" : "active");
+ child_netdev->name, active->name);
return NOTIFY_DONE;
}
@@ -3030,7 +3024,7 @@ static int virtnet_bypass_register_child(struct net_device *child_netdev)
}
}
- /* Align MTU of child with master */
+ /* Align MTU of child with virtio */
ret = dev_set_mtu(child_netdev, dev->mtu);
if (ret) {
netdev_err(dev,
@@ -3044,15 +3038,10 @@ static int virtnet_bypass_register_child(struct net_device *child_netdev)
netdev_info(dev, "registering %s\n", child_netdev->name);
dev_hold(child_netdev);
- if (backup) {
- rcu_assign_pointer(vbi->backup_netdev, child_netdev);
- dev_get_stats(vbi->backup_netdev, &vbi->backup_stats);
- } else {
- rcu_assign_pointer(vbi->active_netdev, child_netdev);
- dev_get_stats(vbi->active_netdev, &vbi->active_stats);
- dev->min_mtu = child_netdev->min_mtu;
- dev->max_mtu = child_netdev->max_mtu;
- }
+ rcu_assign_pointer(vbi->active_netdev, child_netdev);
+ dev_get_stats(vbi->active_netdev, &vbi->active_stats);
+ dev->min_mtu = child_netdev->min_mtu;
+ dev->max_mtu = child_netdev->max_mtu;
return NOTIFY_OK;
@@ -3070,13 +3059,15 @@ static int virtnet_bypass_register_child(struct net_device *child_netdev)
static int virtnet_bypass_unregister_child(struct net_device *child_netdev)
{
struct virtnet_bypass_info *vbi;
- struct net_device *dev, *backup;
+ struct virtnet_info *vi;
+ struct net_device *dev;
dev = get_virtnet_bypass_byref(child_netdev);
if (!dev)
return NOTIFY_DONE;
- vbi = netdev_priv(dev);
+ vi = netdev_priv(dev);
+ vbi = vi->vbi;
netdev_info(dev, "unregistering %s\n", child_netdev->name);
@@ -3084,41 +3075,35 @@ static int virtnet_bypass_unregister_child(struct net_device *child_netdev)
netdev_upper_dev_unlink(child_netdev, dev);
child_netdev->flags &= ~IFF_SLAVE;
- if (child_netdev->dev.parent == dev->dev.parent) {
- RCU_INIT_POINTER(vbi->backup_netdev, NULL);
- } else {
- RCU_INIT_POINTER(vbi->active_netdev, NULL);
- backup = rtnl_dereference(vbi->backup_netdev);
- if (backup) {
- dev->min_mtu = backup->min_mtu;
- dev->max_mtu = backup->max_mtu;
- }
- }
+ RCU_INIT_POINTER(vbi->active_netdev, NULL);
+ dev->min_mtu = MIN_MTU;
+ dev->max_mtu = MAX_MTU;
dev_put(child_netdev);
+ if (!(vi->status & VIRTIO_NET_S_LINK_UP)) {
+ netif_carrier_off(dev);
+ netif_tx_stop_all_queues(dev);
+ }
+
return NOTIFY_OK;
}
static int virtnet_bypass_update_link(struct net_device *child_netdev)
{
- struct net_device *dev, *active, *backup;
- struct virtnet_bypass_info *vbi;
+ struct virtnet_info *vi;
+ struct net_device *dev;
dev = get_virtnet_bypass_byref(child_netdev);
- if (!dev || !netif_running(dev))
+ if (!dev)
return NOTIFY_DONE;
- vbi = netdev_priv(dev);
-
- active = rtnl_dereference(vbi->active_netdev);
- backup = rtnl_dereference(vbi->backup_netdev);
+ vi = netdev_priv(dev);
- if ((active && virtnet_bypass_xmit_ready(active)) ||
- (backup && virtnet_bypass_xmit_ready(backup))) {
+ if (virtnet_bypass_xmit_ready(child_netdev)) {
netif_carrier_on(dev);
netif_tx_wake_all_queues(dev);
- } else {
+ } else if (!(vi->status & VIRTIO_NET_S_LINK_UP)) {
netif_carrier_off(dev);
netif_tx_stop_all_queues(dev);
}
@@ -3169,107 +3154,41 @@ static struct notifier_block virtnet_bypass_notifier = {
static int virtnet_bypass_create(struct virtnet_info *vi)
{
- struct net_device *backup_netdev = vi->dev;
- struct device *dev = &vi->vdev->dev;
- struct net_device *bypass_netdev;
- int res;
+ struct net_device *dev = vi->dev;
+ struct virtnet_bypass_info *vbi;
- /* Alloc at least 2 queues, for now we are going with 16 assuming
- * that most devices being bonded won't have too many queues.
- */
- bypass_netdev = alloc_etherdev_mq(sizeof(struct virtnet_bypass_info),
- 16);
- if (!bypass_netdev) {
- dev_err(dev, "Unable to allocate bypass_netdev!\n");
+ vbi = kzalloc(sizeof(*vbi), GFP_KERNEL);
+ if (!vbi)
return -ENOMEM;
- }
-
- dev_net_set(bypass_netdev, dev_net(backup_netdev));
- SET_NETDEV_DEV(bypass_netdev, dev);
-
- bypass_netdev->netdev_ops = &virtnet_bypass_netdev_ops;
- bypass_netdev->ethtool_ops = &virtnet_bypass_ethtool_ops;
-
- /* Initialize the device options */
- bypass_netdev->flags |= IFF_MASTER;
- bypass_netdev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT |
- IFF_NO_QUEUE;
- bypass_netdev->priv_flags &= ~(IFF_XMIT_DST_RELEASE |
- IFF_TX_SKB_SHARING);
-
- /* don't acquire bypass netdev's netif_tx_lock when transmitting */
- bypass_netdev->features |= NETIF_F_LLTX;
-
- /* Don't allow bypass devices to change network namespaces. */
- bypass_netdev->features |= NETIF_F_NETNS_LOCAL;
-
- bypass_netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG |
- NETIF_F_FRAGLIST | NETIF_F_ALL_TSO |
- NETIF_F_HIGHDMA | NETIF_F_LRO;
-
- bypass_netdev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
- bypass_netdev->features |= bypass_netdev->hw_features;
-
- /* For now treat bypass netdev as VLAN challenged since we
- * cannot assume VLAN functionality with a VF
- */
- bypass_netdev->features |= NETIF_F_VLAN_CHALLENGED;
-
- memcpy(bypass_netdev->dev_addr, backup_netdev->dev_addr,
- bypass_netdev->addr_len);
- bypass_netdev->min_mtu = backup_netdev->min_mtu;
- bypass_netdev->max_mtu = backup_netdev->max_mtu;
+ dev->netdev_ops = &virtnet_bypass_netdev_ops;
+ dev->ethtool_ops = &virtnet_bypass_ethtool_ops;
- res = register_netdev(bypass_netdev);
- if (res < 0) {
- dev_err(dev, "Unable to register bypass_netdev!\n");
- free_netdev(bypass_netdev);
- return res;
- }
-
- netif_carrier_off(bypass_netdev);
-
- vi->bypass_netdev = bypass_netdev;
-
- /* Change the name of the backup interface to vbkup0
- * we may need to revisit naming later but this gets it out
- * of the way for now.
- */
- strcpy(backup_netdev->name, "vbkup%d");
+ vbi->backup_netdev = dev;
+ virtnet_stats(vbi->backup_netdev, &vbi->backup_stats);
+ vi->vbi = vbi;
return 0;
}
static void virtnet_bypass_destroy(struct virtnet_info *vi)
{
- struct net_device *bypass_netdev = vi->bypass_netdev;
- struct virtnet_bypass_info *vbi;
+ struct virtnet_bypass_info *vbi = vi->vbi;
struct net_device *child_netdev;
- /* no device found, nothing to free */
- if (!bypass_netdev)
+ if (!vbi)
return;
- vbi = netdev_priv(bypass_netdev);
-
- netif_device_detach(bypass_netdev);
-
rtnl_lock();
child_netdev = rtnl_dereference(vbi->active_netdev);
if (child_netdev)
virtnet_bypass_unregister_child(child_netdev);
- child_netdev = rtnl_dereference(vbi->backup_netdev);
- if (child_netdev)
- virtnet_bypass_unregister_child(child_netdev);
-
- unregister_netdevice(bypass_netdev);
-
rtnl_unlock();
- free_netdev(bypass_netdev);
+ kfree(vbi);
+ vi->vbi = NULL;
}
static int virtnet_probe(struct virtio_device *vdev)
--
2.14.3
^ permalink raw reply related
* [RFC PATCH v3 2/3] virtio_net: Extend virtio to use VF datapath when available
From: Sridhar Samudrala @ 2018-02-16 18:11 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh
In-Reply-To: <1518804682-16881-1-git-send-email-sridhar.samudrala@intel.com>
This patch enables virtio_net to switch over to a VF datapath when a VF
netdev is present with the same MAC address. It allows live migration
of a VM with a direct attached VF without the need to setup a bond/team
between a VF and virtio net device in the guest.
The hypervisor needs to enable only one datapath at any time so that
packets don't get looped back to the VM over the other datapath. When a VF
is plugged, the virtio datapath link state can be marked as down. The
hypervisor needs to unplug the VF device from the guest on the source host
and reset the MAC filter of the VF to initiate failover of datapath to
virtio before starting the migration. After the migration is completed,
the destination hypervisor sets the MAC filter on the VF and plugs it back
to the guest to switch over to VF datapath.
When BACKUP feature is enabled, an additional netdev(bypass netdev) is
created that acts as a master device and tracks the state of the 2 lower
netdevs. The original virtio_net netdev is marked as 'backup' netdev and a
passthru device with the same MAC is registered as 'active' netdev.
This patch is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
---
drivers/net/virtio_net.c | 639 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 638 insertions(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index bcd13fe906ca..14679806c1b1 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -30,6 +30,7 @@
#include <linux/cpu.h>
#include <linux/average.h>
#include <linux/filter.h>
+#include <linux/netdevice.h>
#include <net/route.h>
#include <net/xdp.h>
@@ -147,6 +148,27 @@ struct receive_queue {
struct xdp_rxq_info xdp_rxq;
};
+/* bypass state maintained when BACKUP feature is enabled */
+struct virtnet_bypass_info {
+ /* passthru netdev with same MAC */
+ struct net_device __rcu *active_netdev;
+
+ /* virtio_net netdev */
+ struct net_device __rcu *backup_netdev;
+
+ /* active netdev stats */
+ struct rtnl_link_stats64 active_stats;
+
+ /* backup netdev stats */
+ struct rtnl_link_stats64 backup_stats;
+
+ /* aggregated stats */
+ struct rtnl_link_stats64 bypass_stats;
+
+ /* spinlock while updating stats */
+ spinlock_t stats_lock;
+};
+
struct virtnet_info {
struct virtio_device *vdev;
struct virtqueue *cvq;
@@ -206,6 +228,9 @@ struct virtnet_info {
u32 speed;
unsigned long guest_offloads;
+
+ /* upper netdev created when BACKUP feature enabled */
+ struct net_device *bypass_netdev;
};
struct padded_vnet_hdr {
@@ -2255,6 +2280,11 @@ static const struct net_device_ops virtnet_netdev = {
.ndo_features_check = passthru_features_check,
};
+static bool virtnet_bypass_xmit_ready(struct net_device *dev)
+{
+ return netif_running(dev) && netif_carrier_ok(dev);
+}
+
static void virtnet_config_changed_work(struct work_struct *work)
{
struct virtnet_info *vi =
@@ -2647,6 +2677,601 @@ static int virtnet_validate(struct virtio_device *vdev)
return 0;
}
+static void
+virtnet_bypass_child_open(struct net_device *dev,
+ struct net_device *child_netdev)
+{
+ int err = dev_open(child_netdev);
+
+ if (err)
+ netdev_warn(dev, "unable to open slave: %s: %d\n",
+ child_netdev->name, err);
+}
+
+static int virtnet_bypass_open(struct net_device *dev)
+{
+ struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct net_device *child_netdev;
+
+ netif_carrier_off(dev);
+ netif_tx_wake_all_queues(dev);
+
+ child_netdev = rtnl_dereference(vbi->active_netdev);
+ if (child_netdev)
+ virtnet_bypass_child_open(dev, child_netdev);
+
+ child_netdev = rtnl_dereference(vbi->backup_netdev);
+ if (child_netdev)
+ virtnet_bypass_child_open(dev, child_netdev);
+
+ return 0;
+}
+
+static int virtnet_bypass_close(struct net_device *dev)
+{
+ struct virtnet_bypass_info *vi = netdev_priv(dev);
+ struct net_device *child_netdev;
+
+ netif_tx_disable(dev);
+
+ child_netdev = rtnl_dereference(vi->active_netdev);
+ if (child_netdev)
+ dev_close(child_netdev);
+
+ child_netdev = rtnl_dereference(vi->backup_netdev);
+ if (child_netdev)
+ dev_close(child_netdev);
+
+ return 0;
+}
+
+static netdev_tx_t
+virtnet_bypass_drop_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ atomic_long_inc(&dev->tx_dropped);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static netdev_tx_t
+virtnet_bypass_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct net_device *xmit_dev;
+
+ /* Try xmit via active netdev followed by backup netdev */
+ xmit_dev = rcu_dereference_bh(vbi->active_netdev);
+ if (!xmit_dev || !virtnet_bypass_xmit_ready(xmit_dev)) {
+ xmit_dev = rcu_dereference_bh(vbi->backup_netdev);
+ if (!xmit_dev || !virtnet_bypass_xmit_ready(xmit_dev))
+ return virtnet_bypass_drop_xmit(skb, dev);
+ }
+
+ skb->dev = xmit_dev;
+ skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+
+ return dev_queue_xmit(skb);
+}
+
+static u16
+virtnet_bypass_select_queue(struct net_device *dev, struct sk_buff *skb,
+ void *accel_priv, select_queue_fallback_t fallback)
+{
+ /* This helper function exists to help dev_pick_tx get the correct
+ * destination queue. Using a helper function skips a call to
+ * skb_tx_hash and will put the skbs in the queue we expect on their
+ * way down to the bonding driver.
+ */
+ u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+ /* Save the original txq to restore before passing to the driver */
+ qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
+
+ if (unlikely(txq >= dev->real_num_tx_queues)) {
+ do {
+ txq -= dev->real_num_tx_queues;
+ } while (txq >= dev->real_num_tx_queues);
+ }
+
+ return txq;
+}
+
+/* fold stats, assuming all rtnl_link_stats64 fields are u64, but
+ * that some drivers can provide 32bit values only.
+ */
+static void
+virtnet_bypass_fold_stats(struct rtnl_link_stats64 *_res,
+ const struct rtnl_link_stats64 *_new,
+ const struct rtnl_link_stats64 *_old)
+{
+ const u64 *new = (const u64 *)_new;
+ const u64 *old = (const u64 *)_old;
+ u64 *res = (u64 *)_res;
+ int i;
+
+ for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) {
+ u64 nv = new[i];
+ u64 ov = old[i];
+ s64 delta = nv - ov;
+
+ /* detects if this particular field is 32bit only */
+ if (((nv | ov) >> 32) == 0)
+ delta = (s64)(s32)((u32)nv - (u32)ov);
+
+ /* filter anomalies, some drivers reset their stats
+ * at down/up events.
+ */
+ if (delta > 0)
+ res[i] += delta;
+ }
+}
+
+static void
+virtnet_bypass_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ const struct rtnl_link_stats64 *new;
+ struct rtnl_link_stats64 temp;
+ struct net_device *child_netdev;
+
+ spin_lock(&vbi->stats_lock);
+ memcpy(stats, &vbi->bypass_stats, sizeof(*stats));
+
+ rcu_read_lock();
+
+ child_netdev = rcu_dereference(vbi->active_netdev);
+ if (child_netdev) {
+ new = dev_get_stats(child_netdev, &temp);
+ virtnet_bypass_fold_stats(stats, new, &vbi->active_stats);
+ memcpy(&vbi->active_stats, new, sizeof(*new));
+ }
+
+ child_netdev = rcu_dereference(vbi->backup_netdev);
+ if (child_netdev) {
+ new = dev_get_stats(child_netdev, &temp);
+ virtnet_bypass_fold_stats(stats, new, &vbi->backup_stats);
+ memcpy(&vbi->backup_stats, new, sizeof(*new));
+ }
+
+ rcu_read_unlock();
+
+ memcpy(&vbi->bypass_stats, stats, sizeof(*stats));
+ spin_unlock(&vbi->stats_lock);
+}
+
+static int virtnet_bypass_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct net_device *child_netdev;
+ int ret = 0;
+
+ child_netdev = rcu_dereference(vbi->active_netdev);
+ if (child_netdev) {
+ ret = dev_set_mtu(child_netdev, new_mtu);
+ if (ret)
+ return ret;
+ }
+
+ child_netdev = rcu_dereference(vbi->backup_netdev);
+ if (child_netdev) {
+ ret = dev_set_mtu(child_netdev, new_mtu);
+ if (ret)
+ netdev_err(child_netdev,
+ "Unexpected failure to set mtu to %d\n",
+ new_mtu);
+ }
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static const struct net_device_ops virtnet_bypass_netdev_ops = {
+ .ndo_open = virtnet_bypass_open,
+ .ndo_stop = virtnet_bypass_close,
+ .ndo_start_xmit = virtnet_bypass_start_xmit,
+ .ndo_select_queue = virtnet_bypass_select_queue,
+ .ndo_get_stats64 = virtnet_bypass_get_stats,
+ .ndo_change_mtu = virtnet_bypass_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_features_check = passthru_features_check,
+};
+
+static int
+virtnet_bypass_ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct virtnet_bypass_info *vbi = netdev_priv(dev);
+ struct net_device *child_netdev;
+
+ child_netdev = rtnl_dereference(vbi->active_netdev);
+ if (!child_netdev || !virtnet_bypass_xmit_ready(child_netdev)) {
+ child_netdev = rtnl_dereference(vbi->backup_netdev);
+ if (!child_netdev || !virtnet_bypass_xmit_ready(child_netdev)) {
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ cmd->base.port = PORT_OTHER;
+ cmd->base.speed = SPEED_UNKNOWN;
+
+ return 0;
+ }
+ }
+
+ return __ethtool_get_link_ksettings(child_netdev, cmd);
+}
+
+#define BYPASS_DRV_NAME "virtnet_bypass"
+#define BYPASS_DRV_VERSION "0.1"
+
+static void
+virtnet_bypass_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strlcpy(drvinfo->driver, BYPASS_DRV_NAME, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, BYPASS_DRV_VERSION, sizeof(drvinfo->version));
+}
+
+static const struct ethtool_ops virtnet_bypass_ethtool_ops = {
+ .get_drvinfo = virtnet_bypass_ethtool_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_link_ksettings = virtnet_bypass_ethtool_get_link_ksettings,
+};
+
+static struct net_device *
+get_virtnet_bypass_bymac(struct net *net, const u8 *mac)
+{
+ struct net_device *dev;
+
+ ASSERT_RTNL();
+
+ for_each_netdev(net, dev) {
+ if (dev->netdev_ops != &virtnet_bypass_netdev_ops)
+ continue; /* not a virtnet_bypass device */
+
+ if (ether_addr_equal(mac, dev->perm_addr))
+ return dev;
+ }
+
+ return NULL;
+}
+
+static struct net_device *
+get_virtnet_bypass_byref(struct net_device *child_netdev)
+{
+ struct net *net = dev_net(child_netdev);
+ struct net_device *dev;
+
+ ASSERT_RTNL();
+
+ for_each_netdev(net, dev) {
+ struct virtnet_bypass_info *vbi;
+
+ if (dev->netdev_ops != &virtnet_bypass_netdev_ops)
+ continue; /* not a virtnet_bypass device */
+
+ vbi = netdev_priv(dev);
+
+ if ((rtnl_dereference(vbi->active_netdev) == child_netdev) ||
+ (rtnl_dereference(vbi->backup_netdev) == child_netdev))
+ return dev; /* a match */
+ }
+
+ return NULL;
+}
+
+/* Called when child dev is injecting data into network stack.
+ * Change the associated network device from lower dev to virtio.
+ * note: already called with rcu_read_lock
+ */
+static rx_handler_result_t virtnet_bypass_handle_frame(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct net_device *ndev = rcu_dereference(skb->dev->rx_handler_data);
+
+ skb->dev = ndev;
+
+ return RX_HANDLER_ANOTHER;
+}
+
+static int virtnet_bypass_register_child(struct net_device *child_netdev)
+{
+ struct virtnet_bypass_info *vbi;
+ struct net_device *dev;
+ bool backup;
+ int ret;
+
+ if (child_netdev->addr_len != ETH_ALEN)
+ return NOTIFY_DONE;
+
+ /* We will use the MAC address to locate the virtnet_bypass netdev
+ * to associate with the child netdev. If we don't find a matching
+ * bypass netdev, move on.
+ */
+ dev = get_virtnet_bypass_bymac(dev_net(child_netdev),
+ child_netdev->perm_addr);
+ if (!dev)
+ return NOTIFY_DONE;
+
+ vbi = netdev_priv(dev);
+ backup = (child_netdev->dev.parent == dev->dev.parent);
+ if (backup ? rtnl_dereference(vbi->backup_netdev) :
+ rtnl_dereference(vbi->active_netdev)) {
+ netdev_info(dev,
+ "%s attempting to join bypass dev when %s already present\n",
+ child_netdev->name,
+ backup ? "backup" : "active");
+ return NOTIFY_DONE;
+ }
+
+ ret = netdev_rx_handler_register(child_netdev,
+ virtnet_bypass_handle_frame, dev);
+ if (ret != 0) {
+ netdev_err(child_netdev,
+ "can not register bypass receive handler (err = %d)\n",
+ ret);
+ goto rx_handler_failed;
+ }
+
+ ret = netdev_upper_dev_link(child_netdev, dev, NULL);
+ if (ret != 0) {
+ netdev_err(child_netdev,
+ "can not set master device %s (err = %d)\n",
+ dev->name, ret);
+ goto upper_link_failed;
+ }
+
+ child_netdev->flags |= IFF_SLAVE;
+
+ if (netif_running(dev)) {
+ ret = dev_open(child_netdev);
+ if (ret && (ret != -EBUSY)) {
+ netdev_err(dev, "Opening child %s failed ret:%d\n",
+ child_netdev->name, ret);
+ goto err_interface_up;
+ }
+ }
+
+ /* Align MTU of child with master */
+ ret = dev_set_mtu(child_netdev, dev->mtu);
+ if (ret) {
+ netdev_err(dev,
+ "unable to change mtu of %s to %u register failed\n",
+ child_netdev->name, dev->mtu);
+ goto err_set_mtu;
+ }
+
+ call_netdevice_notifiers(NETDEV_JOIN, child_netdev);
+
+ netdev_info(dev, "registering %s\n", child_netdev->name);
+
+ dev_hold(child_netdev);
+ if (backup) {
+ rcu_assign_pointer(vbi->backup_netdev, child_netdev);
+ dev_get_stats(vbi->backup_netdev, &vbi->backup_stats);
+ } else {
+ rcu_assign_pointer(vbi->active_netdev, child_netdev);
+ dev_get_stats(vbi->active_netdev, &vbi->active_stats);
+ dev->min_mtu = child_netdev->min_mtu;
+ dev->max_mtu = child_netdev->max_mtu;
+ }
+
+ return NOTIFY_OK;
+
+err_set_mtu:
+ dev_close(child_netdev);
+err_interface_up:
+ netdev_upper_dev_unlink(child_netdev, dev);
+ child_netdev->flags &= ~IFF_SLAVE;
+upper_link_failed:
+ netdev_rx_handler_unregister(child_netdev);
+rx_handler_failed:
+ return NOTIFY_DONE;
+}
+
+static int virtnet_bypass_unregister_child(struct net_device *child_netdev)
+{
+ struct virtnet_bypass_info *vbi;
+ struct net_device *dev, *backup;
+
+ dev = get_virtnet_bypass_byref(child_netdev);
+ if (!dev)
+ return NOTIFY_DONE;
+
+ vbi = netdev_priv(dev);
+
+ netdev_info(dev, "unregistering %s\n", child_netdev->name);
+
+ netdev_rx_handler_unregister(child_netdev);
+ netdev_upper_dev_unlink(child_netdev, dev);
+ child_netdev->flags &= ~IFF_SLAVE;
+
+ if (child_netdev->dev.parent == dev->dev.parent) {
+ RCU_INIT_POINTER(vbi->backup_netdev, NULL);
+ } else {
+ RCU_INIT_POINTER(vbi->active_netdev, NULL);
+ backup = rtnl_dereference(vbi->backup_netdev);
+ if (backup) {
+ dev->min_mtu = backup->min_mtu;
+ dev->max_mtu = backup->max_mtu;
+ }
+ }
+
+ dev_put(child_netdev);
+
+ return NOTIFY_OK;
+}
+
+static int virtnet_bypass_update_link(struct net_device *child_netdev)
+{
+ struct net_device *dev, *active, *backup;
+ struct virtnet_bypass_info *vbi;
+
+ dev = get_virtnet_bypass_byref(child_netdev);
+ if (!dev || !netif_running(dev))
+ return NOTIFY_DONE;
+
+ vbi = netdev_priv(dev);
+
+ active = rtnl_dereference(vbi->active_netdev);
+ backup = rtnl_dereference(vbi->backup_netdev);
+
+ if ((active && virtnet_bypass_xmit_ready(active)) ||
+ (backup && virtnet_bypass_xmit_ready(backup))) {
+ netif_carrier_on(dev);
+ netif_tx_wake_all_queues(dev);
+ } else {
+ netif_carrier_off(dev);
+ netif_tx_stop_all_queues(dev);
+ }
+
+ return NOTIFY_OK;
+}
+
+static int
+virtnet_bypass_event(struct notifier_block *this, unsigned long event,
+ void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ /* Skip our own events */
+ if (event_dev->netdev_ops == &virtnet_bypass_netdev_ops)
+ return NOTIFY_DONE;
+
+ /* Avoid non-Ethernet type devices */
+ if (event_dev->type != ARPHRD_ETHER)
+ return NOTIFY_DONE;
+
+ /* Avoid Vlan dev with same MAC registering as child dev */
+ if (is_vlan_dev(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid Bonding master dev with same MAC registering as child dev */
+ if ((event_dev->priv_flags & IFF_BONDING) &&
+ (event_dev->flags & IFF_MASTER))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return virtnet_bypass_register_child(event_dev);
+ case NETDEV_UNREGISTER:
+ return virtnet_bypass_unregister_child(event_dev);
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ case NETDEV_CHANGE:
+ return virtnet_bypass_update_link(event_dev);
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block virtnet_bypass_notifier = {
+ .notifier_call = virtnet_bypass_event,
+};
+
+static int virtnet_bypass_create(struct virtnet_info *vi)
+{
+ struct net_device *backup_netdev = vi->dev;
+ struct device *dev = &vi->vdev->dev;
+ struct net_device *bypass_netdev;
+ int res;
+
+ /* Alloc at least 2 queues, for now we are going with 16 assuming
+ * that most devices being bonded won't have too many queues.
+ */
+ bypass_netdev = alloc_etherdev_mq(sizeof(struct virtnet_bypass_info),
+ 16);
+ if (!bypass_netdev) {
+ dev_err(dev, "Unable to allocate bypass_netdev!\n");
+ return -ENOMEM;
+ }
+
+ dev_net_set(bypass_netdev, dev_net(backup_netdev));
+ SET_NETDEV_DEV(bypass_netdev, dev);
+
+ bypass_netdev->netdev_ops = &virtnet_bypass_netdev_ops;
+ bypass_netdev->ethtool_ops = &virtnet_bypass_ethtool_ops;
+
+ /* Initialize the device options */
+ bypass_netdev->flags |= IFF_MASTER;
+ bypass_netdev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT |
+ IFF_NO_QUEUE;
+ bypass_netdev->priv_flags &= ~(IFF_XMIT_DST_RELEASE |
+ IFF_TX_SKB_SHARING);
+
+ /* don't acquire bypass netdev's netif_tx_lock when transmitting */
+ bypass_netdev->features |= NETIF_F_LLTX;
+
+ /* Don't allow bypass devices to change network namespaces. */
+ bypass_netdev->features |= NETIF_F_NETNS_LOCAL;
+
+ bypass_netdev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG |
+ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO |
+ NETIF_F_HIGHDMA | NETIF_F_LRO;
+
+ bypass_netdev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
+ bypass_netdev->features |= bypass_netdev->hw_features;
+
+ /* For now treat bypass netdev as VLAN challenged since we
+ * cannot assume VLAN functionality with a VF
+ */
+ bypass_netdev->features |= NETIF_F_VLAN_CHALLENGED;
+
+ memcpy(bypass_netdev->dev_addr, backup_netdev->dev_addr,
+ bypass_netdev->addr_len);
+
+ bypass_netdev->min_mtu = backup_netdev->min_mtu;
+ bypass_netdev->max_mtu = backup_netdev->max_mtu;
+
+ res = register_netdev(bypass_netdev);
+ if (res < 0) {
+ dev_err(dev, "Unable to register bypass_netdev!\n");
+ free_netdev(bypass_netdev);
+ return res;
+ }
+
+ netif_carrier_off(bypass_netdev);
+
+ vi->bypass_netdev = bypass_netdev;
+
+ /* Change the name of the backup interface to vbkup0
+ * we may need to revisit naming later but this gets it out
+ * of the way for now.
+ */
+ strcpy(backup_netdev->name, "vbkup%d");
+
+ return 0;
+}
+
+static void virtnet_bypass_destroy(struct virtnet_info *vi)
+{
+ struct net_device *bypass_netdev = vi->bypass_netdev;
+ struct virtnet_bypass_info *vbi;
+ struct net_device *child_netdev;
+
+ /* no device found, nothing to free */
+ if (!bypass_netdev)
+ return;
+
+ vbi = netdev_priv(bypass_netdev);
+
+ netif_device_detach(bypass_netdev);
+
+ rtnl_lock();
+
+ child_netdev = rtnl_dereference(vbi->active_netdev);
+ if (child_netdev)
+ virtnet_bypass_unregister_child(child_netdev);
+
+ child_netdev = rtnl_dereference(vbi->backup_netdev);
+ if (child_netdev)
+ virtnet_bypass_unregister_child(child_netdev);
+
+ unregister_netdevice(bypass_netdev);
+
+ rtnl_unlock();
+
+ free_netdev(bypass_netdev);
+}
+
static int virtnet_probe(struct virtio_device *vdev)
{
int i, err = -ENOMEM;
@@ -2797,10 +3422,15 @@ static int virtnet_probe(struct virtio_device *vdev)
virtnet_init_settings(dev);
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_BACKUP)) {
+ if (virtnet_bypass_create(vi) != 0)
+ goto free_vqs;
+ }
+
err = register_netdev(dev);
if (err) {
pr_debug("virtio_net: registering device failed\n");
- goto free_vqs;
+ goto free_bypass;
}
virtio_device_ready(vdev);
@@ -2837,6 +3467,8 @@ static int virtnet_probe(struct virtio_device *vdev)
vi->vdev->config->reset(vdev);
unregister_netdev(dev);
+free_bypass:
+ virtnet_bypass_destroy(vi);
free_vqs:
cancel_delayed_work_sync(&vi->refill);
free_receive_page_frags(vi);
@@ -2871,6 +3503,8 @@ static void virtnet_remove(struct virtio_device *vdev)
unregister_netdev(vi->dev);
+ virtnet_bypass_destroy(vi);
+
remove_vq_common(vi);
free_netdev(vi->dev);
@@ -2968,6 +3602,8 @@ static __init int virtio_net_driver_init(void)
ret = register_virtio_driver(&virtio_net_driver);
if (ret)
goto err_virtio;
+
+ register_netdevice_notifier(&virtnet_bypass_notifier);
return 0;
err_virtio:
cpuhp_remove_multi_state(CPUHP_VIRT_NET_DEAD);
@@ -2980,6 +3616,7 @@ module_init(virtio_net_driver_init);
static __exit void virtio_net_driver_exit(void)
{
+ unregister_netdevice_notifier(&virtnet_bypass_notifier);
unregister_virtio_driver(&virtio_net_driver);
cpuhp_remove_multi_state(CPUHP_VIRT_NET_DEAD);
cpuhp_remove_multi_state(virtionet_online);
--
2.14.3
^ permalink raw reply related
* [RFC PATCH v3 1/3] virtio_net: Introduce VIRTIO_NET_F_BACKUP feature bit
From: Sridhar Samudrala @ 2018-02-16 18:11 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh
In-Reply-To: <1518804682-16881-1-git-send-email-sridhar.samudrala@intel.com>
This feature bit can be used by hypervisor to indicate virtio_net device to
act as a backup for another device with the same MAC address.
VIRTIO_NET_F_BACKUP is defined as bit 62 as it is a device feature bit.
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/virtio_net.c | 2 +-
include/uapi/linux/virtio_net.h | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 626c27352ae2..bcd13fe906ca 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2920,7 +2920,7 @@ static struct virtio_device_id id_table[] = {
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
VIRTIO_NET_F_CTRL_MAC_ADDR, \
VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
- VIRTIO_NET_F_SPEED_DUPLEX
+ VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_BACKUP
static unsigned int features[] = {
VIRTNET_FEATURES,
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 5de6ed37695b..c7c35fd1a5ed 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -57,6 +57,9 @@
* Steering */
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
+#define VIRTIO_NET_F_BACKUP 62 /* Act as backup for another device
+ * with the same MAC.
+ */
#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */
#ifndef VIRTIO_NET_NO_LEGACY
--
2.14.3
^ permalink raw reply related
* [RFC PATCH v3 0/3] Enable virtio_net to act as a backup for a passthru device
From: Sridhar Samudrala @ 2018-02-16 18:11 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh
Patch 1 introduces a new feature bit VIRTIO_NET_F_BACKUP that can be
used by hypervisor to indicate that virtio_net interface should act as
a backup for another device with the same MAC address.
Ppatch 2 is in response to the community request for a 3 netdev
solution. However, it creates some issues we'll get into in a moment.
It extends virtio_net to use alternate datapath when available and
registered. When BACKUP feature is enabled, virtio_net driver creates
an additional 'bypass' netdev that acts as a master device and controls
2 slave devices. The original virtio_net netdev is registered as
'backup' netdev and a passthru/vf device with the same MAC gets
registered as 'active' netdev. Both 'bypass' and 'backup' netdevs are
associated with the same 'pci' device. The user accesses the network
interface via 'bypass' netdev. The 'bypass' netdev chooses 'active' netdev
as default for transmits when it is available with link up and running.
We noticed a couple of issues with this approach during testing.
- As both 'bypass' and 'backup' netdevs are associated with the same
virtio pci device, udev tries to rename both of them with the same name
and the 2nd rename will fail. This would be OK as long as the first netdev
to be renamed is the 'bypass' netdev, but the order in which udev gets
to rename the 2 netdevs is not reliable.
- When the 'active' netdev is unplugged OR not present on a destination
system after live migration, the user will see 2 virtio_net netdevs.
Patch 3 refactors much of the changes made in patch 2, which was done on
purpose just to show the solution we recommend as part of one patch set.
If we submit a final version of this, we would combine patch 2/3 together.
This patch removes the creation of an additional netdev, Instead, it
uses a new virtnet_bypass_info struct added to the original 'backup' netdev
to track the 'bypass' information and introduces an additional set of ndo and
ethtool ops that are used when BACKUP feature is enabled.
One difference with the 3 netdev model compared to the 2 netdev model is that
the 'bypass' netdev is created with 'noqueue' qdisc marked as 'NETIF_F_LLTX'.
This avoids going through an additional qdisc and acquiring an additional
qdisc and tx lock during transmits.
If we can replace the qdisc of virtio netdev dynamically, it should be
possible to get these optimizations enabled even with 2 netdev model when
BACKUP feature is enabled.
As this patch series is initially focusing on usecases where hypervisor
fully controls the VM networking and the guest is not expected to directly
configure any hardware settings, it doesn't expose all the ndo/ethtool ops
that are supported by virtio_net at this time. To support additional usecases,
it should be possible to enable additional ops later by caching the state
in virtio netdev and replaying when the 'active' netdev gets registered.
The hypervisor needs to enable only one datapath at any time so that packets
don't get looped back to the VM over the other datapath. When a VF is
plugged, the virtio datapath link state can be marked as down.
At the time of live migration, the hypervisor needs to unplug the VF device
from the guest on the source host and reset the MAC filter of the VF to
initiate failover of datapath to virtio before starting the migration. After
the migration is completed, the destination hypervisor sets the MAC filter
on the VF and plugs it back to the guest to switch over to VF datapath.
This patch is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
Sridhar Samudrala (3):
virtio_net: Introduce VIRTIO_NET_F_BACKUP feature bit
virtio_net: Extend virtio to use VF datapath when available
virtio_net: Enable alternate datapath without creating an additional
netdev
drivers/net/virtio_net.c | 564 +++++++++++++++++++++++++++++++++++++++-
include/uapi/linux/virtio_net.h | 3 +
2 files changed, 563 insertions(+), 4 deletions(-)
--
2.14.3
^ permalink raw reply
* Re: [PATCH v21 1/5] xbitmap: Introduce xbitmap
From: Andy Shevchenko @ 2018-02-16 17:44 UTC (permalink / raw)
To: Wei Wang
Cc: yang.zhang.wz, kvm, Michael S. Tsirkin, Tetsuo Handa,
liliang.opensource, qemu-devel, virtualization, linux-mm,
aarcange, virtio-dev, Matthew Wilcox, Matthew Wilcox, nilal, riel,
cornelia.huck, mhocko, quan.xu0, Linux Kernel Mailing List,
amit.shah, Paolo Bonzini, Andrew Morton, mgorman
In-Reply-To: <1515496262-7533-2-git-send-email-wei.w.wang@intel.com>
On Tue, Jan 9, 2018 at 1:10 PM, Wei Wang <wei.w.wang@intel.com> wrote:
> From: Matthew Wilcox <mawilcox@microsoft.com>
>
> The eXtensible Bitmap is a sparse bitmap representation which is
> efficient for set bits which tend to cluster. It supports up to
> 'unsigned long' worth of bits.
> lib/xbitmap.c | 444 +++++++++++++++++++++++++++++++
Please, split tests to a separate module.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 0/6] crypto: engine - Permit to enqueue all async requests
From: Corentin Labbe @ 2018-02-16 15:36 UTC (permalink / raw)
To: Herbert Xu
Cc: alexandre.torgue, corbet, mst, linux-doc, linux-kernel,
fabien.dessenne, virtualization, linux-sunxi, linux-crypto,
mcoquelin.stm32, davem, linux-arm-kernel
In-Reply-To: <20180215155100.GJ7352@gondor.apana.org.au>
On Thu, Feb 15, 2018 at 11:51:00PM +0800, Herbert Xu wrote:
> On Fri, Jan 26, 2018 at 08:15:28PM +0100, Corentin Labbe wrote:
> > Hello
> >
> > The current crypto_engine support only ahash and ablkcipher request.
> > My first patch which try to add skcipher was Nacked, it will add too many functions
> > and adding other algs(aead, asymetric_key) will make the situation worst.
> >
> > This patchset remove all algs specific stuff and now only process generic crypto_async_request.
> >
> > The requests handler function pointer are now moved out of struct engine and
> > are now stored directly in a crypto_engine_reqctx.
> >
> > The original proposal of Herbert [1] cannot be done completly since the crypto_engine
> > could only dequeue crypto_async_request and it is impossible to access any request_ctx
> > without knowing the underlying request type.
> >
> > So I do something near that was requested: adding crypto_engine_reqctx in TFM context.
> > Note that the current implementation expect that crypto_engine_reqctx
> > is the first member of the context.
> >
> > The first patch is a try to document the crypto engine API.
> > The second patch convert the crypto engine with the new way,
> > while the following patchs convert the 4 existing users of crypto_engine.
> > Note that this split break bisection, so probably the final commit will be all merged.
> >
> > Appart from virtio, all 4 latest patch were compile tested only.
> > But the crypto engine is tested with my new sun8i-ce driver.
> >
> > Regards
> >
> > [1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1474434.html
> >
> > Changes since V1:
> > - renamed crypto_engine_reqctx to crypto_engine_ctx
> > - indentation fix in function parameter
> > - do not export crypto_transfer_request
> > - Add aead support
> > - crypto_finalize_request is now static
> >
> > Changes since RFC:
> > - Added a documentation patch
> > - Added patch for stm32-cryp
> > - Changed parameter of all crypto_engine_op functions from
> > crypto_async_request to void*
> > - Reintroduced crypto_transfer_xxx_request_to_engine functions
> >
> > Corentin Labbe (6):
> > Documentation: crypto: document crypto engine API
> > crypto: engine - Permit to enqueue all async requests
> > crypto: omap: convert to new crypto engine API
> > crypto: virtio: convert to new crypto engine API
> > crypto: stm32-hash: convert to the new crypto engine API
> > crypto: stm32-cryp: convert to the new crypto engine API
>
> All applied. Thanks.
Hello
As mentionned in the cover letter, all patchs (except documentation one) should be squashed.
A kbuild robot reported a build error on cryptodev due to this.
Regards
^ permalink raw reply
* [PATCH 4/4] qxl: drop dummy functions
From: Gerd Hoffmann @ 2018-02-16 13:28 UTC (permalink / raw)
To: dri-devel
Cc: David Airlie, Dave Airlie, open list,
open list:DRM DRIVER FOR QXL VIRTUAL GPU
In-Reply-To: <20180216132832.5374-1-kraxel@redhat.com>
These days drm core checks function pointers everywhere before calling
them. So we can drop a bunch of dummy functions now.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/qxl/qxl_display.c | 50 ---------------------------------------
1 file changed, 50 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index b7dac01f5e..4a8c80bde5 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -456,13 +456,6 @@ qxl_framebuffer_init(struct drm_device *dev,
return 0;
}
-static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
- const struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- return true;
-}
-
static void qxl_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
@@ -476,7 +469,6 @@ static void qxl_crtc_atomic_disable(struct drm_crtc *crtc,
}
static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
- .mode_fixup = qxl_crtc_mode_fixup,
.atomic_flush = qxl_crtc_atomic_flush,
.atomic_enable = qxl_crtc_atomic_enable,
.atomic_disable = qxl_crtc_atomic_disable,
@@ -620,12 +612,6 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
}
}
-static int qxl_plane_atomic_check(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- return 0;
-}
-
static void qxl_cursor_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -831,7 +817,6 @@ static const uint32_t qxl_cursor_plane_formats[] = {
};
static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
- .atomic_check = qxl_plane_atomic_check,
.atomic_update = qxl_cursor_atomic_update,
.atomic_disable = qxl_cursor_atomic_disable,
.prepare_fb = qxl_plane_prepare_fb,
@@ -956,28 +941,6 @@ static int qdev_crtc_init(struct drm_device *dev, int crtc_id)
return r;
}
-static void qxl_enc_dpms(struct drm_encoder *encoder, int mode)
-{
- DRM_DEBUG("\n");
-}
-
-static void qxl_enc_prepare(struct drm_encoder *encoder)
-{
- DRM_DEBUG("\n");
-}
-
-static void qxl_enc_commit(struct drm_encoder *encoder)
-{
- DRM_DEBUG("\n");
-}
-
-static void qxl_enc_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode)
-{
- DRM_DEBUG("\n");
-}
-
static int qxl_conn_get_modes(struct drm_connector *connector)
{
unsigned pwidth = 1024;
@@ -1023,10 +986,6 @@ static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = {
- .dpms = qxl_enc_dpms,
- .prepare = qxl_enc_prepare,
- .mode_set = qxl_enc_mode_set,
- .commit = qxl_enc_commit,
};
static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
@@ -1059,14 +1018,6 @@ static enum drm_connector_status qxl_conn_detect(
: connector_status_disconnected;
}
-static int qxl_conn_set_property(struct drm_connector *connector,
- struct drm_property *property,
- uint64_t value)
-{
- DRM_DEBUG("\n");
- return 0;
-}
-
static void qxl_conn_destroy(struct drm_connector *connector)
{
struct qxl_output *qxl_output =
@@ -1081,7 +1032,6 @@ static const struct drm_connector_funcs qxl_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = qxl_conn_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .set_property = qxl_conn_set_property,
.destroy = qxl_conn_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
--
2.9.3
^ permalink raw reply related
* [PATCH 3/4] qxl: hook monitors_config updates into crtc, not encoder.
From: Gerd Hoffmann @ 2018-02-16 13:28 UTC (permalink / raw)
To: dri-devel
Cc: David Airlie, Dave Airlie, open list,
open list:DRM DRIVER FOR QXL VIRTUAL GPU
In-Reply-To: <20180216132832.5374-1-kraxel@redhat.com>
The encoder callbacks are only called in case the video mode changes.
So any layout changes without mode changes will go unnoticed.
Add qxl_crtc_update_monitors_config(), based on the old
qxl_write_monitors_config_for_encoder() function. Hook it into the
enable, disable and flush atomic crtc callbacks. Remove monitors_config
updates from all other places.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1544322
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/qxl/qxl_cmd.c | 2 +
drivers/gpu/drm/qxl/qxl_display.c | 156 ++++++++++++++++----------------------
2 files changed, 66 insertions(+), 92 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index 850f8d7d37..95db20f214 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -371,6 +371,7 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev)
void qxl_io_destroy_primary(struct qxl_device *qdev)
{
wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC);
+ qdev->primary_created = false;
}
void qxl_io_create_primary(struct qxl_device *qdev,
@@ -396,6 +397,7 @@ void qxl_io_create_primary(struct qxl_device *qdev,
create->type = QXL_SURF_TYPE_PRIMARY;
wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC);
+ qdev->primary_created = true;
}
void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 8efd07f677..b7dac01f5e 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -281,6 +281,66 @@ static void qxl_send_monitors_config(struct qxl_device *qdev)
qxl_io_monitors_config(qdev);
}
+static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc,
+ const char *reason)
+{
+ struct drm_device *dev = crtc->dev;
+ struct qxl_device *qdev = dev->dev_private;
+ struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
+ struct qxl_head head;
+ int oldcount, i = qcrtc->index;
+
+ if (!qdev->primary_created) {
+ DRM_DEBUG_KMS("no primary surface, skip (%s)\n", reason);
+ return;
+ }
+
+ if (!qdev->monitors_config ||
+ qdev->monitors_config->max_allowed <= i)
+ return;
+
+ head.id = i;
+ head.flags = 0;
+ oldcount = qdev->monitors_config->count;
+ if (crtc->state->active) {
+ struct drm_display_mode *mode = &crtc->mode;
+ head.width = mode->hdisplay;
+ head.height = mode->vdisplay;
+ head.x = crtc->x;
+ head.y = crtc->y;
+ if (qdev->monitors_config->count < i + 1)
+ qdev->monitors_config->count = i + 1;
+ } else if (i > 0) {
+ head.width = 0;
+ head.height = 0;
+ head.x = 0;
+ head.y = 0;
+ if (qdev->monitors_config->count == i + 1)
+ qdev->monitors_config->count = i;
+ } else {
+ DRM_DEBUG_KMS("inactive head 0, skip (%s)\n", reason);
+ return;
+ }
+
+ if (head.width == qdev->monitors_config->heads[i].width &&
+ head.height == qdev->monitors_config->heads[i].height &&
+ head.x == qdev->monitors_config->heads[i].x &&
+ head.y == qdev->monitors_config->heads[i].y &&
+ oldcount == qdev->monitors_config->count)
+ return;
+
+ DRM_DEBUG_KMS("head %d, %dx%d, at +%d+%d, %s (%s)\n",
+ i, head.width, head.height, head.x, head.y,
+ crtc->state->active ? "on" : "off", reason);
+ if (oldcount != qdev->monitors_config->count)
+ DRM_DEBUG_KMS("active heads %d -> %d (%d total)\n",
+ oldcount, qdev->monitors_config->count,
+ qdev->monitors_config->max_allowed);
+
+ qdev->monitors_config->heads[i] = head;
+ qxl_send_monitors_config(qdev);
+}
+
static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -296,6 +356,8 @@ static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
+
+ qxl_crtc_update_monitors_config(crtc, "flush");
}
static void qxl_crtc_destroy(struct drm_crtc *crtc)
@@ -401,55 +463,20 @@ static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}
-static void qxl_monitors_config_set(struct qxl_device *qdev,
- int index,
- unsigned x, unsigned y,
- unsigned width, unsigned height,
- unsigned surf_id)
-{
- DRM_DEBUG_KMS("%d:%dx%d+%d+%d\n", index, width, height, x, y);
- qdev->monitors_config->heads[index].x = x;
- qdev->monitors_config->heads[index].y = y;
- qdev->monitors_config->heads[index].width = width;
- qdev->monitors_config->heads[index].height = height;
- qdev->monitors_config->heads[index].surface_id = surf_id;
-
-}
-
-static void qxl_mode_set_nofb(struct drm_crtc *crtc)
-{
- struct qxl_device *qdev = crtc->dev->dev_private;
- struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
- struct drm_display_mode *mode = &crtc->mode;
-
- DRM_DEBUG("Mode set (%d,%d)\n",
- mode->hdisplay, mode->vdisplay);
-
- qxl_monitors_config_set(qdev, qcrtc->index, 0, 0,
- mode->hdisplay, mode->vdisplay, 0);
-
-}
-
static void qxl_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
- DRM_DEBUG("\n");
+ qxl_crtc_update_monitors_config(crtc, "enable");
}
static void qxl_crtc_atomic_disable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
- struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
- struct qxl_device *qdev = crtc->dev->dev_private;
-
- qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
-
- qxl_send_monitors_config(qdev);
+ qxl_crtc_update_monitors_config(crtc, "disable");
}
static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = {
.mode_fixup = qxl_crtc_mode_fixup,
- .mode_set_nofb = qxl_mode_set_nofb,
.atomic_flush = qxl_crtc_atomic_flush,
.atomic_enable = qxl_crtc_atomic_enable,
.atomic_disable = qxl_crtc_atomic_disable,
@@ -939,61 +966,8 @@ static void qxl_enc_prepare(struct drm_encoder *encoder)
DRM_DEBUG("\n");
}
-static void qxl_write_monitors_config_for_encoder(struct qxl_device *qdev,
- struct drm_encoder *encoder)
-{
- int i;
- struct qxl_output *output = drm_encoder_to_qxl_output(encoder);
- struct qxl_head *head;
- struct drm_display_mode *mode;
-
- BUG_ON(!encoder);
- /* TODO: ugly, do better */
- i = output->index;
- if (!qdev->monitors_config ||
- qdev->monitors_config->max_allowed <= i) {
- DRM_ERROR(
- "head number too large or missing monitors config: %p, %d",
- qdev->monitors_config,
- qdev->monitors_config ?
- qdev->monitors_config->max_allowed : -1);
- return;
- }
- if (!encoder->crtc) {
- DRM_ERROR("missing crtc on encoder %p\n", encoder);
- return;
- }
- if (i != 0)
- DRM_DEBUG("missing for multiple monitors: no head holes\n");
- head = &qdev->monitors_config->heads[i];
- head->id = i;
- if (encoder->crtc->enabled) {
- mode = &encoder->crtc->mode;
- head->width = mode->hdisplay;
- head->height = mode->vdisplay;
- head->x = encoder->crtc->x;
- head->y = encoder->crtc->y;
- if (qdev->monitors_config->count < i + 1)
- qdev->monitors_config->count = i + 1;
- } else {
- head->width = 0;
- head->height = 0;
- head->x = 0;
- head->y = 0;
- }
- DRM_DEBUG_KMS("setting head %d to +%d+%d %dx%d out of %d\n",
- i, head->x, head->y, head->width, head->height, qdev->monitors_config->count);
- head->flags = 0;
- /* TODO - somewhere else to call this for multiple monitors
- * (config_commit?) */
- qxl_send_monitors_config(qdev);
-}
-
static void qxl_enc_commit(struct drm_encoder *encoder)
{
- struct qxl_device *qdev = encoder->dev->dev_private;
-
- qxl_write_monitors_config_for_encoder(qdev, encoder);
DRM_DEBUG("\n");
}
@@ -1080,8 +1054,6 @@ static enum drm_connector_status qxl_conn_detect(
qxl_head_enabled(&qdev->client_monitors_config->heads[output->index]);
DRM_DEBUG("#%d connected: %d\n", output->index, connected);
- if (!connected)
- qxl_monitors_config_set(qdev, output->index, 0, 0, 0, 0, 0);
return connected ? connector_status_connected
: connector_status_disconnected;
--
2.9.3
^ permalink raw reply related
* [PATCH 2/4] qxl: move qxl_send_monitors_config()
From: Gerd Hoffmann @ 2018-02-16 13:28 UTC (permalink / raw)
To: dri-devel
Cc: David Airlie, Dave Airlie, open list,
open list:DRM DRIVER FOR QXL VIRTUAL GPU
In-Reply-To: <20180216132832.5374-1-kraxel@redhat.com>
Needed to avoid a forward declaration in a followup patch.
Pure code move, no functional change.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/qxl/qxl_display.c | 47 +++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a0b6bced03..8efd07f677 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -258,6 +258,29 @@ static int qxl_add_common_modes(struct drm_connector *connector,
return i - 1;
}
+static void qxl_send_monitors_config(struct qxl_device *qdev)
+{
+ int i;
+
+ BUG_ON(!qdev->ram_header->monitors_config);
+
+ if (qdev->monitors_config->count == 0)
+ return;
+
+ for (i = 0 ; i < qdev->monitors_config->count ; ++i) {
+ struct qxl_head *head = &qdev->monitors_config->heads[i];
+
+ if (head->y > 8192 || head->x > 8192 ||
+ head->width > 8192 || head->height > 8192) {
+ DRM_ERROR("head %d wrong: %dx%d+%d+%d\n",
+ i, head->width, head->height,
+ head->x, head->y);
+ return;
+ }
+ }
+ qxl_io_monitors_config(qdev);
+}
+
static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -378,30 +401,6 @@ static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
return true;
}
-static void
-qxl_send_monitors_config(struct qxl_device *qdev)
-{
- int i;
-
- BUG_ON(!qdev->ram_header->monitors_config);
-
- if (qdev->monitors_config->count == 0)
- return;
-
- for (i = 0 ; i < qdev->monitors_config->count ; ++i) {
- struct qxl_head *head = &qdev->monitors_config->heads[i];
-
- if (head->y > 8192 || head->x > 8192 ||
- head->width > 8192 || head->height > 8192) {
- DRM_ERROR("head %d wrong: %dx%d+%d+%d\n",
- i, head->width, head->height,
- head->x, head->y);
- return;
- }
- }
- qxl_io_monitors_config(qdev);
-}
-
static void qxl_monitors_config_set(struct qxl_device *qdev,
int index,
unsigned x, unsigned y,
--
2.9.3
^ permalink raw reply related
* [PATCH 1/4] qxl: remove qxl_io_log()
From: Gerd Hoffmann @ 2018-02-16 13:28 UTC (permalink / raw)
To: dri-devel
Cc: David Airlie, Dave Airlie, open list,
open list:DRM DRIVER FOR QXL VIRTUAL GPU
In-Reply-To: <20180216132832.5374-1-kraxel@redhat.com>
qxl_io_log() sends messages over to the host (qemu) for logging.
Remove the function and all callers, we can just use standard
DRM_DEBUG calls (and if needed a serial console).
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
drivers/gpu/drm/qxl/qxl_drv.h | 3 ---
drivers/gpu/drm/qxl/qxl_cmd.c | 34 ++--------------------------------
drivers/gpu/drm/qxl/qxl_display.c | 27 ++++-----------------------
drivers/gpu/drm/qxl/qxl_fb.c | 2 --
drivers/gpu/drm/qxl/qxl_irq.c | 3 +--
5 files changed, 7 insertions(+), 62 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 00a1a66b05..4b89840173 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -298,9 +298,6 @@ struct qxl_device {
int monitors_config_height;
};
-/* forward declaration for QXL_INFO_IO */
-__printf(2,3) void qxl_io_log(struct qxl_device *qdev, const char *fmt, ...);
-
extern const struct drm_ioctl_desc qxl_ioctls[];
extern int qxl_max_ioctl;
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c
index c0fb52c6d4..850f8d7d37 100644
--- a/drivers/gpu/drm/qxl/qxl_cmd.c
+++ b/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -341,12 +341,9 @@ int qxl_io_update_area(struct qxl_device *qdev, struct qxl_bo *surf,
surface_height = surf->surf.height;
if (area->left < 0 || area->top < 0 ||
- area->right > surface_width || area->bottom > surface_height) {
- qxl_io_log(qdev, "%s: not doing area update for "
- "%d, (%d,%d,%d,%d) (%d,%d)\n", __func__, surface_id, area->left,
- area->top, area->right, area->bottom, surface_width, surface_height);
+ area->right > surface_width || area->bottom > surface_height)
return -EINVAL;
- }
+
mutex_lock(&qdev->update_area_mutex);
qdev->ram_header->update_area = *area;
qdev->ram_header->update_surface = surface_id;
@@ -407,20 +404,6 @@ void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id)
wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC);
}
-void qxl_io_log(struct qxl_device *qdev, const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vsnprintf(qdev->ram_header->log_buf, QXL_LOG_BUF_SIZE, fmt, args);
- va_end(args);
- /*
- * DO not do a DRM output here - this will call printk, which will
- * call back into qxl for rendering (qxl_fb)
- */
- outb(0, qdev->io_base + QXL_IO_LOG);
-}
-
void qxl_io_reset(struct qxl_device *qdev)
{
outb(0, qdev->io_base + QXL_IO_RESET);
@@ -428,19 +411,6 @@ void qxl_io_reset(struct qxl_device *qdev)
void qxl_io_monitors_config(struct qxl_device *qdev)
{
- qxl_io_log(qdev, "%s: %d [%dx%d+%d+%d]\n", __func__,
- qdev->monitors_config ?
- qdev->monitors_config->count : -1,
- qdev->monitors_config && qdev->monitors_config->count ?
- qdev->monitors_config->heads[0].width : -1,
- qdev->monitors_config && qdev->monitors_config->count ?
- qdev->monitors_config->heads[0].height : -1,
- qdev->monitors_config && qdev->monitors_config->count ?
- qdev->monitors_config->heads[0].x : -1,
- qdev->monitors_config && qdev->monitors_config->count ?
- qdev->monitors_config->heads[0].y : -1
- );
-
wait_for_io_cmd(qdev, 0, QXL_IO_MONITORS_CONFIG_ASYNC);
}
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index 9a9214ae0f..a0b6bced03 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -48,12 +48,8 @@ static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned c
qdev->client_monitors_config = kzalloc(
sizeof(struct qxl_monitors_config) +
sizeof(struct qxl_head) * count, GFP_KERNEL);
- if (!qdev->client_monitors_config) {
- qxl_io_log(qdev,
- "%s: allocation failure for %u heads\n",
- __func__, count);
+ if (!qdev->client_monitors_config)
return;
- }
}
qdev->client_monitors_config->count = count;
}
@@ -74,12 +70,8 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
num_monitors = qdev->rom->client_monitors_config.count;
crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config,
sizeof(qdev->rom->client_monitors_config));
- if (crc != qdev->rom->client_monitors_config_crc) {
- qxl_io_log(qdev, "crc mismatch: have %X (%zd) != %X\n", crc,
- sizeof(qdev->rom->client_monitors_config),
- qdev->rom->client_monitors_config_crc);
+ if (crc != qdev->rom->client_monitors_config_crc)
return MONITORS_CONFIG_BAD_CRC;
- }
if (!num_monitors) {
DRM_DEBUG_KMS("no client monitors configured\n");
return status;
@@ -170,12 +162,10 @@ void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
udelay(5);
}
if (status == MONITORS_CONFIG_BAD_CRC) {
- qxl_io_log(qdev, "config: bad crc\n");
DRM_DEBUG_KMS("ignoring client monitors config: bad crc");
return;
}
if (status == MONITORS_CONFIG_UNCHANGED) {
- qxl_io_log(qdev, "config: unchanged\n");
DRM_DEBUG_KMS("ignoring client monitors config: unchanged");
return;
}
@@ -385,14 +375,6 @@ static bool qxl_crtc_mode_fixup(struct drm_crtc *crtc,
const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
- struct drm_device *dev = crtc->dev;
- struct qxl_device *qdev = dev->dev_private;
-
- qxl_io_log(qdev, "%s: (%d,%d) => (%d,%d)\n",
- __func__,
- mode->hdisplay, mode->vdisplay,
- adjusted_mode->hdisplay,
- adjusted_mode->vdisplay);
return true;
}
@@ -403,10 +385,9 @@ qxl_send_monitors_config(struct qxl_device *qdev)
BUG_ON(!qdev->ram_header->monitors_config);
- if (qdev->monitors_config->count == 0) {
- qxl_io_log(qdev, "%s: 0 monitors??\n", __func__);
+ if (qdev->monitors_config->count == 0)
return;
- }
+
for (i = 0 ; i < qdev->monitors_config->count ; ++i) {
struct qxl_head *head = &qdev->monitors_config->heads[i];
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 23af3e3526..603bf564ef 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -185,8 +185,6 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
/*
* we are using a shadow draw buffer, at qdev->surface0_shadow
*/
- qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]\n", clips->x1, clips->x2,
- clips->y1, clips->y2);
image->dx = clips->x1;
image->dy = clips->y1;
image->width = clips->x2 - clips->x1;
diff --git a/drivers/gpu/drm/qxl/qxl_irq.c b/drivers/gpu/drm/qxl/qxl_irq.c
index 23a40106ab..3bb31add63 100644
--- a/drivers/gpu/drm/qxl/qxl_irq.c
+++ b/drivers/gpu/drm/qxl/qxl_irq.c
@@ -57,10 +57,9 @@ irqreturn_t qxl_irq_handler(int irq, void *arg)
* to avoid endless loops).
*/
qdev->irq_received_error++;
- qxl_io_log(qdev, "%s: driver is in bug mode.\n", __func__);
+ DRM_WARN("driver is in bug mode\n");
}
if (pending & QXL_INTERRUPT_CLIENT_MONITORS_CONFIG) {
- qxl_io_log(qdev, "QXL_INTERRUPT_CLIENT_MONITORS_CONFIG\n");
schedule_work(&qdev->client_monitors_config_work);
}
qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
--
2.9.3
^ permalink raw reply related
* Re: [PATCH v3 1/2] drm/virtio: Add window server support
From: Gerd Hoffmann @ 2018-02-16 10:48 UTC (permalink / raw)
To: Tomeu Vizoso
Cc: Michael S. Tsirkin, David Airlie, linux-kernel, dri-devel,
virtualization, Zach Reizner, kernel
In-Reply-To: <37179029-8ccb-8eb2-0901-04b64cef3608@collabora.com>
> > Yes.
>
> Would it make sense for virtio-gpu to map buffers to the guest via PCI BARs?
> So we can use a single drm driver for both 2d and 3d.
Should be doable.
I'm wondering two things though:
(1) Will shmem actually help avoiding a copy?
virtio-gpu with virgl will (even if the guest doesn't use opengl) store
the resources in gpu memory. So the VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D
copy goes from guest memory directly to gpu memory, and if we export
that as dma-buf and pass it to the wayland server it should be able to
render it without doing another copy.
How does the wl_shm_pool workflow look like inside the wayland server?
Can it ask the gpu to render directly from the pool? Or is a copy to
gpu memory needed here? If the latter we would effectively trade one
copy for another ...
(2) Could we handle the mapping without needing shmem?
Possibly we could extend the vgem driver. So we pass in a iov (which
qemu gets from guest via VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING), get
back a drm object. Which effectively creates drm objects on the host
which match the drm object in the guest (both backed by the same set of
physical pages).
cheers,
Gerd
^ permalink raw reply
* [PULL] virtio: cleanups and fixes
From: Michael S. Tsirkin @ 2018-02-15 18:27 UTC (permalink / raw)
To: Linus Torvalds
Cc: kvm, mst, netdev, cohuck, linux-kernel, stable, virtualization,
groug
The following changes since commit d25cc43c6775bff6b8e3dad97c747954b805e421:
vhost: don't hold onto file pointer for VHOST_SET_LOG_FD (2018-02-01 16:26:47 +0200)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git tags/for_linus
for you to fetch changes up to fa08a3b4eba59429cf7e241a7af089103e79160f:
virtio/s390: implement PM operations for virtio_ccw (2018-02-14 14:34:09 +0200)
----------------------------------------------------------------
virtio: bugfixes
This includes a bugfix for virtio 9p fs.
It also fixes hybernation for s390 guests with virtio devices.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
----------------------------------------------------------------
Christian Borntraeger (1):
virtio/s390: implement PM operations for virtio_ccw
Greg Kurz (1):
9p/trans_virtio: discard zero-length reply
drivers/s390/virtio/virtio_ccw.c | 29 +++++++++++++++++++++++++++++
net/9p/trans_virtio.c | 3 ++-
2 files changed, 31 insertions(+), 1 deletion(-)
^ permalink raw reply
* Re: [vhost:vhost 24/24] drivers/firmware/qemu_fw_cfg.c:499:22: error: storage size of 'files' isn't known
From: Michael S. Tsirkin @ 2018-02-15 18:26 UTC (permalink / raw)
To: Marc-Andre Lureau
Cc: kvm, netdev, virtualization, kbuild-all, Marc-André Lureau,
kbuild test robot
In-Reply-To: <CAMxuvawhzjNA8gQSCpVtff-A6-Umg6fPz37nPhqRrDiRwKqUCQ@mail.gmail.com>
On Thu, Feb 15, 2018 at 10:46:50AM +0100, Marc-Andre Lureau wrote:
> Hi
>
> On Wed, Feb 14, 2018 at 9:27 PM, kbuild test robot
> <fengguang.wu@intel.com> wrote:
> > tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost
> > head: 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e
> > commit: 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e [24/24] fw_cfg: fix sparse warnings around FW_CFG_FILE_DIR read
> > config: i386-randconfig-x015-201806 (attached as .config)
> > compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
> > reproduce:
> > git checkout 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e
> > # save the attached .config to linux build tree
> > make ARCH=i386
> >
> > All errors (new ones prefixed by >>):
> >
> > drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_register_dir_entries':
> >>> drivers/firmware/qemu_fw_cfg.c:499:22: error: storage size of 'files' isn't known
> > struct fw_cfg_files files;
> > ^~~~~
>
> struct fw_cfg_files {
> __be32 count; /* number of entries */
> struct fw_cfg_file f[];
> };
>
> Interesting, I don't have that warning with 7.3.1.
>
> I thought the size would be sizeof(count) by standard.
>
> I replaced it with a __be32 files_count variable instead.
>
> > drivers/firmware/qemu_fw_cfg.c:499:22: warning: unused variable 'files' [-Wunused-variable]
> >
>
> files.count is used 3 lines below, that looks like a compiler bug to me.
No - i tried dropping one patch out of series, this did not work out.
So whole series is out for now.
> > vim +499 drivers/firmware/qemu_fw_cfg.c
> >
> > 493
> > 494 /* iterate over all fw_cfg directory entries, registering each one */
> > 495 static int fw_cfg_register_dir_entries(void)
> > 496 {
> > 497 int ret = 0;
> > 498 u32 count, i;
> > > 499 struct fw_cfg_files files;
> > 500 struct fw_cfg_file *dir;
> > 501 size_t dir_size;
> > 502
> > 503 fw_cfg_read_blob(FW_CFG_FILE_DIR, &files.count, 0, sizeof(files.count));
> > 504 count = be32_to_cpu(files.count);
> > 505 dir_size = count * sizeof(struct fw_cfg_file);
> > 506
> > 507 dir = kmalloc(dir_size, GFP_KERNEL);
> > 508 if (!dir)
> > 509 return -ENOMEM;
> > 510
> > 511 fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(files.count), dir_size);
> > 512
> > 513 for (i = 0; i < count; i++) {
> > 514 ret = fw_cfg_register_file(&dir[i]);
> > 515 if (ret)
> > 516 break;
> > 517 }
> > 518
> > 519 kfree(dir);
> > 520 return ret;
> > 521 }
> > 522
> >
> > ---
> > 0-DAY kernel test infrastructure Open Source Technology Center
> > https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* Re: [PATCH v2 0/6] crypto: engine - Permit to enqueue all async requests
From: Herbert Xu @ 2018-02-15 15:51 UTC (permalink / raw)
To: Corentin Labbe
Cc: alexandre.torgue, corbet, mst, linux-doc, linux-kernel,
fabien.dessenne, virtualization, linux-sunxi, linux-crypto,
mcoquelin.stm32, davem, linux-arm-kernel
In-Reply-To: <20180126191534.17569-1-clabbe.montjoie@gmail.com>
On Fri, Jan 26, 2018 at 08:15:28PM +0100, Corentin Labbe wrote:
> Hello
>
> The current crypto_engine support only ahash and ablkcipher request.
> My first patch which try to add skcipher was Nacked, it will add too many functions
> and adding other algs(aead, asymetric_key) will make the situation worst.
>
> This patchset remove all algs specific stuff and now only process generic crypto_async_request.
>
> The requests handler function pointer are now moved out of struct engine and
> are now stored directly in a crypto_engine_reqctx.
>
> The original proposal of Herbert [1] cannot be done completly since the crypto_engine
> could only dequeue crypto_async_request and it is impossible to access any request_ctx
> without knowing the underlying request type.
>
> So I do something near that was requested: adding crypto_engine_reqctx in TFM context.
> Note that the current implementation expect that crypto_engine_reqctx
> is the first member of the context.
>
> The first patch is a try to document the crypto engine API.
> The second patch convert the crypto engine with the new way,
> while the following patchs convert the 4 existing users of crypto_engine.
> Note that this split break bisection, so probably the final commit will be all merged.
>
> Appart from virtio, all 4 latest patch were compile tested only.
> But the crypto engine is tested with my new sun8i-ce driver.
>
> Regards
>
> [1] https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1474434.html
>
> Changes since V1:
> - renamed crypto_engine_reqctx to crypto_engine_ctx
> - indentation fix in function parameter
> - do not export crypto_transfer_request
> - Add aead support
> - crypto_finalize_request is now static
>
> Changes since RFC:
> - Added a documentation patch
> - Added patch for stm32-cryp
> - Changed parameter of all crypto_engine_op functions from
> crypto_async_request to void*
> - Reintroduced crypto_transfer_xxx_request_to_engine functions
>
> Corentin Labbe (6):
> Documentation: crypto: document crypto engine API
> crypto: engine - Permit to enqueue all async requests
> crypto: omap: convert to new crypto engine API
> crypto: virtio: convert to new crypto engine API
> crypto: stm32-hash: convert to the new crypto engine API
> crypto: stm32-cryp: convert to the new crypto engine API
All applied. Thanks.
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: [PATCH v3 1/2] drm/virtio: Add window server support
From: Tomeu Vizoso @ 2018-02-15 15:28 UTC (permalink / raw)
To: Gerd Hoffmann
Cc: Michael S. Tsirkin, David Airlie, linux-kernel, dri-devel,
virtualization, Zach Reizner, kernel
In-Reply-To: <20180212114540.iygbha554busy4ip@sirius.home.kraxel.org>
On 02/12/2018 12:45 PM, Gerd Hoffmann wrote:>>>> 4. QEMU pops
data+buffers from the virtqueue, looks up shmem FD for each
>>>> resource, sends data + FDs to the compositor with SCM_RIGHTS
>>>
>>> BTW: Is there a 1:1 relationship between buffers and shmem blocks? Or
>>> does the wayland protocol allow for offsets in buffer meta data, so you
>>> can place multiple buffers in a single shmem block?
>>
>> The latter:
>>
https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_shm_pool
>
> Ah, good, that makes it alot easier.
>
> So, yes, using ivshmem would be one option. Tricky part here is the
> buffer management though. It's just a raw piece of memory. The guest
> proxy could mmap the pci bar and manage it. But then it is again either
> unmodified guest + copying the data, or modified client (which requests
> buffers from guest proxy) for zero-copy.
What if at VIRTIO_GPU_CMD_RESOURCE_CREATE_2D time we created a ivshmem
device to back that resource. The ivshmem device would in turn be backed
by a hostmem device that wraps a shmem FD.
The guest client can then export that resource/BO and pass the FD to the
guest proxy. The guest proxy would import it and put the resource_id in
the equivalent message in our protocol extension.
QEMU would get that resource id from vsock, look up which hostmem device
is associated with that resource, and pass its FD to the compositor.
> We also need a solution for the keymap shmem block. I guess the keymap
> doesn't change all that often, so maybe it is easiest to just copy it
> over (host proxy -> guest proxy) instead of trying to map the host shmem
> into the guest?
Not sure if that would be much simpler than creating a ivshmem+hostmem
combo that wraps the incoming shmem FD and then having virtio-gpu create
a BO that imports it.
Regards,
Tomeu
^ permalink raw reply
* Re: [PATCH 4/4] vfio: Allow type-1 IOMMU instantiation with a virtio-iommu
From: Jean-Philippe Brucker @ 2018-02-15 13:53 UTC (permalink / raw)
To: Robin Murphy, Alex Williamson
Cc: virtio-dev@lists.oasis-open.org, jayachandran.nair@cavium.com,
Lorenzo Pieralisi, tnowicki@caviumnetworks.com,
kvm@vger.kernel.org, mst@redhat.com, joro@8bytes.org, Will Deacon,
virtualization@lists.linux-foundation.org, Marc Zyngier,
iommu@lists.linux-foundation.org, jintack@cs.columbia.edu,
eric.auger@redhat.com, kvmarm@lists.cs.columbia.edu,
eric.auger.pro@gmail.com
In-Reply-To: <9f98aa85-3160-e285-cacd-2f429c58a775@arm.com>
On 14/02/18 15:35, Robin Murphy wrote:
> On 14/02/18 15:26, Alex Williamson wrote:
>> On Wed, 14 Feb 2018 14:53:40 +0000
>> Jean-Philippe Brucker <jean-philippe.brucker@arm.com> wrote:
>>
>>> When enabling both VFIO and VIRTIO_IOMMU modules, automatically select
>>> VFIO_IOMMU_TYPE1 as well.
>>>
>>> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>>> ---
>>> drivers/vfio/Kconfig | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
>>> index c84333eb5eb5..65a1e691110c 100644
>>> --- a/drivers/vfio/Kconfig
>>> +++ b/drivers/vfio/Kconfig
>>> @@ -21,7 +21,7 @@ config VFIO_VIRQFD
>>> menuconfig VFIO
>>> tristate "VFIO Non-Privileged userspace driver framework"
>>> depends on IOMMU_API
>>> - select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM_SMMU || ARM_SMMU_V3)
>>> + select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM_SMMU || ARM_SMMU_V3 || VIRTIO_IOMMU)
>>> select ANON_INODES
>>> help
>>> VFIO provides a framework for secure userspace device drivers.
>>
>> Why are we basing this on specific IOMMU drivers in the first place?
>> Only ARM is doing that. Shouldn't IOMMU_API only be enabled for ARM
>> targets that support it and therefore we can forget about the specific
>> IOMMU drivers? Thanks,
>
> Makes sense - the majority of ARM systems (and mobile/embedded ARM64
> ones) making use of IOMMU_API won't actually support VFIO, but it can't
> hurt to allow them to select the type 1 driver regardless. Especially as
> multiplatform configs are liable to be pulling in the SMMU driver(s) anyway.
Cool, then I'll change that line to:
+ select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM || ARM64)
Thanks,
Jean
^ permalink raw reply
* [vhost:vhost 24/24] drivers/firmware/qemu_fw_cfg.c:499:22: error: storage size of 'files' isn't known
From: kbuild test robot @ 2018-02-14 20:27 UTC (permalink / raw)
To: Marc-André Lureau
Cc: netdev, Michael S. Tsirkin, kbuild-all, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 1905 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost
head: 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e
commit: 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e [24/24] fw_cfg: fix sparse warnings around FW_CFG_FILE_DIR read
config: i386-randconfig-x015-201806 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
git checkout 5d457fe6aeaab9d0a1665eafc8af7139bc6b6f2e
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
drivers/firmware/qemu_fw_cfg.c: In function 'fw_cfg_register_dir_entries':
>> drivers/firmware/qemu_fw_cfg.c:499:22: error: storage size of 'files' isn't known
struct fw_cfg_files files;
^~~~~
drivers/firmware/qemu_fw_cfg.c:499:22: warning: unused variable 'files' [-Wunused-variable]
vim +499 drivers/firmware/qemu_fw_cfg.c
493
494 /* iterate over all fw_cfg directory entries, registering each one */
495 static int fw_cfg_register_dir_entries(void)
496 {
497 int ret = 0;
498 u32 count, i;
> 499 struct fw_cfg_files files;
500 struct fw_cfg_file *dir;
501 size_t dir_size;
502
503 fw_cfg_read_blob(FW_CFG_FILE_DIR, &files.count, 0, sizeof(files.count));
504 count = be32_to_cpu(files.count);
505 dir_size = count * sizeof(struct fw_cfg_file);
506
507 dir = kmalloc(dir_size, GFP_KERNEL);
508 if (!dir)
509 return -ENOMEM;
510
511 fw_cfg_read_blob(FW_CFG_FILE_DIR, dir, sizeof(files.count), dir_size);
512
513 for (i = 0; i < count; i++) {
514 ret = fw_cfg_register_file(&dir[i]);
515 if (ret)
516 break;
517 }
518
519 kfree(dir);
520 return ret;
521 }
522
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32274 bytes --]
[-- Attachment #3: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* [vhost:vhost 22/28] drivers/firmware/qemu_fw_cfg.c:35:10: fatal error: linux/fw_cfg.h: No such file or directory
From: kbuild test robot @ 2018-02-14 18:21 UTC (permalink / raw)
To: Marc-André Lureau
Cc: netdev, Michael S. Tsirkin, kbuild-all, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 929 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost
head: 20b12f92d80433b9bd0d54b9712897501ac66fdd
commit: f59055103f6930c771fc597c42a92cbe997a765d [22/28] fw_cfg: add a public uapi header
config: i386-randconfig-i0-201806 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
git checkout f59055103f6930c771fc597c42a92cbe997a765d
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
>> drivers/firmware/qemu_fw_cfg.c:35:10: fatal error: linux/fw_cfg.h: No such file or directory
#include <linux/fw_cfg.h>
^~~~~~~~~~~~~~~~
compilation terminated.
vim +35 drivers/firmware/qemu_fw_cfg.c
> 35 #include <linux/fw_cfg.h>
36
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 31348 bytes --]
[-- Attachment #3: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH v2 4/6] crypto: virtio: convert to new crypto engine API
From: Michael S. Tsirkin @ 2018-02-14 15:51 UTC (permalink / raw)
To: Corentin Labbe
Cc: herbert, corbet, linux-doc, linux-kernel, fabien.dessenne,
virtualization, linux-sunxi, linux-crypto, mcoquelin.stm32, davem,
linux-arm-kernel, alexandre.torgue
In-Reply-To: <20180126191534.17569-5-clabbe.montjoie@gmail.com>
On Fri, Jan 26, 2018 at 08:15:32PM +0100, Corentin Labbe wrote:
> This patch convert the driver to the new crypto engine API.
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Pls queue when/if rest of changes go in.
> ---
> drivers/crypto/virtio/virtio_crypto_algs.c | 16 ++++++++++------
> drivers/crypto/virtio/virtio_crypto_common.h | 3 +--
> drivers/crypto/virtio/virtio_crypto_core.c | 3 ---
> 3 files changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c b/drivers/crypto/virtio/virtio_crypto_algs.c
> index abe8c15450df..ba190cfa7aa1 100644
> --- a/drivers/crypto/virtio/virtio_crypto_algs.c
> +++ b/drivers/crypto/virtio/virtio_crypto_algs.c
> @@ -29,6 +29,7 @@
>
>
> struct virtio_crypto_ablkcipher_ctx {
> + struct crypto_engine_ctx enginectx;
> struct virtio_crypto *vcrypto;
> struct crypto_tfm *tfm;
>
> @@ -491,7 +492,7 @@ static int virtio_crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
> vc_sym_req->ablkcipher_req = req;
> vc_sym_req->encrypt = true;
>
> - return crypto_transfer_cipher_request_to_engine(data_vq->engine, req);
> + return crypto_transfer_ablkcipher_request_to_engine(data_vq->engine, req);
> }
>
> static int virtio_crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
> @@ -511,7 +512,7 @@ static int virtio_crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
> vc_sym_req->ablkcipher_req = req;
> vc_sym_req->encrypt = false;
>
> - return crypto_transfer_cipher_request_to_engine(data_vq->engine, req);
> + return crypto_transfer_ablkcipher_request_to_engine(data_vq->engine, req);
> }
>
> static int virtio_crypto_ablkcipher_init(struct crypto_tfm *tfm)
> @@ -521,6 +522,9 @@ static int virtio_crypto_ablkcipher_init(struct crypto_tfm *tfm)
> tfm->crt_ablkcipher.reqsize = sizeof(struct virtio_crypto_sym_request);
> ctx->tfm = tfm;
>
> + ctx->enginectx.op.do_one_request = virtio_crypto_ablkcipher_crypt_req;
> + ctx->enginectx.op.prepare_request = NULL;
> + ctx->enginectx.op.unprepare_request = NULL;
> return 0;
> }
>
> @@ -538,9 +542,9 @@ static void virtio_crypto_ablkcipher_exit(struct crypto_tfm *tfm)
> }
>
> int virtio_crypto_ablkcipher_crypt_req(
> - struct crypto_engine *engine,
> - struct ablkcipher_request *req)
> + struct crypto_engine *engine, void *vreq)
> {
> + struct ablkcipher_request *req = container_of(vreq, struct ablkcipher_request, base);
> struct virtio_crypto_sym_request *vc_sym_req =
> ablkcipher_request_ctx(req);
> struct virtio_crypto_request *vc_req = &vc_sym_req->base;
> @@ -561,8 +565,8 @@ static void virtio_crypto_ablkcipher_finalize_req(
> struct ablkcipher_request *req,
> int err)
> {
> - crypto_finalize_cipher_request(vc_sym_req->base.dataq->engine,
> - req, err);
> + crypto_finalize_ablkcipher_request(vc_sym_req->base.dataq->engine,
> + req, err);
> kzfree(vc_sym_req->iv);
> virtcrypto_clear_request(&vc_sym_req->base);
> }
> diff --git a/drivers/crypto/virtio/virtio_crypto_common.h b/drivers/crypto/virtio/virtio_crypto_common.h
> index e976539a05d9..72621bd67211 100644
> --- a/drivers/crypto/virtio/virtio_crypto_common.h
> +++ b/drivers/crypto/virtio/virtio_crypto_common.h
> @@ -107,8 +107,7 @@ struct virtio_crypto *virtcrypto_get_dev_node(int node);
> int virtcrypto_dev_start(struct virtio_crypto *vcrypto);
> void virtcrypto_dev_stop(struct virtio_crypto *vcrypto);
> int virtio_crypto_ablkcipher_crypt_req(
> - struct crypto_engine *engine,
> - struct ablkcipher_request *req);
> + struct crypto_engine *engine, void *vreq);
>
> void
> virtcrypto_clear_request(struct virtio_crypto_request *vc_req);
> diff --git a/drivers/crypto/virtio/virtio_crypto_core.c b/drivers/crypto/virtio/virtio_crypto_core.c
> index ff1410a32c2b..83326986c113 100644
> --- a/drivers/crypto/virtio/virtio_crypto_core.c
> +++ b/drivers/crypto/virtio/virtio_crypto_core.c
> @@ -111,9 +111,6 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi)
> ret = -ENOMEM;
> goto err_engine;
> }
> -
> - vi->data_vq[i].engine->cipher_one_request =
> - virtio_crypto_ablkcipher_crypt_req;
> }
>
> kfree(names);
> --
> 2.13.6
^ permalink raw reply
* Re: [PATCH 4/4] vfio: Allow type-1 IOMMU instantiation with a virtio-iommu
From: Robin Murphy @ 2018-02-14 15:35 UTC (permalink / raw)
To: Alex Williamson, Jean-Philippe Brucker
Cc: virtio-dev, jayachandran.nair, lorenzo.pieralisi, tnowicki, kvm,
mst, joro, will.deacon, virtualization, marc.zyngier, iommu,
jintack, eric.auger, kvmarm, eric.auger.pro
In-Reply-To: <20180214082639.54556efb@w520.home>
On 14/02/18 15:26, Alex Williamson wrote:
> On Wed, 14 Feb 2018 14:53:40 +0000
> Jean-Philippe Brucker <jean-philippe.brucker@arm.com> wrote:
>
>> When enabling both VFIO and VIRTIO_IOMMU modules, automatically select
>> VFIO_IOMMU_TYPE1 as well.
>>
>> Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
>> ---
>> drivers/vfio/Kconfig | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
>> index c84333eb5eb5..65a1e691110c 100644
>> --- a/drivers/vfio/Kconfig
>> +++ b/drivers/vfio/Kconfig
>> @@ -21,7 +21,7 @@ config VFIO_VIRQFD
>> menuconfig VFIO
>> tristate "VFIO Non-Privileged userspace driver framework"
>> depends on IOMMU_API
>> - select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM_SMMU || ARM_SMMU_V3)
>> + select VFIO_IOMMU_TYPE1 if (X86 || S390 || ARM_SMMU || ARM_SMMU_V3 || VIRTIO_IOMMU)
>> select ANON_INODES
>> help
>> VFIO provides a framework for secure userspace device drivers.
>
> Why are we basing this on specific IOMMU drivers in the first place?
> Only ARM is doing that. Shouldn't IOMMU_API only be enabled for ARM
> targets that support it and therefore we can forget about the specific
> IOMMU drivers? Thanks,
Makes sense - the majority of ARM systems (and mobile/embedded ARM64
ones) making use of IOMMU_API won't actually support VFIO, but it can't
hurt to allow them to select the type 1 driver regardless. Especially as
multiplatform configs are liable to be pulling in the SMMU driver(s) anyway.
Robin.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox