diff options
Diffstat (limited to 'drivers/gpu')
105 files changed, 1466 insertions, 943 deletions
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 66e40398b3d3..e620807418ea 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -37,6 +37,7 @@ obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o | |||
| 37 | obj-$(CONFIG_DRM_TTM) += ttm/ | 37 | obj-$(CONFIG_DRM_TTM) += ttm/ |
| 38 | obj-$(CONFIG_DRM_TDFX) += tdfx/ | 38 | obj-$(CONFIG_DRM_TDFX) += tdfx/ |
| 39 | obj-$(CONFIG_DRM_R128) += r128/ | 39 | obj-$(CONFIG_DRM_R128) += r128/ |
| 40 | obj-$(CONFIG_HSA_AMD) += amd/amdkfd/ | ||
| 40 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 41 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
| 41 | obj-$(CONFIG_DRM_MGA) += mga/ | 42 | obj-$(CONFIG_DRM_MGA) += mga/ |
| 42 | obj-$(CONFIG_DRM_I810) += i810/ | 43 | obj-$(CONFIG_DRM_I810) += i810/ |
| @@ -67,4 +68,3 @@ obj-$(CONFIG_DRM_IMX) += imx/ | |||
| 67 | obj-y += i2c/ | 68 | obj-y += i2c/ |
| 68 | obj-y += panel/ | 69 | obj-y += panel/ |
| 69 | obj-y += bridge/ | 70 | obj-y += bridge/ |
| 70 | obj-$(CONFIG_HSA_AMD) += amd/amdkfd/ | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index be6246de5091..307a309110e6 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile | |||
| @@ -8,7 +8,6 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ | |||
| 8 | kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ | 8 | kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ |
| 9 | kfd_process.o kfd_queue.o kfd_mqd_manager.o \ | 9 | kfd_process.o kfd_queue.o kfd_mqd_manager.o \ |
| 10 | kfd_kernel_queue.o kfd_packet_manager.o \ | 10 | kfd_kernel_queue.o kfd_packet_manager.o \ |
| 11 | kfd_process_queue_manager.o kfd_device_queue_manager.o \ | 11 | kfd_process_queue_manager.o kfd_device_queue_manager.o |
| 12 | kfd_interrupt.o | ||
| 13 | 12 | ||
| 14 | obj-$(CONFIG_HSA_AMD) += amdkfd.o | 13 | obj-$(CONFIG_HSA_AMD) += amdkfd.o |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 4f7b275f2f7b..fcfdf23e1913 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <uapi/linux/kfd_ioctl.h> | 31 | #include <uapi/linux/kfd_ioctl.h> |
| 32 | #include <linux/time.h> | 32 | #include <linux/time.h> |
| 33 | #include <linux/mm.h> | 33 | #include <linux/mm.h> |
| 34 | #include <linux/uaccess.h> | ||
| 35 | #include <uapi/asm-generic/mman-common.h> | 34 | #include <uapi/asm-generic/mman-common.h> |
| 36 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
| 37 | #include "kfd_priv.h" | 36 | #include "kfd_priv.h" |
| @@ -121,27 +120,20 @@ static int kfd_open(struct inode *inode, struct file *filep) | |||
| 121 | if (IS_ERR(process)) | 120 | if (IS_ERR(process)) |
| 122 | return PTR_ERR(process); | 121 | return PTR_ERR(process); |
| 123 | 122 | ||
| 124 | process->is_32bit_user_mode = is_32bit_user_mode; | ||
| 125 | |||
| 126 | dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", | 123 | dev_dbg(kfd_device, "process %d opened, compat mode (32 bit) - %d\n", |
| 127 | process->pasid, process->is_32bit_user_mode); | 124 | process->pasid, process->is_32bit_user_mode); |
| 128 | 125 | ||
| 129 | kfd_init_apertures(process); | ||
| 130 | |||
| 131 | return 0; | 126 | return 0; |
| 132 | } | 127 | } |
| 133 | 128 | ||
| 134 | static long kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, | 129 | static int kfd_ioctl_get_version(struct file *filep, struct kfd_process *p, |
| 135 | void __user *arg) | 130 | void *data) |
| 136 | { | 131 | { |
| 137 | struct kfd_ioctl_get_version_args args; | 132 | struct kfd_ioctl_get_version_args *args = data; |
| 138 | int err = 0; | 133 | int err = 0; |
| 139 | 134 | ||
| 140 | args.major_version = KFD_IOCTL_MAJOR_VERSION; | 135 | args->major_version = KFD_IOCTL_MAJOR_VERSION; |
| 141 | args.minor_version = KFD_IOCTL_MINOR_VERSION; | 136 | args->minor_version = KFD_IOCTL_MINOR_VERSION; |
| 142 | |||
| 143 | if (copy_to_user(arg, &args, sizeof(args))) | ||
| 144 | err = -EFAULT; | ||
| 145 | 137 | ||
| 146 | return err; | 138 | return err; |
| 147 | } | 139 | } |
| @@ -225,10 +217,10 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, | |||
| 225 | return 0; | 217 | return 0; |
| 226 | } | 218 | } |
| 227 | 219 | ||
| 228 | static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | 220 | static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, |
| 229 | void __user *arg) | 221 | void *data) |
| 230 | { | 222 | { |
| 231 | struct kfd_ioctl_create_queue_args args; | 223 | struct kfd_ioctl_create_queue_args *args = data; |
| 232 | struct kfd_dev *dev; | 224 | struct kfd_dev *dev; |
| 233 | int err = 0; | 225 | int err = 0; |
| 234 | unsigned int queue_id; | 226 | unsigned int queue_id; |
| @@ -237,16 +229,13 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
| 237 | 229 | ||
| 238 | memset(&q_properties, 0, sizeof(struct queue_properties)); | 230 | memset(&q_properties, 0, sizeof(struct queue_properties)); |
| 239 | 231 | ||
| 240 | if (copy_from_user(&args, arg, sizeof(args))) | ||
| 241 | return -EFAULT; | ||
| 242 | |||
| 243 | pr_debug("kfd: creating queue ioctl\n"); | 232 | pr_debug("kfd: creating queue ioctl\n"); |
| 244 | 233 | ||
| 245 | err = set_queue_properties_from_user(&q_properties, &args); | 234 | err = set_queue_properties_from_user(&q_properties, args); |
| 246 | if (err) | 235 | if (err) |
| 247 | return err; | 236 | return err; |
| 248 | 237 | ||
| 249 | dev = kfd_device_by_id(args.gpu_id); | 238 | dev = kfd_device_by_id(args->gpu_id); |
| 250 | if (dev == NULL) | 239 | if (dev == NULL) |
| 251 | return -EINVAL; | 240 | return -EINVAL; |
| 252 | 241 | ||
| @@ -254,7 +243,7 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
| 254 | 243 | ||
| 255 | pdd = kfd_bind_process_to_device(dev, p); | 244 | pdd = kfd_bind_process_to_device(dev, p); |
| 256 | if (IS_ERR(pdd)) { | 245 | if (IS_ERR(pdd)) { |
| 257 | err = PTR_ERR(pdd); | 246 | err = -ESRCH; |
| 258 | goto err_bind_process; | 247 | goto err_bind_process; |
| 259 | } | 248 | } |
| 260 | 249 | ||
| @@ -267,33 +256,26 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
| 267 | if (err != 0) | 256 | if (err != 0) |
| 268 | goto err_create_queue; | 257 | goto err_create_queue; |
| 269 | 258 | ||
| 270 | args.queue_id = queue_id; | 259 | args->queue_id = queue_id; |
| 271 | 260 | ||
| 272 | /* Return gpu_id as doorbell offset for mmap usage */ | 261 | /* Return gpu_id as doorbell offset for mmap usage */ |
| 273 | args.doorbell_offset = args.gpu_id << PAGE_SHIFT; | 262 | args->doorbell_offset = args->gpu_id << PAGE_SHIFT; |
| 274 | |||
| 275 | if (copy_to_user(arg, &args, sizeof(args))) { | ||
| 276 | err = -EFAULT; | ||
| 277 | goto err_copy_args_out; | ||
| 278 | } | ||
| 279 | 263 | ||
| 280 | mutex_unlock(&p->mutex); | 264 | mutex_unlock(&p->mutex); |
| 281 | 265 | ||
| 282 | pr_debug("kfd: queue id %d was created successfully\n", args.queue_id); | 266 | pr_debug("kfd: queue id %d was created successfully\n", args->queue_id); |
| 283 | 267 | ||
| 284 | pr_debug("ring buffer address == 0x%016llX\n", | 268 | pr_debug("ring buffer address == 0x%016llX\n", |
| 285 | args.ring_base_address); | 269 | args->ring_base_address); |
| 286 | 270 | ||
| 287 | pr_debug("read ptr address == 0x%016llX\n", | 271 | pr_debug("read ptr address == 0x%016llX\n", |
| 288 | args.read_pointer_address); | 272 | args->read_pointer_address); |
| 289 | 273 | ||
| 290 | pr_debug("write ptr address == 0x%016llX\n", | 274 | pr_debug("write ptr address == 0x%016llX\n", |
| 291 | args.write_pointer_address); | 275 | args->write_pointer_address); |
| 292 | 276 | ||
| 293 | return 0; | 277 | return 0; |
| 294 | 278 | ||
| 295 | err_copy_args_out: | ||
| 296 | pqm_destroy_queue(&p->pqm, queue_id); | ||
| 297 | err_create_queue: | 279 | err_create_queue: |
| 298 | err_bind_process: | 280 | err_bind_process: |
| 299 | mutex_unlock(&p->mutex); | 281 | mutex_unlock(&p->mutex); |
| @@ -301,99 +283,90 @@ err_bind_process: | |||
| 301 | } | 283 | } |
| 302 | 284 | ||
| 303 | static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, | 285 | static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, |
| 304 | void __user *arg) | 286 | void *data) |
| 305 | { | 287 | { |
| 306 | int retval; | 288 | int retval; |
| 307 | struct kfd_ioctl_destroy_queue_args args; | 289 | struct kfd_ioctl_destroy_queue_args *args = data; |
| 308 | |||
| 309 | if (copy_from_user(&args, arg, sizeof(args))) | ||
| 310 | return -EFAULT; | ||
| 311 | 290 | ||
| 312 | pr_debug("kfd: destroying queue id %d for PASID %d\n", | 291 | pr_debug("kfd: destroying queue id %d for PASID %d\n", |
| 313 | args.queue_id, | 292 | args->queue_id, |
| 314 | p->pasid); | 293 | p->pasid); |
| 315 | 294 | ||
| 316 | mutex_lock(&p->mutex); | 295 | mutex_lock(&p->mutex); |
| 317 | 296 | ||
| 318 | retval = pqm_destroy_queue(&p->pqm, args.queue_id); | 297 | retval = pqm_destroy_queue(&p->pqm, args->queue_id); |
| 319 | 298 | ||
| 320 | mutex_unlock(&p->mutex); | 299 | mutex_unlock(&p->mutex); |
| 321 | return retval; | 300 | return retval; |
| 322 | } | 301 | } |
| 323 | 302 | ||
| 324 | static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, | 303 | static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, |
| 325 | void __user *arg) | 304 | void *data) |
| 326 | { | 305 | { |
| 327 | int retval; | 306 | int retval; |
| 328 | struct kfd_ioctl_update_queue_args args; | 307 | struct kfd_ioctl_update_queue_args *args = data; |
| 329 | struct queue_properties properties; | 308 | struct queue_properties properties; |
| 330 | 309 | ||
| 331 | if (copy_from_user(&args, arg, sizeof(args))) | 310 | if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { |
| 332 | return -EFAULT; | ||
| 333 | |||
| 334 | if (args.queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { | ||
| 335 | pr_err("kfd: queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); | 311 | pr_err("kfd: queue percentage must be between 0 to KFD_MAX_QUEUE_PERCENTAGE\n"); |
| 336 | return -EINVAL; | 312 | return -EINVAL; |
| 337 | } | 313 | } |
| 338 | 314 | ||
| 339 | if (args.queue_priority > KFD_MAX_QUEUE_PRIORITY) { | 315 | if (args->queue_priority > KFD_MAX_QUEUE_PRIORITY) { |
| 340 | pr_err("kfd: queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); | 316 | pr_err("kfd: queue priority must be between 0 to KFD_MAX_QUEUE_PRIORITY\n"); |
| 341 | return -EINVAL; | 317 | return -EINVAL; |
| 342 | } | 318 | } |
| 343 | 319 | ||
| 344 | if ((args.ring_base_address) && | 320 | if ((args->ring_base_address) && |
| 345 | (!access_ok(VERIFY_WRITE, | 321 | (!access_ok(VERIFY_WRITE, |
| 346 | (const void __user *) args.ring_base_address, | 322 | (const void __user *) args->ring_base_address, |
| 347 | sizeof(uint64_t)))) { | 323 | sizeof(uint64_t)))) { |
| 348 | pr_err("kfd: can't access ring base address\n"); | 324 | pr_err("kfd: can't access ring base address\n"); |
| 349 | return -EFAULT; | 325 | return -EFAULT; |
| 350 | } | 326 | } |
| 351 | 327 | ||
| 352 | if (!is_power_of_2(args.ring_size) && (args.ring_size != 0)) { | 328 | if (!is_power_of_2(args->ring_size) && (args->ring_size != 0)) { |
| 353 | pr_err("kfd: ring size must be a power of 2 or 0\n"); | 329 | pr_err("kfd: ring size must be a power of 2 or 0\n"); |
| 354 | return -EINVAL; | 330 | return -EINVAL; |
| 355 | } | 331 | } |
| 356 | 332 | ||
| 357 | properties.queue_address = args.ring_base_address; | 333 | properties.queue_address = args->ring_base_address; |
| 358 | properties.queue_size = args.ring_size; | 334 | properties.queue_size = args->ring_size; |
| 359 | properties.queue_percent = args.queue_percentage; | 335 | properties.queue_percent = args->queue_percentage; |
| 360 | properties.priority = args.queue_priority; | 336 | properties.priority = args->queue_priority; |
| 361 | 337 | ||
| 362 | pr_debug("kfd: updating queue id %d for PASID %d\n", | 338 | pr_debug("kfd: updating queue id %d for PASID %d\n", |
| 363 | args.queue_id, p->pasid); | 339 | args->queue_id, p->pasid); |
| 364 | 340 | ||
| 365 | mutex_lock(&p->mutex); | 341 | mutex_lock(&p->mutex); |
| 366 | 342 | ||
| 367 | retval = pqm_update_queue(&p->pqm, args.queue_id, &properties); | 343 | retval = pqm_update_queue(&p->pqm, args->queue_id, &properties); |
| 368 | 344 | ||
| 369 | mutex_unlock(&p->mutex); | 345 | mutex_unlock(&p->mutex); |
| 370 | 346 | ||
| 371 | return retval; | 347 | return retval; |
| 372 | } | 348 | } |
| 373 | 349 | ||
| 374 | static long kfd_ioctl_set_memory_policy(struct file *filep, | 350 | static int kfd_ioctl_set_memory_policy(struct file *filep, |
| 375 | struct kfd_process *p, void __user *arg) | 351 | struct kfd_process *p, void *data) |
| 376 | { | 352 | { |
| 377 | struct kfd_ioctl_set_memory_policy_args args; | 353 | struct kfd_ioctl_set_memory_policy_args *args = data; |
| 378 | struct kfd_dev *dev; | 354 | struct kfd_dev *dev; |
| 379 | int err = 0; | 355 | int err = 0; |
| 380 | struct kfd_process_device *pdd; | 356 | struct kfd_process_device *pdd; |
| 381 | enum cache_policy default_policy, alternate_policy; | 357 | enum cache_policy default_policy, alternate_policy; |
| 382 | 358 | ||
| 383 | if (copy_from_user(&args, arg, sizeof(args))) | 359 | if (args->default_policy != KFD_IOC_CACHE_POLICY_COHERENT |
| 384 | return -EFAULT; | 360 | && args->default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
| 385 | |||
| 386 | if (args.default_policy != KFD_IOC_CACHE_POLICY_COHERENT | ||
| 387 | && args.default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | ||
| 388 | return -EINVAL; | 361 | return -EINVAL; |
| 389 | } | 362 | } |
| 390 | 363 | ||
| 391 | if (args.alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT | 364 | if (args->alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT |
| 392 | && args.alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | 365 | && args->alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
| 393 | return -EINVAL; | 366 | return -EINVAL; |
| 394 | } | 367 | } |
| 395 | 368 | ||
| 396 | dev = kfd_device_by_id(args.gpu_id); | 369 | dev = kfd_device_by_id(args->gpu_id); |
| 397 | if (dev == NULL) | 370 | if (dev == NULL) |
| 398 | return -EINVAL; | 371 | return -EINVAL; |
| 399 | 372 | ||
| @@ -401,23 +374,23 @@ static long kfd_ioctl_set_memory_policy(struct file *filep, | |||
| 401 | 374 | ||
| 402 | pdd = kfd_bind_process_to_device(dev, p); | 375 | pdd = kfd_bind_process_to_device(dev, p); |
| 403 | if (IS_ERR(pdd)) { | 376 | if (IS_ERR(pdd)) { |
| 404 | err = PTR_ERR(pdd); | 377 | err = -ESRCH; |
| 405 | goto out; | 378 | goto out; |
| 406 | } | 379 | } |
| 407 | 380 | ||
| 408 | default_policy = (args.default_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 381 | default_policy = (args->default_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
| 409 | ? cache_policy_coherent : cache_policy_noncoherent; | 382 | ? cache_policy_coherent : cache_policy_noncoherent; |
| 410 | 383 | ||
| 411 | alternate_policy = | 384 | alternate_policy = |
| 412 | (args.alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 385 | (args->alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
| 413 | ? cache_policy_coherent : cache_policy_noncoherent; | 386 | ? cache_policy_coherent : cache_policy_noncoherent; |
| 414 | 387 | ||
| 415 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, | 388 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, |
| 416 | &pdd->qpd, | 389 | &pdd->qpd, |
| 417 | default_policy, | 390 | default_policy, |
| 418 | alternate_policy, | 391 | alternate_policy, |
| 419 | (void __user *)args.alternate_aperture_base, | 392 | (void __user *)args->alternate_aperture_base, |
| 420 | args.alternate_aperture_size)) | 393 | args->alternate_aperture_size)) |
| 421 | err = -EINVAL; | 394 | err = -EINVAL; |
| 422 | 395 | ||
| 423 | out: | 396 | out: |
| @@ -426,53 +399,44 @@ out: | |||
| 426 | return err; | 399 | return err; |
| 427 | } | 400 | } |
| 428 | 401 | ||
| 429 | static long kfd_ioctl_get_clock_counters(struct file *filep, | 402 | static int kfd_ioctl_get_clock_counters(struct file *filep, |
| 430 | struct kfd_process *p, void __user *arg) | 403 | struct kfd_process *p, void *data) |
| 431 | { | 404 | { |
| 432 | struct kfd_ioctl_get_clock_counters_args args; | 405 | struct kfd_ioctl_get_clock_counters_args *args = data; |
| 433 | struct kfd_dev *dev; | 406 | struct kfd_dev *dev; |
| 434 | struct timespec time; | 407 | struct timespec time; |
| 435 | 408 | ||
| 436 | if (copy_from_user(&args, arg, sizeof(args))) | 409 | dev = kfd_device_by_id(args->gpu_id); |
| 437 | return -EFAULT; | ||
| 438 | |||
| 439 | dev = kfd_device_by_id(args.gpu_id); | ||
| 440 | if (dev == NULL) | 410 | if (dev == NULL) |
| 441 | return -EINVAL; | 411 | return -EINVAL; |
| 442 | 412 | ||
| 443 | /* Reading GPU clock counter from KGD */ | 413 | /* Reading GPU clock counter from KGD */ |
| 444 | args.gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); | 414 | args->gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); |
| 445 | 415 | ||
| 446 | /* No access to rdtsc. Using raw monotonic time */ | 416 | /* No access to rdtsc. Using raw monotonic time */ |
| 447 | getrawmonotonic(&time); | 417 | getrawmonotonic(&time); |
| 448 | args.cpu_clock_counter = (uint64_t)timespec_to_ns(&time); | 418 | args->cpu_clock_counter = (uint64_t)timespec_to_ns(&time); |
| 449 | 419 | ||
| 450 | get_monotonic_boottime(&time); | 420 | get_monotonic_boottime(&time); |
| 451 | args.system_clock_counter = (uint64_t)timespec_to_ns(&time); | 421 | args->system_clock_counter = (uint64_t)timespec_to_ns(&time); |
| 452 | 422 | ||
| 453 | /* Since the counter is in nano-seconds we use 1GHz frequency */ | 423 | /* Since the counter is in nano-seconds we use 1GHz frequency */ |
| 454 | args.system_clock_freq = 1000000000; | 424 | args->system_clock_freq = 1000000000; |
| 455 | |||
| 456 | if (copy_to_user(arg, &args, sizeof(args))) | ||
| 457 | return -EFAULT; | ||
| 458 | 425 | ||
| 459 | return 0; | 426 | return 0; |
| 460 | } | 427 | } |
| 461 | 428 | ||
| 462 | 429 | ||
| 463 | static int kfd_ioctl_get_process_apertures(struct file *filp, | 430 | static int kfd_ioctl_get_process_apertures(struct file *filp, |
| 464 | struct kfd_process *p, void __user *arg) | 431 | struct kfd_process *p, void *data) |
| 465 | { | 432 | { |
| 466 | struct kfd_ioctl_get_process_apertures_args args; | 433 | struct kfd_ioctl_get_process_apertures_args *args = data; |
| 467 | struct kfd_process_device_apertures *pAperture; | 434 | struct kfd_process_device_apertures *pAperture; |
| 468 | struct kfd_process_device *pdd; | 435 | struct kfd_process_device *pdd; |
| 469 | 436 | ||
| 470 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); | 437 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); |
| 471 | 438 | ||
| 472 | if (copy_from_user(&args, arg, sizeof(args))) | 439 | args->num_of_nodes = 0; |
| 473 | return -EFAULT; | ||
| 474 | |||
| 475 | args.num_of_nodes = 0; | ||
| 476 | 440 | ||
| 477 | mutex_lock(&p->mutex); | 441 | mutex_lock(&p->mutex); |
| 478 | 442 | ||
| @@ -481,7 +445,8 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
| 481 | /* Run over all pdd of the process */ | 445 | /* Run over all pdd of the process */ |
| 482 | pdd = kfd_get_first_process_device_data(p); | 446 | pdd = kfd_get_first_process_device_data(p); |
| 483 | do { | 447 | do { |
| 484 | pAperture = &args.process_apertures[args.num_of_nodes]; | 448 | pAperture = |
| 449 | &args->process_apertures[args->num_of_nodes]; | ||
| 485 | pAperture->gpu_id = pdd->dev->id; | 450 | pAperture->gpu_id = pdd->dev->id; |
| 486 | pAperture->lds_base = pdd->lds_base; | 451 | pAperture->lds_base = pdd->lds_base; |
| 487 | pAperture->lds_limit = pdd->lds_limit; | 452 | pAperture->lds_limit = pdd->lds_limit; |
| @@ -491,7 +456,7 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
| 491 | pAperture->scratch_limit = pdd->scratch_limit; | 456 | pAperture->scratch_limit = pdd->scratch_limit; |
| 492 | 457 | ||
| 493 | dev_dbg(kfd_device, | 458 | dev_dbg(kfd_device, |
| 494 | "node id %u\n", args.num_of_nodes); | 459 | "node id %u\n", args->num_of_nodes); |
| 495 | dev_dbg(kfd_device, | 460 | dev_dbg(kfd_device, |
| 496 | "gpu id %u\n", pdd->dev->id); | 461 | "gpu id %u\n", pdd->dev->id); |
| 497 | dev_dbg(kfd_device, | 462 | dev_dbg(kfd_device, |
| @@ -507,80 +472,131 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
| 507 | dev_dbg(kfd_device, | 472 | dev_dbg(kfd_device, |
| 508 | "scratch_limit %llX\n", pdd->scratch_limit); | 473 | "scratch_limit %llX\n", pdd->scratch_limit); |
| 509 | 474 | ||
| 510 | args.num_of_nodes++; | 475 | args->num_of_nodes++; |
| 511 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && | 476 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && |
| 512 | (args.num_of_nodes < NUM_OF_SUPPORTED_GPUS)); | 477 | (args->num_of_nodes < NUM_OF_SUPPORTED_GPUS)); |
| 513 | } | 478 | } |
| 514 | 479 | ||
| 515 | mutex_unlock(&p->mutex); | 480 | mutex_unlock(&p->mutex); |
| 516 | 481 | ||
| 517 | if (copy_to_user(arg, &args, sizeof(args))) | ||
| 518 | return -EFAULT; | ||
| 519 | |||
| 520 | return 0; | 482 | return 0; |
| 521 | } | 483 | } |
| 522 | 484 | ||
| 485 | #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ | ||
| 486 | [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl} | ||
| 487 | |||
| 488 | /** Ioctl table */ | ||
| 489 | static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { | ||
| 490 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_VERSION, | ||
| 491 | kfd_ioctl_get_version, 0), | ||
| 492 | |||
| 493 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_CREATE_QUEUE, | ||
| 494 | kfd_ioctl_create_queue, 0), | ||
| 495 | |||
| 496 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_DESTROY_QUEUE, | ||
| 497 | kfd_ioctl_destroy_queue, 0), | ||
| 498 | |||
| 499 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_MEMORY_POLICY, | ||
| 500 | kfd_ioctl_set_memory_policy, 0), | ||
| 501 | |||
| 502 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_CLOCK_COUNTERS, | ||
| 503 | kfd_ioctl_get_clock_counters, 0), | ||
| 504 | |||
| 505 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_GET_PROCESS_APERTURES, | ||
| 506 | kfd_ioctl_get_process_apertures, 0), | ||
| 507 | |||
| 508 | AMDKFD_IOCTL_DEF(AMDKFD_IOC_UPDATE_QUEUE, | ||
| 509 | kfd_ioctl_update_queue, 0), | ||
| 510 | }; | ||
| 511 | |||
| 512 | #define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls) | ||
| 513 | |||
| 523 | static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | 514 | static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) |
| 524 | { | 515 | { |
| 525 | struct kfd_process *process; | 516 | struct kfd_process *process; |
| 526 | long err = -EINVAL; | 517 | amdkfd_ioctl_t *func; |
| 518 | const struct amdkfd_ioctl_desc *ioctl = NULL; | ||
| 519 | unsigned int nr = _IOC_NR(cmd); | ||
| 520 | char stack_kdata[128]; | ||
| 521 | char *kdata = NULL; | ||
| 522 | unsigned int usize, asize; | ||
| 523 | int retcode = -EINVAL; | ||
| 524 | |||
| 525 | if (nr >= AMDKFD_CORE_IOCTL_COUNT) | ||
| 526 | goto err_i1; | ||
| 527 | |||
| 528 | if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) { | ||
| 529 | u32 amdkfd_size; | ||
| 530 | |||
| 531 | ioctl = &amdkfd_ioctls[nr]; | ||
| 527 | 532 | ||
| 528 | dev_dbg(kfd_device, | 533 | amdkfd_size = _IOC_SIZE(ioctl->cmd); |
| 529 | "ioctl cmd 0x%x (#%d), arg 0x%lx\n", | 534 | usize = asize = _IOC_SIZE(cmd); |
| 530 | cmd, _IOC_NR(cmd), arg); | 535 | if (amdkfd_size > asize) |
| 536 | asize = amdkfd_size; | ||
| 537 | |||
| 538 | cmd = ioctl->cmd; | ||
| 539 | } else | ||
| 540 | goto err_i1; | ||
| 541 | |||
| 542 | dev_dbg(kfd_device, "ioctl cmd 0x%x (#%d), arg 0x%lx\n", cmd, nr, arg); | ||
| 531 | 543 | ||
| 532 | process = kfd_get_process(current); | 544 | process = kfd_get_process(current); |
| 533 | if (IS_ERR(process)) | 545 | if (IS_ERR(process)) { |
| 534 | return PTR_ERR(process); | 546 | dev_dbg(kfd_device, "no process\n"); |
| 547 | goto err_i1; | ||
| 548 | } | ||
| 535 | 549 | ||
| 536 | switch (cmd) { | 550 | /* Do not trust userspace, use our own definition */ |
| 537 | case KFD_IOC_GET_VERSION: | 551 | func = ioctl->func; |
| 538 | err = kfd_ioctl_get_version(filep, process, (void __user *)arg); | 552 | |
| 539 | break; | 553 | if (unlikely(!func)) { |
| 540 | case KFD_IOC_CREATE_QUEUE: | 554 | dev_dbg(kfd_device, "no function\n"); |
| 541 | err = kfd_ioctl_create_queue(filep, process, | 555 | retcode = -EINVAL; |
| 542 | (void __user *)arg); | 556 | goto err_i1; |
| 543 | break; | ||
| 544 | |||
| 545 | case KFD_IOC_DESTROY_QUEUE: | ||
| 546 | err = kfd_ioctl_destroy_queue(filep, process, | ||
| 547 | (void __user *)arg); | ||
| 548 | break; | ||
| 549 | |||
| 550 | case KFD_IOC_SET_MEMORY_POLICY: | ||
| 551 | err = kfd_ioctl_set_memory_policy(filep, process, | ||
| 552 | (void __user *)arg); | ||
| 553 | break; | ||
| 554 | |||
| 555 | case KFD_IOC_GET_CLOCK_COUNTERS: | ||
| 556 | err = kfd_ioctl_get_clock_counters(filep, process, | ||
| 557 | (void __user *)arg); | ||
| 558 | break; | ||
| 559 | |||
| 560 | case KFD_IOC_GET_PROCESS_APERTURES: | ||
| 561 | err = kfd_ioctl_get_process_apertures(filep, process, | ||
| 562 | (void __user *)arg); | ||
| 563 | break; | ||
| 564 | |||
| 565 | case KFD_IOC_UPDATE_QUEUE: | ||
| 566 | err = kfd_ioctl_update_queue(filep, process, | ||
| 567 | (void __user *)arg); | ||
| 568 | break; | ||
| 569 | |||
| 570 | default: | ||
| 571 | dev_err(kfd_device, | ||
| 572 | "unknown ioctl cmd 0x%x, arg 0x%lx)\n", | ||
| 573 | cmd, arg); | ||
| 574 | err = -EINVAL; | ||
| 575 | break; | ||
| 576 | } | 557 | } |
| 577 | 558 | ||
| 578 | if (err < 0) | 559 | if (cmd & (IOC_IN | IOC_OUT)) { |
| 579 | dev_err(kfd_device, | 560 | if (asize <= sizeof(stack_kdata)) { |
| 580 | "ioctl error %ld for ioctl cmd 0x%x (#%d)\n", | 561 | kdata = stack_kdata; |
| 581 | err, cmd, _IOC_NR(cmd)); | 562 | } else { |
| 563 | kdata = kmalloc(asize, GFP_KERNEL); | ||
| 564 | if (!kdata) { | ||
| 565 | retcode = -ENOMEM; | ||
| 566 | goto err_i1; | ||
| 567 | } | ||
| 568 | } | ||
| 569 | if (asize > usize) | ||
| 570 | memset(kdata + usize, 0, asize - usize); | ||
| 571 | } | ||
| 582 | 572 | ||
| 583 | return err; | 573 | if (cmd & IOC_IN) { |
| 574 | if (copy_from_user(kdata, (void __user *)arg, usize) != 0) { | ||
| 575 | retcode = -EFAULT; | ||
| 576 | goto err_i1; | ||
| 577 | } | ||
| 578 | } else if (cmd & IOC_OUT) { | ||
| 579 | memset(kdata, 0, usize); | ||
| 580 | } | ||
| 581 | |||
| 582 | retcode = func(filep, process, kdata); | ||
| 583 | |||
| 584 | if (cmd & IOC_OUT) | ||
| 585 | if (copy_to_user((void __user *)arg, kdata, usize) != 0) | ||
| 586 | retcode = -EFAULT; | ||
| 587 | |||
| 588 | err_i1: | ||
| 589 | if (!ioctl) | ||
| 590 | dev_dbg(kfd_device, "invalid ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n", | ||
| 591 | task_pid_nr(current), cmd, nr); | ||
| 592 | |||
| 593 | if (kdata != stack_kdata) | ||
| 594 | kfree(kdata); | ||
| 595 | |||
| 596 | if (retcode) | ||
| 597 | dev_dbg(kfd_device, "ret = %d\n", retcode); | ||
| 598 | |||
| 599 | return retcode; | ||
| 584 | } | 600 | } |
| 585 | 601 | ||
| 586 | static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) | 602 | static int kfd_mmap(struct file *filp, struct vm_area_struct *vma) |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 43884ebd4303..25bc47f3c1cf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include "kfd_priv.h" | 27 | #include "kfd_priv.h" |
| 28 | #include "kfd_device_queue_manager.h" | 28 | #include "kfd_device_queue_manager.h" |
| 29 | #include "kfd_pm4_headers.h" | ||
| 29 | 30 | ||
| 30 | #define MQD_SIZE_ALIGNED 768 | 31 | #define MQD_SIZE_ALIGNED 768 |
| 31 | 32 | ||
| @@ -169,9 +170,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, | |||
| 169 | kfd->shared_resources = *gpu_resources; | 170 | kfd->shared_resources = *gpu_resources; |
| 170 | 171 | ||
| 171 | /* calculate max size of mqds needed for queues */ | 172 | /* calculate max size of mqds needed for queues */ |
| 172 | size = max_num_of_processes * | 173 | size = max_num_of_queues_per_device * |
| 173 | max_num_of_queues_per_process * | 174 | kfd->device_info->mqd_size_aligned; |
| 174 | kfd->device_info->mqd_size_aligned; | ||
| 175 | 175 | ||
| 176 | /* add another 512KB for all other allocations on gart */ | 176 | /* add another 512KB for all other allocations on gart */ |
| 177 | size += 512 * 1024; | 177 | size += 512 * 1024; |
| @@ -192,13 +192,6 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, | |||
| 192 | goto kfd_topology_add_device_error; | 192 | goto kfd_topology_add_device_error; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | if (kfd_interrupt_init(kfd)) { | ||
| 196 | dev_err(kfd_device, | ||
| 197 | "Error initializing interrupts for device (%x:%x)\n", | ||
| 198 | kfd->pdev->vendor, kfd->pdev->device); | ||
| 199 | goto kfd_interrupt_error; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (!device_iommu_pasid_init(kfd)) { | 195 | if (!device_iommu_pasid_init(kfd)) { |
| 203 | dev_err(kfd_device, | 196 | dev_err(kfd_device, |
| 204 | "Error initializing iommuv2 for device (%x:%x)\n", | 197 | "Error initializing iommuv2 for device (%x:%x)\n", |
| @@ -237,8 +230,6 @@ dqm_start_error: | |||
| 237 | device_queue_manager_error: | 230 | device_queue_manager_error: |
| 238 | amd_iommu_free_device(kfd->pdev); | 231 | amd_iommu_free_device(kfd->pdev); |
| 239 | device_iommu_pasid_error: | 232 | device_iommu_pasid_error: |
| 240 | kfd_interrupt_exit(kfd); | ||
| 241 | kfd_interrupt_error: | ||
| 242 | kfd_topology_remove_device(kfd); | 233 | kfd_topology_remove_device(kfd); |
| 243 | kfd_topology_add_device_error: | 234 | kfd_topology_add_device_error: |
| 244 | kfd2kgd->fini_sa_manager(kfd->kgd); | 235 | kfd2kgd->fini_sa_manager(kfd->kgd); |
| @@ -254,7 +245,6 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) | |||
| 254 | if (kfd->init_complete) { | 245 | if (kfd->init_complete) { |
| 255 | device_queue_manager_uninit(kfd->dqm); | 246 | device_queue_manager_uninit(kfd->dqm); |
| 256 | amd_iommu_free_device(kfd->pdev); | 247 | amd_iommu_free_device(kfd->pdev); |
| 257 | kfd_interrupt_exit(kfd); | ||
| 258 | kfd_topology_remove_device(kfd); | 248 | kfd_topology_remove_device(kfd); |
| 259 | } | 249 | } |
| 260 | 250 | ||
| @@ -296,13 +286,5 @@ int kgd2kfd_resume(struct kfd_dev *kfd) | |||
| 296 | /* This is called directly from KGD at ISR. */ | 286 | /* This is called directly from KGD at ISR. */ |
| 297 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) | 287 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) |
| 298 | { | 288 | { |
| 299 | if (kfd->init_complete) { | 289 | /* Process interrupts / schedule work as necessary */ |
| 300 | spin_lock(&kfd->interrupt_lock); | ||
| 301 | |||
| 302 | if (kfd->interrupts_active | ||
| 303 | && enqueue_ih_ring_entry(kfd, ih_ring_entry)) | ||
| 304 | schedule_work(&kfd->interrupt_work); | ||
| 305 | |||
| 306 | spin_unlock(&kfd->interrupt_lock); | ||
| 307 | } | ||
| 308 | } | 290 | } |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 924e90c072e5..0fd592799d58 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | |||
| @@ -161,6 +161,9 @@ static void deallocate_vmid(struct device_queue_manager *dqm, | |||
| 161 | { | 161 | { |
| 162 | int bit = qpd->vmid - KFD_VMID_START_OFFSET; | 162 | int bit = qpd->vmid - KFD_VMID_START_OFFSET; |
| 163 | 163 | ||
| 164 | /* Release the vmid mapping */ | ||
| 165 | set_pasid_vmid_mapping(dqm, 0, qpd->vmid); | ||
| 166 | |||
| 164 | set_bit(bit, (unsigned long *)&dqm->vmid_bitmap); | 167 | set_bit(bit, (unsigned long *)&dqm->vmid_bitmap); |
| 165 | qpd->vmid = 0; | 168 | qpd->vmid = 0; |
| 166 | q->properties.vmid = 0; | 169 | q->properties.vmid = 0; |
| @@ -180,6 +183,13 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, | |||
| 180 | 183 | ||
| 181 | mutex_lock(&dqm->lock); | 184 | mutex_lock(&dqm->lock); |
| 182 | 185 | ||
| 186 | if (dqm->total_queue_count >= max_num_of_queues_per_device) { | ||
| 187 | pr_warn("amdkfd: Can't create new usermode queue because %d queues were already created\n", | ||
| 188 | dqm->total_queue_count); | ||
| 189 | mutex_unlock(&dqm->lock); | ||
| 190 | return -EPERM; | ||
| 191 | } | ||
| 192 | |||
| 183 | if (list_empty(&qpd->queues_list)) { | 193 | if (list_empty(&qpd->queues_list)) { |
| 184 | retval = allocate_vmid(dqm, qpd, q); | 194 | retval = allocate_vmid(dqm, qpd, q); |
| 185 | if (retval != 0) { | 195 | if (retval != 0) { |
| @@ -204,6 +214,14 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, | |||
| 204 | list_add(&q->list, &qpd->queues_list); | 214 | list_add(&q->list, &qpd->queues_list); |
| 205 | dqm->queue_count++; | 215 | dqm->queue_count++; |
| 206 | 216 | ||
| 217 | /* | ||
| 218 | * Unconditionally increment this counter, regardless of the queue's | ||
| 219 | * type or whether the queue is active. | ||
| 220 | */ | ||
| 221 | dqm->total_queue_count++; | ||
| 222 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 223 | dqm->total_queue_count); | ||
| 224 | |||
| 207 | mutex_unlock(&dqm->lock); | 225 | mutex_unlock(&dqm->lock); |
| 208 | return 0; | 226 | return 0; |
| 209 | } | 227 | } |
| @@ -272,6 +290,18 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, | |||
| 272 | return retval; | 290 | return retval; |
| 273 | } | 291 | } |
| 274 | 292 | ||
| 293 | pr_debug("kfd: loading mqd to hqd on pipe (%d) queue (%d)\n", | ||
| 294 | q->pipe, | ||
| 295 | q->queue); | ||
| 296 | |||
| 297 | retval = mqd->load_mqd(mqd, q->mqd, q->pipe, | ||
| 298 | q->queue, (uint32_t __user *) q->properties.write_ptr); | ||
| 299 | if (retval != 0) { | ||
| 300 | deallocate_hqd(dqm, q); | ||
| 301 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); | ||
| 302 | return retval; | ||
| 303 | } | ||
| 304 | |||
| 275 | return 0; | 305 | return 0; |
| 276 | } | 306 | } |
| 277 | 307 | ||
| @@ -311,6 +341,15 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, | |||
| 311 | if (list_empty(&qpd->queues_list)) | 341 | if (list_empty(&qpd->queues_list)) |
| 312 | deallocate_vmid(dqm, qpd, q); | 342 | deallocate_vmid(dqm, qpd, q); |
| 313 | dqm->queue_count--; | 343 | dqm->queue_count--; |
| 344 | |||
| 345 | /* | ||
| 346 | * Unconditionally decrement this counter, regardless of the queue's | ||
| 347 | * type | ||
| 348 | */ | ||
| 349 | dqm->total_queue_count--; | ||
| 350 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 351 | dqm->total_queue_count); | ||
| 352 | |||
| 314 | out: | 353 | out: |
| 315 | mutex_unlock(&dqm->lock); | 354 | mutex_unlock(&dqm->lock); |
| 316 | return retval; | 355 | return retval; |
| @@ -320,6 +359,7 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) | |||
| 320 | { | 359 | { |
| 321 | int retval; | 360 | int retval; |
| 322 | struct mqd_manager *mqd; | 361 | struct mqd_manager *mqd; |
| 362 | bool prev_active = false; | ||
| 323 | 363 | ||
| 324 | BUG_ON(!dqm || !q || !q->mqd); | 364 | BUG_ON(!dqm || !q || !q->mqd); |
| 325 | 365 | ||
| @@ -330,10 +370,18 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) | |||
| 330 | return -ENOMEM; | 370 | return -ENOMEM; |
| 331 | } | 371 | } |
| 332 | 372 | ||
| 333 | retval = mqd->update_mqd(mqd, q->mqd, &q->properties); | ||
| 334 | if (q->properties.is_active == true) | 373 | if (q->properties.is_active == true) |
| 374 | prev_active = true; | ||
| 375 | |||
| 376 | /* | ||
| 377 | * | ||
| 378 | * check active state vs. the previous state | ||
| 379 | * and modify counter accordingly | ||
| 380 | */ | ||
| 381 | retval = mqd->update_mqd(mqd, q->mqd, &q->properties); | ||
| 382 | if ((q->properties.is_active == true) && (prev_active == false)) | ||
| 335 | dqm->queue_count++; | 383 | dqm->queue_count++; |
| 336 | else | 384 | else if ((q->properties.is_active == false) && (prev_active == true)) |
| 337 | dqm->queue_count--; | 385 | dqm->queue_count--; |
| 338 | 386 | ||
| 339 | if (sched_policy != KFD_SCHED_POLICY_NO_HWS) | 387 | if (sched_policy != KFD_SCHED_POLICY_NO_HWS) |
| @@ -517,10 +565,14 @@ static int init_pipelines(struct device_queue_manager *dqm, | |||
| 517 | 565 | ||
| 518 | for (i = 0; i < pipes_num; i++) { | 566 | for (i = 0; i < pipes_num; i++) { |
| 519 | inx = i + first_pipe; | 567 | inx = i + first_pipe; |
| 568 | /* | ||
| 569 | * HPD buffer on GTT is allocated by amdkfd, no need to waste | ||
| 570 | * space in GTT for pipelines we don't initialize | ||
| 571 | */ | ||
| 520 | pipe_hpd_addr = dqm->pipelines_addr + i * CIK_HPD_EOP_BYTES; | 572 | pipe_hpd_addr = dqm->pipelines_addr + i * CIK_HPD_EOP_BYTES; |
| 521 | pr_debug("kfd: pipeline address %llX\n", pipe_hpd_addr); | 573 | pr_debug("kfd: pipeline address %llX\n", pipe_hpd_addr); |
| 522 | /* = log2(bytes/4)-1 */ | 574 | /* = log2(bytes/4)-1 */ |
| 523 | kfd2kgd->init_pipeline(dqm->dev->kgd, i, | 575 | kfd2kgd->init_pipeline(dqm->dev->kgd, inx, |
| 524 | CIK_HPD_EOP_BYTES_LOG2 - 3, pipe_hpd_addr); | 576 | CIK_HPD_EOP_BYTES_LOG2 - 3, pipe_hpd_addr); |
| 525 | } | 577 | } |
| 526 | 578 | ||
| @@ -536,7 +588,7 @@ static int init_scheduler(struct device_queue_manager *dqm) | |||
| 536 | 588 | ||
| 537 | pr_debug("kfd: In %s\n", __func__); | 589 | pr_debug("kfd: In %s\n", __func__); |
| 538 | 590 | ||
| 539 | retval = init_pipelines(dqm, get_pipes_num(dqm), KFD_DQM_FIRST_PIPE); | 591 | retval = init_pipelines(dqm, get_pipes_num(dqm), get_first_pipe(dqm)); |
| 540 | if (retval != 0) | 592 | if (retval != 0) |
| 541 | return retval; | 593 | return retval; |
| 542 | 594 | ||
| @@ -728,6 +780,21 @@ static int create_kernel_queue_cpsch(struct device_queue_manager *dqm, | |||
| 728 | pr_debug("kfd: In func %s\n", __func__); | 780 | pr_debug("kfd: In func %s\n", __func__); |
| 729 | 781 | ||
| 730 | mutex_lock(&dqm->lock); | 782 | mutex_lock(&dqm->lock); |
| 783 | if (dqm->total_queue_count >= max_num_of_queues_per_device) { | ||
| 784 | pr_warn("amdkfd: Can't create new kernel queue because %d queues were already created\n", | ||
| 785 | dqm->total_queue_count); | ||
| 786 | mutex_unlock(&dqm->lock); | ||
| 787 | return -EPERM; | ||
| 788 | } | ||
| 789 | |||
| 790 | /* | ||
| 791 | * Unconditionally increment this counter, regardless of the queue's | ||
| 792 | * type or whether the queue is active. | ||
| 793 | */ | ||
| 794 | dqm->total_queue_count++; | ||
| 795 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 796 | dqm->total_queue_count); | ||
| 797 | |||
| 731 | list_add(&kq->list, &qpd->priv_queue_list); | 798 | list_add(&kq->list, &qpd->priv_queue_list); |
| 732 | dqm->queue_count++; | 799 | dqm->queue_count++; |
| 733 | qpd->is_debug = true; | 800 | qpd->is_debug = true; |
| @@ -751,6 +818,13 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, | |||
| 751 | dqm->queue_count--; | 818 | dqm->queue_count--; |
| 752 | qpd->is_debug = false; | 819 | qpd->is_debug = false; |
| 753 | execute_queues_cpsch(dqm, false); | 820 | execute_queues_cpsch(dqm, false); |
| 821 | /* | ||
| 822 | * Unconditionally decrement this counter, regardless of the queue's | ||
| 823 | * type. | ||
| 824 | */ | ||
| 825 | dqm->total_queue_count--; | ||
| 826 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 827 | dqm->total_queue_count); | ||
| 754 | mutex_unlock(&dqm->lock); | 828 | mutex_unlock(&dqm->lock); |
| 755 | } | 829 | } |
| 756 | 830 | ||
| @@ -769,6 +843,13 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, | |||
| 769 | 843 | ||
| 770 | mutex_lock(&dqm->lock); | 844 | mutex_lock(&dqm->lock); |
| 771 | 845 | ||
| 846 | if (dqm->total_queue_count >= max_num_of_queues_per_device) { | ||
| 847 | pr_warn("amdkfd: Can't create new usermode queue because %d queues were already created\n", | ||
| 848 | dqm->total_queue_count); | ||
| 849 | retval = -EPERM; | ||
| 850 | goto out; | ||
| 851 | } | ||
| 852 | |||
| 772 | mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_CP); | 853 | mqd = dqm->get_mqd_manager(dqm, KFD_MQD_TYPE_CIK_CP); |
| 773 | if (mqd == NULL) { | 854 | if (mqd == NULL) { |
| 774 | mutex_unlock(&dqm->lock); | 855 | mutex_unlock(&dqm->lock); |
| @@ -786,6 +867,15 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, | |||
| 786 | retval = execute_queues_cpsch(dqm, false); | 867 | retval = execute_queues_cpsch(dqm, false); |
| 787 | } | 868 | } |
| 788 | 869 | ||
| 870 | /* | ||
| 871 | * Unconditionally increment this counter, regardless of the queue's | ||
| 872 | * type or whether the queue is active. | ||
| 873 | */ | ||
| 874 | dqm->total_queue_count++; | ||
| 875 | |||
| 876 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 877 | dqm->total_queue_count); | ||
| 878 | |||
| 789 | out: | 879 | out: |
| 790 | mutex_unlock(&dqm->lock); | 880 | mutex_unlock(&dqm->lock); |
| 791 | return retval; | 881 | return retval; |
| @@ -906,6 +996,14 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, | |||
| 906 | 996 | ||
| 907 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); | 997 | mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); |
| 908 | 998 | ||
| 999 | /* | ||
| 1000 | * Unconditionally decrement this counter, regardless of the queue's | ||
| 1001 | * type | ||
| 1002 | */ | ||
| 1003 | dqm->total_queue_count--; | ||
| 1004 | pr_debug("Total of %d queues are accountable so far\n", | ||
| 1005 | dqm->total_queue_count); | ||
| 1006 | |||
| 909 | mutex_unlock(&dqm->lock); | 1007 | mutex_unlock(&dqm->lock); |
| 910 | 1008 | ||
| 911 | return 0; | 1009 | return 0; |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index c3f189e8ae35..52035bf0c1cb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | |||
| @@ -130,6 +130,7 @@ struct device_queue_manager { | |||
| 130 | struct list_head queues; | 130 | struct list_head queues; |
| 131 | unsigned int processes_count; | 131 | unsigned int processes_count; |
| 132 | unsigned int queue_count; | 132 | unsigned int queue_count; |
| 133 | unsigned int total_queue_count; | ||
| 133 | unsigned int next_pipe_to_allocate; | 134 | unsigned int next_pipe_to_allocate; |
| 134 | unsigned int *allocated_queues; | 135 | unsigned int *allocated_queues; |
| 135 | unsigned int vmid_bitmap; | 136 | unsigned int vmid_bitmap; |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index 66df4da01c29..e64aa99e5e41 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | |||
| @@ -299,13 +299,13 @@ int kfd_init_apertures(struct kfd_process *process) | |||
| 299 | struct kfd_dev *dev; | 299 | struct kfd_dev *dev; |
| 300 | struct kfd_process_device *pdd; | 300 | struct kfd_process_device *pdd; |
| 301 | 301 | ||
| 302 | mutex_lock(&process->mutex); | ||
| 303 | |||
| 304 | /*Iterating over all devices*/ | 302 | /*Iterating over all devices*/ |
| 305 | while ((dev = kfd_topology_enum_kfd_devices(id)) != NULL && | 303 | while ((dev = kfd_topology_enum_kfd_devices(id)) != NULL && |
| 306 | id < NUM_OF_SUPPORTED_GPUS) { | 304 | id < NUM_OF_SUPPORTED_GPUS) { |
| 307 | 305 | ||
| 308 | pdd = kfd_get_process_device_data(dev, process, 1); | 306 | pdd = kfd_get_process_device_data(dev, process, 1); |
| 307 | if (!pdd) | ||
| 308 | return -1; | ||
| 309 | 309 | ||
| 310 | /* | 310 | /* |
| 311 | * For 64 bit process aperture will be statically reserved in | 311 | * For 64 bit process aperture will be statically reserved in |
| @@ -348,8 +348,6 @@ int kfd_init_apertures(struct kfd_process *process) | |||
| 348 | id++; | 348 | id++; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | mutex_unlock(&process->mutex); | ||
| 352 | |||
| 353 | return 0; | 351 | return 0; |
| 354 | } | 352 | } |
| 355 | 353 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c deleted file mode 100644 index 5b999095a1f7..000000000000 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ /dev/null | |||
| @@ -1,176 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2014 Advanced Micro Devices, Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | /* | ||
| 24 | * KFD Interrupts. | ||
| 25 | * | ||
| 26 | * AMD GPUs deliver interrupts by pushing an interrupt description onto the | ||
| 27 | * interrupt ring and then sending an interrupt. KGD receives the interrupt | ||
| 28 | * in ISR and sends us a pointer to each new entry on the interrupt ring. | ||
| 29 | * | ||
| 30 | * We generally can't process interrupt-signaled events from ISR, so we call | ||
| 31 | * out to each interrupt client module (currently only the scheduler) to ask if | ||
| 32 | * each interrupt is interesting. If they return true, then it requires further | ||
| 33 | * processing so we copy it to an internal interrupt ring and call each | ||
| 34 | * interrupt client again from a work-queue. | ||
| 35 | * | ||
| 36 | * There's no acknowledgment for the interrupts we use. The hardware simply | ||
| 37 | * queues a new interrupt each time without waiting. | ||
| 38 | * | ||
| 39 | * The fixed-size internal queue means that it's possible for us to lose | ||
| 40 | * interrupts because we have no back-pressure to the hardware. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <linux/slab.h> | ||
| 44 | #include <linux/device.h> | ||
| 45 | #include "kfd_priv.h" | ||
| 46 | |||
| 47 | #define KFD_INTERRUPT_RING_SIZE 256 | ||
| 48 | |||
| 49 | static void interrupt_wq(struct work_struct *); | ||
| 50 | |||
| 51 | int kfd_interrupt_init(struct kfd_dev *kfd) | ||
| 52 | { | ||
| 53 | void *interrupt_ring = kmalloc_array(KFD_INTERRUPT_RING_SIZE, | ||
| 54 | kfd->device_info->ih_ring_entry_size, | ||
| 55 | GFP_KERNEL); | ||
| 56 | if (!interrupt_ring) | ||
| 57 | return -ENOMEM; | ||
| 58 | |||
| 59 | kfd->interrupt_ring = interrupt_ring; | ||
| 60 | kfd->interrupt_ring_size = | ||
| 61 | KFD_INTERRUPT_RING_SIZE * kfd->device_info->ih_ring_entry_size; | ||
| 62 | atomic_set(&kfd->interrupt_ring_wptr, 0); | ||
| 63 | atomic_set(&kfd->interrupt_ring_rptr, 0); | ||
| 64 | |||
| 65 | spin_lock_init(&kfd->interrupt_lock); | ||
| 66 | |||
| 67 | INIT_WORK(&kfd->interrupt_work, interrupt_wq); | ||
| 68 | |||
| 69 | kfd->interrupts_active = true; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * After this function returns, the interrupt will be enabled. This | ||
| 73 | * barrier ensures that the interrupt running on a different processor | ||
| 74 | * sees all the above writes. | ||
| 75 | */ | ||
| 76 | smp_wmb(); | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 81 | void kfd_interrupt_exit(struct kfd_dev *kfd) | ||
| 82 | { | ||
| 83 | /* | ||
| 84 | * Stop the interrupt handler from writing to the ring and scheduling | ||
| 85 | * workqueue items. The spinlock ensures that any interrupt running | ||
| 86 | * after we have unlocked sees interrupts_active = false. | ||
| 87 | */ | ||
| 88 | unsigned long flags; | ||
| 89 | |||
| 90 | spin_lock_irqsave(&kfd->interrupt_lock, flags); | ||
| 91 | kfd->interrupts_active = false; | ||
| 92 | spin_unlock_irqrestore(&kfd->interrupt_lock, flags); | ||
| 93 | |||
| 94 | /* | ||
| 95 | * Flush_scheduled_work ensures that there are no outstanding | ||
| 96 | * work-queue items that will access interrupt_ring. New work items | ||
| 97 | * can't be created because we stopped interrupt handling above. | ||
| 98 | */ | ||
| 99 | flush_scheduled_work(); | ||
| 100 | |||
| 101 | kfree(kfd->interrupt_ring); | ||
| 102 | } | ||
| 103 | |||
| 104 | /* | ||
| 105 | * This assumes that it can't be called concurrently with itself | ||
| 106 | * but only with dequeue_ih_ring_entry. | ||
| 107 | */ | ||
| 108 | bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry) | ||
| 109 | { | ||
| 110 | unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); | ||
| 111 | unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); | ||
| 112 | |||
| 113 | if ((rptr - wptr) % kfd->interrupt_ring_size == | ||
| 114 | kfd->device_info->ih_ring_entry_size) { | ||
| 115 | /* This is very bad, the system is likely to hang. */ | ||
| 116 | dev_err_ratelimited(kfd_chardev(), | ||
| 117 | "Interrupt ring overflow, dropping interrupt.\n"); | ||
| 118 | return false; | ||
| 119 | } | ||
| 120 | |||
| 121 | memcpy(kfd->interrupt_ring + wptr, ih_ring_entry, | ||
| 122 | kfd->device_info->ih_ring_entry_size); | ||
| 123 | |||
| 124 | wptr = (wptr + kfd->device_info->ih_ring_entry_size) % | ||
| 125 | kfd->interrupt_ring_size; | ||
| 126 | smp_wmb(); /* Ensure memcpy'd data is visible before wptr update. */ | ||
| 127 | atomic_set(&kfd->interrupt_ring_wptr, wptr); | ||
| 128 | |||
| 129 | return true; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | ||
| 133 | * This assumes that it can't be called concurrently with itself | ||
| 134 | * but only with enqueue_ih_ring_entry. | ||
| 135 | */ | ||
| 136 | static bool dequeue_ih_ring_entry(struct kfd_dev *kfd, void *ih_ring_entry) | ||
| 137 | { | ||
| 138 | /* | ||
| 139 | * Assume that wait queues have an implicit barrier, i.e. anything that | ||
| 140 | * happened in the ISR before it queued work is visible. | ||
| 141 | */ | ||
| 142 | |||
| 143 | unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); | ||
| 144 | unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); | ||
| 145 | |||
| 146 | if (rptr == wptr) | ||
| 147 | return false; | ||
| 148 | |||
| 149 | memcpy(ih_ring_entry, kfd->interrupt_ring + rptr, | ||
| 150 | kfd->device_info->ih_ring_entry_size); | ||
| 151 | |||
| 152 | rptr = (rptr + kfd->device_info->ih_ring_entry_size) % | ||
| 153 | kfd->interrupt_ring_size; | ||
| 154 | |||
| 155 | /* | ||
| 156 | * Ensure the rptr write update is not visible until | ||
| 157 | * memcpy has finished reading. | ||
| 158 | */ | ||
| 159 | smp_mb(); | ||
| 160 | atomic_set(&kfd->interrupt_ring_rptr, rptr); | ||
| 161 | |||
| 162 | return true; | ||
| 163 | } | ||
| 164 | |||
| 165 | static void interrupt_wq(struct work_struct *work) | ||
| 166 | { | ||
| 167 | struct kfd_dev *dev = container_of(work, struct kfd_dev, | ||
| 168 | interrupt_work); | ||
| 169 | |||
| 170 | uint32_t ih_ring_entry[DIV_ROUND_UP( | ||
| 171 | dev->device_info->ih_ring_entry_size, | ||
| 172 | sizeof(uint32_t))]; | ||
| 173 | |||
| 174 | while (dequeue_ih_ring_entry(dev, ih_ring_entry)) | ||
| 175 | ; | ||
| 176 | } | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c index 95d5af138e6e..1c385c23dd0b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c | |||
| @@ -50,15 +50,10 @@ module_param(sched_policy, int, 0444); | |||
| 50 | MODULE_PARM_DESC(sched_policy, | 50 | MODULE_PARM_DESC(sched_policy, |
| 51 | "Kernel cmdline parameter that defines the amdkfd scheduling policy"); | 51 | "Kernel cmdline parameter that defines the amdkfd scheduling policy"); |
| 52 | 52 | ||
| 53 | int max_num_of_processes = KFD_MAX_NUM_OF_PROCESSES_DEFAULT; | 53 | int max_num_of_queues_per_device = KFD_MAX_NUM_OF_QUEUES_PER_DEVICE_DEFAULT; |
| 54 | module_param(max_num_of_processes, int, 0444); | 54 | module_param(max_num_of_queues_per_device, int, 0444); |
| 55 | MODULE_PARM_DESC(max_num_of_processes, | 55 | MODULE_PARM_DESC(max_num_of_queues_per_device, |
| 56 | "Kernel cmdline parameter that defines the amdkfd maximum number of supported processes"); | 56 | "Maximum number of supported queues per device (1 = Minimum, 4096 = default)"); |
| 57 | |||
| 58 | int max_num_of_queues_per_process = KFD_MAX_NUM_OF_QUEUES_PER_PROCESS_DEFAULT; | ||
| 59 | module_param(max_num_of_queues_per_process, int, 0444); | ||
| 60 | MODULE_PARM_DESC(max_num_of_queues_per_process, | ||
| 61 | "Kernel cmdline parameter that defines the amdkfd maximum number of supported queues per process"); | ||
| 62 | 57 | ||
| 63 | bool kgd2kfd_init(unsigned interface_version, | 58 | bool kgd2kfd_init(unsigned interface_version, |
| 64 | const struct kfd2kgd_calls *f2g, | 59 | const struct kfd2kgd_calls *f2g, |
| @@ -100,16 +95,10 @@ static int __init kfd_module_init(void) | |||
| 100 | } | 95 | } |
| 101 | 96 | ||
| 102 | /* Verify module parameters */ | 97 | /* Verify module parameters */ |
| 103 | if ((max_num_of_processes < 0) || | 98 | if ((max_num_of_queues_per_device < 1) || |
| 104 | (max_num_of_processes > KFD_MAX_NUM_OF_PROCESSES)) { | 99 | (max_num_of_queues_per_device > |
| 105 | pr_err("kfd: max_num_of_processes must be between 0 to KFD_MAX_NUM_OF_PROCESSES\n"); | 100 | KFD_MAX_NUM_OF_QUEUES_PER_DEVICE)) { |
| 106 | return -1; | 101 | pr_err("kfd: max_num_of_queues_per_device must be between 1 to KFD_MAX_NUM_OF_QUEUES_PER_DEVICE\n"); |
| 107 | } | ||
| 108 | |||
| 109 | if ((max_num_of_queues_per_process < 0) || | ||
| 110 | (max_num_of_queues_per_process > | ||
| 111 | KFD_MAX_NUM_OF_QUEUES_PER_PROCESS)) { | ||
| 112 | pr_err("kfd: max_num_of_queues_per_process must be between 0 to KFD_MAX_NUM_OF_QUEUES_PER_PROCESS\n"); | ||
| 113 | return -1; | 102 | return -1; |
| 114 | } | 103 | } |
| 115 | 104 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index adc31474e786..4c3828cf45bf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c | |||
| @@ -184,7 +184,7 @@ static bool is_occupied(struct mqd_manager *mm, void *mqd, | |||
| 184 | uint32_t queue_id) | 184 | uint32_t queue_id) |
| 185 | { | 185 | { |
| 186 | 186 | ||
| 187 | return kfd2kgd->hqd_is_occupies(mm->dev->kgd, queue_address, | 187 | return kfd2kgd->hqd_is_occupied(mm->dev->kgd, queue_address, |
| 188 | pipe_id, queue_id); | 188 | pipe_id, queue_id); |
| 189 | 189 | ||
| 190 | } | 190 | } |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c index 71699ad97d74..6cfe7f1f18cf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_pasid.c | |||
| @@ -30,9 +30,9 @@ static DEFINE_MUTEX(pasid_mutex); | |||
| 30 | 30 | ||
| 31 | int kfd_pasid_init(void) | 31 | int kfd_pasid_init(void) |
| 32 | { | 32 | { |
| 33 | pasid_limit = max_num_of_processes; | 33 | pasid_limit = KFD_MAX_NUM_OF_PROCESSES; |
| 34 | 34 | ||
| 35 | pasid_bitmap = kzalloc(BITS_TO_LONGS(pasid_limit), GFP_KERNEL); | 35 | pasid_bitmap = kcalloc(BITS_TO_LONGS(pasid_limit), sizeof(long), GFP_KERNEL); |
| 36 | if (!pasid_bitmap) | 36 | if (!pasid_bitmap) |
| 37 | return -ENOMEM; | 37 | return -ENOMEM; |
| 38 | 38 | ||
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f9fb81e3bb09..96dc10e8904a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h | |||
| @@ -52,20 +52,19 @@ | |||
| 52 | #define kfd_alloc_struct(ptr_to_struct) \ | 52 | #define kfd_alloc_struct(ptr_to_struct) \ |
| 53 | ((typeof(ptr_to_struct)) kzalloc(sizeof(*ptr_to_struct), GFP_KERNEL)) | 53 | ((typeof(ptr_to_struct)) kzalloc(sizeof(*ptr_to_struct), GFP_KERNEL)) |
| 54 | 54 | ||
| 55 | /* Kernel module parameter to specify maximum number of supported processes */ | ||
| 56 | extern int max_num_of_processes; | ||
| 57 | |||
| 58 | #define KFD_MAX_NUM_OF_PROCESSES_DEFAULT 32 | ||
| 59 | #define KFD_MAX_NUM_OF_PROCESSES 512 | 55 | #define KFD_MAX_NUM_OF_PROCESSES 512 |
| 56 | #define KFD_MAX_NUM_OF_QUEUES_PER_PROCESS 1024 | ||
| 60 | 57 | ||
| 61 | /* | 58 | /* |
| 62 | * Kernel module parameter to specify maximum number of supported queues | 59 | * Kernel module parameter to specify maximum number of supported queues per |
| 63 | * per process | 60 | * device |
| 64 | */ | 61 | */ |
| 65 | extern int max_num_of_queues_per_process; | 62 | extern int max_num_of_queues_per_device; |
| 66 | 63 | ||
| 67 | #define KFD_MAX_NUM_OF_QUEUES_PER_PROCESS_DEFAULT 128 | 64 | #define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE_DEFAULT 4096 |
| 68 | #define KFD_MAX_NUM_OF_QUEUES_PER_PROCESS 1024 | 65 | #define KFD_MAX_NUM_OF_QUEUES_PER_DEVICE \ |
| 66 | (KFD_MAX_NUM_OF_PROCESSES * \ | ||
| 67 | KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) | ||
| 69 | 68 | ||
| 70 | #define KFD_KERNEL_QUEUE_SIZE 2048 | 69 | #define KFD_KERNEL_QUEUE_SIZE 2048 |
| 71 | 70 | ||
| @@ -135,22 +134,10 @@ struct kfd_dev { | |||
| 135 | 134 | ||
| 136 | struct kgd2kfd_shared_resources shared_resources; | 135 | struct kgd2kfd_shared_resources shared_resources; |
| 137 | 136 | ||
| 138 | void *interrupt_ring; | ||
| 139 | size_t interrupt_ring_size; | ||
| 140 | atomic_t interrupt_ring_rptr; | ||
| 141 | atomic_t interrupt_ring_wptr; | ||
| 142 | struct work_struct interrupt_work; | ||
| 143 | spinlock_t interrupt_lock; | ||
| 144 | |||
| 145 | /* QCM Device instance */ | 137 | /* QCM Device instance */ |
| 146 | struct device_queue_manager *dqm; | 138 | struct device_queue_manager *dqm; |
| 147 | 139 | ||
| 148 | bool init_complete; | 140 | bool init_complete; |
| 149 | /* | ||
| 150 | * Interrupts of interest to KFD are copied | ||
| 151 | * from the HW ring into a SW ring. | ||
| 152 | */ | ||
| 153 | bool interrupts_active; | ||
| 154 | }; | 141 | }; |
| 155 | 142 | ||
| 156 | /* KGD2KFD callbacks */ | 143 | /* KGD2KFD callbacks */ |
| @@ -463,6 +450,24 @@ struct kfd_process { | |||
| 463 | bool is_32bit_user_mode; | 450 | bool is_32bit_user_mode; |
| 464 | }; | 451 | }; |
| 465 | 452 | ||
| 453 | /** | ||
| 454 | * Ioctl function type. | ||
| 455 | * | ||
| 456 | * \param filep pointer to file structure. | ||
| 457 | * \param p amdkfd process pointer. | ||
| 458 | * \param data pointer to arg that was copied from user. | ||
| 459 | */ | ||
| 460 | typedef int amdkfd_ioctl_t(struct file *filep, struct kfd_process *p, | ||
| 461 | void *data); | ||
| 462 | |||
| 463 | struct amdkfd_ioctl_desc { | ||
| 464 | unsigned int cmd; | ||
| 465 | int flags; | ||
| 466 | amdkfd_ioctl_t *func; | ||
| 467 | unsigned int cmd_drv; | ||
| 468 | const char *name; | ||
| 469 | }; | ||
| 470 | |||
| 466 | void kfd_process_create_wq(void); | 471 | void kfd_process_create_wq(void); |
| 467 | void kfd_process_destroy_wq(void); | 472 | void kfd_process_destroy_wq(void); |
| 468 | struct kfd_process *kfd_create_process(const struct task_struct *); | 473 | struct kfd_process *kfd_create_process(const struct task_struct *); |
| @@ -513,10 +518,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); | |||
| 513 | struct kfd_dev *kfd_topology_enum_kfd_devices(uint8_t idx); | 518 | struct kfd_dev *kfd_topology_enum_kfd_devices(uint8_t idx); |
| 514 | 519 | ||
| 515 | /* Interrupts */ | 520 | /* Interrupts */ |
| 516 | int kfd_interrupt_init(struct kfd_dev *dev); | ||
| 517 | void kfd_interrupt_exit(struct kfd_dev *dev); | ||
| 518 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); | 521 | void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry); |
| 519 | bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry); | ||
| 520 | 522 | ||
| 521 | /* Power Management */ | 523 | /* Power Management */ |
| 522 | void kgd2kfd_suspend(struct kfd_dev *kfd); | 524 | void kgd2kfd_suspend(struct kfd_dev *kfd); |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index b85eb0b830b4..3c76ef05cbcf 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/amd-iommu.h> | 27 | #include <linux/amd-iommu.h> |
| 28 | #include <linux/notifier.h> | 28 | #include <linux/notifier.h> |
| 29 | #include <linux/compat.h> | ||
| 30 | |||
| 29 | struct mm_struct; | 31 | struct mm_struct; |
| 30 | 32 | ||
| 31 | #include "kfd_priv.h" | 33 | #include "kfd_priv.h" |
| @@ -285,8 +287,15 @@ static struct kfd_process *create_process(const struct task_struct *thread) | |||
| 285 | if (err != 0) | 287 | if (err != 0) |
| 286 | goto err_process_pqm_init; | 288 | goto err_process_pqm_init; |
| 287 | 289 | ||
| 290 | /* init process apertures*/ | ||
| 291 | process->is_32bit_user_mode = is_compat_task(); | ||
| 292 | if (kfd_init_apertures(process) != 0) | ||
| 293 | goto err_init_apretures; | ||
| 294 | |||
| 288 | return process; | 295 | return process; |
| 289 | 296 | ||
| 297 | err_init_apretures: | ||
| 298 | pqm_uninit(&process->pqm); | ||
| 290 | err_process_pqm_init: | 299 | err_process_pqm_init: |
| 291 | hash_del_rcu(&process->kfd_processes); | 300 | hash_del_rcu(&process->kfd_processes); |
| 292 | synchronize_rcu(); | 301 | synchronize_rcu(); |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 47526780d736..2fda1927bff7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | |||
| @@ -54,11 +54,11 @@ static int find_available_queue_slot(struct process_queue_manager *pqm, | |||
| 54 | pr_debug("kfd: in %s\n", __func__); | 54 | pr_debug("kfd: in %s\n", __func__); |
| 55 | 55 | ||
| 56 | found = find_first_zero_bit(pqm->queue_slot_bitmap, | 56 | found = find_first_zero_bit(pqm->queue_slot_bitmap, |
| 57 | max_num_of_queues_per_process); | 57 | KFD_MAX_NUM_OF_QUEUES_PER_PROCESS); |
| 58 | 58 | ||
| 59 | pr_debug("kfd: the new slot id %lu\n", found); | 59 | pr_debug("kfd: the new slot id %lu\n", found); |
| 60 | 60 | ||
| 61 | if (found >= max_num_of_queues_per_process) { | 61 | if (found >= KFD_MAX_NUM_OF_QUEUES_PER_PROCESS) { |
| 62 | pr_info("amdkfd: Can not open more queues for process with pasid %d\n", | 62 | pr_info("amdkfd: Can not open more queues for process with pasid %d\n", |
| 63 | pqm->process->pasid); | 63 | pqm->process->pasid); |
| 64 | return -ENOMEM; | 64 | return -ENOMEM; |
| @@ -76,7 +76,7 @@ int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p) | |||
| 76 | 76 | ||
| 77 | INIT_LIST_HEAD(&pqm->queues); | 77 | INIT_LIST_HEAD(&pqm->queues); |
| 78 | pqm->queue_slot_bitmap = | 78 | pqm->queue_slot_bitmap = |
| 79 | kzalloc(DIV_ROUND_UP(max_num_of_queues_per_process, | 79 | kzalloc(DIV_ROUND_UP(KFD_MAX_NUM_OF_QUEUES_PER_PROCESS, |
| 80 | BITS_PER_BYTE), GFP_KERNEL); | 80 | BITS_PER_BYTE), GFP_KERNEL); |
| 81 | if (pqm->queue_slot_bitmap == NULL) | 81 | if (pqm->queue_slot_bitmap == NULL) |
| 82 | return -ENOMEM; | 82 | return -ENOMEM; |
| @@ -203,6 +203,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, | |||
| 203 | pqn->kq = NULL; | 203 | pqn->kq = NULL; |
| 204 | retval = dev->dqm->create_queue(dev->dqm, q, &pdd->qpd, | 204 | retval = dev->dqm->create_queue(dev->dqm, q, &pdd->qpd, |
| 205 | &q->properties.vmid); | 205 | &q->properties.vmid); |
| 206 | pr_debug("DQM returned %d for create_queue\n", retval); | ||
| 206 | print_queue(q); | 207 | print_queue(q); |
| 207 | break; | 208 | break; |
| 208 | case KFD_QUEUE_TYPE_DIQ: | 209 | case KFD_QUEUE_TYPE_DIQ: |
| @@ -222,7 +223,7 @@ int pqm_create_queue(struct process_queue_manager *pqm, | |||
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | if (retval != 0) { | 225 | if (retval != 0) { |
| 225 | pr_err("kfd: error dqm create queue\n"); | 226 | pr_debug("Error dqm create queue\n"); |
| 226 | goto err_create_queue; | 227 | goto err_create_queue; |
| 227 | } | 228 | } |
| 228 | 229 | ||
| @@ -241,7 +242,10 @@ int pqm_create_queue(struct process_queue_manager *pqm, | |||
| 241 | err_create_queue: | 242 | err_create_queue: |
| 242 | kfree(pqn); | 243 | kfree(pqn); |
| 243 | err_allocate_pqn: | 244 | err_allocate_pqn: |
| 245 | /* check if queues list is empty unregister process from device */ | ||
| 244 | clear_bit(*qid, pqm->queue_slot_bitmap); | 246 | clear_bit(*qid, pqm->queue_slot_bitmap); |
| 247 | if (list_empty(&pqm->queues)) | ||
| 248 | dev->dqm->unregister_process(dev->dqm, &pdd->qpd); | ||
| 245 | return retval; | 249 | return retval; |
| 246 | } | 250 | } |
| 247 | 251 | ||
| @@ -311,7 +315,11 @@ int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid, | |||
| 311 | BUG_ON(!pqm); | 315 | BUG_ON(!pqm); |
| 312 | 316 | ||
| 313 | pqn = get_queue_by_qid(pqm, qid); | 317 | pqn = get_queue_by_qid(pqm, qid); |
| 314 | BUG_ON(!pqn); | 318 | if (!pqn) { |
| 319 | pr_debug("amdkfd: No queue %d exists for update operation\n", | ||
| 320 | qid); | ||
| 321 | return -EFAULT; | ||
| 322 | } | ||
| 315 | 323 | ||
| 316 | pqn->q->properties.queue_address = p->queue_address; | 324 | pqn->q->properties.queue_address = p->queue_address; |
| 317 | pqn->q->properties.queue_size = p->queue_size; | 325 | pqn->q->properties.queue_size = p->queue_size; |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5733e2859e8a..cca1708fd811 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c | |||
| @@ -700,8 +700,6 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, | |||
| 700 | dev->node_props.simd_per_cu); | 700 | dev->node_props.simd_per_cu); |
| 701 | sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", | 701 | sysfs_show_32bit_prop(buffer, "max_slots_scratch_cu", |
| 702 | dev->node_props.max_slots_scratch_cu); | 702 | dev->node_props.max_slots_scratch_cu); |
| 703 | sysfs_show_32bit_prop(buffer, "engine_id", | ||
| 704 | dev->node_props.engine_id); | ||
| 705 | sysfs_show_32bit_prop(buffer, "vendor_id", | 703 | sysfs_show_32bit_prop(buffer, "vendor_id", |
| 706 | dev->node_props.vendor_id); | 704 | dev->node_props.vendor_id); |
| 707 | sysfs_show_32bit_prop(buffer, "device_id", | 705 | sysfs_show_32bit_prop(buffer, "device_id", |
| @@ -715,6 +713,12 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, | |||
| 715 | dev->gpu->kgd)); | 713 | dev->gpu->kgd)); |
| 716 | sysfs_show_64bit_prop(buffer, "local_mem_size", | 714 | sysfs_show_64bit_prop(buffer, "local_mem_size", |
| 717 | kfd2kgd->get_vmem_size(dev->gpu->kgd)); | 715 | kfd2kgd->get_vmem_size(dev->gpu->kgd)); |
| 716 | |||
| 717 | sysfs_show_32bit_prop(buffer, "fw_version", | ||
| 718 | kfd2kgd->get_fw_version( | ||
| 719 | dev->gpu->kgd, | ||
| 720 | KGD_ENGINE_MEC1)); | ||
| 721 | |||
| 718 | } | 722 | } |
| 719 | 723 | ||
| 720 | ret = sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", | 724 | ret = sysfs_show_32bit_prop(buffer, "max_engine_clk_ccompute", |
| @@ -917,7 +921,7 @@ static int kfd_build_sysfs_node_tree(void) | |||
| 917 | uint32_t i = 0; | 921 | uint32_t i = 0; |
| 918 | 922 | ||
| 919 | list_for_each_entry(dev, &topology_device_list, list) { | 923 | list_for_each_entry(dev, &topology_device_list, list) { |
| 920 | ret = kfd_build_sysfs_node_entry(dev, 0); | 924 | ret = kfd_build_sysfs_node_entry(dev, i); |
| 921 | if (ret < 0) | 925 | if (ret < 0) |
| 922 | return ret; | 926 | return ret; |
| 923 | i++; | 927 | i++; |
diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 9c729dd8dd50..96a512208fad 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h | |||
| @@ -45,6 +45,17 @@ enum kgd_memory_pool { | |||
| 45 | KGD_POOL_FRAMEBUFFER = 3, | 45 | KGD_POOL_FRAMEBUFFER = 3, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | enum kgd_engine_type { | ||
| 49 | KGD_ENGINE_PFP = 1, | ||
| 50 | KGD_ENGINE_ME, | ||
| 51 | KGD_ENGINE_CE, | ||
| 52 | KGD_ENGINE_MEC1, | ||
| 53 | KGD_ENGINE_MEC2, | ||
| 54 | KGD_ENGINE_RLC, | ||
| 55 | KGD_ENGINE_SDMA, | ||
| 56 | KGD_ENGINE_MAX | ||
| 57 | }; | ||
| 58 | |||
| 48 | struct kgd2kfd_shared_resources { | 59 | struct kgd2kfd_shared_resources { |
| 49 | /* Bit n == 1 means VMID n is available for KFD. */ | 60 | /* Bit n == 1 means VMID n is available for KFD. */ |
| 50 | unsigned int compute_vmid_bitmap; | 61 | unsigned int compute_vmid_bitmap; |
| @@ -137,6 +148,8 @@ struct kgd2kfd_calls { | |||
| 137 | * | 148 | * |
| 138 | * @hqd_destroy: Destructs and preempts the queue assigned to that hqd slot. | 149 | * @hqd_destroy: Destructs and preempts the queue assigned to that hqd slot. |
| 139 | * | 150 | * |
| 151 | * @get_fw_version: Returns FW versions from the header | ||
| 152 | * | ||
| 140 | * This structure contains function pointers to services that the kgd driver | 153 | * This structure contains function pointers to services that the kgd driver |
| 141 | * provides to amdkfd driver. | 154 | * provides to amdkfd driver. |
| 142 | * | 155 | * |
| @@ -170,12 +183,14 @@ struct kfd2kgd_calls { | |||
| 170 | int (*hqd_load)(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | 183 | int (*hqd_load)(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, |
| 171 | uint32_t queue_id, uint32_t __user *wptr); | 184 | uint32_t queue_id, uint32_t __user *wptr); |
| 172 | 185 | ||
| 173 | bool (*hqd_is_occupies)(struct kgd_dev *kgd, uint64_t queue_address, | 186 | bool (*hqd_is_occupied)(struct kgd_dev *kgd, uint64_t queue_address, |
| 174 | uint32_t pipe_id, uint32_t queue_id); | 187 | uint32_t pipe_id, uint32_t queue_id); |
| 175 | 188 | ||
| 176 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, | 189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, |
| 177 | unsigned int timeout, uint32_t pipe_id, | 190 | unsigned int timeout, uint32_t pipe_id, |
| 178 | uint32_t queue_id); | 191 | uint32_t queue_id); |
| 192 | uint16_t (*get_fw_version)(struct kgd_dev *kgd, | ||
| 193 | enum kgd_engine_type type); | ||
| 179 | }; | 194 | }; |
| 180 | 195 | ||
| 181 | bool kgd2kfd_init(unsigned interface_version, | 196 | bool kgd2kfd_init(unsigned interface_version, |
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index c2a1cba1e984..b9140032962d 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c | |||
| @@ -16,9 +16,12 @@ | |||
| 16 | #include "cirrus_drv.h" | 16 | #include "cirrus_drv.h" |
| 17 | 17 | ||
| 18 | int cirrus_modeset = -1; | 18 | int cirrus_modeset = -1; |
| 19 | int cirrus_bpp = 24; | ||
| 19 | 20 | ||
| 20 | MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); | 21 | MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); |
| 21 | module_param_named(modeset, cirrus_modeset, int, 0400); | 22 | module_param_named(modeset, cirrus_modeset, int, 0400); |
| 23 | MODULE_PARM_DESC(bpp, "Max bits-per-pixel (default:24)"); | ||
| 24 | module_param_named(bpp, cirrus_bpp, int, 0400); | ||
| 22 | 25 | ||
| 23 | /* | 26 | /* |
| 24 | * This is the generic driver code. This binds the driver to the drm core, | 27 | * This is the generic driver code. This binds the driver to the drm core, |
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h index 693a4565c4ff..705061537a27 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.h +++ b/drivers/gpu/drm/cirrus/cirrus_drv.h | |||
| @@ -262,4 +262,7 @@ static inline void cirrus_bo_unreserve(struct cirrus_bo *bo) | |||
| 262 | 262 | ||
| 263 | int cirrus_bo_push_sysram(struct cirrus_bo *bo); | 263 | int cirrus_bo_push_sysram(struct cirrus_bo *bo); |
| 264 | int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr); | 264 | int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr); |
| 265 | |||
| 266 | extern int cirrus_bpp; | ||
| 267 | |||
| 265 | #endif /* __CIRRUS_DRV_H__ */ | 268 | #endif /* __CIRRUS_DRV_H__ */ |
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index 4c2d68e9102d..e4b976658087 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c | |||
| @@ -320,6 +320,8 @@ bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height, | |||
| 320 | const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */ | 320 | const int max_pitch = 0x1FF << 3; /* (4096 - 1) & ~111b bytes */ |
| 321 | const int max_size = cdev->mc.vram_size; | 321 | const int max_size = cdev->mc.vram_size; |
| 322 | 322 | ||
| 323 | if (bpp > cirrus_bpp) | ||
| 324 | return false; | ||
| 323 | if (bpp > 32) | 325 | if (bpp > 32) |
| 324 | return false; | 326 | return false; |
| 325 | 327 | ||
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 99d4a74ffeaf..61385f2298bf 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
| @@ -501,8 +501,13 @@ static int cirrus_vga_get_modes(struct drm_connector *connector) | |||
| 501 | int count; | 501 | int count; |
| 502 | 502 | ||
| 503 | /* Just add a static list of modes */ | 503 | /* Just add a static list of modes */ |
| 504 | count = drm_add_modes_noedid(connector, 1280, 1024); | 504 | if (cirrus_bpp <= 24) { |
| 505 | drm_set_preferred_mode(connector, 1024, 768); | 505 | count = drm_add_modes_noedid(connector, 1280, 1024); |
| 506 | drm_set_preferred_mode(connector, 1024, 768); | ||
| 507 | } else { | ||
| 508 | count = drm_add_modes_noedid(connector, 800, 600); | ||
| 509 | drm_set_preferred_mode(connector, 800, 600); | ||
| 510 | } | ||
| 506 | return count; | 511 | return count; |
| 507 | } | 512 | } |
| 508 | 513 | ||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4a78a773151c..bbdbe4721573 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -61,7 +61,7 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state, | |||
| 61 | struct drm_crtc_state *crtc_state; | 61 | struct drm_crtc_state *crtc_state; |
| 62 | 62 | ||
| 63 | if (plane->state->crtc) { | 63 | if (plane->state->crtc) { |
| 64 | crtc_state = state->crtc_states[drm_crtc_index(plane->crtc)]; | 64 | crtc_state = state->crtc_states[drm_crtc_index(plane->state->crtc)]; |
| 65 | 65 | ||
| 66 | if (WARN_ON(!crtc_state)) | 66 | if (WARN_ON(!crtc_state)) |
| 67 | return; | 67 | return; |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 52ce26d6b4fb..dc386ebe5193 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
| @@ -145,6 +145,31 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_ | |||
| 145 | } | 145 | } |
| 146 | EXPORT_SYMBOL(drm_fb_helper_add_one_connector); | 146 | EXPORT_SYMBOL(drm_fb_helper_add_one_connector); |
| 147 | 147 | ||
| 148 | static void remove_from_modeset(struct drm_mode_set *set, | ||
| 149 | struct drm_connector *connector) | ||
| 150 | { | ||
| 151 | int i, j; | ||
| 152 | |||
| 153 | for (i = 0; i < set->num_connectors; i++) { | ||
| 154 | if (set->connectors[i] == connector) | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | |||
| 158 | if (i == set->num_connectors) | ||
| 159 | return; | ||
| 160 | |||
| 161 | for (j = i + 1; j < set->num_connectors; j++) { | ||
| 162 | set->connectors[j - 1] = set->connectors[j]; | ||
| 163 | } | ||
| 164 | set->num_connectors--; | ||
| 165 | |||
| 166 | /* because i915 is pissy about this.. | ||
| 167 | * TODO maybe need to makes sure we set it back to !=NULL somewhere? | ||
| 168 | */ | ||
| 169 | if (set->num_connectors == 0) | ||
| 170 | set->fb = NULL; | ||
| 171 | } | ||
| 172 | |||
| 148 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, | 173 | int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, |
| 149 | struct drm_connector *connector) | 174 | struct drm_connector *connector) |
| 150 | { | 175 | { |
| @@ -167,6 +192,11 @@ int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper, | |||
| 167 | } | 192 | } |
| 168 | fb_helper->connector_count--; | 193 | fb_helper->connector_count--; |
| 169 | kfree(fb_helper_connector); | 194 | kfree(fb_helper_connector); |
| 195 | |||
| 196 | /* also cleanup dangling references to the connector: */ | ||
| 197 | for (i = 0; i < fb_helper->crtc_count; i++) | ||
| 198 | remove_from_modeset(&fb_helper->crtc_info[i].mode_set, connector); | ||
| 199 | |||
| 170 | return 0; | 200 | return 0; |
| 171 | } | 201 | } |
| 172 | EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); | 202 | EXPORT_SYMBOL(drm_fb_helper_remove_one_connector); |
| @@ -741,7 +771,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) | |||
| 741 | int i, j, rc = 0; | 771 | int i, j, rc = 0; |
| 742 | int start; | 772 | int start; |
| 743 | 773 | ||
| 744 | drm_modeset_lock_all(dev); | 774 | if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { |
| 775 | return -EBUSY; | ||
| 776 | } | ||
| 745 | if (!drm_fb_helper_is_bound(fb_helper)) { | 777 | if (!drm_fb_helper_is_bound(fb_helper)) { |
| 746 | drm_modeset_unlock_all(dev); | 778 | drm_modeset_unlock_all(dev); |
| 747 | return -EBUSY; | 779 | return -EBUSY; |
| @@ -915,7 +947,9 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, | |||
| 915 | int ret = 0; | 947 | int ret = 0; |
| 916 | int i; | 948 | int i; |
| 917 | 949 | ||
| 918 | drm_modeset_lock_all(dev); | 950 | if (__drm_modeset_lock_all(dev, !!oops_in_progress)) { |
| 951 | return -EBUSY; | ||
| 952 | } | ||
| 919 | if (!drm_fb_helper_is_bound(fb_helper)) { | 953 | if (!drm_fb_helper_is_bound(fb_helper)) { |
| 920 | drm_modeset_unlock_all(dev); | 954 | drm_modeset_unlock_all(dev); |
| 921 | return -EBUSY; | 955 | return -EBUSY; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f5a5f18efa5b..4d79dad9d44f 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -830,6 +830,8 @@ drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, | |||
| 830 | * vblank events since the system was booted, including lost events due to | 830 | * vblank events since the system was booted, including lost events due to |
| 831 | * modesetting activity. | 831 | * modesetting activity. |
| 832 | * | 832 | * |
| 833 | * This is the legacy version of drm_crtc_vblank_count(). | ||
| 834 | * | ||
| 833 | * Returns: | 835 | * Returns: |
| 834 | * The software vblank counter. | 836 | * The software vblank counter. |
| 835 | */ | 837 | */ |
| @@ -844,6 +846,25 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc) | |||
| 844 | EXPORT_SYMBOL(drm_vblank_count); | 846 | EXPORT_SYMBOL(drm_vblank_count); |
| 845 | 847 | ||
| 846 | /** | 848 | /** |
| 849 | * drm_crtc_vblank_count - retrieve "cooked" vblank counter value | ||
| 850 | * @crtc: which counter to retrieve | ||
| 851 | * | ||
| 852 | * Fetches the "cooked" vblank count value that represents the number of | ||
| 853 | * vblank events since the system was booted, including lost events due to | ||
| 854 | * modesetting activity. | ||
| 855 | * | ||
| 856 | * This is the native KMS version of drm_vblank_count(). | ||
| 857 | * | ||
| 858 | * Returns: | ||
| 859 | * The software vblank counter. | ||
| 860 | */ | ||
| 861 | u32 drm_crtc_vblank_count(struct drm_crtc *crtc) | ||
| 862 | { | ||
| 863 | return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); | ||
| 864 | } | ||
| 865 | EXPORT_SYMBOL(drm_crtc_vblank_count); | ||
| 866 | |||
| 867 | /** | ||
| 847 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value | 868 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value |
| 848 | * and the system timestamp corresponding to that vblank counter value. | 869 | * and the system timestamp corresponding to that vblank counter value. |
| 849 | * | 870 | * |
| @@ -904,6 +925,8 @@ static void send_vblank_event(struct drm_device *dev, | |||
| 904 | * | 925 | * |
| 905 | * Updates sequence # and timestamp on event, and sends it to userspace. | 926 | * Updates sequence # and timestamp on event, and sends it to userspace. |
| 906 | * Caller must hold event lock. | 927 | * Caller must hold event lock. |
| 928 | * | ||
| 929 | * This is the legacy version of drm_crtc_send_vblank_event(). | ||
| 907 | */ | 930 | */ |
| 908 | void drm_send_vblank_event(struct drm_device *dev, int crtc, | 931 | void drm_send_vblank_event(struct drm_device *dev, int crtc, |
| 909 | struct drm_pending_vblank_event *e) | 932 | struct drm_pending_vblank_event *e) |
| @@ -923,6 +946,23 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc, | |||
| 923 | EXPORT_SYMBOL(drm_send_vblank_event); | 946 | EXPORT_SYMBOL(drm_send_vblank_event); |
| 924 | 947 | ||
| 925 | /** | 948 | /** |
| 949 | * drm_crtc_send_vblank_event - helper to send vblank event after pageflip | ||
| 950 | * @crtc: the source CRTC of the vblank event | ||
| 951 | * @e: the event to send | ||
| 952 | * | ||
| 953 | * Updates sequence # and timestamp on event, and sends it to userspace. | ||
| 954 | * Caller must hold event lock. | ||
| 955 | * | ||
| 956 | * This is the native KMS version of drm_send_vblank_event(). | ||
| 957 | */ | ||
| 958 | void drm_crtc_send_vblank_event(struct drm_crtc *crtc, | ||
| 959 | struct drm_pending_vblank_event *e) | ||
| 960 | { | ||
| 961 | drm_send_vblank_event(crtc->dev, drm_crtc_index(crtc), e); | ||
| 962 | } | ||
| 963 | EXPORT_SYMBOL(drm_crtc_send_vblank_event); | ||
| 964 | |||
| 965 | /** | ||
| 926 | * drm_vblank_enable - enable the vblank interrupt on a CRTC | 966 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
| 927 | * @dev: DRM device | 967 | * @dev: DRM device |
| 928 | * @crtc: CRTC in question | 968 | * @crtc: CRTC in question |
| @@ -1594,6 +1634,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, int crtc) | |||
| 1594 | * | 1634 | * |
| 1595 | * Drivers should call this routine in their vblank interrupt handlers to | 1635 | * Drivers should call this routine in their vblank interrupt handlers to |
| 1596 | * update the vblank counter and send any signals that may be pending. | 1636 | * update the vblank counter and send any signals that may be pending. |
| 1637 | * | ||
| 1638 | * This is the legacy version of drm_crtc_handle_vblank(). | ||
| 1597 | */ | 1639 | */ |
| 1598 | bool drm_handle_vblank(struct drm_device *dev, int crtc) | 1640 | bool drm_handle_vblank(struct drm_device *dev, int crtc) |
| 1599 | { | 1641 | { |
| @@ -1670,3 +1712,21 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 1670 | return true; | 1712 | return true; |
| 1671 | } | 1713 | } |
| 1672 | EXPORT_SYMBOL(drm_handle_vblank); | 1714 | EXPORT_SYMBOL(drm_handle_vblank); |
| 1715 | |||
| 1716 | /** | ||
| 1717 | * drm_crtc_handle_vblank - handle a vblank event | ||
| 1718 | * @crtc: where this event occurred | ||
| 1719 | * | ||
| 1720 | * Drivers should call this routine in their vblank interrupt handlers to | ||
| 1721 | * update the vblank counter and send any signals that may be pending. | ||
| 1722 | * | ||
| 1723 | * This is the native KMS version of drm_handle_vblank(). | ||
| 1724 | * | ||
| 1725 | * Returns: | ||
| 1726 | * True if the event was successfully handled, false on failure. | ||
| 1727 | */ | ||
| 1728 | bool drm_crtc_handle_vblank(struct drm_crtc *crtc) | ||
| 1729 | { | ||
| 1730 | return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); | ||
| 1731 | } | ||
| 1732 | EXPORT_SYMBOL(drm_crtc_handle_vblank); | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 121470a83d1a..1bcbe07cecfc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c | |||
| @@ -645,18 +645,6 @@ static int exynos_drm_init(void) | |||
| 645 | if (!is_exynos) | 645 | if (!is_exynos) |
| 646 | return -ENODEV; | 646 | return -ENODEV; |
| 647 | 647 | ||
| 648 | /* | ||
| 649 | * Register device object only in case of Exynos SoC. | ||
| 650 | * | ||
| 651 | * Below codes resolves temporarily infinite loop issue incurred | ||
| 652 | * by Exynos drm driver when using multi-platform kernel. | ||
| 653 | * So these codes will be replaced with more generic way later. | ||
| 654 | */ | ||
| 655 | if (!of_machine_is_compatible("samsung,exynos3") && | ||
| 656 | !of_machine_is_compatible("samsung,exynos4") && | ||
| 657 | !of_machine_is_compatible("samsung,exynos5")) | ||
| 658 | return -ENODEV; | ||
| 659 | |||
| 660 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, | 648 | exynos_drm_pdev = platform_device_register_simple("exynos-drm", -1, |
| 661 | NULL, 0); | 649 | NULL, 0); |
| 662 | if (IS_ERR(exynos_drm_pdev)) | 650 | if (IS_ERR(exynos_drm_pdev)) |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 5765a161abdd..98051e8e855a 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
| @@ -1669,7 +1669,6 @@ static void hdmi_mode_apply(struct hdmi_context *hdata) | |||
| 1669 | 1669 | ||
| 1670 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) | 1670 | static void hdmiphy_conf_reset(struct hdmi_context *hdata) |
| 1671 | { | 1671 | { |
| 1672 | u8 buffer[2]; | ||
| 1673 | u32 reg; | 1672 | u32 reg; |
| 1674 | 1673 | ||
| 1675 | clk_disable_unprepare(hdata->res.sclk_hdmi); | 1674 | clk_disable_unprepare(hdata->res.sclk_hdmi); |
| @@ -1677,11 +1676,8 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
| 1677 | clk_prepare_enable(hdata->res.sclk_hdmi); | 1676 | clk_prepare_enable(hdata->res.sclk_hdmi); |
| 1678 | 1677 | ||
| 1679 | /* operation mode */ | 1678 | /* operation mode */ |
| 1680 | buffer[0] = 0x1f; | 1679 | hdmiphy_reg_writeb(hdata, HDMIPHY_MODE_SET_DONE, |
| 1681 | buffer[1] = 0x00; | 1680 | HDMI_PHY_ENABLE_MODE_SET); |
| 1682 | |||
| 1683 | if (hdata->hdmiphy_port) | ||
| 1684 | i2c_master_send(hdata->hdmiphy_port, buffer, 2); | ||
| 1685 | 1681 | ||
| 1686 | if (hdata->type == HDMI_TYPE13) | 1682 | if (hdata->type == HDMI_TYPE13) |
| 1687 | reg = HDMI_V13_PHY_RSTOUT; | 1683 | reg = HDMI_V13_PHY_RSTOUT; |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 820b76234ef4..064ed6597def 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
| @@ -1026,6 +1026,7 @@ static void mixer_win_disable(struct exynos_drm_manager *mgr, int zpos) | |||
| 1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | 1026 | static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) |
| 1027 | { | 1027 | { |
| 1028 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); | 1028 | struct mixer_context *mixer_ctx = mgr_to_mixer(mgr); |
| 1029 | int err; | ||
| 1029 | 1030 | ||
| 1030 | mutex_lock(&mixer_ctx->mixer_mutex); | 1031 | mutex_lock(&mixer_ctx->mixer_mutex); |
| 1031 | if (!mixer_ctx->powered) { | 1032 | if (!mixer_ctx->powered) { |
| @@ -1034,7 +1035,11 @@ static void mixer_wait_for_vblank(struct exynos_drm_manager *mgr) | |||
| 1034 | } | 1035 | } |
| 1035 | mutex_unlock(&mixer_ctx->mixer_mutex); | 1036 | mutex_unlock(&mixer_ctx->mixer_mutex); |
| 1036 | 1037 | ||
| 1037 | drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); | 1038 | err = drm_vblank_get(mgr->crtc->dev, mixer_ctx->pipe); |
| 1039 | if (err < 0) { | ||
| 1040 | DRM_DEBUG_KMS("failed to acquire vblank counter\n"); | ||
| 1041 | return; | ||
| 1042 | } | ||
| 1038 | 1043 | ||
| 1039 | atomic_set(&mixer_ctx->wait_vsync_event, 1); | 1044 | atomic_set(&mixer_ctx->wait_vsync_event, 1); |
| 1040 | 1045 | ||
| @@ -1262,8 +1267,6 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data) | |||
| 1262 | return ret; | 1267 | return ret; |
| 1263 | } | 1268 | } |
| 1264 | 1269 | ||
| 1265 | pm_runtime_enable(dev); | ||
| 1266 | |||
| 1267 | return 0; | 1270 | return 0; |
| 1268 | } | 1271 | } |
| 1269 | 1272 | ||
| @@ -1272,8 +1275,6 @@ static void mixer_unbind(struct device *dev, struct device *master, void *data) | |||
| 1272 | struct mixer_context *ctx = dev_get_drvdata(dev); | 1275 | struct mixer_context *ctx = dev_get_drvdata(dev); |
| 1273 | 1276 | ||
| 1274 | mixer_mgr_remove(&ctx->manager); | 1277 | mixer_mgr_remove(&ctx->manager); |
| 1275 | |||
| 1276 | pm_runtime_disable(dev); | ||
| 1277 | } | 1278 | } |
| 1278 | 1279 | ||
| 1279 | static const struct component_ops mixer_component_ops = { | 1280 | static const struct component_ops mixer_component_ops = { |
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index d4762799351d..a9041d1a8ff0 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c | |||
| @@ -32,6 +32,8 @@ | |||
| 32 | struct tda998x_priv { | 32 | struct tda998x_priv { |
| 33 | struct i2c_client *cec; | 33 | struct i2c_client *cec; |
| 34 | struct i2c_client *hdmi; | 34 | struct i2c_client *hdmi; |
| 35 | struct mutex mutex; | ||
| 36 | struct delayed_work dwork; | ||
| 35 | uint16_t rev; | 37 | uint16_t rev; |
| 36 | uint8_t current_page; | 38 | uint8_t current_page; |
| 37 | int dpms; | 39 | int dpms; |
| @@ -402,9 +404,10 @@ reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt) | |||
| 402 | uint8_t addr = REG2ADDR(reg); | 404 | uint8_t addr = REG2ADDR(reg); |
| 403 | int ret; | 405 | int ret; |
| 404 | 406 | ||
| 407 | mutex_lock(&priv->mutex); | ||
| 405 | ret = set_page(priv, reg); | 408 | ret = set_page(priv, reg); |
| 406 | if (ret < 0) | 409 | if (ret < 0) |
| 407 | return ret; | 410 | goto out; |
| 408 | 411 | ||
| 409 | ret = i2c_master_send(client, &addr, sizeof(addr)); | 412 | ret = i2c_master_send(client, &addr, sizeof(addr)); |
| 410 | if (ret < 0) | 413 | if (ret < 0) |
| @@ -414,10 +417,12 @@ reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt) | |||
| 414 | if (ret < 0) | 417 | if (ret < 0) |
| 415 | goto fail; | 418 | goto fail; |
| 416 | 419 | ||
| 417 | return ret; | 420 | goto out; |
| 418 | 421 | ||
| 419 | fail: | 422 | fail: |
| 420 | dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg); | 423 | dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg); |
| 424 | out: | ||
| 425 | mutex_unlock(&priv->mutex); | ||
| 421 | return ret; | 426 | return ret; |
| 422 | } | 427 | } |
| 423 | 428 | ||
| @@ -431,13 +436,16 @@ reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt) | |||
| 431 | buf[0] = REG2ADDR(reg); | 436 | buf[0] = REG2ADDR(reg); |
| 432 | memcpy(&buf[1], p, cnt); | 437 | memcpy(&buf[1], p, cnt); |
| 433 | 438 | ||
| 439 | mutex_lock(&priv->mutex); | ||
| 434 | ret = set_page(priv, reg); | 440 | ret = set_page(priv, reg); |
| 435 | if (ret < 0) | 441 | if (ret < 0) |
| 436 | return; | 442 | goto out; |
| 437 | 443 | ||
| 438 | ret = i2c_master_send(client, buf, cnt + 1); | 444 | ret = i2c_master_send(client, buf, cnt + 1); |
| 439 | if (ret < 0) | 445 | if (ret < 0) |
| 440 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); | 446 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); |
| 447 | out: | ||
| 448 | mutex_unlock(&priv->mutex); | ||
| 441 | } | 449 | } |
| 442 | 450 | ||
| 443 | static int | 451 | static int |
| @@ -459,13 +467,16 @@ reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val) | |||
| 459 | uint8_t buf[] = {REG2ADDR(reg), val}; | 467 | uint8_t buf[] = {REG2ADDR(reg), val}; |
| 460 | int ret; | 468 | int ret; |
| 461 | 469 | ||
| 470 | mutex_lock(&priv->mutex); | ||
| 462 | ret = set_page(priv, reg); | 471 | ret = set_page(priv, reg); |
| 463 | if (ret < 0) | 472 | if (ret < 0) |
| 464 | return; | 473 | goto out; |
| 465 | 474 | ||
| 466 | ret = i2c_master_send(client, buf, sizeof(buf)); | 475 | ret = i2c_master_send(client, buf, sizeof(buf)); |
| 467 | if (ret < 0) | 476 | if (ret < 0) |
| 468 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); | 477 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); |
| 478 | out: | ||
| 479 | mutex_unlock(&priv->mutex); | ||
| 469 | } | 480 | } |
| 470 | 481 | ||
| 471 | static void | 482 | static void |
| @@ -475,13 +486,16 @@ reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val) | |||
| 475 | uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; | 486 | uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; |
| 476 | int ret; | 487 | int ret; |
| 477 | 488 | ||
| 489 | mutex_lock(&priv->mutex); | ||
| 478 | ret = set_page(priv, reg); | 490 | ret = set_page(priv, reg); |
| 479 | if (ret < 0) | 491 | if (ret < 0) |
| 480 | return; | 492 | goto out; |
| 481 | 493 | ||
| 482 | ret = i2c_master_send(client, buf, sizeof(buf)); | 494 | ret = i2c_master_send(client, buf, sizeof(buf)); |
| 483 | if (ret < 0) | 495 | if (ret < 0) |
| 484 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); | 496 | dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); |
| 497 | out: | ||
| 498 | mutex_unlock(&priv->mutex); | ||
| 485 | } | 499 | } |
| 486 | 500 | ||
| 487 | static void | 501 | static void |
| @@ -536,6 +550,17 @@ tda998x_reset(struct tda998x_priv *priv) | |||
| 536 | reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24); | 550 | reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24); |
| 537 | } | 551 | } |
| 538 | 552 | ||
| 553 | /* handle HDMI connect/disconnect */ | ||
| 554 | static void tda998x_hpd(struct work_struct *work) | ||
| 555 | { | ||
| 556 | struct delayed_work *dwork = to_delayed_work(work); | ||
| 557 | struct tda998x_priv *priv = | ||
| 558 | container_of(dwork, struct tda998x_priv, dwork); | ||
| 559 | |||
| 560 | if (priv->encoder && priv->encoder->dev) | ||
| 561 | drm_kms_helper_hotplug_event(priv->encoder->dev); | ||
| 562 | } | ||
| 563 | |||
| 539 | /* | 564 | /* |
| 540 | * only 2 interrupts may occur: screen plug/unplug and EDID read | 565 | * only 2 interrupts may occur: screen plug/unplug and EDID read |
| 541 | */ | 566 | */ |
| @@ -559,8 +584,7 @@ static irqreturn_t tda998x_irq_thread(int irq, void *data) | |||
| 559 | priv->wq_edid_wait = 0; | 584 | priv->wq_edid_wait = 0; |
| 560 | wake_up(&priv->wq_edid); | 585 | wake_up(&priv->wq_edid); |
| 561 | } else if (cec != 0) { /* HPD change */ | 586 | } else if (cec != 0) { /* HPD change */ |
| 562 | if (priv->encoder && priv->encoder->dev) | 587 | schedule_delayed_work(&priv->dwork, HZ/10); |
| 563 | drm_helper_hpd_irq_event(priv->encoder->dev); | ||
| 564 | } | 588 | } |
| 565 | return IRQ_HANDLED; | 589 | return IRQ_HANDLED; |
| 566 | } | 590 | } |
| @@ -1170,8 +1194,10 @@ static void tda998x_destroy(struct tda998x_priv *priv) | |||
| 1170 | /* disable all IRQs and free the IRQ handler */ | 1194 | /* disable all IRQs and free the IRQ handler */ |
| 1171 | cec_write(priv, REG_CEC_RXSHPDINTENA, 0); | 1195 | cec_write(priv, REG_CEC_RXSHPDINTENA, 0); |
| 1172 | reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); | 1196 | reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); |
| 1173 | if (priv->hdmi->irq) | 1197 | if (priv->hdmi->irq) { |
| 1174 | free_irq(priv->hdmi->irq, priv); | 1198 | free_irq(priv->hdmi->irq, priv); |
| 1199 | cancel_delayed_work_sync(&priv->dwork); | ||
| 1200 | } | ||
| 1175 | 1201 | ||
| 1176 | i2c_unregister_device(priv->cec); | 1202 | i2c_unregister_device(priv->cec); |
| 1177 | } | 1203 | } |
| @@ -1255,6 +1281,7 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) | |||
| 1255 | struct device_node *np = client->dev.of_node; | 1281 | struct device_node *np = client->dev.of_node; |
| 1256 | u32 video; | 1282 | u32 video; |
| 1257 | int rev_lo, rev_hi, ret; | 1283 | int rev_lo, rev_hi, ret; |
| 1284 | unsigned short cec_addr; | ||
| 1258 | 1285 | ||
| 1259 | priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); | 1286 | priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); |
| 1260 | priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); | 1287 | priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); |
| @@ -1262,12 +1289,16 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) | |||
| 1262 | 1289 | ||
| 1263 | priv->current_page = 0xff; | 1290 | priv->current_page = 0xff; |
| 1264 | priv->hdmi = client; | 1291 | priv->hdmi = client; |
| 1265 | priv->cec = i2c_new_dummy(client->adapter, 0x34); | 1292 | /* CEC I2C address bound to TDA998x I2C addr by configuration pins */ |
| 1293 | cec_addr = 0x34 + (client->addr & 0x03); | ||
| 1294 | priv->cec = i2c_new_dummy(client->adapter, cec_addr); | ||
| 1266 | if (!priv->cec) | 1295 | if (!priv->cec) |
| 1267 | return -ENODEV; | 1296 | return -ENODEV; |
| 1268 | 1297 | ||
| 1269 | priv->dpms = DRM_MODE_DPMS_OFF; | 1298 | priv->dpms = DRM_MODE_DPMS_OFF; |
| 1270 | 1299 | ||
| 1300 | mutex_init(&priv->mutex); /* protect the page access */ | ||
| 1301 | |||
| 1271 | /* wake up the device: */ | 1302 | /* wake up the device: */ |
| 1272 | cec_write(priv, REG_CEC_ENAMODS, | 1303 | cec_write(priv, REG_CEC_ENAMODS, |
| 1273 | CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI); | 1304 | CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI); |
| @@ -1323,8 +1354,9 @@ static int tda998x_create(struct i2c_client *client, struct tda998x_priv *priv) | |||
| 1323 | if (client->irq) { | 1354 | if (client->irq) { |
| 1324 | int irqf_trigger; | 1355 | int irqf_trigger; |
| 1325 | 1356 | ||
| 1326 | /* init read EDID waitqueue */ | 1357 | /* init read EDID waitqueue and HDP work */ |
| 1327 | init_waitqueue_head(&priv->wq_edid); | 1358 | init_waitqueue_head(&priv->wq_edid); |
| 1359 | INIT_DELAYED_WORK(&priv->dwork, tda998x_hpd); | ||
| 1328 | 1360 | ||
| 1329 | /* clear pending interrupts */ | 1361 | /* clear pending interrupts */ |
| 1330 | reg_read(priv, REG_INT_FLAGS_0); | 1362 | reg_read(priv, REG_INT_FLAGS_0); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f990ab4c3efb..7643300828c3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -462,19 +462,13 @@ void intel_detect_pch(struct drm_device *dev) | |||
| 462 | } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { | 462 | } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { |
| 463 | dev_priv->pch_type = PCH_LPT; | 463 | dev_priv->pch_type = PCH_LPT; |
| 464 | DRM_DEBUG_KMS("Found LynxPoint PCH\n"); | 464 | DRM_DEBUG_KMS("Found LynxPoint PCH\n"); |
| 465 | WARN_ON(!IS_HASWELL(dev)); | 465 | WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); |
| 466 | WARN_ON(IS_HSW_ULT(dev)); | 466 | WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev)); |
| 467 | } else if (IS_BROADWELL(dev)) { | ||
| 468 | dev_priv->pch_type = PCH_LPT; | ||
| 469 | dev_priv->pch_id = | ||
| 470 | INTEL_PCH_LPT_LP_DEVICE_ID_TYPE; | ||
| 471 | DRM_DEBUG_KMS("This is Broadwell, assuming " | ||
| 472 | "LynxPoint LP PCH\n"); | ||
| 473 | } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { | 467 | } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { |
| 474 | dev_priv->pch_type = PCH_LPT; | 468 | dev_priv->pch_type = PCH_LPT; |
| 475 | DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); | 469 | DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); |
| 476 | WARN_ON(!IS_HASWELL(dev)); | 470 | WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); |
| 477 | WARN_ON(!IS_HSW_ULT(dev)); | 471 | WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev)); |
| 478 | } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { | 472 | } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { |
| 479 | dev_priv->pch_type = PCH_SPT; | 473 | dev_priv->pch_type = PCH_SPT; |
| 480 | DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); | 474 | DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); |
| @@ -811,6 +805,8 @@ int i915_reset(struct drm_device *dev) | |||
| 811 | if (!i915.reset) | 805 | if (!i915.reset) |
| 812 | return 0; | 806 | return 0; |
| 813 | 807 | ||
| 808 | intel_reset_gt_powersave(dev); | ||
| 809 | |||
| 814 | mutex_lock(&dev->struct_mutex); | 810 | mutex_lock(&dev->struct_mutex); |
| 815 | 811 | ||
| 816 | i915_gem_reset(dev); | 812 | i915_gem_reset(dev); |
| @@ -880,7 +876,7 @@ int i915_reset(struct drm_device *dev) | |||
| 880 | * of re-init after reset. | 876 | * of re-init after reset. |
| 881 | */ | 877 | */ |
| 882 | if (INTEL_INFO(dev)->gen > 5) | 878 | if (INTEL_INFO(dev)->gen > 5) |
| 883 | intel_reset_gt_powersave(dev); | 879 | intel_enable_gt_powersave(dev); |
| 884 | } else { | 880 | } else { |
| 885 | mutex_unlock(&dev->struct_mutex); | 881 | mutex_unlock(&dev->struct_mutex); |
| 886 | } | 882 | } |
| @@ -1584,7 +1580,7 @@ static struct drm_driver driver = { | |||
| 1584 | .gem_prime_import = i915_gem_prime_import, | 1580 | .gem_prime_import = i915_gem_prime_import, |
| 1585 | 1581 | ||
| 1586 | .dumb_create = i915_gem_dumb_create, | 1582 | .dumb_create = i915_gem_dumb_create, |
| 1587 | .dumb_map_offset = i915_gem_dumb_map_offset, | 1583 | .dumb_map_offset = i915_gem_mmap_gtt, |
| 1588 | .dumb_destroy = drm_gem_dumb_destroy, | 1584 | .dumb_destroy = drm_gem_dumb_destroy, |
| 1589 | .ioctls = i915_ioctls, | 1585 | .ioctls = i915_ioctls, |
| 1590 | .fops = &i915_driver_fops, | 1586 | .fops = &i915_driver_fops, |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 63bcda5541ec..9d7a7155bf02 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -1756,8 +1756,6 @@ struct drm_i915_private { | |||
| 1756 | */ | 1756 | */ |
| 1757 | struct workqueue_struct *dp_wq; | 1757 | struct workqueue_struct *dp_wq; |
| 1758 | 1758 | ||
| 1759 | uint32_t bios_vgacntr; | ||
| 1760 | |||
| 1761 | /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ | 1759 | /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ |
| 1762 | struct { | 1760 | struct { |
| 1763 | int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, | 1761 | int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, |
| @@ -2161,8 +2159,7 @@ struct drm_i915_cmd_table { | |||
| 2161 | #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ | 2159 | #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ |
| 2162 | (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) | 2160 | (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) |
| 2163 | #define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ | 2161 | #define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ |
| 2164 | ((INTEL_DEVID(dev) & 0xf) == 0x2 || \ | 2162 | ((INTEL_DEVID(dev) & 0xf) == 0x6 || \ |
| 2165 | (INTEL_DEVID(dev) & 0xf) == 0x6 || \ | ||
| 2166 | (INTEL_DEVID(dev) & 0xf) == 0xe)) | 2163 | (INTEL_DEVID(dev) & 0xf) == 0xe)) |
| 2167 | #define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ | 2164 | #define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ |
| 2168 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) | 2165 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) |
| @@ -2501,9 +2498,8 @@ void i915_vma_move_to_active(struct i915_vma *vma, | |||
| 2501 | int i915_gem_dumb_create(struct drm_file *file_priv, | 2498 | int i915_gem_dumb_create(struct drm_file *file_priv, |
| 2502 | struct drm_device *dev, | 2499 | struct drm_device *dev, |
| 2503 | struct drm_mode_create_dumb *args); | 2500 | struct drm_mode_create_dumb *args); |
| 2504 | int i915_gem_dumb_map_offset(struct drm_file *file_priv, | 2501 | int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev, |
| 2505 | struct drm_device *dev, uint32_t handle, | 2502 | uint32_t handle, uint64_t *offset); |
| 2506 | uint64_t *offset); | ||
| 2507 | /** | 2503 | /** |
| 2508 | * Returns true if seq1 is later than seq2. | 2504 | * Returns true if seq1 is later than seq2. |
| 2509 | */ | 2505 | */ |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4a9faea626db..5f614828d365 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -401,7 +401,6 @@ static int | |||
| 401 | i915_gem_create(struct drm_file *file, | 401 | i915_gem_create(struct drm_file *file, |
| 402 | struct drm_device *dev, | 402 | struct drm_device *dev, |
| 403 | uint64_t size, | 403 | uint64_t size, |
| 404 | bool dumb, | ||
| 405 | uint32_t *handle_p) | 404 | uint32_t *handle_p) |
| 406 | { | 405 | { |
| 407 | struct drm_i915_gem_object *obj; | 406 | struct drm_i915_gem_object *obj; |
| @@ -417,7 +416,6 @@ i915_gem_create(struct drm_file *file, | |||
| 417 | if (obj == NULL) | 416 | if (obj == NULL) |
| 418 | return -ENOMEM; | 417 | return -ENOMEM; |
| 419 | 418 | ||
| 420 | obj->base.dumb = dumb; | ||
| 421 | ret = drm_gem_handle_create(file, &obj->base, &handle); | 419 | ret = drm_gem_handle_create(file, &obj->base, &handle); |
| 422 | /* drop reference from allocate - handle holds it now */ | 420 | /* drop reference from allocate - handle holds it now */ |
| 423 | drm_gem_object_unreference_unlocked(&obj->base); | 421 | drm_gem_object_unreference_unlocked(&obj->base); |
| @@ -437,7 +435,7 @@ i915_gem_dumb_create(struct drm_file *file, | |||
| 437 | args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); | 435 | args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); |
| 438 | args->size = args->pitch * args->height; | 436 | args->size = args->pitch * args->height; |
| 439 | return i915_gem_create(file, dev, | 437 | return i915_gem_create(file, dev, |
| 440 | args->size, true, &args->handle); | 438 | args->size, &args->handle); |
| 441 | } | 439 | } |
| 442 | 440 | ||
| 443 | /** | 441 | /** |
| @@ -450,7 +448,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, | |||
| 450 | struct drm_i915_gem_create *args = data; | 448 | struct drm_i915_gem_create *args = data; |
| 451 | 449 | ||
| 452 | return i915_gem_create(file, dev, | 450 | return i915_gem_create(file, dev, |
| 453 | args->size, false, &args->handle); | 451 | args->size, &args->handle); |
| 454 | } | 452 | } |
| 455 | 453 | ||
| 456 | static inline int | 454 | static inline int |
| @@ -1050,6 +1048,7 @@ int | |||
| 1050 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | 1048 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, |
| 1051 | struct drm_file *file) | 1049 | struct drm_file *file) |
| 1052 | { | 1050 | { |
| 1051 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1053 | struct drm_i915_gem_pwrite *args = data; | 1052 | struct drm_i915_gem_pwrite *args = data; |
| 1054 | struct drm_i915_gem_object *obj; | 1053 | struct drm_i915_gem_object *obj; |
| 1055 | int ret; | 1054 | int ret; |
| @@ -1069,9 +1068,11 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 1069 | return -EFAULT; | 1068 | return -EFAULT; |
| 1070 | } | 1069 | } |
| 1071 | 1070 | ||
| 1071 | intel_runtime_pm_get(dev_priv); | ||
| 1072 | |||
| 1072 | ret = i915_mutex_lock_interruptible(dev); | 1073 | ret = i915_mutex_lock_interruptible(dev); |
| 1073 | if (ret) | 1074 | if (ret) |
| 1074 | return ret; | 1075 | goto put_rpm; |
| 1075 | 1076 | ||
| 1076 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); | 1077 | obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); |
| 1077 | if (&obj->base == NULL) { | 1078 | if (&obj->base == NULL) { |
| @@ -1123,6 +1124,9 @@ out: | |||
| 1123 | drm_gem_object_unreference(&obj->base); | 1124 | drm_gem_object_unreference(&obj->base); |
| 1124 | unlock: | 1125 | unlock: |
| 1125 | mutex_unlock(&dev->struct_mutex); | 1126 | mutex_unlock(&dev->struct_mutex); |
| 1127 | put_rpm: | ||
| 1128 | intel_runtime_pm_put(dev_priv); | ||
| 1129 | |||
| 1126 | return ret; | 1130 | return ret; |
| 1127 | } | 1131 | } |
| 1128 | 1132 | ||
| @@ -1840,10 +1844,10 @@ static void i915_gem_object_free_mmap_offset(struct drm_i915_gem_object *obj) | |||
| 1840 | drm_gem_free_mmap_offset(&obj->base); | 1844 | drm_gem_free_mmap_offset(&obj->base); |
| 1841 | } | 1845 | } |
| 1842 | 1846 | ||
| 1843 | static int | 1847 | int |
| 1844 | i915_gem_mmap_gtt(struct drm_file *file, | 1848 | i915_gem_mmap_gtt(struct drm_file *file, |
| 1845 | struct drm_device *dev, | 1849 | struct drm_device *dev, |
| 1846 | uint32_t handle, bool dumb, | 1850 | uint32_t handle, |
| 1847 | uint64_t *offset) | 1851 | uint64_t *offset) |
| 1848 | { | 1852 | { |
| 1849 | struct drm_i915_private *dev_priv = dev->dev_private; | 1853 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -1860,13 +1864,6 @@ i915_gem_mmap_gtt(struct drm_file *file, | |||
| 1860 | goto unlock; | 1864 | goto unlock; |
| 1861 | } | 1865 | } |
| 1862 | 1866 | ||
| 1863 | /* | ||
| 1864 | * We don't allow dumb mmaps on objects created using another | ||
| 1865 | * interface. | ||
| 1866 | */ | ||
| 1867 | WARN_ONCE(dumb && !(obj->base.dumb || obj->base.import_attach), | ||
| 1868 | "Illegal dumb map of accelerated buffer.\n"); | ||
| 1869 | |||
| 1870 | if (obj->base.size > dev_priv->gtt.mappable_end) { | 1867 | if (obj->base.size > dev_priv->gtt.mappable_end) { |
| 1871 | ret = -E2BIG; | 1868 | ret = -E2BIG; |
| 1872 | goto out; | 1869 | goto out; |
| @@ -1891,15 +1888,6 @@ unlock: | |||
| 1891 | return ret; | 1888 | return ret; |
| 1892 | } | 1889 | } |
| 1893 | 1890 | ||
| 1894 | int | ||
| 1895 | i915_gem_dumb_map_offset(struct drm_file *file, | ||
| 1896 | struct drm_device *dev, | ||
| 1897 | uint32_t handle, | ||
| 1898 | uint64_t *offset) | ||
| 1899 | { | ||
| 1900 | return i915_gem_mmap_gtt(file, dev, handle, true, offset); | ||
| 1901 | } | ||
| 1902 | |||
| 1903 | /** | 1891 | /** |
| 1904 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing | 1892 | * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing |
| 1905 | * @dev: DRM device | 1893 | * @dev: DRM device |
| @@ -1921,7 +1909,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
| 1921 | { | 1909 | { |
| 1922 | struct drm_i915_gem_mmap_gtt *args = data; | 1910 | struct drm_i915_gem_mmap_gtt *args = data; |
| 1923 | 1911 | ||
| 1924 | return i915_gem_mmap_gtt(file, dev, args->handle, false, &args->offset); | 1912 | return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); |
| 1925 | } | 1913 | } |
| 1926 | 1914 | ||
| 1927 | static inline int | 1915 | static inline int |
| @@ -3160,6 +3148,13 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, | |||
| 3160 | u32 size = i915_gem_obj_ggtt_size(obj); | 3148 | u32 size = i915_gem_obj_ggtt_size(obj); |
| 3161 | uint64_t val; | 3149 | uint64_t val; |
| 3162 | 3150 | ||
| 3151 | /* Adjust fence size to match tiled area */ | ||
| 3152 | if (obj->tiling_mode != I915_TILING_NONE) { | ||
| 3153 | uint32_t row_size = obj->stride * | ||
| 3154 | (obj->tiling_mode == I915_TILING_Y ? 32 : 8); | ||
| 3155 | size = (size / row_size) * row_size; | ||
| 3156 | } | ||
| 3157 | |||
| 3163 | val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & | 3158 | val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & |
| 3164 | 0xfffff000) << 32; | 3159 | 0xfffff000) << 32; |
| 3165 | val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; | 3160 | val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; |
| @@ -4896,25 +4891,18 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 4896 | for (i = 0; i < NUM_L3_SLICES(dev); i++) | 4891 | for (i = 0; i < NUM_L3_SLICES(dev); i++) |
| 4897 | i915_gem_l3_remap(&dev_priv->ring[RCS], i); | 4892 | i915_gem_l3_remap(&dev_priv->ring[RCS], i); |
| 4898 | 4893 | ||
| 4899 | /* | 4894 | ret = i915_ppgtt_init_hw(dev); |
| 4900 | * XXX: Contexts should only be initialized once. Doing a switch to the | ||
| 4901 | * default context switch however is something we'd like to do after | ||
| 4902 | * reset or thaw (the latter may not actually be necessary for HW, but | ||
| 4903 | * goes with our code better). Context switching requires rings (for | ||
| 4904 | * the do_switch), but before enabling PPGTT. So don't move this. | ||
| 4905 | */ | ||
| 4906 | ret = i915_gem_context_enable(dev_priv); | ||
| 4907 | if (ret && ret != -EIO) { | 4895 | if (ret && ret != -EIO) { |
| 4908 | DRM_ERROR("Context enable failed %d\n", ret); | 4896 | DRM_ERROR("PPGTT enable failed %d\n", ret); |
| 4909 | i915_gem_cleanup_ringbuffer(dev); | 4897 | i915_gem_cleanup_ringbuffer(dev); |
| 4910 | |||
| 4911 | return ret; | ||
| 4912 | } | 4898 | } |
| 4913 | 4899 | ||
| 4914 | ret = i915_ppgtt_init_hw(dev); | 4900 | ret = i915_gem_context_enable(dev_priv); |
| 4915 | if (ret && ret != -EIO) { | 4901 | if (ret && ret != -EIO) { |
| 4916 | DRM_ERROR("PPGTT enable failed %d\n", ret); | 4902 | DRM_ERROR("Context enable failed %d\n", ret); |
| 4917 | i915_gem_cleanup_ringbuffer(dev); | 4903 | i915_gem_cleanup_ringbuffer(dev); |
| 4904 | |||
| 4905 | return ret; | ||
| 4918 | } | 4906 | } |
| 4919 | 4907 | ||
| 4920 | return ret; | 4908 | return ret; |
| @@ -5167,7 +5155,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) | |||
| 5167 | if (!mutex_is_locked(mutex)) | 5155 | if (!mutex_is_locked(mutex)) |
| 5168 | return false; | 5156 | return false; |
| 5169 | 5157 | ||
| 5170 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) | 5158 | #if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) |
| 5171 | return mutex->owner == task; | 5159 | return mutex->owner == task; |
| 5172 | #else | 5160 | #else |
| 5173 | /* Since UP may be pre-empted, we cannot assume that we own the lock */ | 5161 | /* Since UP may be pre-empted, we cannot assume that we own the lock */ |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d17ff435f276..d011ec82ef1e 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -473,7 +473,12 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 473 | u32 hw_flags) | 473 | u32 hw_flags) |
| 474 | { | 474 | { |
| 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; | 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; |
| 476 | int ret; | 476 | const int num_rings = |
| 477 | /* Use an extended w/a on ivb+ if signalling from other rings */ | ||
| 478 | i915_semaphore_is_enabled(ring->dev) ? | ||
| 479 | hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : | ||
| 480 | 0; | ||
| 481 | int len, i, ret; | ||
| 477 | 482 | ||
| 478 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB | 483 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB |
| 479 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value | 484 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value |
| @@ -490,15 +495,31 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 490 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) | 495 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) |
| 491 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); | 496 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); |
| 492 | 497 | ||
| 493 | ret = intel_ring_begin(ring, 6); | 498 | |
| 499 | len = 4; | ||
| 500 | if (INTEL_INFO(ring->dev)->gen >= 7) | ||
| 501 | len += 2 + (num_rings ? 4*num_rings + 2 : 0); | ||
| 502 | |||
| 503 | ret = intel_ring_begin(ring, len); | ||
| 494 | if (ret) | 504 | if (ret) |
| 495 | return ret; | 505 | return ret; |
| 496 | 506 | ||
| 497 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ | 507 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ |
| 498 | if (INTEL_INFO(ring->dev)->gen >= 7) | 508 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 499 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); | 509 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); |
| 500 | else | 510 | if (num_rings) { |
| 501 | intel_ring_emit(ring, MI_NOOP); | 511 | struct intel_engine_cs *signaller; |
| 512 | |||
| 513 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 514 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 515 | if (signaller == ring) | ||
| 516 | continue; | ||
| 517 | |||
| 518 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 519 | intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 520 | } | ||
| 521 | } | ||
| 522 | } | ||
| 502 | 523 | ||
| 503 | intel_ring_emit(ring, MI_NOOP); | 524 | intel_ring_emit(ring, MI_NOOP); |
| 504 | intel_ring_emit(ring, MI_SET_CONTEXT); | 525 | intel_ring_emit(ring, MI_SET_CONTEXT); |
| @@ -510,10 +531,21 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 510 | */ | 531 | */ |
| 511 | intel_ring_emit(ring, MI_NOOP); | 532 | intel_ring_emit(ring, MI_NOOP); |
| 512 | 533 | ||
| 513 | if (INTEL_INFO(ring->dev)->gen >= 7) | 534 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 535 | if (num_rings) { | ||
| 536 | struct intel_engine_cs *signaller; | ||
| 537 | |||
| 538 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 539 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 540 | if (signaller == ring) | ||
| 541 | continue; | ||
| 542 | |||
| 543 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 544 | intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 545 | } | ||
| 546 | } | ||
| 514 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); | 547 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); |
| 515 | else | 548 | } |
| 516 | intel_ring_emit(ring, MI_NOOP); | ||
| 517 | 549 | ||
| 518 | intel_ring_advance(ring); | 550 | intel_ring_advance(ring); |
| 519 | 551 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f06027ba3ee5..11738316394a 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -121,9 +121,6 @@ eb_lookup_vmas(struct eb_vmas *eb, | |||
| 121 | goto err; | 121 | goto err; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | WARN_ONCE(obj->base.dumb, | ||
| 125 | "GPU use of dumb buffer is illegal.\n"); | ||
| 126 | |||
| 127 | drm_gem_object_reference(&obj->base); | 124 | drm_gem_object_reference(&obj->base); |
| 128 | list_add_tail(&obj->obj_exec_link, &objects); | 125 | list_add_tail(&obj->obj_exec_link, &objects); |
| 129 | } | 126 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 981834b0f9b6..b051a238baf9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -281,13 +281,34 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
| 281 | struct drm_i915_private *dev_priv = dev->dev_private; | 281 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 282 | 282 | ||
| 283 | spin_lock_irq(&dev_priv->irq_lock); | 283 | spin_lock_irq(&dev_priv->irq_lock); |
| 284 | |||
| 284 | WARN_ON(dev_priv->rps.pm_iir); | 285 | WARN_ON(dev_priv->rps.pm_iir); |
| 285 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | 286 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); |
| 286 | dev_priv->rps.interrupts_enabled = true; | 287 | dev_priv->rps.interrupts_enabled = true; |
| 288 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) | | ||
| 289 | dev_priv->pm_rps_events); | ||
| 287 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 290 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
| 291 | |||
| 288 | spin_unlock_irq(&dev_priv->irq_lock); | 292 | spin_unlock_irq(&dev_priv->irq_lock); |
| 289 | } | 293 | } |
| 290 | 294 | ||
| 295 | u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) | ||
| 296 | { | ||
| 297 | /* | ||
| 298 | * SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer | ||
| 299 | * if GEN6_PM_UP_EI_EXPIRED is masked. | ||
| 300 | * | ||
| 301 | * TODO: verify if this can be reproduced on VLV,CHV. | ||
| 302 | */ | ||
| 303 | if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv)) | ||
| 304 | mask &= ~GEN6_PM_RP_UP_EI_EXPIRED; | ||
| 305 | |||
| 306 | if (INTEL_INFO(dev_priv)->gen >= 8) | ||
| 307 | mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP; | ||
| 308 | |||
| 309 | return mask; | ||
| 310 | } | ||
| 311 | |||
| 291 | void gen6_disable_rps_interrupts(struct drm_device *dev) | 312 | void gen6_disable_rps_interrupts(struct drm_device *dev) |
| 292 | { | 313 | { |
| 293 | struct drm_i915_private *dev_priv = dev->dev_private; | 314 | struct drm_i915_private *dev_priv = dev->dev_private; |
| @@ -300,8 +321,7 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) | |||
| 300 | 321 | ||
| 301 | spin_lock_irq(&dev_priv->irq_lock); | 322 | spin_lock_irq(&dev_priv->irq_lock); |
| 302 | 323 | ||
| 303 | I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ? | 324 | I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); |
| 304 | ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0); | ||
| 305 | 325 | ||
| 306 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 326 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
| 307 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & | 327 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) & |
| @@ -3307,8 +3327,10 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) | |||
| 3307 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); | 3327 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); |
| 3308 | 3328 | ||
| 3309 | if (INTEL_INFO(dev)->gen >= 6) { | 3329 | if (INTEL_INFO(dev)->gen >= 6) { |
| 3310 | pm_irqs |= dev_priv->pm_rps_events; | 3330 | /* |
| 3311 | 3331 | * RPS interrupts will get enabled/disabled on demand when RPS | |
| 3332 | * itself is enabled/disabled. | ||
| 3333 | */ | ||
| 3312 | if (HAS_VEBOX(dev)) | 3334 | if (HAS_VEBOX(dev)) |
| 3313 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; | 3335 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; |
| 3314 | 3336 | ||
| @@ -3520,7 +3542,11 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) | |||
| 3520 | dev_priv->pm_irq_mask = 0xffffffff; | 3542 | dev_priv->pm_irq_mask = 0xffffffff; |
| 3521 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); | 3543 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); |
| 3522 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); | 3544 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); |
| 3523 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, dev_priv->pm_rps_events); | 3545 | /* |
| 3546 | * RPS interrupts will get enabled/disabled on demand when RPS itself | ||
| 3547 | * is enabled/disabled. | ||
| 3548 | */ | ||
| 3549 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0); | ||
| 3524 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); | 3550 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); |
| 3525 | } | 3551 | } |
| 3526 | 3552 | ||
| @@ -3609,7 +3635,7 @@ static void vlv_display_irq_uninstall(struct drm_i915_private *dev_priv) | |||
| 3609 | 3635 | ||
| 3610 | vlv_display_irq_reset(dev_priv); | 3636 | vlv_display_irq_reset(dev_priv); |
| 3611 | 3637 | ||
| 3612 | dev_priv->irq_mask = 0; | 3638 | dev_priv->irq_mask = ~0; |
| 3613 | } | 3639 | } |
| 3614 | 3640 | ||
| 3615 | static void valleyview_irq_uninstall(struct drm_device *dev) | 3641 | static void valleyview_irq_uninstall(struct drm_device *dev) |
| @@ -3715,8 +3741,6 @@ static bool i8xx_handle_vblank(struct drm_device *dev, | |||
| 3715 | if ((iir & flip_pending) == 0) | 3741 | if ((iir & flip_pending) == 0) |
| 3716 | goto check_page_flip; | 3742 | goto check_page_flip; |
| 3717 | 3743 | ||
| 3718 | intel_prepare_page_flip(dev, plane); | ||
| 3719 | |||
| 3720 | /* We detect FlipDone by looking for the change in PendingFlip from '1' | 3744 | /* We detect FlipDone by looking for the change in PendingFlip from '1' |
| 3721 | * to '0' on the following vblank, i.e. IIR has the Pendingflip | 3745 | * to '0' on the following vblank, i.e. IIR has the Pendingflip |
| 3722 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence | 3746 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence |
| @@ -3726,6 +3750,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev, | |||
| 3726 | if (I915_READ16(ISR) & flip_pending) | 3750 | if (I915_READ16(ISR) & flip_pending) |
| 3727 | goto check_page_flip; | 3751 | goto check_page_flip; |
| 3728 | 3752 | ||
| 3753 | intel_prepare_page_flip(dev, plane); | ||
| 3729 | intel_finish_page_flip(dev, pipe); | 3754 | intel_finish_page_flip(dev, pipe); |
| 3730 | return true; | 3755 | return true; |
| 3731 | 3756 | ||
| @@ -3897,8 +3922,6 @@ static bool i915_handle_vblank(struct drm_device *dev, | |||
| 3897 | if ((iir & flip_pending) == 0) | 3922 | if ((iir & flip_pending) == 0) |
| 3898 | goto check_page_flip; | 3923 | goto check_page_flip; |
| 3899 | 3924 | ||
| 3900 | intel_prepare_page_flip(dev, plane); | ||
| 3901 | |||
| 3902 | /* We detect FlipDone by looking for the change in PendingFlip from '1' | 3925 | /* We detect FlipDone by looking for the change in PendingFlip from '1' |
| 3903 | * to '0' on the following vblank, i.e. IIR has the Pendingflip | 3926 | * to '0' on the following vblank, i.e. IIR has the Pendingflip |
| 3904 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence | 3927 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence |
| @@ -3908,6 +3931,7 @@ static bool i915_handle_vblank(struct drm_device *dev, | |||
| 3908 | if (I915_READ(ISR) & flip_pending) | 3931 | if (I915_READ(ISR) & flip_pending) |
| 3909 | goto check_page_flip; | 3932 | goto check_page_flip; |
| 3910 | 3933 | ||
| 3934 | intel_prepare_page_flip(dev, plane); | ||
| 3911 | intel_finish_page_flip(dev, pipe); | 3935 | intel_finish_page_flip(dev, pipe); |
| 3912 | return true; | 3936 | return true; |
| 3913 | 3937 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index eefdc238f70b..172de3b3433b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -395,6 +395,7 @@ | |||
| 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) | 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) |
| 396 | #define PIPE_CONTROL_CS_STALL (1<<20) | 396 | #define PIPE_CONTROL_CS_STALL (1<<20) |
| 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) |
| 398 | #define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) | ||
| 398 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 399 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 399 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | 400 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) |
| 400 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 401 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| @@ -1128,6 +1129,7 @@ enum punit_power_well { | |||
| 1128 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) | 1129 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) |
| 1129 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) | 1130 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) |
| 1130 | #define GEN6_NOSYNC 0 | 1131 | #define GEN6_NOSYNC 0 |
| 1132 | #define RING_PSMI_CTL(base) ((base)+0x50) | ||
| 1131 | #define RING_MAX_IDLE(base) ((base)+0x54) | 1133 | #define RING_MAX_IDLE(base) ((base)+0x54) |
| 1132 | #define RING_HWS_PGA(base) ((base)+0x80) | 1134 | #define RING_HWS_PGA(base) ((base)+0x80) |
| 1133 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) | 1135 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) |
| @@ -1458,6 +1460,7 @@ enum punit_power_well { | |||
| 1458 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) | 1460 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) |
| 1459 | 1461 | ||
| 1460 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 | 1462 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 |
| 1463 | #define GEN6_PSMI_SLEEP_MSG_DISABLE (1 << 0) | ||
| 1461 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) | 1464 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) |
| 1462 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) | 1465 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) |
| 1463 | 1466 | ||
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fb3e3d429191..e7a16f119a29 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -9815,7 +9815,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 9815 | if (obj->tiling_mode != work->old_fb_obj->tiling_mode) | 9815 | if (obj->tiling_mode != work->old_fb_obj->tiling_mode) |
| 9816 | /* vlv: DISPLAY_FLIP fails to change tiling */ | 9816 | /* vlv: DISPLAY_FLIP fails to change tiling */ |
| 9817 | ring = NULL; | 9817 | ring = NULL; |
| 9818 | } else if (IS_IVYBRIDGE(dev)) { | 9818 | } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { |
| 9819 | ring = &dev_priv->ring[BCS]; | 9819 | ring = &dev_priv->ring[BCS]; |
| 9820 | } else if (INTEL_INFO(dev)->gen >= 7) { | 9820 | } else if (INTEL_INFO(dev)->gen >= 7) { |
| 9821 | ring = obj->ring; | 9821 | ring = obj->ring; |
| @@ -13057,11 +13057,7 @@ static void i915_disable_vga(struct drm_device *dev) | |||
| 13057 | vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); | 13057 | vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); |
| 13058 | udelay(300); | 13058 | udelay(300); |
| 13059 | 13059 | ||
| 13060 | /* | 13060 | I915_WRITE(vga_reg, VGA_DISP_DISABLE); |
| 13061 | * Fujitsu-Siemens Lifebook S6010 (830) has problems resuming | ||
| 13062 | * from S3 without preserving (some of?) the other bits. | ||
| 13063 | */ | ||
| 13064 | I915_WRITE(vga_reg, dev_priv->bios_vgacntr | VGA_DISP_DISABLE); | ||
| 13065 | POSTING_READ(vga_reg); | 13061 | POSTING_READ(vga_reg); |
| 13066 | } | 13062 | } |
| 13067 | 13063 | ||
| @@ -13146,8 +13142,6 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 13146 | 13142 | ||
| 13147 | intel_shared_dpll_init(dev); | 13143 | intel_shared_dpll_init(dev); |
| 13148 | 13144 | ||
| 13149 | /* save the BIOS value before clobbering it */ | ||
| 13150 | dev_priv->bios_vgacntr = I915_READ(i915_vgacntrl_reg(dev)); | ||
| 13151 | /* Just disable it once at startup */ | 13145 | /* Just disable it once at startup */ |
| 13152 | i915_disable_vga(dev); | 13146 | i915_disable_vga(dev); |
| 13153 | intel_setup_outputs(dev); | 13147 | intel_setup_outputs(dev); |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 25fdbb16d4e0..3b40a17b8852 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -794,6 +794,7 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask); | |||
| 794 | void gen6_reset_rps_interrupts(struct drm_device *dev); | 794 | void gen6_reset_rps_interrupts(struct drm_device *dev); |
| 795 | void gen6_enable_rps_interrupts(struct drm_device *dev); | 795 | void gen6_enable_rps_interrupts(struct drm_device *dev); |
| 796 | void gen6_disable_rps_interrupts(struct drm_device *dev); | 796 | void gen6_disable_rps_interrupts(struct drm_device *dev); |
| 797 | u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask); | ||
| 797 | void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); | 798 | void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); |
| 798 | void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv); | 799 | void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv); |
| 799 | static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) | 800 | static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 4d63839bd9b4..dfb783a8f2c3 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -962,7 +962,7 @@ void intel_panel_enable_backlight(struct intel_connector *connector) | |||
| 962 | 962 | ||
| 963 | WARN_ON(panel->backlight.max == 0); | 963 | WARN_ON(panel->backlight.max == 0); |
| 964 | 964 | ||
| 965 | if (panel->backlight.level == 0) { | 965 | if (panel->backlight.level <= panel->backlight.min) { |
| 966 | panel->backlight.level = panel->backlight.max; | 966 | panel->backlight.level = panel->backlight.max; |
| 967 | if (panel->backlight.device) | 967 | if (panel->backlight.device) |
| 968 | panel->backlight.device->props.brightness = | 968 | panel->backlight.device->props.brightness = |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1f4b56e273c8..bf814a64582a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -4363,16 +4363,7 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) | |||
| 4363 | mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED); | 4363 | mask |= dev_priv->pm_rps_events & (GEN6_PM_RP_DOWN_EI_EXPIRED | GEN6_PM_RP_UP_EI_EXPIRED); |
| 4364 | mask &= dev_priv->pm_rps_events; | 4364 | mask &= dev_priv->pm_rps_events; |
| 4365 | 4365 | ||
| 4366 | /* IVB and SNB hard hangs on looping batchbuffer | 4366 | return gen6_sanitize_rps_pm_mask(dev_priv, ~mask); |
| 4367 | * if GEN6_PM_UP_EI_EXPIRED is masked. | ||
| 4368 | */ | ||
| 4369 | if (INTEL_INFO(dev_priv->dev)->gen <= 7 && !IS_HASWELL(dev_priv->dev)) | ||
| 4370 | mask |= GEN6_PM_RP_UP_EI_EXPIRED; | ||
| 4371 | |||
| 4372 | if (IS_GEN8(dev_priv->dev)) | ||
| 4373 | mask |= GEN8_PMINTR_REDIRECT_TO_NON_DISP; | ||
| 4374 | |||
| 4375 | return ~mask; | ||
| 4376 | } | 4367 | } |
| 4377 | 4368 | ||
| 4378 | /* gen6_set_rps is called to update the frequency request, but should also be | 4369 | /* gen6_set_rps is called to update the frequency request, but should also be |
| @@ -4441,7 +4432,8 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) | |||
| 4441 | return; | 4432 | return; |
| 4442 | 4433 | ||
| 4443 | /* Mask turbo interrupt so that they will not come in between */ | 4434 | /* Mask turbo interrupt so that they will not come in between */ |
| 4444 | I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); | 4435 | I915_WRITE(GEN6_PMINTRMSK, |
| 4436 | gen6_sanitize_rps_pm_mask(dev_priv, ~0)); | ||
| 4445 | 4437 | ||
| 4446 | vlv_force_gfx_clock(dev_priv, true); | 4438 | vlv_force_gfx_clock(dev_priv, true); |
| 4447 | 4439 | ||
| @@ -6191,6 +6183,20 @@ void intel_cleanup_gt_powersave(struct drm_device *dev) | |||
| 6191 | valleyview_cleanup_gt_powersave(dev); | 6183 | valleyview_cleanup_gt_powersave(dev); |
| 6192 | } | 6184 | } |
| 6193 | 6185 | ||
| 6186 | static void gen6_suspend_rps(struct drm_device *dev) | ||
| 6187 | { | ||
| 6188 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 6189 | |||
| 6190 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | ||
| 6191 | |||
| 6192 | /* | ||
| 6193 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6194 | * is added for it. | ||
| 6195 | */ | ||
| 6196 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6197 | gen6_disable_rps_interrupts(dev); | ||
| 6198 | } | ||
| 6199 | |||
| 6194 | /** | 6200 | /** |
| 6195 | * intel_suspend_gt_powersave - suspend PM work and helper threads | 6201 | * intel_suspend_gt_powersave - suspend PM work and helper threads |
| 6196 | * @dev: drm device | 6202 | * @dev: drm device |
| @@ -6206,14 +6212,7 @@ void intel_suspend_gt_powersave(struct drm_device *dev) | |||
| 6206 | if (INTEL_INFO(dev)->gen < 6) | 6212 | if (INTEL_INFO(dev)->gen < 6) |
| 6207 | return; | 6213 | return; |
| 6208 | 6214 | ||
| 6209 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | 6215 | gen6_suspend_rps(dev); |
| 6210 | |||
| 6211 | /* | ||
| 6212 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6213 | * is added for it. | ||
| 6214 | */ | ||
| 6215 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6216 | gen6_disable_rps_interrupts(dev); | ||
| 6217 | 6216 | ||
| 6218 | /* Force GPU to min freq during suspend */ | 6217 | /* Force GPU to min freq during suspend */ |
| 6219 | gen6_rps_idle(dev_priv); | 6218 | gen6_rps_idle(dev_priv); |
| @@ -6316,8 +6315,11 @@ void intel_reset_gt_powersave(struct drm_device *dev) | |||
| 6316 | { | 6315 | { |
| 6317 | struct drm_i915_private *dev_priv = dev->dev_private; | 6316 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 6318 | 6317 | ||
| 6318 | if (INTEL_INFO(dev)->gen < 6) | ||
| 6319 | return; | ||
| 6320 | |||
| 6321 | gen6_suspend_rps(dev); | ||
| 6319 | dev_priv->rps.enabled = false; | 6322 | dev_priv->rps.enabled = false; |
| 6320 | intel_enable_gt_powersave(dev); | ||
| 6321 | } | 6323 | } |
| 6322 | 6324 | ||
| 6323 | static void ibx_init_clock_gating(struct drm_device *dev) | 6325 | static void ibx_init_clock_gating(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9f445e9a75d1..c7bc93d28d84 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -362,12 +362,15 @@ gen7_render_ring_flush(struct intel_engine_cs *ring, | |||
| 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; | 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
| 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; | 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
| 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; | 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
| 365 | flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; | ||
| 365 | /* | 366 | /* |
| 366 | * TLB invalidate requires a post-sync write. | 367 | * TLB invalidate requires a post-sync write. |
| 367 | */ | 368 | */ |
| 368 | flags |= PIPE_CONTROL_QW_WRITE; | 369 | flags |= PIPE_CONTROL_QW_WRITE; |
| 369 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; | 370 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; |
| 370 | 371 | ||
| 372 | flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; | ||
| 373 | |||
| 371 | /* Workaround: we must issue a pipe_control with CS-stall bit | 374 | /* Workaround: we must issue a pipe_control with CS-stall bit |
| 372 | * set before a pipe_control command that has the state cache | 375 | * set before a pipe_control command that has the state cache |
| 373 | * invalidate bit set. */ | 376 | * invalidate bit set. */ |
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f5a78d53e297..ac6da7102fbb 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
| @@ -615,29 +615,6 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, | |||
| 615 | vlv_power_sequencer_reset(dev_priv); | 615 | vlv_power_sequencer_reset(dev_priv); |
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | static void check_power_well_state(struct drm_i915_private *dev_priv, | ||
| 619 | struct i915_power_well *power_well) | ||
| 620 | { | ||
| 621 | bool enabled = power_well->ops->is_enabled(dev_priv, power_well); | ||
| 622 | |||
| 623 | if (power_well->always_on || !i915.disable_power_well) { | ||
| 624 | if (!enabled) | ||
| 625 | goto mismatch; | ||
| 626 | |||
| 627 | return; | ||
| 628 | } | ||
| 629 | |||
| 630 | if (enabled != (power_well->count > 0)) | ||
| 631 | goto mismatch; | ||
| 632 | |||
| 633 | return; | ||
| 634 | |||
| 635 | mismatch: | ||
| 636 | WARN(1, "state mismatch for '%s' (always_on %d hw state %d use-count %d disable_power_well %d\n", | ||
| 637 | power_well->name, power_well->always_on, enabled, | ||
| 638 | power_well->count, i915.disable_power_well); | ||
| 639 | } | ||
| 640 | |||
| 641 | /** | 618 | /** |
| 642 | * intel_display_power_get - grab a power domain reference | 619 | * intel_display_power_get - grab a power domain reference |
| 643 | * @dev_priv: i915 device instance | 620 | * @dev_priv: i915 device instance |
| @@ -669,8 +646,6 @@ void intel_display_power_get(struct drm_i915_private *dev_priv, | |||
| 669 | power_well->ops->enable(dev_priv, power_well); | 646 | power_well->ops->enable(dev_priv, power_well); |
| 670 | power_well->hw_enabled = true; | 647 | power_well->hw_enabled = true; |
| 671 | } | 648 | } |
| 672 | |||
| 673 | check_power_well_state(dev_priv, power_well); | ||
| 674 | } | 649 | } |
| 675 | 650 | ||
| 676 | power_domains->domain_use_count[domain]++; | 651 | power_domains->domain_use_count[domain]++; |
| @@ -709,8 +684,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, | |||
| 709 | power_well->hw_enabled = false; | 684 | power_well->hw_enabled = false; |
| 710 | power_well->ops->disable(dev_priv, power_well); | 685 | power_well->ops->disable(dev_priv, power_well); |
| 711 | } | 686 | } |
| 712 | |||
| 713 | check_power_well_state(dev_priv, power_well); | ||
| 714 | } | 687 | } |
| 715 | 688 | ||
| 716 | mutex_unlock(&power_domains->lock); | 689 | mutex_unlock(&power_domains->lock); |
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index aa873048308b..94a5bee69fe7 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c | |||
| @@ -386,9 +386,7 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu) | |||
| 386 | msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); | 386 | msm_gem_put_iova(gpu->memptrs_bo, gpu->base.id); |
| 387 | drm_gem_object_unreference(gpu->memptrs_bo); | 387 | drm_gem_object_unreference(gpu->memptrs_bo); |
| 388 | } | 388 | } |
| 389 | if (gpu->pm4) | 389 | release_firmware(gpu->pm4); |
| 390 | release_firmware(gpu->pm4); | 390 | release_firmware(gpu->pfp); |
| 391 | if (gpu->pfp) | ||
| 392 | release_firmware(gpu->pfp); | ||
| 393 | msm_gpu_cleanup(&gpu->base); | 391 | msm_gpu_cleanup(&gpu->base); |
| 394 | } | 392 | } |
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c index fbebb0405d76..b4e70e0e3cfa 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c | |||
| @@ -141,6 +141,15 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) | |||
| 141 | uint32_t hpd_ctrl; | 141 | uint32_t hpd_ctrl; |
| 142 | int i, ret; | 142 | int i, ret; |
| 143 | 143 | ||
| 144 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 145 | ret = regulator_enable(hdmi->hpd_regs[i]); | ||
| 146 | if (ret) { | ||
| 147 | dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", | ||
| 148 | config->hpd_reg_names[i], ret); | ||
| 149 | goto fail; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 144 | ret = gpio_config(hdmi, true); | 153 | ret = gpio_config(hdmi, true); |
| 145 | if (ret) { | 154 | if (ret) { |
| 146 | dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); | 155 | dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret); |
| @@ -164,15 +173,6 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector) | |||
| 164 | } | 173 | } |
| 165 | } | 174 | } |
| 166 | 175 | ||
| 167 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 168 | ret = regulator_enable(hdmi->hpd_regs[i]); | ||
| 169 | if (ret) { | ||
| 170 | dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n", | ||
| 171 | config->hpd_reg_names[i], ret); | ||
| 172 | goto fail; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | hdmi_set_mode(hdmi, false); | 176 | hdmi_set_mode(hdmi, false); |
| 177 | phy->funcs->reset(phy); | 177 | phy->funcs->reset(phy); |
| 178 | hdmi_set_mode(hdmi, true); | 178 | hdmi_set_mode(hdmi, true); |
| @@ -200,7 +200,7 @@ fail: | |||
| 200 | return ret; | 200 | return ret; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static int hdp_disable(struct hdmi_connector *hdmi_connector) | 203 | static void hdp_disable(struct hdmi_connector *hdmi_connector) |
| 204 | { | 204 | { |
| 205 | struct hdmi *hdmi = hdmi_connector->hdmi; | 205 | struct hdmi *hdmi = hdmi_connector->hdmi; |
| 206 | const struct hdmi_platform_config *config = hdmi->config; | 206 | const struct hdmi_platform_config *config = hdmi->config; |
| @@ -212,28 +212,19 @@ static int hdp_disable(struct hdmi_connector *hdmi_connector) | |||
| 212 | 212 | ||
| 213 | hdmi_set_mode(hdmi, false); | 213 | hdmi_set_mode(hdmi, false); |
| 214 | 214 | ||
| 215 | for (i = 0; i < config->hpd_reg_cnt; i++) { | ||
| 216 | ret = regulator_disable(hdmi->hpd_regs[i]); | ||
| 217 | if (ret) { | ||
| 218 | dev_err(dev->dev, "failed to disable hpd regulator: %s (%d)\n", | ||
| 219 | config->hpd_reg_names[i], ret); | ||
| 220 | goto fail; | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | for (i = 0; i < config->hpd_clk_cnt; i++) | 215 | for (i = 0; i < config->hpd_clk_cnt; i++) |
| 225 | clk_disable_unprepare(hdmi->hpd_clks[i]); | 216 | clk_disable_unprepare(hdmi->hpd_clks[i]); |
| 226 | 217 | ||
| 227 | ret = gpio_config(hdmi, false); | 218 | ret = gpio_config(hdmi, false); |
| 228 | if (ret) { | 219 | if (ret) |
| 229 | dev_err(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); | 220 | dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret); |
| 230 | goto fail; | ||
| 231 | } | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | 221 | ||
| 235 | fail: | 222 | for (i = 0; i < config->hpd_reg_cnt; i++) { |
| 236 | return ret; | 223 | ret = regulator_disable(hdmi->hpd_regs[i]); |
| 224 | if (ret) | ||
| 225 | dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n", | ||
| 226 | config->hpd_reg_names[i], ret); | ||
| 227 | } | ||
| 237 | } | 228 | } |
| 238 | 229 | ||
| 239 | static void | 230 | static void |
| @@ -260,11 +251,11 @@ void hdmi_connector_irq(struct drm_connector *connector) | |||
| 260 | (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { | 251 | (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) { |
| 261 | bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); | 252 | bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED); |
| 262 | 253 | ||
| 263 | DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); | 254 | /* ack & disable (temporarily) HPD events: */ |
| 264 | |||
| 265 | /* ack the irq: */ | ||
| 266 | hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, | 255 | hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, |
| 267 | hpd_int_ctrl | HDMI_HPD_INT_CTRL_INT_ACK); | 256 | HDMI_HPD_INT_CTRL_INT_ACK); |
| 257 | |||
| 258 | DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl); | ||
| 268 | 259 | ||
| 269 | /* detect disconnect if we are connected or visa versa: */ | 260 | /* detect disconnect if we are connected or visa versa: */ |
| 270 | hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; | 261 | hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN; |
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index a7672e100d8b..3449213f1e76 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c | |||
| @@ -331,17 +331,8 @@ static int mdp4_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 331 | struct drm_crtc_state *state) | 331 | struct drm_crtc_state *state) |
| 332 | { | 332 | { |
| 333 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); | 333 | struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc); |
| 334 | struct drm_device *dev = crtc->dev; | ||
| 335 | |||
| 336 | DBG("%s: check", mdp4_crtc->name); | 334 | DBG("%s: check", mdp4_crtc->name); |
| 337 | |||
| 338 | if (mdp4_crtc->event) { | ||
| 339 | dev_err(dev->dev, "already pending flip!\n"); | ||
| 340 | return -EBUSY; | ||
| 341 | } | ||
| 342 | |||
| 343 | // TODO anything else to check? | 335 | // TODO anything else to check? |
| 344 | |||
| 345 | return 0; | 336 | return 0; |
| 346 | } | 337 | } |
| 347 | 338 | ||
| @@ -357,7 +348,7 @@ static void mdp4_crtc_atomic_flush(struct drm_crtc *crtc) | |||
| 357 | struct drm_device *dev = crtc->dev; | 348 | struct drm_device *dev = crtc->dev; |
| 358 | unsigned long flags; | 349 | unsigned long flags; |
| 359 | 350 | ||
| 360 | DBG("%s: flush", mdp4_crtc->name); | 351 | DBG("%s: event: %p", mdp4_crtc->name, crtc->state->event); |
| 361 | 352 | ||
| 362 | WARN_ON(mdp4_crtc->event); | 353 | WARN_ON(mdp4_crtc->event); |
| 363 | 354 | ||
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 0e9a2e3a82d7..f021f960a8a2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | |||
| @@ -303,11 +303,6 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, | |||
| 303 | 303 | ||
| 304 | DBG("%s: check", mdp5_crtc->name); | 304 | DBG("%s: check", mdp5_crtc->name); |
| 305 | 305 | ||
| 306 | if (mdp5_crtc->event) { | ||
| 307 | dev_err(dev->dev, "already pending flip!\n"); | ||
| 308 | return -EBUSY; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* request a free CTL, if none is already allocated for this CRTC */ | 306 | /* request a free CTL, if none is already allocated for this CRTC */ |
| 312 | if (state->enable && !mdp5_crtc->ctl) { | 307 | if (state->enable && !mdp5_crtc->ctl) { |
| 313 | mdp5_crtc->ctl = mdp5_ctlm_request(mdp5_kms->ctlm, crtc); | 308 | mdp5_crtc->ctl = mdp5_ctlm_request(mdp5_kms->ctlm, crtc); |
| @@ -364,7 +359,7 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc) | |||
| 364 | struct drm_device *dev = crtc->dev; | 359 | struct drm_device *dev = crtc->dev; |
| 365 | unsigned long flags; | 360 | unsigned long flags; |
| 366 | 361 | ||
| 367 | DBG("%s: flush", mdp5_crtc->name); | 362 | DBG("%s: event: %p", mdp5_crtc->name, crtc->state->event); |
| 368 | 363 | ||
| 369 | WARN_ON(mdp5_crtc->event); | 364 | WARN_ON(mdp5_crtc->event); |
| 370 | 365 | ||
| @@ -460,10 +455,7 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, int intf, | |||
| 460 | /* now that we know what irq's we want: */ | 455 | /* now that we know what irq's we want: */ |
| 461 | mdp5_crtc->err.irqmask = intf2err(intf); | 456 | mdp5_crtc->err.irqmask = intf2err(intf); |
| 462 | mdp5_crtc->vblank.irqmask = intf2vblank(intf); | 457 | mdp5_crtc->vblank.irqmask = intf2vblank(intf); |
| 463 | 458 | mdp_irq_update(&mdp5_kms->base); | |
| 464 | /* when called from modeset_init(), skip the rest until later: */ | ||
| 465 | if (!mdp5_kms) | ||
| 466 | return; | ||
| 467 | 459 | ||
| 468 | spin_lock_irqsave(&mdp5_kms->resource_lock, flags); | 460 | spin_lock_irqsave(&mdp5_kms->resource_lock, flags); |
| 469 | intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL); | 461 | intf_sel = mdp5_read(mdp5_kms, REG_MDP5_DISP_INTF_SEL); |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index a11f1b80c488..9f01a4f21af2 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
| @@ -216,17 +216,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms) | |||
| 216 | goto fail; | 216 | goto fail; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /* NOTE: the vsync and error irq's are actually associated with | 219 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;; |
| 220 | * the INTF/encoder.. the easiest way to deal with this (ie. what | ||
| 221 | * we do now) is assume a fixed relationship between crtc's and | ||
| 222 | * encoders. I'm not sure if there is ever a need to more freely | ||
| 223 | * assign crtcs to encoders, but if there is then we need to take | ||
| 224 | * care of error and vblank irq's that the crtc has registered, | ||
| 225 | * and also update user-requested vblank_mask. | ||
| 226 | */ | ||
| 227 | encoder->possible_crtcs = BIT(0); | ||
| 228 | mdp5_crtc_set_intf(priv->crtcs[0], 3, INTF_HDMI); | ||
| 229 | |||
| 230 | priv->encoders[priv->num_encoders++] = encoder; | 220 | priv->encoders[priv->num_encoders++] = encoder; |
| 231 | 221 | ||
| 232 | /* Construct bridge/connector for HDMI: */ | 222 | /* Construct bridge/connector for HDMI: */ |
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.c b/drivers/gpu/drm/msm/mdp/mdp_kms.c index 03455b64a245..2a731722d840 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.c | |||
| @@ -42,7 +42,10 @@ static void update_irq(struct mdp_kms *mdp_kms) | |||
| 42 | mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); | 42 | mdp_kms->funcs->set_irqmask(mdp_kms, irqmask); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static void update_irq_unlocked(struct mdp_kms *mdp_kms) | 45 | /* if an mdp_irq's irqmask has changed, such as when mdp5 crtc<->encoder |
| 46 | * link changes, this must be called to figure out the new global irqmask | ||
| 47 | */ | ||
| 48 | void mdp_irq_update(struct mdp_kms *mdp_kms) | ||
| 46 | { | 49 | { |
| 47 | unsigned long flags; | 50 | unsigned long flags; |
| 48 | spin_lock_irqsave(&list_lock, flags); | 51 | spin_lock_irqsave(&list_lock, flags); |
| @@ -122,7 +125,7 @@ void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | |||
| 122 | spin_unlock_irqrestore(&list_lock, flags); | 125 | spin_unlock_irqrestore(&list_lock, flags); |
| 123 | 126 | ||
| 124 | if (needs_update) | 127 | if (needs_update) |
| 125 | update_irq_unlocked(mdp_kms); | 128 | mdp_irq_update(mdp_kms); |
| 126 | } | 129 | } |
| 127 | 130 | ||
| 128 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | 131 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) |
| @@ -141,5 +144,5 @@ void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq) | |||
| 141 | spin_unlock_irqrestore(&list_lock, flags); | 144 | spin_unlock_irqrestore(&list_lock, flags); |
| 142 | 145 | ||
| 143 | if (needs_update) | 146 | if (needs_update) |
| 144 | update_irq_unlocked(mdp_kms); | 147 | mdp_irq_update(mdp_kms); |
| 145 | } | 148 | } |
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h index 99557b5ad4fd..b268ce95d394 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h | |||
| @@ -75,7 +75,7 @@ void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable) | |||
| 75 | void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask); | 75 | void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask); |
| 76 | void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq); | 76 | void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq); |
| 77 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq); | 77 | void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq); |
| 78 | 78 | void mdp_irq_update(struct mdp_kms *mdp_kms); | |
| 79 | 79 | ||
| 80 | /* | 80 | /* |
| 81 | * pixel format helpers: | 81 | * pixel format helpers: |
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index f0de412e13dc..191968256c58 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c | |||
| @@ -23,10 +23,41 @@ struct msm_commit { | |||
| 23 | struct drm_atomic_state *state; | 23 | struct drm_atomic_state *state; |
| 24 | uint32_t fence; | 24 | uint32_t fence; |
| 25 | struct msm_fence_cb fence_cb; | 25 | struct msm_fence_cb fence_cb; |
| 26 | uint32_t crtc_mask; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | static void fence_cb(struct msm_fence_cb *cb); | 29 | static void fence_cb(struct msm_fence_cb *cb); |
| 29 | 30 | ||
| 31 | /* block until specified crtcs are no longer pending update, and | ||
| 32 | * atomically mark them as pending update | ||
| 33 | */ | ||
| 34 | static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) | ||
| 35 | { | ||
| 36 | int ret; | ||
| 37 | |||
| 38 | spin_lock(&priv->pending_crtcs_event.lock); | ||
| 39 | ret = wait_event_interruptible_locked(priv->pending_crtcs_event, | ||
| 40 | !(priv->pending_crtcs & crtc_mask)); | ||
| 41 | if (ret == 0) { | ||
| 42 | DBG("start: %08x", crtc_mask); | ||
| 43 | priv->pending_crtcs |= crtc_mask; | ||
| 44 | } | ||
| 45 | spin_unlock(&priv->pending_crtcs_event.lock); | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* clear specified crtcs (no longer pending update) | ||
| 51 | */ | ||
| 52 | static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask) | ||
| 53 | { | ||
| 54 | spin_lock(&priv->pending_crtcs_event.lock); | ||
| 55 | DBG("end: %08x", crtc_mask); | ||
| 56 | priv->pending_crtcs &= ~crtc_mask; | ||
| 57 | wake_up_all_locked(&priv->pending_crtcs_event); | ||
| 58 | spin_unlock(&priv->pending_crtcs_event.lock); | ||
| 59 | } | ||
| 60 | |||
| 30 | static struct msm_commit *new_commit(struct drm_atomic_state *state) | 61 | static struct msm_commit *new_commit(struct drm_atomic_state *state) |
| 31 | { | 62 | { |
| 32 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); | 63 | struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL); |
| @@ -58,12 +89,27 @@ static void complete_commit(struct msm_commit *c) | |||
| 58 | 89 | ||
| 59 | drm_atomic_helper_commit_post_planes(dev, state); | 90 | drm_atomic_helper_commit_post_planes(dev, state); |
| 60 | 91 | ||
| 92 | /* NOTE: _wait_for_vblanks() only waits for vblank on | ||
| 93 | * enabled CRTCs. So we end up faulting when disabling | ||
| 94 | * due to (potentially) unref'ing the outgoing fb's | ||
| 95 | * before the vblank when the disable has latched. | ||
| 96 | * | ||
| 97 | * But if it did wait on disabled (or newly disabled) | ||
| 98 | * CRTCs, that would be racy (ie. we could have missed | ||
| 99 | * the irq. We need some way to poll for pipe shut | ||
| 100 | * down. Or just live with occasionally hitting the | ||
| 101 | * timeout in the CRTC disable path (which really should | ||
| 102 | * not be critical path) | ||
| 103 | */ | ||
| 104 | |||
| 61 | drm_atomic_helper_wait_for_vblanks(dev, state); | 105 | drm_atomic_helper_wait_for_vblanks(dev, state); |
| 62 | 106 | ||
| 63 | drm_atomic_helper_cleanup_planes(dev, state); | 107 | drm_atomic_helper_cleanup_planes(dev, state); |
| 64 | 108 | ||
| 65 | drm_atomic_state_free(state); | 109 | drm_atomic_state_free(state); |
| 66 | 110 | ||
| 111 | end_atomic(dev->dev_private, c->crtc_mask); | ||
| 112 | |||
| 67 | kfree(c); | 113 | kfree(c); |
| 68 | } | 114 | } |
| 69 | 115 | ||
| @@ -97,8 +143,9 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb) | |||
| 97 | int msm_atomic_commit(struct drm_device *dev, | 143 | int msm_atomic_commit(struct drm_device *dev, |
| 98 | struct drm_atomic_state *state, bool async) | 144 | struct drm_atomic_state *state, bool async) |
| 99 | { | 145 | { |
| 100 | struct msm_commit *c; | ||
| 101 | int nplanes = dev->mode_config.num_total_plane; | 146 | int nplanes = dev->mode_config.num_total_plane; |
| 147 | int ncrtcs = dev->mode_config.num_crtc; | ||
| 148 | struct msm_commit *c; | ||
| 102 | int i, ret; | 149 | int i, ret; |
| 103 | 150 | ||
| 104 | ret = drm_atomic_helper_prepare_planes(dev, state); | 151 | ret = drm_atomic_helper_prepare_planes(dev, state); |
| @@ -106,6 +153,18 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 106 | return ret; | 153 | return ret; |
| 107 | 154 | ||
| 108 | c = new_commit(state); | 155 | c = new_commit(state); |
| 156 | if (!c) | ||
| 157 | return -ENOMEM; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * Figure out what crtcs we have: | ||
| 161 | */ | ||
| 162 | for (i = 0; i < ncrtcs; i++) { | ||
| 163 | struct drm_crtc *crtc = state->crtcs[i]; | ||
| 164 | if (!crtc) | ||
| 165 | continue; | ||
| 166 | c->crtc_mask |= (1 << drm_crtc_index(crtc)); | ||
| 167 | } | ||
| 109 | 168 | ||
| 110 | /* | 169 | /* |
| 111 | * Figure out what fence to wait for: | 170 | * Figure out what fence to wait for: |
| @@ -122,6 +181,14 @@ int msm_atomic_commit(struct drm_device *dev, | |||
| 122 | } | 181 | } |
| 123 | 182 | ||
| 124 | /* | 183 | /* |
| 184 | * Wait for pending updates on any of the same crtc's and then | ||
| 185 | * mark our set of crtc's as busy: | ||
| 186 | */ | ||
| 187 | ret = start_atomic(dev->dev_private, c->crtc_mask); | ||
| 188 | if (ret) | ||
| 189 | return ret; | ||
| 190 | |||
| 191 | /* | ||
| 125 | * This is the point of no return - everything below never fails except | 192 | * This is the point of no return - everything below never fails except |
| 126 | * when the hw goes bonghits. Which means we can commit the new state on | 193 | * when the hw goes bonghits. Which means we can commit the new state on |
| 127 | * the software side now. | 194 | * the software side now. |
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c795217e1bfc..9a61546a0b05 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
| @@ -193,6 +193,7 @@ static int msm_load(struct drm_device *dev, unsigned long flags) | |||
| 193 | 193 | ||
| 194 | priv->wq = alloc_ordered_workqueue("msm", 0); | 194 | priv->wq = alloc_ordered_workqueue("msm", 0); |
| 195 | init_waitqueue_head(&priv->fence_event); | 195 | init_waitqueue_head(&priv->fence_event); |
| 196 | init_waitqueue_head(&priv->pending_crtcs_event); | ||
| 196 | 197 | ||
| 197 | INIT_LIST_HEAD(&priv->inactive_list); | 198 | INIT_LIST_HEAD(&priv->inactive_list); |
| 198 | INIT_LIST_HEAD(&priv->fence_cbs); | 199 | INIT_LIST_HEAD(&priv->fence_cbs); |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 136303818436..b69ef2d5a26c 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
| @@ -96,6 +96,10 @@ struct msm_drm_private { | |||
| 96 | /* callbacks deferred until bo is inactive: */ | 96 | /* callbacks deferred until bo is inactive: */ |
| 97 | struct list_head fence_cbs; | 97 | struct list_head fence_cbs; |
| 98 | 98 | ||
| 99 | /* crtcs pending async atomic updates: */ | ||
| 100 | uint32_t pending_crtcs; | ||
| 101 | wait_queue_head_t pending_crtcs_event; | ||
| 102 | |||
| 99 | /* registered MMUs: */ | 103 | /* registered MMUs: */ |
| 100 | unsigned int num_mmus; | 104 | unsigned int num_mmus; |
| 101 | struct msm_mmu *mmus[NUM_DOMAINS]; | 105 | struct msm_mmu *mmus[NUM_DOMAINS]; |
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index 94d55e526b4e..1f3af13ccede 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c | |||
| @@ -190,8 +190,7 @@ fail_unlock: | |||
| 190 | fail: | 190 | fail: |
| 191 | 191 | ||
| 192 | if (ret) { | 192 | if (ret) { |
| 193 | if (fbi) | 193 | framebuffer_release(fbi); |
| 194 | framebuffer_release(fbi); | ||
| 195 | if (fb) { | 194 | if (fb) { |
| 196 | drm_framebuffer_unregister_private(fb); | 195 | drm_framebuffer_unregister_private(fb); |
| 197 | drm_framebuffer_remove(fb); | 196 | drm_framebuffer_remove(fb); |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 4a6f0e49d5b5..49dea4fb55ac 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
| @@ -535,8 +535,7 @@ void msm_gem_free_object(struct drm_gem_object *obj) | |||
| 535 | drm_free_large(msm_obj->pages); | 535 | drm_free_large(msm_obj->pages); |
| 536 | 536 | ||
| 537 | } else { | 537 | } else { |
| 538 | if (msm_obj->vaddr) | 538 | vunmap(msm_obj->vaddr); |
| 539 | vunmap(msm_obj->vaddr); | ||
| 540 | put_pages(obj); | 539 | put_pages(obj); |
| 541 | } | 540 | } |
| 542 | 541 | ||
diff --git a/drivers/gpu/drm/nouveau/core/core/event.c b/drivers/gpu/drm/nouveau/core/core/event.c index ff2b434b3db4..760947e380c9 100644 --- a/drivers/gpu/drm/nouveau/core/core/event.c +++ b/drivers/gpu/drm/nouveau/core/core/event.c | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | void | 26 | void |
| 27 | nvkm_event_put(struct nvkm_event *event, u32 types, int index) | 27 | nvkm_event_put(struct nvkm_event *event, u32 types, int index) |
| 28 | { | 28 | { |
| 29 | BUG_ON(!spin_is_locked(&event->refs_lock)); | 29 | assert_spin_locked(&event->refs_lock); |
| 30 | while (types) { | 30 | while (types) { |
| 31 | int type = __ffs(types); types &= ~(1 << type); | 31 | int type = __ffs(types); types &= ~(1 << type); |
| 32 | if (--event->refs[index * event->types_nr + type] == 0) { | 32 | if (--event->refs[index * event->types_nr + type] == 0) { |
| @@ -39,7 +39,7 @@ nvkm_event_put(struct nvkm_event *event, u32 types, int index) | |||
| 39 | void | 39 | void |
| 40 | nvkm_event_get(struct nvkm_event *event, u32 types, int index) | 40 | nvkm_event_get(struct nvkm_event *event, u32 types, int index) |
| 41 | { | 41 | { |
| 42 | BUG_ON(!spin_is_locked(&event->refs_lock)); | 42 | assert_spin_locked(&event->refs_lock); |
| 43 | while (types) { | 43 | while (types) { |
| 44 | int type = __ffs(types); types &= ~(1 << type); | 44 | int type = __ffs(types); types &= ~(1 << type); |
| 45 | if (++event->refs[index * event->types_nr + type] == 1) { | 45 | if (++event->refs[index * event->types_nr + type] == 1) { |
diff --git a/drivers/gpu/drm/nouveau/core/core/notify.c b/drivers/gpu/drm/nouveau/core/core/notify.c index d1bcde55e9d7..839a32577680 100644 --- a/drivers/gpu/drm/nouveau/core/core/notify.c +++ b/drivers/gpu/drm/nouveau/core/core/notify.c | |||
| @@ -98,7 +98,7 @@ nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size) | |||
| 98 | struct nvkm_event *event = notify->event; | 98 | struct nvkm_event *event = notify->event; |
| 99 | unsigned long flags; | 99 | unsigned long flags; |
| 100 | 100 | ||
| 101 | BUG_ON(!spin_is_locked(&event->list_lock)); | 101 | assert_spin_locked(&event->list_lock); |
| 102 | BUG_ON(size != notify->size); | 102 | BUG_ON(size != notify->size); |
| 103 | 103 | ||
| 104 | spin_lock_irqsave(&event->refs_lock, flags); | 104 | spin_lock_irqsave(&event->refs_lock, flags); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c index 674da1f095b2..732922690653 100644 --- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c | |||
| @@ -249,6 +249,39 @@ nve0_identify(struct nouveau_device *device) | |||
| 249 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | 249 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; |
| 250 | device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass; | 250 | device->oclass[NVDEV_ENGINE_PERFMON] = &nvf0_perfmon_oclass; |
| 251 | break; | 251 | break; |
| 252 | case 0x106: | ||
| 253 | device->cname = "GK208B"; | ||
| 254 | device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; | ||
| 255 | device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; | ||
| 256 | device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; | ||
| 257 | device->oclass[NVDEV_SUBDEV_FUSE ] = &gf100_fuse_oclass; | ||
| 258 | device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; | ||
| 259 | device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; | ||
| 260 | device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; | ||
| 261 | device->oclass[NVDEV_SUBDEV_DEVINIT] = nvc0_devinit_oclass; | ||
| 262 | device->oclass[NVDEV_SUBDEV_MC ] = gk20a_mc_oclass; | ||
| 263 | device->oclass[NVDEV_SUBDEV_BUS ] = nvc0_bus_oclass; | ||
| 264 | device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; | ||
| 265 | device->oclass[NVDEV_SUBDEV_FB ] = nve0_fb_oclass; | ||
| 266 | device->oclass[NVDEV_SUBDEV_LTC ] = gk104_ltc_oclass; | ||
| 267 | device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass; | ||
| 268 | device->oclass[NVDEV_SUBDEV_INSTMEM] = nv50_instmem_oclass; | ||
| 269 | device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass; | ||
| 270 | device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass; | ||
| 271 | device->oclass[NVDEV_SUBDEV_PWR ] = nv108_pwr_oclass; | ||
| 272 | device->oclass[NVDEV_SUBDEV_VOLT ] = &nv40_volt_oclass; | ||
| 273 | device->oclass[NVDEV_ENGINE_DMAOBJ ] = nvd0_dmaeng_oclass; | ||
| 274 | device->oclass[NVDEV_ENGINE_FIFO ] = nv108_fifo_oclass; | ||
| 275 | device->oclass[NVDEV_ENGINE_SW ] = nvc0_software_oclass; | ||
| 276 | device->oclass[NVDEV_ENGINE_GR ] = nv108_graph_oclass; | ||
| 277 | device->oclass[NVDEV_ENGINE_DISP ] = nvf0_disp_oclass; | ||
| 278 | device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass; | ||
| 279 | device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass; | ||
| 280 | device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass; | ||
| 281 | device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass; | ||
| 282 | device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass; | ||
| 283 | device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass; | ||
| 284 | break; | ||
| 252 | case 0x108: | 285 | case 0x108: |
| 253 | device->cname = "GK208"; | 286 | device->cname = "GK208"; |
| 254 | device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; | 287 | device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/shadowramin.c b/drivers/gpu/drm/nouveau/core/subdev/bios/shadowramin.c index 5e58bba0dd5c..a7a890fad1e5 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/shadowramin.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/shadowramin.c | |||
| @@ -44,8 +44,10 @@ static void | |||
| 44 | pramin_fini(void *data) | 44 | pramin_fini(void *data) |
| 45 | { | 45 | { |
| 46 | struct priv *priv = data; | 46 | struct priv *priv = data; |
| 47 | nv_wr32(priv->bios, 0x001700, priv->bar0); | 47 | if (priv) { |
| 48 | kfree(priv); | 48 | nv_wr32(priv->bios, 0x001700, priv->bar0); |
| 49 | kfree(priv); | ||
| 50 | } | ||
| 49 | } | 51 | } |
| 50 | 52 | ||
| 51 | static void * | 53 | static void * |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c index 00f2ca7e44a5..033a8e999497 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvaa.c | |||
| @@ -24,34 +24,71 @@ | |||
| 24 | 24 | ||
| 25 | #include "nv50.h" | 25 | #include "nv50.h" |
| 26 | 26 | ||
| 27 | struct nvaa_ram_priv { | ||
| 28 | struct nouveau_ram base; | ||
| 29 | u64 poller_base; | ||
| 30 | }; | ||
| 31 | |||
| 27 | static int | 32 | static int |
| 28 | nvaa_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 33 | nvaa_ram_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
| 29 | struct nouveau_oclass *oclass, void *data, u32 datasize, | 34 | struct nouveau_oclass *oclass, void *data, u32 datasize, |
| 30 | struct nouveau_object **pobject) | 35 | struct nouveau_object **pobject) |
| 31 | { | 36 | { |
| 32 | const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ | 37 | u32 rsvd_head = ( 256 * 1024); /* vga memory */ |
| 33 | const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ | 38 | u32 rsvd_tail = (1024 * 1024); /* vbios etc */ |
| 34 | struct nouveau_fb *pfb = nouveau_fb(parent); | 39 | struct nouveau_fb *pfb = nouveau_fb(parent); |
| 35 | struct nouveau_ram *ram; | 40 | struct nvaa_ram_priv *priv; |
| 36 | int ret; | 41 | int ret; |
| 37 | 42 | ||
| 38 | ret = nouveau_ram_create(parent, engine, oclass, &ram); | 43 | ret = nouveau_ram_create(parent, engine, oclass, &priv); |
| 39 | *pobject = nv_object(ram); | 44 | *pobject = nv_object(priv); |
| 40 | if (ret) | 45 | if (ret) |
| 41 | return ret; | 46 | return ret; |
| 42 | 47 | ||
| 43 | ram->size = nv_rd32(pfb, 0x10020c); | 48 | priv->base.type = NV_MEM_TYPE_STOLEN; |
| 44 | ram->size = (ram->size & 0xffffff00) | ((ram->size & 0x000000ff) << 32); | 49 | priv->base.stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; |
| 50 | priv->base.size = (u64)nv_rd32(pfb, 0x100e14) << 12; | ||
| 45 | 51 | ||
| 46 | ret = nouveau_mm_init(&pfb->vram, rsvd_head, (ram->size >> 12) - | 52 | rsvd_tail += 0x1000; |
| 47 | (rsvd_head + rsvd_tail), 1); | 53 | priv->poller_base = priv->base.size - rsvd_tail; |
| 54 | |||
| 55 | ret = nouveau_mm_init(&pfb->vram, rsvd_head >> 12, | ||
| 56 | (priv->base.size - (rsvd_head + rsvd_tail)) >> 12, | ||
| 57 | 1); | ||
| 48 | if (ret) | 58 | if (ret) |
| 49 | return ret; | 59 | return ret; |
| 50 | 60 | ||
| 51 | ram->type = NV_MEM_TYPE_STOLEN; | 61 | priv->base.get = nv50_ram_get; |
| 52 | ram->stolen = (u64)nv_rd32(pfb, 0x100e10) << 12; | 62 | priv->base.put = nv50_ram_put; |
| 53 | ram->get = nv50_ram_get; | 63 | return 0; |
| 54 | ram->put = nv50_ram_put; | 64 | } |
| 65 | |||
| 66 | static int | ||
| 67 | nvaa_ram_init(struct nouveau_object *object) | ||
| 68 | { | ||
| 69 | struct nouveau_fb *pfb = nouveau_fb(object); | ||
| 70 | struct nvaa_ram_priv *priv = (void *)object; | ||
| 71 | int ret; | ||
| 72 | u64 dniso, hostnb, flush; | ||
| 73 | |||
| 74 | ret = nouveau_ram_init(&priv->base); | ||
| 75 | if (ret) | ||
| 76 | return ret; | ||
| 77 | |||
| 78 | dniso = ((priv->base.size - (priv->poller_base + 0x00)) >> 5) - 1; | ||
| 79 | hostnb = ((priv->base.size - (priv->poller_base + 0x20)) >> 5) - 1; | ||
| 80 | flush = ((priv->base.size - (priv->poller_base + 0x40)) >> 5) - 1; | ||
| 81 | |||
| 82 | /* Enable NISO poller for various clients and set their associated | ||
| 83 | * read address, only for MCP77/78 and MCP79/7A. (fd#25701) | ||
| 84 | */ | ||
| 85 | nv_wr32(pfb, 0x100c18, dniso); | ||
| 86 | nv_mask(pfb, 0x100c14, 0x00000000, 0x00000001); | ||
| 87 | nv_wr32(pfb, 0x100c1c, hostnb); | ||
| 88 | nv_mask(pfb, 0x100c14, 0x00000000, 0x00000002); | ||
| 89 | nv_wr32(pfb, 0x100c24, flush); | ||
| 90 | nv_mask(pfb, 0x100c14, 0x00000000, 0x00010000); | ||
| 91 | |||
| 55 | return 0; | 92 | return 0; |
| 56 | } | 93 | } |
| 57 | 94 | ||
| @@ -60,7 +97,7 @@ nvaa_ram_oclass = { | |||
| 60 | .ofuncs = &(struct nouveau_ofuncs) { | 97 | .ofuncs = &(struct nouveau_ofuncs) { |
| 61 | .ctor = nvaa_ram_ctor, | 98 | .ctor = nvaa_ram_ctor, |
| 62 | .dtor = _nouveau_ram_dtor, | 99 | .dtor = _nouveau_ram_dtor, |
| 63 | .init = _nouveau_ram_init, | 100 | .init = nvaa_ram_init, |
| 64 | .fini = _nouveau_ram_fini, | 101 | .fini = _nouveau_ram_fini, |
| 65 | }, | 102 | }, |
| 66 | }; | 103 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c index a75c35ccf25c..165401c4045c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv4c.c | |||
| @@ -24,13 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | #include "nv04.h" | 25 | #include "nv04.h" |
| 26 | 26 | ||
| 27 | static void | ||
| 28 | nv4c_mc_msi_rearm(struct nouveau_mc *pmc) | ||
| 29 | { | ||
| 30 | struct nv04_mc_priv *priv = (void *)pmc; | ||
| 31 | nv_wr08(priv, 0x088050, 0xff); | ||
| 32 | } | ||
| 33 | |||
| 34 | struct nouveau_oclass * | 27 | struct nouveau_oclass * |
| 35 | nv4c_mc_oclass = &(struct nouveau_mc_oclass) { | 28 | nv4c_mc_oclass = &(struct nouveau_mc_oclass) { |
| 36 | .base.handle = NV_SUBDEV(MC, 0x4c), | 29 | .base.handle = NV_SUBDEV(MC, 0x4c), |
| @@ -41,5 +34,4 @@ nv4c_mc_oclass = &(struct nouveau_mc_oclass) { | |||
| 41 | .fini = _nouveau_mc_fini, | 34 | .fini = _nouveau_mc_fini, |
| 42 | }, | 35 | }, |
| 43 | .intr = nv04_mc_intr, | 36 | .intr = nv04_mc_intr, |
| 44 | .msi_rearm = nv4c_mc_msi_rearm, | ||
| 45 | }.base; | 37 | }.base; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 21ec561edc99..bba2960d3dfb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -1572,8 +1572,10 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) | |||
| 1572 | * so use the DMA API for them. | 1572 | * so use the DMA API for them. |
| 1573 | */ | 1573 | */ |
| 1574 | if (!nv_device_is_cpu_coherent(device) && | 1574 | if (!nv_device_is_cpu_coherent(device) && |
| 1575 | ttm->caching_state == tt_uncached) | 1575 | ttm->caching_state == tt_uncached) { |
| 1576 | ttm_dma_unpopulate(ttm_dma, dev->dev); | 1576 | ttm_dma_unpopulate(ttm_dma, dev->dev); |
| 1577 | return; | ||
| 1578 | } | ||
| 1577 | 1579 | ||
| 1578 | #if __OS_HAS_AGP | 1580 | #if __OS_HAS_AGP |
| 1579 | if (drm->agp.stat == ENABLED) { | 1581 | if (drm->agp.stat == ENABLED) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 5d93902a91ab..f8042433752b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -876,7 +876,6 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, | |||
| 876 | if (ret) | 876 | if (ret) |
| 877 | return ret; | 877 | return ret; |
| 878 | 878 | ||
| 879 | bo->gem.dumb = true; | ||
| 880 | ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); | 879 | ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); |
| 881 | drm_gem_object_unreference_unlocked(&bo->gem); | 880 | drm_gem_object_unreference_unlocked(&bo->gem); |
| 882 | return ret; | 881 | return ret; |
| @@ -892,14 +891,6 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, | |||
| 892 | gem = drm_gem_object_lookup(dev, file_priv, handle); | 891 | gem = drm_gem_object_lookup(dev, file_priv, handle); |
| 893 | if (gem) { | 892 | if (gem) { |
| 894 | struct nouveau_bo *bo = nouveau_gem_object(gem); | 893 | struct nouveau_bo *bo = nouveau_gem_object(gem); |
| 895 | |||
| 896 | /* | ||
| 897 | * We don't allow dumb mmaps on objects created using another | ||
| 898 | * interface. | ||
| 899 | */ | ||
| 900 | WARN_ONCE(!(gem->dumb || gem->import_attach), | ||
| 901 | "Illegal dumb map of accelerated buffer.\n"); | ||
| 902 | |||
| 903 | *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); | 894 | *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); |
| 904 | drm_gem_object_unreference_unlocked(gem); | 895 | drm_gem_object_unreference_unlocked(gem); |
| 905 | return 0; | 896 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 28d51a22a4bf..bf0f9e21d714 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -36,7 +36,14 @@ void | |||
| 36 | nouveau_gem_object_del(struct drm_gem_object *gem) | 36 | nouveau_gem_object_del(struct drm_gem_object *gem) |
| 37 | { | 37 | { |
| 38 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); | 38 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
| 39 | struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); | ||
| 39 | struct ttm_buffer_object *bo = &nvbo->bo; | 40 | struct ttm_buffer_object *bo = &nvbo->bo; |
| 41 | struct device *dev = drm->dev->dev; | ||
| 42 | int ret; | ||
| 43 | |||
| 44 | ret = pm_runtime_get_sync(dev); | ||
| 45 | if (WARN_ON(ret < 0 && ret != -EACCES)) | ||
| 46 | return; | ||
| 40 | 47 | ||
| 41 | if (gem->import_attach) | 48 | if (gem->import_attach) |
| 42 | drm_prime_gem_destroy(gem, nvbo->bo.sg); | 49 | drm_prime_gem_destroy(gem, nvbo->bo.sg); |
| @@ -46,6 +53,9 @@ nouveau_gem_object_del(struct drm_gem_object *gem) | |||
| 46 | /* reset filp so nouveau_bo_del_ttm() can test for it */ | 53 | /* reset filp so nouveau_bo_del_ttm() can test for it */ |
| 47 | gem->filp = NULL; | 54 | gem->filp = NULL; |
| 48 | ttm_bo_unref(&bo); | 55 | ttm_bo_unref(&bo); |
| 56 | |||
| 57 | pm_runtime_mark_last_busy(dev); | ||
| 58 | pm_runtime_put_autosuspend(dev); | ||
| 49 | } | 59 | } |
| 50 | 60 | ||
| 51 | int | 61 | int |
| @@ -53,7 +63,9 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) | |||
| 53 | { | 63 | { |
| 54 | struct nouveau_cli *cli = nouveau_cli(file_priv); | 64 | struct nouveau_cli *cli = nouveau_cli(file_priv); |
| 55 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); | 65 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
| 66 | struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); | ||
| 56 | struct nouveau_vma *vma; | 67 | struct nouveau_vma *vma; |
| 68 | struct device *dev = drm->dev->dev; | ||
| 57 | int ret; | 69 | int ret; |
| 58 | 70 | ||
| 59 | if (!cli->vm) | 71 | if (!cli->vm) |
| @@ -71,11 +83,16 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) | |||
| 71 | goto out; | 83 | goto out; |
| 72 | } | 84 | } |
| 73 | 85 | ||
| 86 | ret = pm_runtime_get_sync(dev); | ||
| 87 | if (ret < 0 && ret != -EACCES) | ||
| 88 | goto out; | ||
| 89 | |||
| 74 | ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); | 90 | ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); |
| 75 | if (ret) { | 91 | if (ret) |
| 76 | kfree(vma); | 92 | kfree(vma); |
| 77 | goto out; | 93 | |
| 78 | } | 94 | pm_runtime_mark_last_busy(dev); |
| 95 | pm_runtime_put_autosuspend(dev); | ||
| 79 | } else { | 96 | } else { |
| 80 | vma->refcount++; | 97 | vma->refcount++; |
| 81 | } | 98 | } |
| @@ -129,6 +146,8 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) | |||
| 129 | { | 146 | { |
| 130 | struct nouveau_cli *cli = nouveau_cli(file_priv); | 147 | struct nouveau_cli *cli = nouveau_cli(file_priv); |
| 131 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); | 148 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
| 149 | struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); | ||
| 150 | struct device *dev = drm->dev->dev; | ||
| 132 | struct nouveau_vma *vma; | 151 | struct nouveau_vma *vma; |
| 133 | int ret; | 152 | int ret; |
| 134 | 153 | ||
| @@ -141,8 +160,14 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) | |||
| 141 | 160 | ||
| 142 | vma = nouveau_bo_vma_find(nvbo, cli->vm); | 161 | vma = nouveau_bo_vma_find(nvbo, cli->vm); |
| 143 | if (vma) { | 162 | if (vma) { |
| 144 | if (--vma->refcount == 0) | 163 | if (--vma->refcount == 0) { |
| 145 | nouveau_gem_object_unmap(nvbo, vma); | 164 | ret = pm_runtime_get_sync(dev); |
| 165 | if (!WARN_ON(ret < 0 && ret != -EACCES)) { | ||
| 166 | nouveau_gem_object_unmap(nvbo, vma); | ||
| 167 | pm_runtime_mark_last_busy(dev); | ||
| 168 | pm_runtime_put_autosuspend(dev); | ||
| 169 | } | ||
| 170 | } | ||
| 146 | } | 171 | } |
| 147 | ttm_bo_unreserve(&nvbo->bo); | 172 | ttm_bo_unreserve(&nvbo->bo); |
| 148 | } | 173 | } |
| @@ -444,9 +469,6 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, | |||
| 444 | list_for_each_entry(nvbo, list, entry) { | 469 | list_for_each_entry(nvbo, list, entry) { |
| 445 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; | 470 | struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; |
| 446 | 471 | ||
| 447 | WARN_ONCE(nvbo->gem.dumb, | ||
| 448 | "GPU use of dumb buffer is illegal.\n"); | ||
| 449 | |||
| 450 | ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, | 472 | ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, |
| 451 | b->write_domains, | 473 | b->write_domains, |
| 452 | b->valid_domains); | 474 | b->valid_domains); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 753a6def61e7..3d1cfcb96b6b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include "nouveau_ttm.h" | 28 | #include "nouveau_ttm.h" |
| 29 | #include "nouveau_gem.h" | 29 | #include "nouveau_gem.h" |
| 30 | 30 | ||
| 31 | #include "drm_legacy.h" | ||
| 31 | static int | 32 | static int |
| 32 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 33 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) |
| 33 | { | 34 | { |
| @@ -281,7 +282,7 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 281 | struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); | 282 | struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); |
| 282 | 283 | ||
| 283 | if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) | 284 | if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) |
| 284 | return -EINVAL; | 285 | return drm_legacy_mmap(filp, vma); |
| 285 | 286 | ||
| 286 | return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); | 287 | return ttm_bo_mmap(filp, vma, &drm->ttm.bdev); |
| 287 | } | 288 | } |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d59ec491dbb9..ed644a4f6f57 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -1851,10 +1851,9 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1851 | return pll; | 1851 | return pll; |
| 1852 | } | 1852 | } |
| 1853 | /* otherwise, pick one of the plls */ | 1853 | /* otherwise, pick one of the plls */ |
| 1854 | if ((rdev->family == CHIP_KAVERI) || | 1854 | if ((rdev->family == CHIP_KABINI) || |
| 1855 | (rdev->family == CHIP_KABINI) || | ||
| 1856 | (rdev->family == CHIP_MULLINS)) { | 1855 | (rdev->family == CHIP_MULLINS)) { |
| 1857 | /* KB/KV/ML has PPLL1 and PPLL2 */ | 1856 | /* KB/ML has PPLL1 and PPLL2 */ |
| 1858 | pll_in_use = radeon_get_pll_use_mask(crtc); | 1857 | pll_in_use = radeon_get_pll_use_mask(crtc); |
| 1859 | if (!(pll_in_use & (1 << ATOM_PPLL2))) | 1858 | if (!(pll_in_use & (1 << ATOM_PPLL2))) |
| 1860 | return ATOM_PPLL2; | 1859 | return ATOM_PPLL2; |
| @@ -1863,7 +1862,7 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) | |||
| 1863 | DRM_ERROR("unable to allocate a PPLL\n"); | 1862 | DRM_ERROR("unable to allocate a PPLL\n"); |
| 1864 | return ATOM_PPLL_INVALID; | 1863 | return ATOM_PPLL_INVALID; |
| 1865 | } else { | 1864 | } else { |
| 1866 | /* CI has PPLL0, PPLL1, and PPLL2 */ | 1865 | /* CI/KV has PPLL0, PPLL1, and PPLL2 */ |
| 1867 | pll_in_use = radeon_get_pll_use_mask(crtc); | 1866 | pll_in_use = radeon_get_pll_use_mask(crtc); |
| 1868 | if (!(pll_in_use & (1 << ATOM_PPLL2))) | 1867 | if (!(pll_in_use & (1 << ATOM_PPLL2))) |
| 1869 | return ATOM_PPLL2; | 1868 | return ATOM_PPLL2; |
| @@ -2155,6 +2154,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) | |||
| 2155 | case ATOM_PPLL0: | 2154 | case ATOM_PPLL0: |
| 2156 | /* disable the ppll */ | 2155 | /* disable the ppll */ |
| 2157 | if ((rdev->family == CHIP_ARUBA) || | 2156 | if ((rdev->family == CHIP_ARUBA) || |
| 2157 | (rdev->family == CHIP_KAVERI) || | ||
| 2158 | (rdev->family == CHIP_BONAIRE) || | 2158 | (rdev->family == CHIP_BONAIRE) || |
| 2159 | (rdev->family == CHIP_HAWAII)) | 2159 | (rdev->family == CHIP_HAWAII)) |
| 2160 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, | 2160 | atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, |
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 11ba9d21b89b..db42a670f995 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c | |||
| @@ -492,6 +492,10 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, | |||
| 492 | struct radeon_connector_atom_dig *dig_connector; | 492 | struct radeon_connector_atom_dig *dig_connector; |
| 493 | int dp_clock; | 493 | int dp_clock; |
| 494 | 494 | ||
| 495 | if ((mode->clock > 340000) && | ||
| 496 | (!radeon_connector_is_dp12_capable(connector))) | ||
| 497 | return MODE_CLOCK_HIGH; | ||
| 498 | |||
| 495 | if (!radeon_connector->con_priv) | 499 | if (!radeon_connector->con_priv) |
| 496 | return MODE_CLOCK_HIGH; | 500 | return MODE_CLOCK_HIGH; |
| 497 | dig_connector = radeon_connector->con_priv; | 501 | dig_connector = radeon_connector->con_priv; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 6dcde3798b45..64fdae558d36 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -6033,6 +6033,17 @@ void cik_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 6033 | radeon_ring_write(ring, 0); | 6033 | radeon_ring_write(ring, 0); |
| 6034 | radeon_ring_write(ring, 1 << vm_id); | 6034 | radeon_ring_write(ring, 1 << vm_id); |
| 6035 | 6035 | ||
| 6036 | /* wait for the invalidate to complete */ | ||
| 6037 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 6038 | radeon_ring_write(ring, (WAIT_REG_MEM_OPERATION(0) | /* wait */ | ||
| 6039 | WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 6040 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 6041 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 6042 | radeon_ring_write(ring, 0); | ||
| 6043 | radeon_ring_write(ring, 0); /* ref */ | ||
| 6044 | radeon_ring_write(ring, 0); /* mask */ | ||
| 6045 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 6046 | |||
| 6036 | /* compute doesn't have PFP */ | 6047 | /* compute doesn't have PFP */ |
| 6037 | if (usepfp) { | 6048 | if (usepfp) { |
| 6038 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 6049 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index dde5c7e29eb2..42cd0cffe210 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c | |||
| @@ -816,7 +816,6 @@ void cik_sdma_vm_write_pages(struct radeon_device *rdev, | |||
| 816 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { | 816 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { |
| 817 | if (flags & R600_PTE_SYSTEM) { | 817 | if (flags & R600_PTE_SYSTEM) { |
| 818 | value = radeon_vm_map_gart(rdev, addr); | 818 | value = radeon_vm_map_gart(rdev, addr); |
| 819 | value &= 0xFFFFFFFFFFFFF000ULL; | ||
| 820 | } else if (flags & R600_PTE_VALID) { | 819 | } else if (flags & R600_PTE_VALID) { |
| 821 | value = addr; | 820 | value = addr; |
| 822 | } else { | 821 | } else { |
| @@ -903,6 +902,9 @@ void cik_sdma_vm_pad_ib(struct radeon_ib *ib) | |||
| 903 | void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | 902 | void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, |
| 904 | unsigned vm_id, uint64_t pd_addr) | 903 | unsigned vm_id, uint64_t pd_addr) |
| 905 | { | 904 | { |
| 905 | u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(0) | | ||
| 906 | SDMA_POLL_REG_MEM_EXTRA_FUNC(0)); /* always */ | ||
| 907 | |||
| 906 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | 908 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); |
| 907 | if (vm_id < 8) { | 909 | if (vm_id < 8) { |
| 908 | radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2); | 910 | radeon_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm_id << 2)) >> 2); |
| @@ -943,5 +945,12 @@ void cik_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 943 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | 945 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); |
| 944 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | 946 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); |
| 945 | radeon_ring_write(ring, 1 << vm_id); | 947 | radeon_ring_write(ring, 1 << vm_id); |
| 948 | |||
| 949 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits)); | ||
| 950 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 951 | radeon_ring_write(ring, 0); | ||
| 952 | radeon_ring_write(ring, 0); /* reference */ | ||
| 953 | radeon_ring_write(ring, 0); /* mask */ | ||
| 954 | radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ | ||
| 946 | } | 955 | } |
| 947 | 956 | ||
diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index ba85986febea..03003f8a6de6 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h | |||
| @@ -2156,4 +2156,6 @@ | |||
| 2156 | #define ATC_VM_APERTURE1_HIGH_ADDR 0x330Cu | 2156 | #define ATC_VM_APERTURE1_HIGH_ADDR 0x330Cu |
| 2157 | #define ATC_VM_APERTURE1_LOW_ADDR 0x3304u | 2157 | #define ATC_VM_APERTURE1_LOW_ADDR 0x3304u |
| 2158 | 2158 | ||
| 2159 | #define IH_VMID_0_LUT 0x3D40u | ||
| 2160 | |||
| 2159 | #endif | 2161 | #endif |
diff --git a/drivers/gpu/drm/radeon/dce3_1_afmt.c b/drivers/gpu/drm/radeon/dce3_1_afmt.c index 2fe8cfc966d9..bafdf92a5732 100644 --- a/drivers/gpu/drm/radeon/dce3_1_afmt.c +++ b/drivers/gpu/drm/radeon/dce3_1_afmt.c | |||
| @@ -103,7 +103,7 @@ static void dce3_2_afmt_write_sad_regs(struct drm_encoder *encoder) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); | 105 | sad_count = drm_edid_to_sad(radeon_connector->edid, &sads); |
| 106 | if (sad_count < 0) { | 106 | if (sad_count <= 0) { |
| 107 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); | 107 | DRM_ERROR("Couldn't read SADs: %d\n", sad_count); |
| 108 | return; | 108 | return; |
| 109 | } | 109 | } |
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 9b42001295ba..e3e9c10cfba9 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c | |||
| @@ -2745,13 +2745,11 @@ int kv_dpm_init(struct radeon_device *rdev) | |||
| 2745 | pi->enable_auto_thermal_throttling = true; | 2745 | pi->enable_auto_thermal_throttling = true; |
| 2746 | pi->disable_nb_ps3_in_battery = false; | 2746 | pi->disable_nb_ps3_in_battery = false; |
| 2747 | if (radeon_bapm == -1) { | 2747 | if (radeon_bapm == -1) { |
| 2748 | /* There are stability issues reported on with | 2748 | /* only enable bapm on KB, ML by default */ |
| 2749 | * bapm enabled on an asrock system. | 2749 | if (rdev->family == CHIP_KABINI || rdev->family == CHIP_MULLINS) |
| 2750 | */ | ||
| 2751 | if (rdev->pdev->subsystem_vendor == 0x1849) | ||
| 2752 | pi->bapm_enable = false; | ||
| 2753 | else | ||
| 2754 | pi->bapm_enable = true; | 2750 | pi->bapm_enable = true; |
| 2751 | else | ||
| 2752 | pi->bapm_enable = false; | ||
| 2755 | } else if (radeon_bapm == 0) { | 2753 | } else if (radeon_bapm == 0) { |
| 2756 | pi->bapm_enable = false; | 2754 | pi->bapm_enable = false; |
| 2757 | } else { | 2755 | } else { |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 360de9f1f491..aea48c89b241 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -2516,6 +2516,16 @@ void cayman_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 2516 | radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); | 2516 | radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0)); |
| 2517 | radeon_ring_write(ring, 1 << vm_id); | 2517 | radeon_ring_write(ring, 1 << vm_id); |
| 2518 | 2518 | ||
| 2519 | /* wait for the invalidate to complete */ | ||
| 2520 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 2521 | radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 2522 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 2523 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 2524 | radeon_ring_write(ring, 0); | ||
| 2525 | radeon_ring_write(ring, 0); /* ref */ | ||
| 2526 | radeon_ring_write(ring, 0); /* mask */ | ||
| 2527 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 2528 | |||
| 2519 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 2529 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
| 2520 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); | 2530 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); |
| 2521 | radeon_ring_write(ring, 0x0); | 2531 | radeon_ring_write(ring, 0x0); |
diff --git a/drivers/gpu/drm/radeon/ni_dma.c b/drivers/gpu/drm/radeon/ni_dma.c index 50f88611ff60..ce787a9f12c0 100644 --- a/drivers/gpu/drm/radeon/ni_dma.c +++ b/drivers/gpu/drm/radeon/ni_dma.c | |||
| @@ -372,7 +372,6 @@ void cayman_dma_vm_write_pages(struct radeon_device *rdev, | |||
| 372 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { | 372 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { |
| 373 | if (flags & R600_PTE_SYSTEM) { | 373 | if (flags & R600_PTE_SYSTEM) { |
| 374 | value = radeon_vm_map_gart(rdev, addr); | 374 | value = radeon_vm_map_gart(rdev, addr); |
| 375 | value &= 0xFFFFFFFFFFFFF000ULL; | ||
| 376 | } else if (flags & R600_PTE_VALID) { | 375 | } else if (flags & R600_PTE_VALID) { |
| 377 | value = addr; | 376 | value = addr; |
| 378 | } else { | 377 | } else { |
| @@ -463,5 +462,11 @@ void cayman_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 463 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); | 462 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0)); |
| 464 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); | 463 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); |
| 465 | radeon_ring_write(ring, 1 << vm_id); | 464 | radeon_ring_write(ring, 1 << vm_id); |
| 465 | |||
| 466 | /* wait for invalidate to complete */ | ||
| 467 | radeon_ring_write(ring, DMA_SRBM_READ_PACKET); | ||
| 468 | radeon_ring_write(ring, (0xff << 20) | (VM_INVALIDATE_REQUEST >> 2)); | ||
| 469 | radeon_ring_write(ring, 0); /* mask */ | ||
| 470 | radeon_ring_write(ring, 0); /* value */ | ||
| 466 | } | 471 | } |
| 467 | 472 | ||
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2e12e4d69253..ad7125486894 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h | |||
| @@ -1133,6 +1133,23 @@ | |||
| 1133 | #define PACKET3_MEM_SEMAPHORE 0x39 | 1133 | #define PACKET3_MEM_SEMAPHORE 0x39 |
| 1134 | #define PACKET3_MPEG_INDEX 0x3A | 1134 | #define PACKET3_MPEG_INDEX 0x3A |
| 1135 | #define PACKET3_WAIT_REG_MEM 0x3C | 1135 | #define PACKET3_WAIT_REG_MEM 0x3C |
| 1136 | #define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) | ||
| 1137 | /* 0 - always | ||
| 1138 | * 1 - < | ||
| 1139 | * 2 - <= | ||
| 1140 | * 3 - == | ||
| 1141 | * 4 - != | ||
| 1142 | * 5 - >= | ||
| 1143 | * 6 - > | ||
| 1144 | */ | ||
| 1145 | #define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) | ||
| 1146 | /* 0 - reg | ||
| 1147 | * 1 - mem | ||
| 1148 | */ | ||
| 1149 | #define WAIT_REG_MEM_ENGINE(x) ((x) << 8) | ||
| 1150 | /* 0 - me | ||
| 1151 | * 1 - pfp | ||
| 1152 | */ | ||
| 1136 | #define PACKET3_MEM_WRITE 0x3D | 1153 | #define PACKET3_MEM_WRITE 0x3D |
| 1137 | #define PACKET3_PFP_SYNC_ME 0x42 | 1154 | #define PACKET3_PFP_SYNC_ME 0x42 |
| 1138 | #define PACKET3_SURFACE_SYNC 0x43 | 1155 | #define PACKET3_SURFACE_SYNC 0x43 |
| @@ -1272,6 +1289,13 @@ | |||
| 1272 | (1 << 21) | \ | 1289 | (1 << 21) | \ |
| 1273 | (((n) & 0xFFFFF) << 0)) | 1290 | (((n) & 0xFFFFF) << 0)) |
| 1274 | 1291 | ||
| 1292 | #define DMA_SRBM_POLL_PACKET ((9 << 28) | \ | ||
| 1293 | (1 << 27) | \ | ||
| 1294 | (1 << 26)) | ||
| 1295 | |||
| 1296 | #define DMA_SRBM_READ_PACKET ((9 << 28) | \ | ||
| 1297 | (1 << 27)) | ||
| 1298 | |||
| 1275 | /* async DMA Packet types */ | 1299 | /* async DMA Packet types */ |
| 1276 | #define DMA_PACKET_WRITE 0x2 | 1300 | #define DMA_PACKET_WRITE 0x2 |
| 1277 | #define DMA_PACKET_COPY 0x3 | 1301 | #define DMA_PACKET_COPY 0x3 |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 74f06d540591..279801ca5110 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -644,6 +644,7 @@ int r100_pci_gart_init(struct radeon_device *rdev) | |||
| 644 | return r; | 644 | return r; |
| 645 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; | 645 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
| 646 | rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; | 646 | rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; |
| 647 | rdev->asic->gart.get_page_entry = &r100_pci_gart_get_page_entry; | ||
| 647 | rdev->asic->gart.set_page = &r100_pci_gart_set_page; | 648 | rdev->asic->gart.set_page = &r100_pci_gart_set_page; |
| 648 | return radeon_gart_table_ram_alloc(rdev); | 649 | return radeon_gart_table_ram_alloc(rdev); |
| 649 | } | 650 | } |
| @@ -681,11 +682,16 @@ void r100_pci_gart_disable(struct radeon_device *rdev) | |||
| 681 | WREG32(RADEON_AIC_HI_ADDR, 0); | 682 | WREG32(RADEON_AIC_HI_ADDR, 0); |
| 682 | } | 683 | } |
| 683 | 684 | ||
| 685 | uint64_t r100_pci_gart_get_page_entry(uint64_t addr, uint32_t flags) | ||
| 686 | { | ||
| 687 | return addr; | ||
| 688 | } | ||
| 689 | |||
| 684 | void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, | 690 | void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, |
| 685 | uint64_t addr, uint32_t flags) | 691 | uint64_t entry) |
| 686 | { | 692 | { |
| 687 | u32 *gtt = rdev->gart.ptr; | 693 | u32 *gtt = rdev->gart.ptr; |
| 688 | gtt[i] = cpu_to_le32(lower_32_bits(addr)); | 694 | gtt[i] = cpu_to_le32(lower_32_bits(entry)); |
| 689 | } | 695 | } |
| 690 | 696 | ||
| 691 | void r100_pci_gart_fini(struct radeon_device *rdev) | 697 | void r100_pci_gart_fini(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 064ad5569cca..08d68f3e13e9 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -73,11 +73,8 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) | |||
| 73 | #define R300_PTE_WRITEABLE (1 << 2) | 73 | #define R300_PTE_WRITEABLE (1 << 2) |
| 74 | #define R300_PTE_READABLE (1 << 3) | 74 | #define R300_PTE_READABLE (1 << 3) |
| 75 | 75 | ||
| 76 | void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, | 76 | uint64_t rv370_pcie_gart_get_page_entry(uint64_t addr, uint32_t flags) |
| 77 | uint64_t addr, uint32_t flags) | ||
| 78 | { | 77 | { |
| 79 | void __iomem *ptr = rdev->gart.ptr; | ||
| 80 | |||
| 81 | addr = (lower_32_bits(addr) >> 8) | | 78 | addr = (lower_32_bits(addr) >> 8) | |
| 82 | ((upper_32_bits(addr) & 0xff) << 24); | 79 | ((upper_32_bits(addr) & 0xff) << 24); |
| 83 | if (flags & RADEON_GART_PAGE_READ) | 80 | if (flags & RADEON_GART_PAGE_READ) |
| @@ -86,10 +83,18 @@ void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, | |||
| 86 | addr |= R300_PTE_WRITEABLE; | 83 | addr |= R300_PTE_WRITEABLE; |
| 87 | if (!(flags & RADEON_GART_PAGE_SNOOP)) | 84 | if (!(flags & RADEON_GART_PAGE_SNOOP)) |
| 88 | addr |= R300_PTE_UNSNOOPED; | 85 | addr |= R300_PTE_UNSNOOPED; |
| 86 | return addr; | ||
| 87 | } | ||
| 88 | |||
| 89 | void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, | ||
| 90 | uint64_t entry) | ||
| 91 | { | ||
| 92 | void __iomem *ptr = rdev->gart.ptr; | ||
| 93 | |||
| 89 | /* on x86 we want this to be CPU endian, on powerpc | 94 | /* on x86 we want this to be CPU endian, on powerpc |
| 90 | * on powerpc without HW swappers, it'll get swapped on way | 95 | * on powerpc without HW swappers, it'll get swapped on way |
| 91 | * into VRAM - so no need for cpu_to_le32 on VRAM tables */ | 96 | * into VRAM - so no need for cpu_to_le32 on VRAM tables */ |
| 92 | writel(addr, ((void __iomem *)ptr) + (i * 4)); | 97 | writel(entry, ((void __iomem *)ptr) + (i * 4)); |
| 93 | } | 98 | } |
| 94 | 99 | ||
| 95 | int rv370_pcie_gart_init(struct radeon_device *rdev) | 100 | int rv370_pcie_gart_init(struct radeon_device *rdev) |
| @@ -109,6 +114,7 @@ int rv370_pcie_gart_init(struct radeon_device *rdev) | |||
| 109 | DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); | 114 | DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); |
| 110 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; | 115 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; |
| 111 | rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; | 116 | rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; |
| 117 | rdev->asic->gart.get_page_entry = &rv370_pcie_gart_get_page_entry; | ||
| 112 | rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; | 118 | rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; |
| 113 | return radeon_gart_table_vram_alloc(rdev); | 119 | return radeon_gart_table_vram_alloc(rdev); |
| 114 | } | 120 | } |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 54529b837afa..3f2a8d3febca 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -242,6 +242,7 @@ bool radeon_get_bios(struct radeon_device *rdev); | |||
| 242 | * Dummy page | 242 | * Dummy page |
| 243 | */ | 243 | */ |
| 244 | struct radeon_dummy_page { | 244 | struct radeon_dummy_page { |
| 245 | uint64_t entry; | ||
| 245 | struct page *page; | 246 | struct page *page; |
| 246 | dma_addr_t addr; | 247 | dma_addr_t addr; |
| 247 | }; | 248 | }; |
| @@ -645,7 +646,7 @@ struct radeon_gart { | |||
| 645 | unsigned num_cpu_pages; | 646 | unsigned num_cpu_pages; |
| 646 | unsigned table_size; | 647 | unsigned table_size; |
| 647 | struct page **pages; | 648 | struct page **pages; |
| 648 | dma_addr_t *pages_addr; | 649 | uint64_t *pages_entry; |
| 649 | bool ready; | 650 | bool ready; |
| 650 | }; | 651 | }; |
| 651 | 652 | ||
| @@ -1847,8 +1848,9 @@ struct radeon_asic { | |||
| 1847 | /* gart */ | 1848 | /* gart */ |
| 1848 | struct { | 1849 | struct { |
| 1849 | void (*tlb_flush)(struct radeon_device *rdev); | 1850 | void (*tlb_flush)(struct radeon_device *rdev); |
| 1851 | uint64_t (*get_page_entry)(uint64_t addr, uint32_t flags); | ||
| 1850 | void (*set_page)(struct radeon_device *rdev, unsigned i, | 1852 | void (*set_page)(struct radeon_device *rdev, unsigned i, |
| 1851 | uint64_t addr, uint32_t flags); | 1853 | uint64_t entry); |
| 1852 | } gart; | 1854 | } gart; |
| 1853 | struct { | 1855 | struct { |
| 1854 | int (*init)(struct radeon_device *rdev); | 1856 | int (*init)(struct radeon_device *rdev); |
| @@ -2852,7 +2854,8 @@ static inline void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | |||
| 2852 | #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) | 2854 | #define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state)) |
| 2853 | #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev)) | 2855 | #define radeon_asic_reset(rdev) (rdev)->asic->asic_reset((rdev)) |
| 2854 | #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev)) | 2856 | #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart.tlb_flush((rdev)) |
| 2855 | #define radeon_gart_set_page(rdev, i, p, f) (rdev)->asic->gart.set_page((rdev), (i), (p), (f)) | 2857 | #define radeon_gart_get_page_entry(a, f) (rdev)->asic->gart.get_page_entry((a), (f)) |
| 2858 | #define radeon_gart_set_page(rdev, i, e) (rdev)->asic->gart.set_page((rdev), (i), (e)) | ||
| 2856 | #define radeon_asic_vm_init(rdev) (rdev)->asic->vm.init((rdev)) | 2859 | #define radeon_asic_vm_init(rdev) (rdev)->asic->vm.init((rdev)) |
| 2857 | #define radeon_asic_vm_fini(rdev) (rdev)->asic->vm.fini((rdev)) | 2860 | #define radeon_asic_vm_fini(rdev) (rdev)->asic->vm.fini((rdev)) |
| 2858 | #define radeon_asic_vm_copy_pages(rdev, ib, pe, src, count) ((rdev)->asic->vm.copy_pages((rdev), (ib), (pe), (src), (count))) | 2861 | #define radeon_asic_vm_copy_pages(rdev, ib, pe, src, count) ((rdev)->asic->vm.copy_pages((rdev), (ib), (pe), (src), (count))) |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 850de57069be..ed0e10eee2dc 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -159,11 +159,13 @@ void radeon_agp_disable(struct radeon_device *rdev) | |||
| 159 | DRM_INFO("Forcing AGP to PCIE mode\n"); | 159 | DRM_INFO("Forcing AGP to PCIE mode\n"); |
| 160 | rdev->flags |= RADEON_IS_PCIE; | 160 | rdev->flags |= RADEON_IS_PCIE; |
| 161 | rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; | 161 | rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush; |
| 162 | rdev->asic->gart.get_page_entry = &rv370_pcie_gart_get_page_entry; | ||
| 162 | rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; | 163 | rdev->asic->gart.set_page = &rv370_pcie_gart_set_page; |
| 163 | } else { | 164 | } else { |
| 164 | DRM_INFO("Forcing AGP to PCI mode\n"); | 165 | DRM_INFO("Forcing AGP to PCI mode\n"); |
| 165 | rdev->flags |= RADEON_IS_PCI; | 166 | rdev->flags |= RADEON_IS_PCI; |
| 166 | rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; | 167 | rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; |
| 168 | rdev->asic->gart.get_page_entry = &r100_pci_gart_get_page_entry; | ||
| 167 | rdev->asic->gart.set_page = &r100_pci_gart_set_page; | 169 | rdev->asic->gart.set_page = &r100_pci_gart_set_page; |
| 168 | } | 170 | } |
| 169 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | 171 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; |
| @@ -199,6 +201,7 @@ static struct radeon_asic r100_asic = { | |||
| 199 | .mc_wait_for_idle = &r100_mc_wait_for_idle, | 201 | .mc_wait_for_idle = &r100_mc_wait_for_idle, |
| 200 | .gart = { | 202 | .gart = { |
| 201 | .tlb_flush = &r100_pci_gart_tlb_flush, | 203 | .tlb_flush = &r100_pci_gart_tlb_flush, |
| 204 | .get_page_entry = &r100_pci_gart_get_page_entry, | ||
| 202 | .set_page = &r100_pci_gart_set_page, | 205 | .set_page = &r100_pci_gart_set_page, |
| 203 | }, | 206 | }, |
| 204 | .ring = { | 207 | .ring = { |
| @@ -265,6 +268,7 @@ static struct radeon_asic r200_asic = { | |||
| 265 | .mc_wait_for_idle = &r100_mc_wait_for_idle, | 268 | .mc_wait_for_idle = &r100_mc_wait_for_idle, |
| 266 | .gart = { | 269 | .gart = { |
| 267 | .tlb_flush = &r100_pci_gart_tlb_flush, | 270 | .tlb_flush = &r100_pci_gart_tlb_flush, |
| 271 | .get_page_entry = &r100_pci_gart_get_page_entry, | ||
| 268 | .set_page = &r100_pci_gart_set_page, | 272 | .set_page = &r100_pci_gart_set_page, |
| 269 | }, | 273 | }, |
| 270 | .ring = { | 274 | .ring = { |
| @@ -333,6 +337,20 @@ static struct radeon_asic_ring r300_gfx_ring = { | |||
| 333 | .set_wptr = &r100_gfx_set_wptr, | 337 | .set_wptr = &r100_gfx_set_wptr, |
| 334 | }; | 338 | }; |
| 335 | 339 | ||
| 340 | static struct radeon_asic_ring rv515_gfx_ring = { | ||
| 341 | .ib_execute = &r100_ring_ib_execute, | ||
| 342 | .emit_fence = &r300_fence_ring_emit, | ||
| 343 | .emit_semaphore = &r100_semaphore_ring_emit, | ||
| 344 | .cs_parse = &r300_cs_parse, | ||
| 345 | .ring_start = &rv515_ring_start, | ||
| 346 | .ring_test = &r100_ring_test, | ||
| 347 | .ib_test = &r100_ib_test, | ||
| 348 | .is_lockup = &r100_gpu_is_lockup, | ||
| 349 | .get_rptr = &r100_gfx_get_rptr, | ||
| 350 | .get_wptr = &r100_gfx_get_wptr, | ||
| 351 | .set_wptr = &r100_gfx_set_wptr, | ||
| 352 | }; | ||
| 353 | |||
| 336 | static struct radeon_asic r300_asic = { | 354 | static struct radeon_asic r300_asic = { |
| 337 | .init = &r300_init, | 355 | .init = &r300_init, |
| 338 | .fini = &r300_fini, | 356 | .fini = &r300_fini, |
| @@ -345,6 +363,7 @@ static struct radeon_asic r300_asic = { | |||
| 345 | .mc_wait_for_idle = &r300_mc_wait_for_idle, | 363 | .mc_wait_for_idle = &r300_mc_wait_for_idle, |
| 346 | .gart = { | 364 | .gart = { |
| 347 | .tlb_flush = &r100_pci_gart_tlb_flush, | 365 | .tlb_flush = &r100_pci_gart_tlb_flush, |
| 366 | .get_page_entry = &r100_pci_gart_get_page_entry, | ||
| 348 | .set_page = &r100_pci_gart_set_page, | 367 | .set_page = &r100_pci_gart_set_page, |
| 349 | }, | 368 | }, |
| 350 | .ring = { | 369 | .ring = { |
| @@ -411,6 +430,7 @@ static struct radeon_asic r300_asic_pcie = { | |||
| 411 | .mc_wait_for_idle = &r300_mc_wait_for_idle, | 430 | .mc_wait_for_idle = &r300_mc_wait_for_idle, |
| 412 | .gart = { | 431 | .gart = { |
| 413 | .tlb_flush = &rv370_pcie_gart_tlb_flush, | 432 | .tlb_flush = &rv370_pcie_gart_tlb_flush, |
| 433 | .get_page_entry = &rv370_pcie_gart_get_page_entry, | ||
| 414 | .set_page = &rv370_pcie_gart_set_page, | 434 | .set_page = &rv370_pcie_gart_set_page, |
| 415 | }, | 435 | }, |
| 416 | .ring = { | 436 | .ring = { |
| @@ -477,6 +497,7 @@ static struct radeon_asic r420_asic = { | |||
| 477 | .mc_wait_for_idle = &r300_mc_wait_for_idle, | 497 | .mc_wait_for_idle = &r300_mc_wait_for_idle, |
| 478 | .gart = { | 498 | .gart = { |
| 479 | .tlb_flush = &rv370_pcie_gart_tlb_flush, | 499 | .tlb_flush = &rv370_pcie_gart_tlb_flush, |
| 500 | .get_page_entry = &rv370_pcie_gart_get_page_entry, | ||
| 480 | .set_page = &rv370_pcie_gart_set_page, | 501 | .set_page = &rv370_pcie_gart_set_page, |
| 481 | }, | 502 | }, |
| 482 | .ring = { | 503 | .ring = { |
| @@ -543,6 +564,7 @@ static struct radeon_asic rs400_asic = { | |||
| 543 | .mc_wait_for_idle = &rs400_mc_wait_for_idle, | 564 | .mc_wait_for_idle = &rs400_mc_wait_for_idle, |
| 544 | .gart = { | 565 | .gart = { |
| 545 | .tlb_flush = &rs400_gart_tlb_flush, | 566 | .tlb_flush = &rs400_gart_tlb_flush, |
| 567 | .get_page_entry = &rs400_gart_get_page_entry, | ||
| 546 | .set_page = &rs400_gart_set_page, | 568 | .set_page = &rs400_gart_set_page, |
| 547 | }, | 569 | }, |
| 548 | .ring = { | 570 | .ring = { |
| @@ -609,6 +631,7 @@ static struct radeon_asic rs600_asic = { | |||
| 609 | .mc_wait_for_idle = &rs600_mc_wait_for_idle, | 631 | .mc_wait_for_idle = &rs600_mc_wait_for_idle, |
| 610 | .gart = { | 632 | .gart = { |
| 611 | .tlb_flush = &rs600_gart_tlb_flush, | 633 | .tlb_flush = &rs600_gart_tlb_flush, |
| 634 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 612 | .set_page = &rs600_gart_set_page, | 635 | .set_page = &rs600_gart_set_page, |
| 613 | }, | 636 | }, |
| 614 | .ring = { | 637 | .ring = { |
| @@ -677,6 +700,7 @@ static struct radeon_asic rs690_asic = { | |||
| 677 | .mc_wait_for_idle = &rs690_mc_wait_for_idle, | 700 | .mc_wait_for_idle = &rs690_mc_wait_for_idle, |
| 678 | .gart = { | 701 | .gart = { |
| 679 | .tlb_flush = &rs400_gart_tlb_flush, | 702 | .tlb_flush = &rs400_gart_tlb_flush, |
| 703 | .get_page_entry = &rs400_gart_get_page_entry, | ||
| 680 | .set_page = &rs400_gart_set_page, | 704 | .set_page = &rs400_gart_set_page, |
| 681 | }, | 705 | }, |
| 682 | .ring = { | 706 | .ring = { |
| @@ -745,10 +769,11 @@ static struct radeon_asic rv515_asic = { | |||
| 745 | .mc_wait_for_idle = &rv515_mc_wait_for_idle, | 769 | .mc_wait_for_idle = &rv515_mc_wait_for_idle, |
| 746 | .gart = { | 770 | .gart = { |
| 747 | .tlb_flush = &rv370_pcie_gart_tlb_flush, | 771 | .tlb_flush = &rv370_pcie_gart_tlb_flush, |
| 772 | .get_page_entry = &rv370_pcie_gart_get_page_entry, | ||
| 748 | .set_page = &rv370_pcie_gart_set_page, | 773 | .set_page = &rv370_pcie_gart_set_page, |
| 749 | }, | 774 | }, |
| 750 | .ring = { | 775 | .ring = { |
| 751 | [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring | 776 | [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring |
| 752 | }, | 777 | }, |
| 753 | .irq = { | 778 | .irq = { |
| 754 | .set = &rs600_irq_set, | 779 | .set = &rs600_irq_set, |
| @@ -811,10 +836,11 @@ static struct radeon_asic r520_asic = { | |||
| 811 | .mc_wait_for_idle = &r520_mc_wait_for_idle, | 836 | .mc_wait_for_idle = &r520_mc_wait_for_idle, |
| 812 | .gart = { | 837 | .gart = { |
| 813 | .tlb_flush = &rv370_pcie_gart_tlb_flush, | 838 | .tlb_flush = &rv370_pcie_gart_tlb_flush, |
| 839 | .get_page_entry = &rv370_pcie_gart_get_page_entry, | ||
| 814 | .set_page = &rv370_pcie_gart_set_page, | 840 | .set_page = &rv370_pcie_gart_set_page, |
| 815 | }, | 841 | }, |
| 816 | .ring = { | 842 | .ring = { |
| 817 | [RADEON_RING_TYPE_GFX_INDEX] = &r300_gfx_ring | 843 | [RADEON_RING_TYPE_GFX_INDEX] = &rv515_gfx_ring |
| 818 | }, | 844 | }, |
| 819 | .irq = { | 845 | .irq = { |
| 820 | .set = &rs600_irq_set, | 846 | .set = &rs600_irq_set, |
| @@ -905,6 +931,7 @@ static struct radeon_asic r600_asic = { | |||
| 905 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 931 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 906 | .gart = { | 932 | .gart = { |
| 907 | .tlb_flush = &r600_pcie_gart_tlb_flush, | 933 | .tlb_flush = &r600_pcie_gart_tlb_flush, |
| 934 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 908 | .set_page = &rs600_gart_set_page, | 935 | .set_page = &rs600_gart_set_page, |
| 909 | }, | 936 | }, |
| 910 | .ring = { | 937 | .ring = { |
| @@ -990,6 +1017,7 @@ static struct radeon_asic rv6xx_asic = { | |||
| 990 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1017 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 991 | .gart = { | 1018 | .gart = { |
| 992 | .tlb_flush = &r600_pcie_gart_tlb_flush, | 1019 | .tlb_flush = &r600_pcie_gart_tlb_flush, |
| 1020 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 993 | .set_page = &rs600_gart_set_page, | 1021 | .set_page = &rs600_gart_set_page, |
| 994 | }, | 1022 | }, |
| 995 | .ring = { | 1023 | .ring = { |
| @@ -1081,6 +1109,7 @@ static struct radeon_asic rs780_asic = { | |||
| 1081 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1109 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1082 | .gart = { | 1110 | .gart = { |
| 1083 | .tlb_flush = &r600_pcie_gart_tlb_flush, | 1111 | .tlb_flush = &r600_pcie_gart_tlb_flush, |
| 1112 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1084 | .set_page = &rs600_gart_set_page, | 1113 | .set_page = &rs600_gart_set_page, |
| 1085 | }, | 1114 | }, |
| 1086 | .ring = { | 1115 | .ring = { |
| @@ -1185,6 +1214,7 @@ static struct radeon_asic rv770_asic = { | |||
| 1185 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1214 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1186 | .gart = { | 1215 | .gart = { |
| 1187 | .tlb_flush = &r600_pcie_gart_tlb_flush, | 1216 | .tlb_flush = &r600_pcie_gart_tlb_flush, |
| 1217 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1188 | .set_page = &rs600_gart_set_page, | 1218 | .set_page = &rs600_gart_set_page, |
| 1189 | }, | 1219 | }, |
| 1190 | .ring = { | 1220 | .ring = { |
| @@ -1303,6 +1333,7 @@ static struct radeon_asic evergreen_asic = { | |||
| 1303 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1333 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1304 | .gart = { | 1334 | .gart = { |
| 1305 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, | 1335 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, |
| 1336 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1306 | .set_page = &rs600_gart_set_page, | 1337 | .set_page = &rs600_gart_set_page, |
| 1307 | }, | 1338 | }, |
| 1308 | .ring = { | 1339 | .ring = { |
| @@ -1395,6 +1426,7 @@ static struct radeon_asic sumo_asic = { | |||
| 1395 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1426 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1396 | .gart = { | 1427 | .gart = { |
| 1397 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, | 1428 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, |
| 1429 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1398 | .set_page = &rs600_gart_set_page, | 1430 | .set_page = &rs600_gart_set_page, |
| 1399 | }, | 1431 | }, |
| 1400 | .ring = { | 1432 | .ring = { |
| @@ -1486,6 +1518,7 @@ static struct radeon_asic btc_asic = { | |||
| 1486 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1518 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1487 | .gart = { | 1519 | .gart = { |
| 1488 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, | 1520 | .tlb_flush = &evergreen_pcie_gart_tlb_flush, |
| 1521 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1489 | .set_page = &rs600_gart_set_page, | 1522 | .set_page = &rs600_gart_set_page, |
| 1490 | }, | 1523 | }, |
| 1491 | .ring = { | 1524 | .ring = { |
| @@ -1621,6 +1654,7 @@ static struct radeon_asic cayman_asic = { | |||
| 1621 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1654 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1622 | .gart = { | 1655 | .gart = { |
| 1623 | .tlb_flush = &cayman_pcie_gart_tlb_flush, | 1656 | .tlb_flush = &cayman_pcie_gart_tlb_flush, |
| 1657 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1624 | .set_page = &rs600_gart_set_page, | 1658 | .set_page = &rs600_gart_set_page, |
| 1625 | }, | 1659 | }, |
| 1626 | .vm = { | 1660 | .vm = { |
| @@ -1724,6 +1758,7 @@ static struct radeon_asic trinity_asic = { | |||
| 1724 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, | 1758 | .get_gpu_clock_counter = &r600_get_gpu_clock_counter, |
| 1725 | .gart = { | 1759 | .gart = { |
| 1726 | .tlb_flush = &cayman_pcie_gart_tlb_flush, | 1760 | .tlb_flush = &cayman_pcie_gart_tlb_flush, |
| 1761 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1727 | .set_page = &rs600_gart_set_page, | 1762 | .set_page = &rs600_gart_set_page, |
| 1728 | }, | 1763 | }, |
| 1729 | .vm = { | 1764 | .vm = { |
| @@ -1857,6 +1892,7 @@ static struct radeon_asic si_asic = { | |||
| 1857 | .get_gpu_clock_counter = &si_get_gpu_clock_counter, | 1892 | .get_gpu_clock_counter = &si_get_gpu_clock_counter, |
| 1858 | .gart = { | 1893 | .gart = { |
| 1859 | .tlb_flush = &si_pcie_gart_tlb_flush, | 1894 | .tlb_flush = &si_pcie_gart_tlb_flush, |
| 1895 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 1860 | .set_page = &rs600_gart_set_page, | 1896 | .set_page = &rs600_gart_set_page, |
| 1861 | }, | 1897 | }, |
| 1862 | .vm = { | 1898 | .vm = { |
| @@ -2018,6 +2054,7 @@ static struct radeon_asic ci_asic = { | |||
| 2018 | .get_gpu_clock_counter = &cik_get_gpu_clock_counter, | 2054 | .get_gpu_clock_counter = &cik_get_gpu_clock_counter, |
| 2019 | .gart = { | 2055 | .gart = { |
| 2020 | .tlb_flush = &cik_pcie_gart_tlb_flush, | 2056 | .tlb_flush = &cik_pcie_gart_tlb_flush, |
| 2057 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 2021 | .set_page = &rs600_gart_set_page, | 2058 | .set_page = &rs600_gart_set_page, |
| 2022 | }, | 2059 | }, |
| 2023 | .vm = { | 2060 | .vm = { |
| @@ -2125,6 +2162,7 @@ static struct radeon_asic kv_asic = { | |||
| 2125 | .get_gpu_clock_counter = &cik_get_gpu_clock_counter, | 2162 | .get_gpu_clock_counter = &cik_get_gpu_clock_counter, |
| 2126 | .gart = { | 2163 | .gart = { |
| 2127 | .tlb_flush = &cik_pcie_gart_tlb_flush, | 2164 | .tlb_flush = &cik_pcie_gart_tlb_flush, |
| 2165 | .get_page_entry = &rs600_gart_get_page_entry, | ||
| 2128 | .set_page = &rs600_gart_set_page, | 2166 | .set_page = &rs600_gart_set_page, |
| 2129 | }, | 2167 | }, |
| 2130 | .vm = { | 2168 | .vm = { |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 2a45d548d5ec..8d787d115653 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -67,8 +67,9 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *cp); | |||
| 67 | int r100_asic_reset(struct radeon_device *rdev); | 67 | int r100_asic_reset(struct radeon_device *rdev); |
| 68 | u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); | 68 | u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc); |
| 69 | void r100_pci_gart_tlb_flush(struct radeon_device *rdev); | 69 | void r100_pci_gart_tlb_flush(struct radeon_device *rdev); |
| 70 | uint64_t r100_pci_gart_get_page_entry(uint64_t addr, uint32_t flags); | ||
| 70 | void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, | 71 | void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, |
| 71 | uint64_t addr, uint32_t flags); | 72 | uint64_t entry); |
| 72 | void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); | 73 | void r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring); |
| 73 | int r100_irq_set(struct radeon_device *rdev); | 74 | int r100_irq_set(struct radeon_device *rdev); |
| 74 | int r100_irq_process(struct radeon_device *rdev); | 75 | int r100_irq_process(struct radeon_device *rdev); |
| @@ -172,8 +173,9 @@ extern void r300_fence_ring_emit(struct radeon_device *rdev, | |||
| 172 | struct radeon_fence *fence); | 173 | struct radeon_fence *fence); |
| 173 | extern int r300_cs_parse(struct radeon_cs_parser *p); | 174 | extern int r300_cs_parse(struct radeon_cs_parser *p); |
| 174 | extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); | 175 | extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); |
| 176 | extern uint64_t rv370_pcie_gart_get_page_entry(uint64_t addr, uint32_t flags); | ||
| 175 | extern void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, | 177 | extern void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i, |
| 176 | uint64_t addr, uint32_t flags); | 178 | uint64_t entry); |
| 177 | extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); | 179 | extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); |
| 178 | extern int rv370_get_pcie_lanes(struct radeon_device *rdev); | 180 | extern int rv370_get_pcie_lanes(struct radeon_device *rdev); |
| 179 | extern void r300_set_reg_safe(struct radeon_device *rdev); | 181 | extern void r300_set_reg_safe(struct radeon_device *rdev); |
| @@ -208,8 +210,9 @@ extern void rs400_fini(struct radeon_device *rdev); | |||
| 208 | extern int rs400_suspend(struct radeon_device *rdev); | 210 | extern int rs400_suspend(struct radeon_device *rdev); |
| 209 | extern int rs400_resume(struct radeon_device *rdev); | 211 | extern int rs400_resume(struct radeon_device *rdev); |
| 210 | void rs400_gart_tlb_flush(struct radeon_device *rdev); | 212 | void rs400_gart_tlb_flush(struct radeon_device *rdev); |
| 213 | uint64_t rs400_gart_get_page_entry(uint64_t addr, uint32_t flags); | ||
| 211 | void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, | 214 | void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, |
| 212 | uint64_t addr, uint32_t flags); | 215 | uint64_t entry); |
| 213 | uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); | 216 | uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); |
| 214 | void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 217 | void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
| 215 | int rs400_gart_init(struct radeon_device *rdev); | 218 | int rs400_gart_init(struct radeon_device *rdev); |
| @@ -232,8 +235,9 @@ int rs600_irq_process(struct radeon_device *rdev); | |||
| 232 | void rs600_irq_disable(struct radeon_device *rdev); | 235 | void rs600_irq_disable(struct radeon_device *rdev); |
| 233 | u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); | 236 | u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc); |
| 234 | void rs600_gart_tlb_flush(struct radeon_device *rdev); | 237 | void rs600_gart_tlb_flush(struct radeon_device *rdev); |
| 238 | uint64_t rs600_gart_get_page_entry(uint64_t addr, uint32_t flags); | ||
| 235 | void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, | 239 | void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, |
| 236 | uint64_t addr, uint32_t flags); | 240 | uint64_t entry); |
| 237 | uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); | 241 | uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); |
| 238 | void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 242 | void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
| 239 | void rs600_bandwidth_update(struct radeon_device *rdev); | 243 | void rs600_bandwidth_update(struct radeon_device *rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 9e7f23dd14bd..87d5fb21cb61 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
| @@ -34,7 +34,8 @@ | |||
| 34 | 34 | ||
| 35 | static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, | 35 | static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, |
| 36 | uint64_t saddr, uint64_t daddr, | 36 | uint64_t saddr, uint64_t daddr, |
| 37 | int flag, int n) | 37 | int flag, int n, |
| 38 | struct reservation_object *resv) | ||
| 38 | { | 39 | { |
| 39 | unsigned long start_jiffies; | 40 | unsigned long start_jiffies; |
| 40 | unsigned long end_jiffies; | 41 | unsigned long end_jiffies; |
| @@ -47,12 +48,12 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, | |||
| 47 | case RADEON_BENCHMARK_COPY_DMA: | 48 | case RADEON_BENCHMARK_COPY_DMA: |
| 48 | fence = radeon_copy_dma(rdev, saddr, daddr, | 49 | fence = radeon_copy_dma(rdev, saddr, daddr, |
| 49 | size / RADEON_GPU_PAGE_SIZE, | 50 | size / RADEON_GPU_PAGE_SIZE, |
| 50 | NULL); | 51 | resv); |
| 51 | break; | 52 | break; |
| 52 | case RADEON_BENCHMARK_COPY_BLIT: | 53 | case RADEON_BENCHMARK_COPY_BLIT: |
| 53 | fence = radeon_copy_blit(rdev, saddr, daddr, | 54 | fence = radeon_copy_blit(rdev, saddr, daddr, |
| 54 | size / RADEON_GPU_PAGE_SIZE, | 55 | size / RADEON_GPU_PAGE_SIZE, |
| 55 | NULL); | 56 | resv); |
| 56 | break; | 57 | break; |
| 57 | default: | 58 | default: |
| 58 | DRM_ERROR("Unknown copy method\n"); | 59 | DRM_ERROR("Unknown copy method\n"); |
| @@ -120,7 +121,8 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, | |||
| 120 | 121 | ||
| 121 | if (rdev->asic->copy.dma) { | 122 | if (rdev->asic->copy.dma) { |
| 122 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, | 123 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, |
| 123 | RADEON_BENCHMARK_COPY_DMA, n); | 124 | RADEON_BENCHMARK_COPY_DMA, n, |
| 125 | dobj->tbo.resv); | ||
| 124 | if (time < 0) | 126 | if (time < 0) |
| 125 | goto out_cleanup; | 127 | goto out_cleanup; |
| 126 | if (time > 0) | 128 | if (time > 0) |
| @@ -130,7 +132,8 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, | |||
| 130 | 132 | ||
| 131 | if (rdev->asic->copy.blit) { | 133 | if (rdev->asic->copy.blit) { |
| 132 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, | 134 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, |
| 133 | RADEON_BENCHMARK_COPY_BLIT, n); | 135 | RADEON_BENCHMARK_COPY_BLIT, n, |
| 136 | dobj->tbo.resv); | ||
| 134 | if (time < 0) | 137 | if (time < 0) |
| 135 | goto out_cleanup; | 138 | goto out_cleanup; |
| 136 | if (time > 0) | 139 | if (time > 0) |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0ec65168f331..bd7519fdd3f4 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -774,6 +774,8 @@ int radeon_dummy_page_init(struct radeon_device *rdev) | |||
| 774 | rdev->dummy_page.page = NULL; | 774 | rdev->dummy_page.page = NULL; |
| 775 | return -ENOMEM; | 775 | return -ENOMEM; |
| 776 | } | 776 | } |
| 777 | rdev->dummy_page.entry = radeon_gart_get_page_entry(rdev->dummy_page.addr, | ||
| 778 | RADEON_GART_PAGE_DUMMY); | ||
| 777 | return 0; | 779 | return 0; |
| 778 | } | 780 | } |
| 779 | 781 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 102116902a07..913fafa597ad 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -960,6 +960,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
| 960 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && | 960 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV && |
| 961 | pll->flags & RADEON_PLL_USE_REF_DIV) | 961 | pll->flags & RADEON_PLL_USE_REF_DIV) |
| 962 | ref_div_max = pll->reference_div; | 962 | ref_div_max = pll->reference_div; |
| 963 | else if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) | ||
| 964 | /* fix for problems on RS880 */ | ||
| 965 | ref_div_max = min(pll->max_ref_div, 7u); | ||
| 963 | else | 966 | else |
| 964 | ref_div_max = pll->max_ref_div; | 967 | ref_div_max = pll->max_ref_div; |
| 965 | 968 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 84146d5901aa..5450fa95a47e 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -165,6 +165,19 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev) | |||
| 165 | radeon_bo_unpin(rdev->gart.robj); | 165 | radeon_bo_unpin(rdev->gart.robj); |
| 166 | radeon_bo_unreserve(rdev->gart.robj); | 166 | radeon_bo_unreserve(rdev->gart.robj); |
| 167 | rdev->gart.table_addr = gpu_addr; | 167 | rdev->gart.table_addr = gpu_addr; |
| 168 | |||
| 169 | if (!r) { | ||
| 170 | int i; | ||
| 171 | |||
| 172 | /* We might have dropped some GART table updates while it wasn't | ||
| 173 | * mapped, restore all entries | ||
| 174 | */ | ||
| 175 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) | ||
| 176 | radeon_gart_set_page(rdev, i, rdev->gart.pages_entry[i]); | ||
| 177 | mb(); | ||
| 178 | radeon_gart_tlb_flush(rdev); | ||
| 179 | } | ||
| 180 | |||
| 168 | return r; | 181 | return r; |
| 169 | } | 182 | } |
| 170 | 183 | ||
| @@ -228,7 +241,6 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
| 228 | unsigned t; | 241 | unsigned t; |
| 229 | unsigned p; | 242 | unsigned p; |
| 230 | int i, j; | 243 | int i, j; |
| 231 | u64 page_base; | ||
| 232 | 244 | ||
| 233 | if (!rdev->gart.ready) { | 245 | if (!rdev->gart.ready) { |
| 234 | WARN(1, "trying to unbind memory from uninitialized GART !\n"); | 246 | WARN(1, "trying to unbind memory from uninitialized GART !\n"); |
| @@ -239,14 +251,12 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | |||
| 239 | for (i = 0; i < pages; i++, p++) { | 251 | for (i = 0; i < pages; i++, p++) { |
| 240 | if (rdev->gart.pages[p]) { | 252 | if (rdev->gart.pages[p]) { |
| 241 | rdev->gart.pages[p] = NULL; | 253 | rdev->gart.pages[p] = NULL; |
| 242 | rdev->gart.pages_addr[p] = rdev->dummy_page.addr; | ||
| 243 | page_base = rdev->gart.pages_addr[p]; | ||
| 244 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { | 254 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
| 255 | rdev->gart.pages_entry[t] = rdev->dummy_page.entry; | ||
| 245 | if (rdev->gart.ptr) { | 256 | if (rdev->gart.ptr) { |
| 246 | radeon_gart_set_page(rdev, t, page_base, | 257 | radeon_gart_set_page(rdev, t, |
| 247 | RADEON_GART_PAGE_DUMMY); | 258 | rdev->dummy_page.entry); |
| 248 | } | 259 | } |
| 249 | page_base += RADEON_GPU_PAGE_SIZE; | ||
| 250 | } | 260 | } |
| 251 | } | 261 | } |
| 252 | } | 262 | } |
| @@ -274,7 +284,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
| 274 | { | 284 | { |
| 275 | unsigned t; | 285 | unsigned t; |
| 276 | unsigned p; | 286 | unsigned p; |
| 277 | uint64_t page_base; | 287 | uint64_t page_base, page_entry; |
| 278 | int i, j; | 288 | int i, j; |
| 279 | 289 | ||
| 280 | if (!rdev->gart.ready) { | 290 | if (!rdev->gart.ready) { |
| @@ -285,14 +295,15 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | |||
| 285 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); | 295 | p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); |
| 286 | 296 | ||
| 287 | for (i = 0; i < pages; i++, p++) { | 297 | for (i = 0; i < pages; i++, p++) { |
| 288 | rdev->gart.pages_addr[p] = dma_addr[i]; | ||
| 289 | rdev->gart.pages[p] = pagelist[i]; | 298 | rdev->gart.pages[p] = pagelist[i]; |
| 290 | if (rdev->gart.ptr) { | 299 | page_base = dma_addr[i]; |
| 291 | page_base = rdev->gart.pages_addr[p]; | 300 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { |
| 292 | for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) { | 301 | page_entry = radeon_gart_get_page_entry(page_base, flags); |
| 293 | radeon_gart_set_page(rdev, t, page_base, flags); | 302 | rdev->gart.pages_entry[t] = page_entry; |
| 294 | page_base += RADEON_GPU_PAGE_SIZE; | 303 | if (rdev->gart.ptr) { |
| 304 | radeon_gart_set_page(rdev, t, page_entry); | ||
| 295 | } | 305 | } |
| 306 | page_base += RADEON_GPU_PAGE_SIZE; | ||
| 296 | } | 307 | } |
| 297 | } | 308 | } |
| 298 | mb(); | 309 | mb(); |
| @@ -334,16 +345,15 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
| 334 | radeon_gart_fini(rdev); | 345 | radeon_gart_fini(rdev); |
| 335 | return -ENOMEM; | 346 | return -ENOMEM; |
| 336 | } | 347 | } |
| 337 | rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) * | 348 | rdev->gart.pages_entry = vmalloc(sizeof(uint64_t) * |
| 338 | rdev->gart.num_cpu_pages); | 349 | rdev->gart.num_gpu_pages); |
| 339 | if (rdev->gart.pages_addr == NULL) { | 350 | if (rdev->gart.pages_entry == NULL) { |
| 340 | radeon_gart_fini(rdev); | 351 | radeon_gart_fini(rdev); |
| 341 | return -ENOMEM; | 352 | return -ENOMEM; |
| 342 | } | 353 | } |
| 343 | /* set GART entry to point to the dummy page by default */ | 354 | /* set GART entry to point to the dummy page by default */ |
| 344 | for (i = 0; i < rdev->gart.num_cpu_pages; i++) { | 355 | for (i = 0; i < rdev->gart.num_gpu_pages; i++) |
| 345 | rdev->gart.pages_addr[i] = rdev->dummy_page.addr; | 356 | rdev->gart.pages_entry[i] = rdev->dummy_page.entry; |
| 346 | } | ||
| 347 | return 0; | 357 | return 0; |
| 348 | } | 358 | } |
| 349 | 359 | ||
| @@ -356,15 +366,15 @@ int radeon_gart_init(struct radeon_device *rdev) | |||
| 356 | */ | 366 | */ |
| 357 | void radeon_gart_fini(struct radeon_device *rdev) | 367 | void radeon_gart_fini(struct radeon_device *rdev) |
| 358 | { | 368 | { |
| 359 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { | 369 | if (rdev->gart.ready) { |
| 360 | /* unbind pages */ | 370 | /* unbind pages */ |
| 361 | radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); | 371 | radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); |
| 362 | } | 372 | } |
| 363 | rdev->gart.ready = false; | 373 | rdev->gart.ready = false; |
| 364 | vfree(rdev->gart.pages); | 374 | vfree(rdev->gart.pages); |
| 365 | vfree(rdev->gart.pages_addr); | 375 | vfree(rdev->gart.pages_entry); |
| 366 | rdev->gart.pages = NULL; | 376 | rdev->gart.pages = NULL; |
| 367 | rdev->gart.pages_addr = NULL; | 377 | rdev->gart.pages_entry = NULL; |
| 368 | 378 | ||
| 369 | radeon_dummy_page_fini(rdev); | 379 | radeon_dummy_page_fini(rdev); |
| 370 | } | 380 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index fe48f229043e..ac3c1310b953 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -146,7 +146,8 @@ int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_pri | |||
| 146 | struct radeon_bo_va *bo_va; | 146 | struct radeon_bo_va *bo_va; |
| 147 | int r; | 147 | int r; |
| 148 | 148 | ||
| 149 | if (rdev->family < CHIP_CAYMAN) { | 149 | if ((rdev->family < CHIP_CAYMAN) || |
| 150 | (!rdev->accel_working)) { | ||
| 150 | return 0; | 151 | return 0; |
| 151 | } | 152 | } |
| 152 | 153 | ||
| @@ -176,7 +177,8 @@ void radeon_gem_object_close(struct drm_gem_object *obj, | |||
| 176 | struct radeon_bo_va *bo_va; | 177 | struct radeon_bo_va *bo_va; |
| 177 | int r; | 178 | int r; |
| 178 | 179 | ||
| 179 | if (rdev->family < CHIP_CAYMAN) { | 180 | if ((rdev->family < CHIP_CAYMAN) || |
| 181 | (!rdev->accel_working)) { | ||
| 180 | return; | 182 | return; |
| 181 | } | 183 | } |
| 182 | 184 | ||
| @@ -394,10 +396,9 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 394 | return r; | 396 | return r; |
| 395 | } | 397 | } |
| 396 | 398 | ||
| 397 | static int radeon_mode_mmap(struct drm_file *filp, | 399 | int radeon_mode_dumb_mmap(struct drm_file *filp, |
| 398 | struct drm_device *dev, | 400 | struct drm_device *dev, |
| 399 | uint32_t handle, bool dumb, | 401 | uint32_t handle, uint64_t *offset_p) |
| 400 | uint64_t *offset_p) | ||
| 401 | { | 402 | { |
| 402 | struct drm_gem_object *gobj; | 403 | struct drm_gem_object *gobj; |
| 403 | struct radeon_bo *robj; | 404 | struct radeon_bo *robj; |
| @@ -406,14 +407,6 @@ static int radeon_mode_mmap(struct drm_file *filp, | |||
| 406 | if (gobj == NULL) { | 407 | if (gobj == NULL) { |
| 407 | return -ENOENT; | 408 | return -ENOENT; |
| 408 | } | 409 | } |
| 409 | |||
| 410 | /* | ||
| 411 | * We don't allow dumb mmaps on objects created using another | ||
| 412 | * interface. | ||
| 413 | */ | ||
| 414 | WARN_ONCE(dumb && !(gobj->dumb || gobj->import_attach), | ||
| 415 | "Illegal dumb map of GPU buffer.\n"); | ||
| 416 | |||
| 417 | robj = gem_to_radeon_bo(gobj); | 410 | robj = gem_to_radeon_bo(gobj); |
| 418 | if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) { | 411 | if (radeon_ttm_tt_has_userptr(robj->tbo.ttm)) { |
| 419 | drm_gem_object_unreference_unlocked(gobj); | 412 | drm_gem_object_unreference_unlocked(gobj); |
| @@ -424,20 +417,12 @@ static int radeon_mode_mmap(struct drm_file *filp, | |||
| 424 | return 0; | 417 | return 0; |
| 425 | } | 418 | } |
| 426 | 419 | ||
| 427 | int radeon_mode_dumb_mmap(struct drm_file *filp, | ||
| 428 | struct drm_device *dev, | ||
| 429 | uint32_t handle, uint64_t *offset_p) | ||
| 430 | { | ||
| 431 | return radeon_mode_mmap(filp, dev, handle, true, offset_p); | ||
| 432 | } | ||
| 433 | |||
| 434 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | 420 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, |
| 435 | struct drm_file *filp) | 421 | struct drm_file *filp) |
| 436 | { | 422 | { |
| 437 | struct drm_radeon_gem_mmap *args = data; | 423 | struct drm_radeon_gem_mmap *args = data; |
| 438 | 424 | ||
| 439 | return radeon_mode_mmap(filp, dev, args->handle, false, | 425 | return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr); |
| 440 | &args->addr_ptr); | ||
| 441 | } | 426 | } |
| 442 | 427 | ||
| 443 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | 428 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, |
| @@ -593,7 +578,7 @@ error_unreserve: | |||
| 593 | error_free: | 578 | error_free: |
| 594 | drm_free_large(vm_bos); | 579 | drm_free_large(vm_bos); |
| 595 | 580 | ||
| 596 | if (r) | 581 | if (r && r != -ERESTARTSYS) |
| 597 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); | 582 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); |
| 598 | } | 583 | } |
| 599 | 584 | ||
| @@ -763,7 +748,6 @@ int radeon_mode_dumb_create(struct drm_file *file_priv, | |||
| 763 | return -ENOMEM; | 748 | return -ENOMEM; |
| 764 | 749 | ||
| 765 | r = drm_gem_handle_create(file_priv, gobj, &handle); | 750 | r = drm_gem_handle_create(file_priv, gobj, &handle); |
| 766 | gobj->dumb = true; | ||
| 767 | /* drop reference from allocate - handle holds it now */ | 751 | /* drop reference from allocate - handle holds it now */ |
| 768 | drm_gem_object_unreference_unlocked(gobj); | 752 | drm_gem_object_unreference_unlocked(gobj); |
| 769 | if (r) { | 753 | if (r) { |
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 065d02068ec3..bef9a0953284 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include "cikd.h" | 28 | #include "cikd.h" |
| 29 | #include "cik_reg.h" | 29 | #include "cik_reg.h" |
| 30 | #include "radeon_kfd.h" | 30 | #include "radeon_kfd.h" |
| 31 | #include "radeon_ucode.h" | ||
| 32 | #include <linux/firmware.h> | ||
| 31 | 33 | ||
| 32 | #define CIK_PIPE_PER_MEC (4) | 34 | #define CIK_PIPE_PER_MEC (4) |
| 33 | 35 | ||
| @@ -49,6 +51,7 @@ static uint64_t get_vmem_size(struct kgd_dev *kgd); | |||
| 49 | static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); | 51 | static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); |
| 50 | 52 | ||
| 51 | static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); | 53 | static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); |
| 54 | static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type); | ||
| 52 | 55 | ||
| 53 | /* | 56 | /* |
| 54 | * Register access functions | 57 | * Register access functions |
| @@ -69,7 +72,7 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, | |||
| 69 | static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | 72 | static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, |
| 70 | uint32_t queue_id, uint32_t __user *wptr); | 73 | uint32_t queue_id, uint32_t __user *wptr); |
| 71 | 74 | ||
| 72 | static bool kgd_hqd_is_occupies(struct kgd_dev *kgd, uint64_t queue_address, | 75 | static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, |
| 73 | uint32_t pipe_id, uint32_t queue_id); | 76 | uint32_t pipe_id, uint32_t queue_id); |
| 74 | 77 | ||
| 75 | static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | 78 | static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, |
| @@ -89,14 +92,16 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
| 89 | .init_memory = kgd_init_memory, | 92 | .init_memory = kgd_init_memory, |
| 90 | .init_pipeline = kgd_init_pipeline, | 93 | .init_pipeline = kgd_init_pipeline, |
| 91 | .hqd_load = kgd_hqd_load, | 94 | .hqd_load = kgd_hqd_load, |
| 92 | .hqd_is_occupies = kgd_hqd_is_occupies, | 95 | .hqd_is_occupied = kgd_hqd_is_occupied, |
| 93 | .hqd_destroy = kgd_hqd_destroy, | 96 | .hqd_destroy = kgd_hqd_destroy, |
| 97 | .get_fw_version = get_fw_version | ||
| 94 | }; | 98 | }; |
| 95 | 99 | ||
| 96 | static const struct kgd2kfd_calls *kgd2kfd; | 100 | static const struct kgd2kfd_calls *kgd2kfd; |
| 97 | 101 | ||
| 98 | bool radeon_kfd_init(void) | 102 | bool radeon_kfd_init(void) |
| 99 | { | 103 | { |
| 104 | #if defined(CONFIG_HSA_AMD_MODULE) | ||
| 100 | bool (*kgd2kfd_init_p)(unsigned, const struct kfd2kgd_calls*, | 105 | bool (*kgd2kfd_init_p)(unsigned, const struct kfd2kgd_calls*, |
| 101 | const struct kgd2kfd_calls**); | 106 | const struct kgd2kfd_calls**); |
| 102 | 107 | ||
| @@ -113,6 +118,17 @@ bool radeon_kfd_init(void) | |||
| 113 | } | 118 | } |
| 114 | 119 | ||
| 115 | return true; | 120 | return true; |
| 121 | #elif defined(CONFIG_HSA_AMD) | ||
| 122 | if (!kgd2kfd_init(KFD_INTERFACE_VERSION, &kfd2kgd, &kgd2kfd)) { | ||
| 123 | kgd2kfd = NULL; | ||
| 124 | |||
| 125 | return false; | ||
| 126 | } | ||
| 127 | |||
| 128 | return true; | ||
| 129 | #else | ||
| 130 | return false; | ||
| 131 | #endif | ||
| 116 | } | 132 | } |
| 117 | 133 | ||
| 118 | void radeon_kfd_fini(void) | 134 | void radeon_kfd_fini(void) |
| @@ -374,6 +390,10 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, | |||
| 374 | cpu_relax(); | 390 | cpu_relax(); |
| 375 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); | 391 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); |
| 376 | 392 | ||
| 393 | /* Mapping vmid to pasid also for IH block */ | ||
| 394 | write_register(kgd, IH_VMID_0_LUT + vmid * sizeof(uint32_t), | ||
| 395 | pasid_mapping); | ||
| 396 | |||
| 377 | return 0; | 397 | return 0; |
| 378 | } | 398 | } |
| 379 | 399 | ||
| @@ -416,7 +436,7 @@ static int kgd_init_memory(struct kgd_dev *kgd) | |||
| 416 | static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, | 436 | static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, |
| 417 | uint32_t hpd_size, uint64_t hpd_gpu_addr) | 437 | uint32_t hpd_size, uint64_t hpd_gpu_addr) |
| 418 | { | 438 | { |
| 419 | uint32_t mec = (++pipe_id / CIK_PIPE_PER_MEC) + 1; | 439 | uint32_t mec = (pipe_id / CIK_PIPE_PER_MEC) + 1; |
| 420 | uint32_t pipe = (pipe_id % CIK_PIPE_PER_MEC); | 440 | uint32_t pipe = (pipe_id % CIK_PIPE_PER_MEC); |
| 421 | 441 | ||
| 422 | lock_srbm(kgd, mec, pipe, 0, 0); | 442 | lock_srbm(kgd, mec, pipe, 0, 0); |
| @@ -513,7 +533,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | |||
| 513 | return 0; | 533 | return 0; |
| 514 | } | 534 | } |
| 515 | 535 | ||
| 516 | static bool kgd_hqd_is_occupies(struct kgd_dev *kgd, uint64_t queue_address, | 536 | static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, |
| 517 | uint32_t pipe_id, uint32_t queue_id) | 537 | uint32_t pipe_id, uint32_t queue_id) |
| 518 | { | 538 | { |
| 519 | uint32_t act; | 539 | uint32_t act; |
| @@ -552,6 +572,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | |||
| 552 | if (timeout == 0) { | 572 | if (timeout == 0) { |
| 553 | pr_err("kfd: cp queue preemption time out (%dms)\n", | 573 | pr_err("kfd: cp queue preemption time out (%dms)\n", |
| 554 | temp); | 574 | temp); |
| 575 | release_queue(kgd); | ||
| 555 | return -ETIME; | 576 | return -ETIME; |
| 556 | } | 577 | } |
| 557 | msleep(20); | 578 | msleep(20); |
| @@ -561,3 +582,52 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | |||
| 561 | release_queue(kgd); | 582 | release_queue(kgd); |
| 562 | return 0; | 583 | return 0; |
| 563 | } | 584 | } |
| 585 | |||
| 586 | static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type) | ||
| 587 | { | ||
| 588 | struct radeon_device *rdev = (struct radeon_device *) kgd; | ||
| 589 | const union radeon_firmware_header *hdr; | ||
| 590 | |||
| 591 | BUG_ON(kgd == NULL || rdev->mec_fw == NULL); | ||
| 592 | |||
| 593 | switch (type) { | ||
| 594 | case KGD_ENGINE_PFP: | ||
| 595 | hdr = (const union radeon_firmware_header *) rdev->pfp_fw->data; | ||
| 596 | break; | ||
| 597 | |||
| 598 | case KGD_ENGINE_ME: | ||
| 599 | hdr = (const union radeon_firmware_header *) rdev->me_fw->data; | ||
| 600 | break; | ||
| 601 | |||
| 602 | case KGD_ENGINE_CE: | ||
| 603 | hdr = (const union radeon_firmware_header *) rdev->ce_fw->data; | ||
| 604 | break; | ||
| 605 | |||
| 606 | case KGD_ENGINE_MEC1: | ||
| 607 | hdr = (const union radeon_firmware_header *) rdev->mec_fw->data; | ||
| 608 | break; | ||
| 609 | |||
| 610 | case KGD_ENGINE_MEC2: | ||
| 611 | hdr = (const union radeon_firmware_header *) | ||
| 612 | rdev->mec2_fw->data; | ||
| 613 | break; | ||
| 614 | |||
| 615 | case KGD_ENGINE_RLC: | ||
| 616 | hdr = (const union radeon_firmware_header *) rdev->rlc_fw->data; | ||
| 617 | break; | ||
| 618 | |||
| 619 | case KGD_ENGINE_SDMA: | ||
| 620 | hdr = (const union radeon_firmware_header *) | ||
| 621 | rdev->sdma_fw->data; | ||
| 622 | break; | ||
| 623 | |||
| 624 | default: | ||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | if (hdr == NULL) | ||
| 629 | return 0; | ||
| 630 | |||
| 631 | /* Only 12 bit in use*/ | ||
| 632 | return hdr->common.ucode_version; | ||
| 633 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3cf9c1fa6475..686411e4e4f6 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -605,14 +605,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | |||
| 605 | return -ENOMEM; | 605 | return -ENOMEM; |
| 606 | } | 606 | } |
| 607 | 607 | ||
| 608 | vm = &fpriv->vm; | ||
| 609 | r = radeon_vm_init(rdev, vm); | ||
| 610 | if (r) { | ||
| 611 | kfree(fpriv); | ||
| 612 | return r; | ||
| 613 | } | ||
| 614 | |||
| 615 | if (rdev->accel_working) { | 608 | if (rdev->accel_working) { |
| 609 | vm = &fpriv->vm; | ||
| 610 | r = radeon_vm_init(rdev, vm); | ||
| 611 | if (r) { | ||
| 612 | kfree(fpriv); | ||
| 613 | return r; | ||
| 614 | } | ||
| 615 | |||
| 616 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); | 616 | r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); |
| 617 | if (r) { | 617 | if (r) { |
| 618 | radeon_vm_fini(rdev, vm); | 618 | radeon_vm_fini(rdev, vm); |
| @@ -668,9 +668,9 @@ void radeon_driver_postclose_kms(struct drm_device *dev, | |||
| 668 | radeon_vm_bo_rmv(rdev, vm->ib_bo_va); | 668 | radeon_vm_bo_rmv(rdev, vm->ib_bo_va); |
| 669 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); | 669 | radeon_bo_unreserve(rdev->ring_tmp_bo.bo); |
| 670 | } | 670 | } |
| 671 | radeon_vm_fini(rdev, vm); | ||
| 671 | } | 672 | } |
| 672 | 673 | ||
| 673 | radeon_vm_fini(rdev, vm); | ||
| 674 | kfree(fpriv); | 674 | kfree(fpriv); |
| 675 | file_priv->driver_priv = NULL; | 675 | file_priv->driver_priv = NULL; |
| 676 | } | 676 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 7d68223eb469..86fc56434b28 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -529,9 +529,6 @@ int radeon_bo_list_validate(struct radeon_device *rdev, | |||
| 529 | u32 current_domain = | 529 | u32 current_domain = |
| 530 | radeon_mem_type_to_domain(bo->tbo.mem.mem_type); | 530 | radeon_mem_type_to_domain(bo->tbo.mem.mem_type); |
| 531 | 531 | ||
| 532 | WARN_ONCE(bo->gem_base.dumb, | ||
| 533 | "GPU use of dumb buffer is illegal.\n"); | ||
| 534 | |||
| 535 | /* Check if this buffer will be moved and don't move it | 532 | /* Check if this buffer will be moved and don't move it |
| 536 | * if we have moved too many buffers for this IB already. | 533 | * if we have moved too many buffers for this IB already. |
| 537 | * | 534 | * |
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 32522cc940a1..f7da8fe96a66 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c | |||
| @@ -1287,8 +1287,39 @@ dpm_failed: | |||
| 1287 | return ret; | 1287 | return ret; |
| 1288 | } | 1288 | } |
| 1289 | 1289 | ||
| 1290 | struct radeon_dpm_quirk { | ||
| 1291 | u32 chip_vendor; | ||
| 1292 | u32 chip_device; | ||
| 1293 | u32 subsys_vendor; | ||
| 1294 | u32 subsys_device; | ||
| 1295 | }; | ||
| 1296 | |||
| 1297 | /* cards with dpm stability problems */ | ||
| 1298 | static struct radeon_dpm_quirk radeon_dpm_quirk_list[] = { | ||
| 1299 | /* TURKS - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1386534 */ | ||
| 1300 | { PCI_VENDOR_ID_ATI, 0x6759, 0x1682, 0x3195 }, | ||
| 1301 | /* TURKS - https://bugzilla.kernel.org/show_bug.cgi?id=83731 */ | ||
| 1302 | { PCI_VENDOR_ID_ATI, 0x6840, 0x1179, 0xfb81 }, | ||
| 1303 | { 0, 0, 0, 0 }, | ||
| 1304 | }; | ||
| 1305 | |||
| 1290 | int radeon_pm_init(struct radeon_device *rdev) | 1306 | int radeon_pm_init(struct radeon_device *rdev) |
| 1291 | { | 1307 | { |
| 1308 | struct radeon_dpm_quirk *p = radeon_dpm_quirk_list; | ||
| 1309 | bool disable_dpm = false; | ||
| 1310 | |||
| 1311 | /* Apply dpm quirks */ | ||
| 1312 | while (p && p->chip_device != 0) { | ||
| 1313 | if (rdev->pdev->vendor == p->chip_vendor && | ||
| 1314 | rdev->pdev->device == p->chip_device && | ||
| 1315 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
| 1316 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
| 1317 | disable_dpm = true; | ||
| 1318 | break; | ||
| 1319 | } | ||
| 1320 | ++p; | ||
| 1321 | } | ||
| 1322 | |||
| 1292 | /* enable dpm on rv6xx+ */ | 1323 | /* enable dpm on rv6xx+ */ |
| 1293 | switch (rdev->family) { | 1324 | switch (rdev->family) { |
| 1294 | case CHIP_RV610: | 1325 | case CHIP_RV610: |
| @@ -1344,6 +1375,8 @@ int radeon_pm_init(struct radeon_device *rdev) | |||
| 1344 | (!(rdev->flags & RADEON_IS_IGP)) && | 1375 | (!(rdev->flags & RADEON_IS_IGP)) && |
| 1345 | (!rdev->smc_fw)) | 1376 | (!rdev->smc_fw)) |
| 1346 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1377 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
| 1378 | else if (disable_dpm && (radeon_dpm == -1)) | ||
| 1379 | rdev->pm.pm_method = PM_METHOD_PROFILE; | ||
| 1347 | else if (radeon_dpm == 0) | 1380 | else if (radeon_dpm == 0) |
| 1348 | rdev->pm.pm_method = PM_METHOD_PROFILE; | 1381 | rdev->pm.pm_method = PM_METHOD_PROFILE; |
| 1349 | else | 1382 | else |
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 535403e0c8a2..15aee723db77 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c | |||
| @@ -1703,7 +1703,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, | |||
| 1703 | u32 format; | 1703 | u32 format; |
| 1704 | u32 *buffer; | 1704 | u32 *buffer; |
| 1705 | const u8 __user *data; | 1705 | const u8 __user *data; |
| 1706 | int size, dwords, tex_width, blit_width, spitch; | 1706 | unsigned int size, dwords, tex_width, blit_width, spitch; |
| 1707 | u32 height; | 1707 | u32 height; |
| 1708 | int i; | 1708 | int i; |
| 1709 | u32 texpitch, microtile; | 1709 | u32 texpitch, microtile; |
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 07b506b41008..791818165c76 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c | |||
| @@ -119,11 +119,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) | |||
| 119 | if (ring == R600_RING_TYPE_DMA_INDEX) | 119 | if (ring == R600_RING_TYPE_DMA_INDEX) |
| 120 | fence = radeon_copy_dma(rdev, gtt_addr, vram_addr, | 120 | fence = radeon_copy_dma(rdev, gtt_addr, vram_addr, |
| 121 | size / RADEON_GPU_PAGE_SIZE, | 121 | size / RADEON_GPU_PAGE_SIZE, |
| 122 | NULL); | 122 | vram_obj->tbo.resv); |
| 123 | else | 123 | else |
| 124 | fence = radeon_copy_blit(rdev, gtt_addr, vram_addr, | 124 | fence = radeon_copy_blit(rdev, gtt_addr, vram_addr, |
| 125 | size / RADEON_GPU_PAGE_SIZE, | 125 | size / RADEON_GPU_PAGE_SIZE, |
| 126 | NULL); | 126 | vram_obj->tbo.resv); |
| 127 | if (IS_ERR(fence)) { | 127 | if (IS_ERR(fence)) { |
| 128 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); | 128 | DRM_ERROR("Failed GTT->VRAM copy %d\n", i); |
| 129 | r = PTR_ERR(fence); | 129 | r = PTR_ERR(fence); |
| @@ -170,11 +170,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) | |||
| 170 | if (ring == R600_RING_TYPE_DMA_INDEX) | 170 | if (ring == R600_RING_TYPE_DMA_INDEX) |
| 171 | fence = radeon_copy_dma(rdev, vram_addr, gtt_addr, | 171 | fence = radeon_copy_dma(rdev, vram_addr, gtt_addr, |
| 172 | size / RADEON_GPU_PAGE_SIZE, | 172 | size / RADEON_GPU_PAGE_SIZE, |
| 173 | NULL); | 173 | vram_obj->tbo.resv); |
| 174 | else | 174 | else |
| 175 | fence = radeon_copy_blit(rdev, vram_addr, gtt_addr, | 175 | fence = radeon_copy_blit(rdev, vram_addr, gtt_addr, |
| 176 | size / RADEON_GPU_PAGE_SIZE, | 176 | size / RADEON_GPU_PAGE_SIZE, |
| 177 | NULL); | 177 | vram_obj->tbo.resv); |
| 178 | if (IS_ERR(fence)) { | 178 | if (IS_ERR(fence)) { |
| 179 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); | 179 | DRM_ERROR("Failed VRAM->GTT copy %d\n", i); |
| 180 | r = PTR_ERR(fence); | 180 | r = PTR_ERR(fence); |
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index cde48c42b30a..2a5a4a9e772d 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c | |||
| @@ -587,10 +587,8 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr) | |||
| 587 | uint64_t result; | 587 | uint64_t result; |
| 588 | 588 | ||
| 589 | /* page table offset */ | 589 | /* page table offset */ |
| 590 | result = rdev->gart.pages_addr[addr >> PAGE_SHIFT]; | 590 | result = rdev->gart.pages_entry[addr >> RADEON_GPU_PAGE_SHIFT]; |
| 591 | 591 | result &= ~RADEON_GPU_PAGE_MASK; | |
| 592 | /* in case cpu page size != gpu page size*/ | ||
| 593 | result |= addr & (~PAGE_MASK); | ||
| 594 | 592 | ||
| 595 | return result; | 593 | return result; |
| 596 | } | 594 | } |
| @@ -745,9 +743,11 @@ static void radeon_vm_frag_ptes(struct radeon_device *rdev, | |||
| 745 | */ | 743 | */ |
| 746 | 744 | ||
| 747 | /* NI is optimized for 256KB fragments, SI and newer for 64KB */ | 745 | /* NI is optimized for 256KB fragments, SI and newer for 64KB */ |
| 748 | uint64_t frag_flags = rdev->family == CHIP_CAYMAN ? | 746 | uint64_t frag_flags = ((rdev->family == CHIP_CAYMAN) || |
| 747 | (rdev->family == CHIP_ARUBA)) ? | ||
| 749 | R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB; | 748 | R600_PTE_FRAG_256KB : R600_PTE_FRAG_64KB; |
| 750 | uint64_t frag_align = rdev->family == CHIP_CAYMAN ? 0x200 : 0x80; | 749 | uint64_t frag_align = ((rdev->family == CHIP_CAYMAN) || |
| 750 | (rdev->family == CHIP_ARUBA)) ? 0x200 : 0x80; | ||
| 751 | 751 | ||
| 752 | uint64_t frag_start = ALIGN(pe_start, frag_align); | 752 | uint64_t frag_start = ALIGN(pe_start, frag_align); |
| 753 | uint64_t frag_end = pe_end & ~(frag_align - 1); | 753 | uint64_t frag_end = pe_end & ~(frag_align - 1); |
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index c5799f16aa4b..34e3235f41d2 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -212,11 +212,9 @@ void rs400_gart_fini(struct radeon_device *rdev) | |||
| 212 | #define RS400_PTE_WRITEABLE (1 << 2) | 212 | #define RS400_PTE_WRITEABLE (1 << 2) |
| 213 | #define RS400_PTE_READABLE (1 << 3) | 213 | #define RS400_PTE_READABLE (1 << 3) |
| 214 | 214 | ||
| 215 | void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, | 215 | uint64_t rs400_gart_get_page_entry(uint64_t addr, uint32_t flags) |
| 216 | uint64_t addr, uint32_t flags) | ||
| 217 | { | 216 | { |
| 218 | uint32_t entry; | 217 | uint32_t entry; |
| 219 | u32 *gtt = rdev->gart.ptr; | ||
| 220 | 218 | ||
| 221 | entry = (lower_32_bits(addr) & PAGE_MASK) | | 219 | entry = (lower_32_bits(addr) & PAGE_MASK) | |
| 222 | ((upper_32_bits(addr) & 0xff) << 4); | 220 | ((upper_32_bits(addr) & 0xff) << 4); |
| @@ -226,8 +224,14 @@ void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, | |||
| 226 | entry |= RS400_PTE_WRITEABLE; | 224 | entry |= RS400_PTE_WRITEABLE; |
| 227 | if (!(flags & RADEON_GART_PAGE_SNOOP)) | 225 | if (!(flags & RADEON_GART_PAGE_SNOOP)) |
| 228 | entry |= RS400_PTE_UNSNOOPED; | 226 | entry |= RS400_PTE_UNSNOOPED; |
| 229 | entry = cpu_to_le32(entry); | 227 | return entry; |
| 230 | gtt[i] = entry; | 228 | } |
| 229 | |||
| 230 | void rs400_gart_set_page(struct radeon_device *rdev, unsigned i, | ||
| 231 | uint64_t entry) | ||
| 232 | { | ||
| 233 | u32 *gtt = rdev->gart.ptr; | ||
| 234 | gtt[i] = cpu_to_le32(lower_32_bits(entry)); | ||
| 231 | } | 235 | } |
| 232 | 236 | ||
| 233 | int rs400_mc_wait_for_idle(struct radeon_device *rdev) | 237 | int rs400_mc_wait_for_idle(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 9acb1c3c005b..74bce91aecc1 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -625,11 +625,8 @@ static void rs600_gart_fini(struct radeon_device *rdev) | |||
| 625 | radeon_gart_table_vram_free(rdev); | 625 | radeon_gart_table_vram_free(rdev); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, | 628 | uint64_t rs600_gart_get_page_entry(uint64_t addr, uint32_t flags) |
| 629 | uint64_t addr, uint32_t flags) | ||
| 630 | { | 629 | { |
| 631 | void __iomem *ptr = (void *)rdev->gart.ptr; | ||
| 632 | |||
| 633 | addr = addr & 0xFFFFFFFFFFFFF000ULL; | 630 | addr = addr & 0xFFFFFFFFFFFFF000ULL; |
| 634 | addr |= R600_PTE_SYSTEM; | 631 | addr |= R600_PTE_SYSTEM; |
| 635 | if (flags & RADEON_GART_PAGE_VALID) | 632 | if (flags & RADEON_GART_PAGE_VALID) |
| @@ -640,7 +637,14 @@ void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, | |||
| 640 | addr |= R600_PTE_WRITEABLE; | 637 | addr |= R600_PTE_WRITEABLE; |
| 641 | if (flags & RADEON_GART_PAGE_SNOOP) | 638 | if (flags & RADEON_GART_PAGE_SNOOP) |
| 642 | addr |= R600_PTE_SNOOPED; | 639 | addr |= R600_PTE_SNOOPED; |
| 643 | writeq(addr, ptr + (i * 8)); | 640 | return addr; |
| 641 | } | ||
| 642 | |||
| 643 | void rs600_gart_set_page(struct radeon_device *rdev, unsigned i, | ||
| 644 | uint64_t entry) | ||
| 645 | { | ||
| 646 | void __iomem *ptr = (void *)rdev->gart.ptr; | ||
| 647 | writeq(entry, ptr + (i * 8)); | ||
| 644 | } | 648 | } |
| 645 | 649 | ||
| 646 | int rs600_irq_set(struct radeon_device *rdev) | 650 | int rs600_irq_set(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 60df444bd075..5d89b874a1a2 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -5057,6 +5057,16 @@ void si_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 5057 | radeon_ring_write(ring, 0); | 5057 | radeon_ring_write(ring, 0); |
| 5058 | radeon_ring_write(ring, 1 << vm_id); | 5058 | radeon_ring_write(ring, 1 << vm_id); |
| 5059 | 5059 | ||
| 5060 | /* wait for the invalidate to complete */ | ||
| 5061 | radeon_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5)); | ||
| 5062 | radeon_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) | /* always */ | ||
| 5063 | WAIT_REG_MEM_ENGINE(0))); /* me */ | ||
| 5064 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2); | ||
| 5065 | radeon_ring_write(ring, 0); | ||
| 5066 | radeon_ring_write(ring, 0); /* ref */ | ||
| 5067 | radeon_ring_write(ring, 0); /* mask */ | ||
| 5068 | radeon_ring_write(ring, 0x20); /* poll interval */ | ||
| 5069 | |||
| 5060 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ | 5070 | /* sync PFP to ME, otherwise we might get invalid PFP reads */ |
| 5061 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); | 5071 | radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); |
| 5062 | radeon_ring_write(ring, 0x0); | 5072 | radeon_ring_write(ring, 0x0); |
diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index f5cc777e1c5f..83207929fc62 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c | |||
| @@ -123,7 +123,6 @@ void si_dma_vm_write_pages(struct radeon_device *rdev, | |||
| 123 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { | 123 | for (; ndw > 0; ndw -= 2, --count, pe += 8) { |
| 124 | if (flags & R600_PTE_SYSTEM) { | 124 | if (flags & R600_PTE_SYSTEM) { |
| 125 | value = radeon_vm_map_gart(rdev, addr); | 125 | value = radeon_vm_map_gart(rdev, addr); |
| 126 | value &= 0xFFFFFFFFFFFFF000ULL; | ||
| 127 | } else if (flags & R600_PTE_VALID) { | 126 | } else if (flags & R600_PTE_VALID) { |
| 128 | value = addr; | 127 | value = addr; |
| 129 | } else { | 128 | } else { |
| @@ -206,6 +205,14 @@ void si_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, | |||
| 206 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); | 205 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_SRBM_WRITE, 0, 0, 0, 0)); |
| 207 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); | 206 | radeon_ring_write(ring, (0xf << 16) | (VM_INVALIDATE_REQUEST >> 2)); |
| 208 | radeon_ring_write(ring, 1 << vm_id); | 207 | radeon_ring_write(ring, 1 << vm_id); |
| 208 | |||
| 209 | /* wait for invalidate to complete */ | ||
| 210 | radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_POLL_REG_MEM, 0, 0, 0, 0)); | ||
| 211 | radeon_ring_write(ring, VM_INVALIDATE_REQUEST); | ||
| 212 | radeon_ring_write(ring, 0xff << 16); /* retry */ | ||
| 213 | radeon_ring_write(ring, 1 << vm_id); /* mask */ | ||
| 214 | radeon_ring_write(ring, 0); /* value */ | ||
| 215 | radeon_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */ | ||
| 209 | } | 216 | } |
| 210 | 217 | ||
| 211 | /** | 218 | /** |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 32e354b8b0ab..eff8a6444956 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -2908,6 +2908,22 @@ static int si_init_smc_spll_table(struct radeon_device *rdev) | |||
| 2908 | return ret; | 2908 | return ret; |
| 2909 | } | 2909 | } |
| 2910 | 2910 | ||
| 2911 | struct si_dpm_quirk { | ||
| 2912 | u32 chip_vendor; | ||
| 2913 | u32 chip_device; | ||
| 2914 | u32 subsys_vendor; | ||
| 2915 | u32 subsys_device; | ||
| 2916 | u32 max_sclk; | ||
| 2917 | u32 max_mclk; | ||
| 2918 | }; | ||
| 2919 | |||
| 2920 | /* cards with dpm stability problems */ | ||
| 2921 | static struct si_dpm_quirk si_dpm_quirk_list[] = { | ||
| 2922 | /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ | ||
| 2923 | { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, | ||
| 2924 | { 0, 0, 0, 0 }, | ||
| 2925 | }; | ||
| 2926 | |||
| 2911 | static void si_apply_state_adjust_rules(struct radeon_device *rdev, | 2927 | static void si_apply_state_adjust_rules(struct radeon_device *rdev, |
| 2912 | struct radeon_ps *rps) | 2928 | struct radeon_ps *rps) |
| 2913 | { | 2929 | { |
| @@ -2918,7 +2934,22 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2918 | u32 mclk, sclk; | 2934 | u32 mclk, sclk; |
| 2919 | u16 vddc, vddci; | 2935 | u16 vddc, vddci; |
| 2920 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; | 2936 | u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; |
| 2937 | u32 max_sclk = 0, max_mclk = 0; | ||
| 2921 | int i; | 2938 | int i; |
| 2939 | struct si_dpm_quirk *p = si_dpm_quirk_list; | ||
| 2940 | |||
| 2941 | /* Apply dpm quirks */ | ||
| 2942 | while (p && p->chip_device != 0) { | ||
| 2943 | if (rdev->pdev->vendor == p->chip_vendor && | ||
| 2944 | rdev->pdev->device == p->chip_device && | ||
| 2945 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
| 2946 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
| 2947 | max_sclk = p->max_sclk; | ||
| 2948 | max_mclk = p->max_mclk; | ||
| 2949 | break; | ||
| 2950 | } | ||
| 2951 | ++p; | ||
| 2952 | } | ||
| 2922 | 2953 | ||
| 2923 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || | 2954 | if ((rdev->pm.dpm.new_active_crtc_count > 1) || |
| 2924 | ni_dpm_vblank_too_short(rdev)) | 2955 | ni_dpm_vblank_too_short(rdev)) |
| @@ -2972,6 +3003,14 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 2972 | if (ps->performance_levels[i].mclk > max_mclk_vddc) | 3003 | if (ps->performance_levels[i].mclk > max_mclk_vddc) |
| 2973 | ps->performance_levels[i].mclk = max_mclk_vddc; | 3004 | ps->performance_levels[i].mclk = max_mclk_vddc; |
| 2974 | } | 3005 | } |
| 3006 | if (max_mclk) { | ||
| 3007 | if (ps->performance_levels[i].mclk > max_mclk) | ||
| 3008 | ps->performance_levels[i].mclk = max_mclk; | ||
| 3009 | } | ||
| 3010 | if (max_sclk) { | ||
| 3011 | if (ps->performance_levels[i].sclk > max_sclk) | ||
| 3012 | ps->performance_levels[i].sclk = max_sclk; | ||
| 3013 | } | ||
| 2975 | } | 3014 | } |
| 2976 | 3015 | ||
| 2977 | /* XXX validate the min clocks required for display */ | 3016 | /* XXX validate the min clocks required for display */ |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 4069be89e585..84999242c747 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -1632,6 +1632,23 @@ | |||
| 1632 | #define PACKET3_MPEG_INDEX 0x3A | 1632 | #define PACKET3_MPEG_INDEX 0x3A |
| 1633 | #define PACKET3_COPY_DW 0x3B | 1633 | #define PACKET3_COPY_DW 0x3B |
| 1634 | #define PACKET3_WAIT_REG_MEM 0x3C | 1634 | #define PACKET3_WAIT_REG_MEM 0x3C |
| 1635 | #define WAIT_REG_MEM_FUNCTION(x) ((x) << 0) | ||
| 1636 | /* 0 - always | ||
| 1637 | * 1 - < | ||
| 1638 | * 2 - <= | ||
| 1639 | * 3 - == | ||
| 1640 | * 4 - != | ||
| 1641 | * 5 - >= | ||
| 1642 | * 6 - > | ||
| 1643 | */ | ||
| 1644 | #define WAIT_REG_MEM_MEM_SPACE(x) ((x) << 4) | ||
| 1645 | /* 0 - reg | ||
| 1646 | * 1 - mem | ||
| 1647 | */ | ||
| 1648 | #define WAIT_REG_MEM_ENGINE(x) ((x) << 8) | ||
| 1649 | /* 0 - me | ||
| 1650 | * 1 - pfp | ||
| 1651 | */ | ||
| 1635 | #define PACKET3_MEM_WRITE 0x3D | 1652 | #define PACKET3_MEM_WRITE 0x3D |
| 1636 | #define PACKET3_COPY_DATA 0x40 | 1653 | #define PACKET3_COPY_DATA 0x40 |
| 1637 | #define PACKET3_CP_DMA 0x41 | 1654 | #define PACKET3_CP_DMA 0x41 |
| @@ -1835,6 +1852,7 @@ | |||
| 1835 | #define DMA_PACKET_TRAP 0x7 | 1852 | #define DMA_PACKET_TRAP 0x7 |
| 1836 | #define DMA_PACKET_SRBM_WRITE 0x9 | 1853 | #define DMA_PACKET_SRBM_WRITE 0x9 |
| 1837 | #define DMA_PACKET_CONSTANT_FILL 0xd | 1854 | #define DMA_PACKET_CONSTANT_FILL 0xd |
| 1855 | #define DMA_PACKET_POLL_REG_MEM 0xe | ||
| 1838 | #define DMA_PACKET_NOP 0xf | 1856 | #define DMA_PACKET_NOP 0xf |
| 1839 | 1857 | ||
| 1840 | #define VCE_STATUS 0x20004 | 1858 | #define VCE_STATUS 0x20004 |
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3367960286a6..978993fa3a36 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
| @@ -168,7 +168,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 168 | const struct tegra_dc_window *window) | 168 | const struct tegra_dc_window *window) |
| 169 | { | 169 | { |
| 170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; | 170 | unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; |
| 171 | unsigned long value; | 171 | unsigned long value, flags; |
| 172 | bool yuv, planar; | 172 | bool yuv, planar; |
| 173 | 173 | ||
| 174 | /* | 174 | /* |
| @@ -181,6 +181,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 181 | else | 181 | else |
| 182 | bpp = planar ? 1 : 2; | 182 | bpp = planar ? 1 : 2; |
| 183 | 183 | ||
| 184 | spin_lock_irqsave(&dc->lock, flags); | ||
| 185 | |||
| 184 | value = WINDOW_A_SELECT << index; | 186 | value = WINDOW_A_SELECT << index; |
| 185 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 187 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 186 | 188 | ||
| @@ -273,6 +275,7 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 273 | 275 | ||
| 274 | case TEGRA_BO_TILING_MODE_BLOCK: | 276 | case TEGRA_BO_TILING_MODE_BLOCK: |
| 275 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 277 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
| 278 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 276 | return -EINVAL; | 279 | return -EINVAL; |
| 277 | } | 280 | } |
| 278 | 281 | ||
| @@ -331,6 +334,8 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
| 331 | 334 | ||
| 332 | tegra_dc_window_commit(dc, index); | 335 | tegra_dc_window_commit(dc, index); |
| 333 | 336 | ||
| 337 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 338 | |||
| 334 | return 0; | 339 | return 0; |
| 335 | } | 340 | } |
| 336 | 341 | ||
| @@ -338,11 +343,14 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
| 338 | { | 343 | { |
| 339 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); | 344 | struct tegra_dc *dc = to_tegra_dc(plane->crtc); |
| 340 | struct tegra_plane *p = to_tegra_plane(plane); | 345 | struct tegra_plane *p = to_tegra_plane(plane); |
| 346 | unsigned long flags; | ||
| 341 | u32 value; | 347 | u32 value; |
| 342 | 348 | ||
| 343 | if (!plane->crtc) | 349 | if (!plane->crtc) |
| 344 | return 0; | 350 | return 0; |
| 345 | 351 | ||
| 352 | spin_lock_irqsave(&dc->lock, flags); | ||
| 353 | |||
| 346 | value = WINDOW_A_SELECT << p->index; | 354 | value = WINDOW_A_SELECT << p->index; |
| 347 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); | 355 | tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 348 | 356 | ||
| @@ -352,6 +360,8 @@ static int tegra_window_plane_disable(struct drm_plane *plane) | |||
| 352 | 360 | ||
| 353 | tegra_dc_window_commit(dc, p->index); | 361 | tegra_dc_window_commit(dc, p->index); |
| 354 | 362 | ||
| 363 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 364 | |||
| 355 | return 0; | 365 | return 0; |
| 356 | } | 366 | } |
| 357 | 367 | ||
| @@ -699,14 +709,16 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 699 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); | 709 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
| 700 | unsigned int h_offset = 0, v_offset = 0; | 710 | unsigned int h_offset = 0, v_offset = 0; |
| 701 | struct tegra_bo_tiling tiling; | 711 | struct tegra_bo_tiling tiling; |
| 712 | unsigned long value, flags; | ||
| 702 | unsigned int format, swap; | 713 | unsigned int format, swap; |
| 703 | unsigned long value; | ||
| 704 | int err; | 714 | int err; |
| 705 | 715 | ||
| 706 | err = tegra_fb_get_tiling(fb, &tiling); | 716 | err = tegra_fb_get_tiling(fb, &tiling); |
| 707 | if (err < 0) | 717 | if (err < 0) |
| 708 | return err; | 718 | return err; |
| 709 | 719 | ||
| 720 | spin_lock_irqsave(&dc->lock, flags); | ||
| 721 | |||
| 710 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 722 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
| 711 | 723 | ||
| 712 | value = fb->offsets[0] + y * fb->pitches[0] + | 724 | value = fb->offsets[0] + y * fb->pitches[0] + |
| @@ -752,6 +764,7 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 752 | 764 | ||
| 753 | case TEGRA_BO_TILING_MODE_BLOCK: | 765 | case TEGRA_BO_TILING_MODE_BLOCK: |
| 754 | DRM_ERROR("hardware doesn't support block linear mode\n"); | 766 | DRM_ERROR("hardware doesn't support block linear mode\n"); |
| 767 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 755 | return -EINVAL; | 768 | return -EINVAL; |
| 756 | } | 769 | } |
| 757 | 770 | ||
| @@ -778,6 +791,8 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
| 778 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); | 791 | tegra_dc_writel(dc, value << 8, DC_CMD_STATE_CONTROL); |
| 779 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); | 792 | tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); |
| 780 | 793 | ||
| 794 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 795 | |||
| 781 | return 0; | 796 | return 0; |
| 782 | } | 797 | } |
| 783 | 798 | ||
| @@ -814,23 +829,32 @@ static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | |||
| 814 | unsigned long flags, base; | 829 | unsigned long flags, base; |
| 815 | struct tegra_bo *bo; | 830 | struct tegra_bo *bo; |
| 816 | 831 | ||
| 817 | if (!dc->event) | 832 | spin_lock_irqsave(&drm->event_lock, flags); |
| 833 | |||
| 834 | if (!dc->event) { | ||
| 835 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 818 | return; | 836 | return; |
| 837 | } | ||
| 819 | 838 | ||
| 820 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); | 839 | bo = tegra_fb_get_plane(crtc->primary->fb, 0); |
| 821 | 840 | ||
| 841 | spin_lock_irqsave(&dc->lock, flags); | ||
| 842 | |||
| 822 | /* check if new start address has been latched */ | 843 | /* check if new start address has been latched */ |
| 844 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | ||
| 823 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); | 845 | tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); |
| 824 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); | 846 | base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); |
| 825 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); | 847 | tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); |
| 826 | 848 | ||
| 849 | spin_unlock_irqrestore(&dc->lock, flags); | ||
| 850 | |||
| 827 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { | 851 | if (base == bo->paddr + crtc->primary->fb->offsets[0]) { |
| 828 | spin_lock_irqsave(&drm->event_lock, flags); | 852 | drm_crtc_send_vblank_event(crtc, dc->event); |
| 829 | drm_send_vblank_event(drm, dc->pipe, dc->event); | 853 | drm_crtc_vblank_put(crtc); |
| 830 | drm_vblank_put(drm, dc->pipe); | ||
| 831 | dc->event = NULL; | 854 | dc->event = NULL; |
| 832 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 833 | } | 855 | } |
| 856 | |||
| 857 | spin_unlock_irqrestore(&drm->event_lock, flags); | ||
| 834 | } | 858 | } |
| 835 | 859 | ||
| 836 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | 860 | void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) |
| @@ -843,7 +867,7 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
| 843 | 867 | ||
| 844 | if (dc->event && dc->event->base.file_priv == file) { | 868 | if (dc->event && dc->event->base.file_priv == file) { |
| 845 | dc->event->base.destroy(&dc->event->base); | 869 | dc->event->base.destroy(&dc->event->base); |
| 846 | drm_vblank_put(drm, dc->pipe); | 870 | drm_crtc_vblank_put(crtc); |
| 847 | dc->event = NULL; | 871 | dc->event = NULL; |
| 848 | } | 872 | } |
| 849 | 873 | ||
| @@ -853,16 +877,16 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) | |||
| 853 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 877 | static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
| 854 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) | 878 | struct drm_pending_vblank_event *event, uint32_t page_flip_flags) |
| 855 | { | 879 | { |
| 880 | unsigned int pipe = drm_crtc_index(crtc); | ||
| 856 | struct tegra_dc *dc = to_tegra_dc(crtc); | 881 | struct tegra_dc *dc = to_tegra_dc(crtc); |
| 857 | struct drm_device *drm = crtc->dev; | ||
| 858 | 882 | ||
| 859 | if (dc->event) | 883 | if (dc->event) |
| 860 | return -EBUSY; | 884 | return -EBUSY; |
| 861 | 885 | ||
| 862 | if (event) { | 886 | if (event) { |
| 863 | event->pipe = dc->pipe; | 887 | event->pipe = pipe; |
| 864 | dc->event = event; | 888 | dc->event = event; |
| 865 | drm_vblank_get(drm, dc->pipe); | 889 | drm_crtc_vblank_get(crtc); |
| 866 | } | 890 | } |
| 867 | 891 | ||
| 868 | tegra_dc_set_base(dc, 0, 0, fb); | 892 | tegra_dc_set_base(dc, 0, 0, fb); |
| @@ -1127,7 +1151,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) | |||
| 1127 | /* | 1151 | /* |
| 1128 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); | 1152 | dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); |
| 1129 | */ | 1153 | */ |
| 1130 | drm_handle_vblank(dc->base.dev, dc->pipe); | 1154 | drm_crtc_handle_vblank(&dc->base); |
| 1131 | tegra_dc_finish_page_flip(dc); | 1155 | tegra_dc_finish_page_flip(dc); |
| 1132 | } | 1156 | } |
| 1133 | 1157 | ||
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e549afeece1f..d4f827593dfa 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
| @@ -694,24 +694,28 @@ static const struct file_operations tegra_drm_fops = { | |||
| 694 | .llseek = noop_llseek, | 694 | .llseek = noop_llseek, |
| 695 | }; | 695 | }; |
| 696 | 696 | ||
| 697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) | 697 | static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, |
| 698 | unsigned int pipe) | ||
| 698 | { | 699 | { |
| 699 | struct drm_crtc *crtc; | 700 | struct drm_crtc *crtc; |
| 700 | 701 | ||
| 701 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { | 702 | list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { |
| 702 | struct tegra_dc *dc = to_tegra_dc(crtc); | 703 | if (pipe == drm_crtc_index(crtc)) |
| 703 | |||
| 704 | if (dc->pipe == pipe) | ||
| 705 | return crtc; | 704 | return crtc; |
| 706 | } | 705 | } |
| 707 | 706 | ||
| 708 | return NULL; | 707 | return NULL; |
| 709 | } | 708 | } |
| 710 | 709 | ||
| 711 | static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) | 710 | static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe) |
| 712 | { | 711 | { |
| 712 | struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); | ||
| 713 | |||
| 714 | if (!crtc) | ||
| 715 | return 0; | ||
| 716 | |||
| 713 | /* TODO: implement real hardware counter using syncpoints */ | 717 | /* TODO: implement real hardware counter using syncpoints */ |
| 714 | return drm_vblank_count(dev, crtc); | 718 | return drm_crtc_vblank_count(crtc); |
| 715 | } | 719 | } |
| 716 | 720 | ||
| 717 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) | 721 | static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) |
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index da32086cbeaf..8777b7f75791 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
| @@ -216,32 +216,58 @@ static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) | |||
| 216 | } | 216 | } |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo, | 219 | static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) |
| 220 | size_t size) | ||
| 221 | { | 220 | { |
| 221 | struct scatterlist *s; | ||
| 222 | struct sg_table *sgt; | ||
| 223 | unsigned int i; | ||
| 224 | |||
| 222 | bo->pages = drm_gem_get_pages(&bo->gem); | 225 | bo->pages = drm_gem_get_pages(&bo->gem); |
| 223 | if (IS_ERR(bo->pages)) | 226 | if (IS_ERR(bo->pages)) |
| 224 | return PTR_ERR(bo->pages); | 227 | return PTR_ERR(bo->pages); |
| 225 | 228 | ||
| 226 | bo->num_pages = size >> PAGE_SHIFT; | 229 | bo->num_pages = bo->gem.size >> PAGE_SHIFT; |
| 227 | 230 | ||
| 228 | bo->sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); | 231 | sgt = drm_prime_pages_to_sg(bo->pages, bo->num_pages); |
| 229 | if (IS_ERR(bo->sgt)) { | 232 | if (IS_ERR(sgt)) |
| 230 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | 233 | goto put_pages; |
| 231 | return PTR_ERR(bo->sgt); | 234 | |
| 235 | /* | ||
| 236 | * Fake up the SG table so that dma_map_sg() can be used to flush the | ||
| 237 | * pages associated with it. Note that this relies on the fact that | ||
| 238 | * the DMA API doesn't hook into IOMMU on Tegra, therefore mapping is | ||
| 239 | * only cache maintenance. | ||
| 240 | * | ||
| 241 | * TODO: Replace this by drm_clflash_sg() once it can be implemented | ||
| 242 | * without relying on symbols that are not exported. | ||
| 243 | */ | ||
| 244 | for_each_sg(sgt->sgl, s, sgt->nents, i) | ||
| 245 | sg_dma_address(s) = sg_phys(s); | ||
| 246 | |||
| 247 | if (dma_map_sg(drm->dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE) == 0) { | ||
| 248 | sgt = ERR_PTR(-ENOMEM); | ||
| 249 | goto release_sgt; | ||
| 232 | } | 250 | } |
| 233 | 251 | ||
| 252 | bo->sgt = sgt; | ||
| 253 | |||
| 234 | return 0; | 254 | return 0; |
| 255 | |||
| 256 | release_sgt: | ||
| 257 | sg_free_table(sgt); | ||
| 258 | kfree(sgt); | ||
| 259 | put_pages: | ||
| 260 | drm_gem_put_pages(&bo->gem, bo->pages, false, false); | ||
| 261 | return PTR_ERR(sgt); | ||
| 235 | } | 262 | } |
| 236 | 263 | ||
| 237 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | 264 | static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo) |
| 238 | size_t size) | ||
| 239 | { | 265 | { |
| 240 | struct tegra_drm *tegra = drm->dev_private; | 266 | struct tegra_drm *tegra = drm->dev_private; |
| 241 | int err; | 267 | int err; |
| 242 | 268 | ||
| 243 | if (tegra->domain) { | 269 | if (tegra->domain) { |
| 244 | err = tegra_bo_get_pages(drm, bo, size); | 270 | err = tegra_bo_get_pages(drm, bo); |
| 245 | if (err < 0) | 271 | if (err < 0) |
| 246 | return err; | 272 | return err; |
| 247 | 273 | ||
| @@ -251,6 +277,8 @@ static int tegra_bo_alloc(struct drm_device *drm, struct tegra_bo *bo, | |||
| 251 | return err; | 277 | return err; |
| 252 | } | 278 | } |
| 253 | } else { | 279 | } else { |
| 280 | size_t size = bo->gem.size; | ||
| 281 | |||
| 254 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, | 282 | bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, |
| 255 | GFP_KERNEL | __GFP_NOWARN); | 283 | GFP_KERNEL | __GFP_NOWARN); |
| 256 | if (!bo->vaddr) { | 284 | if (!bo->vaddr) { |
| @@ -274,7 +302,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, size_t size, | |||
| 274 | if (IS_ERR(bo)) | 302 | if (IS_ERR(bo)) |
| 275 | return bo; | 303 | return bo; |
| 276 | 304 | ||
| 277 | err = tegra_bo_alloc(drm, bo, size); | 305 | err = tegra_bo_alloc(drm, bo); |
| 278 | if (err < 0) | 306 | if (err < 0) |
| 279 | goto release; | 307 | goto release; |
| 280 | 308 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7b5d22110f25..6c6b655defcf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -406,11 +406,9 @@ int vmw_3d_resource_inc(struct vmw_private *dev_priv, | |||
| 406 | if (unlikely(ret != 0)) | 406 | if (unlikely(ret != 0)) |
| 407 | --dev_priv->num_3d_resources; | 407 | --dev_priv->num_3d_resources; |
| 408 | } else if (unhide_svga) { | 408 | } else if (unhide_svga) { |
| 409 | mutex_lock(&dev_priv->hw_mutex); | ||
| 410 | vmw_write(dev_priv, SVGA_REG_ENABLE, | 409 | vmw_write(dev_priv, SVGA_REG_ENABLE, |
| 411 | vmw_read(dev_priv, SVGA_REG_ENABLE) & | 410 | vmw_read(dev_priv, SVGA_REG_ENABLE) & |
| 412 | ~SVGA_REG_ENABLE_HIDE); | 411 | ~SVGA_REG_ENABLE_HIDE); |
| 413 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 414 | } | 412 | } |
| 415 | 413 | ||
| 416 | mutex_unlock(&dev_priv->release_mutex); | 414 | mutex_unlock(&dev_priv->release_mutex); |
| @@ -433,13 +431,10 @@ void vmw_3d_resource_dec(struct vmw_private *dev_priv, | |||
| 433 | mutex_lock(&dev_priv->release_mutex); | 431 | mutex_lock(&dev_priv->release_mutex); |
| 434 | if (unlikely(--dev_priv->num_3d_resources == 0)) | 432 | if (unlikely(--dev_priv->num_3d_resources == 0)) |
| 435 | vmw_release_device(dev_priv); | 433 | vmw_release_device(dev_priv); |
| 436 | else if (hide_svga) { | 434 | else if (hide_svga) |
| 437 | mutex_lock(&dev_priv->hw_mutex); | ||
| 438 | vmw_write(dev_priv, SVGA_REG_ENABLE, | 435 | vmw_write(dev_priv, SVGA_REG_ENABLE, |
| 439 | vmw_read(dev_priv, SVGA_REG_ENABLE) | | 436 | vmw_read(dev_priv, SVGA_REG_ENABLE) | |
| 440 | SVGA_REG_ENABLE_HIDE); | 437 | SVGA_REG_ENABLE_HIDE); |
| 441 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 442 | } | ||
| 443 | 438 | ||
| 444 | n3d = (int32_t) dev_priv->num_3d_resources; | 439 | n3d = (int32_t) dev_priv->num_3d_resources; |
| 445 | mutex_unlock(&dev_priv->release_mutex); | 440 | mutex_unlock(&dev_priv->release_mutex); |
| @@ -600,12 +595,14 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 600 | dev_priv->dev = dev; | 595 | dev_priv->dev = dev; |
| 601 | dev_priv->vmw_chipset = chipset; | 596 | dev_priv->vmw_chipset = chipset; |
| 602 | dev_priv->last_read_seqno = (uint32_t) -100; | 597 | dev_priv->last_read_seqno = (uint32_t) -100; |
| 603 | mutex_init(&dev_priv->hw_mutex); | ||
| 604 | mutex_init(&dev_priv->cmdbuf_mutex); | 598 | mutex_init(&dev_priv->cmdbuf_mutex); |
| 605 | mutex_init(&dev_priv->release_mutex); | 599 | mutex_init(&dev_priv->release_mutex); |
| 606 | mutex_init(&dev_priv->binding_mutex); | 600 | mutex_init(&dev_priv->binding_mutex); |
| 607 | rwlock_init(&dev_priv->resource_lock); | 601 | rwlock_init(&dev_priv->resource_lock); |
| 608 | ttm_lock_init(&dev_priv->reservation_sem); | 602 | ttm_lock_init(&dev_priv->reservation_sem); |
| 603 | spin_lock_init(&dev_priv->hw_lock); | ||
| 604 | spin_lock_init(&dev_priv->waiter_lock); | ||
| 605 | spin_lock_init(&dev_priv->cap_lock); | ||
| 609 | 606 | ||
| 610 | for (i = vmw_res_context; i < vmw_res_max; ++i) { | 607 | for (i = vmw_res_context; i < vmw_res_max; ++i) { |
| 611 | idr_init(&dev_priv->res_idr[i]); | 608 | idr_init(&dev_priv->res_idr[i]); |
| @@ -626,14 +623,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 626 | 623 | ||
| 627 | dev_priv->enable_fb = enable_fbdev; | 624 | dev_priv->enable_fb = enable_fbdev; |
| 628 | 625 | ||
| 629 | mutex_lock(&dev_priv->hw_mutex); | ||
| 630 | |||
| 631 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | 626 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
| 632 | svga_id = vmw_read(dev_priv, SVGA_REG_ID); | 627 | svga_id = vmw_read(dev_priv, SVGA_REG_ID); |
| 633 | if (svga_id != SVGA_ID_2) { | 628 | if (svga_id != SVGA_ID_2) { |
| 634 | ret = -ENOSYS; | 629 | ret = -ENOSYS; |
| 635 | DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); | 630 | DRM_ERROR("Unsupported SVGA ID 0x%x\n", svga_id); |
| 636 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 637 | goto out_err0; | 631 | goto out_err0; |
| 638 | } | 632 | } |
| 639 | 633 | ||
| @@ -683,10 +677,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 683 | dev_priv->prim_bb_mem = dev_priv->vram_size; | 677 | dev_priv->prim_bb_mem = dev_priv->vram_size; |
| 684 | 678 | ||
| 685 | ret = vmw_dma_masks(dev_priv); | 679 | ret = vmw_dma_masks(dev_priv); |
| 686 | if (unlikely(ret != 0)) { | 680 | if (unlikely(ret != 0)) |
| 687 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 688 | goto out_err0; | 681 | goto out_err0; |
| 689 | } | ||
| 690 | 682 | ||
| 691 | /* | 683 | /* |
| 692 | * Limit back buffer size to VRAM size. Remove this once | 684 | * Limit back buffer size to VRAM size. Remove this once |
| @@ -695,8 +687,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
| 695 | if (dev_priv->prim_bb_mem > dev_priv->vram_size) | 687 | if (dev_priv->prim_bb_mem > dev_priv->vram_size) |
| 696 | dev_priv->prim_bb_mem = dev_priv->vram_size; | 688 | dev_priv->prim_bb_mem = dev_priv->vram_size; |
| 697 | 689 | ||
| 698 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 699 | |||
| 700 | vmw_print_capabilities(dev_priv->capabilities); | 690 | vmw_print_capabilities(dev_priv->capabilities); |
| 701 | 691 | ||
| 702 | if (dev_priv->capabilities & SVGA_CAP_GMR2) { | 692 | if (dev_priv->capabilities & SVGA_CAP_GMR2) { |
| @@ -1160,9 +1150,7 @@ static int vmw_master_set(struct drm_device *dev, | |||
| 1160 | if (unlikely(ret != 0)) | 1150 | if (unlikely(ret != 0)) |
| 1161 | return ret; | 1151 | return ret; |
| 1162 | vmw_kms_save_vga(dev_priv); | 1152 | vmw_kms_save_vga(dev_priv); |
| 1163 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1164 | vmw_write(dev_priv, SVGA_REG_TRACES, 0); | 1153 | vmw_write(dev_priv, SVGA_REG_TRACES, 0); |
| 1165 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1166 | } | 1154 | } |
| 1167 | 1155 | ||
| 1168 | if (active) { | 1156 | if (active) { |
| @@ -1196,9 +1184,7 @@ out_no_active_lock: | |||
| 1196 | if (!dev_priv->enable_fb) { | 1184 | if (!dev_priv->enable_fb) { |
| 1197 | vmw_kms_restore_vga(dev_priv); | 1185 | vmw_kms_restore_vga(dev_priv); |
| 1198 | vmw_3d_resource_dec(dev_priv, true); | 1186 | vmw_3d_resource_dec(dev_priv, true); |
| 1199 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1200 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | 1187 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); |
| 1201 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1202 | } | 1188 | } |
| 1203 | return ret; | 1189 | return ret; |
| 1204 | } | 1190 | } |
| @@ -1233,9 +1219,7 @@ static void vmw_master_drop(struct drm_device *dev, | |||
| 1233 | DRM_ERROR("Unable to clean VRAM on master drop.\n"); | 1219 | DRM_ERROR("Unable to clean VRAM on master drop.\n"); |
| 1234 | vmw_kms_restore_vga(dev_priv); | 1220 | vmw_kms_restore_vga(dev_priv); |
| 1235 | vmw_3d_resource_dec(dev_priv, true); | 1221 | vmw_3d_resource_dec(dev_priv, true); |
| 1236 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1237 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); | 1222 | vmw_write(dev_priv, SVGA_REG_TRACES, 1); |
| 1238 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1239 | } | 1223 | } |
| 1240 | 1224 | ||
| 1241 | dev_priv->active_master = &dev_priv->fbdev_master; | 1225 | dev_priv->active_master = &dev_priv->fbdev_master; |
| @@ -1367,10 +1351,8 @@ static void vmw_pm_complete(struct device *kdev) | |||
| 1367 | struct drm_device *dev = pci_get_drvdata(pdev); | 1351 | struct drm_device *dev = pci_get_drvdata(pdev); |
| 1368 | struct vmw_private *dev_priv = vmw_priv(dev); | 1352 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1369 | 1353 | ||
| 1370 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1371 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); | 1354 | vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); |
| 1372 | (void) vmw_read(dev_priv, SVGA_REG_ID); | 1355 | (void) vmw_read(dev_priv, SVGA_REG_ID); |
| 1373 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1374 | 1356 | ||
| 1375 | /** | 1357 | /** |
| 1376 | * Reclaim 3d reference held by fbdev and potentially | 1358 | * Reclaim 3d reference held by fbdev and potentially |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4ee799b43d5d..d26a6daa9719 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
| @@ -399,7 +399,8 @@ struct vmw_private { | |||
| 399 | uint32_t memory_size; | 399 | uint32_t memory_size; |
| 400 | bool has_gmr; | 400 | bool has_gmr; |
| 401 | bool has_mob; | 401 | bool has_mob; |
| 402 | struct mutex hw_mutex; | 402 | spinlock_t hw_lock; |
| 403 | spinlock_t cap_lock; | ||
| 403 | 404 | ||
| 404 | /* | 405 | /* |
| 405 | * VGA registers. | 406 | * VGA registers. |
| @@ -449,8 +450,9 @@ struct vmw_private { | |||
| 449 | atomic_t marker_seq; | 450 | atomic_t marker_seq; |
| 450 | wait_queue_head_t fence_queue; | 451 | wait_queue_head_t fence_queue; |
| 451 | wait_queue_head_t fifo_queue; | 452 | wait_queue_head_t fifo_queue; |
| 452 | int fence_queue_waiters; /* Protected by hw_mutex */ | 453 | spinlock_t waiter_lock; |
| 453 | int goal_queue_waiters; /* Protected by hw_mutex */ | 454 | int fence_queue_waiters; /* Protected by waiter_lock */ |
| 455 | int goal_queue_waiters; /* Protected by waiter_lock */ | ||
| 454 | atomic_t fifo_queue_waiters; | 456 | atomic_t fifo_queue_waiters; |
| 455 | uint32_t last_read_seqno; | 457 | uint32_t last_read_seqno; |
| 456 | spinlock_t irq_lock; | 458 | spinlock_t irq_lock; |
| @@ -553,20 +555,35 @@ static inline struct vmw_master *vmw_master(struct drm_master *master) | |||
| 553 | return (struct vmw_master *) master->driver_priv; | 555 | return (struct vmw_master *) master->driver_priv; |
| 554 | } | 556 | } |
| 555 | 557 | ||
| 558 | /* | ||
| 559 | * The locking here is fine-grained, so that it is performed once | ||
| 560 | * for every read- and write operation. This is of course costly, but we | ||
| 561 | * don't perform much register access in the timing critical paths anyway. | ||
| 562 | * Instead we have the extra benefit of being sure that we don't forget | ||
| 563 | * the hw lock around register accesses. | ||
| 564 | */ | ||
| 556 | static inline void vmw_write(struct vmw_private *dev_priv, | 565 | static inline void vmw_write(struct vmw_private *dev_priv, |
| 557 | unsigned int offset, uint32_t value) | 566 | unsigned int offset, uint32_t value) |
| 558 | { | 567 | { |
| 568 | unsigned long irq_flags; | ||
| 569 | |||
| 570 | spin_lock_irqsave(&dev_priv->hw_lock, irq_flags); | ||
| 559 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); | 571 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); |
| 560 | outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT); | 572 | outl(value, dev_priv->io_start + VMWGFX_VALUE_PORT); |
| 573 | spin_unlock_irqrestore(&dev_priv->hw_lock, irq_flags); | ||
| 561 | } | 574 | } |
| 562 | 575 | ||
| 563 | static inline uint32_t vmw_read(struct vmw_private *dev_priv, | 576 | static inline uint32_t vmw_read(struct vmw_private *dev_priv, |
| 564 | unsigned int offset) | 577 | unsigned int offset) |
| 565 | { | 578 | { |
| 566 | uint32_t val; | 579 | unsigned long irq_flags; |
| 580 | u32 val; | ||
| 567 | 581 | ||
| 582 | spin_lock_irqsave(&dev_priv->hw_lock, irq_flags); | ||
| 568 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); | 583 | outl(offset, dev_priv->io_start + VMWGFX_INDEX_PORT); |
| 569 | val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT); | 584 | val = inl(dev_priv->io_start + VMWGFX_VALUE_PORT); |
| 585 | spin_unlock_irqrestore(&dev_priv->hw_lock, irq_flags); | ||
| 586 | |||
| 570 | return val; | 587 | return val; |
| 571 | } | 588 | } |
| 572 | 589 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index b7594cb758af..945f1e0dad92 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | |||
| @@ -35,7 +35,7 @@ struct vmw_fence_manager { | |||
| 35 | struct vmw_private *dev_priv; | 35 | struct vmw_private *dev_priv; |
| 36 | spinlock_t lock; | 36 | spinlock_t lock; |
| 37 | struct list_head fence_list; | 37 | struct list_head fence_list; |
| 38 | struct work_struct work, ping_work; | 38 | struct work_struct work; |
| 39 | u32 user_fence_size; | 39 | u32 user_fence_size; |
| 40 | u32 fence_size; | 40 | u32 fence_size; |
| 41 | u32 event_fence_action_size; | 41 | u32 event_fence_action_size; |
| @@ -134,14 +134,6 @@ static const char *vmw_fence_get_timeline_name(struct fence *f) | |||
| 134 | return "svga"; | 134 | return "svga"; |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void vmw_fence_ping_func(struct work_struct *work) | ||
| 138 | { | ||
| 139 | struct vmw_fence_manager *fman = | ||
| 140 | container_of(work, struct vmw_fence_manager, ping_work); | ||
| 141 | |||
| 142 | vmw_fifo_ping_host(fman->dev_priv, SVGA_SYNC_GENERIC); | ||
| 143 | } | ||
| 144 | |||
| 145 | static bool vmw_fence_enable_signaling(struct fence *f) | 137 | static bool vmw_fence_enable_signaling(struct fence *f) |
| 146 | { | 138 | { |
| 147 | struct vmw_fence_obj *fence = | 139 | struct vmw_fence_obj *fence = |
| @@ -155,11 +147,7 @@ static bool vmw_fence_enable_signaling(struct fence *f) | |||
| 155 | if (seqno - fence->base.seqno < VMW_FENCE_WRAP) | 147 | if (seqno - fence->base.seqno < VMW_FENCE_WRAP) |
| 156 | return false; | 148 | return false; |
| 157 | 149 | ||
| 158 | if (mutex_trylock(&dev_priv->hw_mutex)) { | 150 | vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); |
| 159 | vmw_fifo_ping_host_locked(dev_priv, SVGA_SYNC_GENERIC); | ||
| 160 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 161 | } else | ||
| 162 | schedule_work(&fman->ping_work); | ||
| 163 | 151 | ||
| 164 | return true; | 152 | return true; |
| 165 | } | 153 | } |
| @@ -305,7 +293,6 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) | |||
| 305 | INIT_LIST_HEAD(&fman->fence_list); | 293 | INIT_LIST_HEAD(&fman->fence_list); |
| 306 | INIT_LIST_HEAD(&fman->cleanup_list); | 294 | INIT_LIST_HEAD(&fman->cleanup_list); |
| 307 | INIT_WORK(&fman->work, &vmw_fence_work_func); | 295 | INIT_WORK(&fman->work, &vmw_fence_work_func); |
| 308 | INIT_WORK(&fman->ping_work, &vmw_fence_ping_func); | ||
| 309 | fman->fifo_down = true; | 296 | fman->fifo_down = true; |
| 310 | fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); | 297 | fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)); |
| 311 | fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); | 298 | fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); |
| @@ -323,7 +310,6 @@ void vmw_fence_manager_takedown(struct vmw_fence_manager *fman) | |||
| 323 | bool lists_empty; | 310 | bool lists_empty; |
| 324 | 311 | ||
| 325 | (void) cancel_work_sync(&fman->work); | 312 | (void) cancel_work_sync(&fman->work); |
| 326 | (void) cancel_work_sync(&fman->ping_work); | ||
| 327 | 313 | ||
| 328 | spin_lock_irqsave(&fman->lock, irq_flags); | 314 | spin_lock_irqsave(&fman->lock, irq_flags); |
| 329 | lists_empty = list_empty(&fman->fence_list) && | 315 | lists_empty = list_empty(&fman->fence_list) && |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 09e10aefcd8e..39f2b03888e7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
| @@ -44,10 +44,10 @@ bool vmw_fifo_have_3d(struct vmw_private *dev_priv) | |||
| 44 | if (!dev_priv->has_mob) | 44 | if (!dev_priv->has_mob) |
| 45 | return false; | 45 | return false; |
| 46 | 46 | ||
| 47 | mutex_lock(&dev_priv->hw_mutex); | 47 | spin_lock(&dev_priv->cap_lock); |
| 48 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D); | 48 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_3D); |
| 49 | result = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 49 | result = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 50 | mutex_unlock(&dev_priv->hw_mutex); | 50 | spin_unlock(&dev_priv->cap_lock); |
| 51 | 51 | ||
| 52 | return (result != 0); | 52 | return (result != 0); |
| 53 | } | 53 | } |
| @@ -120,7 +120,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 120 | DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT)); | 120 | DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT)); |
| 121 | DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL)); | 121 | DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL)); |
| 122 | 122 | ||
| 123 | mutex_lock(&dev_priv->hw_mutex); | ||
| 124 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); | 123 | dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE); |
| 125 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); | 124 | dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE); |
| 126 | dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); | 125 | dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES); |
| @@ -143,7 +142,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 143 | mb(); | 142 | mb(); |
| 144 | 143 | ||
| 145 | vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1); | 144 | vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1); |
| 146 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 147 | 145 | ||
| 148 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); | 146 | max = ioread32(fifo_mem + SVGA_FIFO_MAX); |
| 149 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); | 147 | min = ioread32(fifo_mem + SVGA_FIFO_MIN); |
| @@ -160,31 +158,28 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 160 | return vmw_fifo_send_fence(dev_priv, &dummy); | 158 | return vmw_fifo_send_fence(dev_priv, &dummy); |
| 161 | } | 159 | } |
| 162 | 160 | ||
| 163 | void vmw_fifo_ping_host_locked(struct vmw_private *dev_priv, uint32_t reason) | 161 | void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason) |
| 164 | { | 162 | { |
| 165 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; | 163 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; |
| 164 | static DEFINE_SPINLOCK(ping_lock); | ||
| 165 | unsigned long irq_flags; | ||
| 166 | 166 | ||
| 167 | /* | ||
| 168 | * The ping_lock is needed because we don't have an atomic | ||
| 169 | * test-and-set of the SVGA_FIFO_BUSY register. | ||
| 170 | */ | ||
| 171 | spin_lock_irqsave(&ping_lock, irq_flags); | ||
| 167 | if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) { | 172 | if (unlikely(ioread32(fifo_mem + SVGA_FIFO_BUSY) == 0)) { |
| 168 | iowrite32(1, fifo_mem + SVGA_FIFO_BUSY); | 173 | iowrite32(1, fifo_mem + SVGA_FIFO_BUSY); |
| 169 | vmw_write(dev_priv, SVGA_REG_SYNC, reason); | 174 | vmw_write(dev_priv, SVGA_REG_SYNC, reason); |
| 170 | } | 175 | } |
| 171 | } | 176 | spin_unlock_irqrestore(&ping_lock, irq_flags); |
| 172 | |||
| 173 | void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason) | ||
| 174 | { | ||
| 175 | mutex_lock(&dev_priv->hw_mutex); | ||
| 176 | |||
| 177 | vmw_fifo_ping_host_locked(dev_priv, reason); | ||
| 178 | |||
| 179 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 180 | } | 177 | } |
| 181 | 178 | ||
| 182 | void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | 179 | void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) |
| 183 | { | 180 | { |
| 184 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; | 181 | __le32 __iomem *fifo_mem = dev_priv->mmio_virt; |
| 185 | 182 | ||
| 186 | mutex_lock(&dev_priv->hw_mutex); | ||
| 187 | |||
| 188 | vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); | 183 | vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); |
| 189 | while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) | 184 | while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0) |
| 190 | ; | 185 | ; |
| @@ -198,7 +193,6 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
| 198 | vmw_write(dev_priv, SVGA_REG_TRACES, | 193 | vmw_write(dev_priv, SVGA_REG_TRACES, |
| 199 | dev_priv->traces_state); | 194 | dev_priv->traces_state); |
| 200 | 195 | ||
| 201 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 202 | vmw_marker_queue_takedown(&fifo->marker_queue); | 196 | vmw_marker_queue_takedown(&fifo->marker_queue); |
| 203 | 197 | ||
| 204 | if (likely(fifo->static_buffer != NULL)) { | 198 | if (likely(fifo->static_buffer != NULL)) { |
| @@ -271,7 +265,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 271 | return vmw_fifo_wait_noirq(dev_priv, bytes, | 265 | return vmw_fifo_wait_noirq(dev_priv, bytes, |
| 272 | interruptible, timeout); | 266 | interruptible, timeout); |
| 273 | 267 | ||
| 274 | mutex_lock(&dev_priv->hw_mutex); | 268 | spin_lock(&dev_priv->waiter_lock); |
| 275 | if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) { | 269 | if (atomic_add_return(1, &dev_priv->fifo_queue_waiters) > 0) { |
| 276 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | 270 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); |
| 277 | outl(SVGA_IRQFLAG_FIFO_PROGRESS, | 271 | outl(SVGA_IRQFLAG_FIFO_PROGRESS, |
| @@ -280,7 +274,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 280 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 274 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 281 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 275 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 282 | } | 276 | } |
| 283 | mutex_unlock(&dev_priv->hw_mutex); | 277 | spin_unlock(&dev_priv->waiter_lock); |
| 284 | 278 | ||
| 285 | if (interruptible) | 279 | if (interruptible) |
| 286 | ret = wait_event_interruptible_timeout | 280 | ret = wait_event_interruptible_timeout |
| @@ -296,14 +290,14 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, | |||
| 296 | else if (likely(ret > 0)) | 290 | else if (likely(ret > 0)) |
| 297 | ret = 0; | 291 | ret = 0; |
| 298 | 292 | ||
| 299 | mutex_lock(&dev_priv->hw_mutex); | 293 | spin_lock(&dev_priv->waiter_lock); |
| 300 | if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { | 294 | if (atomic_dec_and_test(&dev_priv->fifo_queue_waiters)) { |
| 301 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); | 295 | spin_lock_irqsave(&dev_priv->irq_lock, irq_flags); |
| 302 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; | 296 | dev_priv->irq_mask &= ~SVGA_IRQFLAG_FIFO_PROGRESS; |
| 303 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 297 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 304 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 298 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 305 | } | 299 | } |
| 306 | mutex_unlock(&dev_priv->hw_mutex); | 300 | spin_unlock(&dev_priv->waiter_lock); |
| 307 | 301 | ||
| 308 | return ret; | 302 | return ret; |
| 309 | } | 303 | } |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 37881ecf5d7a..69c8ce23123c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | |||
| @@ -135,13 +135,13 @@ static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce, | |||
| 135 | (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32); | 135 | (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32); |
| 136 | compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS; | 136 | compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS; |
| 137 | 137 | ||
| 138 | mutex_lock(&dev_priv->hw_mutex); | 138 | spin_lock(&dev_priv->cap_lock); |
| 139 | for (i = 0; i < max_size; ++i) { | 139 | for (i = 0; i < max_size; ++i) { |
| 140 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); | 140 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); |
| 141 | compat_cap->pairs[i][0] = i; | 141 | compat_cap->pairs[i][0] = i; |
| 142 | compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 142 | compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 143 | } | 143 | } |
| 144 | mutex_unlock(&dev_priv->hw_mutex); | 144 | spin_unlock(&dev_priv->cap_lock); |
| 145 | 145 | ||
| 146 | return 0; | 146 | return 0; |
| 147 | } | 147 | } |
| @@ -191,12 +191,12 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, | |||
| 191 | if (num > SVGA3D_DEVCAP_MAX) | 191 | if (num > SVGA3D_DEVCAP_MAX) |
| 192 | num = SVGA3D_DEVCAP_MAX; | 192 | num = SVGA3D_DEVCAP_MAX; |
| 193 | 193 | ||
| 194 | mutex_lock(&dev_priv->hw_mutex); | 194 | spin_lock(&dev_priv->cap_lock); |
| 195 | for (i = 0; i < num; ++i) { | 195 | for (i = 0; i < num; ++i) { |
| 196 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); | 196 | vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); |
| 197 | *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP); | 197 | *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP); |
| 198 | } | 198 | } |
| 199 | mutex_unlock(&dev_priv->hw_mutex); | 199 | spin_unlock(&dev_priv->cap_lock); |
| 200 | } else if (gb_objects) { | 200 | } else if (gb_objects) { |
| 201 | ret = vmw_fill_compat_cap(dev_priv, bounce, size); | 201 | ret = vmw_fill_compat_cap(dev_priv, bounce, size); |
| 202 | if (unlikely(ret != 0)) | 202 | if (unlikely(ret != 0)) |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 0c423766c441..9fe9827ee499 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | |||
| @@ -62,13 +62,8 @@ irqreturn_t vmw_irq_handler(int irq, void *arg) | |||
| 62 | 62 | ||
| 63 | static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) | 63 | static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) |
| 64 | { | 64 | { |
| 65 | uint32_t busy; | ||
| 66 | 65 | ||
| 67 | mutex_lock(&dev_priv->hw_mutex); | 66 | return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0); |
| 68 | busy = vmw_read(dev_priv, SVGA_REG_BUSY); | ||
| 69 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 70 | |||
| 71 | return (busy == 0); | ||
| 72 | } | 67 | } |
| 73 | 68 | ||
| 74 | void vmw_update_seqno(struct vmw_private *dev_priv, | 69 | void vmw_update_seqno(struct vmw_private *dev_priv, |
| @@ -184,7 +179,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, | |||
| 184 | 179 | ||
| 185 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | 180 | void vmw_seqno_waiter_add(struct vmw_private *dev_priv) |
| 186 | { | 181 | { |
| 187 | mutex_lock(&dev_priv->hw_mutex); | 182 | spin_lock(&dev_priv->waiter_lock); |
| 188 | if (dev_priv->fence_queue_waiters++ == 0) { | 183 | if (dev_priv->fence_queue_waiters++ == 0) { |
| 189 | unsigned long irq_flags; | 184 | unsigned long irq_flags; |
| 190 | 185 | ||
| @@ -195,12 +190,12 @@ void vmw_seqno_waiter_add(struct vmw_private *dev_priv) | |||
| 195 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 190 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 196 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 191 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 197 | } | 192 | } |
| 198 | mutex_unlock(&dev_priv->hw_mutex); | 193 | spin_unlock(&dev_priv->waiter_lock); |
| 199 | } | 194 | } |
| 200 | 195 | ||
| 201 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | 196 | void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) |
| 202 | { | 197 | { |
| 203 | mutex_lock(&dev_priv->hw_mutex); | 198 | spin_lock(&dev_priv->waiter_lock); |
| 204 | if (--dev_priv->fence_queue_waiters == 0) { | 199 | if (--dev_priv->fence_queue_waiters == 0) { |
| 205 | unsigned long irq_flags; | 200 | unsigned long irq_flags; |
| 206 | 201 | ||
| @@ -209,13 +204,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) | |||
| 209 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 204 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 210 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 205 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 211 | } | 206 | } |
| 212 | mutex_unlock(&dev_priv->hw_mutex); | 207 | spin_unlock(&dev_priv->waiter_lock); |
| 213 | } | 208 | } |
| 214 | 209 | ||
| 215 | 210 | ||
| 216 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) | 211 | void vmw_goal_waiter_add(struct vmw_private *dev_priv) |
| 217 | { | 212 | { |
| 218 | mutex_lock(&dev_priv->hw_mutex); | 213 | spin_lock(&dev_priv->waiter_lock); |
| 219 | if (dev_priv->goal_queue_waiters++ == 0) { | 214 | if (dev_priv->goal_queue_waiters++ == 0) { |
| 220 | unsigned long irq_flags; | 215 | unsigned long irq_flags; |
| 221 | 216 | ||
| @@ -226,12 +221,12 @@ void vmw_goal_waiter_add(struct vmw_private *dev_priv) | |||
| 226 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 221 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 227 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 222 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 228 | } | 223 | } |
| 229 | mutex_unlock(&dev_priv->hw_mutex); | 224 | spin_unlock(&dev_priv->waiter_lock); |
| 230 | } | 225 | } |
| 231 | 226 | ||
| 232 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) | 227 | void vmw_goal_waiter_remove(struct vmw_private *dev_priv) |
| 233 | { | 228 | { |
| 234 | mutex_lock(&dev_priv->hw_mutex); | 229 | spin_lock(&dev_priv->waiter_lock); |
| 235 | if (--dev_priv->goal_queue_waiters == 0) { | 230 | if (--dev_priv->goal_queue_waiters == 0) { |
| 236 | unsigned long irq_flags; | 231 | unsigned long irq_flags; |
| 237 | 232 | ||
| @@ -240,7 +235,7 @@ void vmw_goal_waiter_remove(struct vmw_private *dev_priv) | |||
| 240 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); | 235 | vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); |
| 241 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); | 236 | spin_unlock_irqrestore(&dev_priv->irq_lock, irq_flags); |
| 242 | } | 237 | } |
| 243 | mutex_unlock(&dev_priv->hw_mutex); | 238 | spin_unlock(&dev_priv->waiter_lock); |
| 244 | } | 239 | } |
| 245 | 240 | ||
| 246 | int vmw_wait_seqno(struct vmw_private *dev_priv, | 241 | int vmw_wait_seqno(struct vmw_private *dev_priv, |
| @@ -315,9 +310,7 @@ void vmw_irq_uninstall(struct drm_device *dev) | |||
| 315 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) | 310 | if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) |
| 316 | return; | 311 | return; |
| 317 | 312 | ||
| 318 | mutex_lock(&dev_priv->hw_mutex); | ||
| 319 | vmw_write(dev_priv, SVGA_REG_IRQMASK, 0); | 313 | vmw_write(dev_priv, SVGA_REG_IRQMASK, 0); |
| 320 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 321 | 314 | ||
| 322 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 315 | status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
| 323 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); | 316 | outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 3725b521d931..8725b79e7847 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
| @@ -1828,9 +1828,7 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force) | |||
| 1828 | struct vmw_private *dev_priv = vmw_priv(dev); | 1828 | struct vmw_private *dev_priv = vmw_priv(dev); |
| 1829 | struct vmw_display_unit *du = vmw_connector_to_du(connector); | 1829 | struct vmw_display_unit *du = vmw_connector_to_du(connector); |
| 1830 | 1830 | ||
| 1831 | mutex_lock(&dev_priv->hw_mutex); | ||
| 1832 | num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); | 1831 | num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS); |
| 1833 | mutex_unlock(&dev_priv->hw_mutex); | ||
| 1834 | 1832 | ||
| 1835 | return ((vmw_connector_to_du(connector)->unit < num_displays && | 1833 | return ((vmw_connector_to_du(connector)->unit < num_displays && |
| 1836 | du->pref_active) ? | 1834 | du->pref_active) ? |
