Merge tag 'drm-next-2019-09-27' of git://anongit.freedesktop.org/drm/drm
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 Sep 2019 18:13:35 +0000 (11:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 Sep 2019 18:13:35 +0000 (11:13 -0700)
Pull drm fixes from Dave Airlie:
 "Fixes built up over the past 1.5 weeks or so, it's two weeks of
  amdgpu, some core cleanups and some panfrost fixes. I also finally
  figured out why my desktop was slow to do a bunch of stuff (someone
  gave it an IPv6 address which can't reach anything!).

  core:
   - Some cleanups and fixes in the self-refresh helpers
   - Some cleanups and fixes in the atomic helpers

  amdgpu:
   - Fix a 64 bit divide
   - Prevent a memory leak in a failure case in dc
   - Load proper gfx firmware on navi14 variants
   - Add more navi12 and navi14 PCI ids
   - Misc fixes for renoir
   - Fix bandwidth issues with multiple displays on vega20
   - Support for Dali
   - Fix a possible oops with KFD on hawaii
   - Fix for backlight level after resume on some APUs
   - Other misc fixes

  panfrost:
   - Multiple panfrost fixes for regulator support and page fault
     handling"

* tag 'drm-next-2019-09-27' of git://anongit.freedesktop.org/drm/drm: (34 commits)
  drm/amd/display: prevent memory leak
  drm/amdgpu/gfx10: add support for wks firmware loading
  drm/amdgpu/display: include slab.h in dcn21_resource.c
  drm/amdgpu/display: fix 64 bit divide
  drm/panfrost: Prevent race when handling page fault
  drm/panfrost: Remove NULL checks for regulator
  drm/panfrost: Fix regulator_get_optional() misuse
  drm: Measure Self Refresh Entry/Exit times to avoid thrashing
  drm: Fix kerneldoc and remove unused struct member in self_refresh helper
  drm/atomic: Rename crtc_state->pageflip_flags to async_flip
  drm/atomic: Reject FLIP_ASYNC unconditionally
  drm/atomic: Take the atomic toys away from X
  drm/amdgpu: flag navi12 and 14 as experimental for 5.4
  drm/kms: Duct-tape for mode object lifetime checks
  drm/amdgpu: add navi12 pci id
  drm/amdgpu: add navi14 PCI ID for work station SKU
  drm/amdkfd: Swap trap temporary registers in gfx10 trap handler
  drm/amd/powerplay: implement sysfs for getting dpm clock
  drm/amd/display: Restore backlight brightness after system resume
  drm/amd/display: Implement voltage limitation for dali
  ...

1  2 
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/radeon/radeon_drv.c

index bdf849da32e42e11d28017e59a18e47d9ca41898,5da72ca6f3e1a2bd8105d7d1abdc83ea21b7d7f5..264677ab248a1af2d3a816132b64aca4d4ffd567
@@@ -35,7 -35,6 +35,7 @@@
  #include <linux/pm_runtime.h>
  #include <linux/vga_switcheroo.h>
  #include <drm/drm_probe_helper.h>
 +#include <linux/mmu_notifier.h>
  
  #include "amdgpu.h"
  #include "amdgpu_irq.h"
@@@ -1012,11 -1011,16 +1012,16 @@@ static const struct pci_device_id pciid
        {0x1002, 0x731B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        {0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
        /* Navi14 */
-       {0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
+       {0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x7341, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x7347, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14|AMD_EXP_HW_SUPPORT},
  
        /* Renoir */
        {0x1002, 0x1636, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RENOIR|AMD_IS_APU|AMD_EXP_HW_SUPPORT},
  
+       /* Navi12 */
+       {0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
        {0, 0, 0}
  };
  
@@@ -1470,7 -1474,6 +1475,7 @@@ static void __exit amdgpu_exit(void
        amdgpu_unregister_atpx_handler();
        amdgpu_sync_fini();
        amdgpu_fence_slab_fini();
 +      mmu_notifier_synchronize();
  }
  
  module_init(amdgpu_init);
index 3d61c4fb4dec0f6fc108a7d7c1c057a5ac99aa12,f6d2681f69273584c753a8625fc9638f7766fb93..9e13e466e72c09a52d84ee40ead55cef7b2d26a0
@@@ -874,6 -874,9 +874,9 @@@ static int adv7511_bridge_attach(struc
                                 &adv7511_connector_helper_funcs);
        drm_connector_attach_encoder(&adv->connector, bridge->encoder);
  
+       if (adv->type == ADV7533)
+               ret = adv7533_attach_dsi(adv);
        if (adv->i2c_main->irq)
                regmap_write(adv->regmap, ADV7511_REG_INT_ENABLE(0),
                             ADV7511_INT0_HPD);
@@@ -978,10 -981,10 +981,10 @@@ static int adv7511_init_cec_regmap(stru
  {
        int ret;
  
 -      adv->i2c_cec = i2c_new_secondary_device(adv->i2c_main, "cec",
 +      adv->i2c_cec = i2c_new_ancillary_device(adv->i2c_main, "cec",
                                                ADV7511_CEC_I2C_ADDR_DEFAULT);
 -      if (!adv->i2c_cec)
 -              return -EINVAL;
 +      if (IS_ERR(adv->i2c_cec))
 +              return PTR_ERR(adv->i2c_cec);
        i2c_set_clientdata(adv->i2c_cec, adv);
  
        adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec,
@@@ -1162,20 -1165,20 +1165,20 @@@ static int adv7511_probe(struct i2c_cli
  
        adv7511_packet_disable(adv7511, 0xffff);
  
 -      adv7511->i2c_edid = i2c_new_secondary_device(i2c, "edid",
 +      adv7511->i2c_edid = i2c_new_ancillary_device(i2c, "edid",
                                        ADV7511_EDID_I2C_ADDR_DEFAULT);
 -      if (!adv7511->i2c_edid) {
 -              ret = -EINVAL;
 +      if (IS_ERR(adv7511->i2c_edid)) {
 +              ret = PTR_ERR(adv7511->i2c_edid);
                goto uninit_regulators;
        }
  
        regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR,
                     adv7511->i2c_edid->addr << 1);
  
 -      adv7511->i2c_packet = i2c_new_secondary_device(i2c, "packet",
 +      adv7511->i2c_packet = i2c_new_ancillary_device(i2c, "packet",
                                        ADV7511_PACKET_I2C_ADDR_DEFAULT);
 -      if (!adv7511->i2c_packet) {
 -              ret = -EINVAL;
 +      if (IS_ERR(adv7511->i2c_packet)) {
 +              ret = PTR_ERR(adv7511->i2c_packet);
                goto err_i2c_unregister_edid;
        }
  
        drm_bridge_add(&adv7511->bridge);
  
        adv7511_audio_init(dev, adv7511);
-       if (adv7511->type == ADV7533) {
-               ret = adv7533_attach_dsi(adv7511);
-               if (ret)
-                       goto err_remove_bridge;
-       }
        return 0;
  
- err_remove_bridge:
-       drm_bridge_remove(&adv7511->bridge);
  err_unregister_cec:
        i2c_unregister_device(adv7511->i2c_cec);
        if (adv7511->cec_clk)
index 6010f9ee7c1fd95487c74561d2d52501bae9c8ae,6e7891ded46462f7c71aa45c445ecdfb459e4649..bdd99056847689c2c88fe67d1435e84662cd0eb6
@@@ -311,7 -311,7 +311,7 @@@ void panfrost_mmu_unmap(struct panfrost
                size_t pgsize = get_pgsize(iova, len - unmapped_len);
  
                if (ops->iova_to_phys(ops, iova)) {
 -                      unmapped_page = ops->unmap(ops, iova, pgsize);
 +                      unmapped_page = ops->unmap(ops, iova, pgsize, NULL);
                        WARN_ON(unmapped_page != pgsize);
                }
                iova += pgsize;
  static void mmu_tlb_inv_context_s1(void *cookie)
  {}
  
 -static void mmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
 -                                   size_t granule, bool leaf, void *cookie)
 -{}
 -
  static void mmu_tlb_sync_context(void *cookie)
  {
        //struct panfrost_device *pfdev = cookie;
        // TODO: Wait 1000 GPU cycles for HW_ISSUE_6367/T60X
  }
  
 -static const struct iommu_gather_ops mmu_tlb_ops = {
 +static void mmu_tlb_flush_walk(unsigned long iova, size_t size, size_t granule,
 +                             void *cookie)
 +{
 +      mmu_tlb_sync_context(cookie);
 +}
 +
 +static void mmu_tlb_flush_leaf(unsigned long iova, size_t size, size_t granule,
 +                             void *cookie)
 +{
 +      mmu_tlb_sync_context(cookie);
 +}
 +
 +static const struct iommu_flush_ops mmu_tlb_ops = {
        .tlb_flush_all  = mmu_tlb_inv_context_s1,
 -      .tlb_add_flush  = mmu_tlb_inv_range_nosync,
 -      .tlb_sync       = mmu_tlb_sync_context,
 +      .tlb_flush_walk = mmu_tlb_flush_walk,
 +      .tlb_flush_leaf = mmu_tlb_flush_leaf,
  };
  
  int panfrost_mmu_pgtable_alloc(struct panfrost_file_priv *priv)
@@@ -394,28 -386,40 +394,40 @@@ void panfrost_mmu_pgtable_free(struct p
        free_io_pgtable_ops(mmu->pgtbl_ops);
  }
  
- static struct drm_mm_node *addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr)
+ static struct panfrost_gem_object *
+ addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr)
  {
-       struct drm_mm_node *node = NULL;
+       struct panfrost_gem_object *bo = NULL;
+       struct panfrost_file_priv *priv;
+       struct drm_mm_node *node;
        u64 offset = addr >> PAGE_SHIFT;
        struct panfrost_mmu *mmu;
  
        spin_lock(&pfdev->as_lock);
        list_for_each_entry(mmu, &pfdev->as_lru_list, list) {
-               struct panfrost_file_priv *priv;
-               if (as != mmu->as)
-                       continue;
-               priv = container_of(mmu, struct panfrost_file_priv, mmu);
-               drm_mm_for_each_node(node, &priv->mm) {
-                       if (offset >= node->start && offset < (node->start + node->size))
-                               goto out;
+               if (as == mmu->as)
+                       break;
+       }
+       if (as != mmu->as)
+               goto out;
+       priv = container_of(mmu, struct panfrost_file_priv, mmu);
+       spin_lock(&priv->mm_lock);
+       drm_mm_for_each_node(node, &priv->mm) {
+               if (offset >= node->start &&
+                   offset < (node->start + node->size)) {
+                       bo = drm_mm_node_to_panfrost_bo(node);
+                       drm_gem_object_get(&bo->base.base);
+                       break;
                }
        }
  
+       spin_unlock(&priv->mm_lock);
  out:
        spin_unlock(&pfdev->as_lock);
-       return node;
+       return bo;
  }
  
  #define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE)
  int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr)
  {
        int ret, i;
-       struct drm_mm_node *node;
        struct panfrost_gem_object *bo;
        struct address_space *mapping;
        pgoff_t page_offset;
        struct sg_table *sgt;
        struct page **pages;
  
-       node = addr_to_drm_mm_node(pfdev, as, addr);
-       if (!node)
+       bo = addr_to_drm_mm_node(pfdev, as, addr);
+       if (!bo)
                return -ENOENT;
  
-       bo = drm_mm_node_to_panfrost_bo(node);
        if (!bo->is_heap) {
                dev_WARN(pfdev->dev, "matching BO is not heap type (GPU VA = %llx)",
-                        node->start << PAGE_SHIFT);
-               return -EINVAL;
+                        bo->node.start << PAGE_SHIFT);
+               ret = -EINVAL;
+               goto err_bo;
        }
        WARN_ON(bo->mmu->as != as);
  
        /* Assume 2MB alignment and size multiple */
        addr &= ~((u64)SZ_2M - 1);
        page_offset = addr >> PAGE_SHIFT;
-       page_offset -= node->start;
+       page_offset -= bo->node.start;
  
        mutex_lock(&bo->base.pages_lock);
  
                                     sizeof(struct sg_table), GFP_KERNEL | __GFP_ZERO);
                if (!bo->sgts) {
                        mutex_unlock(&bo->base.pages_lock);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_bo;
                }
  
                pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
                        kfree(bo->sgts);
                        bo->sgts = NULL;
                        mutex_unlock(&bo->base.pages_lock);
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_bo;
                }
                bo->base.pages = pages;
                bo->base.pages_use_count = 1;
  
        dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
  
+       drm_gem_object_put_unlocked(&bo->base.base);
        return 0;
  
  err_map:
        sg_free_table(sgt);
  err_pages:
        drm_gem_shmem_put_pages(&bo->base);
+ err_bo:
+       drm_gem_object_put_unlocked(&bo->base.base);
        return ret;
  }
  
index 431e6b64b77db6914dedbe24f122e72eaddf9de9,4267cb55bc331e0f4ebd37a2d3eed6b7319c1fbb..d0bc91ed7c90a73b898e57a6a77a4786c11ed169
@@@ -35,7 -35,6 +35,7 @@@
  #include <linux/module.h>
  #include <linux/pm_runtime.h>
  #include <linux/vga_switcheroo.h>
 +#include <linux/mmu_notifier.h>
  
  #include <drm/drm_crtc_helper.h>
  #include <drm/drm_drv.h>
@@@ -324,8 -323,39 +324,39 @@@ bool radeon_device_is_virtual(void)
  static int radeon_pci_probe(struct pci_dev *pdev,
                            const struct pci_device_id *ent)
  {
+       unsigned long flags = 0;
        int ret;
  
+       if (!ent)
+               return -ENODEV; /* Avoid NULL-ptr deref in drm_get_pci_dev */
+       flags = ent->driver_data;
+       if (!radeon_si_support) {
+               switch (flags & RADEON_FAMILY_MASK) {
+               case CHIP_TAHITI:
+               case CHIP_PITCAIRN:
+               case CHIP_VERDE:
+               case CHIP_OLAND:
+               case CHIP_HAINAN:
+                       dev_info(&pdev->dev,
+                                "SI support disabled by module param\n");
+                       return -ENODEV;
+               }
+       }
+       if (!radeon_cik_support) {
+               switch (flags & RADEON_FAMILY_MASK) {
+               case CHIP_KAVERI:
+               case CHIP_BONAIRE:
+               case CHIP_HAWAII:
+               case CHIP_KABINI:
+               case CHIP_MULLINS:
+                       dev_info(&pdev->dev,
+                                "CIK support disabled by module param\n");
+                       return -ENODEV;
+               }
+       }
        if (vga_switcheroo_client_probe_defer(pdev))
                return -EPROBE_DEFER;
  
@@@ -624,7 -654,6 +655,7 @@@ static void __exit radeon_exit(void
  {
        pci_unregister_driver(pdriver);
        radeon_unregister_atpx_handler();
 +      mmu_notifier_synchronize();
  }
  
  module_init(radeon_init);