drm/i915: Add second slice l3 remapping
Certain HSW SKUs have a second bank of L3. This L3 remapping has a separate register set, and interrupt from the first "slice". A slice is simply a term to define some subset of the GPU's l3 cache. This patch implements both the interrupt handler, and ability to communicate with userspace about this second slice. v2: Remove redundant check about non-existent slice. Change warning about interrupts of unknown slices to WARN_ON_ONCE Handle the case where we get 2 slice interrupts concurrently, and switch the tracking of interrupts to be non-destructive (all Ville) Don't enable/mask the second slice parity interrupt for ivb/vlv (even though all docs I can find claim it's rsvd) (Ville + Bryan) Keep BYT excluded from L3 parity v3: Fix the slice = ffs to be decremented by one (found by Ville). When I initially did my testing on the series, I was using 1-based slice counting, so this code was correct. Not sure why my simpler tests that I've been running since then didn't pick it up sooner. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Ben Widawsky <ben@bwidawsk.net> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Esse commit está contido em:
@@ -119,6 +119,7 @@ i915_l3_read(struct file *filp, struct kobject *kobj,
|
||||
struct drm_device *drm_dev = dminor->dev;
|
||||
struct drm_i915_private *dev_priv = drm_dev->dev_private;
|
||||
uint32_t misccpctl;
|
||||
int slice = (int)(uintptr_t)attr->private;
|
||||
int i, ret;
|
||||
|
||||
count = round_down(count, 4);
|
||||
@@ -134,9 +135,9 @@ i915_l3_read(struct file *filp, struct kobject *kobj,
|
||||
return ret;
|
||||
|
||||
if (IS_HASWELL(drm_dev)) {
|
||||
if (dev_priv->l3_parity.remap_info)
|
||||
if (dev_priv->l3_parity.remap_info[slice])
|
||||
memcpy(buf,
|
||||
dev_priv->l3_parity.remap_info + (offset/4),
|
||||
dev_priv->l3_parity.remap_info[slice] + (offset/4),
|
||||
count);
|
||||
else
|
||||
memset(buf, 0, count);
|
||||
@@ -168,6 +169,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
|
||||
struct drm_device *drm_dev = dminor->dev;
|
||||
struct drm_i915_private *dev_priv = drm_dev->dev_private;
|
||||
u32 *temp = NULL; /* Just here to make handling failures easy */
|
||||
int slice = (int)(uintptr_t)attr->private;
|
||||
int ret;
|
||||
|
||||
ret = l3_access_valid(drm_dev, offset);
|
||||
@@ -178,7 +180,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!dev_priv->l3_parity.remap_info) {
|
||||
if (!dev_priv->l3_parity.remap_info[slice]) {
|
||||
temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
|
||||
if (!temp) {
|
||||
mutex_unlock(&drm_dev->struct_mutex);
|
||||
@@ -198,11 +200,11 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
|
||||
* at this point it is left as a TODO.
|
||||
*/
|
||||
if (temp)
|
||||
dev_priv->l3_parity.remap_info = temp;
|
||||
dev_priv->l3_parity.remap_info[slice] = temp;
|
||||
|
||||
memcpy(dev_priv->l3_parity.remap_info + (offset/4), buf, count);
|
||||
memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);
|
||||
|
||||
i915_gem_l3_remap(drm_dev);
|
||||
i915_gem_l3_remap(drm_dev, slice);
|
||||
|
||||
mutex_unlock(&drm_dev->struct_mutex);
|
||||
|
||||
@@ -214,7 +216,17 @@ static struct bin_attribute dpf_attrs = {
|
||||
.size = GEN7_L3LOG_SIZE,
|
||||
.read = i915_l3_read,
|
||||
.write = i915_l3_write,
|
||||
.mmap = NULL
|
||||
.mmap = NULL,
|
||||
.private = (void *)0
|
||||
};
|
||||
|
||||
static struct bin_attribute dpf_attrs_1 = {
|
||||
.attr = {.name = "l3_parity_slice_1", .mode = (S_IRUSR | S_IWUSR)},
|
||||
.size = GEN7_L3LOG_SIZE,
|
||||
.read = i915_l3_read,
|
||||
.write = i915_l3_write,
|
||||
.mmap = NULL,
|
||||
.private = (void *)1
|
||||
};
|
||||
|
||||
static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
|
||||
@@ -525,6 +537,13 @@ void i915_setup_sysfs(struct drm_device *dev)
|
||||
ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
|
||||
if (ret)
|
||||
DRM_ERROR("l3 parity sysfs setup failed\n");
|
||||
|
||||
if (NUM_L3_SLICES(dev) > 1) {
|
||||
ret = device_create_bin_file(&dev->primary->kdev,
|
||||
&dpf_attrs_1);
|
||||
if (ret)
|
||||
DRM_ERROR("l3 parity slice 1 setup failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
@@ -548,6 +567,7 @@ void i915_teardown_sysfs(struct drm_device *dev)
|
||||
sysfs_remove_files(&dev->primary->kdev.kobj, vlv_attrs);
|
||||
else
|
||||
sysfs_remove_files(&dev->primary->kdev.kobj, gen6_attrs);
|
||||
device_remove_bin_file(&dev->primary->kdev, &dpf_attrs_1);
|
||||
device_remove_bin_file(&dev->primary->kdev, &dpf_attrs);
|
||||
#ifdef CONFIG_PM
|
||||
sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
|
||||
|
Referência em uma nova issue
Block a user