Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'vmwgfx-next-160520' of git://people.freedesktop.org/~thomash/linux into drm-next

Pull request of 2016-05-20

* tag 'vmwgfx-next-160520' of git://people.freedesktop.org/~thomash/linux:
drm/vmwgfx: Report vmwgfx version to vmware.log
drm/vmwgfx: Add VMWare host messaging capability
drm/vmwgfx: Kill some lockdep warnings

+653 -16
+1 -1
drivers/gpu/drm/vmwgfx/Makefile
··· 8 8 vmwgfx_fence.o vmwgfx_dmabuf.o vmwgfx_scrn.o vmwgfx_context.o \ 9 9 vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ 10 10 vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \ 11 - vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o 11 + vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o 12 12 13 13 obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
+19 -1
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
··· 1 1 /************************************************************************** 2 2 * 3 - * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA 3 + * Copyright © 2009-2016 VMware, Inc., Palo Alto, CA., USA 4 4 * All Rights Reserved. 5 5 * 6 6 * Permission is hereby granted, free of charge, to any person obtaining a ··· 43 43 44 44 #define VMW_MIN_INITIAL_WIDTH 800 45 45 #define VMW_MIN_INITIAL_HEIGHT 600 46 + 47 + #ifndef VMWGFX_GIT_VERSION 48 + #define VMWGFX_GIT_VERSION "Unknown" 49 + #endif 50 + 51 + #define VMWGFX_REPO "In Tree" 46 52 47 53 48 54 /** ··· 619 613 uint32_t svga_id; 620 614 enum vmw_res_type i; 621 615 bool refuse_dma = false; 616 + char host_log[100] = {0}; 622 617 623 618 dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); 624 619 if (unlikely(dev_priv == NULL)) { ··· 635 628 mutex_init(&dev_priv->cmdbuf_mutex); 636 629 mutex_init(&dev_priv->release_mutex); 637 630 mutex_init(&dev_priv->binding_mutex); 631 + mutex_init(&dev_priv->global_kms_state_mutex); 638 632 rwlock_init(&dev_priv->resource_lock); 639 633 ttm_lock_init(&dev_priv->reservation_sem); 640 634 spin_lock_init(&dev_priv->hw_lock); ··· 880 872 goto out_no_fifo; 881 873 882 874 DRM_INFO("DX: %s\n", dev_priv->has_dx ? "yes." : "no."); 875 + 876 + snprintf(host_log, sizeof(host_log), "vmwgfx: %s-%s", 877 + VMWGFX_REPO, VMWGFX_GIT_VERSION); 878 + vmw_host_log(host_log); 879 + 880 + memset(host_log, 0, sizeof(host_log)); 881 + snprintf(host_log, sizeof(host_log), "vmwgfx: Module Version: %d.%d.%d", 882 + VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR, 883 + VMWGFX_DRIVER_PATCHLEVEL); 884 + vmw_host_log(host_log); 883 885 884 886 if (dev_priv->enable_fb) { 885 887 vmw_fifo_resource_inc(dev_priv);
+7
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
··· 412 412 struct drm_property *implicit_placement_property; 413 413 unsigned num_implicit; 414 414 struct vmw_framebuffer *implicit_fb; 415 + struct mutex global_kms_state_mutex; 415 416 416 417 /* 417 418 * Context and surface management. ··· 1235 1234 { 1236 1235 WRITE_ONCE(*addr, value); 1237 1236 } 1237 + 1238 + /** 1239 + * Add vmw_msg module function 1240 + */ 1241 + extern int vmw_host_log(const char *log); 1242 + 1238 1243 #endif
+13 -14
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 2143 2143 void vmw_kms_del_active(struct vmw_private *dev_priv, 2144 2144 struct vmw_display_unit *du) 2145 2145 { 2146 - lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); 2147 - 2146 + mutex_lock(&dev_priv->global_kms_state_mutex); 2148 2147 if (du->active_implicit) { 2149 2148 if (--(dev_priv->num_implicit) == 0) 2150 2149 dev_priv->implicit_fb = NULL; 2151 2150 du->active_implicit = false; 2152 2151 } 2152 + mutex_unlock(&dev_priv->global_kms_state_mutex); 2153 2153 } 2154 2154 2155 2155 /** ··· 2165 2165 struct vmw_display_unit *du, 2166 2166 struct vmw_framebuffer *vfb) 2167 2167 { 2168 - lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); 2169 - 2168 + mutex_lock(&dev_priv->global_kms_state_mutex); 2170 2169 WARN_ON_ONCE(!dev_priv->num_implicit && dev_priv->implicit_fb); 2171 2170 2172 2171 if (!du->active_implicit && du->is_implicit) { ··· 2173 2174 du->active_implicit = true; 2174 2175 dev_priv->num_implicit++; 2175 2176 } 2177 + mutex_unlock(&dev_priv->global_kms_state_mutex); 2176 2178 } 2177 2179 2178 2180 /** ··· 2190 2190 struct drm_crtc *crtc) 2191 2191 { 2192 2192 struct vmw_display_unit *du = vmw_crtc_to_du(crtc); 2193 + bool ret; 2193 2194 2194 - lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); 2195 + mutex_lock(&dev_priv->global_kms_state_mutex); 2196 + ret = !du->is_implicit || dev_priv->num_implicit == 1; 2197 + mutex_unlock(&dev_priv->global_kms_state_mutex); 2195 2198 2196 - if (!du->is_implicit) 2197 - return true; 2198 - 2199 - if (dev_priv->num_implicit != 1) 2200 - return false; 2201 - 2202 - return true; 2199 + return ret; 2203 2200 } 2204 2201 2205 2202 /** ··· 2211 2214 struct vmw_display_unit *du = vmw_crtc_to_du(crtc); 2212 2215 struct vmw_framebuffer *vfb; 2213 2216 2214 - lockdep_assert_held_once(&dev_priv->dev->mode_config.mutex); 2217 + mutex_lock(&dev_priv->global_kms_state_mutex); 2215 2218 2216 2219 if (!du->is_implicit) 2217 - return; 2220 + goto out_unlock; 2218 2221 2219 2222 vfb = vmw_framebuffer_to_vfb(crtc->primary->fb); 2220 2223 WARN_ON_ONCE(dev_priv->num_implicit != 1 && 2221 2224 dev_priv->implicit_fb != vfb); 2222 2225 2223 2226 dev_priv->implicit_fb = vfb; 2227 + out_unlock: 2228 + mutex_unlock(&dev_priv->global_kms_state_mutex); 2224 2229 } 2225 2230 2226 2231 /**
+416
drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
··· 1 + /* 2 + * Copyright © 2016 VMware, Inc., Palo Alto, CA., USA 3 + * All Rights Reserved. 4 + * 5 + * Permission is hereby granted, free of charge, to any person obtaining a 6 + * copy of this software and associated documentation files (the 7 + * "Software"), to deal in the Software without restriction, including 8 + * without limitation the rights to use, copy, modify, merge, publish, 9 + * distribute, sub license, and/or sell copies of the Software, and to 10 + * permit persons to whom the Software is furnished to do so, subject to 11 + * the following conditions: 12 + * 13 + * The above copyright notice and this permission notice (including the 14 + * next paragraph) shall be included in all copies or substantial portions 15 + * of the Software. 16 + * 17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 21 + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 23 + * USE OR OTHER DEALINGS IN THE SOFTWARE. 24 + * 25 + */ 26 + 27 + 28 + #include <linux/slab.h> 29 + #include <linux/module.h> 30 + #include <linux/kernel.h> 31 + #include <asm/hypervisor.h> 32 + #include "drmP.h" 33 + #include "vmwgfx_msg.h" 34 + 35 + 36 + #define MESSAGE_STATUS_SUCCESS 0x0001 37 + #define MESSAGE_STATUS_DORECV 0x0002 38 + #define MESSAGE_STATUS_CPT 0x0010 39 + #define MESSAGE_STATUS_HB 0x0080 40 + 41 + #define RPCI_PROTOCOL_NUM 0x49435052 42 + #define GUESTMSG_FLAG_COOKIE 0x80000000 43 + 44 + #define RETRIES 3 45 + 46 + #define VMW_HYPERVISOR_MAGIC 0x564D5868 47 + #define VMW_HYPERVISOR_PORT 0x5658 48 + #define VMW_HYPERVISOR_HB_PORT 0x5659 49 + 50 + #define VMW_PORT_CMD_MSG 30 51 + #define VMW_PORT_CMD_HB_MSG 0 52 + #define VMW_PORT_CMD_OPEN_CHANNEL (MSG_TYPE_OPEN << 16 | VMW_PORT_CMD_MSG) 53 + #define VMW_PORT_CMD_CLOSE_CHANNEL (MSG_TYPE_CLOSE << 16 | VMW_PORT_CMD_MSG) 54 + #define VMW_PORT_CMD_SENDSIZE (MSG_TYPE_SENDSIZE << 16 | VMW_PORT_CMD_MSG) 55 + #define VMW_PORT_CMD_RECVSIZE (MSG_TYPE_RECVSIZE << 16 | VMW_PORT_CMD_MSG) 56 + #define VMW_PORT_CMD_RECVSTATUS (MSG_TYPE_RECVSTATUS << 16 | VMW_PORT_CMD_MSG) 57 + 58 + #define HIGH_WORD(X) ((X & 0xFFFF0000) >> 16) 59 + 60 + static u32 vmw_msg_enabled = 1; 61 + 62 + enum rpc_msg_type { 63 + MSG_TYPE_OPEN, 64 + MSG_TYPE_SENDSIZE, 65 + MSG_TYPE_SENDPAYLOAD, 66 + MSG_TYPE_RECVSIZE, 67 + MSG_TYPE_RECVPAYLOAD, 68 + MSG_TYPE_RECVSTATUS, 69 + MSG_TYPE_CLOSE, 70 + }; 71 + 72 + struct rpc_channel { 73 + u16 channel_id; 74 + u32 cookie_high; 75 + u32 cookie_low; 76 + }; 77 + 78 + 79 + 80 + /** 81 + * vmw_open_channel 82 + * 83 + * @channel: RPC channel 84 + * @protocol: 85 + * 86 + * Returns: 0 on success 87 + */ 88 + static int vmw_open_channel(struct rpc_channel *channel, unsigned int protocol) 89 + { 90 + unsigned long eax, ebx, ecx, edx, si = 0, di = 0; 91 + 92 + VMW_PORT(VMW_PORT_CMD_OPEN_CHANNEL, 93 + (protocol | GUESTMSG_FLAG_COOKIE), si, di, 94 + VMW_HYPERVISOR_PORT, 95 + VMW_HYPERVISOR_MAGIC, 96 + eax, ebx, ecx, edx, si, di); 97 + 98 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) 99 + return -EINVAL; 100 + 101 + channel->channel_id = HIGH_WORD(edx); 102 + channel->cookie_high = si; 103 + channel->cookie_low = di; 104 + 105 + return 0; 106 + } 107 + 108 + 109 + 110 + /** 111 + * vmw_close_channel 112 + * 113 + * @channel: RPC channel 114 + * 115 + * Returns: 0 on success 116 + */ 117 + static int vmw_close_channel(struct rpc_channel *channel) 118 + { 119 + unsigned long eax, ebx, ecx, edx, si, di; 120 + 121 + /* Set up additional parameters */ 122 + si = channel->cookie_high; 123 + di = channel->cookie_low; 124 + 125 + VMW_PORT(VMW_PORT_CMD_CLOSE_CHANNEL, 126 + 0, si, di, 127 + (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), 128 + VMW_HYPERVISOR_MAGIC, 129 + eax, ebx, ecx, edx, si, di); 130 + 131 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) 132 + return -EINVAL; 133 + 134 + return 0; 135 + } 136 + 137 + 138 + 139 + /** 140 + * vmw_send_msg: Sends a message to the host 141 + * 142 + * @channel: RPC channel 143 + * @logmsg: NULL terminated string 144 + * 145 + * Returns: 0 on success 146 + */ 147 + static int vmw_send_msg(struct rpc_channel *channel, const char *msg) 148 + { 149 + unsigned long eax, ebx, ecx, edx, si, di, bp; 150 + size_t msg_len = strlen(msg); 151 + int retries = 0; 152 + 153 + 154 + while (retries < RETRIES) { 155 + retries++; 156 + 157 + /* Set up additional parameters */ 158 + si = channel->cookie_high; 159 + di = channel->cookie_low; 160 + 161 + VMW_PORT(VMW_PORT_CMD_SENDSIZE, 162 + msg_len, si, di, 163 + VMW_HYPERVISOR_PORT | (channel->channel_id << 16), 164 + VMW_HYPERVISOR_MAGIC, 165 + eax, ebx, ecx, edx, si, di); 166 + 167 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0 || 168 + (HIGH_WORD(ecx) & MESSAGE_STATUS_HB) == 0) { 169 + /* Expected success + high-bandwidth. Give up. */ 170 + return -EINVAL; 171 + } 172 + 173 + /* Send msg */ 174 + si = (uintptr_t) msg; 175 + di = channel->cookie_low; 176 + bp = channel->cookie_high; 177 + 178 + VMW_PORT_HB_OUT( 179 + (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, 180 + msg_len, si, di, 181 + VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), 182 + VMW_HYPERVISOR_MAGIC, bp, 183 + eax, ebx, ecx, edx, si, di); 184 + 185 + if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) != 0) { 186 + return 0; 187 + } else if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) { 188 + /* A checkpoint occurred. Retry. */ 189 + continue; 190 + } else { 191 + break; 192 + } 193 + } 194 + 195 + return -EINVAL; 196 + } 197 + 198 + 199 + 200 + /** 201 + * vmw_recv_msg: Receives a message from the host 202 + * 203 + * Note: It is the caller's responsibility to call kfree() on msg. 204 + * 205 + * @channel: channel opened by vmw_open_channel 206 + * @msg: [OUT] message received from the host 207 + * @msg_len: message length 208 + */ 209 + static int vmw_recv_msg(struct rpc_channel *channel, void **msg, 210 + size_t *msg_len) 211 + { 212 + unsigned long eax, ebx, ecx, edx, si, di, bp; 213 + char *reply; 214 + size_t reply_len; 215 + int retries = 0; 216 + 217 + 218 + *msg_len = 0; 219 + *msg = NULL; 220 + 221 + while (retries < RETRIES) { 222 + retries++; 223 + 224 + /* Set up additional parameters */ 225 + si = channel->cookie_high; 226 + di = channel->cookie_low; 227 + 228 + VMW_PORT(VMW_PORT_CMD_RECVSIZE, 229 + 0, si, di, 230 + (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), 231 + VMW_HYPERVISOR_MAGIC, 232 + eax, ebx, ecx, edx, si, di); 233 + 234 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0 || 235 + (HIGH_WORD(ecx) & MESSAGE_STATUS_HB) == 0) { 236 + DRM_ERROR("Failed to get reply size\n"); 237 + return -EINVAL; 238 + } 239 + 240 + /* No reply available. This is okay. */ 241 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_DORECV) == 0) 242 + return 0; 243 + 244 + reply_len = ebx; 245 + reply = kzalloc(reply_len + 1, GFP_KERNEL); 246 + if (reply == NULL) { 247 + DRM_ERROR("Cannot allocate memory for reply\n"); 248 + return -ENOMEM; 249 + } 250 + 251 + 252 + /* Receive buffer */ 253 + si = channel->cookie_high; 254 + di = (uintptr_t) reply; 255 + bp = channel->cookie_low; 256 + 257 + VMW_PORT_HB_IN( 258 + (MESSAGE_STATUS_SUCCESS << 16) | VMW_PORT_CMD_HB_MSG, 259 + reply_len, si, di, 260 + VMW_HYPERVISOR_HB_PORT | (channel->channel_id << 16), 261 + VMW_HYPERVISOR_MAGIC, bp, 262 + eax, ebx, ecx, edx, si, di); 263 + 264 + if ((HIGH_WORD(ebx) & MESSAGE_STATUS_SUCCESS) == 0) { 265 + kfree(reply); 266 + 267 + if ((HIGH_WORD(ebx) & MESSAGE_STATUS_CPT) != 0) { 268 + /* A checkpoint occurred. Retry. */ 269 + continue; 270 + } 271 + 272 + return -EINVAL; 273 + } 274 + 275 + reply[reply_len] = '\0'; 276 + 277 + 278 + /* Ack buffer */ 279 + si = channel->cookie_high; 280 + di = channel->cookie_low; 281 + 282 + VMW_PORT(VMW_PORT_CMD_RECVSTATUS, 283 + MESSAGE_STATUS_SUCCESS, si, di, 284 + (VMW_HYPERVISOR_PORT | (channel->channel_id << 16)), 285 + VMW_HYPERVISOR_MAGIC, 286 + eax, ebx, ecx, edx, si, di); 287 + 288 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_SUCCESS) == 0) { 289 + kfree(reply); 290 + 291 + if ((HIGH_WORD(ecx) & MESSAGE_STATUS_CPT) != 0) { 292 + /* A checkpoint occurred. Retry. */ 293 + continue; 294 + } 295 + 296 + return -EINVAL; 297 + } 298 + 299 + break; 300 + } 301 + 302 + *msg_len = reply_len; 303 + *msg = reply; 304 + 305 + return 0; 306 + } 307 + 308 + 309 + /** 310 + * vmw_host_get_guestinfo: Gets a GuestInfo parameter 311 + * 312 + * Gets the value of a GuestInfo.* parameter. The value returned will be in 313 + * a string, and it is up to the caller to post-process. 314 + * 315 + * @guest_info_param: Parameter to get, e.g. GuestInfo.svga.gl3 316 + * @buffer: if NULL, *reply_len will contain reply size. 317 + * @length: size of the reply_buf. Set to size of reply upon return 318 + * 319 + * Returns: 0 on success 320 + */ 321 + int vmw_host_get_guestinfo(const char *guest_info_param, 322 + char *buffer, size_t *length) 323 + { 324 + struct rpc_channel channel; 325 + char *msg, *reply = NULL; 326 + size_t msg_len, reply_len = 0; 327 + int ret = 0; 328 + 329 + 330 + if (!vmw_msg_enabled) 331 + return -ENODEV; 332 + 333 + if (!guest_info_param || !length) 334 + return -EINVAL; 335 + 336 + msg_len = strlen(guest_info_param) + strlen("info-get ") + 1; 337 + msg = kzalloc(msg_len, GFP_KERNEL); 338 + if (msg == NULL) { 339 + DRM_ERROR("Cannot allocate memory to get %s", guest_info_param); 340 + return -ENOMEM; 341 + } 342 + 343 + sprintf(msg, "info-get %s", guest_info_param); 344 + 345 + if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM) || 346 + vmw_send_msg(&channel, msg) || 347 + vmw_recv_msg(&channel, (void *) &reply, &reply_len) || 348 + vmw_close_channel(&channel)) { 349 + DRM_ERROR("Failed to get %s", guest_info_param); 350 + 351 + ret = -EINVAL; 352 + } 353 + 354 + if (buffer && reply && reply_len > 0) { 355 + /* Remove reply code, which are the first 2 characters of 356 + * the reply 357 + */ 358 + reply_len = max(reply_len - 2, (size_t) 0); 359 + reply_len = min(reply_len, *length); 360 + 361 + if (reply_len > 0) 362 + memcpy(buffer, reply + 2, reply_len); 363 + } 364 + 365 + *length = reply_len; 366 + 367 + kfree(reply); 368 + kfree(msg); 369 + 370 + return ret; 371 + } 372 + 373 + 374 + 375 + /** 376 + * vmw_host_log: Sends a log message to the host 377 + * 378 + * @log: NULL terminated string 379 + * 380 + * Returns: 0 on success 381 + */ 382 + int vmw_host_log(const char *log) 383 + { 384 + struct rpc_channel channel; 385 + char *msg; 386 + int msg_len; 387 + int ret = 0; 388 + 389 + 390 + if (!vmw_msg_enabled) 391 + return -ENODEV; 392 + 393 + if (!log) 394 + return ret; 395 + 396 + msg_len = strlen(log) + strlen("log ") + 1; 397 + msg = kzalloc(msg_len, GFP_KERNEL); 398 + if (msg == NULL) { 399 + DRM_ERROR("Cannot allocate memory for log message\n"); 400 + return -ENOMEM; 401 + } 402 + 403 + sprintf(msg, "log %s", log); 404 + 405 + if (vmw_open_channel(&channel, RPCI_PROTOCOL_NUM) || 406 + vmw_send_msg(&channel, msg) || 407 + vmw_close_channel(&channel)) { 408 + DRM_ERROR("Failed to send log\n"); 409 + 410 + ret = -EINVAL; 411 + } 412 + 413 + kfree(msg); 414 + 415 + return ret; 416 + }
+191
drivers/gpu/drm/vmwgfx/vmwgfx_msg.h
··· 1 + /* 2 + * Copyright (C) 2016, VMware, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, but 10 + * WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 12 + * NON INFRINGEMENT. See the GNU General Public License for more 13 + * details. 14 + * 15 + * Based on code from vmware.c and vmmouse.c. 16 + * Author: 17 + * Sinclair Yeh <syeh@vmware.com> 18 + */ 19 + #ifndef _VMWGFX_MSG_H 20 + #define _VMWGFX_MSG_H 21 + 22 + 23 + /** 24 + * Hypervisor-specific bi-directional communication channel. Should never 25 + * execute on bare metal hardware. The caller must make sure to check for 26 + * supported hypervisor before using these macros. 27 + * 28 + * The last two parameters are both input and output and must be initialized. 29 + * 30 + * @cmd: [IN] Message Cmd 31 + * @in_ebx: [IN] Message Len, through EBX 32 + * @in_si: [IN] Input argument through SI, set to 0 if not used 33 + * @in_di: [IN] Input argument through DI, set ot 0 if not used 34 + * @port_num: [IN] port number + [channel id] 35 + * @magic: [IN] hypervisor magic value 36 + * @eax: [OUT] value of EAX register 37 + * @ebx: [OUT] e.g. status from an HB message status command 38 + * @ecx: [OUT] e.g. status from a non-HB message status command 39 + * @edx: [OUT] e.g. channel id 40 + * @si: [OUT] 41 + * @di: [OUT] 42 + */ 43 + #define VMW_PORT(cmd, in_ebx, in_si, in_di, \ 44 + port_num, magic, \ 45 + eax, ebx, ecx, edx, si, di) \ 46 + ({ \ 47 + asm volatile ("inl %%dx, %%eax;" : \ 48 + "=a"(eax), \ 49 + "=b"(ebx), \ 50 + "=c"(ecx), \ 51 + "=d"(edx), \ 52 + "=S"(si), \ 53 + "=D"(di) : \ 54 + "a"(magic), \ 55 + "b"(in_ebx), \ 56 + "c"(cmd), \ 57 + "d"(port_num), \ 58 + "S"(in_si), \ 59 + "D"(in_di) : \ 60 + "memory"); \ 61 + }) 62 + 63 + 64 + /** 65 + * Hypervisor-specific bi-directional communication channel. Should never 66 + * execute on bare metal hardware. The caller must make sure to check for 67 + * supported hypervisor before using these macros. 68 + * 69 + * The last 3 parameters are both input and output and must be initialized. 70 + * 71 + * @cmd: [IN] Message Cmd 72 + * @in_ecx: [IN] Message Len, through ECX 73 + * @in_si: [IN] Input argument through SI, set to 0 if not used 74 + * @in_di: [IN] Input argument through DI, set to 0 if not used 75 + * @port_num: [IN] port number + [channel id] 76 + * @magic: [IN] hypervisor magic value 77 + * @bp: [IN] 78 + * @eax: [OUT] value of EAX register 79 + * @ebx: [OUT] e.g. status from an HB message status command 80 + * @ecx: [OUT] e.g. status from a non-HB message status command 81 + * @edx: [OUT] e.g. channel id 82 + * @si: [OUT] 83 + * @di: [OUT] 84 + */ 85 + #ifdef __x86_64__ 86 + 87 + #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ 88 + port_num, magic, bp, \ 89 + eax, ebx, ecx, edx, si, di) \ 90 + ({ \ 91 + asm volatile ("push %%rbp;" \ 92 + "mov %12, %%rbp;" \ 93 + "rep outsb;" \ 94 + "pop %%rbp;" : \ 95 + "=a"(eax), \ 96 + "=b"(ebx), \ 97 + "=c"(ecx), \ 98 + "=d"(edx), \ 99 + "=S"(si), \ 100 + "=D"(di) : \ 101 + "a"(magic), \ 102 + "b"(cmd), \ 103 + "c"(in_ecx), \ 104 + "d"(port_num), \ 105 + "S"(in_si), \ 106 + "D"(in_di), \ 107 + "r"(bp) : \ 108 + "memory", "cc"); \ 109 + }) 110 + 111 + 112 + #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ 113 + port_num, magic, bp, \ 114 + eax, ebx, ecx, edx, si, di) \ 115 + ({ \ 116 + asm volatile ("push %%rbp;" \ 117 + "mov %12, %%rbp;" \ 118 + "rep insb;" \ 119 + "pop %%rbp" : \ 120 + "=a"(eax), \ 121 + "=b"(ebx), \ 122 + "=c"(ecx), \ 123 + "=d"(edx), \ 124 + "=S"(si), \ 125 + "=D"(di) : \ 126 + "a"(magic), \ 127 + "b"(cmd), \ 128 + "c"(in_ecx), \ 129 + "d"(port_num), \ 130 + "S"(in_si), \ 131 + "D"(in_di), \ 132 + "r"(bp) : \ 133 + "memory", "cc"); \ 134 + }) 135 + 136 + #else 137 + 138 + /* In the 32-bit version of this macro, we use "m" because there is no 139 + * more register left for bp 140 + */ 141 + #define VMW_PORT_HB_OUT(cmd, in_ecx, in_si, in_di, \ 142 + port_num, magic, bp, \ 143 + eax, ebx, ecx, edx, si, di) \ 144 + ({ \ 145 + asm volatile ("push %%ebp;" \ 146 + "mov %12, %%ebp;" \ 147 + "rep outsb;" \ 148 + "pop %%ebp;" : \ 149 + "=a"(eax), \ 150 + "=b"(ebx), \ 151 + "=c"(ecx), \ 152 + "=d"(edx), \ 153 + "=S"(si), \ 154 + "=D"(di) : \ 155 + "a"(magic), \ 156 + "b"(cmd), \ 157 + "c"(in_ecx), \ 158 + "d"(port_num), \ 159 + "S"(in_si), \ 160 + "D"(in_di), \ 161 + "m"(bp) : \ 162 + "memory", "cc"); \ 163 + }) 164 + 165 + 166 + #define VMW_PORT_HB_IN(cmd, in_ecx, in_si, in_di, \ 167 + port_num, magic, bp, \ 168 + eax, ebx, ecx, edx, si, di) \ 169 + ({ \ 170 + asm volatile ("push %%ebp;" \ 171 + "mov %12, %%ebp;" \ 172 + "rep insb;" \ 173 + "pop %%ebp" : \ 174 + "=a"(eax), \ 175 + "=b"(ebx), \ 176 + "=c"(ecx), \ 177 + "=d"(edx), \ 178 + "=S"(si), \ 179 + "=D"(di) : \ 180 + "a"(magic), \ 181 + "b"(cmd), \ 182 + "c"(in_ecx), \ 183 + "d"(port_num), \ 184 + "S"(in_si), \ 185 + "D"(in_di), \ 186 + "m"(bp) : \ 187 + "memory", "cc"); \ 188 + }) 189 + #endif /* #if __x86_64__ */ 190 + 191 + #endif
+3
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
··· 285 285 } 286 286 287 287 /* Only one active implicit frame-buffer at a time. */ 288 + mutex_lock(&dev_priv->global_kms_state_mutex); 288 289 if (sou->base.is_implicit && 289 290 dev_priv->implicit_fb && vfb && 290 291 !(dev_priv->num_implicit == 1 && 291 292 sou->base.active_implicit) && 292 293 dev_priv->implicit_fb != vfb) { 294 + mutex_unlock(&dev_priv->global_kms_state_mutex); 293 295 DRM_ERROR("Multiple implicit framebuffers not supported.\n"); 294 296 return -EINVAL; 295 297 } 298 + mutex_unlock(&dev_priv->global_kms_state_mutex); 296 299 297 300 /* since they always map one to one these are safe */ 298 301 connector = &sou->base.connector;
+3
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
··· 553 553 } 554 554 555 555 /* Only one active implicit frame-buffer at a time. */ 556 + mutex_lock(&dev_priv->global_kms_state_mutex); 556 557 if (!turning_off && stdu->base.is_implicit && dev_priv->implicit_fb && 557 558 !(dev_priv->num_implicit == 1 && stdu->base.active_implicit) 558 559 && dev_priv->implicit_fb != vfb) { 560 + mutex_unlock(&dev_priv->global_kms_state_mutex); 559 561 DRM_ERROR("Multiple implicit framebuffers not supported.\n"); 560 562 return -EINVAL; 561 563 } 564 + mutex_unlock(&dev_priv->global_kms_state_mutex); 562 565 563 566 /* Since they always map one to one these are safe */ 564 567 connector = &stdu->base.connector;