diff options
Diffstat (limited to 'drivers/gpu')
82 files changed, 1156 insertions, 801 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 7d4974b83af7..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" |
@@ -127,17 +126,14 @@ static int kfd_open(struct inode *inode, struct file *filep) | |||
127 | return 0; | 126 | return 0; |
128 | } | 127 | } |
129 | 128 | ||
130 | 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, |
131 | void __user *arg) | 130 | void *data) |
132 | { | 131 | { |
133 | struct kfd_ioctl_get_version_args args; | 132 | struct kfd_ioctl_get_version_args *args = data; |
134 | int err = 0; | 133 | int err = 0; |
135 | 134 | ||
136 | args.major_version = KFD_IOCTL_MAJOR_VERSION; | 135 | args->major_version = KFD_IOCTL_MAJOR_VERSION; |
137 | args.minor_version = KFD_IOCTL_MINOR_VERSION; | 136 | args->minor_version = KFD_IOCTL_MINOR_VERSION; |
138 | |||
139 | if (copy_to_user(arg, &args, sizeof(args))) | ||
140 | err = -EFAULT; | ||
141 | 137 | ||
142 | return err; | 138 | return err; |
143 | } | 139 | } |
@@ -221,10 +217,10 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, | |||
221 | return 0; | 217 | return 0; |
222 | } | 218 | } |
223 | 219 | ||
224 | 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, |
225 | void __user *arg) | 221 | void *data) |
226 | { | 222 | { |
227 | struct kfd_ioctl_create_queue_args args; | 223 | struct kfd_ioctl_create_queue_args *args = data; |
228 | struct kfd_dev *dev; | 224 | struct kfd_dev *dev; |
229 | int err = 0; | 225 | int err = 0; |
230 | unsigned int queue_id; | 226 | unsigned int queue_id; |
@@ -233,16 +229,13 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
233 | 229 | ||
234 | memset(&q_properties, 0, sizeof(struct queue_properties)); | 230 | memset(&q_properties, 0, sizeof(struct queue_properties)); |
235 | 231 | ||
236 | if (copy_from_user(&args, arg, sizeof(args))) | ||
237 | return -EFAULT; | ||
238 | |||
239 | pr_debug("kfd: creating queue ioctl\n"); | 232 | pr_debug("kfd: creating queue ioctl\n"); |
240 | 233 | ||
241 | err = set_queue_properties_from_user(&q_properties, &args); | 234 | err = set_queue_properties_from_user(&q_properties, args); |
242 | if (err) | 235 | if (err) |
243 | return err; | 236 | return err; |
244 | 237 | ||
245 | dev = kfd_device_by_id(args.gpu_id); | 238 | dev = kfd_device_by_id(args->gpu_id); |
246 | if (dev == NULL) | 239 | if (dev == NULL) |
247 | return -EINVAL; | 240 | return -EINVAL; |
248 | 241 | ||
@@ -250,7 +243,7 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
250 | 243 | ||
251 | pdd = kfd_bind_process_to_device(dev, p); | 244 | pdd = kfd_bind_process_to_device(dev, p); |
252 | if (IS_ERR(pdd)) { | 245 | if (IS_ERR(pdd)) { |
253 | err = PTR_ERR(pdd); | 246 | err = -ESRCH; |
254 | goto err_bind_process; | 247 | goto err_bind_process; |
255 | } | 248 | } |
256 | 249 | ||
@@ -263,33 +256,26 @@ static long kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, | |||
263 | if (err != 0) | 256 | if (err != 0) |
264 | goto err_create_queue; | 257 | goto err_create_queue; |
265 | 258 | ||
266 | args.queue_id = queue_id; | 259 | args->queue_id = queue_id; |
267 | 260 | ||
268 | /* Return gpu_id as doorbell offset for mmap usage */ | 261 | /* Return gpu_id as doorbell offset for mmap usage */ |
269 | args.doorbell_offset = args.gpu_id << PAGE_SHIFT; | 262 | args->doorbell_offset = args->gpu_id << PAGE_SHIFT; |
270 | |||
271 | if (copy_to_user(arg, &args, sizeof(args))) { | ||
272 | err = -EFAULT; | ||
273 | goto err_copy_args_out; | ||
274 | } | ||
275 | 263 | ||
276 | mutex_unlock(&p->mutex); | 264 | mutex_unlock(&p->mutex); |
277 | 265 | ||
278 | 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); |
279 | 267 | ||
280 | pr_debug("ring buffer address == 0x%016llX\n", | 268 | pr_debug("ring buffer address == 0x%016llX\n", |
281 | args.ring_base_address); | 269 | args->ring_base_address); |
282 | 270 | ||
283 | pr_debug("read ptr address == 0x%016llX\n", | 271 | pr_debug("read ptr address == 0x%016llX\n", |
284 | args.read_pointer_address); | 272 | args->read_pointer_address); |
285 | 273 | ||
286 | pr_debug("write ptr address == 0x%016llX\n", | 274 | pr_debug("write ptr address == 0x%016llX\n", |
287 | args.write_pointer_address); | 275 | args->write_pointer_address); |
288 | 276 | ||
289 | return 0; | 277 | return 0; |
290 | 278 | ||
291 | err_copy_args_out: | ||
292 | pqm_destroy_queue(&p->pqm, queue_id); | ||
293 | err_create_queue: | 279 | err_create_queue: |
294 | err_bind_process: | 280 | err_bind_process: |
295 | mutex_unlock(&p->mutex); | 281 | mutex_unlock(&p->mutex); |
@@ -297,99 +283,90 @@ err_bind_process: | |||
297 | } | 283 | } |
298 | 284 | ||
299 | 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, |
300 | void __user *arg) | 286 | void *data) |
301 | { | 287 | { |
302 | int retval; | 288 | int retval; |
303 | struct kfd_ioctl_destroy_queue_args args; | 289 | struct kfd_ioctl_destroy_queue_args *args = data; |
304 | |||
305 | if (copy_from_user(&args, arg, sizeof(args))) | ||
306 | return -EFAULT; | ||
307 | 290 | ||
308 | pr_debug("kfd: destroying queue id %d for PASID %d\n", | 291 | pr_debug("kfd: destroying queue id %d for PASID %d\n", |
309 | args.queue_id, | 292 | args->queue_id, |
310 | p->pasid); | 293 | p->pasid); |
311 | 294 | ||
312 | mutex_lock(&p->mutex); | 295 | mutex_lock(&p->mutex); |
313 | 296 | ||
314 | retval = pqm_destroy_queue(&p->pqm, args.queue_id); | 297 | retval = pqm_destroy_queue(&p->pqm, args->queue_id); |
315 | 298 | ||
316 | mutex_unlock(&p->mutex); | 299 | mutex_unlock(&p->mutex); |
317 | return retval; | 300 | return retval; |
318 | } | 301 | } |
319 | 302 | ||
320 | 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, |
321 | void __user *arg) | 304 | void *data) |
322 | { | 305 | { |
323 | int retval; | 306 | int retval; |
324 | struct kfd_ioctl_update_queue_args args; | 307 | struct kfd_ioctl_update_queue_args *args = data; |
325 | struct queue_properties properties; | 308 | struct queue_properties properties; |
326 | 309 | ||
327 | if (copy_from_user(&args, arg, sizeof(args))) | 310 | if (args->queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { |
328 | return -EFAULT; | ||
329 | |||
330 | if (args.queue_percentage > KFD_MAX_QUEUE_PERCENTAGE) { | ||
331 | 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"); |
332 | return -EINVAL; | 312 | return -EINVAL; |
333 | } | 313 | } |
334 | 314 | ||
335 | if (args.queue_priority > KFD_MAX_QUEUE_PRIORITY) { | 315 | if (args->queue_priority > KFD_MAX_QUEUE_PRIORITY) { |
336 | 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"); |
337 | return -EINVAL; | 317 | return -EINVAL; |
338 | } | 318 | } |
339 | 319 | ||
340 | if ((args.ring_base_address) && | 320 | if ((args->ring_base_address) && |
341 | (!access_ok(VERIFY_WRITE, | 321 | (!access_ok(VERIFY_WRITE, |
342 | (const void __user *) args.ring_base_address, | 322 | (const void __user *) args->ring_base_address, |
343 | sizeof(uint64_t)))) { | 323 | sizeof(uint64_t)))) { |
344 | pr_err("kfd: can't access ring base address\n"); | 324 | pr_err("kfd: can't access ring base address\n"); |
345 | return -EFAULT; | 325 | return -EFAULT; |
346 | } | 326 | } |
347 | 327 | ||
348 | 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)) { |
349 | 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"); |
350 | return -EINVAL; | 330 | return -EINVAL; |
351 | } | 331 | } |
352 | 332 | ||
353 | properties.queue_address = args.ring_base_address; | 333 | properties.queue_address = args->ring_base_address; |
354 | properties.queue_size = args.ring_size; | 334 | properties.queue_size = args->ring_size; |
355 | properties.queue_percent = args.queue_percentage; | 335 | properties.queue_percent = args->queue_percentage; |
356 | properties.priority = args.queue_priority; | 336 | properties.priority = args->queue_priority; |
357 | 337 | ||
358 | pr_debug("kfd: updating queue id %d for PASID %d\n", | 338 | pr_debug("kfd: updating queue id %d for PASID %d\n", |
359 | args.queue_id, p->pasid); | 339 | args->queue_id, p->pasid); |
360 | 340 | ||
361 | mutex_lock(&p->mutex); | 341 | mutex_lock(&p->mutex); |
362 | 342 | ||
363 | retval = pqm_update_queue(&p->pqm, args.queue_id, &properties); | 343 | retval = pqm_update_queue(&p->pqm, args->queue_id, &properties); |
364 | 344 | ||
365 | mutex_unlock(&p->mutex); | 345 | mutex_unlock(&p->mutex); |
366 | 346 | ||
367 | return retval; | 347 | return retval; |
368 | } | 348 | } |
369 | 349 | ||
370 | static long kfd_ioctl_set_memory_policy(struct file *filep, | 350 | static int kfd_ioctl_set_memory_policy(struct file *filep, |
371 | struct kfd_process *p, void __user *arg) | 351 | struct kfd_process *p, void *data) |
372 | { | 352 | { |
373 | struct kfd_ioctl_set_memory_policy_args args; | 353 | struct kfd_ioctl_set_memory_policy_args *args = data; |
374 | struct kfd_dev *dev; | 354 | struct kfd_dev *dev; |
375 | int err = 0; | 355 | int err = 0; |
376 | struct kfd_process_device *pdd; | 356 | struct kfd_process_device *pdd; |
377 | enum cache_policy default_policy, alternate_policy; | 357 | enum cache_policy default_policy, alternate_policy; |
378 | 358 | ||
379 | if (copy_from_user(&args, arg, sizeof(args))) | 359 | if (args->default_policy != KFD_IOC_CACHE_POLICY_COHERENT |
380 | return -EFAULT; | 360 | && args->default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
381 | |||
382 | if (args.default_policy != KFD_IOC_CACHE_POLICY_COHERENT | ||
383 | && args.default_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | ||
384 | return -EINVAL; | 361 | return -EINVAL; |
385 | } | 362 | } |
386 | 363 | ||
387 | if (args.alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT | 364 | if (args->alternate_policy != KFD_IOC_CACHE_POLICY_COHERENT |
388 | && args.alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { | 365 | && args->alternate_policy != KFD_IOC_CACHE_POLICY_NONCOHERENT) { |
389 | return -EINVAL; | 366 | return -EINVAL; |
390 | } | 367 | } |
391 | 368 | ||
392 | dev = kfd_device_by_id(args.gpu_id); | 369 | dev = kfd_device_by_id(args->gpu_id); |
393 | if (dev == NULL) | 370 | if (dev == NULL) |
394 | return -EINVAL; | 371 | return -EINVAL; |
395 | 372 | ||
@@ -397,23 +374,23 @@ static long kfd_ioctl_set_memory_policy(struct file *filep, | |||
397 | 374 | ||
398 | pdd = kfd_bind_process_to_device(dev, p); | 375 | pdd = kfd_bind_process_to_device(dev, p); |
399 | if (IS_ERR(pdd)) { | 376 | if (IS_ERR(pdd)) { |
400 | err = PTR_ERR(pdd); | 377 | err = -ESRCH; |
401 | goto out; | 378 | goto out; |
402 | } | 379 | } |
403 | 380 | ||
404 | default_policy = (args.default_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 381 | default_policy = (args->default_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
405 | ? cache_policy_coherent : cache_policy_noncoherent; | 382 | ? cache_policy_coherent : cache_policy_noncoherent; |
406 | 383 | ||
407 | alternate_policy = | 384 | alternate_policy = |
408 | (args.alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) | 385 | (args->alternate_policy == KFD_IOC_CACHE_POLICY_COHERENT) |
409 | ? cache_policy_coherent : cache_policy_noncoherent; | 386 | ? cache_policy_coherent : cache_policy_noncoherent; |
410 | 387 | ||
411 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, | 388 | if (!dev->dqm->set_cache_memory_policy(dev->dqm, |
412 | &pdd->qpd, | 389 | &pdd->qpd, |
413 | default_policy, | 390 | default_policy, |
414 | alternate_policy, | 391 | alternate_policy, |
415 | (void __user *)args.alternate_aperture_base, | 392 | (void __user *)args->alternate_aperture_base, |
416 | args.alternate_aperture_size)) | 393 | args->alternate_aperture_size)) |
417 | err = -EINVAL; | 394 | err = -EINVAL; |
418 | 395 | ||
419 | out: | 396 | out: |
@@ -422,53 +399,44 @@ out: | |||
422 | return err; | 399 | return err; |
423 | } | 400 | } |
424 | 401 | ||
425 | static long kfd_ioctl_get_clock_counters(struct file *filep, | 402 | static int kfd_ioctl_get_clock_counters(struct file *filep, |
426 | struct kfd_process *p, void __user *arg) | 403 | struct kfd_process *p, void *data) |
427 | { | 404 | { |
428 | struct kfd_ioctl_get_clock_counters_args args; | 405 | struct kfd_ioctl_get_clock_counters_args *args = data; |
429 | struct kfd_dev *dev; | 406 | struct kfd_dev *dev; |
430 | struct timespec time; | 407 | struct timespec time; |
431 | 408 | ||
432 | if (copy_from_user(&args, arg, sizeof(args))) | 409 | dev = kfd_device_by_id(args->gpu_id); |
433 | return -EFAULT; | ||
434 | |||
435 | dev = kfd_device_by_id(args.gpu_id); | ||
436 | if (dev == NULL) | 410 | if (dev == NULL) |
437 | return -EINVAL; | 411 | return -EINVAL; |
438 | 412 | ||
439 | /* Reading GPU clock counter from KGD */ | 413 | /* Reading GPU clock counter from KGD */ |
440 | args.gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); | 414 | args->gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd); |
441 | 415 | ||
442 | /* No access to rdtsc. Using raw monotonic time */ | 416 | /* No access to rdtsc. Using raw monotonic time */ |
443 | getrawmonotonic(&time); | 417 | getrawmonotonic(&time); |
444 | args.cpu_clock_counter = (uint64_t)timespec_to_ns(&time); | 418 | args->cpu_clock_counter = (uint64_t)timespec_to_ns(&time); |
445 | 419 | ||
446 | get_monotonic_boottime(&time); | 420 | get_monotonic_boottime(&time); |
447 | args.system_clock_counter = (uint64_t)timespec_to_ns(&time); | 421 | args->system_clock_counter = (uint64_t)timespec_to_ns(&time); |
448 | 422 | ||
449 | /* Since the counter is in nano-seconds we use 1GHz frequency */ | 423 | /* Since the counter is in nano-seconds we use 1GHz frequency */ |
450 | args.system_clock_freq = 1000000000; | 424 | args->system_clock_freq = 1000000000; |
451 | |||
452 | if (copy_to_user(arg, &args, sizeof(args))) | ||
453 | return -EFAULT; | ||
454 | 425 | ||
455 | return 0; | 426 | return 0; |
456 | } | 427 | } |
457 | 428 | ||
458 | 429 | ||
459 | static int kfd_ioctl_get_process_apertures(struct file *filp, | 430 | static int kfd_ioctl_get_process_apertures(struct file *filp, |
460 | struct kfd_process *p, void __user *arg) | 431 | struct kfd_process *p, void *data) |
461 | { | 432 | { |
462 | struct kfd_ioctl_get_process_apertures_args args; | 433 | struct kfd_ioctl_get_process_apertures_args *args = data; |
463 | struct kfd_process_device_apertures *pAperture; | 434 | struct kfd_process_device_apertures *pAperture; |
464 | struct kfd_process_device *pdd; | 435 | struct kfd_process_device *pdd; |
465 | 436 | ||
466 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); | 437 | dev_dbg(kfd_device, "get apertures for PASID %d", p->pasid); |
467 | 438 | ||
468 | if (copy_from_user(&args, arg, sizeof(args))) | 439 | args->num_of_nodes = 0; |
469 | return -EFAULT; | ||
470 | |||
471 | args.num_of_nodes = 0; | ||
472 | 440 | ||
473 | mutex_lock(&p->mutex); | 441 | mutex_lock(&p->mutex); |
474 | 442 | ||
@@ -477,7 +445,8 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
477 | /* Run over all pdd of the process */ | 445 | /* Run over all pdd of the process */ |
478 | pdd = kfd_get_first_process_device_data(p); | 446 | pdd = kfd_get_first_process_device_data(p); |
479 | do { | 447 | do { |
480 | pAperture = &args.process_apertures[args.num_of_nodes]; | 448 | pAperture = |
449 | &args->process_apertures[args->num_of_nodes]; | ||
481 | pAperture->gpu_id = pdd->dev->id; | 450 | pAperture->gpu_id = pdd->dev->id; |
482 | pAperture->lds_base = pdd->lds_base; | 451 | pAperture->lds_base = pdd->lds_base; |
483 | pAperture->lds_limit = pdd->lds_limit; | 452 | pAperture->lds_limit = pdd->lds_limit; |
@@ -487,7 +456,7 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
487 | pAperture->scratch_limit = pdd->scratch_limit; | 456 | pAperture->scratch_limit = pdd->scratch_limit; |
488 | 457 | ||
489 | dev_dbg(kfd_device, | 458 | dev_dbg(kfd_device, |
490 | "node id %u\n", args.num_of_nodes); | 459 | "node id %u\n", args->num_of_nodes); |
491 | dev_dbg(kfd_device, | 460 | dev_dbg(kfd_device, |
492 | "gpu id %u\n", pdd->dev->id); | 461 | "gpu id %u\n", pdd->dev->id); |
493 | dev_dbg(kfd_device, | 462 | dev_dbg(kfd_device, |
@@ -503,80 +472,131 @@ static int kfd_ioctl_get_process_apertures(struct file *filp, | |||
503 | dev_dbg(kfd_device, | 472 | dev_dbg(kfd_device, |
504 | "scratch_limit %llX\n", pdd->scratch_limit); | 473 | "scratch_limit %llX\n", pdd->scratch_limit); |
505 | 474 | ||
506 | args.num_of_nodes++; | 475 | args->num_of_nodes++; |
507 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && | 476 | } while ((pdd = kfd_get_next_process_device_data(p, pdd)) != NULL && |
508 | (args.num_of_nodes < NUM_OF_SUPPORTED_GPUS)); | 477 | (args->num_of_nodes < NUM_OF_SUPPORTED_GPUS)); |
509 | } | 478 | } |
510 | 479 | ||
511 | mutex_unlock(&p->mutex); | 480 | mutex_unlock(&p->mutex); |
512 | 481 | ||
513 | if (copy_to_user(arg, &args, sizeof(args))) | ||
514 | return -EFAULT; | ||
515 | |||
516 | return 0; | 482 | return 0; |
517 | } | 483 | } |
518 | 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 | |||
519 | 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) |
520 | { | 515 | { |
521 | struct kfd_process *process; | 516 | struct kfd_process *process; |
522 | 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; | ||
523 | 524 | ||
524 | dev_dbg(kfd_device, | 525 | if (nr >= AMDKFD_CORE_IOCTL_COUNT) |
525 | "ioctl cmd 0x%x (#%d), arg 0x%lx\n", | 526 | goto err_i1; |
526 | cmd, _IOC_NR(cmd), arg); | 527 | |
528 | if ((nr >= AMDKFD_COMMAND_START) && (nr < AMDKFD_COMMAND_END)) { | ||
529 | u32 amdkfd_size; | ||
530 | |||
531 | ioctl = &amdkfd_ioctls[nr]; | ||
532 | |||
533 | amdkfd_size = _IOC_SIZE(ioctl->cmd); | ||
534 | usize = asize = _IOC_SIZE(cmd); | ||
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); | ||
527 | 543 | ||
528 | process = kfd_get_process(current); | 544 | process = kfd_get_process(current); |
529 | if (IS_ERR(process)) | 545 | if (IS_ERR(process)) { |
530 | return PTR_ERR(process); | 546 | dev_dbg(kfd_device, "no process\n"); |
547 | goto err_i1; | ||
548 | } | ||
531 | 549 | ||
532 | switch (cmd) { | 550 | /* Do not trust userspace, use our own definition */ |
533 | case KFD_IOC_GET_VERSION: | 551 | func = ioctl->func; |
534 | err = kfd_ioctl_get_version(filep, process, (void __user *)arg); | 552 | |
535 | break; | 553 | if (unlikely(!func)) { |
536 | case KFD_IOC_CREATE_QUEUE: | 554 | dev_dbg(kfd_device, "no function\n"); |
537 | err = kfd_ioctl_create_queue(filep, process, | 555 | retcode = -EINVAL; |
538 | (void __user *)arg); | 556 | goto err_i1; |
539 | break; | ||
540 | |||
541 | case KFD_IOC_DESTROY_QUEUE: | ||
542 | err = kfd_ioctl_destroy_queue(filep, process, | ||
543 | (void __user *)arg); | ||
544 | break; | ||
545 | |||
546 | case KFD_IOC_SET_MEMORY_POLICY: | ||
547 | err = kfd_ioctl_set_memory_policy(filep, process, | ||
548 | (void __user *)arg); | ||
549 | break; | ||
550 | |||
551 | case KFD_IOC_GET_CLOCK_COUNTERS: | ||
552 | err = kfd_ioctl_get_clock_counters(filep, process, | ||
553 | (void __user *)arg); | ||
554 | break; | ||
555 | |||
556 | case KFD_IOC_GET_PROCESS_APERTURES: | ||
557 | err = kfd_ioctl_get_process_apertures(filep, process, | ||
558 | (void __user *)arg); | ||
559 | break; | ||
560 | |||
561 | case KFD_IOC_UPDATE_QUEUE: | ||
562 | err = kfd_ioctl_update_queue(filep, process, | ||
563 | (void __user *)arg); | ||
564 | break; | ||
565 | |||
566 | default: | ||
567 | dev_err(kfd_device, | ||
568 | "unknown ioctl cmd 0x%x, arg 0x%lx)\n", | ||
569 | cmd, arg); | ||
570 | err = -EINVAL; | ||
571 | break; | ||
572 | } | 557 | } |
573 | 558 | ||
574 | if (err < 0) | 559 | if (cmd & (IOC_IN | IOC_OUT)) { |
575 | dev_err(kfd_device, | 560 | if (asize <= sizeof(stack_kdata)) { |
576 | "ioctl error %ld for ioctl cmd 0x%x (#%d)\n", | 561 | kdata = stack_kdata; |
577 | 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 | } | ||
578 | 572 | ||
579 | 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; | ||
580 | } | 600 | } |
581 | 601 | ||
582 | 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_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_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 b11792d7e70e..cca1708fd811 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c | |||
@@ -921,7 +921,7 @@ static int kfd_build_sysfs_node_tree(void) | |||
921 | uint32_t i = 0; | 921 | uint32_t i = 0; |
922 | 922 | ||
923 | list_for_each_entry(dev, &topology_device_list, list) { | 923 | list_for_each_entry(dev, &topology_device_list, list) { |
924 | ret = kfd_build_sysfs_node_entry(dev, 0); | 924 | ret = kfd_build_sysfs_node_entry(dev, i); |
925 | if (ret < 0) | 925 | if (ret < 0) |
926 | return ret; | 926 | return ret; |
927 | 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 47b551970a14..96a512208fad 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h | |||
@@ -183,7 +183,7 @@ struct kfd2kgd_calls { | |||
183 | 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, |
184 | uint32_t queue_id, uint32_t __user *wptr); | 184 | uint32_t queue_id, uint32_t __user *wptr); |
185 | 185 | ||
186 | 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, |
187 | uint32_t pipe_id, uint32_t queue_id); | 187 | uint32_t pipe_id, uint32_t queue_id); |
188 | 188 | ||
189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, | 189 | int (*hqd_destroy)(struct kgd_dev *kgd, uint32_t reset_type, |
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_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_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c index 63b471205072..68c1f32fb086 100644 --- a/drivers/gpu/drm/drm_vma_manager.c +++ b/drivers/gpu/drm/drm_vma_manager.c | |||
@@ -50,8 +50,7 @@ | |||
50 | * | 50 | * |
51 | * You must not use multiple offset managers on a single address_space. | 51 | * You must not use multiple offset managers on a single address_space. |
52 | * Otherwise, mm-core will be unable to tear down memory mappings as the VM will | 52 | * Otherwise, mm-core will be unable to tear down memory mappings as the VM will |
53 | * no longer be linear. Please use VM_NONLINEAR in that case and implement your | 53 | * no longer be linear. |
54 | * own offset managers. | ||
55 | * | 54 | * |
56 | * This offset manager works on page-based addresses. That is, every argument | 55 | * This offset manager works on page-based addresses. That is, every argument |
57 | * and return code (with the exception of drm_vma_node_offset_addr()) is given | 56 | * and return code (with the exception of drm_vma_node_offset_addr()) is given |
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_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ecee3bcc8772..26b3199e0af2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -830,6 +830,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
830 | 830 | ||
831 | intel_runtime_pm_enable(dev_priv); | 831 | intel_runtime_pm_enable(dev_priv); |
832 | 832 | ||
833 | i915_audio_component_init(dev_priv); | ||
834 | |||
833 | return 0; | 835 | return 0; |
834 | 836 | ||
835 | out_power_well: | 837 | out_power_well: |
@@ -870,6 +872,8 @@ int i915_driver_unload(struct drm_device *dev) | |||
870 | struct drm_i915_private *dev_priv = dev->dev_private; | 872 | struct drm_i915_private *dev_priv = dev->dev_private; |
871 | int ret; | 873 | int ret; |
872 | 874 | ||
875 | i915_audio_component_cleanup(dev_priv); | ||
876 | |||
873 | ret = i915_gem_suspend(dev); | 877 | ret = i915_gem_suspend(dev); |
874 | if (ret) { | 878 | if (ret) { |
875 | DRM_ERROR("failed to idle hardware: %d\n", ret); | 879 | DRM_ERROR("failed to idle hardware: %d\n", ret); |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 574057cd1d09..489b220af02b 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"); |
@@ -940,8 +934,7 @@ static int i915_pm_suspend(struct device *dev) | |||
940 | 934 | ||
941 | static int i915_pm_suspend_late(struct device *dev) | 935 | static int i915_pm_suspend_late(struct device *dev) |
942 | { | 936 | { |
943 | struct pci_dev *pdev = to_pci_dev(dev); | 937 | struct drm_device *drm_dev = dev_to_i915(dev)->dev; |
944 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
945 | 938 | ||
946 | /* | 939 | /* |
947 | * We have a suspedn ordering issue with the snd-hda driver also | 940 | * We have a suspedn ordering issue with the snd-hda driver also |
@@ -960,8 +953,7 @@ static int i915_pm_suspend_late(struct device *dev) | |||
960 | 953 | ||
961 | static int i915_pm_resume_early(struct device *dev) | 954 | static int i915_pm_resume_early(struct device *dev) |
962 | { | 955 | { |
963 | struct pci_dev *pdev = to_pci_dev(dev); | 956 | struct drm_device *drm_dev = dev_to_i915(dev)->dev; |
964 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
965 | 957 | ||
966 | if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) | 958 | if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
967 | return 0; | 959 | return 0; |
@@ -971,8 +963,7 @@ static int i915_pm_resume_early(struct device *dev) | |||
971 | 963 | ||
972 | static int i915_pm_resume(struct device *dev) | 964 | static int i915_pm_resume(struct device *dev) |
973 | { | 965 | { |
974 | struct pci_dev *pdev = to_pci_dev(dev); | 966 | struct drm_device *drm_dev = dev_to_i915(dev)->dev; |
975 | struct drm_device *drm_dev = pci_get_drvdata(pdev); | ||
976 | 967 | ||
977 | if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) | 968 | if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
978 | return 0; | 969 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 70d0f0f06f1a..24cc36a9f3ff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1698,6 +1698,9 @@ struct drm_i915_private { | |||
1698 | struct drm_property *broadcast_rgb_property; | 1698 | struct drm_property *broadcast_rgb_property; |
1699 | struct drm_property *force_audio_property; | 1699 | struct drm_property *force_audio_property; |
1700 | 1700 | ||
1701 | /* hda/i915 audio component */ | ||
1702 | bool audio_component_registered; | ||
1703 | |||
1701 | uint32_t hw_context_size; | 1704 | uint32_t hw_context_size; |
1702 | struct list_head context_list; | 1705 | struct list_head context_list; |
1703 | 1706 | ||
@@ -1756,8 +1759,6 @@ struct drm_i915_private { | |||
1756 | */ | 1759 | */ |
1757 | struct workqueue_struct *dp_wq; | 1760 | struct workqueue_struct *dp_wq; |
1758 | 1761 | ||
1759 | uint32_t bios_vgacntr; | ||
1760 | |||
1761 | /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ | 1762 | /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ |
1762 | struct { | 1763 | struct { |
1763 | int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, | 1764 | int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, |
@@ -1783,6 +1784,11 @@ static inline struct drm_i915_private *to_i915(const struct drm_device *dev) | |||
1783 | return dev->dev_private; | 1784 | return dev->dev_private; |
1784 | } | 1785 | } |
1785 | 1786 | ||
1787 | static inline struct drm_i915_private *dev_to_i915(struct device *dev) | ||
1788 | { | ||
1789 | return to_i915(dev_get_drvdata(dev)); | ||
1790 | } | ||
1791 | |||
1786 | /* Iterate over initialised rings */ | 1792 | /* Iterate over initialised rings */ |
1787 | #define for_each_ring(ring__, dev_priv__, i__) \ | 1793 | #define for_each_ring(ring__, dev_priv__, i__) \ |
1788 | for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ | 1794 | for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \ |
@@ -2161,8 +2167,7 @@ struct drm_i915_cmd_table { | |||
2161 | #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ | 2167 | #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ |
2162 | (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) | 2168 | (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) |
2163 | #define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ | 2169 | #define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ |
2164 | ((INTEL_DEVID(dev) & 0xf) == 0x2 || \ | 2170 | ((INTEL_DEVID(dev) & 0xf) == 0x6 || \ |
2165 | (INTEL_DEVID(dev) & 0xf) == 0x6 || \ | ||
2166 | (INTEL_DEVID(dev) & 0xf) == 0xe)) | 2171 | (INTEL_DEVID(dev) & 0xf) == 0xe)) |
2167 | #define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ | 2172 | #define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ |
2168 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) | 2173 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 52adcb680be3..5f614828d365 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1048,6 +1048,7 @@ int | |||
1048 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | 1048 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, |
1049 | struct drm_file *file) | 1049 | struct drm_file *file) |
1050 | { | 1050 | { |
1051 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
1051 | struct drm_i915_gem_pwrite *args = data; | 1052 | struct drm_i915_gem_pwrite *args = data; |
1052 | struct drm_i915_gem_object *obj; | 1053 | struct drm_i915_gem_object *obj; |
1053 | int ret; | 1054 | int ret; |
@@ -1067,9 +1068,11 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
1067 | return -EFAULT; | 1068 | return -EFAULT; |
1068 | } | 1069 | } |
1069 | 1070 | ||
1071 | intel_runtime_pm_get(dev_priv); | ||
1072 | |||
1070 | ret = i915_mutex_lock_interruptible(dev); | 1073 | ret = i915_mutex_lock_interruptible(dev); |
1071 | if (ret) | 1074 | if (ret) |
1072 | return ret; | 1075 | goto put_rpm; |
1073 | 1076 | ||
1074 | 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)); |
1075 | if (&obj->base == NULL) { | 1078 | if (&obj->base == NULL) { |
@@ -1121,6 +1124,9 @@ out: | |||
1121 | drm_gem_object_unreference(&obj->base); | 1124 | drm_gem_object_unreference(&obj->base); |
1122 | unlock: | 1125 | unlock: |
1123 | mutex_unlock(&dev->struct_mutex); | 1126 | mutex_unlock(&dev->struct_mutex); |
1127 | put_rpm: | ||
1128 | intel_runtime_pm_put(dev_priv); | ||
1129 | |||
1124 | return ret; | 1130 | return ret; |
1125 | } | 1131 | } |
1126 | 1132 | ||
@@ -3142,6 +3148,13 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg, | |||
3142 | u32 size = i915_gem_obj_ggtt_size(obj); | 3148 | u32 size = i915_gem_obj_ggtt_size(obj); |
3143 | uint64_t val; | 3149 | uint64_t val; |
3144 | 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 | |||
3145 | val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & | 3158 | val = (uint64_t)((i915_gem_obj_ggtt_offset(obj) + size - 4096) & |
3146 | 0xfffff000) << 32; | 3159 | 0xfffff000) << 32; |
3147 | val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; | 3160 | val |= i915_gem_obj_ggtt_offset(obj) & 0xfffff000; |
@@ -4878,25 +4891,18 @@ i915_gem_init_hw(struct drm_device *dev) | |||
4878 | for (i = 0; i < NUM_L3_SLICES(dev); i++) | 4891 | for (i = 0; i < NUM_L3_SLICES(dev); i++) |
4879 | i915_gem_l3_remap(&dev_priv->ring[RCS], i); | 4892 | i915_gem_l3_remap(&dev_priv->ring[RCS], i); |
4880 | 4893 | ||
4881 | /* | 4894 | ret = i915_ppgtt_init_hw(dev); |
4882 | * XXX: Contexts should only be initialized once. Doing a switch to the | ||
4883 | * default context switch however is something we'd like to do after | ||
4884 | * reset or thaw (the latter may not actually be necessary for HW, but | ||
4885 | * goes with our code better). Context switching requires rings (for | ||
4886 | * the do_switch), but before enabling PPGTT. So don't move this. | ||
4887 | */ | ||
4888 | ret = i915_gem_context_enable(dev_priv); | ||
4889 | if (ret && ret != -EIO) { | 4895 | if (ret && ret != -EIO) { |
4890 | DRM_ERROR("Context enable failed %d\n", ret); | 4896 | DRM_ERROR("PPGTT enable failed %d\n", ret); |
4891 | i915_gem_cleanup_ringbuffer(dev); | 4897 | i915_gem_cleanup_ringbuffer(dev); |
4892 | |||
4893 | return ret; | ||
4894 | } | 4898 | } |
4895 | 4899 | ||
4896 | ret = i915_ppgtt_init_hw(dev); | 4900 | ret = i915_gem_context_enable(dev_priv); |
4897 | if (ret && ret != -EIO) { | 4901 | if (ret && ret != -EIO) { |
4898 | DRM_ERROR("PPGTT enable failed %d\n", ret); | 4902 | DRM_ERROR("Context enable failed %d\n", ret); |
4899 | i915_gem_cleanup_ringbuffer(dev); | 4903 | i915_gem_cleanup_ringbuffer(dev); |
4904 | |||
4905 | return ret; | ||
4900 | } | 4906 | } |
4901 | 4907 | ||
4902 | return ret; | 4908 | return ret; |
@@ -5149,7 +5155,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task) | |||
5149 | if (!mutex_is_locked(mutex)) | 5155 | if (!mutex_is_locked(mutex)) |
5150 | return false; | 5156 | return false; |
5151 | 5157 | ||
5152 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES) | 5158 | #if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) |
5153 | return mutex->owner == task; | 5159 | return mutex->owner == task; |
5154 | #else | 5160 | #else |
5155 | /* 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_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 996c2931c499..b051a238baf9 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -292,6 +292,23 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
292 | spin_unlock_irq(&dev_priv->irq_lock); | 292 | spin_unlock_irq(&dev_priv->irq_lock); |
293 | } | 293 | } |
294 | 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 | |||
295 | void gen6_disable_rps_interrupts(struct drm_device *dev) | 312 | void gen6_disable_rps_interrupts(struct drm_device *dev) |
296 | { | 313 | { |
297 | struct drm_i915_private *dev_priv = dev->dev_private; | 314 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -304,8 +321,7 @@ void gen6_disable_rps_interrupts(struct drm_device *dev) | |||
304 | 321 | ||
305 | spin_lock_irq(&dev_priv->irq_lock); | 322 | spin_lock_irq(&dev_priv->irq_lock); |
306 | 323 | ||
307 | I915_WRITE(GEN6_PMINTRMSK, INTEL_INFO(dev_priv)->gen >= 8 ? | 324 | I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); |
308 | ~GEN8_PMINTR_REDIRECT_TO_NON_DISP : ~0); | ||
309 | 325 | ||
310 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 326 | __gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
311 | 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)) & |
@@ -3725,8 +3741,6 @@ static bool i8xx_handle_vblank(struct drm_device *dev, | |||
3725 | if ((iir & flip_pending) == 0) | 3741 | if ((iir & flip_pending) == 0) |
3726 | goto check_page_flip; | 3742 | goto check_page_flip; |
3727 | 3743 | ||
3728 | intel_prepare_page_flip(dev, plane); | ||
3729 | |||
3730 | /* 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' |
3731 | * 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 |
3732 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence | 3746 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence |
@@ -3736,6 +3750,7 @@ static bool i8xx_handle_vblank(struct drm_device *dev, | |||
3736 | if (I915_READ16(ISR) & flip_pending) | 3750 | if (I915_READ16(ISR) & flip_pending) |
3737 | goto check_page_flip; | 3751 | goto check_page_flip; |
3738 | 3752 | ||
3753 | intel_prepare_page_flip(dev, plane); | ||
3739 | intel_finish_page_flip(dev, pipe); | 3754 | intel_finish_page_flip(dev, pipe); |
3740 | return true; | 3755 | return true; |
3741 | 3756 | ||
@@ -3907,8 +3922,6 @@ static bool i915_handle_vblank(struct drm_device *dev, | |||
3907 | if ((iir & flip_pending) == 0) | 3922 | if ((iir & flip_pending) == 0) |
3908 | goto check_page_flip; | 3923 | goto check_page_flip; |
3909 | 3924 | ||
3910 | intel_prepare_page_flip(dev, plane); | ||
3911 | |||
3912 | /* 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' |
3913 | * 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 |
3914 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence | 3927 | * asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence |
@@ -3918,6 +3931,7 @@ static bool i915_handle_vblank(struct drm_device *dev, | |||
3918 | if (I915_READ(ISR) & flip_pending) | 3931 | if (I915_READ(ISR) & flip_pending) |
3919 | goto check_page_flip; | 3932 | goto check_page_flip; |
3920 | 3933 | ||
3934 | intel_prepare_page_flip(dev, plane); | ||
3921 | intel_finish_page_flip(dev, pipe); | 3935 | intel_finish_page_flip(dev, pipe); |
3922 | return true; | 3936 | return true; |
3923 | 3937 | ||
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 2c7ed5cb29c0..ee41b882e71a 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c | |||
@@ -22,6 +22,9 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/component.h> | ||
26 | #include <drm/i915_component.h> | ||
27 | #include "intel_drv.h" | ||
25 | 28 | ||
26 | #include <drm/drmP.h> | 29 | #include <drm/drmP.h> |
27 | #include <drm/drm_edid.h> | 30 | #include <drm/drm_edid.h> |
@@ -461,3 +464,110 @@ void intel_init_audio(struct drm_device *dev) | |||
461 | dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; | 464 | dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; |
462 | } | 465 | } |
463 | } | 466 | } |
467 | |||
468 | static void i915_audio_component_get_power(struct device *dev) | ||
469 | { | ||
470 | intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO); | ||
471 | } | ||
472 | |||
473 | static void i915_audio_component_put_power(struct device *dev) | ||
474 | { | ||
475 | intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO); | ||
476 | } | ||
477 | |||
478 | /* Get CDCLK in kHz */ | ||
479 | static int i915_audio_component_get_cdclk_freq(struct device *dev) | ||
480 | { | ||
481 | struct drm_i915_private *dev_priv = dev_to_i915(dev); | ||
482 | int ret; | ||
483 | |||
484 | if (WARN_ON_ONCE(!HAS_DDI(dev_priv))) | ||
485 | return -ENODEV; | ||
486 | |||
487 | intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); | ||
488 | ret = intel_ddi_get_cdclk_freq(dev_priv); | ||
489 | intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); | ||
490 | |||
491 | return ret; | ||
492 | } | ||
493 | |||
494 | static const struct i915_audio_component_ops i915_audio_component_ops = { | ||
495 | .owner = THIS_MODULE, | ||
496 | .get_power = i915_audio_component_get_power, | ||
497 | .put_power = i915_audio_component_put_power, | ||
498 | .get_cdclk_freq = i915_audio_component_get_cdclk_freq, | ||
499 | }; | ||
500 | |||
501 | static int i915_audio_component_bind(struct device *i915_dev, | ||
502 | struct device *hda_dev, void *data) | ||
503 | { | ||
504 | struct i915_audio_component *acomp = data; | ||
505 | |||
506 | if (WARN_ON(acomp->ops || acomp->dev)) | ||
507 | return -EEXIST; | ||
508 | |||
509 | acomp->ops = &i915_audio_component_ops; | ||
510 | acomp->dev = i915_dev; | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | static void i915_audio_component_unbind(struct device *i915_dev, | ||
516 | struct device *hda_dev, void *data) | ||
517 | { | ||
518 | struct i915_audio_component *acomp = data; | ||
519 | |||
520 | acomp->ops = NULL; | ||
521 | acomp->dev = NULL; | ||
522 | } | ||
523 | |||
524 | static const struct component_ops i915_audio_component_bind_ops = { | ||
525 | .bind = i915_audio_component_bind, | ||
526 | .unbind = i915_audio_component_unbind, | ||
527 | }; | ||
528 | |||
529 | /** | ||
530 | * i915_audio_component_init - initialize and register the audio component | ||
531 | * @dev_priv: i915 device instance | ||
532 | * | ||
533 | * This will register with the component framework a child component which | ||
534 | * will bind dynamically to the snd_hda_intel driver's corresponding master | ||
535 | * component when the latter is registered. During binding the child | ||
536 | * initializes an instance of struct i915_audio_component which it receives | ||
537 | * from the master. The master can then start to use the interface defined by | ||
538 | * this struct. Each side can break the binding at any point by deregistering | ||
539 | * its own component after which each side's component unbind callback is | ||
540 | * called. | ||
541 | * | ||
542 | * We ignore any error during registration and continue with reduced | ||
543 | * functionality (i.e. without HDMI audio). | ||
544 | */ | ||
545 | void i915_audio_component_init(struct drm_i915_private *dev_priv) | ||
546 | { | ||
547 | int ret; | ||
548 | |||
549 | ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops); | ||
550 | if (ret < 0) { | ||
551 | DRM_ERROR("failed to add audio component (%d)\n", ret); | ||
552 | /* continue with reduced functionality */ | ||
553 | return; | ||
554 | } | ||
555 | |||
556 | dev_priv->audio_component_registered = true; | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * i915_audio_component_cleanup - deregister the audio component | ||
561 | * @dev_priv: i915 device instance | ||
562 | * | ||
563 | * Deregisters the audio component, breaking any existing binding to the | ||
564 | * corresponding snd_hda_intel driver's master component. | ||
565 | */ | ||
566 | void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) | ||
567 | { | ||
568 | if (!dev_priv->audio_component_registered) | ||
569 | return; | ||
570 | |||
571 | component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops); | ||
572 | dev_priv->audio_component_registered = false; | ||
573 | } | ||
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..29ba962d15e3 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) |
@@ -872,6 +873,8 @@ void intel_fb_obj_flush(struct drm_i915_gem_object *obj, bool retire); | |||
872 | void intel_init_audio(struct drm_device *dev); | 873 | void intel_init_audio(struct drm_device *dev); |
873 | void intel_audio_codec_enable(struct intel_encoder *encoder); | 874 | void intel_audio_codec_enable(struct intel_encoder *encoder); |
874 | void intel_audio_codec_disable(struct intel_encoder *encoder); | 875 | void intel_audio_codec_disable(struct intel_encoder *encoder); |
876 | void i915_audio_component_init(struct drm_i915_private *dev_priv); | ||
877 | void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); | ||
875 | 878 | ||
876 | /* intel_display.c */ | 879 | /* intel_display.c */ |
877 | const char *intel_output_name(int output); | 880 | const char *intel_output_name(int output); |
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 964b28e3c630..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 | ||
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index f5a78d53e297..39ddf40171bf 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
@@ -31,7 +31,6 @@ | |||
31 | 31 | ||
32 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
33 | #include "intel_drv.h" | 33 | #include "intel_drv.h" |
34 | #include <drm/i915_powerwell.h> | ||
35 | 34 | ||
36 | /** | 35 | /** |
37 | * DOC: runtime pm | 36 | * DOC: runtime pm |
@@ -50,8 +49,6 @@ | |||
50 | * present for a given platform. | 49 | * present for a given platform. |
51 | */ | 50 | */ |
52 | 51 | ||
53 | static struct i915_power_domains *hsw_pwr; | ||
54 | |||
55 | #define for_each_power_well(i, power_well, domain_mask, power_domains) \ | 52 | #define for_each_power_well(i, power_well, domain_mask, power_domains) \ |
56 | for (i = 0; \ | 53 | for (i = 0; \ |
57 | i < (power_domains)->power_well_count && \ | 54 | i < (power_domains)->power_well_count && \ |
@@ -615,29 +612,6 @@ static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv, | |||
615 | vlv_power_sequencer_reset(dev_priv); | 612 | vlv_power_sequencer_reset(dev_priv); |
616 | } | 613 | } |
617 | 614 | ||
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 | /** | 615 | /** |
642 | * intel_display_power_get - grab a power domain reference | 616 | * intel_display_power_get - grab a power domain reference |
643 | * @dev_priv: i915 device instance | 617 | * @dev_priv: i915 device instance |
@@ -669,8 +643,6 @@ void intel_display_power_get(struct drm_i915_private *dev_priv, | |||
669 | power_well->ops->enable(dev_priv, power_well); | 643 | power_well->ops->enable(dev_priv, power_well); |
670 | power_well->hw_enabled = true; | 644 | power_well->hw_enabled = true; |
671 | } | 645 | } |
672 | |||
673 | check_power_well_state(dev_priv, power_well); | ||
674 | } | 646 | } |
675 | 647 | ||
676 | power_domains->domain_use_count[domain]++; | 648 | power_domains->domain_use_count[domain]++; |
@@ -709,8 +681,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, | |||
709 | power_well->hw_enabled = false; | 681 | power_well->hw_enabled = false; |
710 | power_well->ops->disable(dev_priv, power_well); | 682 | power_well->ops->disable(dev_priv, power_well); |
711 | } | 683 | } |
712 | |||
713 | check_power_well_state(dev_priv, power_well); | ||
714 | } | 684 | } |
715 | 685 | ||
716 | mutex_unlock(&power_domains->lock); | 686 | mutex_unlock(&power_domains->lock); |
@@ -1098,10 +1068,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) | |||
1098 | */ | 1068 | */ |
1099 | if (IS_HASWELL(dev_priv->dev)) { | 1069 | if (IS_HASWELL(dev_priv->dev)) { |
1100 | set_power_wells(power_domains, hsw_power_wells); | 1070 | set_power_wells(power_domains, hsw_power_wells); |
1101 | hsw_pwr = power_domains; | ||
1102 | } else if (IS_BROADWELL(dev_priv->dev)) { | 1071 | } else if (IS_BROADWELL(dev_priv->dev)) { |
1103 | set_power_wells(power_domains, bdw_power_wells); | 1072 | set_power_wells(power_domains, bdw_power_wells); |
1104 | hsw_pwr = power_domains; | ||
1105 | } else if (IS_CHERRYVIEW(dev_priv->dev)) { | 1073 | } else if (IS_CHERRYVIEW(dev_priv->dev)) { |
1106 | set_power_wells(power_domains, chv_power_wells); | 1074 | set_power_wells(power_domains, chv_power_wells); |
1107 | } else if (IS_VALLEYVIEW(dev_priv->dev)) { | 1075 | } else if (IS_VALLEYVIEW(dev_priv->dev)) { |
@@ -1145,8 +1113,6 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv) | |||
1145 | * the power well is not enabled, so just enable it in case | 1113 | * the power well is not enabled, so just enable it in case |
1146 | * we're going to unload/reload. */ | 1114 | * we're going to unload/reload. */ |
1147 | intel_display_set_init_power(dev_priv, true); | 1115 | intel_display_set_init_power(dev_priv, true); |
1148 | |||
1149 | hsw_pwr = NULL; | ||
1150 | } | 1116 | } |
1151 | 1117 | ||
1152 | static void intel_power_domains_resume(struct drm_i915_private *dev_priv) | 1118 | static void intel_power_domains_resume(struct drm_i915_private *dev_priv) |
@@ -1355,52 +1321,3 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) | |||
1355 | pm_runtime_put_autosuspend(device); | 1321 | pm_runtime_put_autosuspend(device); |
1356 | } | 1322 | } |
1357 | 1323 | ||
1358 | /* Display audio driver power well request */ | ||
1359 | int i915_request_power_well(void) | ||
1360 | { | ||
1361 | struct drm_i915_private *dev_priv; | ||
1362 | |||
1363 | if (!hsw_pwr) | ||
1364 | return -ENODEV; | ||
1365 | |||
1366 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | ||
1367 | power_domains); | ||
1368 | intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); | ||
1369 | return 0; | ||
1370 | } | ||
1371 | EXPORT_SYMBOL_GPL(i915_request_power_well); | ||
1372 | |||
1373 | /* Display audio driver power well release */ | ||
1374 | int i915_release_power_well(void) | ||
1375 | { | ||
1376 | struct drm_i915_private *dev_priv; | ||
1377 | |||
1378 | if (!hsw_pwr) | ||
1379 | return -ENODEV; | ||
1380 | |||
1381 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | ||
1382 | power_domains); | ||
1383 | intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); | ||
1384 | return 0; | ||
1385 | } | ||
1386 | EXPORT_SYMBOL_GPL(i915_release_power_well); | ||
1387 | |||
1388 | /* | ||
1389 | * Private interface for the audio driver to get CDCLK in kHz. | ||
1390 | * | ||
1391 | * Caller must request power well using i915_request_power_well() prior to | ||
1392 | * making the call. | ||
1393 | */ | ||
1394 | int i915_get_cdclk_freq(void) | ||
1395 | { | ||
1396 | struct drm_i915_private *dev_priv; | ||
1397 | |||
1398 | if (!hsw_pwr) | ||
1399 | return -ENODEV; | ||
1400 | |||
1401 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | ||
1402 | power_domains); | ||
1403 | |||
1404 | return intel_ddi_get_cdclk_freq(dev_priv); | ||
1405 | } | ||
1406 | EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); | ||
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_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 42c34babc2e5..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 | } |
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 a46f73737994..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 | ||
@@ -576,7 +578,7 @@ error_unreserve: | |||
576 | error_free: | 578 | error_free: |
577 | drm_free_large(vm_bos); | 579 | drm_free_large(vm_bos); |
578 | 580 | ||
579 | if (r) | 581 | if (r && r != -ERESTARTSYS) |
580 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); | 582 | DRM_ERROR("Couldn't update BO_VA (%d)\n", r); |
581 | } | 583 | } |
582 | 584 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c index 242fd8b1b221..bef9a0953284 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ b/drivers/gpu/drm/radeon/radeon_kfd.c | |||
@@ -72,7 +72,7 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, | |||
72 | 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, |
73 | uint32_t queue_id, uint32_t __user *wptr); | 73 | uint32_t queue_id, uint32_t __user *wptr); |
74 | 74 | ||
75 | 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, |
76 | uint32_t pipe_id, uint32_t queue_id); | 76 | uint32_t pipe_id, uint32_t queue_id); |
77 | 77 | ||
78 | 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, |
@@ -92,7 +92,7 @@ static const struct kfd2kgd_calls kfd2kgd = { | |||
92 | .init_memory = kgd_init_memory, | 92 | .init_memory = kgd_init_memory, |
93 | .init_pipeline = kgd_init_pipeline, | 93 | .init_pipeline = kgd_init_pipeline, |
94 | .hqd_load = kgd_hqd_load, | 94 | .hqd_load = kgd_hqd_load, |
95 | .hqd_is_occupies = kgd_hqd_is_occupies, | 95 | .hqd_is_occupied = kgd_hqd_is_occupied, |
96 | .hqd_destroy = kgd_hqd_destroy, | 96 | .hqd_destroy = kgd_hqd_destroy, |
97 | .get_fw_version = get_fw_version | 97 | .get_fw_version = get_fw_version |
98 | }; | 98 | }; |
@@ -101,6 +101,7 @@ static const struct kgd2kfd_calls *kgd2kfd; | |||
101 | 101 | ||
102 | bool radeon_kfd_init(void) | 102 | bool radeon_kfd_init(void) |
103 | { | 103 | { |
104 | #if defined(CONFIG_HSA_AMD_MODULE) | ||
104 | bool (*kgd2kfd_init_p)(unsigned, const struct kfd2kgd_calls*, | 105 | bool (*kgd2kfd_init_p)(unsigned, const struct kfd2kgd_calls*, |
105 | const struct kgd2kfd_calls**); | 106 | const struct kgd2kfd_calls**); |
106 | 107 | ||
@@ -117,6 +118,17 @@ bool radeon_kfd_init(void) | |||
117 | } | 118 | } |
118 | 119 | ||
119 | 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 | ||
120 | } | 132 | } |
121 | 133 | ||
122 | void radeon_kfd_fini(void) | 134 | void radeon_kfd_fini(void) |
@@ -378,6 +390,10 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, | |||
378 | cpu_relax(); | 390 | cpu_relax(); |
379 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); | 391 | write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); |
380 | 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 | |||
381 | return 0; | 397 | return 0; |
382 | } | 398 | } |
383 | 399 | ||
@@ -420,7 +436,7 @@ static int kgd_init_memory(struct kgd_dev *kgd) | |||
420 | 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, |
421 | uint32_t hpd_size, uint64_t hpd_gpu_addr) | 437 | uint32_t hpd_size, uint64_t hpd_gpu_addr) |
422 | { | 438 | { |
423 | uint32_t mec = (++pipe_id / CIK_PIPE_PER_MEC) + 1; | 439 | uint32_t mec = (pipe_id / CIK_PIPE_PER_MEC) + 1; |
424 | uint32_t pipe = (pipe_id % CIK_PIPE_PER_MEC); | 440 | uint32_t pipe = (pipe_id % CIK_PIPE_PER_MEC); |
425 | 441 | ||
426 | lock_srbm(kgd, mec, pipe, 0, 0); | 442 | lock_srbm(kgd, mec, pipe, 0, 0); |
@@ -517,7 +533,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, | |||
517 | return 0; | 533 | return 0; |
518 | } | 534 | } |
519 | 535 | ||
520 | 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, |
521 | uint32_t pipe_id, uint32_t queue_id) | 537 | uint32_t pipe_id, uint32_t queue_id) |
522 | { | 538 | { |
523 | uint32_t act; | 539 | uint32_t act; |
@@ -556,6 +572,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, uint32_t reset_type, | |||
556 | if (timeout == 0) { | 572 | if (timeout == 0) { |
557 | pr_err("kfd: cp queue preemption time out (%dms)\n", | 573 | pr_err("kfd: cp queue preemption time out (%dms)\n", |
558 | temp); | 574 | temp); |
575 | release_queue(kgd); | ||
559 | return -ETIME; | 576 | return -ETIME; |
560 | } | 577 | } |
561 | msleep(20); | 578 | msleep(20); |
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_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/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) ? |