OSDN Git Service

drm/i915: Implement inter-engine read-read optimisations
[uclinux-h8/linux.git] / drivers / gpu / drm / i915 / i915_debugfs.c
index 007c7d7..5fceb94 100644 (file)
@@ -96,7 +96,7 @@ static int i915_capabilities(struct seq_file *m, void *data)
 
 static const char *get_pin_flag(struct drm_i915_gem_object *obj)
 {
-       if (i915_gem_obj_is_pinned(obj))
+       if (obj->pin_display)
                return "p";
        else
                return " ";
@@ -120,18 +120,25 @@ static inline const char *get_global_flag(struct drm_i915_gem_object *obj)
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+       struct intel_engine_cs *ring;
        struct i915_vma *vma;
        int pin_count = 0;
+       int i;
 
-       seq_printf(m, "%pK: %s%s%s %8zdKiB %02x %02x %x %x %x%s%s%s",
+       seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ",
                   &obj->base,
+                  obj->active ? "*" : " ",
                   get_pin_flag(obj),
                   get_tiling_flag(obj),
                   get_global_flag(obj),
                   obj->base.size / 1024,
                   obj->base.read_domains,
-                  obj->base.write_domain,
-                  i915_gem_request_get_seqno(obj->last_read_req),
+                  obj->base.write_domain);
+       for_each_ring(ring, dev_priv, i)
+               seq_printf(m, "%x ",
+                               i915_gem_request_get_seqno(obj->last_read_req[i]));
+       seq_printf(m, "] %x %x%s%s%s",
                   i915_gem_request_get_seqno(obj->last_write_req),
                   i915_gem_request_get_seqno(obj->last_fenced_req),
                   i915_cache_level_str(to_i915(obj->base.dev), obj->cache_level),
@@ -159,18 +166,18 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
        }
        if (obj->stolen)
                seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
-       if (obj->pin_mappable || obj->fault_mappable) {
+       if (obj->pin_display || obj->fault_mappable) {
                char s[3], *t = s;
-               if (obj->pin_mappable)
+               if (obj->pin_display)
                        *t++ = 'p';
                if (obj->fault_mappable)
                        *t++ = 'f';
                *t = '\0';
                seq_printf(m, " (%s mappable)", s);
        }
-       if (obj->last_read_req != NULL)
+       if (obj->last_write_req != NULL)
                seq_printf(m, " (%s)",
-                          i915_gem_request_get_ring(obj->last_read_req)->name);
+                          i915_gem_request_get_ring(obj->last_write_req)->name);
        if (obj->frontbuffer_bits)
                seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
 }
@@ -361,31 +368,39 @@ static int per_file_stats(int id, void *ptr, void *data)
        return 0;
 }
 
-#define print_file_stats(m, name, stats) \
-       seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \
-                  name, \
-                  stats.count, \
-                  stats.total, \
-                  stats.active, \
-                  stats.inactive, \
-                  stats.global, \
-                  stats.shared, \
-                  stats.unbound)
+#define print_file_stats(m, name, stats) do { \
+       if (stats.count) \
+               seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu global, %zu shared, %zu unbound)\n", \
+                          name, \
+                          stats.count, \
+                          stats.total, \
+                          stats.active, \
+                          stats.inactive, \
+                          stats.global, \
+                          stats.shared, \
+                          stats.unbound); \
+} while (0)
 
 static void print_batch_pool_stats(struct seq_file *m,
                                   struct drm_i915_private *dev_priv)
 {
        struct drm_i915_gem_object *obj;
        struct file_stats stats;
+       struct intel_engine_cs *ring;
+       int i, j;
 
        memset(&stats, 0, sizeof(stats));
 
-       list_for_each_entry(obj,
-                           &dev_priv->mm.batch_pool.cache_list,
-                           batch_pool_list)
-               per_file_stats(0, obj, &stats);
+       for_each_ring(ring, dev_priv, i) {
+               for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+                       list_for_each_entry(obj,
+                                           &ring->batch_pool.cache_list[j],
+                                           batch_pool_link)
+                               per_file_stats(0, obj, &stats);
+               }
+       }
 
-       print_file_stats(m, "batch pool", stats);
+       print_file_stats(m, "[k]batch pool", stats);
 }
 
 #define count_vmas(list, member) do { \
@@ -449,7 +464,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
                        size += i915_gem_obj_ggtt_size(obj);
                        ++count;
                }
-               if (obj->pin_mappable) {
+               if (obj->pin_display) {
                        mappable_size += i915_gem_obj_ggtt_size(obj);
                        ++mappable_count;
                }
@@ -471,8 +486,6 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
 
        seq_putc(m, '\n');
        print_batch_pool_stats(m, dev_priv);
-
-       seq_putc(m, '\n');
        list_for_each_entry_reverse(file, &dev->filelist, lhead) {
                struct file_stats stats;
                struct task_struct *task;
@@ -613,24 +626,39 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
-       int count = 0;
-       int ret;
+       struct intel_engine_cs *ring;
+       int total = 0;
+       int ret, i, j;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
 
-       seq_puts(m, "cache:\n");
-       list_for_each_entry(obj,
-                           &dev_priv->mm.batch_pool.cache_list,
-                           batch_pool_list) {
-               seq_puts(m, "   ");
-               describe_obj(m, obj);
-               seq_putc(m, '\n');
-               count++;
+       for_each_ring(ring, dev_priv, i) {
+               for (j = 0; j < ARRAY_SIZE(ring->batch_pool.cache_list); j++) {
+                       int count;
+
+                       count = 0;
+                       list_for_each_entry(obj,
+                                           &ring->batch_pool.cache_list[j],
+                                           batch_pool_link)
+                               count++;
+                       seq_printf(m, "%s cache[%d]: %d objects\n",
+                                  ring->name, j, count);
+
+                       list_for_each_entry(obj,
+                                           &ring->batch_pool.cache_list[j],
+                                           batch_pool_link) {
+                               seq_puts(m, "   ");
+                               describe_obj(m, obj);
+                               seq_putc(m, '\n');
+                       }
+
+                       total += count;
+               }
        }
 
-       seq_printf(m, "total: %d\n", count);
+       seq_printf(m, "total: %d\n", total);
 
        mutex_unlock(&dev->struct_mutex);
 
@@ -643,31 +671,44 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_engine_cs *ring;
-       struct drm_i915_gem_request *gem_request;
-       int ret, count, i;
+       struct drm_i915_gem_request *req;
+       int ret, any, i;
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
                return ret;
 
-       count = 0;
+       any = 0;
        for_each_ring(ring, dev_priv, i) {
-               if (list_empty(&ring->request_list))
+               int count;
+
+               count = 0;
+               list_for_each_entry(req, &ring->request_list, list)
+                       count++;
+               if (count == 0)
                        continue;
 
-               seq_printf(m, "%s requests:\n", ring->name);
-               list_for_each_entry(gem_request,
-                                   &ring->request_list,
-                                   list) {
-                       seq_printf(m, "    %x @ %d\n",
-                                  gem_request->seqno,
-                                  (int) (jiffies - gem_request->emitted_jiffies));
+               seq_printf(m, "%s requests: %d\n", ring->name, count);
+               list_for_each_entry(req, &ring->request_list, list) {
+                       struct task_struct *task;
+
+                       rcu_read_lock();
+                       task = NULL;
+                       if (req->pid)
+                               task = pid_task(req->pid, PIDTYPE_PID);
+                       seq_printf(m, "    %x @ %d: %s [%d]\n",
+                                  req->seqno,
+                                  (int) (jiffies - req->emitted_jiffies),
+                                  task ? task->comm : "<unknown>",
+                                  task ? task->pid : -1);
+                       rcu_read_unlock();
                }
-               count++;
+
+               any++;
        }
        mutex_unlock(&dev->struct_mutex);
 
-       if (count == 0)
+       if (any == 0)
                seq_puts(m, "No requests\n");
 
        return 0;
@@ -1176,12 +1217,17 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
                           GEN6_CURBSYTAVG_MASK);
                seq_printf(m, "RP PREV UP: %dus\n", rpprevup &
                           GEN6_CURBSYTAVG_MASK);
+               seq_printf(m, "Up threshold: %d%%\n",
+                          dev_priv->rps.up_threshold);
+
                seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei &
                           GEN6_CURIAVG_MASK);
                seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown &
                           GEN6_CURBSYTAVG_MASK);
                seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown &
                           GEN6_CURBSYTAVG_MASK);
+               seq_printf(m, "Down threshold: %d%%\n",
+                          dev_priv->rps.down_threshold);
 
                max_freq = (rp_state_cap & 0xff0000) >> 16;
                max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
@@ -1197,12 +1243,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
                max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
                seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
                           intel_gpu_freq(dev_priv, max_freq));
-
                seq_printf(m, "Max overclocked frequency: %dMHz\n",
                           intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
 
+               seq_printf(m, "Current freq: %d MHz\n",
+                          intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
+               seq_printf(m, "Actual freq: %d MHz\n", cagf);
                seq_printf(m, "Idle freq: %d MHz\n",
                           intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
+               seq_printf(m, "Min freq: %d MHz\n",
+                          intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
+               seq_printf(m, "Max freq: %d MHz\n",
+                          intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
+               seq_printf(m,
+                          "efficient (RPe) frequency: %d MHz\n",
+                          intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
        } else if (IS_VALLEYVIEW(dev)) {
                u32 freq_sts;
 
@@ -1211,6 +1266,12 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
                seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
                seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
 
+               seq_printf(m, "actual GPU freq: %d MHz\n",
+                          intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
+
+               seq_printf(m, "current GPU freq: %d MHz\n",
+                          intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
+
                seq_printf(m, "max GPU freq: %d MHz\n",
                           intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
 
@@ -1223,9 +1284,6 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
                seq_printf(m,
                           "efficient (RPe) frequency: %d MHz\n",
                           intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
-
-               seq_printf(m, "current GPU freq: %d MHz\n",
-                          intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
                mutex_unlock(&dev_priv->rps.hw_lock);
        } else {
                seq_puts(m, "no P-state info available\n");
@@ -2153,8 +2211,6 @@ static void gen8_ppgtt_info(struct seq_file *m, struct drm_device *dev)
        if (!ppgtt)
                return;
 
-       seq_printf(m, "Page directories: %d\n", ppgtt->num_pd_pages);
-       seq_printf(m, "Page tables: %d\n", ppgtt->num_pd_entries);
        for_each_ring(ring, dev_priv, unused) {
                seq_printf(m, "%s\n", ring->name);
                for (i = 0; i < 4; i++) {
@@ -2226,6 +2282,44 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)
        return 0;
 }
 
+static int i915_rps_boost_info(struct seq_file *m, void *data)
+{
+       struct drm_info_node *node = m->private;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_file *file;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock);
+       if (ret)
+               goto unlock;
+
+       list_for_each_entry_reverse(file, &dev->filelist, lhead) {
+               struct drm_i915_file_private *file_priv = file->driver_priv;
+               struct task_struct *task;
+
+               rcu_read_lock();
+               task = pid_task(file->pid, PIDTYPE_PID);
+               seq_printf(m, "%s [%d]: %d boosts%s\n",
+                          task ? task->comm : "<unknown>",
+                          task ? task->pid : -1,
+                          file_priv->rps_boosts,
+                          list_empty(&file_priv->rps_boost) ? "" : ", active");
+               rcu_read_unlock();
+       }
+       seq_printf(m, "Kernel boosts: %d\n", dev_priv->rps.boosts);
+
+       mutex_unlock(&dev_priv->rps.hw_lock);
+unlock:
+       mutex_unlock(&dev->struct_mutex);
+
+       return ret;
+}
+
 static int i915_llc(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = m->private;
@@ -2287,9 +2381,6 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                }
        seq_puts(m, "\n");
 
-       seq_printf(m, "Link standby: %s\n",
-                  yesno((bool)dev_priv->psr.link_standby));
-
        /* CHV PSR has no kind of performance counter */
        if (HAS_DDI(dev)) {
                psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
@@ -3526,8 +3617,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
                intel_display_power_get(dev_priv,
                                        POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
 
-               dev_priv->display.crtc_disable(&crtc->base);
-               dev_priv->display.crtc_enable(&crtc->base);
+               intel_crtc_reset(crtc);
        }
        drm_modeset_unlock_all(dev);
 }
@@ -3548,8 +3638,7 @@ static void hsw_undo_trans_edp_pipe_A_crc_wa(struct drm_device *dev)
        if (crtc->config->pch_pfit.force_thru) {
                crtc->config->pch_pfit.force_thru = false;
 
-               dev_priv->display.crtc_disable(&crtc->base);
-               dev_priv->display.crtc_enable(&crtc->base);
+               intel_crtc_reset(crtc);
 
                intel_display_power_put(dev_priv,
                                        POWER_DOMAIN_PIPE_PANEL_FITTER(PIPE_A));
@@ -3866,6 +3955,212 @@ static const struct file_operations i915_display_crc_ctl_fops = {
        .write = display_crc_ctl_write
 };
 
+static ssize_t i915_displayport_test_active_write(struct file *file,
+                                           const char __user *ubuf,
+                                           size_t len, loff_t *offp)
+{
+       char *input_buffer;
+       int status = 0;
+       struct seq_file *m;
+       struct drm_device *dev;
+       struct drm_connector *connector;
+       struct list_head *connector_list;
+       struct intel_dp *intel_dp;
+       int val = 0;
+
+       m = file->private_data;
+       if (!m) {
+               status = -ENODEV;
+               return status;
+       }
+       dev = m->private;
+
+       if (!dev) {
+               status = -ENODEV;
+               return status;
+       }
+       connector_list = &dev->mode_config.connector_list;
+
+       if (len == 0)
+               return 0;
+
+       input_buffer = kmalloc(len + 1, GFP_KERNEL);
+       if (!input_buffer)
+               return -ENOMEM;
+
+       if (copy_from_user(input_buffer, ubuf, len)) {
+               status = -EFAULT;
+               goto out;
+       }
+
+       input_buffer[len] = '\0';
+       DRM_DEBUG_DRIVER("Copied %d bytes from user\n", (unsigned int)len);
+
+       list_for_each_entry(connector, connector_list, head) {
+
+               if (connector->connector_type !=
+                   DRM_MODE_CONNECTOR_DisplayPort)
+                       continue;
+
+               if (connector->connector_type ==
+                   DRM_MODE_CONNECTOR_DisplayPort &&
+                   connector->status == connector_status_connected &&
+                   connector->encoder != NULL) {
+                       intel_dp = enc_to_intel_dp(connector->encoder);
+                       status = kstrtoint(input_buffer, 10, &val);
+                       if (status < 0)
+                               goto out;
+                       DRM_DEBUG_DRIVER("Got %d for test active\n", val);
+                       /* To prevent erroneous activation of the compliance
+                        * testing code, only accept an actual value of 1 here
+                        */
+                       if (val == 1)
+                               intel_dp->compliance_test_active = 1;
+                       else
+                               intel_dp->compliance_test_active = 0;
+               }
+       }
+out:
+       kfree(input_buffer);
+       if (status < 0)
+               return status;
+
+       *offp += len;
+       return len;
+}
+
+static int i915_displayport_test_active_show(struct seq_file *m, void *data)
+{
+       struct drm_device *dev = m->private;
+       struct drm_connector *connector;
+       struct list_head *connector_list = &dev->mode_config.connector_list;
+       struct intel_dp *intel_dp;
+
+       if (!dev)
+               return -ENODEV;
+
+       list_for_each_entry(connector, connector_list, head) {
+
+               if (connector->connector_type !=
+                   DRM_MODE_CONNECTOR_DisplayPort)
+                       continue;
+
+               if (connector->status == connector_status_connected &&
+                   connector->encoder != NULL) {
+                       intel_dp = enc_to_intel_dp(connector->encoder);
+                       if (intel_dp->compliance_test_active)
+                               seq_puts(m, "1");
+                       else
+                               seq_puts(m, "0");
+               } else
+                       seq_puts(m, "0");
+       }
+
+       return 0;
+}
+
+static int i915_displayport_test_active_open(struct inode *inode,
+                                      struct file *file)
+{
+       struct drm_device *dev = inode->i_private;
+
+       return single_open(file, i915_displayport_test_active_show, dev);
+}
+
+static const struct file_operations i915_displayport_test_active_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_displayport_test_active_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .write = i915_displayport_test_active_write
+};
+
+static int i915_displayport_test_data_show(struct seq_file *m, void *data)
+{
+       struct drm_device *dev = m->private;
+       struct drm_connector *connector;
+       struct list_head *connector_list = &dev->mode_config.connector_list;
+       struct intel_dp *intel_dp;
+
+       if (!dev)
+               return -ENODEV;
+
+       list_for_each_entry(connector, connector_list, head) {
+
+               if (connector->connector_type !=
+                   DRM_MODE_CONNECTOR_DisplayPort)
+                       continue;
+
+               if (connector->status == connector_status_connected &&
+                   connector->encoder != NULL) {
+                       intel_dp = enc_to_intel_dp(connector->encoder);
+                       seq_printf(m, "%lx", intel_dp->compliance_test_data);
+               } else
+                       seq_puts(m, "0");
+       }
+
+       return 0;
+}
+static int i915_displayport_test_data_open(struct inode *inode,
+                                      struct file *file)
+{
+       struct drm_device *dev = inode->i_private;
+
+       return single_open(file, i915_displayport_test_data_show, dev);
+}
+
+static const struct file_operations i915_displayport_test_data_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_displayport_test_data_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release
+};
+
+static int i915_displayport_test_type_show(struct seq_file *m, void *data)
+{
+       struct drm_device *dev = m->private;
+       struct drm_connector *connector;
+       struct list_head *connector_list = &dev->mode_config.connector_list;
+       struct intel_dp *intel_dp;
+
+       if (!dev)
+               return -ENODEV;
+
+       list_for_each_entry(connector, connector_list, head) {
+
+               if (connector->connector_type !=
+                   DRM_MODE_CONNECTOR_DisplayPort)
+                       continue;
+
+               if (connector->status == connector_status_connected &&
+                   connector->encoder != NULL) {
+                       intel_dp = enc_to_intel_dp(connector->encoder);
+                       seq_printf(m, "%02lx", intel_dp->compliance_test_type);
+               } else
+                       seq_puts(m, "0");
+       }
+
+       return 0;
+}
+
+static int i915_displayport_test_type_open(struct inode *inode,
+                                      struct file *file)
+{
+       struct drm_device *dev = inode->i_private;
+
+       return single_open(file, i915_displayport_test_type_show, dev);
+}
+
+static const struct file_operations i915_displayport_test_type_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_displayport_test_type_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release
+};
+
 static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
 {
        struct drm_device *dev = m->private;
@@ -4470,12 +4765,116 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops,
                        i915_cache_sharing_get, i915_cache_sharing_set,
                        "%llu\n");
 
+struct sseu_dev_status {
+       unsigned int slice_total;
+       unsigned int subslice_total;
+       unsigned int subslice_per_slice;
+       unsigned int eu_total;
+       unsigned int eu_per_subslice;
+};
+
+static void cherryview_sseu_device_status(struct drm_device *dev,
+                                         struct sseu_dev_status *stat)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       const int ss_max = 2;
+       int ss;
+       u32 sig1[ss_max], sig2[ss_max];
+
+       sig1[0] = I915_READ(CHV_POWER_SS0_SIG1);
+       sig1[1] = I915_READ(CHV_POWER_SS1_SIG1);
+       sig2[0] = I915_READ(CHV_POWER_SS0_SIG2);
+       sig2[1] = I915_READ(CHV_POWER_SS1_SIG2);
+
+       for (ss = 0; ss < ss_max; ss++) {
+               unsigned int eu_cnt;
+
+               if (sig1[ss] & CHV_SS_PG_ENABLE)
+                       /* skip disabled subslice */
+                       continue;
+
+               stat->slice_total = 1;
+               stat->subslice_per_slice++;
+               eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) +
+                        ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) +
+                        ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) +
+                        ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2);
+               stat->eu_total += eu_cnt;
+               stat->eu_per_subslice = max(stat->eu_per_subslice, eu_cnt);
+       }
+       stat->subslice_total = stat->subslice_per_slice;
+}
+
+static void gen9_sseu_device_status(struct drm_device *dev,
+                                   struct sseu_dev_status *stat)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int s_max = 3, ss_max = 4;
+       int s, ss;
+       u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
+
+       /* BXT has a single slice and at most 3 subslices. */
+       if (IS_BROXTON(dev)) {
+               s_max = 1;
+               ss_max = 3;
+       }
+
+       for (s = 0; s < s_max; s++) {
+               s_reg[s] = I915_READ(GEN9_SLICE_PGCTL_ACK(s));
+               eu_reg[2*s] = I915_READ(GEN9_SS01_EU_PGCTL_ACK(s));
+               eu_reg[2*s + 1] = I915_READ(GEN9_SS23_EU_PGCTL_ACK(s));
+       }
+
+       eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |
+                    GEN9_PGCTL_SSA_EU19_ACK |
+                    GEN9_PGCTL_SSA_EU210_ACK |
+                    GEN9_PGCTL_SSA_EU311_ACK;
+       eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |
+                    GEN9_PGCTL_SSB_EU19_ACK |
+                    GEN9_PGCTL_SSB_EU210_ACK |
+                    GEN9_PGCTL_SSB_EU311_ACK;
+
+       for (s = 0; s < s_max; s++) {
+               unsigned int ss_cnt = 0;
+
+               if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
+                       /* skip disabled slice */
+                       continue;
+
+               stat->slice_total++;
+
+               if (IS_SKYLAKE(dev))
+                       ss_cnt = INTEL_INFO(dev)->subslice_per_slice;
+
+               for (ss = 0; ss < ss_max; ss++) {
+                       unsigned int eu_cnt;
+
+                       if (IS_BROXTON(dev) &&
+                           !(s_reg[s] & (GEN9_PGCTL_SS_ACK(ss))))
+                               /* skip disabled subslice */
+                               continue;
+
+                       if (IS_BROXTON(dev))
+                               ss_cnt++;
+
+                       eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] &
+                                              eu_mask[ss%2]);
+                       stat->eu_total += eu_cnt;
+                       stat->eu_per_subslice = max(stat->eu_per_subslice,
+                                                   eu_cnt);
+               }
+
+               stat->subslice_total += ss_cnt;
+               stat->subslice_per_slice = max(stat->subslice_per_slice,
+                                              ss_cnt);
+       }
+}
+
 static int i915_sseu_status(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       unsigned int s_tot = 0, ss_tot = 0, ss_per = 0, eu_tot = 0, eu_per = 0;
+       struct sseu_dev_status stat;
 
        if ((INTEL_INFO(dev)->gen < 8) || IS_BROADWELL(dev))
                return -ENODEV;
@@ -4499,79 +4898,22 @@ static int i915_sseu_status(struct seq_file *m, void *unused)
                   yesno(INTEL_INFO(dev)->has_eu_pg));
 
        seq_puts(m, "SSEU Device Status\n");
+       memset(&stat, 0, sizeof(stat));
        if (IS_CHERRYVIEW(dev)) {
-               const int ss_max = 2;
-               int ss;
-               u32 sig1[ss_max], sig2[ss_max];
-
-               sig1[0] = I915_READ(CHV_POWER_SS0_SIG1);
-               sig1[1] = I915_READ(CHV_POWER_SS1_SIG1);
-               sig2[0] = I915_READ(CHV_POWER_SS0_SIG2);
-               sig2[1] = I915_READ(CHV_POWER_SS1_SIG2);
-
-               for (ss = 0; ss < ss_max; ss++) {
-                       unsigned int eu_cnt;
-
-                       if (sig1[ss] & CHV_SS_PG_ENABLE)
-                               /* skip disabled subslice */
-                               continue;
-
-                       s_tot = 1;
-                       ss_per++;
-                       eu_cnt = ((sig1[ss] & CHV_EU08_PG_ENABLE) ? 0 : 2) +
-                                ((sig1[ss] & CHV_EU19_PG_ENABLE) ? 0 : 2) +
-                                ((sig1[ss] & CHV_EU210_PG_ENABLE) ? 0 : 2) +
-                                ((sig2[ss] & CHV_EU311_PG_ENABLE) ? 0 : 2);
-                       eu_tot += eu_cnt;
-                       eu_per = max(eu_per, eu_cnt);
-               }
-               ss_tot = ss_per;
-       } else if (IS_SKYLAKE(dev)) {
-               const int s_max = 3, ss_max = 4;
-               int s, ss;
-               u32 s_reg[s_max], eu_reg[2*s_max], eu_mask[2];
-
-               s_reg[0] = I915_READ(GEN9_SLICE0_PGCTL_ACK);
-               s_reg[1] = I915_READ(GEN9_SLICE1_PGCTL_ACK);
-               s_reg[2] = I915_READ(GEN9_SLICE2_PGCTL_ACK);
-               eu_reg[0] = I915_READ(GEN9_SLICE0_SS01_EU_PGCTL_ACK);
-               eu_reg[1] = I915_READ(GEN9_SLICE0_SS23_EU_PGCTL_ACK);
-               eu_reg[2] = I915_READ(GEN9_SLICE1_SS01_EU_PGCTL_ACK);
-               eu_reg[3] = I915_READ(GEN9_SLICE1_SS23_EU_PGCTL_ACK);
-               eu_reg[4] = I915_READ(GEN9_SLICE2_SS01_EU_PGCTL_ACK);
-               eu_reg[5] = I915_READ(GEN9_SLICE2_SS23_EU_PGCTL_ACK);
-               eu_mask[0] = GEN9_PGCTL_SSA_EU08_ACK |
-                            GEN9_PGCTL_SSA_EU19_ACK |
-                            GEN9_PGCTL_SSA_EU210_ACK |
-                            GEN9_PGCTL_SSA_EU311_ACK;
-               eu_mask[1] = GEN9_PGCTL_SSB_EU08_ACK |
-                            GEN9_PGCTL_SSB_EU19_ACK |
-                            GEN9_PGCTL_SSB_EU210_ACK |
-                            GEN9_PGCTL_SSB_EU311_ACK;
-
-               for (s = 0; s < s_max; s++) {
-                       if ((s_reg[s] & GEN9_PGCTL_SLICE_ACK) == 0)
-                               /* skip disabled slice */
-                               continue;
-
-                       s_tot++;
-                       ss_per = INTEL_INFO(dev)->subslice_per_slice;
-                       ss_tot += ss_per;
-                       for (ss = 0; ss < ss_max; ss++) {
-                               unsigned int eu_cnt;
-
-                               eu_cnt = 2 * hweight32(eu_reg[2*s + ss/2] &
-                                                      eu_mask[ss%2]);
-                               eu_tot += eu_cnt;
-                               eu_per = max(eu_per, eu_cnt);
-                       }
-               }
+               cherryview_sseu_device_status(dev, &stat);
+       } else if (INTEL_INFO(dev)->gen >= 9) {
+               gen9_sseu_device_status(dev, &stat);
        }
-       seq_printf(m, "  Enabled Slice Total: %u\n", s_tot);
-       seq_printf(m, "  Enabled Subslice Total: %u\n", ss_tot);
-       seq_printf(m, "  Enabled Subslice Per Slice: %u\n", ss_per);
-       seq_printf(m, "  Enabled EU Total: %u\n", eu_tot);
-       seq_printf(m, "  Enabled EU Per Subslice: %u\n", eu_per);
+       seq_printf(m, "  Enabled Slice Total: %u\n",
+                  stat.slice_total);
+       seq_printf(m, "  Enabled Subslice Total: %u\n",
+                  stat.subslice_total);
+       seq_printf(m, "  Enabled Subslice Per Slice: %u\n",
+                  stat.subslice_per_slice);
+       seq_printf(m, "  Enabled EU Total: %u\n",
+                  stat.eu_total);
+       seq_printf(m, "  Enabled EU Per Subslice: %u\n",
+                  stat.eu_per_subslice);
 
        return 0;
 }
@@ -4691,6 +5033,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
        {"i915_ddb_info", i915_ddb_info, 0},
        {"i915_sseu_status", i915_sseu_status, 0},
        {"i915_drrs_status", i915_drrs_status, 0},
+       {"i915_rps_boost_info", i915_rps_boost_info, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
@@ -4713,6 +5056,9 @@ static const struct i915_debugfs_files {
        {"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
        {"i915_cur_wm_latency", &i915_cur_wm_latency_fops},
        {"i915_fbc_false_color", &i915_fbc_fc_fops},
+       {"i915_dp_test_data", &i915_displayport_test_data_fops},
+       {"i915_dp_test_type", &i915_displayport_test_type_fops},
+       {"i915_dp_test_active", &i915_displayport_test_active_fops}
 };
 
 void intel_display_crc_init(struct drm_device *dev)
@@ -4780,3 +5126,102 @@ void i915_debugfs_cleanup(struct drm_minor *minor)
                drm_debugfs_remove_files(info_list, 1, minor);
        }
 }
+
+struct dpcd_block {
+       /* DPCD dump start address. */
+       unsigned int offset;
+       /* DPCD dump end address, inclusive. If unset, .size will be used. */
+       unsigned int end;
+       /* DPCD dump size. Used if .end is unset. If unset, defaults to 1. */
+       size_t size;
+       /* Only valid for eDP. */
+       bool edp;
+};
+
+static const struct dpcd_block i915_dpcd_debug[] = {
+       { .offset = DP_DPCD_REV, .size = DP_RECEIVER_CAP_SIZE },
+       { .offset = DP_PSR_SUPPORT, .end = DP_PSR_CAPS },
+       { .offset = DP_DOWNSTREAM_PORT_0, .size = 16 },
+       { .offset = DP_LINK_BW_SET, .end = DP_EDP_CONFIGURATION_SET },
+       { .offset = DP_SINK_COUNT, .end = DP_ADJUST_REQUEST_LANE2_3 },
+       { .offset = DP_SET_POWER },
+       { .offset = DP_EDP_DPCD_REV },
+       { .offset = DP_EDP_GENERAL_CAP_1, .end = DP_EDP_GENERAL_CAP_3 },
+       { .offset = DP_EDP_DISPLAY_CONTROL_REGISTER, .end = DP_EDP_BACKLIGHT_FREQ_CAP_MAX_LSB },
+       { .offset = DP_EDP_DBC_MINIMUM_BRIGHTNESS_SET, .end = DP_EDP_DBC_MAXIMUM_BRIGHTNESS_SET },
+};
+
+static int i915_dpcd_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct intel_dp *intel_dp =
+               enc_to_intel_dp(&intel_attached_encoder(connector)->base);
+       uint8_t buf[16];
+       ssize_t err;
+       int i;
+
+       if (connector->status != connector_status_connected)
+               return -ENODEV;
+
+       for (i = 0; i < ARRAY_SIZE(i915_dpcd_debug); i++) {
+               const struct dpcd_block *b = &i915_dpcd_debug[i];
+               size_t size = b->end ? b->end - b->offset + 1 : (b->size ?: 1);
+
+               if (b->edp &&
+                   connector->connector_type != DRM_MODE_CONNECTOR_eDP)
+                       continue;
+
+               /* low tech for now */
+               if (WARN_ON(size > sizeof(buf)))
+                       continue;
+
+               err = drm_dp_dpcd_read(&intel_dp->aux, b->offset, buf, size);
+               if (err <= 0) {
+                       DRM_ERROR("dpcd read (%zu bytes at %u) failed (%zd)\n",
+                                 size, b->offset, err);
+                       continue;
+               }
+
+               seq_printf(m, "%04x: %*ph\n", b->offset, (int) size, buf);
+       }
+
+       return 0;
+}
+
+static int i915_dpcd_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, i915_dpcd_show, inode->i_private);
+}
+
+static const struct file_operations i915_dpcd_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_dpcd_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+/**
+ * i915_debugfs_connector_add - add i915 specific connector debugfs files
+ * @connector: pointer to a registered drm_connector
+ *
+ * Cleanup will be done by drm_connector_unregister() through a call to
+ * drm_debugfs_connector_remove().
+ *
+ * Returns 0 on success, negative error codes on error.
+ */
+int i915_debugfs_connector_add(struct drm_connector *connector)
+{
+       struct dentry *root = connector->debugfs_entry;
+
+       /* The connector must have been registered beforehands. */
+       if (!root)
+               return -ENODEV;
+
+       if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+               debugfs_create_file("i915_dpcd", S_IRUGO, root, connector,
+                                   &i915_dpcd_fops);
+
+       return 0;
+}