提交 db7f06d4 编写于 作者: D Dave Airlie

Merge tag 'drm-intel-fixes-2018-09-11' of...

Merge tag 'drm-intel-fixes-2018-09-11' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes

This contains a regression fix for video playbacks on gen 2 hardware,
a IPS timeout error suppression on Broadwell and GVT bucked with
"Most critical one is to fix KVM's mm reference when we access guest memory,
issue was raised by Linus [1], and another one with virtual opregion fix."

[1] - https://lists.freedesktop.org/archives/intel-gvt-dev/2018-August/004130.htmlSigned-off-by: NDave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180911223229.GA30328@intel.com
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mmu_context.h> #include <linux/mmu_context.h>
#include <linux/sched/mm.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
...@@ -1792,16 +1793,21 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa, ...@@ -1792,16 +1793,21 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
info = (struct kvmgt_guest_info *)handle; info = (struct kvmgt_guest_info *)handle;
kvm = info->kvm; kvm = info->kvm;
if (kthread) if (kthread) {
if (!mmget_not_zero(kvm->mm))
return -EFAULT;
use_mm(kvm->mm); use_mm(kvm->mm);
}
idx = srcu_read_lock(&kvm->srcu); idx = srcu_read_lock(&kvm->srcu);
ret = write ? kvm_write_guest(kvm, gpa, buf, len) : ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
kvm_read_guest(kvm, gpa, buf, len); kvm_read_guest(kvm, gpa, buf, len);
srcu_read_unlock(&kvm->srcu, idx); srcu_read_unlock(&kvm->srcu, idx);
if (kthread) if (kthread) {
unuse_mm(kvm->mm); unuse_mm(kvm->mm);
mmput(kvm->mm);
}
return ret; return ret;
} }
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
#define DEVICE_TYPE_EFP3 0x20 #define DEVICE_TYPE_EFP3 0x20
#define DEVICE_TYPE_EFP4 0x10 #define DEVICE_TYPE_EFP4 0x10
#define DEV_SIZE 38
struct opregion_header { struct opregion_header {
u8 signature[16]; u8 signature[16];
u32 size; u32 size;
...@@ -63,6 +61,10 @@ struct bdb_data_header { ...@@ -63,6 +61,10 @@ struct bdb_data_header {
u16 size; /* data size */ u16 size; /* data size */
} __packed; } __packed;
/* For supporting windows guest with opregion, here hardcode the emulated
* bdb header version as '186', and the corresponding child_device_config
* length should be '33' but not '38'.
*/
struct efp_child_device_config { struct efp_child_device_config {
u16 handle; u16 handle;
u16 device_type; u16 device_type;
...@@ -109,12 +111,6 @@ struct efp_child_device_config { ...@@ -109,12 +111,6 @@ struct efp_child_device_config {
u8 mipi_bridge_type; /* 171 */ u8 mipi_bridge_type; /* 171 */
u16 device_class_ext; u16 device_class_ext;
u8 dvo_function; u8 dvo_function;
u8 dp_usb_type_c:1; /* 195 */
u8 skip6:7;
u8 dp_usb_type_c_2x_gpio_index; /* 195 */
u16 dp_usb_type_c_2x_gpio_pin; /* 195 */
u8 iboost_dp:4; /* 196 */
u8 iboost_hdmi:4; /* 196 */
} __packed; } __packed;
struct vbt { struct vbt {
...@@ -155,7 +151,7 @@ static void virt_vbt_generation(struct vbt *v) ...@@ -155,7 +151,7 @@ static void virt_vbt_generation(struct vbt *v)
v->header.bdb_offset = offsetof(struct vbt, bdb_header); v->header.bdb_offset = offsetof(struct vbt, bdb_header);
strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK"); strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK");
v->bdb_header.version = 186; /* child_dev_size = 38 */ v->bdb_header.version = 186; /* child_dev_size = 33 */
v->bdb_header.header_size = sizeof(v->bdb_header); v->bdb_header.header_size = sizeof(v->bdb_header);
v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header) v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header)
...@@ -169,11 +165,13 @@ static void virt_vbt_generation(struct vbt *v) ...@@ -169,11 +165,13 @@ static void virt_vbt_generation(struct vbt *v)
/* child device */ /* child device */
num_child = 4; /* each port has one child */ num_child = 4; /* each port has one child */
v->general_definitions.child_dev_size =
sizeof(struct efp_child_device_config);
v->general_definitions_header.id = BDB_GENERAL_DEFINITIONS; v->general_definitions_header.id = BDB_GENERAL_DEFINITIONS;
/* size will include child devices */ /* size will include child devices */
v->general_definitions_header.size = v->general_definitions_header.size =
sizeof(struct bdb_general_definitions) + num_child * DEV_SIZE; sizeof(struct bdb_general_definitions) +
v->general_definitions.child_dev_size = DEV_SIZE; num_child * v->general_definitions.child_dev_size;
/* portA */ /* portA */
v->child0.handle = DEVICE_TYPE_EFP1; v->child0.handle = DEVICE_TYPE_EFP1;
......
...@@ -5079,10 +5079,14 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state) ...@@ -5079,10 +5079,14 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state)
mutex_lock(&dev_priv->pcu_lock); mutex_lock(&dev_priv->pcu_lock);
WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
mutex_unlock(&dev_priv->pcu_lock); mutex_unlock(&dev_priv->pcu_lock);
/* wait for pcode to finish disabling IPS, which may take up to 42ms */ /*
* Wait for PCODE to finish disabling IPS. The BSpec specified
* 42ms timeout value leads to occasional timeouts so use 100ms
* instead.
*/
if (intel_wait_for_register(dev_priv, if (intel_wait_for_register(dev_priv,
IPS_CTL, IPS_ENABLE, 0, IPS_CTL, IPS_ENABLE, 0,
42)) 100))
DRM_ERROR("Timed out waiting for IPS disable\n"); DRM_ERROR("Timed out waiting for IPS disable\n");
} else { } else {
I915_WRITE(IPS_CTL, 0); I915_WRITE(IPS_CTL, 0);
......
...@@ -181,8 +181,9 @@ struct intel_overlay { ...@@ -181,8 +181,9 @@ struct intel_overlay {
u32 brightness, contrast, saturation; u32 brightness, contrast, saturation;
u32 old_xscale, old_yscale; u32 old_xscale, old_yscale;
/* register access */ /* register access */
u32 flip_addr;
struct drm_i915_gem_object *reg_bo; struct drm_i915_gem_object *reg_bo;
struct overlay_registers __iomem *regs;
u32 flip_addr;
/* flip handling */ /* flip handling */
struct i915_gem_active last_flip; struct i915_gem_active last_flip;
}; };
...@@ -210,29 +211,6 @@ static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv, ...@@ -210,29 +211,6 @@ static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv,
PCI_DEVFN(0, 0), I830_CLOCK_GATE, val); PCI_DEVFN(0, 0), I830_CLOCK_GATE, val);
} }
static struct overlay_registers __iomem *
intel_overlay_map_regs(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct overlay_registers __iomem *regs;
if (OVERLAY_NEEDS_PHYSICAL(dev_priv))
regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
else
regs = io_mapping_map_wc(&dev_priv->ggtt.iomap,
overlay->flip_addr,
PAGE_SIZE);
return regs;
}
static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
struct overlay_registers __iomem *regs)
{
if (!OVERLAY_NEEDS_PHYSICAL(overlay->i915))
io_mapping_unmap(regs);
}
static void intel_overlay_submit_request(struct intel_overlay *overlay, static void intel_overlay_submit_request(struct intel_overlay *overlay,
struct i915_request *rq, struct i915_request *rq,
i915_gem_retire_fn retire) i915_gem_retire_fn retire)
...@@ -784,13 +762,13 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ...@@ -784,13 +762,13 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
struct drm_i915_gem_object *new_bo, struct drm_i915_gem_object *new_bo,
struct put_image_params *params) struct put_image_params *params)
{ {
int ret, tmp_width; struct overlay_registers __iomem *regs = overlay->regs;
struct overlay_registers __iomem *regs;
bool scale_changed = false;
struct drm_i915_private *dev_priv = overlay->i915; struct drm_i915_private *dev_priv = overlay->i915;
u32 swidth, swidthsw, sheight, ostride; u32 swidth, swidthsw, sheight, ostride;
enum pipe pipe = overlay->crtc->pipe; enum pipe pipe = overlay->crtc->pipe;
bool scale_changed = false;
struct i915_vma *vma; struct i915_vma *vma;
int ret, tmp_width;
lockdep_assert_held(&dev_priv->drm.struct_mutex); lockdep_assert_held(&dev_priv->drm.struct_mutex);
WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
...@@ -815,30 +793,19 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ...@@ -815,30 +793,19 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
if (!overlay->active) { if (!overlay->active) {
u32 oconfig; u32 oconfig;
regs = intel_overlay_map_regs(overlay);
if (!regs) {
ret = -ENOMEM;
goto out_unpin;
}
oconfig = OCONF_CC_OUT_8BIT; oconfig = OCONF_CC_OUT_8BIT;
if (IS_GEN4(dev_priv)) if (IS_GEN4(dev_priv))
oconfig |= OCONF_CSC_MODE_BT709; oconfig |= OCONF_CSC_MODE_BT709;
oconfig |= pipe == 0 ? oconfig |= pipe == 0 ?
OCONF_PIPE_A : OCONF_PIPE_B; OCONF_PIPE_A : OCONF_PIPE_B;
iowrite32(oconfig, &regs->OCONFIG); iowrite32(oconfig, &regs->OCONFIG);
intel_overlay_unmap_regs(overlay, regs);
ret = intel_overlay_on(overlay); ret = intel_overlay_on(overlay);
if (ret != 0) if (ret != 0)
goto out_unpin; goto out_unpin;
} }
regs = intel_overlay_map_regs(overlay);
if (!regs) {
ret = -ENOMEM;
goto out_unpin;
}
iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS); iowrite32((params->dst_y << 16) | params->dst_x, &regs->DWINPOS);
iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ); iowrite32((params->dst_h << 16) | params->dst_w, &regs->DWINSZ);
...@@ -882,8 +849,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ...@@ -882,8 +849,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
iowrite32(overlay_cmd_reg(params), &regs->OCMD); iowrite32(overlay_cmd_reg(params), &regs->OCMD);
intel_overlay_unmap_regs(overlay, regs);
ret = intel_overlay_continue(overlay, vma, scale_changed); ret = intel_overlay_continue(overlay, vma, scale_changed);
if (ret) if (ret)
goto out_unpin; goto out_unpin;
...@@ -901,7 +866,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, ...@@ -901,7 +866,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
int intel_overlay_switch_off(struct intel_overlay *overlay) int intel_overlay_switch_off(struct intel_overlay *overlay)
{ {
struct drm_i915_private *dev_priv = overlay->i915; struct drm_i915_private *dev_priv = overlay->i915;
struct overlay_registers __iomem *regs;
int ret; int ret;
lockdep_assert_held(&dev_priv->drm.struct_mutex); lockdep_assert_held(&dev_priv->drm.struct_mutex);
...@@ -918,9 +882,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) ...@@ -918,9 +882,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
if (ret != 0) if (ret != 0)
return ret; return ret;
regs = intel_overlay_map_regs(overlay); iowrite32(0, &overlay->regs->OCMD);
iowrite32(0, &regs->OCMD);
intel_overlay_unmap_regs(overlay, regs);
return intel_overlay_off(overlay); return intel_overlay_off(overlay);
} }
...@@ -1305,7 +1267,6 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, ...@@ -1305,7 +1267,6 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
struct drm_intel_overlay_attrs *attrs = data; struct drm_intel_overlay_attrs *attrs = data;
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_overlay *overlay; struct intel_overlay *overlay;
struct overlay_registers __iomem *regs;
int ret; int ret;
overlay = dev_priv->overlay; overlay = dev_priv->overlay;
...@@ -1345,15 +1306,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, ...@@ -1345,15 +1306,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
overlay->contrast = attrs->contrast; overlay->contrast = attrs->contrast;
overlay->saturation = attrs->saturation; overlay->saturation = attrs->saturation;
regs = intel_overlay_map_regs(overlay); update_reg_attrs(overlay, overlay->regs);
if (!regs) {
ret = -ENOMEM;
goto out_unlock;
}
update_reg_attrs(overlay, regs);
intel_overlay_unmap_regs(overlay, regs);
if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) {
if (IS_GEN2(dev_priv)) if (IS_GEN2(dev_priv))
...@@ -1386,12 +1339,47 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, ...@@ -1386,12 +1339,47 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
return ret; return ret;
} }
static int get_registers(struct intel_overlay *overlay, bool use_phys)
{
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
int err;
obj = i915_gem_object_create_stolen(overlay->i915, PAGE_SIZE);
if (obj == NULL)
obj = i915_gem_object_create_internal(overlay->i915, PAGE_SIZE);
if (IS_ERR(obj))
return PTR_ERR(obj);
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
if (IS_ERR(vma)) {
err = PTR_ERR(vma);
goto err_put_bo;
}
if (use_phys)
overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl);
else
overlay->flip_addr = i915_ggtt_offset(vma);
overlay->regs = i915_vma_pin_iomap(vma);
i915_vma_unpin(vma);
if (IS_ERR(overlay->regs)) {
err = PTR_ERR(overlay->regs);
goto err_put_bo;
}
overlay->reg_bo = obj;
return 0;
err_put_bo:
i915_gem_object_put(obj);
return err;
}
void intel_setup_overlay(struct drm_i915_private *dev_priv) void intel_setup_overlay(struct drm_i915_private *dev_priv)
{ {
struct intel_overlay *overlay; struct intel_overlay *overlay;
struct drm_i915_gem_object *reg_bo;
struct overlay_registers __iomem *regs;
struct i915_vma *vma = NULL;
int ret; int ret;
if (!HAS_OVERLAY(dev_priv)) if (!HAS_OVERLAY(dev_priv))
...@@ -1401,46 +1389,8 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv) ...@@ -1401,46 +1389,8 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
if (!overlay) if (!overlay)
return; return;
mutex_lock(&dev_priv->drm.struct_mutex);
if (WARN_ON(dev_priv->overlay))
goto out_free;
overlay->i915 = dev_priv; overlay->i915 = dev_priv;
reg_bo = NULL;
if (!OVERLAY_NEEDS_PHYSICAL(dev_priv))
reg_bo = i915_gem_object_create_stolen(dev_priv, PAGE_SIZE);
if (reg_bo == NULL)
reg_bo = i915_gem_object_create(dev_priv, PAGE_SIZE);
if (IS_ERR(reg_bo))
goto out_free;
overlay->reg_bo = reg_bo;
if (OVERLAY_NEEDS_PHYSICAL(dev_priv)) {
ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE);
if (ret) {
DRM_ERROR("failed to attach phys overlay regs\n");
goto out_free_bo;
}
overlay->flip_addr = reg_bo->phys_handle->busaddr;
} else {
vma = i915_gem_object_ggtt_pin(reg_bo, NULL,
0, PAGE_SIZE, PIN_MAPPABLE);
if (IS_ERR(vma)) {
DRM_ERROR("failed to pin overlay register bo\n");
ret = PTR_ERR(vma);
goto out_free_bo;
}
overlay->flip_addr = i915_ggtt_offset(vma);
ret = i915_gem_object_set_to_gtt_domain(reg_bo, true);
if (ret) {
DRM_ERROR("failed to move overlay register bo into the GTT\n");
goto out_unpin_bo;
}
}
/* init all values */
overlay->color_key = 0x0101fe; overlay->color_key = 0x0101fe;
overlay->color_key_enabled = true; overlay->color_key_enabled = true;
overlay->brightness = -19; overlay->brightness = -19;
...@@ -1449,44 +1399,51 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv) ...@@ -1449,44 +1399,51 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv)
init_request_active(&overlay->last_flip, NULL); init_request_active(&overlay->last_flip, NULL);
regs = intel_overlay_map_regs(overlay); mutex_lock(&dev_priv->drm.struct_mutex);
if (!regs)
goto out_unpin_bo;
memset_io(regs, 0, sizeof(struct overlay_registers)); ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
update_polyphase_filter(regs); if (ret)
update_reg_attrs(overlay, regs); goto out_free;
intel_overlay_unmap_regs(overlay, regs); ret = i915_gem_object_set_to_gtt_domain(overlay->reg_bo, true);
if (ret)
goto out_reg_bo;
dev_priv->overlay = overlay;
mutex_unlock(&dev_priv->drm.struct_mutex); mutex_unlock(&dev_priv->drm.struct_mutex);
DRM_INFO("initialized overlay support\n");
memset_io(overlay->regs, 0, sizeof(struct overlay_registers));
update_polyphase_filter(overlay->regs);
update_reg_attrs(overlay, overlay->regs);
dev_priv->overlay = overlay;
DRM_INFO("Initialized overlay support.\n");
return; return;
out_unpin_bo: out_reg_bo:
if (vma) i915_gem_object_put(overlay->reg_bo);
i915_vma_unpin(vma);
out_free_bo:
i915_gem_object_put(reg_bo);
out_free: out_free:
mutex_unlock(&dev_priv->drm.struct_mutex); mutex_unlock(&dev_priv->drm.struct_mutex);
kfree(overlay); kfree(overlay);
return;
} }
void intel_cleanup_overlay(struct drm_i915_private *dev_priv) void intel_cleanup_overlay(struct drm_i915_private *dev_priv)
{ {
if (!dev_priv->overlay) struct intel_overlay *overlay;
overlay = fetch_and_zero(&dev_priv->overlay);
if (!overlay)
return; return;
/* The bo's should be free'd by the generic code already. /*
* The bo's should be free'd by the generic code already.
* Furthermore modesetting teardown happens beforehand so the * Furthermore modesetting teardown happens beforehand so the
* hardware should be off already */ * hardware should be off already.
WARN_ON(dev_priv->overlay->active); */
WARN_ON(overlay->active);
i915_gem_object_put(dev_priv->overlay->reg_bo); i915_gem_object_put(overlay->reg_bo);
kfree(dev_priv->overlay);
kfree(overlay);
} }
#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
...@@ -1498,37 +1455,11 @@ struct intel_overlay_error_state { ...@@ -1498,37 +1455,11 @@ struct intel_overlay_error_state {
u32 isr; u32 isr;
}; };
static struct overlay_registers __iomem *
intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->i915;
struct overlay_registers __iomem *regs;
if (OVERLAY_NEEDS_PHYSICAL(dev_priv))
/* Cast to make sparse happy, but it's wc memory anyway, so
* equivalent to the wc io mapping on X86. */
regs = (struct overlay_registers __iomem *)
overlay->reg_bo->phys_handle->vaddr;
else
regs = io_mapping_map_atomic_wc(&dev_priv->ggtt.iomap,
overlay->flip_addr);
return regs;
}
static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay,
struct overlay_registers __iomem *regs)
{
if (!OVERLAY_NEEDS_PHYSICAL(overlay->i915))
io_mapping_unmap_atomic(regs);
}
struct intel_overlay_error_state * struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
{ {
struct intel_overlay *overlay = dev_priv->overlay; struct intel_overlay *overlay = dev_priv->overlay;
struct intel_overlay_error_state *error; struct intel_overlay_error_state *error;
struct overlay_registers __iomem *regs;
if (!overlay || !overlay->active) if (!overlay || !overlay->active)
return NULL; return NULL;
...@@ -1541,18 +1472,9 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) ...@@ -1541,18 +1472,9 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv)
error->isr = I915_READ(ISR); error->isr = I915_READ(ISR);
error->base = overlay->flip_addr; error->base = overlay->flip_addr;
regs = intel_overlay_map_regs_atomic(overlay); memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs));
if (!regs)
goto err;
memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
intel_overlay_unmap_regs_atomic(overlay, regs);
return error; return error;
err:
kfree(error);
return NULL;
} }
void void
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册