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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux

Pull more drm fixes from Dave Airlie:
"Some more fixes trickled in:

A bunch of VC4 ones since it's a pretty new driver not much chance of
regressions, and it fixes GPU resets.

Also one atomic fix, one set of fixes for a common bug in TTM cleanup,
and one i915 hotplug fix"

* 'drm-fixes' of git://people.freedesktop.org/~airlied/linux:
drm/nouveau: use post-decrement in error handling
drm/atomic: Allow for holes in connector state, v2.
drm/i915: Fix hpd live status bits for g4x
drm/vc4: Use runtime PM to power cycle the device when the GPU hangs.
drm/vc4: Enable runtime PM.
drm/vc4: Fix spurious GPU resets due to BO reuse.
drm/vc4: Drop error message on seqno wait timeouts.
drm/vc4: Fix -ERESTARTSYS error return from BO waits.
drm/vc4: Return an ERR_PTR from BO creation instead of NULL.
drm/vc4: Fix the clear color for the first tile rendered.
drm/vc4: Validate that WAIT_BO padding is cleared.
drm/radeon: use post-decrement in error handling
drm/amdgpu: use post-decrement in error handling

+184 -124
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 712 712 0, PAGE_SIZE, 713 713 PCI_DMA_BIDIRECTIONAL); 714 714 if (pci_dma_mapping_error(adev->pdev, gtt->ttm.dma_address[i])) { 715 - while (--i) { 715 + while (i--) { 716 716 pci_unmap_page(adev->pdev, gtt->ttm.dma_address[i], 717 717 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 718 718 gtt->ttm.dma_address[i] = 0;
+20 -24
drivers/gpu/drm/drm_atomic.c
··· 65 65 */ 66 66 state->allow_modeset = true; 67 67 68 - state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector); 69 - 70 68 state->crtcs = kcalloc(dev->mode_config.num_crtc, 71 69 sizeof(*state->crtcs), GFP_KERNEL); 72 70 if (!state->crtcs) ··· 80 82 state->plane_states = kcalloc(dev->mode_config.num_total_plane, 81 83 sizeof(*state->plane_states), GFP_KERNEL); 82 84 if (!state->plane_states) 83 - goto fail; 84 - state->connectors = kcalloc(state->num_connector, 85 - sizeof(*state->connectors), 86 - GFP_KERNEL); 87 - if (!state->connectors) 88 - goto fail; 89 - state->connector_states = kcalloc(state->num_connector, 90 - sizeof(*state->connector_states), 91 - GFP_KERNEL); 92 - if (!state->connector_states) 93 85 goto fail; 94 86 95 87 state->dev = dev; ··· 811 823 812 824 index = drm_connector_index(connector); 813 825 814 - /* 815 - * Construction of atomic state updates can race with a connector 816 - * hot-add which might overflow. In this case flip the table and just 817 - * restart the entire ioctl - no one is fast enough to livelock a cpu 818 - * with physical hotplug events anyway. 819 - * 820 - * Note that we only grab the indexes once we have the right lock to 821 - * prevent hotplug/unplugging of connectors. So removal is no problem, 822 - * at most the array is a bit too large. 823 - */ 824 826 if (index >= state->num_connector) { 825 - DRM_DEBUG_ATOMIC("Hot-added connector would overflow state array, restarting\n"); 826 - return ERR_PTR(-EAGAIN); 827 + struct drm_connector **c; 828 + struct drm_connector_state **cs; 829 + int alloc = max(index + 1, config->num_connector); 830 + 831 + c = krealloc(state->connectors, alloc * sizeof(*state->connectors), GFP_KERNEL); 832 + if (!c) 833 + return ERR_PTR(-ENOMEM); 834 + 835 + state->connectors = c; 836 + memset(&state->connectors[state->num_connector], 0, 837 + sizeof(*state->connectors) * (alloc - state->num_connector)); 838 + 839 + cs = krealloc(state->connector_states, alloc * sizeof(*state->connector_states), GFP_KERNEL); 840 + if (!cs) 841 + return ERR_PTR(-ENOMEM); 842 + 843 + state->connector_states = cs; 844 + memset(&state->connector_states[state->num_connector], 0, 845 + sizeof(*state->connector_states) * (alloc - state->num_connector)); 846 + state->num_connector = alloc; 827 847 } 828 848 829 849 if (state->connector_states[index])
+1 -1
drivers/gpu/drm/drm_atomic_helper.c
··· 1493 1493 { 1494 1494 int i; 1495 1495 1496 - for (i = 0; i < dev->mode_config.num_connector; i++) { 1496 + for (i = 0; i < state->num_connector; i++) { 1497 1497 struct drm_connector *connector = state->connectors[i]; 1498 1498 1499 1499 if (!connector)
+20 -29
drivers/gpu/drm/drm_crtc.c
··· 918 918 connector->base.properties = &connector->properties; 919 919 connector->dev = dev; 920 920 connector->funcs = funcs; 921 + 922 + connector->connector_id = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL); 923 + if (connector->connector_id < 0) { 924 + ret = connector->connector_id; 925 + goto out_put; 926 + } 927 + 921 928 connector->connector_type = connector_type; 922 929 connector->connector_type_id = 923 930 ida_simple_get(connector_ida, 1, 0, GFP_KERNEL); 924 931 if (connector->connector_type_id < 0) { 925 932 ret = connector->connector_type_id; 926 - goto out_put; 933 + goto out_put_id; 927 934 } 928 935 connector->name = 929 936 kasprintf(GFP_KERNEL, "%s-%d", ··· 938 931 connector->connector_type_id); 939 932 if (!connector->name) { 940 933 ret = -ENOMEM; 941 - goto out_put; 934 + goto out_put_type_id; 942 935 } 943 936 944 937 INIT_LIST_HEAD(&connector->probed_modes); ··· 966 959 } 967 960 968 961 connector->debugfs_entry = NULL; 969 - 962 + out_put_type_id: 963 + if (ret) 964 + ida_remove(connector_ida, connector->connector_type_id); 965 + out_put_id: 966 + if (ret) 967 + ida_remove(&config->connector_ida, connector->connector_id); 970 968 out_put: 971 969 if (ret) 972 970 drm_mode_object_put(dev, &connector->base); ··· 1008 996 ida_remove(&drm_connector_enum_list[connector->connector_type].ida, 1009 997 connector->connector_type_id); 1010 998 999 + ida_remove(&dev->mode_config.connector_ida, 1000 + connector->connector_id); 1001 + 1011 1002 kfree(connector->display_info.bus_formats); 1012 1003 drm_mode_object_put(dev, &connector->base); 1013 1004 kfree(connector->name); ··· 1026 1011 memset(connector, 0, sizeof(*connector)); 1027 1012 } 1028 1013 EXPORT_SYMBOL(drm_connector_cleanup); 1029 - 1030 - /** 1031 - * drm_connector_index - find the index of a registered connector 1032 - * @connector: connector to find index for 1033 - * 1034 - * Given a registered connector, return the index of that connector within a DRM 1035 - * device's list of connectors. 1036 - */ 1037 - unsigned int drm_connector_index(struct drm_connector *connector) 1038 - { 1039 - unsigned int index = 0; 1040 - struct drm_connector *tmp; 1041 - struct drm_mode_config *config = &connector->dev->mode_config; 1042 - 1043 - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); 1044 - 1045 - drm_for_each_connector(tmp, connector->dev) { 1046 - if (tmp == connector) 1047 - return index; 1048 - 1049 - index++; 1050 - } 1051 - 1052 - BUG(); 1053 - } 1054 - EXPORT_SYMBOL(drm_connector_index); 1055 1014 1056 1015 /** 1057 1016 * drm_connector_register - register a connector ··· 5778 5789 INIT_LIST_HEAD(&dev->mode_config.plane_list); 5779 5790 idr_init(&dev->mode_config.crtc_idr); 5780 5791 idr_init(&dev->mode_config.tile_idr); 5792 + ida_init(&dev->mode_config.connector_ida); 5781 5793 5782 5794 drm_modeset_lock_all(dev); 5783 5795 drm_mode_create_standard_properties(dev); ··· 5859 5869 crtc->funcs->destroy(crtc); 5860 5870 } 5861 5871 5872 + ida_destroy(&dev->mode_config.connector_ida); 5862 5873 idr_destroy(&dev->mode_config.tile_idr); 5863 5874 idr_destroy(&dev->mode_config.crtc_idr); 5864 5875 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
+8 -7
drivers/gpu/drm/i915/i915_reg.h
··· 3287 3287 3288 3288 #define PORT_HOTPLUG_STAT _MMIO(dev_priv->info.display_mmio_offset + 0x61114) 3289 3289 /* 3290 - * HDMI/DP bits are gen4+ 3290 + * HDMI/DP bits are g4x+ 3291 3291 * 3292 3292 * WARNING: Bspec for hpd status bits on gen4 seems to be completely confused. 3293 3293 * Please check the detailed lore in the commit message for for experimental 3294 3294 * evidence. 3295 3295 */ 3296 - #define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 29) 3296 + /* Bspec says GM45 should match G4X/VLV/CHV, but reality disagrees */ 3297 + #define PORTD_HOTPLUG_LIVE_STATUS_GM45 (1 << 29) 3298 + #define PORTC_HOTPLUG_LIVE_STATUS_GM45 (1 << 28) 3299 + #define PORTB_HOTPLUG_LIVE_STATUS_GM45 (1 << 27) 3300 + /* G4X/VLV/CHV DP/HDMI bits again match Bspec */ 3301 + #define PORTD_HOTPLUG_LIVE_STATUS_G4X (1 << 27) 3297 3302 #define PORTC_HOTPLUG_LIVE_STATUS_G4X (1 << 28) 3298 - #define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 27) 3299 - /* VLV DP/HDMI bits again match Bspec */ 3300 - #define PORTD_HOTPLUG_LIVE_STATUS_VLV (1 << 27) 3301 - #define PORTC_HOTPLUG_LIVE_STATUS_VLV (1 << 28) 3302 - #define PORTB_HOTPLUG_LIVE_STATUS_VLV (1 << 29) 3303 + #define PORTB_HOTPLUG_LIVE_STATUS_G4X (1 << 29) 3303 3304 #define PORTD_HOTPLUG_INT_STATUS (3 << 21) 3304 3305 #define PORTD_HOTPLUG_INT_LONG_PULSE (2 << 21) 3305 3306 #define PORTD_HOTPLUG_INT_SHORT_PULSE (1 << 21)
+7 -7
drivers/gpu/drm/i915/intel_dp.c
··· 4493 4493 return I915_READ(PORT_HOTPLUG_STAT) & bit; 4494 4494 } 4495 4495 4496 - static bool vlv_digital_port_connected(struct drm_i915_private *dev_priv, 4497 - struct intel_digital_port *port) 4496 + static bool gm45_digital_port_connected(struct drm_i915_private *dev_priv, 4497 + struct intel_digital_port *port) 4498 4498 { 4499 4499 u32 bit; 4500 4500 4501 4501 switch (port->port) { 4502 4502 case PORT_B: 4503 - bit = PORTB_HOTPLUG_LIVE_STATUS_VLV; 4503 + bit = PORTB_HOTPLUG_LIVE_STATUS_GM45; 4504 4504 break; 4505 4505 case PORT_C: 4506 - bit = PORTC_HOTPLUG_LIVE_STATUS_VLV; 4506 + bit = PORTC_HOTPLUG_LIVE_STATUS_GM45; 4507 4507 break; 4508 4508 case PORT_D: 4509 - bit = PORTD_HOTPLUG_LIVE_STATUS_VLV; 4509 + bit = PORTD_HOTPLUG_LIVE_STATUS_GM45; 4510 4510 break; 4511 4511 default: 4512 4512 MISSING_CASE(port->port); ··· 4558 4558 return cpt_digital_port_connected(dev_priv, port); 4559 4559 else if (IS_BROXTON(dev_priv)) 4560 4560 return bxt_digital_port_connected(dev_priv, port); 4561 - else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) 4562 - return vlv_digital_port_connected(dev_priv, port); 4561 + else if (IS_GM45(dev_priv)) 4562 + return gm45_digital_port_connected(dev_priv, port); 4563 4563 else 4564 4564 return g4x_digital_port_connected(dev_priv, port); 4565 4565 }
+1 -1
drivers/gpu/drm/nouveau/nouveau_bo.c
··· 1520 1520 DMA_BIDIRECTIONAL); 1521 1521 1522 1522 if (dma_mapping_error(pdev, addr)) { 1523 - while (--i) { 1523 + while (i--) { 1524 1524 dma_unmap_page(pdev, ttm_dma->dma_address[i], 1525 1525 PAGE_SIZE, DMA_BIDIRECTIONAL); 1526 1526 ttm_dma->dma_address[i] = 0;
+1 -1
drivers/gpu/drm/radeon/radeon_ttm.c
··· 758 758 0, PAGE_SIZE, 759 759 PCI_DMA_BIDIRECTIONAL); 760 760 if (pci_dma_mapping_error(rdev->pdev, gtt->ttm.dma_address[i])) { 761 - while (--i) { 761 + while (i--) { 762 762 pci_unmap_page(rdev->pdev, gtt->ttm.dma_address[i], 763 763 PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 764 764 gtt->ttm.dma_address[i] = 0;
+8 -8
drivers/gpu/drm/vc4/vc4_bo.c
··· 215 215 struct drm_gem_cma_object *cma_obj; 216 216 217 217 if (size == 0) 218 - return NULL; 218 + return ERR_PTR(-EINVAL); 219 219 220 220 /* First, try to get a vc4_bo from the kernel BO cache. */ 221 221 if (from_cache) { ··· 237 237 if (IS_ERR(cma_obj)) { 238 238 DRM_ERROR("Failed to allocate from CMA:\n"); 239 239 vc4_bo_stats_dump(vc4); 240 - return NULL; 240 + return ERR_PTR(-ENOMEM); 241 241 } 242 242 } 243 243 ··· 259 259 args->size = args->pitch * args->height; 260 260 261 261 bo = vc4_bo_create(dev, args->size, false); 262 - if (!bo) 263 - return -ENOMEM; 262 + if (IS_ERR(bo)) 263 + return PTR_ERR(bo); 264 264 265 265 ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); 266 266 drm_gem_object_unreference_unlocked(&bo->base.base); ··· 443 443 * get zeroed, and that might leak data between users. 444 444 */ 445 445 bo = vc4_bo_create(dev, args->size, false); 446 - if (!bo) 447 - return -ENOMEM; 446 + if (IS_ERR(bo)) 447 + return PTR_ERR(bo); 448 448 449 449 ret = drm_gem_handle_create(file_priv, &bo->base.base, &args->handle); 450 450 drm_gem_object_unreference_unlocked(&bo->base.base); ··· 496 496 } 497 497 498 498 bo = vc4_bo_create(dev, args->size, true); 499 - if (!bo) 500 - return -ENOMEM; 499 + if (IS_ERR(bo)) 500 + return PTR_ERR(bo); 501 501 502 502 ret = copy_from_user(bo->base.vaddr, 503 503 (void __user *)(uintptr_t)args->data,
+11 -2
drivers/gpu/drm/vc4/vc4_drv.h
··· 91 91 struct vc4_bo *overflow_mem; 92 92 struct work_struct overflow_mem_work; 93 93 94 + int power_refcount; 95 + 96 + /* Mutex controlling the power refcount. */ 97 + struct mutex power_lock; 98 + 94 99 struct { 95 - uint32_t last_ct0ca, last_ct1ca; 96 100 struct timer_list timer; 97 101 struct work_struct reset_work; 98 102 } hangcheck; ··· 146 142 }; 147 143 148 144 struct vc4_v3d { 145 + struct vc4_dev *vc4; 149 146 struct platform_device *pdev; 150 147 void __iomem *regs; 151 148 }; ··· 196 191 struct vc4_exec_info { 197 192 /* Sequence number for this bin/render job. */ 198 193 uint64_t seqno; 194 + 195 + /* Last current addresses the hardware was processing when the 196 + * hangcheck timer checked on us. 197 + */ 198 + uint32_t last_ct0ca, last_ct1ca; 199 199 200 200 /* Kernel-space copy of the ioctl arguments */ 201 201 struct drm_vc4_submit_cl *args; ··· 444 434 extern struct platform_driver vc4_v3d_driver; 445 435 int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused); 446 436 int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused); 447 - int vc4_v3d_set_power(struct vc4_dev *vc4, bool on); 448 437 449 438 /* vc4_validate.c */ 450 439 int
+49 -16
drivers/gpu/drm/vc4/vc4_gem.c
··· 23 23 24 24 #include <linux/module.h> 25 25 #include <linux/platform_device.h> 26 + #include <linux/pm_runtime.h> 26 27 #include <linux/device.h> 27 28 #include <linux/io.h> 28 29 ··· 229 228 struct vc4_dev *vc4 = to_vc4_dev(dev); 230 229 231 230 DRM_INFO("Resetting GPU.\n"); 232 - vc4_v3d_set_power(vc4, false); 233 - vc4_v3d_set_power(vc4, true); 231 + 232 + mutex_lock(&vc4->power_lock); 233 + if (vc4->power_refcount) { 234 + /* Power the device off and back on the by dropping the 235 + * reference on runtime PM. 236 + */ 237 + pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev); 238 + pm_runtime_get_sync(&vc4->v3d->pdev->dev); 239 + } 240 + mutex_unlock(&vc4->power_lock); 234 241 235 242 vc4_irq_reset(dev); 236 243 ··· 266 257 struct drm_device *dev = (struct drm_device *)data; 267 258 struct vc4_dev *vc4 = to_vc4_dev(dev); 268 259 uint32_t ct0ca, ct1ca; 260 + unsigned long irqflags; 261 + struct vc4_exec_info *exec; 262 + 263 + spin_lock_irqsave(&vc4->job_lock, irqflags); 264 + exec = vc4_first_job(vc4); 269 265 270 266 /* If idle, we can stop watching for hangs. */ 271 - if (list_empty(&vc4->job_list)) 267 + if (!exec) { 268 + spin_unlock_irqrestore(&vc4->job_lock, irqflags); 272 269 return; 270 + } 273 271 274 272 ct0ca = V3D_READ(V3D_CTNCA(0)); 275 273 ct1ca = V3D_READ(V3D_CTNCA(1)); ··· 284 268 /* If we've made any progress in execution, rearm the timer 285 269 * and wait. 286 270 */ 287 - if (ct0ca != vc4->hangcheck.last_ct0ca || 288 - ct1ca != vc4->hangcheck.last_ct1ca) { 289 - vc4->hangcheck.last_ct0ca = ct0ca; 290 - vc4->hangcheck.last_ct1ca = ct1ca; 271 + if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) { 272 + exec->last_ct0ca = ct0ca; 273 + exec->last_ct1ca = ct1ca; 274 + spin_unlock_irqrestore(&vc4->job_lock, irqflags); 291 275 vc4_queue_hangcheck(dev); 292 276 return; 293 277 } 278 + 279 + spin_unlock_irqrestore(&vc4->job_lock, irqflags); 294 280 295 281 /* We've gone too long with no progress, reset. This has to 296 282 * be done from a work struct, since resetting can sleep and ··· 358 340 finish_wait(&vc4->job_wait_queue, &wait); 359 341 trace_vc4_wait_for_seqno_end(dev, seqno); 360 342 361 - if (ret && ret != -ERESTARTSYS) { 362 - DRM_ERROR("timeout waiting for render thread idle\n"); 363 - return ret; 364 - } 365 - 366 - return 0; 343 + return ret; 367 344 } 368 345 369 346 static void ··· 591 578 } 592 579 593 580 bo = vc4_bo_create(dev, exec_size, true); 594 - if (!bo) { 581 + if (IS_ERR(bo)) { 595 582 DRM_ERROR("Couldn't allocate BO for binning\n"); 596 - ret = -ENOMEM; 583 + ret = PTR_ERR(bo); 597 584 goto fail; 598 585 } 599 586 exec->exec_bo = &bo->base; ··· 630 617 static void 631 618 vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec) 632 619 { 620 + struct vc4_dev *vc4 = to_vc4_dev(dev); 633 621 unsigned i; 634 622 635 623 /* Need the struct lock for drm_gem_object_unreference(). */ ··· 648 634 drm_gem_object_unreference(&bo->base.base); 649 635 } 650 636 mutex_unlock(&dev->struct_mutex); 637 + 638 + mutex_lock(&vc4->power_lock); 639 + if (--vc4->power_refcount == 0) 640 + pm_runtime_put(&vc4->v3d->pdev->dev); 641 + mutex_unlock(&vc4->power_lock); 651 642 652 643 kfree(exec); 653 644 } ··· 765 746 struct drm_gem_object *gem_obj; 766 747 struct vc4_bo *bo; 767 748 749 + if (args->pad != 0) 750 + return -EINVAL; 751 + 768 752 gem_obj = drm_gem_object_lookup(dev, file_priv, args->handle); 769 753 if (!gem_obj) { 770 754 DRM_ERROR("Failed to look up GEM BO %d\n", args->handle); ··· 794 772 struct vc4_dev *vc4 = to_vc4_dev(dev); 795 773 struct drm_vc4_submit_cl *args = data; 796 774 struct vc4_exec_info *exec; 797 - int ret; 775 + int ret = 0; 798 776 799 777 if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) { 800 778 DRM_ERROR("Unknown flags: 0x%02x\n", args->flags); ··· 805 783 if (!exec) { 806 784 DRM_ERROR("malloc failure on exec struct\n"); 807 785 return -ENOMEM; 786 + } 787 + 788 + mutex_lock(&vc4->power_lock); 789 + if (vc4->power_refcount++ == 0) 790 + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); 791 + mutex_unlock(&vc4->power_lock); 792 + if (ret < 0) { 793 + kfree(exec); 794 + return ret; 808 795 } 809 796 810 797 exec->args = args; ··· 870 839 (unsigned long)dev); 871 840 872 841 INIT_WORK(&vc4->job_done_work, vc4_job_done_work); 842 + 843 + mutex_init(&vc4->power_lock); 873 844 } 874 845 875 846 void
+1 -1
drivers/gpu/drm/vc4/vc4_irq.c
··· 57 57 struct vc4_bo *bo; 58 58 59 59 bo = vc4_bo_create(dev, 256 * 1024, true); 60 - if (!bo) { 60 + if (IS_ERR(bo)) { 61 61 DRM_ERROR("Couldn't allocate binner overflow mem\n"); 62 62 return; 63 63 }
+11 -11
drivers/gpu/drm/vc4/vc4_render_cl.c
··· 316 316 size += xtiles * ytiles * loop_body_size; 317 317 318 318 setup->rcl = &vc4_bo_create(dev, size, true)->base; 319 - if (!setup->rcl) 320 - return -ENOMEM; 319 + if (IS_ERR(setup->rcl)) 320 + return PTR_ERR(setup->rcl); 321 321 list_add_tail(&to_vc4_bo(&setup->rcl->base)->unref_head, 322 322 &exec->unref_list); 323 - 324 - rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); 325 - rcl_u32(setup, 326 - (setup->color_write ? (setup->color_write->paddr + 327 - args->color_write.offset) : 328 - 0)); 329 - rcl_u16(setup, args->width); 330 - rcl_u16(setup, args->height); 331 - rcl_u16(setup, args->color_write.bits); 332 323 333 324 /* The tile buffer gets cleared when the previous tile is stored. If 334 325 * the clear values changed between frames, then the tile buffer has ··· 339 348 rcl_u16(setup, VC4_LOADSTORE_TILE_BUFFER_NONE); 340 349 rcl_u32(setup, 0); /* no address, since we're in None mode */ 341 350 } 351 + 352 + rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); 353 + rcl_u32(setup, 354 + (setup->color_write ? (setup->color_write->paddr + 355 + args->color_write.offset) : 356 + 0)); 357 + rcl_u16(setup, args->width); 358 + rcl_u16(setup, args->height); 359 + rcl_u16(setup, args->color_write.bits); 342 360 343 361 for (y = min_y_tile; y <= max_y_tile; y++) { 344 362 for (x = min_x_tile; x <= max_x_tile; x++) {
+36 -12
drivers/gpu/drm/vc4/vc4_v3d.c
··· 17 17 */ 18 18 19 19 #include "linux/component.h" 20 + #include "linux/pm_runtime.h" 20 21 #include "vc4_drv.h" 21 22 #include "vc4_regs.h" 22 23 ··· 145 144 } 146 145 #endif /* CONFIG_DEBUG_FS */ 147 146 148 - int 149 - vc4_v3d_set_power(struct vc4_dev *vc4, bool on) 150 - { 151 - /* XXX: This interface is needed for GPU reset, and the way to 152 - * do it is to turn our power domain off and back on. We 153 - * can't just reset from within the driver, because the reset 154 - * bits are in the power domain's register area, and get set 155 - * during the poweron process. 156 - */ 157 - return 0; 158 - } 159 - 160 147 static void vc4_v3d_init_hw(struct drm_device *dev) 161 148 { 162 149 struct vc4_dev *vc4 = to_vc4_dev(dev); ··· 155 166 */ 156 167 V3D_WRITE(V3D_VPMBASE, 0); 157 168 } 169 + 170 + #ifdef CONFIG_PM 171 + static int vc4_v3d_runtime_suspend(struct device *dev) 172 + { 173 + struct vc4_v3d *v3d = dev_get_drvdata(dev); 174 + struct vc4_dev *vc4 = v3d->vc4; 175 + 176 + vc4_irq_uninstall(vc4->dev); 177 + 178 + return 0; 179 + } 180 + 181 + static int vc4_v3d_runtime_resume(struct device *dev) 182 + { 183 + struct vc4_v3d *v3d = dev_get_drvdata(dev); 184 + struct vc4_dev *vc4 = v3d->vc4; 185 + 186 + vc4_v3d_init_hw(vc4->dev); 187 + vc4_irq_postinstall(vc4->dev); 188 + 189 + return 0; 190 + } 191 + #endif 158 192 159 193 static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) 160 194 { ··· 191 179 if (!v3d) 192 180 return -ENOMEM; 193 181 182 + dev_set_drvdata(dev, v3d); 183 + 194 184 v3d->pdev = pdev; 195 185 196 186 v3d->regs = vc4_ioremap_regs(pdev, 0); ··· 200 186 return PTR_ERR(v3d->regs); 201 187 202 188 vc4->v3d = v3d; 189 + v3d->vc4 = vc4; 203 190 204 191 if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) { 205 192 DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n", ··· 222 207 return ret; 223 208 } 224 209 210 + pm_runtime_enable(dev); 211 + 225 212 return 0; 226 213 } 227 214 ··· 232 215 { 233 216 struct drm_device *drm = dev_get_drvdata(master); 234 217 struct vc4_dev *vc4 = to_vc4_dev(drm); 218 + 219 + pm_runtime_disable(dev); 235 220 236 221 drm_irq_uninstall(drm); 237 222 ··· 246 227 247 228 vc4->v3d = NULL; 248 229 } 230 + 231 + static const struct dev_pm_ops vc4_v3d_pm_ops = { 232 + SET_RUNTIME_PM_OPS(vc4_v3d_runtime_suspend, vc4_v3d_runtime_resume, NULL) 233 + }; 249 234 250 235 static const struct component_ops vc4_v3d_ops = { 251 236 .bind = vc4_v3d_bind, ··· 278 255 .driver = { 279 256 .name = "vc4_v3d", 280 257 .of_match_table = vc4_v3d_dt_match, 258 + .pm = &vc4_v3d_pm_ops, 281 259 }, 282 260 };
+2 -2
drivers/gpu/drm/vc4/vc4_validate.c
··· 401 401 tile_bo = vc4_bo_create(dev, exec->tile_alloc_offset + tile_alloc_size, 402 402 true); 403 403 exec->tile_bo = &tile_bo->base; 404 - if (!exec->tile_bo) 405 - return -ENOMEM; 404 + if (IS_ERR(exec->tile_bo)) 405 + return PTR_ERR(exec->tile_bo); 406 406 list_add_tail(&tile_bo->unref_head, &exec->unref_list); 407 407 408 408 /* tile alloc address. */
+7 -1
include/drm/drm_crtc.h
··· 1166 1166 struct drm_mode_object base; 1167 1167 1168 1168 char *name; 1169 + int connector_id; 1169 1170 int connector_type; 1170 1171 int connector_type_id; 1171 1172 bool interlace_allowed; ··· 2048 2047 struct list_head fb_list; 2049 2048 2050 2049 int num_connector; 2050 + struct ida connector_ida; 2051 2051 struct list_head connector_list; 2052 2052 int num_encoder; 2053 2053 struct list_head encoder_list; ··· 2202 2200 void drm_connector_unregister(struct drm_connector *connector); 2203 2201 2204 2202 extern void drm_connector_cleanup(struct drm_connector *connector); 2205 - extern unsigned int drm_connector_index(struct drm_connector *connector); 2203 + static inline unsigned drm_connector_index(struct drm_connector *connector) 2204 + { 2205 + return connector->connector_id; 2206 + } 2207 + 2206 2208 /* helper to unplug all connectors from sysfs for device */ 2207 2209 extern void drm_connector_unplug_all(struct drm_device *dev); 2208 2210