summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
authorChirantan Ekbote <chirantan@chromium.org>2019-06-11 21:50:46 +0900
committerCommit Bot <commit-bot@chromium.org>2019-06-24 03:29:42 +0000
commitdd11d434730a5dea56106d0533bf42c6b7206ed0 (patch)
treeed43e4d244f5ecda11d4efd0cb833341339fbd7b /devices
parentcc91fc825241a3ac5b00693e0be79c50a9528dab (diff)
downloadcrosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar.gz
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar.bz2
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar.lz
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar.xz
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.tar.zst
crosvm-dd11d434730a5dea56106d0533bf42c6b7206ed0.zip
gpu: Allow more than one resource bridge socket
Currently the wayland device accesses buffers allocated by the gpu
device via a dedicated socket connection.  Upcoming virtual devices like
vdec and camera will also need access to these buffers.  Modify the gpu
device so that it can process requests on multiple resource_bridge
sockets.

Each future device that needs access to gpu device buffers should create
a new resource bridge socket pair and add it to the list of sockets that
the gpu device monitors.

The actual interface between the devices is unchanged.

BUG=b:133381367
TEST=run glxgears in a crostini container with and without gpu enabled

Change-Id: I58693881945965071a53653bf4f86681725267d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1652876
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Chirantan Ekbote <chirantan@chromium.org>
Auto-Submit: Chirantan Ekbote <chirantan@chromium.org>
Diffstat (limited to 'devices')
-rw-r--r--devices/src/virtio/gpu/mod.rs42
1 files changed, 25 insertions, 17 deletions
diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs
index cc42ace..0031b73 100644
--- a/devices/src/virtio/gpu/mod.rs
+++ b/devices/src/virtio/gpu/mod.rs
@@ -8,7 +8,7 @@ mod protocol;
 use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::i64;
-use std::mem::size_of;
+use std::mem::{self, size_of};
 use std::os::unix::io::{AsRawFd, RawFd};
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -474,7 +474,7 @@ struct Worker {
     ctrl_evt: EventFd,
     cursor_queue: Queue,
     cursor_evt: EventFd,
-    resource_bridge: Option<ResourceResponseSocket>,
+    resource_bridges: Vec<ResourceResponseSocket>,
     kill_evt: EventFd,
     state: Frontend,
 }
@@ -492,9 +492,9 @@ impl Worker {
             CtrlQueue,
             CursorQueue,
             Display,
-            ResourceBridge,
             InterruptResample,
             Kill,
+            ResourceBridge { index: usize },
         }
 
         let poll_ctx: PollContext<Token> = match PollContext::new()
@@ -517,12 +517,14 @@ impl Worker {
             }
         };
 
-        if let Some(resource_bridge) = &self.resource_bridge {
-            if let Err(e) = poll_ctx.add(resource_bridge, Token::ResourceBridge) {
+        for (index, bridge) in self.resource_bridges.iter().enumerate() {
+            if let Err(e) = poll_ctx.add(bridge, Token::ResourceBridge { index }) {
                 error!("failed to add resource bridge to PollContext: {}", e);
             }
         }
 
+        // Declare this outside the loop so we don't keep allocating and freeing the vector.
+        let mut process_resource_bridge = Vec::with_capacity(self.resource_bridges.len());
         'poll: loop {
             // If there are outstanding fences, wake up early to poll them.
             let duration = if !self.state.fence_descriptors.is_empty() {
@@ -539,7 +541,11 @@ impl Worker {
                 }
             };
             let mut signal_used = false;
-            let mut process_resource_bridge = false;
+
+            // Clear the old values and re-initialize with false.
+            process_resource_bridge.clear();
+            process_resource_bridge.resize(self.resource_bridges.len(), false);
+
             for event in events.iter_readable() {
                 match event.token() {
                     Token::CtrlQueue => {
@@ -558,7 +564,7 @@ impl Worker {
                             let _ = self.exit_evt.write(1);
                         }
                     }
-                    Token::ResourceBridge => process_resource_bridge = true,
+                    Token::ResourceBridge { index } => process_resource_bridge[index] = true,
                     Token::InterruptResample => {
                         let _ = self.interrupt_resample_evt.read();
                         if self.interrupt_status.load(Ordering::SeqCst) != 0 {
@@ -587,9 +593,11 @@ impl Worker {
             // Process the entire control queue before the resource bridge in case a resource is
             // created or destroyed by the control queue. Processing the resource bridge first may
             // lead to a race condition.
-            if process_resource_bridge {
-                if let Some(resource_bridge) = &self.resource_bridge {
-                    self.state.process_resource_bridge(resource_bridge);
+            for (bridge, &should_process) in
+                self.resource_bridges.iter().zip(&process_resource_bridge)
+            {
+                if should_process {
+                    self.state.process_resource_bridge(bridge);
                 }
             }
 
@@ -604,7 +612,7 @@ pub struct Gpu {
     config_event: bool,
     exit_evt: EventFd,
     gpu_device_socket: Option<VmMemoryControlRequestSocket>,
-    resource_bridge: Option<ResourceResponseSocket>,
+    resource_bridges: Vec<ResourceResponseSocket>,
     kill_evt: Option<EventFd>,
     wayland_socket_path: PathBuf,
 }
@@ -613,14 +621,14 @@ impl Gpu {
     pub fn new<P: AsRef<Path>>(
         exit_evt: EventFd,
         gpu_device_socket: Option<VmMemoryControlRequestSocket>,
-        resource_bridge: Option<ResourceResponseSocket>,
+        resource_bridges: Vec<ResourceResponseSocket>,
         wayland_socket_path: P,
     ) -> Gpu {
         Gpu {
             config_event: false,
             exit_evt,
             gpu_device_socket,
-            resource_bridge,
+            resource_bridges,
             kill_evt: None,
             wayland_socket_path: wayland_socket_path.as_ref().to_path_buf(),
         }
@@ -664,8 +672,8 @@ impl VirtioDevice for Gpu {
         }
 
         keep_fds.push(self.exit_evt.as_raw_fd());
-        if let Some(resource_bridge) = &self.resource_bridge {
-            keep_fds.push(resource_bridge.as_raw_fd());
+        for bridge in &self.resource_bridges {
+            keep_fds.push(bridge.as_raw_fd());
         }
         keep_fds
     }
@@ -739,7 +747,7 @@ impl VirtioDevice for Gpu {
         };
         self.kill_evt = Some(self_kill_evt);
 
-        let resource_bridge = self.resource_bridge.take();
+        let resource_bridges = mem::replace(&mut self.resource_bridges, Vec::new());
 
         let ctrl_queue = queues.remove(0);
         let ctrl_evt = queue_evts.remove(0);
@@ -802,7 +810,7 @@ impl VirtioDevice for Gpu {
                             ctrl_evt,
                             cursor_queue,
                             cursor_evt,
-                            resource_bridge,
+                            resource_bridges,
                             kill_evt,
                             state: Frontend::new(Backend::new(
                                 device,