* Re: [bpf-next V2 PATCH 11/14] virtio_net: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-26 11:20 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: Michael S. Tsirkin, netdev, brouer, virtualization, dsahern,
gospo, bjorn.topel, michael.chan
In-Reply-To: <151396275093.20006.9684557344807016870.stgit@firesoul>
On Fri, 22 Dec 2017 18:12:31 +0100
Jesper Dangaard Brouer <brouer@redhat.com> wrote:
> The virtio_net driver doesn't dynamically change the RX-ring queue
> layout and backing pages, but instead reject XDP setup if all the
> conditions for XDP is not meet. Thus, the xdp_rxq_info also remains
> fairly static. This allow us to simply add the reg/unreg to
> net_device open/close functions.
>
> Driver hook points for xdp_rxq_info:
> * reg : virtnet_open
> * unreg: virtnet_close
>
> Cc: "Michael S. Tsirkin" <mst@redhat.com>
> Cc: Jason Wang <jasowang@redhat.com>
> Cc: virtualization@lists.linux-foundation.org
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> ---
> drivers/net/virtio_net.c | 12 +++++++++++-
Found a bug while testing this... I forgot to update receive_mergeable() too.
I'll send a V3
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* Re: [PATCH v20 4/7] virtio-balloon: VIRTIO_BALLOON_F_SG
From: Wei Wang @ 2017-12-26 11:36 UTC (permalink / raw)
To: Tetsuo Handa, willy
Cc: aarcange, virtio-dev, riel, quan.xu0, kvm, mst, qemu-devel,
amit.shah, liliang.opensource, mawilcox, linux-kernel,
virtualization, linux-mm, yang.zhang.wz, nilal, cornelia.huck,
pbonzini, akpm, mhocko, mgorman
In-Reply-To: <201712261938.IFF64061.LtFMOVJFHOSFQO@I-love.SAKURA.ne.jp>
On 12/26/2017 06:38 PM, Tetsuo Handa wrote:
> Wei Wang wrote:
>> On 12/25/2017 10:51 PM, Tetsuo Handa wrote:
>>> Wei Wang wrote:
>>>
>> What we are doing here is to free the pages that were just allocated in
>> this round of inflating. Next round will be sometime later when the
>> balloon work item gets its turn to run. Yes, it will then continue to
>> inflate.
>> Here are the two cases that will happen then:
>> 1) the guest is still under memory pressure, the inflate will fail at
>> memory allocation, which results in a msleep(200), and then it exists
>> for another time to run.
>> 2) the guest isn't under memory pressure any more (e.g. the task which
>> consumes the huge amount of memory is gone), it will continue to inflate
>> as normal till the requested size.
>>
> How likely does 2) occur? It is not so likely. msleep(200) is enough to spam
> the guest with puff messages. Next round is starting too quickly.
I meant one of the two cases, 1) or 2), would happen, rather than 2)
happens after 1).
If 2) doesn't happen, then 1) happens. It will continue to try to
inflate round by round. But the memory allocation won't succeed, so
there will be no pages to inflate to the host. That is, the inflating is
simply a code path to the msleep(200) as long as the guest is under
memory pressure.
Back to our code change, it doesn't result in incorrect behavior as
explained above.
>> I think what we are doing is a quite sensible behavior, except a small
>> change I plan to make:
>>
>> while ((page = balloon_page_pop(&pages))) {
>> - balloon_page_enqueue(&vb->vb_dev_info, page);
>> if (use_sg) {
>> if (xb_set_page(vb, page, &pfn_min, &pfn_max) <
>> 0) {
>> __free_page(page);
>> continue;
>> }
>> } else {
>> set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
>> }
>> + balloon_page_enqueue(&vb->vb_dev_info, page);
>>
>>> Also, as of Linux 4.15, only up to VIRTIO_BALLOON_ARRAY_PFNS_MAX pages (i.e.
>>> 1MB) are invisible from deflate request. That amount would be an acceptable
>>> error. But your patch makes more pages being invisible, for pages allocated
>>> by balloon_page_alloc() without holding balloon_lock are stored into a local
>>> variable "LIST_HEAD(pages)" (which means that balloon_page_dequeue() with
>>> balloon_lock held won't be able to find pages not yet queued by
>>> balloon_page_enqueue()), doesn't it? What if all memory pages were held in
>>> "LIST_HEAD(pages)" and balloon_page_dequeue() was called before
>>> balloon_page_enqueue() is called?
>>>
>> If we think of the balloon driver just as a regular driver or
>> application, that will be a pretty nature thing. A regular driver can
>> eat a huge amount of memory for its own usages, would this amount of
>> memory be treated as an error as they are invisible to the
>> balloon_page_enqueue?
>>
> No. Memory used by applications which consumed a lot of memory in their
> mm_struct is reclaimed by the OOM killer/reaper. Drivers try to avoid
> allocating more memory than they need. If drivers allocate more memory
> than they need, they have a hook for releasing unused memory (i.e.
> register_shrinker() or OOM notifier). What I'm saying here is that
> the hook for releasing unused memory does not work unless memory held in
> LIST_HEAD(pages) becomes visible to balloon_page_dequeue().
>
> If a system has 128GB of memory, and 127GB of memory was stored into
> LIST_HEAD(pages) upon first fill_balloon() request, and somebody held
> balloon_lock from OOM notifier path from out_of_memory() before
> fill_balloon() holds balloon_lock, leak_balloon_sg_oom() finds that
> no memory can be freed because balloon_page_enqueue() was never called,
> and allows the caller of out_of_memory() to invoke the OOM killer despite
> there is 127GB of memory which can be freed if fill_balloon() was able
> to hold balloon_lock before leak_balloon_sg_oom() holds balloon_lock.
> I don't think that that amount is an acceptable error.
I understand you are worried that OOM couldn't get balloon pages while
there are some in the local list. This is a debatable issue, and it may
lead to a long discussion. If this is considered to be a big issue, we
can make the local list to be global in vb, and accessed by oom
notifier, this won't affect this patch, and can be achieved with an
add-on patch. How about leaving this discussion as a second step outside
this series? Balloon has something more that can be improved, and this
patch series is already big.
Best,
Wei
^ permalink raw reply
* [RFC PATCH] virtio: add space for device features show
From: weiping zhang @ 2017-12-26 13:35 UTC (permalink / raw)
To: cohuck, mst, jasowang; +Cc: virtualization
make features string more readable, add space every 8bit.
example:
00101010 01110000 00000000 00001100
Signed-off-by: weiping zhang <zhangweiping@didichuxing.com>
---
drivers/virtio/virtio.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 59e36ef..d7d2db1 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -50,9 +50,12 @@ static ssize_t features_show(struct device *_d,
/* We actually represent this as a bitstring, as it could be
* arbitrary length in future. */
- for (i = 0; i < sizeof(dev->features)*8; i++)
- len += sprintf(buf+len, "%c",
+ for (i = 0; i < sizeof(dev->features) * 8; i++) {
+ len += sprintf(buf + len, "%c",
__virtio_test_bit(dev, i) ? '1' : '0');
+ if (i % 8 == 7)
+ len += sprintf(buf + len, " ");
+ }
len += sprintf(buf+len, "\n");
return len;
}
--
2.9.4
^ permalink raw reply related
* CISTI'2018 - Doctoral Symposium
From: ML @ 2017-12-27 12:43 UTC (permalink / raw)
To: virtualization
[-- Attachment #1.1: Type: text/plain, Size: 4319 bytes --]
* Proceedings published in IEEE Xplore and indexed by ISI, Scopus, etc.
---------------------------------------------------------------------------------------------------------------------------
Doctoral Symposium of CISTI'2018 - 13th Iberian Conference on Information Systems and Technologies
Caceres, Spain, 16 - 13 June 2018
http://www.cisti.eu/ <http://www.cisti.eu/>
------------------------------------------------------------------------------------------------------------------------------------
The purpose of CISTI'2018’s Doctoral Symposium is to provide graduate students a setting where they can, informally, expose and discuss their work, collecting valuable expert opinions and sharing new ideas, methods and applications. The Doctoral Symposium is an excellent opportunity for PhD students to present and discuss their work in a Workshop format. Each presentation will be evaluated by a panel composed by at least three Information Systems and Technologies experts.
Contributions Submission
The Doctoral Symposium is opened to PhD students whose research area includes the themes proposed for this Conference. Submissions must include an extended abstract (maximum 4 pages), following the Conference style guide <http://cisti.eu/2017/images/templates.zip>. All selected contributions will be handed out along with the Conference Proceedings, in CD with an ISBN. These contributions will be available in the IEEE Xplore <http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=7511893> Digital Library and will be sent for indexing in ISI, Scopus, EI-Compendex, INSPEC and Google Scholar.
Submissions must include the field, the PhD institution and the number of months devoted to the development of the work. Additionally, they should include in a clear and succinct manner:
• The problem approached and its significance or relevance
• The research objectives and related investigation topics
• A brief display of what is already known
• A proposed solution methodology for the problem
• Expected results
Important Dates
Paper submission: February 4, 2018
Notification of acceptance: March 18, 2018
Submission of accepted papers: March 30, 2018
Payment of registration, to ensure the inclusion of an accepted paper in the conference proceedings: April 1, 2018
Organizing Committee
Álvaro Rocha, Universidade de Coimbra
Manuel Pérez Cota, Universidad de Vigo
Scientific Committee
Manuel Pérez Cota, Universidad de Vigo (Chair)
Adolfo Lozano Tello, Universidad de Extremadura
Álvaro Rocha, Universidade de Coimbra
Ana Amélia Carvalho, Universidade de Coimbra
Ana Maria Ramalho Correia, Nova Information Management School
Antonio Garcia Loureiro, Universidad de Santiago de Compostela
António Lucas Soares, Universidade do Porto, FEUP
Arnaldo Martins, Universidade de Aveiro
Bráulio Alturas, Instituto Universitário de Lisboa (ISCTE-IUL)
Carlos Ferrás Sexto, Universidad de Santiago de Compostela
David Fonseca, La Salle, Universitat Ramon Llull
Ernest Redondo, Universidad Politécnica de Catalunya
Francisco Restivo, Universidade Católica Portuguesa
Gonçalo Paiva Dias, Universidade de Aveiro
Gonzalo Cuevas Agustin, Universidad Politécnica de Madrid
João Paulo Costa, Universidade de Coimbra
José Borbinha, INESC-ID, IST, Universidade de Lisboa
José Valença, Universidade do Minho
Jose Antonio Calvo-Manzano Villalón, Universidad Politécnica de Madrid
Juan Hernádez, Universidad de Extremadura
Luis Camarinha-Matos, Universidade Nova de Lisboa
Luís Paulo Reis, Universidade do Minho
Marco Painho, Nova Information Management School
Mário Piattini, Universidad de Castilla-La Mancha
Nelson Pacheco Rocha, Universidade de Aveiro
Ramiro Gonçalves, Universidade de Trás-os-Montes e Alto Douro
Webpage of the Doctoral Symposium: http://cisti.eu/index.php?option=com_content&view=article&id=35&Itemid=119&lang=en
Kind regards,
CISTI'2018 Team
http://www.cisti.eu/
---
This email has been checked for viruses by AVG.
http://www.avg.com
[-- Attachment #1.2: Type: text/html, Size: 7964 bytes --]
[-- Attachment #2: 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 net-next v2 1/3] virtio_net: propagate linkspeed/duplex settings from the hypervisor
From: David Miller @ 2017-12-27 21:43 UTC (permalink / raw)
To: jbaron; +Cc: netdev, mst, qemu-devel, virtualization
In-Reply-To: <44da522ecee60792ec918234ee4d61a84e4574f0.1513974243.git.jbaron@akamai.com>
From: Jason Baron <jbaron@akamai.com>
Date: Fri, 22 Dec 2017 16:54:01 -0500
> The ability to set speed and duplex for virtio_net in useful in various
> scenarios as described here:
>
> 16032be virtio_net: add ethtool support for set and get of settings
>
> However, it would be nice to be able to set this from the hypervisor,
> such that virtio_net doesn't require custom guest ethtool commands.
>
> Introduce a new feature flag, VIRTIO_NET_F_SPEED_DUPLEX, which allows
> the hypervisor to export a linkspeed and duplex setting. The user can
> subsequently overwrite it later if desired via: 'ethtool -s'.
>
> Signed-off-by: Jason Baron <jbaron@akamai.com>
> Cc: "Michael S. Tsirkin" <mst@redhat.com>
> Cc: Jason Wang <jasowang@redhat.com>
Looks mostly fine to me but need some virtio_net reviewers on this one.
> @@ -57,6 +57,8 @@
> * Steering */
> #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
>
> +#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Host set linkspeed and duplex */
> +
Why use a value so far away from the largest existing one?
Just curious.
^ permalink raw reply
* [PATCH] drm/virtio: Add window server support
From: Tomeu Vizoso @ 2017-12-28 11:53 UTC (permalink / raw)
To: dri-devel
Cc: Tomeu Vizoso, Michael S. Tsirkin, David Airlie, linux-kernel,
virtualization, Zach Reizner
This is to allow clients running within VMs to be able to communicate
with a compositor in the host. Clients will use the communication
protocol that the compositor supports, and virtio-gpu will assist with
making buffers available in both sides, and copying content as needed.
It is expected that a service in the guest will act as a proxy,
interacting with virtio-gpu to support unmodified clients. For some
features of the protocol, the hypervisor might have to intervene and
also parse the protocol data to properly bridge resources. The following
IOCTLs have been added to this effect:
*_WINSRV_CONNECT: Opens a connection to the compositor in the host,
returns a FD that represents this connection and on which the following
IOCTLs can be used. Callers are expected to poll this FD for new
messages from the compositor.
*_WINSRV_TX: Asks the hypervisor to forward a message to the compositor
*_WINSRV_RX: Returns all queued messages
Alongside protocol data that is opaque to the kernel, the client can
send file descriptors that reference GEM buffers allocated by
virtio-gpu. The guest proxy is expected to figure out when a client is
passing a FD that refers to shared memory in the guest and allocate a
virtio-gpu buffer of the same size with DRM_VIRTGPU_RESOURCE_CREATE.
When the client notifies the compositor that it can read from that buffer,
the proxy should copy the contents from the SHM region to the virtio-gpu
resource and call DRM_VIRTGPU_TRANSFER_TO_HOST.
This has been tested with Wayland clients that make use of wl_shm to
pass buffers to the compositor, but is expected to work similarly for X
clients that make use of MIT-SHM with FD passing.
v2: * Add padding to two virtio command structs
* Properly cast two __user pointers (kbuild test robot)
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Cc: Zach Reizner <zachr@google.com>
---
Hi,
this work is based on the virtio_wl driver in the ChromeOS kernel by
Zach Reizner, currently at:
https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-4.4/drivers/virtio/virtio_wl.c
There's two features missing in this patch when compared with virtio_wl:
* Allow the guest access directly host memory, without having to resort
to TRANSFER_TO_HOST
* Pass FDs from host to guest (Wayland specifies that the compositor
shares keyboard data with the guest via a shared buffer)
I plan to work on this next, but I would like to get some comments on
the general approach so I can better choose which patch to follow.
Thanks,
Tomeu
---
drivers/gpu/drm/virtio/virtgpu_drv.h | 39 ++++-
drivers/gpu/drm/virtio/virtgpu_ioctl.c | 168 +++++++++++++++++++
drivers/gpu/drm/virtio/virtgpu_kms.c | 58 +++++--
drivers/gpu/drm/virtio/virtgpu_vq.c | 285 ++++++++++++++++++++++++++++++++-
include/uapi/drm/virtgpu_drm.h | 29 ++++
include/uapi/linux/virtio_gpu.h | 41 +++++
6 files changed, 605 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index da2fb585fea4..268b386e1232 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -178,6 +178,8 @@ struct virtio_gpu_device {
struct virtio_gpu_queue ctrlq;
struct virtio_gpu_queue cursorq;
+ struct virtio_gpu_queue winsrv_rxq;
+ struct virtio_gpu_queue winsrv_txq;
struct kmem_cache *vbufs;
bool vqs_ready;
@@ -205,10 +207,32 @@ struct virtio_gpu_device {
struct virtio_gpu_fpriv {
uint32_t ctx_id;
+
+ struct list_head winsrv_conns; /* list of virtio_gpu_winsrv_conn */
+ spinlock_t winsrv_lock;
+};
+
+struct virtio_gpu_winsrv_rx_qentry {
+ struct virtio_gpu_winsrv_rx *cmd;
+ struct list_head next;
+};
+
+struct virtio_gpu_winsrv_conn {
+ struct virtio_gpu_device *vgdev;
+
+ spinlock_t lock;
+
+ int fd;
+ struct drm_file *drm_file;
+
+ struct list_head cmdq; /* queue of virtio_gpu_winsrv_rx_qentry */
+ wait_queue_head_t cmdwq;
+
+ struct list_head next;
};
/* virtio_ioctl.c */
-#define DRM_VIRTIO_NUM_IOCTLS 10
+#define DRM_VIRTIO_NUM_IOCTLS 11
extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
/* virtio_kms.c */
@@ -318,9 +342,22 @@ virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
void virtio_gpu_ctrl_ack(struct virtqueue *vq);
void virtio_gpu_cursor_ack(struct virtqueue *vq);
void virtio_gpu_fence_ack(struct virtqueue *vq);
+void virtio_gpu_winsrv_tx_ack(struct virtqueue *vq);
+void virtio_gpu_winsrv_rx_read(struct virtqueue *vq);
void virtio_gpu_dequeue_ctrl_func(struct work_struct *work);
void virtio_gpu_dequeue_cursor_func(struct work_struct *work);
+void virtio_gpu_dequeue_winsrv_rx_func(struct work_struct *work);
+void virtio_gpu_dequeue_winsrv_tx_func(struct work_struct *work);
void virtio_gpu_dequeue_fence_func(struct work_struct *work);
+void virtio_gpu_fill_winsrv_rx(struct virtio_gpu_device *vgdev);
+void virtio_gpu_queue_winsrv_rx_in(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_winsrv_rx *cmd);
+int virtio_gpu_cmd_winsrv_connect(struct virtio_gpu_device *vgdev, int fd);
+void virtio_gpu_cmd_winsrv_disconnect(struct virtio_gpu_device *vgdev, int fd);
+int virtio_gpu_cmd_winsrv_tx(struct virtio_gpu_device *vgdev,
+ const char __user *buffer, u32 len,
+ int *fds, struct virtio_gpu_winsrv_conn *conn,
+ bool nonblock);
/* virtio_gpu_display.c */
int virtio_gpu_framebuffer_init(struct drm_device *dev,
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 0528edb4a2bf..630ed16d5f74 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -25,6 +25,9 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <linux/anon_inodes.h>
+#include <linux/syscalls.h>
+
#include <drm/drmP.h>
#include <drm/virtgpu_drm.h>
#include <drm/ttm/ttm_execbuf_util.h>
@@ -527,6 +530,168 @@ static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
return 0;
}
+static unsigned int winsrv_poll(struct file *filp,
+ struct poll_table_struct *wait)
+{
+ struct virtio_gpu_winsrv_conn *conn = filp->private_data;
+ unsigned int mask = 0;
+
+ spin_lock(&conn->lock);
+ poll_wait(filp, &conn->cmdwq, wait);
+ if (!list_empty(&conn->cmdq))
+ mask |= POLLIN | POLLRDNORM;
+ spin_unlock(&conn->lock);
+
+ return mask;
+}
+
+static int winsrv_ioctl_rx(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_winsrv_conn *conn,
+ struct drm_virtgpu_winsrv *cmd)
+{
+ struct virtio_gpu_winsrv_rx_qentry *qentry, *tmp;
+ struct virtio_gpu_winsrv_rx *virtio_cmd;
+ int available_len = cmd->len;
+ int read_count = 0;
+
+ list_for_each_entry_safe(qentry, tmp, &conn->cmdq, next) {
+ virtio_cmd = qentry->cmd;
+ if (virtio_cmd->len > available_len)
+ return 0;
+
+ if (copy_to_user((void __user *)cmd->data + read_count,
+ virtio_cmd->data,
+ virtio_cmd->len)) {
+ /* return error unless we have some data to return */
+ if (read_count == 0)
+ return -EFAULT;
+ }
+
+ /*
+ * here we could export resource IDs to FDs, but no protocol
+ * as of today requires it
+ */
+
+ available_len -= virtio_cmd->len;
+ read_count += virtio_cmd->len;
+
+ virtio_gpu_queue_winsrv_rx_in(vgdev, virtio_cmd);
+
+ list_del(&qentry->next);
+ kfree(qentry);
+ }
+
+ cmd->len = read_count;
+
+ return 0;
+}
+
+static long winsrv_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct virtio_gpu_winsrv_conn *conn = filp->private_data;
+ struct virtio_gpu_device *vgdev = conn->vgdev;
+ struct drm_virtgpu_winsrv winsrv_cmd;
+ int ret;
+
+ if (_IOC_SIZE(cmd) > sizeof(winsrv_cmd))
+ return -EINVAL;
+
+ if (copy_from_user(&winsrv_cmd, (void __user *)arg,
+ _IOC_SIZE(cmd)) != 0)
+ return -EFAULT;
+
+ switch (cmd) {
+ case DRM_IOCTL_VIRTGPU_WINSRV_RX:
+ ret = winsrv_ioctl_rx(vgdev, conn, &winsrv_cmd);
+ if (copy_to_user((void __user *)arg, &winsrv_cmd,
+ _IOC_SIZE(cmd)) != 0)
+ return -EFAULT;
+
+ break;
+
+ case DRM_IOCTL_VIRTGPU_WINSRV_TX:
+ ret = virtio_gpu_cmd_winsrv_tx(vgdev,
+ u64_to_user_ptr(winsrv_cmd.data),
+ winsrv_cmd.len,
+ winsrv_cmd.fds,
+ conn,
+ filp->f_flags & O_NONBLOCK);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int winsrv_release(struct inode *inodep, struct file *filp)
+{
+ struct virtio_gpu_winsrv_conn *conn = filp->private_data;
+ struct virtio_gpu_device *vgdev = conn->vgdev;
+
+ virtio_gpu_cmd_winsrv_disconnect(vgdev, conn->fd);
+
+ list_del(&conn->next);
+ kfree(conn);
+
+ return 0;
+}
+
+static const struct file_operations winsrv_fops = {
+
+ .poll = winsrv_poll,
+ .unlocked_ioctl = winsrv_ioctl,
+ .release = winsrv_release,
+};
+
+static int virtio_gpu_winsrv_connect(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+ struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+ struct drm_virtgpu_winsrv_connect *args = data;
+ struct virtio_gpu_winsrv_conn *conn;
+ int ret;
+
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+ if (!conn)
+ return -ENOMEM;
+
+ conn->vgdev = vgdev;
+ conn->drm_file = file;
+ spin_lock_init(&conn->lock);
+ INIT_LIST_HEAD(&conn->cmdq);
+ init_waitqueue_head(&conn->cmdwq);
+
+ ret = anon_inode_getfd("[virtgpu_winsrv]", &winsrv_fops, conn,
+ O_CLOEXEC | O_RDWR);
+ if (ret < 0)
+ goto free_conn;
+
+ conn->fd = ret;
+
+ ret = virtio_gpu_cmd_winsrv_connect(vgdev, conn->fd);
+ if (ret < 0)
+ goto close_fd;
+
+ spin_lock(&vfpriv->winsrv_lock);
+ list_add_tail(&conn->next, &vfpriv->winsrv_conns);
+ spin_unlock(&vfpriv->winsrv_lock);
+
+ args->fd = conn->fd;
+
+ return 0;
+
+close_fd:
+ sys_close(conn->fd);
+
+free_conn:
+ kfree(conn);
+
+ return ret;
+}
+
struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
@@ -558,4 +723,7 @@ struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+
+ DRM_IOCTL_DEF_DRV(VIRTGPU_WINSRV_CONNECT, virtio_gpu_winsrv_connect,
+ DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
};
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 6400506a06b0..ad7872037982 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -128,13 +128,15 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
{
static vq_callback_t *callbacks[] = {
- virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack
+ virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack,
+ virtio_gpu_winsrv_rx_read, virtio_gpu_winsrv_tx_ack
};
- static const char * const names[] = { "control", "cursor" };
+ static const char * const names[] = { "control", "cursor",
+ "winsrv-rx", "winsrv-tx" };
struct virtio_gpu_device *vgdev;
/* this will expand later */
- struct virtqueue *vqs[2];
+ struct virtqueue *vqs[4];
u32 num_scanouts, num_capsets;
int ret;
@@ -158,6 +160,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
init_waitqueue_head(&vgdev->resp_wq);
virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func);
virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func);
+ virtio_gpu_init_vq(&vgdev->winsrv_rxq,
+ virtio_gpu_dequeue_winsrv_rx_func);
+ virtio_gpu_init_vq(&vgdev->winsrv_txq,
+ virtio_gpu_dequeue_winsrv_tx_func);
vgdev->fence_drv.context = dma_fence_context_alloc(1);
spin_lock_init(&vgdev->fence_drv.lock);
@@ -175,13 +181,15 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
DRM_INFO("virgl 3d acceleration not supported by guest\n");
#endif
- ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
+ ret = virtio_find_vqs(vgdev->vdev, 4, vqs, callbacks, names, NULL);
if (ret) {
DRM_ERROR("failed to find virt queues\n");
goto err_vqs;
}
vgdev->ctrlq.vq = vqs[0];
vgdev->cursorq.vq = vqs[1];
+ vgdev->winsrv_rxq.vq = vqs[2];
+ vgdev->winsrv_txq.vq = vqs[3];
ret = virtio_gpu_alloc_vbufs(vgdev);
if (ret) {
DRM_ERROR("failed to alloc vbufs\n");
@@ -215,6 +223,9 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
goto err_modeset;
virtio_device_ready(vgdev->vdev);
+
+ virtio_gpu_fill_winsrv_rx(vgdev);
+
vgdev->vqs_ready = true;
if (num_capsets)
@@ -256,6 +267,8 @@ void virtio_gpu_driver_unload(struct drm_device *dev)
vgdev->vqs_ready = false;
flush_work(&vgdev->ctrlq.dequeue_work);
flush_work(&vgdev->cursorq.dequeue_work);
+ flush_work(&vgdev->winsrv_rxq.dequeue_work);
+ flush_work(&vgdev->winsrv_txq.dequeue_work);
flush_work(&vgdev->config_changed_work);
vgdev->vdev->config->del_vqs(vgdev->vdev);
@@ -274,25 +287,43 @@ int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
uint32_t id;
char dbgname[64], tmpname[TASK_COMM_LEN];
- /* can't create contexts without 3d renderer */
- if (!vgdev->has_virgl_3d)
- return 0;
-
- get_task_comm(tmpname, current);
- snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
- dbgname[63] = 0;
/* allocate a virt GPU context for this opener */
vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL);
if (!vfpriv)
return -ENOMEM;
- virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
+ /* can't create contexts without 3d renderer */
+ if (vgdev->has_virgl_3d) {
+ get_task_comm(tmpname, current);
+ snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
+ dbgname[63] = 0;
+
+ virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
+
+ vfpriv->ctx_id = id;
+ }
+
+ spin_lock_init(&vfpriv->winsrv_lock);
+ INIT_LIST_HEAD(&vfpriv->winsrv_conns);
- vfpriv->ctx_id = id;
file->driver_priv = vfpriv;
+
return 0;
}
+static void virtio_gpu_cleanup_conns(struct virtio_gpu_fpriv *vfpriv)
+{
+ struct virtio_gpu_winsrv_conn *conn, *tmp;
+ struct virtio_gpu_winsrv_rx_qentry *qentry, *tmp2;
+
+ list_for_each_entry_safe(conn, tmp, &vfpriv->winsrv_conns, next) {
+ list_for_each_entry_safe(qentry, tmp2, &conn->cmdq, next) {
+ kfree(qentry);
+ }
+ kfree(conn);
+ }
+}
+
void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file)
{
struct virtio_gpu_device *vgdev = dev->dev_private;
@@ -303,6 +334,7 @@ void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file)
vfpriv = file->driver_priv;
+ virtio_gpu_cleanup_conns(vfpriv);
virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id);
kfree(vfpriv);
file->driver_priv = NULL;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 9eb96fb2c147..ea5f9352d364 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -32,7 +32,7 @@
#include <linux/virtio_config.h>
#include <linux/virtio_ring.h>
-#define MAX_INLINE_CMD_SIZE 96
+#define MAX_INLINE_CMD_SIZE 144
#define MAX_INLINE_RESP_SIZE 24
#define VBUFFER_SIZE (sizeof(struct virtio_gpu_vbuffer) \
+ MAX_INLINE_CMD_SIZE \
@@ -72,6 +72,67 @@ void virtio_gpu_cursor_ack(struct virtqueue *vq)
schedule_work(&vgdev->cursorq.dequeue_work);
}
+void virtio_gpu_winsrv_rx_read(struct virtqueue *vq)
+{
+ struct drm_device *dev = vq->vdev->priv;
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+
+ schedule_work(&vgdev->winsrv_rxq.dequeue_work);
+}
+
+void virtio_gpu_winsrv_tx_ack(struct virtqueue *vq)
+{
+ struct drm_device *dev = vq->vdev->priv;
+ struct virtio_gpu_device *vgdev = dev->dev_private;
+
+ schedule_work(&vgdev->winsrv_txq.dequeue_work);
+}
+
+void virtio_gpu_queue_winsrv_rx_in(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_winsrv_rx *cmd)
+{
+ struct virtqueue *vq = vgdev->winsrv_rxq.vq;
+ struct scatterlist sg[1];
+ int ret;
+
+ sg_init_one(sg, cmd, sizeof(*cmd));
+
+ spin_lock(&vgdev->winsrv_rxq.qlock);
+retry:
+ ret = virtqueue_add_inbuf(vq, sg, 1, cmd, GFP_KERNEL);
+ if (ret == -ENOSPC) {
+ spin_unlock(&vgdev->winsrv_rxq.qlock);
+ wait_event(vgdev->winsrv_rxq.ack_queue, vq->num_free);
+ spin_lock(&vgdev->winsrv_rxq.qlock);
+ goto retry;
+ }
+ virtqueue_kick(vq);
+ spin_unlock(&vgdev->winsrv_rxq.qlock);
+}
+
+void virtio_gpu_fill_winsrv_rx(struct virtio_gpu_device *vgdev)
+{
+ struct virtqueue *vq = vgdev->winsrv_rxq.vq;
+ struct virtio_gpu_winsrv_rx *cmd;
+ int ret = 0;
+
+ while (vq->num_free > 0) {
+ cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto clear_queue;
+ }
+
+ virtio_gpu_queue_winsrv_rx_in(vgdev, cmd);
+ }
+
+ return;
+
+clear_queue:
+ while ((cmd = virtqueue_detach_unused_buf(vq)))
+ kfree(cmd);
+}
+
int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
{
vgdev->vbufs = kmem_cache_create("virtio-gpu-vbufs",
@@ -258,6 +319,96 @@ void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
wake_up(&vgdev->cursorq.ack_queue);
}
+void virtio_gpu_dequeue_winsrv_tx_func(struct work_struct *work)
+{
+ struct virtio_gpu_device *vgdev =
+ container_of(work, struct virtio_gpu_device,
+ winsrv_txq.dequeue_work);
+ struct virtio_gpu_vbuffer *vbuf;
+ int len;
+
+ spin_lock(&vgdev->winsrv_txq.qlock);
+ do {
+ while ((vbuf = virtqueue_get_buf(vgdev->winsrv_txq.vq, &len)))
+ free_vbuf(vgdev, vbuf);
+ } while (!virtqueue_enable_cb(vgdev->winsrv_txq.vq));
+ spin_unlock(&vgdev->winsrv_txq.qlock);
+
+ wake_up(&vgdev->winsrv_txq.ack_queue);
+}
+
+static struct virtio_gpu_winsrv_conn *find_conn(struct virtio_gpu_device *vgdev,
+ int fd)
+{
+ struct virtio_gpu_winsrv_conn *conn;
+ struct drm_device *ddev = vgdev->ddev;
+ struct drm_file *file;
+ struct virtio_gpu_fpriv *vfpriv;
+
+ mutex_lock(&ddev->filelist_mutex);
+ list_for_each_entry(file, &ddev->filelist, lhead) {
+ vfpriv = file->driver_priv;
+ spin_lock(&vfpriv->winsrv_lock);
+ list_for_each_entry(conn, &vfpriv->winsrv_conns, next) {
+ if (conn->fd == fd) {
+ spin_lock(&conn->lock);
+ spin_unlock(&vfpriv->winsrv_lock);
+ mutex_unlock(&ddev->filelist_mutex);
+ return conn;
+ }
+ }
+ spin_unlock(&vfpriv->winsrv_lock);
+ }
+ mutex_unlock(&ddev->filelist_mutex);
+
+ return NULL;
+}
+
+static void handle_rx_cmd(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_winsrv_rx *cmd)
+{
+ struct virtio_gpu_winsrv_conn *conn;
+ struct virtio_gpu_winsrv_rx_qentry *qentry;
+
+ conn = find_conn(vgdev, cmd->client_fd);
+ if (!conn) {
+ DRM_DEBUG("recv for unknown client fd %u\n", cmd->client_fd);
+ return;
+ }
+
+ qentry = kzalloc(sizeof(*qentry), GFP_KERNEL);
+ if (!qentry) {
+ spin_unlock(&conn->lock);
+ DRM_DEBUG("failed to allocate qentry for winsrv connection\n");
+ return;
+ }
+
+ qentry->cmd = cmd;
+
+ list_add_tail(&qentry->next, &conn->cmdq);
+ wake_up_interruptible(&conn->cmdwq);
+ spin_unlock(&conn->lock);
+}
+
+void virtio_gpu_dequeue_winsrv_rx_func(struct work_struct *work)
+{
+ struct virtio_gpu_device *vgdev =
+ container_of(work, struct virtio_gpu_device,
+ winsrv_rxq.dequeue_work);
+ struct virtio_gpu_winsrv_rx *cmd;
+ unsigned int len;
+
+ spin_lock(&vgdev->winsrv_rxq.qlock);
+ while ((cmd = virtqueue_get_buf(vgdev->winsrv_rxq.vq, &len)) != NULL) {
+ spin_unlock(&vgdev->winsrv_rxq.qlock);
+ handle_rx_cmd(vgdev, cmd);
+ spin_lock(&vgdev->winsrv_rxq.qlock);
+ }
+ spin_unlock(&vgdev->winsrv_rxq.qlock);
+
+ virtqueue_kick(vgdev->winsrv_rxq.vq);
+}
+
static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
struct virtio_gpu_vbuffer *vbuf)
__releases(&vgdev->ctrlq.qlock)
@@ -380,6 +531,41 @@ static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
return ret;
}
+static int virtio_gpu_queue_winsrv_tx(struct virtio_gpu_device *vgdev,
+ struct virtio_gpu_vbuffer *vbuf)
+{
+ struct virtqueue *vq = vgdev->winsrv_txq.vq;
+ struct scatterlist *sgs[2], vcmd, vout;
+ int ret;
+
+ if (!vgdev->vqs_ready)
+ return -ENODEV;
+
+ sg_init_one(&vcmd, vbuf->buf, vbuf->size);
+ sgs[0] = &vcmd;
+
+ sg_init_one(&vout, vbuf->data_buf, vbuf->data_size);
+ sgs[1] = &vout;
+
+ spin_lock(&vgdev->winsrv_txq.qlock);
+retry:
+ ret = virtqueue_add_sgs(vq, sgs, 2, 0, vbuf, GFP_ATOMIC);
+ if (ret == -ENOSPC) {
+ spin_unlock(&vgdev->winsrv_txq.qlock);
+ wait_event(vgdev->winsrv_txq.ack_queue, vq->num_free);
+ spin_lock(&vgdev->winsrv_txq.qlock);
+ goto retry;
+ }
+
+ virtqueue_kick(vq);
+
+ spin_unlock(&vgdev->winsrv_txq.qlock);
+
+ if (!ret)
+ ret = vq->num_free;
+ return ret;
+}
+
/* just create gem objects for userspace and long lived objects,
just use dma_alloced pages for the queue objects? */
@@ -890,3 +1076,100 @@ void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
memcpy(cur_p, &output->cursor, sizeof(output->cursor));
virtio_gpu_queue_cursor(vgdev, vbuf);
}
+
+int virtio_gpu_cmd_winsrv_connect(struct virtio_gpu_device *vgdev, int fd)
+{
+ struct virtio_gpu_winsrv_connect *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_WINSRV_CONNECT);
+ cmd_p->client_fd = cpu_to_le32(fd);
+ return virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void virtio_gpu_cmd_winsrv_disconnect(struct virtio_gpu_device *vgdev, int fd)
+{
+ struct virtio_gpu_winsrv_disconnect *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_WINSRV_DISCONNECT);
+ cmd_p->client_fd = cpu_to_le32(fd);
+ virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+int virtio_gpu_cmd_winsrv_tx(struct virtio_gpu_device *vgdev,
+ const char __user *buffer, u32 len,
+ int *fds, struct virtio_gpu_winsrv_conn *conn,
+ bool nonblock)
+{
+ int client_fd = conn->fd;
+ struct drm_file *file = conn->drm_file;
+ struct virtio_gpu_winsrv_tx *cmd_p;
+ struct virtio_gpu_vbuffer *vbuf;
+ uint32_t gem_handle;
+ struct drm_gem_object *gobj = NULL;
+ struct virtio_gpu_object *qobj = NULL;
+ int ret, i, fd;
+
+ cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+ memset(cmd_p, 0, sizeof(*cmd_p));
+
+ cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_WINSRV_TX);
+
+ for (i = 0; i < VIRTIO_GPU_WINSRV_MAX_ALLOCS; i++) {
+ cmd_p->resource_ids[i] = -1;
+
+ fd = fds[i];
+ if (fd < 0)
+ break;
+
+ ret = drm_gem_prime_fd_to_handle(vgdev->ddev, file, fd,
+ &gem_handle);
+ if (ret != 0)
+ goto err_free_vbuf;
+
+ gobj = drm_gem_object_lookup(file, gem_handle);
+ if (gobj == NULL) {
+ ret = -ENOENT;
+ goto err_free_vbuf;
+ }
+
+ qobj = gem_to_virtio_gpu_obj(gobj);
+ cmd_p->resource_ids[i] = qobj->hw_res_handle;
+ }
+
+ cmd_p->client_fd = client_fd;
+ cmd_p->len = cpu_to_le32(len);
+
+ /* gets freed when the ring has consumed it */
+ vbuf->data_buf = kmalloc(cmd_p->len, GFP_KERNEL);
+ if (!vbuf->data_buf) {
+ DRM_ERROR("failed to allocate winsrv tx buffer\n");
+ ret = -ENOMEM;
+ goto err_free_vbuf;
+ }
+
+ vbuf->data_size = cmd_p->len;
+
+ if (copy_from_user(vbuf->data_buf, buffer, cmd_p->len)) {
+ ret = -EFAULT;
+ goto err_free_databuf;
+ }
+
+ virtio_gpu_queue_winsrv_tx(vgdev, vbuf);
+
+ return 0;
+
+err_free_databuf:
+ kfree(vbuf->data_buf);
+err_free_vbuf:
+ free_vbuf(vgdev, vbuf);
+
+ return ret;
+}
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
index 91a31ffed828..89b0a1a707a7 100644
--- a/include/uapi/drm/virtgpu_drm.h
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -46,6 +46,11 @@ extern "C" {
#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07
#define DRM_VIRTGPU_WAIT 0x08
#define DRM_VIRTGPU_GET_CAPS 0x09
+#define DRM_VIRTGPU_WINSRV_CONNECT 0x0a
+#define DRM_VIRTGPU_WINSRV_TX 0x0b
+#define DRM_VIRTGPU_WINSRV_RX 0x0c
+
+#define VIRTGPU_WINSRV_MAX_ALLOCS 28
struct drm_virtgpu_map {
__u64 offset; /* use for mmap system call */
@@ -132,6 +137,18 @@ struct drm_virtgpu_get_caps {
__u32 pad;
};
+struct drm_virtgpu_winsrv {
+ __s32 fds[VIRTGPU_WINSRV_MAX_ALLOCS];
+ __u64 data;
+ __u32 len;
+ __u32 pad;
+};
+
+struct drm_virtgpu_winsrv_connect {
+ __u32 fd; /* returned by kernel */
+ __u32 pad;
+};
+
#define DRM_IOCTL_VIRTGPU_MAP \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
@@ -167,6 +184,18 @@ struct drm_virtgpu_get_caps {
DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \
struct drm_virtgpu_get_caps)
+#define DRM_IOCTL_VIRTGPU_WINSRV_CONNECT \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WINSRV_CONNECT, \
+ struct drm_virtgpu_winsrv_connect)
+
+#define DRM_IOCTL_VIRTGPU_WINSRV_TX \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WINSRV_TX, \
+ struct drm_virtgpu_winsrv)
+
+#define DRM_IOCTL_VIRTGPU_WINSRV_RX \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WINSRV_RX, \
+ struct drm_virtgpu_winsrv)
+
#if defined(__cplusplus)
}
#endif
diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
index 4b04ead26cd9..afe830bb8d00 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -71,6 +71,12 @@ enum virtio_gpu_ctrl_type {
VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
VIRTIO_GPU_CMD_MOVE_CURSOR,
+ /* window server commands */
+ VIRTIO_GPU_CMD_WINSRV_CONNECT = 0x0400,
+ VIRTIO_GPU_CMD_WINSRV_DISCONNECT,
+ VIRTIO_GPU_CMD_WINSRV_TX,
+ VIRTIO_GPU_CMD_WINSRV_RX,
+
/* success responses */
VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
@@ -290,6 +296,41 @@ struct virtio_gpu_resp_capset {
__u8 capset_data[];
};
+/* VIRTIO_GPU_CMD_WINSRV_CONNECT */
+struct virtio_gpu_winsrv_connect {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 client_fd;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_WINSRV_DISCONNECT */
+struct virtio_gpu_winsrv_disconnect {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 client_fd;
+ __le32 padding;
+};
+
+#define VIRTIO_GPU_WINSRV_MAX_ALLOCS 28
+#define VIRTIO_GPU_WINSRV_TX_MAX_DATA 4096
+
+/* VIRTIO_GPU_CMD_WINSRV_TX */
+/* these commands are followed in the queue descriptor by protocol buffers */
+struct virtio_gpu_winsrv_tx {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 client_fd;
+ __le32 len;
+ __le32 resource_ids[VIRTIO_GPU_WINSRV_MAX_ALLOCS];
+};
+
+/* VIRTIO_GPU_CMD_WINSRV_RX */
+struct virtio_gpu_winsrv_rx {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 client_fd;
+ __u8 data[VIRTIO_GPU_WINSRV_TX_MAX_DATA];
+ __le32 len;
+ __le32 resource_ids[VIRTIO_GPU_WINSRV_MAX_ALLOCS];
+};
+
#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
struct virtio_gpu_config {
--
2.14.3
^ permalink raw reply related
* Re: [PATCH net-next v2 1/3] virtio_net: propagate linkspeed/duplex settings from the hypervisor
From: Jason Baron via Virtualization @ 2017-12-28 15:53 UTC (permalink / raw)
To: David Miller; +Cc: netdev, mst, qemu-devel, virtualization
In-Reply-To: <20171227.164334.2079471466039224265.davem@davemloft.net>
On 12/27/2017 04:43 PM, David Miller wrote:
> From: Jason Baron <jbaron@akamai.com>
> Date: Fri, 22 Dec 2017 16:54:01 -0500
>
>> The ability to set speed and duplex for virtio_net in useful in various
>> scenarios as described here:
>>
>> 16032be virtio_net: add ethtool support for set and get of settings
>>
>> However, it would be nice to be able to set this from the hypervisor,
>> such that virtio_net doesn't require custom guest ethtool commands.
>>
>> Introduce a new feature flag, VIRTIO_NET_F_SPEED_DUPLEX, which allows
>> the hypervisor to export a linkspeed and duplex setting. The user can
>> subsequently overwrite it later if desired via: 'ethtool -s'.
>>
>> Signed-off-by: Jason Baron <jbaron@akamai.com>
>> Cc: "Michael S. Tsirkin" <mst@redhat.com>
>> Cc: Jason Wang <jasowang@redhat.com>
>
> Looks mostly fine to me but need some virtio_net reviewers on this one.
>
>> @@ -57,6 +57,8 @@
>> * Steering */
>> #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
>>
>> +#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Host set linkspeed and duplex */
>> +
>
> Why use a value so far away from the largest existing one?
>
> Just curious.
>
So that came from a discussion with Michael about which bit to use for
this, and he suggested using 63:
"
Transports started from bit 24 and are growing up.
So I would say devices should start from bit 63 and grow down.
"
https://patchwork.ozlabs.org/patch/848814/#1826669
I will add a comment to explain it.
Thanks,
-Jason
^ permalink raw reply
* Re: [PATCH net-next] virtio_net: implement VIRTIO_CONFIG_S_NEEDS_RESET
From: Willem de Bruijn @ 2017-12-28 19:11 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Willem de Bruijn, Network Development, David Miller,
virtualization
In-Reply-To: <20171017064254-mutt-send-email-mst@kernel.org>
On Mon, Oct 16, 2017 at 11:44 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Tue, Oct 17, 2017 at 11:05:07AM +0800, Jason Wang wrote:
>>
>>
>> On 2017年10月17日 06:34, Willem de Bruijn wrote:
>> > On Mon, Oct 16, 2017 at 12:38 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > > On Mon, Oct 16, 2017 at 12:04:57PM -0400, Willem de Bruijn wrote:
>> > > > On Mon, Oct 16, 2017 at 11:31 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > > > > On Mon, Oct 16, 2017 at 11:03:18AM -0400, Willem de Bruijn wrote:
>> > > > > > > > +static int virtnet_reset(struct virtnet_info *vi)
>> > > > > > > > +{
>> > > > > > > > + struct virtio_device *dev = vi->vdev;
>> > > > > > > > + int ret;
>> > > > > > > > +
>> > > > > > > > + virtio_config_disable(dev);
>> > > > > > > > + dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
>> > > > > > > > + virtnet_freeze_down(dev, true);
>> > > > > > > > + remove_vq_common(vi);
>> > > > > > > > +
>> > > > > > > > + virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
>> > > > > > > > + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
>> > > > > > > > +
>> > > > > > > > + ret = virtio_finalize_features(dev);
>> > > > > > > > + if (ret)
>> > > > > > > > + goto err;
>> > > > > > > > +
>> > > > > > > > + ret = virtnet_restore_up(dev);
>> > > > > > > > + if (ret)
>> > > > > > > > + goto err;
>> > > > > > > > +
>> > > > > > > > + ret = virtnet_set_queues(vi, vi->curr_queue_pairs);
>> > > > > > > > + if (ret)
>> > > > > > > > + goto err;
>> > > > > > > > +
>> > > > > > > > + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
>> > > > > > > > + virtio_config_enable(dev);
>> > > > > > > > + return 0;
>> > > > > > > > +
>> > > > > > > > +err:
>> > > > > > > > + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
>> > > > > > > > + return ret;
>> > > > > > > > +}
>> > > > > > > > +
>> > > > > > > > static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
>> > > > > > > > {
>> > > > > > > > struct scatterlist sg;
>> > > > > > > I have a question here though. How do things like MAC address
>> > > > > > > get restored?
>> > > > > > >
>> > > > > > > What about the rx mode?
>> > > > > > >
>> > > > > > > vlans?
>> > > > > > The function as is releases and reinitializes only ring state.
>> > > > > > Device configuration such as mac and vlan persist across
>> > > > > > the reset.
>> > > > > What gave you this impression? Take a look at e.g. this
>> > > > > code in qemu:
>> > > > >
>> > > > > static void virtio_net_reset(VirtIODevice *vdev)
>> > > > > {
>> > > > > VirtIONet *n = VIRTIO_NET(vdev);
>> > > > >
>> > > > > /* Reset back to compatibility mode */
>> > > > > n->promisc = 1;
>> > > > > n->allmulti = 0;
>> > > > > n->alluni = 0;
>> > > > > n->nomulti = 0;
>> > > > > n->nouni = 0;
>> > > > > n->nobcast = 0;
>> > > > > /* multiqueue is disabled by default */
>> > > > > n->curr_queues = 1;
>> > > > > timer_del(n->announce_timer);
>> > > > > n->announce_counter = 0;
>> > > > > n->status &= ~VIRTIO_NET_S_ANNOUNCE;
>> > > > >
>> > > > > /* Flush any MAC and VLAN filter table state */
>> > > > > n->mac_table.in_use = 0;
>> > > > > n->mac_table.first_multi = 0;
>> > > > > n->mac_table.multi_overflow = 0;
>> > > > > n->mac_table.uni_overflow = 0;
>> > > > > memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
>> > > > > memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
>> > > > > qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
>> > > > > memset(n->vlans, 0, MAX_VLAN >> 3);
>> > > > > }
>> > > > >
>> > > > > So device seems to lose all state, you have to re-program it.
>> > > > Oh, indeed! The guest does not reset its state, so it might
>> > > > be out of sync with the host after the operation. Was this not
>> > > > an issue when previously resetting in the context of xdp?
>> > > I suspect it was broken back then, too.
>> > Okay. I guess that in principle this is all programmable through
>> > virtnet_set_rx_mode, virtnet_vlan_rx_add_vid, etc. But it's a
>> > lot more complex than just restoring virtnet_reset. Will need to
>> > be careful about concurrency issues at the least. Similar to the
>> > ones you point out below.
>> >
>>
>> The problem has been pointed out during developing virtio-net XDP. But it
>> may not be a big issue since vhost_net ignores all kinds of the filters now.
>>
>> Thanks
>
> It might not keep doing that in the future though.
> And virtio-net in userspace doesn't ignore the filters.
How about the guest honor the request only if no state has been
offloaded to the host?
This is the common case for vhost_net, and not expected to change
soon.
Even when it does, we have a graceful degradation strategy. Guest
revert state prior to reset and reapply. Though for the time being,
solving this only in the case without state offload would be solve my
use case.
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH net-next] virtio_net: implement VIRTIO_CONFIG_S_NEEDS_RESET
From: Jason Wang @ 2017-12-29 3:10 UTC (permalink / raw)
To: Willem de Bruijn, Michael S. Tsirkin
Cc: Network Development, Willem de Bruijn, David Miller,
virtualization
In-Reply-To: <CAF=yD-+z_3Pmsa=6_j4Yzt1QxfgbVwNsDoKLc-2rb7rH63p1WQ@mail.gmail.com>
On 2017年12月29日 03:11, Willem de Bruijn wrote:
> On Mon, Oct 16, 2017 at 11:44 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> On Tue, Oct 17, 2017 at 11:05:07AM +0800, Jason Wang wrote:
>>>
>>> On 2017年10月17日 06:34, Willem de Bruijn wrote:
>>>> On Mon, Oct 16, 2017 at 12:38 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>>>>> On Mon, Oct 16, 2017 at 12:04:57PM -0400, Willem de Bruijn wrote:
>>>>>> On Mon, Oct 16, 2017 at 11:31 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>>>>>>> On Mon, Oct 16, 2017 at 11:03:18AM -0400, Willem de Bruijn wrote:
>>>>>>>>>> +static int virtnet_reset(struct virtnet_info *vi)
>>>>>>>>>> +{
>>>>>>>>>> + struct virtio_device *dev = vi->vdev;
>>>>>>>>>> + int ret;
>>>>>>>>>> +
>>>>>>>>>> + virtio_config_disable(dev);
>>>>>>>>>> + dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
>>>>>>>>>> + virtnet_freeze_down(dev, true);
>>>>>>>>>> + remove_vq_common(vi);
>>>>>>>>>> +
>>>>>>>>>> + virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
>>>>>>>>>> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
>>>>>>>>>> +
>>>>>>>>>> + ret = virtio_finalize_features(dev);
>>>>>>>>>> + if (ret)
>>>>>>>>>> + goto err;
>>>>>>>>>> +
>>>>>>>>>> + ret = virtnet_restore_up(dev);
>>>>>>>>>> + if (ret)
>>>>>>>>>> + goto err;
>>>>>>>>>> +
>>>>>>>>>> + ret = virtnet_set_queues(vi, vi->curr_queue_pairs);
>>>>>>>>>> + if (ret)
>>>>>>>>>> + goto err;
>>>>>>>>>> +
>>>>>>>>>> + virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
>>>>>>>>>> + virtio_config_enable(dev);
>>>>>>>>>> + return 0;
>>>>>>>>>> +
>>>>>>>>>> +err:
>>>>>>>>>> + virtio_add_status(dev, VIRTIO_CONFIG_S_FAILED);
>>>>>>>>>> + return ret;
>>>>>>>>>> +}
>>>>>>>>>> +
>>>>>>>>>> static int virtnet_set_guest_offloads(struct virtnet_info *vi, u64 offloads)
>>>>>>>>>> {
>>>>>>>>>> struct scatterlist sg;
>>>>>>>>> I have a question here though. How do things like MAC address
>>>>>>>>> get restored?
>>>>>>>>>
>>>>>>>>> What about the rx mode?
>>>>>>>>>
>>>>>>>>> vlans?
>>>>>>>> The function as is releases and reinitializes only ring state.
>>>>>>>> Device configuration such as mac and vlan persist across
>>>>>>>> the reset.
>>>>>>> What gave you this impression? Take a look at e.g. this
>>>>>>> code in qemu:
>>>>>>>
>>>>>>> static void virtio_net_reset(VirtIODevice *vdev)
>>>>>>> {
>>>>>>> VirtIONet *n = VIRTIO_NET(vdev);
>>>>>>>
>>>>>>> /* Reset back to compatibility mode */
>>>>>>> n->promisc = 1;
>>>>>>> n->allmulti = 0;
>>>>>>> n->alluni = 0;
>>>>>>> n->nomulti = 0;
>>>>>>> n->nouni = 0;
>>>>>>> n->nobcast = 0;
>>>>>>> /* multiqueue is disabled by default */
>>>>>>> n->curr_queues = 1;
>>>>>>> timer_del(n->announce_timer);
>>>>>>> n->announce_counter = 0;
>>>>>>> n->status &= ~VIRTIO_NET_S_ANNOUNCE;
>>>>>>>
>>>>>>> /* Flush any MAC and VLAN filter table state */
>>>>>>> n->mac_table.in_use = 0;
>>>>>>> n->mac_table.first_multi = 0;
>>>>>>> n->mac_table.multi_overflow = 0;
>>>>>>> n->mac_table.uni_overflow = 0;
>>>>>>> memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
>>>>>>> memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
>>>>>>> qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
>>>>>>> memset(n->vlans, 0, MAX_VLAN >> 3);
>>>>>>> }
>>>>>>>
>>>>>>> So device seems to lose all state, you have to re-program it.
>>>>>> Oh, indeed! The guest does not reset its state, so it might
>>>>>> be out of sync with the host after the operation. Was this not
>>>>>> an issue when previously resetting in the context of xdp?
>>>>> I suspect it was broken back then, too.
>>>> Okay. I guess that in principle this is all programmable through
>>>> virtnet_set_rx_mode, virtnet_vlan_rx_add_vid, etc. But it's a
>>>> lot more complex than just restoring virtnet_reset. Will need to
>>>> be careful about concurrency issues at the least. Similar to the
>>>> ones you point out below.
>>>>
>>> The problem has been pointed out during developing virtio-net XDP. But it
>>> may not be a big issue since vhost_net ignores all kinds of the filters now.
>>>
>>> Thanks
>> It might not keep doing that in the future though.
>> And virtio-net in userspace doesn't ignore the filters.
> How about the guest honor the request only if no state has been
> offloaded to the host?
>
> This is the common case for vhost_net, and not expected to change
> soon.
FYI, I'm implementing to use tun eBPF filter for virtio-net. So
recovering filter should be considered.
Thanks
>
> Even when it does, we have a graceful degradation strategy. Guest
> revert state prior to reset and reapply. Though for the time being,
> solving this only in the case without state offload would be solve my
> use case.
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Call for papers - MICRADS 2018 - Salinas, Ecuador
From: Marle @ 2017-12-29 20:52 UTC (permalink / raw)
To: virtualization
* Proceedings by Springer and indexed by Scopus, etc.
---------------------------------------------------------------------------------------------------------------------------
MICRADS´18 - The 2018 Multidisciplinary International Conference of Research Applied to Defense and Security
Salinas, Ecuador, 18 - 20 April 2018
http://www.micrads.org/
------------------------------------------------------------------------------------------------------------------------------------
SCOPE
MICRADS´18 - The 2018 Multidisciplinary International Conference of Research Applied to Defense and Security, to be held at Salinas, Ecuador, 18 - 20 April 2018, is an international forum for researchers and practitioners to present and discuss the most recent innovations, trends, results, experiences and concerns in the several perspectives of Defense and Security.
We are pleased to invite you to submit your papers to MICRADS´18. They can be written in English, Spanish or Portuguese. All submissions will be reviewed on the basis of relevance, originality, importance and clarity.
TOPICS
Submitted papers should be related with one or more of the main themes proposed for the Conference:
A) Information and Communication Technology in Education;
B) Computer vision in military applications;
C) Engineering Analysis and Signal Processing;
D) Cybersecurity and Cyberdefense;
E) Maritime Security and Safety;
F) Strategy, geopolitics and Oceanopolitics;
G) Defense planning;
H) Leadership (e-leadership);
I) Defense Economics;
J) Defense Logistics;
K) Health informatics in military applications;
L) Simulation in Military Application;
M) Computer Networks, Mobility and Pervasive Systems;
N) Military Marketing;
O) Military Physical Training;
P) Assistive Devices and Wearable Technology;
Q) Naval and Military Engineering;
R) Weapons and Combat Systems;
S) Operational Oceanography.
SUBMISSION AND DECISION
Submitted papers (until 6-page limit) must comply with the format standard (http://www.micrads.org/images/Templates.rar), be written in English, Spanish or Portuguese, must not have been published before, not be under review for any other conference or publication and not include any information leading to the authors? identification. Therefore, the authors? names, affiliations and bibliographic references should not be included in the version for evaluation by the Scientific Committee. This information should only be included in the camera-ready version, saved in Word format and uploaded at the conference management system.
All papers will be subjected to a ?double-blind review? by at least two members of the Scientific Committee.
Based on Scientific Committee evaluation, a paper can be rejected or accepted by the Conference Chairs. In the later case, it can be accepted as paper or poster.
The authors of papers accepted as posters must build and print a poster to be exhibited during the Conference. This poster must follow an A1 or A2 vertical format. The Conference can includes Work Sessions where these posters are presented and orally discussed, with a 7 minute limit per poster.
The authors of accepted papers will have 15 minutes to present their work in a Conference Work Session; approximately 5 minutes of discussion will follow each presentation.
PUBLICATION AND INDEXING
To ensure that an accepted paper is published, at least one of the authors must be fully registered by the 3 of February 2018, and the paper must comply with the suggested layout and page-limit (until 10 pages). Additionally, all recommended changes must be addressed by the authors before they submit the camera-ready version.
No more than one paper per registration will be published. An extra fee must be paid for publication of additional papers, with a maximum of one additional paper per registration. One registration permits only the participation of one author in the conference.
Papers can be written in English, Spanish or Portuguese. Accepted and registered papers will be published in Proceedings by Springer, in a book of its SIST series, and will be submitted for indexing by ISI, SCOPUS, EI-Compendex, SpingerLink, and Google Scholar.
IMPORTANT DATES
Paper Submission: January 14, 2018
Notification of Acceptance: February 14, 2018
Payment of Registration, to ensure the inclusion of an accepted paper in the conference proceedings: February 18, 2018.
Camera-ready Submission: February 21, 2018
-
Website o MICRADS'18: http://www.micrads.org/
-------
---
This email has been checked for viruses by AVG.
http://www.avg.com
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* [bpf-next V3 PATCH 11/14] virtio_net: setup xdp_rxq_info
From: Jesper Dangaard Brouer @ 2017-12-31 11:01 UTC (permalink / raw)
To: Daniel Borkmann, Alexei Starovoitov
Cc: Michael S. Tsirkin, netdev, Jesper Dangaard Brouer,
virtualization, dsahern, gospo, bjorn.topel, michael.chan
In-Reply-To: <151471801977.30703.3258796879718706203.stgit@firesoul>
The virtio_net driver doesn't dynamically change the RX-ring queue
layout and backing pages, but instead reject XDP setup if all the
conditions for XDP is not meet. Thus, the xdp_rxq_info also remains
fairly static. This allow us to simply add the reg/unreg to
net_device open/close functions.
Driver hook points for xdp_rxq_info:
* reg : virtnet_open
* unreg: virtnet_close
V3:
- bugfix, also setup xdp.rxq in receive_mergeable()
- Tested bpf-sample prog inside guest on a virtio_net device
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: virtualization@lists.linux-foundation.org
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
---
drivers/net/virtio_net.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6fb7b658a6cc..ed8299343728 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -31,6 +31,7 @@
#include <linux/average.h>
#include <linux/filter.h>
#include <net/route.h>
+#include <net/xdp.h>
static int napi_weight = NAPI_POLL_WEIGHT;
module_param(napi_weight, int, 0444);
@@ -115,6 +116,8 @@ struct receive_queue {
/* Name of this receive queue: input.$index */
char name[40];
+
+ struct xdp_rxq_info xdp_rxq;
};
struct virtnet_info {
@@ -559,6 +562,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
xdp.data = xdp.data_hard_start + xdp_headroom;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + len;
+ xdp.rxq = &rq->xdp_rxq;
orig_data = xdp.data;
act = bpf_prog_run_xdp(xdp_prog, &xdp);
@@ -692,6 +696,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
xdp.data = data + vi->hdr_len;
xdp_set_data_meta_invalid(&xdp);
xdp.data_end = xdp.data + (len - vi->hdr_len);
+ xdp.rxq = &rq->xdp_rxq;
+
act = bpf_prog_run_xdp(xdp_prog, &xdp);
if (act != XDP_PASS)
@@ -1225,13 +1231,18 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
static int virtnet_open(struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
- int i;
+ int i, err;
for (i = 0; i < vi->max_queue_pairs; i++) {
if (i < vi->curr_queue_pairs)
/* Make sure we have some buffers: if oom use wq. */
if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
schedule_delayed_work(&vi->refill, 0);
+
+ err = xdp_rxq_info_reg(&vi->rq[i].xdp_rxq, dev, i);
+ if (err < 0)
+ return err;
+
virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
}
@@ -1560,6 +1571,7 @@ static int virtnet_close(struct net_device *dev)
cancel_delayed_work_sync(&vi->refill);
for (i = 0; i < vi->max_queue_pairs; i++) {
+ xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
napi_disable(&vi->rq[i].napi);
virtnet_napi_tx_disable(&vi->sq[i].napi);
}
^ permalink raw reply related
* Re: [bpf-next V3 PATCH 11/14] virtio_net: setup xdp_rxq_info
From: Jason Wang @ 2018-01-02 3:38 UTC (permalink / raw)
To: Jesper Dangaard Brouer, Daniel Borkmann, Alexei Starovoitov
Cc: Michael S. Tsirkin, netdev, virtualization, dsahern, gospo,
bjorn.topel, michael.chan
In-Reply-To: <151471811006.30703.5247549257959215999.stgit@firesoul>
On 2017年12月31日 19:01, Jesper Dangaard Brouer wrote:
> The virtio_net driver doesn't dynamically change the RX-ring queue
> layout and backing pages, but instead reject XDP setup if all the
> conditions for XDP is not meet. Thus, the xdp_rxq_info also remains
> fairly static. This allow us to simply add the reg/unreg to
> net_device open/close functions.
>
> Driver hook points for xdp_rxq_info:
> * reg : virtnet_open
> * unreg: virtnet_close
>
> V3:
> - bugfix, also setup xdp.rxq in receive_mergeable()
> - Tested bpf-sample prog inside guest on a virtio_net device
>
> Cc: "Michael S. Tsirkin" <mst@redhat.com>
> Cc: Jason Wang <jasowang@redhat.com>
> Cc: virtualization@lists.linux-foundation.org
> Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
> ---
> drivers/net/virtio_net.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 6fb7b658a6cc..ed8299343728 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -31,6 +31,7 @@
> #include <linux/average.h>
> #include <linux/filter.h>
> #include <net/route.h>
> +#include <net/xdp.h>
>
> static int napi_weight = NAPI_POLL_WEIGHT;
> module_param(napi_weight, int, 0444);
> @@ -115,6 +116,8 @@ struct receive_queue {
>
> /* Name of this receive queue: input.$index */
> char name[40];
> +
> + struct xdp_rxq_info xdp_rxq;
> };
>
> struct virtnet_info {
> @@ -559,6 +562,7 @@ static struct sk_buff *receive_small(struct net_device *dev,
> xdp.data = xdp.data_hard_start + xdp_headroom;
> xdp_set_data_meta_invalid(&xdp);
> xdp.data_end = xdp.data + len;
> + xdp.rxq = &rq->xdp_rxq;
> orig_data = xdp.data;
> act = bpf_prog_run_xdp(xdp_prog, &xdp);
>
> @@ -692,6 +696,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
> xdp.data = data + vi->hdr_len;
> xdp_set_data_meta_invalid(&xdp);
> xdp.data_end = xdp.data + (len - vi->hdr_len);
> + xdp.rxq = &rq->xdp_rxq;
> +
> act = bpf_prog_run_xdp(xdp_prog, &xdp);
>
> if (act != XDP_PASS)
> @@ -1225,13 +1231,18 @@ static int virtnet_poll(struct napi_struct *napi, int budget)
> static int virtnet_open(struct net_device *dev)
> {
> struct virtnet_info *vi = netdev_priv(dev);
> - int i;
> + int i, err;
>
> for (i = 0; i < vi->max_queue_pairs; i++) {
> if (i < vi->curr_queue_pairs)
> /* Make sure we have some buffers: if oom use wq. */
> if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
> schedule_delayed_work(&vi->refill, 0);
> +
> + err = xdp_rxq_info_reg(&vi->rq[i].xdp_rxq, dev, i);
> + if (err < 0)
> + return err;
> +
> virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
> virtnet_napi_tx_enable(vi, vi->sq[i].vq, &vi->sq[i].napi);
> }
> @@ -1560,6 +1571,7 @@ static int virtnet_close(struct net_device *dev)
> cancel_delayed_work_sync(&vi->refill);
>
> for (i = 0; i < vi->max_queue_pairs; i++) {
> + xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
> napi_disable(&vi->rq[i].napi);
> virtnet_napi_tx_disable(&vi->sq[i].napi);
> }
>
Reviewed-by: Jason Wang <jasowang@redhat.com>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [PATCH v20 4/7] virtio-balloon: VIRTIO_BALLOON_F_SG
From: Matthew Wilcox @ 2018-01-02 13:24 UTC (permalink / raw)
To: Wei Wang
Cc: yang.zhang.wz, kvm, mst, Tetsuo Handa, liliang.opensource,
qemu-devel, virtualization, linux-mm, aarcange, virtio-dev,
mawilcox, nilal, riel, cornelia.huck, mhocko, quan.xu0,
linux-kernel, amit.shah, pbonzini, akpm, mgorman
In-Reply-To: <5A3F5A4A.1070009@intel.com>
On Sun, Dec 24, 2017 at 03:42:02PM +0800, Wei Wang wrote:
> On 12/24/2017 12:45 PM, Tetsuo Handa wrote:
> > Matthew Wilcox wrote:
> > > If you can't preload with anything better than that, I think that
> > > xb_set_bit() should attempt an allocation with GFP_NOWAIT | __GFP_NOWARN,
> > > and then you can skip the preload; it has no value for you.
> > Yes, that's why I suggest directly using kzalloc() at xb_set_bit().
>
> It has some possibilities to remove that preload if we also do the bitmap
> allocation in the xb_set_bit():
>
> bitmap = rcu_dereference_raw(*slot);
> if (!bitmap) {
> bitmap = this_cpu_xchg(ida_bitmap, NULL);
> if (!bitmap) {
> bitmap = kmalloc(sizeof(*bitmap), gfp);
> if (!bitmap)
> return -ENOMEM;
> }
> }
>
> But why not just follow the radix tree implementation style that puts the
> allocation in preload, which would be invoked with a more relaxed gfp in
> other use cases?
Actually, the radix tree does attempt allocation, and falls back to the
preload. The IDA was the odd one out that doesn't attempt allocation,
and that was where I copied the code from. For other users, the preload
API is beneficial, so I will leave it in.
> Its usage in virtio_balloon is just a little special that we need to put the
> allocation within the balloon_lock, which doesn't give us the benefit of
> using a relaxed gfp in preload, but it doesn't prevent us from living with
> the current APIs (i.e. the preload + xb_set pattern).
> On the other side, if we do it as above, we have more things that need to
> consider. For example, what if the a use case just want the radix tree
> implementation style, which means it doesn't want allocation within
> xb_set(), then would we be troubled with how to avoid the allocation path in
> that case?
>
> So, I think it is better to stick with the convention by putting the
> allocation in preload. Breaking the convention should show obvious
> advantages, IMHO.
The radix tree convention is objectively awful, which is why I'm working
to change it. Specifying the GFP flags at radix tree initialisation time
rather than allocation time leads to all kinds of confusion. The preload
API is a pretty awful workaround, and it will go away once the XArray
is working correctly. That said, there's no alternative to it without
making XBitmap depend on XArray, and I don't want to hold you up there.
So there's an xb_preload for the moment.
^ permalink raw reply
* Re: [PATCH v20 3/7 RESEND] xbitmap: add more operations
From: Matthew Wilcox @ 2018-01-02 14:09 UTC (permalink / raw)
To: Wei Wang
Cc: virtio-dev, kvm, mst, qemu-devel, penguin-kernel, mawilcox,
linux-kernel, virtualization, linux-mm, akpm, mhocko
In-Reply-To: <5A3CC707.9070708@intel.com>
On Fri, Dec 22, 2017 at 04:49:11PM +0800, Wei Wang wrote:
> Thanks for the improvement. I also found a small bug in xb_zero. With the
> following changes, it has passed the current test cases and tested with the
> virtio-balloon usage without any issue.
Thanks; I applied the change. Can you supply a test-case for testing
xb_zero please?
> > @@ -25,8 +26,11 @@ idr-test: idr-test.o $(CORE_OFILES)
> > multiorder: multiorder.o $(CORE_OFILES)
> > +xbitmap: xbitmap.o $(CORE_OFILES)
> > + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o xbitmap
> > +
>
> I think the "$(CC).." line should be removed, which will fix the build error
> when adding "xbitmap" to TARGET.
Not sure what build error you're talking about, but yes that CC line
should go. Thanks, deleted.
^ permalink raw reply
* Re: [PATCH v5 4/4] virtio_remoteproc: correct put_device virtio_device.dev
From: Bjorn Andersson @ 2018-01-02 17:34 UTC (permalink / raw)
To: weiping zhang; +Cc: cohuck, virtualization, mst
In-Reply-To: <742b7e56647f9a1c9fbf0bbc0dc5b93742382371.1513825904.git.zhangweiping@didichuxing.com>
On Thu 21 Dec 04:40 PST 2017, weiping zhang wrote:
> rproc_virtio_dev_release will be called iff virtio_device.dev's
> reference count drops to 0. Here we just put vdev.dev, and then
> rproc->dev's cleanup will be done in rproc_virtio_dev_release.
>
> Signed-off-by: weiping zhang <zhangweiping@didichuxing.com>
Thanks weiping and Cornelia, applied.
Regards,
Bjorn
> ---
> drivers/remoteproc/remoteproc_virtio.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 2946348..b0633fd 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -327,7 +327,7 @@ int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
>
> ret = register_virtio_device(vdev);
> if (ret) {
> - put_device(&rproc->dev);
> + put_device(&vdev->dev);
> dev_err(dev, "failed to register vdev: %d\n", ret);
> goto out;
> }
> --
> 2.9.4
>
^ permalink raw reply
* Re: [PATCH] virtio: make VIRTIO a menuconfig to ease disabling it all
From: Michael Ellerman @ 2018-01-02 22:40 UTC (permalink / raw)
To: Vincent Legoll; +Cc: virtualization, Linux Kernel ML, mst
In-Reply-To: <87h8sjpl2p.fsf@concordia.ellerman.id.au>
Michael Ellerman <mpe@ellerman.id.au> writes:
> Vincent Legoll <vincent.legoll@gmail.com> writes:
>
>> Hello,
>>
>> thanks for the help, and sorry for the poor patch,
>>
>> On Thu, Dec 21, 2017 at 11:53 AM, Michael Ellerman <mpe@ellerman.id.au> wrote:
>>> This breaks all existing .configs *and* defconfigs that use VIRTIO.
>>>
>>> Please don't do that.
>>>
>>> If you make it default y then everything will continue to work.
>>
>> Do you want me to respin it with the added default ?
>
> Yes please, either that or revert it.
This still seems to be broken.
cheers
^ permalink raw reply
* [PATCH net-next 0/2] Enable virtio to act as a master for a passthru device
From: Sridhar Samudrala @ 2018-01-03 0:35 UTC (permalink / raw)
To: mst, stephen, netdev, virtualization, virtio-dev,
jesse.brandeburg, sridhar.samudrala
This patch series enables virtio 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 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.
It is based on netvsc implementation and it may be possible to make this code
generic and move it to a common location that can be shared by netvsc and virtio.
This patch series is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
Sridhar Samudrala (2):
virtio_net: Introduce VIRTIO_NET_F_MASTER feature bit
virtio_net: Extend virtio to use VF datapath when available
drivers/net/virtio_net.c | 308 +++++++++++++++++++++++++++++++++++++++-
include/uapi/linux/virtio_net.h | 1 +
2 files changed, 306 insertions(+), 3 deletions(-)
--
2.14.3
^ permalink raw reply
* [PATCH net-next 1/2] virtio_net: Introduce VIRTIO_NET_F_MASTER feature bit
From: Sridhar Samudrala @ 2018-01-03 0:35 UTC (permalink / raw)
To: mst, stephen, netdev, virtualization, virtio-dev,
jesse.brandeburg, sridhar.samudrala
In-Reply-To: <1514939738-22423-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 master for a directly attached passthru device with the same MAC
address.
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/virtio_net.c | 3 ++-
include/uapi/linux/virtio_net.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6fb7b658a6cc..46844a1d9a62 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2796,7 +2796,8 @@ static struct virtio_device_id id_table[] = {
VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, \
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
VIRTIO_NET_F_CTRL_MAC_ADDR, \
- VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
+ VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
+ VIRTIO_NET_F_MASTER
static unsigned int features[] = {
VIRTNET_FEATURES,
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index fc353b518288..a9b4e0836786 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -56,6 +56,7 @@
#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow
* Steering */
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
+#define VIRTIO_NET_F_MASTER 62 /* act as master for a VF device */
#ifndef VIRTIO_NET_NO_LEGACY
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
--
2.14.3
^ permalink raw reply related
* [PATCH net-next 2/2] virtio_net: Extend virtio to use VF datapath when available
From: Sridhar Samudrala @ 2018-01-03 0:35 UTC (permalink / raw)
To: mst, stephen, netdev, virtualization, virtio-dev,
jesse.brandeburg, sridhar.samudrala
In-Reply-To: <1514939738-22423-1-git-send-email-sridhar.samudrala@intel.com>
This patch enables virtio 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 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
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---
drivers/net/virtio_net.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 303 insertions(+), 2 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 46844a1d9a62..6516dcb55b7d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -31,6 +31,8 @@
#include <linux/average.h>
#include <linux/filter.h>
#include <net/route.h>
+#include <linux/netdevice.h>
+#include <linux/netpoll.h>
static int napi_weight = NAPI_POLL_WEIGHT;
module_param(napi_weight, int, 0444);
@@ -117,6 +119,15 @@ struct receive_queue {
char name[40];
};
+struct virtnet_vf_pcpu_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync syncp;
+ u32 tx_dropped;
+};
+
struct virtnet_info {
struct virtio_device *vdev;
struct virtqueue *cvq;
@@ -179,6 +190,10 @@ struct virtnet_info {
u32 speed;
unsigned long guest_offloads;
+
+ /* State to manage the associated VF interface. */
+ struct net_device __rcu *vf_netdev;
+ struct virtnet_vf_pcpu_stats __percpu *vf_stats;
};
struct padded_vnet_hdr {
@@ -1303,16 +1318,51 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC);
}
+/* Send skb on the slave VF device. */
+static int virtnet_vf_xmit(struct net_device *dev, struct net_device *vf_netdev,
+ struct sk_buff *skb)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ unsigned int len = skb->len;
+ int rc;
+
+ skb->dev = vf_netdev;
+ skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+
+ rc = dev_queue_xmit(skb);
+ if (likely(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN)) {
+ struct virtnet_vf_pcpu_stats *pcpu_stats
+ = this_cpu_ptr(vi->vf_stats);
+
+ u64_stats_update_begin(&pcpu_stats->syncp);
+ pcpu_stats->tx_packets++;
+ pcpu_stats->tx_bytes += len;
+ u64_stats_update_end(&pcpu_stats->syncp);
+ } else {
+ this_cpu_inc(vi->vf_stats->tx_dropped);
+ }
+
+ return rc;
+}
+
static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct virtnet_info *vi = netdev_priv(dev);
int qnum = skb_get_queue_mapping(skb);
struct send_queue *sq = &vi->sq[qnum];
+ struct net_device *vf_netdev;
int err;
struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
bool kick = !skb->xmit_more;
bool use_napi = sq->napi.weight;
+ /* If VF is present and up then redirect packets
+ * called with rcu_read_lock_bh
+ */
+ vf_netdev = rcu_dereference_bh(vi->vf_netdev);
+ if (vf_netdev && netif_running(vf_netdev) && !netpoll_tx_running(dev))
+ return virtnet_vf_xmit(dev, vf_netdev, skb);
+
/* Free up any pending old buffers before queueing new ones. */
free_old_xmit_skbs(sq);
@@ -1459,10 +1509,41 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
return ret;
}
+static void virtnet_get_vf_stats(struct net_device *dev,
+ struct virtnet_vf_pcpu_stats *tot)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int i;
+
+ memset(tot, 0, sizeof(*tot));
+
+ for_each_possible_cpu(i) {
+ const struct virtnet_vf_pcpu_stats *stats
+ = per_cpu_ptr(vi->vf_stats, i);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ unsigned int start;
+
+ do {
+ start = u64_stats_fetch_begin_irq(&stats->syncp);
+ rx_packets = stats->rx_packets;
+ tx_packets = stats->tx_packets;
+ rx_bytes = stats->rx_bytes;
+ tx_bytes = stats->tx_bytes;
+ } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
+
+ tot->rx_packets += rx_packets;
+ tot->tx_packets += tx_packets;
+ tot->rx_bytes += rx_bytes;
+ tot->tx_bytes += tx_bytes;
+ tot->tx_dropped += stats->tx_dropped;
+ }
+}
+
static void virtnet_stats(struct net_device *dev,
struct rtnl_link_stats64 *tot)
{
struct virtnet_info *vi = netdev_priv(dev);
+ struct virtnet_vf_pcpu_stats vf_stats;
int cpu;
unsigned int start;
@@ -1493,6 +1574,13 @@ static void virtnet_stats(struct net_device *dev,
tot->rx_dropped = dev->stats.rx_dropped;
tot->rx_length_errors = dev->stats.rx_length_errors;
tot->rx_frame_errors = dev->stats.rx_frame_errors;
+
+ virtnet_get_vf_stats(dev, &vf_stats);
+ tot->rx_packets += vf_stats.rx_packets;
+ tot->tx_packets += vf_stats.tx_packets;
+ tot->rx_bytes += vf_stats.rx_bytes;
+ tot->tx_bytes += vf_stats.tx_bytes;
+ tot->tx_dropped += vf_stats.tx_dropped;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2604,6 +2692,13 @@ static int virtnet_probe(struct virtio_device *vdev)
INIT_WORK(&vi->config_work, virtnet_config_changed_work);
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_MASTER)) {
+ vi->vf_stats =
+ netdev_alloc_pcpu_stats(struct virtnet_vf_pcpu_stats);
+ if (!vi->vf_stats)
+ goto free_stats;
+ }
+
/* If we can receive ANY GSO packets, we must allocate large ones. */
if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
@@ -2637,7 +2732,7 @@ static int virtnet_probe(struct virtio_device *vdev)
*/
dev_err(&vdev->dev, "device MTU appears to have changed "
"it is now %d < %d", mtu, dev->min_mtu);
- goto free_stats;
+ goto free_vf_stats;
}
dev->mtu = mtu;
@@ -2661,7 +2756,7 @@ static int virtnet_probe(struct virtio_device *vdev)
/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
err = init_vqs(vi);
if (err)
- goto free_stats;
+ goto free_vf_stats;
#ifdef CONFIG_SYSFS
if (vi->mergeable_rx_bufs)
@@ -2715,6 +2810,8 @@ static int virtnet_probe(struct virtio_device *vdev)
cancel_delayed_work_sync(&vi->refill);
free_receive_page_frags(vi);
virtnet_del_vqs(vi);
+free_vf_stats:
+ free_percpu(vi->vf_stats);
free_stats:
free_percpu(vi->stats);
free:
@@ -2736,19 +2833,184 @@ static void remove_vq_common(struct virtnet_info *vi)
virtnet_del_vqs(vi);
}
+static struct net_device *get_virtio_bymac(const u8 *mac)
+{
+ struct net_device *dev;
+
+ ASSERT_RTNL();
+
+ for_each_netdev(&init_net, dev) {
+ if (dev->netdev_ops != &virtnet_netdev)
+ continue; /* not a virtio_net device */
+
+ if (ether_addr_equal(mac, dev->perm_addr))
+ return dev;
+ }
+
+ return NULL;
+}
+
+static struct net_device *get_virtio_byref(struct net_device *vf_netdev)
+{
+ struct net_device *dev;
+
+ ASSERT_RTNL();
+
+ for_each_netdev(&init_net, dev) {
+ struct virtnet_info *vi;
+
+ if (dev->netdev_ops != &virtnet_netdev)
+ continue; /* not a virtio_net device */
+
+ vi = netdev_priv(dev);
+ if (rtnl_dereference(vi->vf_netdev) == vf_netdev)
+ return dev; /* a match */
+ }
+
+ return NULL;
+}
+
+/* Called when VF is injecting data into network stack.
+ * Change the associated network device from VF to virtio.
+ * note: already called with rcu_read_lock
+ */
+static rx_handler_result_t virtnet_vf_handle_frame(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct net_device *ndev = rcu_dereference(skb->dev->rx_handler_data);
+ struct virtnet_info *vi = netdev_priv(ndev);
+ struct virtnet_vf_pcpu_stats *pcpu_stats =
+ this_cpu_ptr(vi->vf_stats);
+
+ skb->dev = ndev;
+
+ u64_stats_update_begin(&pcpu_stats->syncp);
+ pcpu_stats->rx_packets++;
+ pcpu_stats->rx_bytes += skb->len;
+ u64_stats_update_end(&pcpu_stats->syncp);
+
+ return RX_HANDLER_ANOTHER;
+}
+
+static int virtnet_vf_join(struct net_device *vf_netdev,
+ struct net_device *ndev)
+{
+ int ret;
+
+ ret = netdev_rx_handler_register(vf_netdev,
+ virtnet_vf_handle_frame, ndev);
+ if (ret != 0) {
+ netdev_err(vf_netdev,
+ "can not register virtio VF receive handler (err = %d)\n",
+ ret);
+ goto rx_handler_failed;
+ }
+
+ ret = netdev_upper_dev_link(vf_netdev, ndev, NULL);
+ if (ret != 0) {
+ netdev_err(vf_netdev,
+ "can not set master device %s (err = %d)\n",
+ ndev->name, ret);
+ goto upper_link_failed;
+ }
+
+ vf_netdev->flags |= IFF_SLAVE;
+
+ /* Align MTU of VF with master */
+ ret = dev_set_mtu(vf_netdev, ndev->mtu);
+ if (ret)
+ netdev_warn(vf_netdev,
+ "unable to change mtu to %u\n", ndev->mtu);
+
+ call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+
+ netdev_info(vf_netdev, "joined to %s\n", ndev->name);
+ return 0;
+
+upper_link_failed:
+ netdev_rx_handler_unregister(vf_netdev);
+rx_handler_failed:
+ return ret;
+}
+
+static int virtnet_register_vf(struct net_device *vf_netdev)
+{
+ struct net_device *ndev;
+ struct virtnet_info *vi;
+
+ if (vf_netdev->addr_len != ETH_ALEN)
+ return NOTIFY_DONE;
+
+ /* We will use the MAC address to locate the virtio_net interface to
+ * associate with the VF interface. If we don't find a matching
+ * virtio interface, move on.
+ */
+ ndev = get_virtio_bymac(vf_netdev->perm_addr);
+ if (!ndev)
+ return NOTIFY_DONE;
+
+ vi = netdev_priv(ndev);
+ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_MASTER))
+ return NOTIFY_DONE;
+
+ if (rtnl_dereference(vi->vf_netdev))
+ return NOTIFY_DONE;
+
+ if (virtnet_vf_join(vf_netdev, ndev) != 0)
+ return NOTIFY_DONE;
+
+ netdev_info(ndev, "VF registering %s\n", vf_netdev->name);
+
+ dev_hold(vf_netdev);
+ rcu_assign_pointer(vi->vf_netdev, vf_netdev);
+
+ return NOTIFY_OK;
+}
+
+static int virtnet_unregister_vf(struct net_device *vf_netdev)
+{
+ struct net_device *ndev;
+ struct virtnet_info *vi;
+
+ ndev = get_virtio_byref(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
+
+ vi = netdev_priv(ndev);
+ if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_MASTER))
+ return NOTIFY_DONE;
+
+ netdev_info(ndev, "VF unregistering %s\n", vf_netdev->name);
+
+ netdev_rx_handler_unregister(vf_netdev);
+ netdev_upper_dev_unlink(vf_netdev, ndev);
+ RCU_INIT_POINTER(vi->vf_netdev, NULL);
+ dev_put(vf_netdev);
+
+ return NOTIFY_OK;
+}
+
static void virtnet_remove(struct virtio_device *vdev)
{
struct virtnet_info *vi = vdev->priv;
+ struct net_device *vf_netdev;
virtnet_cpu_notif_remove(vi);
/* Make sure no work handler is accessing the device. */
flush_work(&vi->config_work);
+ rtnl_lock();
+ vf_netdev = rtnl_dereference(vi->vf_netdev);
+ if (vf_netdev)
+ virtnet_unregister_vf(vf_netdev);
+ rtnl_unlock();
+
unregister_netdev(vi->dev);
remove_vq_common(vi);
+ free_percpu(vi->vf_stats);
free_percpu(vi->stats);
free_netdev(vi->dev);
}
@@ -2827,6 +3089,42 @@ static struct virtio_driver virtio_net_driver = {
#endif
};
+static int virtio_netdev_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_netdev)
+ 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 VF */
+ if (is_vlan_dev(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid Bonding master dev with same MAC registering as VF */
+ if ((event_dev->priv_flags & IFF_BONDING) &&
+ (event_dev->flags & IFF_MASTER))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return virtnet_register_vf(event_dev);
+ case NETDEV_UNREGISTER:
+ return virtnet_unregister_vf(event_dev);
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block virtio_netdev_notifier = {
+ .notifier_call = virtio_netdev_event,
+};
+
static __init int virtio_net_driver_init(void)
{
int ret;
@@ -2845,6 +3143,8 @@ static __init int virtio_net_driver_init(void)
ret = register_virtio_driver(&virtio_net_driver);
if (ret)
goto err_virtio;
+
+ register_netdevice_notifier(&virtio_netdev_notifier);
return 0;
err_virtio:
cpuhp_remove_multi_state(CPUHP_VIRT_NET_DEAD);
@@ -2857,6 +3157,7 @@ module_init(virtio_net_driver_init);
static __exit void virtio_net_driver_exit(void)
{
+ unregister_netdevice_notifier(&virtio_netdev_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
* Re: [PATCH net-next 0/2] Enable virtio to act as a master for a passthru device
From: Jakub Kicinski @ 2018-01-03 2:16 UTC (permalink / raw)
To: jesse.brandeburg
Cc: Alexander Duyck, virtio-dev, mst, Sridhar Samudrala,
virtualization, netdev
In-Reply-To: <1514939738-22423-1-git-send-email-sridhar.samudrala@intel.com>
On Tue, 2 Jan 2018 16:35:36 -0800, Sridhar Samudrala wrote:
> This patch series enables virtio 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 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.
>
> It is based on netvsc implementation and it may be possible to make this code
> generic and move it to a common location that can be shared by netvsc and virtio.
>
> This patch series is based on the discussion initiated by Jesse on this thread.
> https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
How does the notion of a device which is both a bond and a leg of a
bond fit with Alex's recent discussions about feature propagation?
Which propagation rules will apply to VirtIO master? Meaning of the
flags on a software upper device may be different. Why muddy the
architecture like this and not introduce a synthetic bond device?
^ permalink raw reply
* Re: [PATCH v20 3/7 RESEND] xbitmap: add more operations
From: Wei Wang @ 2018-01-03 8:56 UTC (permalink / raw)
To: Matthew Wilcox
Cc: virtio-dev, kvm, mst, qemu-devel, penguin-kernel, mawilcox,
linux-kernel, virtualization, linux-mm, akpm, mhocko
In-Reply-To: <20180102140906.GC8222@bombadil.infradead.org>
On 01/02/2018 10:09 PM, Matthew Wilcox wrote:
> On Fri, Dec 22, 2017 at 04:49:11PM +0800, Wei Wang wrote:
>> Thanks for the improvement. I also found a small bug in xb_zero. With the
>> following changes, it has passed the current test cases and tested with the
>> virtio-balloon usage without any issue.
> Thanks; I applied the change. Can you supply a test-case for testing
> xb_zero please?
>
Sure. Please check below the test cases. Do you plan to send out the new
version of xbitmap yourself? If so, I will wait for that to send out the
virtio-balloon patches.
static void xbitmap_check_zero_bits(void)
{
assert(xb_empty(&xb1));
/* Zero an empty xbitmap should work though no real work to do */
xb_zero(&xb1, 0, ULONG_MAX);
assert(xb_empty(&xb1));
xb_preload(GFP_KERNEL);
assert(xb_set_bit(&xb1, 0) == 0);
xb_preload_end();
/* Overflow test */
xb_zero(&xb1, ULONG_MAX - 10, ULONG_MAX);
assert(xb_test_bit(&xb1, 0));
xb_preload(GFP_KERNEL);
assert(xb_set_bit(&xb1, ULONG_MAX) == 0);
xb_preload_end();
xb_zero(&xb1, 0, ULONG_MAX);
assert(xb_empty(&xb1));
}
/*
* In the following tests, preload is called once when all the bits to set
* locate in the same ida bitmap. Otherwise, it is recommended to call
* preload for each xb_set_bit.
*/
static void xbitmap_check_bit_range(void)
{
unsigned long nbit = 0;
/* Regular test1: node = NULL */
xb_preload(GFP_KERNEL);
xb_set_bit(&xb1, 700);
xb_preload_end();
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == true);
assert(nbit == 700);
nbit++;
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == false);
assert(nbit == 701);
xb_zero(&xb1, 0, 1023);
/*
* Regular test2
* set bit 2000, 2001, 2040
* Next 1 in [0, 2048] --> 2000
* Next 1 in [2000, 2002] --> 2000
* Next 1 in [2002, 2040] --> 2040
* Next 1 in [2002, 2039] --> none
* Next 0 in [2000, 2048] --> 2002
* Next 0 in [2048, 2060] --> 2048
*/
xb_preload(GFP_KERNEL);
assert(!xb_set_bit(&xb1, 2000));
assert(!xb_set_bit(&xb1, 2001));
assert(!xb_set_bit(&xb1, 2040));
nbit = 0;
assert(xb_find_set(&xb1, 2048, &nbit) == true);
assert(nbit == 2000);
assert(xb_find_set(&xb1, 2002, &nbit) == true);
assert(nbit == 2000);
nbit = 2002;
assert(xb_find_set(&xb1, 2040, &nbit) == true);
assert(nbit == 2040);
nbit = 2002;
assert(xb_find_set(&xb1, 2039, &nbit) == false);
assert(nbit == 2002);
nbit = 2000;
assert(xb_find_zero(&xb1, 2048, &nbit) == true);
assert(nbit == 2002);
nbit = 2048;
assert(xb_find_zero(&xb1, 2060, &nbit) == true);
assert(nbit == 2048);
xb_zero(&xb1, 0, 2048);
nbit = 0;
assert(xb_find_set(&xb1, 2048, &nbit) == false);
assert(nbit == 0);
xb_preload_end();
/*
* Overflow tests:
* Set bit 1 and ULONG_MAX - 4
* Next 1 in [0, ULONG_MAX] --> 1
* Next 1 in [1, ULONG_MAX] --> 1
* Next 1 in [2, ULONG_MAX] --> ULONG_MAX - 4
* Next 1 in [ULONG_MAX - 3, 2] --> none
* Next 0 in [ULONG_MAX - 4, ULONG_MAX] --> ULONG_MAX - 3
* Zero [ULONG_MAX - 4, ULONG_MAX]
* Next 1 in [ULONG_MAX - 10, ULONG_MAX] --> none
* Next 1 in [ULONG_MAX - 1, 2] --> none
* Zero [0, 1]
* Next 1 in [0, 2] --> none
*/
xb_preload(GFP_KERNEL);
assert(!xb_set_bit(&xb1, 1));
xb_preload_end();
xb_preload(GFP_KERNEL);
assert(!xb_set_bit(&xb1, ULONG_MAX - 4));
nbit = 0;
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == true);
assert(nbit == 1);
nbit = 1;
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == true);
assert(nbit == 1);
nbit = 2;
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == true);
assert(nbit == ULONG_MAX - 4);
nbit++;
assert(xb_find_set(&xb1, 2, &nbit) == false);
assert(nbit == ULONG_MAX - 3);
nbit--;
assert(xb_find_zero(&xb1, ULONG_MAX, &nbit) == true);
assert(nbit == ULONG_MAX - 3);
xb_zero(&xb1, ULONG_MAX - 4, ULONG_MAX);
nbit = ULONG_MAX - 10;
assert(xb_find_set(&xb1, ULONG_MAX, &nbit) == false);
assert(nbit == ULONG_MAX - 10);
nbit = ULONG_MAX - 1;
assert(xb_find_set(&xb1, 2, &nbit) == false);
xb_zero(&xb1, 0, 1);
nbit = 0;
assert(xb_find_set(&xb1, 2, &nbit) == false);
assert(nbit == 0);
xb_preload_end();
assert(xb_empty(&xb1));
}
Best,
Wei
^ permalink raw reply
* Re: [PATCH v20 4/7] virtio-balloon: VIRTIO_BALLOON_F_SG
From: Wei Wang @ 2018-01-03 9:00 UTC (permalink / raw)
To: Tetsuo Handa, willy
Cc: aarcange, virtio-dev, riel, quan.xu0, kvm, mst, qemu-devel,
amit.shah, liliang.opensource, mawilcox, linux-kernel,
virtualization, linux-mm, yang.zhang.wz, nilal, cornelia.huck,
pbonzini, akpm, mhocko, mgorman
In-Reply-To: <201801031129.JFC18298.FJMHtOFLVSQOFO@I-love.SAKURA.ne.jp>
On 01/03/2018 10:29 AM, Tetsuo Handa wrote:
> Matthew Wilcox wrote:
>> The radix tree convention is objectively awful, which is why I'm working
>> to change it. Specifying the GFP flags at radix tree initialisation time
>> rather than allocation time leads to all kinds of confusion. The preload
>> API is a pretty awful workaround, and it will go away once the XArray
>> is working correctly. That said, there's no alternative to it without
>> making XBitmap depend on XArray, and I don't want to hold you up there.
>> So there's an xb_preload for the moment.
> I'm ready to propose cvbmp shown below as an alternative to xbitmap (but
> specialized for virtio-balloon case). Wei, can you do some benchmarking
> between xbitmap and cvbmp?
> ----------------------------------------
> cvbmp: clustered values bitmap
I don't think we need to replace xbitmap, at least at this stage. The
new implementation doesn't look simpler at all, and virtio-balloon has
worked well with xbitmap.
I would suggest you to send out the new implementation for discussion
after this series ends, and justify with better performance results if
you could get.
Best,
Wei
^ permalink raw reply
* Re: [PATCH] vhost: remove unused lock check flag in vhost_dev_cleanup()
From: Jason Wang @ 2018-01-03 9:14 UTC (permalink / raw)
To: 夷则(Caspar), Michael S. Tsirkin, Stefan Hajnoczi
Cc: linux-kernel, kvm, virtualization
In-Reply-To: <57a32eb1fd105b2aacc96b7caae0d8336c010fe0.1514130393.git.jinli.zjl@alibaba-inc.com>
On 2017年12月25日 00:08, 夷则(Caspar) wrote:
> In commit ea5d404655ba ("vhost: fix release path lockdep checks"),
> Michael added a flag to check whether we should hold a lock in
> vhost_dev_cleanup(), however, in commit 47283bef7ed3 ("vhost: move
> memory pointer to VQs"), RCU operations have been replaced by
> mutex, we can remove the no-longer-used `locked' parameter now.
>
> Signed-off-by: Caspar Zhang <jinli.zjl@alibaba-inc.com>
> ---
> drivers/vhost/net.c | 2 +-
> drivers/vhost/scsi.c | 2 +-
> drivers/vhost/test.c | 2 +-
> drivers/vhost/vhost.c | 5 ++---
> drivers/vhost/vhost.h | 2 +-
> drivers/vhost/vsock.c | 2 +-
> 6 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index c7bdeb655646..a354d8d731e3 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -996,7 +996,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
> vhost_net_stop(n, &tx_sock, &rx_sock);
> vhost_net_flush(n);
> vhost_dev_stop(&n->dev);
> - vhost_dev_cleanup(&n->dev, false);
> + vhost_dev_cleanup(&n->dev);
> vhost_net_vq_reset(n);
> if (tx_sock)
> sockfd_put(tx_sock);
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 71517b3c5558..797d08916553 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -1420,7 +1420,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
> mutex_unlock(&vs->dev.mutex);
> vhost_scsi_clear_endpoint(vs, &t);
> vhost_dev_stop(&vs->dev);
> - vhost_dev_cleanup(&vs->dev, false);
> + vhost_dev_cleanup(&vs->dev);
> /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */
> vhost_scsi_flush(vs);
> kfree(vs->dev.vqs);
> diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> index 3cc98c07dcd3..906b8f0f19f7 100644
> --- a/drivers/vhost/test.c
> +++ b/drivers/vhost/test.c
> @@ -157,7 +157,7 @@ static int vhost_test_release(struct inode *inode, struct file *f)
>
> vhost_test_stop(n, &private);
> vhost_test_flush(n);
> - vhost_dev_cleanup(&n->dev, false);
> + vhost_dev_cleanup(&n->dev);
> /* We do an extra flush before freeing memory,
> * since jobs can re-queue themselves. */
> vhost_test_flush(n);
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 33ac2b186b85..014675c3d569 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -544,7 +544,7 @@ void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_umem *umem)
> {
> int i;
>
> - vhost_dev_cleanup(dev, true);
> + vhost_dev_cleanup(dev);
>
> /* Restore memory to default empty mapping. */
> INIT_LIST_HEAD(&umem->umem_list);
> @@ -611,8 +611,7 @@ static void vhost_clear_msg(struct vhost_dev *dev)
> spin_unlock(&dev->iotlb_lock);
> }
>
> -/* Caller should have device mutex if and only if locked is set */
> -void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
> +void vhost_dev_cleanup(struct vhost_dev *dev)
> {
> int i;
>
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 79c6e7a60a5e..ff4d918e3e0a 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -181,7 +181,7 @@ bool vhost_dev_has_owner(struct vhost_dev *dev);
> long vhost_dev_check_owner(struct vhost_dev *);
> struct vhost_umem *vhost_dev_reset_owner_prepare(void);
> void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *);
> -void vhost_dev_cleanup(struct vhost_dev *, bool locked);
> +void vhost_dev_cleanup(struct vhost_dev *);
> void vhost_dev_stop(struct vhost_dev *);
> long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
> long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp);
> diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
> index 5a5e981bd8e4..0d14e2ff19f1 100644
> --- a/drivers/vhost/vsock.c
> +++ b/drivers/vhost/vsock.c
> @@ -599,7 +599,7 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
> }
> spin_unlock_bh(&vsock->send_pkt_list_lock);
>
> - vhost_dev_cleanup(&vsock->dev, false);
> + vhost_dev_cleanup(&vsock->dev);
> kfree(vsock->dev.vqs);
> vhost_vsock_free(vsock);
> return 0;
Acked-by: Jason Wang <jasowang@redhat.com>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* [PATCH, v2] virtio: make VIRTIO a menuconfig to ease disabling it
From: Vincent Legoll @ 2018-01-03 9:49 UTC (permalink / raw)
To: mst, jasowang, virtualization, linux-kernel; +Cc: Vincent Legoll
In-Reply-To: <871sj7dgvr.fsf@concordia.ellerman.id.au>
No need to get into the submenu to disable all VIRTIO-related
config entries.
This makes it easier to disable all VIRTIO config options
without entering the submenu. It will also enable one
to see that en/dis-abled state from the outside menu.
This is only intended to change menuconfig UI, not change
the config dependencies.
v2: Added "default y" to avoid breaking existing configs
Signed-off-by: Vincent Legoll <vincent.legoll@gmail.com>
^ permalink raw reply
* [PATCH] [PATCH] virtio: make VIRTIO a menuconfig to ease disabling it all
From: Vincent Legoll @ 2018-01-03 9:49 UTC (permalink / raw)
To: mst, jasowang, virtualization, linux-kernel; +Cc: Vincent Legoll
In-Reply-To: <20180103094918.6106-1-vincent.legoll@gmail.com>
No need to get into the submenu to disable all VIRTIO-related
config entries.
This makes it easier to disable all VIRTIO config options
without entering the submenu. It will also enable one
to see that en/dis-abled state from the outside menu.
This is only intended to change menuconfig UI, not change
the config dependencies.
v2: add "default y" to avoid breaking existing configs
Signed-off-by: Vincent Legoll <vincent.legoll@gmail.com>
---
drivers/virtio/Kconfig | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index cff773f15b7e..290a1875e1d3 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -5,7 +5,11 @@ config VIRTIO
bus, such as CONFIG_VIRTIO_PCI, CONFIG_VIRTIO_MMIO, CONFIG_RPMSG
or CONFIG_S390_GUEST.
-menu "Virtio drivers"
+menuconfig VIRTIO_MENU
+ bool "Virtio drivers"
+ default y
+
+if VIRTIO_MENU
config VIRTIO_PCI
tristate "PCI driver for virtio devices"
@@ -79,4 +83,4 @@ config VIRTIO_MMIO_CMDLINE_DEVICES
If unsure, say 'N'.
-endmenu
+endif # VIRTIO_MENU
--
2.11.0
^ permalink raw reply related
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