From: Greg Kroah-Hartman Date: Sun, 9 Apr 2017 08:25:05 +0000 (+0200) Subject: 4.10-stable patches X-Git-Tag: v4.4.61~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9b9f2d4d07ca14cf1f768b8ac358d9ee5d4de50b;p=thirdparty%2Fkernel%2Fstable-queue.git 4.10-stable patches added patches: drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch drm-vmwgfx-remove-getparam-error-message.patch drm-vmwgfx-type-check-lookups-of-fence-objects.patch pci-thunder-pem-add-legacy-firmware-support-for-cavium-thunderx-host-controller.patch pci-thunder-pem-fix-legacy-firmware-pem-specific-resources.patch --- diff --git a/queue-4.10/drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch b/queue-4.10/drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch new file mode 100644 index 00000000000..86e6d57a8a0 --- /dev/null +++ b/queue-4.10/drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch @@ -0,0 +1,172 @@ +From fe25deb7737ce6c0879ccf79c99fa1221d428bf2 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Mon, 27 Mar 2017 11:21:25 +0200 +Subject: drm/ttm, drm/vmwgfx: Relax permission checking when opening surfaces + +From: Thomas Hellstrom + +commit fe25deb7737ce6c0879ccf79c99fa1221d428bf2 upstream. + +Previously, when a surface was opened using a legacy (non prime) handle, +it was verified to have been created by a client in the same master realm. +Relax this so that opening is also allowed recursively if the client +already has the surface open. + +This works around a regression in svga mesa where opening of a shared +surface is used recursively to obtain surface information. + +Signed-off-by: Thomas Hellstrom +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/ttm/ttm_object.c | 10 +++++++--- + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 6 ++---- + drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 4 ++-- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 +++++++++------------- + include/drm/ttm/ttm_object.h | 5 ++++- + 5 files changed, 24 insertions(+), 23 deletions(-) + +--- a/drivers/gpu/drm/ttm/ttm_object.c ++++ b/drivers/gpu/drm/ttm/ttm_object.c +@@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_obje + if (unlikely(ret != 0)) + goto out_err0; + +- ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ++ ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); + if (unlikely(ret != 0)) + goto out_err1; + +@@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists); + + int ttm_ref_object_add(struct ttm_object_file *tfile, + struct ttm_base_object *base, +- enum ttm_ref_type ref_type, bool *existed) ++ enum ttm_ref_type ref_type, bool *existed, ++ bool require_existed) + { + struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; + struct ttm_ref_object *ref; +@@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object + } + + rcu_read_unlock(); ++ if (require_existed) ++ return -EPERM; ++ + ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), + false, false); + if (unlikely(ret != 0)) +@@ -635,7 +639,7 @@ int ttm_prime_fd_to_handle(struct ttm_ob + prime = (struct ttm_prime_object *) dma_buf->priv; + base = &prime->base; + *handle = base->hash.key; +- ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ++ ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); + + dma_buf_put(dma_buf); + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -1075,10 +1075,8 @@ int vmw_fence_event_ioctl(struct drm_dev + (void) vmw_fence_obj_reference(fence); + + if (user_fence_rep != NULL) { +- bool existed; +- +- ret = ttm_ref_object_add(tfile, base, +- TTM_REF_USAGE, &existed); ++ ret = ttm_ref_object_add(vmw_fp->tfile, base, ++ TTM_REF_USAGE, NULL, false); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed to reference a fence " + "object.\n"); +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +@@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab( + return ret; + + ret = ttm_ref_object_add(tfile, &user_bo->prime.base, +- TTM_REF_SYNCCPU_WRITE, &existed); ++ TTM_REF_SYNCCPU_WRITE, &existed, false); + if (ret != 0 || existed) + ttm_bo_synccpu_write_release(&user_bo->dma.base); + +@@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm + + *handle = user_bo->prime.base.hash.key; + return ttm_ref_object_add(tfile, &user_bo->prime.base, +- TTM_REF_USAGE, NULL); ++ TTM_REF_USAGE, NULL, false); + } + + /* +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -891,17 +891,16 @@ vmw_surface_handle_reference(struct vmw_ + uint32_t handle; + struct ttm_base_object *base; + int ret; ++ bool require_exist = false; + + if (handle_type == DRM_VMW_HANDLE_PRIME) { + ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); + if (unlikely(ret != 0)) + return ret; + } else { +- if (unlikely(drm_is_render_client(file_priv))) { +- DRM_ERROR("Render client refused legacy " +- "surface reference.\n"); +- return -EACCES; +- } ++ if (unlikely(drm_is_render_client(file_priv))) ++ require_exist = true; ++ + if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) { + DRM_ERROR("Locked master refused legacy " + "surface reference.\n"); +@@ -929,17 +928,14 @@ vmw_surface_handle_reference(struct vmw_ + + /* + * Make sure the surface creator has the same +- * authenticating master. ++ * authenticating master, or is already registered with us. + */ + if (drm_is_primary_client(file_priv) && +- user_srf->master != file_priv->master) { +- DRM_ERROR("Trying to reference surface outside of" +- " master domain.\n"); +- ret = -EACCES; +- goto out_bad_resource; +- } ++ user_srf->master != file_priv->master) ++ require_exist = true; + +- ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ++ ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, ++ require_exist); + if (unlikely(ret != 0)) { + DRM_ERROR("Could not add a reference to a surface.\n"); + goto out_bad_resource; +--- a/include/drm/ttm/ttm_object.h ++++ b/include/drm/ttm/ttm_object.h +@@ -229,6 +229,8 @@ extern void ttm_base_object_unref(struct + * @ref_type: The type of reference. + * @existed: Upon completion, indicates that an identical reference object + * already existed, and the refcount was upped on that object instead. ++ * @require_existed: Fail with -EPERM if an identical ref object didn't ++ * already exist. + * + * Checks that the base object is shareable and adds a ref object to it. + * +@@ -243,7 +245,8 @@ extern void ttm_base_object_unref(struct + */ + extern int ttm_ref_object_add(struct ttm_object_file *tfile, + struct ttm_base_object *base, +- enum ttm_ref_type ref_type, bool *existed); ++ enum ttm_ref_type ref_type, bool *existed, ++ bool require_existed); + + extern bool ttm_ref_object_exists(struct ttm_object_file *tfile, + struct ttm_base_object *base); diff --git a/queue-4.10/drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch b/queue-4.10/drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch new file mode 100644 index 00000000000..a6b90fd4bce --- /dev/null +++ b/queue-4.10/drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch @@ -0,0 +1,34 @@ +From 63774069d9527a1aeaa4aa20e929ef5e8e9ecc38 Mon Sep 17 00:00:00 2001 +From: Murray McAllister +Date: Mon, 27 Mar 2017 11:15:12 +0200 +Subject: drm/vmwgfx: avoid calling vzalloc with a 0 size in vmw_get_cap_3d_ioctl() + +From: Murray McAllister + +commit 63774069d9527a1aeaa4aa20e929ef5e8e9ecc38 upstream. + +In vmw_get_cap_3d_ioctl(), a user can supply 0 for a size that is +used in vzalloc(). This eventually calls dump_stack() (in warn_alloc()), +which can leak useful addresses to dmesg. + +Add check to avoid a size of 0. + +Signed-off-by: Murray McAllister +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +@@ -186,7 +186,7 @@ int vmw_get_cap_3d_ioctl(struct drm_devi + bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS); + struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); + +- if (unlikely(arg->pad64 != 0)) { ++ if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) { + DRM_ERROR("Illegal GET_3D_CAP argument.\n"); + return -EINVAL; + } diff --git a/queue-4.10/drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch b/queue-4.10/drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch new file mode 100644 index 00000000000..3af83447bf6 --- /dev/null +++ b/queue-4.10/drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch @@ -0,0 +1,39 @@ +From e7e11f99564222d82f0ce84bd521e57d78a6b678 Mon Sep 17 00:00:00 2001 +From: Li Qiang +Date: Mon, 27 Mar 2017 20:10:53 -0700 +Subject: drm/vmwgfx: fix integer overflow in vmw_surface_define_ioctl() + +From: Li Qiang + +commit e7e11f99564222d82f0ce84bd521e57d78a6b678 upstream. + +In vmw_surface_define_ioctl(), the 'num_sizes' is the sum of the +'req->mip_levels' array. This array can be assigned any value from +the user space. As both the 'num_sizes' and the array is uint32_t, +it is easy to make 'num_sizes' overflow. The later 'mip_levels' is +used as the loop count. This can lead an oob write. Add the check of +'req->mip_levels' to avoid this. + +Signed-off-by: Li Qiang +Reviewed-by: Thomas Hellstrom +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -713,8 +713,11 @@ int vmw_surface_define_ioctl(struct drm_ + 128; + + num_sizes = 0; +- for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) ++ for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { ++ if (req->mip_levels[i] > DRM_VMW_MAX_MIP_LEVELS) ++ return -EINVAL; + num_sizes += req->mip_levels[i]; ++ } + + if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || + num_sizes == 0) diff --git a/queue-4.10/drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch b/queue-4.10/drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch new file mode 100644 index 00000000000..9eead97d9a0 --- /dev/null +++ b/queue-4.10/drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch @@ -0,0 +1,36 @@ +From 36274ab8c596f1240c606bb514da329add2a1bcd Mon Sep 17 00:00:00 2001 +From: Murray McAllister +Date: Mon, 27 Mar 2017 11:12:53 +0200 +Subject: drm/vmwgfx: NULL pointer dereference in vmw_surface_define_ioctl() + +From: Murray McAllister + +commit 36274ab8c596f1240c606bb514da329add2a1bcd upstream. + +Before memory allocations vmw_surface_define_ioctl() checks the +upper-bounds of a user-supplied size, but does not check if the +supplied size is 0. + +Add check to avoid NULL pointer dereferences. + +Signed-off-by: Murray McAllister +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +@@ -716,8 +716,8 @@ int vmw_surface_define_ioctl(struct drm_ + for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) + num_sizes += req->mip_levels[i]; + +- if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * +- DRM_VMW_MAX_MIP_LEVELS) ++ if (num_sizes > DRM_VMW_MAX_SURFACE_FACES * DRM_VMW_MAX_MIP_LEVELS || ++ num_sizes == 0) + return -EINVAL; + + size = vmw_user_surface_size + 128 + diff --git a/queue-4.10/drm-vmwgfx-remove-getparam-error-message.patch b/queue-4.10/drm-vmwgfx-remove-getparam-error-message.patch new file mode 100644 index 00000000000..afba4ffdbb7 --- /dev/null +++ b/queue-4.10/drm-vmwgfx-remove-getparam-error-message.patch @@ -0,0 +1,33 @@ +From 53e16798b0864464c5444a204e1bb93ae246c429 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Mon, 27 Mar 2017 13:06:05 +0200 +Subject: drm/vmwgfx: Remove getparam error message + +From: Thomas Hellstrom + +commit 53e16798b0864464c5444a204e1bb93ae246c429 upstream. + +The mesa winsys sometimes uses unimplemented parameter requests to +check for features. Remove the error message to avoid bloating the +kernel log. + +Signed-off-by: Thomas Hellstrom +Reviewed-by: Brian Paul +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +@@ -114,8 +114,6 @@ int vmw_getparam_ioctl(struct drm_device + param->value = dev_priv->has_dx; + break; + default: +- DRM_ERROR("Illegal vmwgfx get param request: %d\n", +- param->param); + return -EINVAL; + } + diff --git a/queue-4.10/drm-vmwgfx-type-check-lookups-of-fence-objects.patch b/queue-4.10/drm-vmwgfx-type-check-lookups-of-fence-objects.patch new file mode 100644 index 00000000000..48852f6690d --- /dev/null +++ b/queue-4.10/drm-vmwgfx-type-check-lookups-of-fence-objects.patch @@ -0,0 +1,157 @@ +From f7652afa8eadb416b23eb57dec6f158529942041 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Mon, 27 Mar 2017 11:09:08 +0200 +Subject: drm/vmwgfx: Type-check lookups of fence objects + +From: Thomas Hellstrom + +commit f7652afa8eadb416b23eb57dec6f158529942041 upstream. + +A malicious caller could otherwise hand over handles to other objects +causing all sorts of interesting problems. + +Testing done: Ran a Fedora 25 desktop using both Xorg and +gnome-shell/Wayland. + +Signed-off-by: Thomas Hellstrom +Reviewed-by: Sinclair Yeh +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 75 ++++++++++++++++++++++------------ + 1 file changed, 49 insertions(+), 26 deletions(-) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +@@ -538,7 +538,7 @@ int vmw_fence_create(struct vmw_fence_ma + struct vmw_fence_obj **p_fence) + { + struct vmw_fence_obj *fence; +- int ret; ++ int ret; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (unlikely(fence == NULL)) +@@ -701,6 +701,41 @@ void vmw_fence_fifo_up(struct vmw_fence_ + } + + ++/** ++ * vmw_fence_obj_lookup - Look up a user-space fence object ++ * ++ * @tfile: A struct ttm_object_file identifying the caller. ++ * @handle: A handle identifying the fence object. ++ * @return: A struct vmw_user_fence base ttm object on success or ++ * an error pointer on failure. ++ * ++ * The fence object is looked up and type-checked. The caller needs ++ * to have opened the fence object first, but since that happens on ++ * creation and fence objects aren't shareable, that's not an ++ * issue currently. ++ */ ++static struct ttm_base_object * ++vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle) ++{ ++ struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle); ++ ++ if (!base) { ++ pr_err("Invalid fence object handle 0x%08lx.\n", ++ (unsigned long)handle); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (base->refcount_release != vmw_user_fence_base_release) { ++ pr_err("Invalid fence object handle 0x%08lx.\n", ++ (unsigned long)handle); ++ ttm_base_object_unref(&base); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ return base; ++} ++ ++ + int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) + { +@@ -726,13 +761,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_ + arg->kernel_cookie = jiffies + wait_timeout; + } + +- base = ttm_base_object_lookup(tfile, arg->handle); +- if (unlikely(base == NULL)) { +- printk(KERN_ERR "Wait invalid fence object handle " +- "0x%08lx.\n", +- (unsigned long)arg->handle); +- return -EINVAL; +- } ++ base = vmw_fence_obj_lookup(tfile, arg->handle); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + + fence = &(container_of(base, struct vmw_user_fence, base)->fence); + +@@ -771,13 +802,9 @@ int vmw_fence_obj_signaled_ioctl(struct + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_private *dev_priv = vmw_priv(dev); + +- base = ttm_base_object_lookup(tfile, arg->handle); +- if (unlikely(base == NULL)) { +- printk(KERN_ERR "Fence signaled invalid fence object handle " +- "0x%08lx.\n", +- (unsigned long)arg->handle); +- return -EINVAL; +- } ++ base = vmw_fence_obj_lookup(tfile, arg->handle); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + + fence = &(container_of(base, struct vmw_user_fence, base)->fence); + fman = fman_from_fence(fence); +@@ -1024,6 +1051,7 @@ int vmw_fence_event_ioctl(struct drm_dev + (struct drm_vmw_fence_event_arg *) data; + struct vmw_fence_obj *fence = NULL; + struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); ++ struct ttm_object_file *tfile = vmw_fp->tfile; + struct drm_vmw_fence_rep __user *user_fence_rep = + (struct drm_vmw_fence_rep __user *)(unsigned long) + arg->fence_rep; +@@ -1037,15 +1065,11 @@ int vmw_fence_event_ioctl(struct drm_dev + */ + if (arg->handle) { + struct ttm_base_object *base = +- ttm_base_object_lookup_for_ref(dev_priv->tdev, +- arg->handle); ++ vmw_fence_obj_lookup(tfile, arg->handle); ++ ++ if (IS_ERR(base)) ++ return PTR_ERR(base); + +- if (unlikely(base == NULL)) { +- DRM_ERROR("Fence event invalid fence object handle " +- "0x%08lx.\n", +- (unsigned long)arg->handle); +- return -EINVAL; +- } + fence = &(container_of(base, struct vmw_user_fence, + base)->fence); + (void) vmw_fence_obj_reference(fence); +@@ -1053,7 +1077,7 @@ int vmw_fence_event_ioctl(struct drm_dev + if (user_fence_rep != NULL) { + bool existed; + +- ret = ttm_ref_object_add(vmw_fp->tfile, base, ++ ret = ttm_ref_object_add(tfile, base, + TTM_REF_USAGE, &existed); + if (unlikely(ret != 0)) { + DRM_ERROR("Failed to reference a fence " +@@ -1097,8 +1121,7 @@ int vmw_fence_event_ioctl(struct drm_dev + return 0; + out_no_create: + if (user_fence_rep != NULL) +- ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, +- handle, TTM_REF_USAGE); ++ ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE); + out_no_ref_obj: + vmw_fence_obj_unreference(&fence); + return ret; diff --git a/queue-4.10/pci-thunder-pem-add-legacy-firmware-support-for-cavium-thunderx-host-controller.patch b/queue-4.10/pci-thunder-pem-add-legacy-firmware-support-for-cavium-thunderx-host-controller.patch new file mode 100644 index 00000000000..af73fe088a4 --- /dev/null +++ b/queue-4.10/pci-thunder-pem-add-legacy-firmware-support-for-cavium-thunderx-host-controller.patch @@ -0,0 +1,109 @@ +From 9abb27c7594a62bbf6385e20b7f5a90b4eceae2f Mon Sep 17 00:00:00 2001 +From: Tomasz Nowicki +Date: Thu, 23 Mar 2017 17:10:16 -0500 +Subject: PCI: thunder-pem: Add legacy firmware support for Cavium ThunderX host controller + +From: Tomasz Nowicki + +commit 9abb27c7594a62bbf6385e20b7f5a90b4eceae2f upstream. + +During early days of PCI quirks support, ThunderX firmware did not provide +PNP0c02 node with PCI configuration space and PEM-specific register ranges. +This means that for legacy FW we are not reserving these resources and +cannot gather PEM-specific resources for further PEM initialization. + +To support already deployed legacy FW, calculate PEM-specific ranges and +provide resources reservation as fallback scenario into PEM driver when we +could not gather PEM reg base from ACPI tables. + +Tested-by: Robert Richter +Signed-off-by: Tomasz Nowicki +Signed-off-by: Vadim Lomovtsev +Signed-off-by: Bjorn Helgaas +Acked-by: Robert Richter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/host/pci-thunder-pem.c | 56 +++++++++++++++++++++++++++++++++++-- + 1 file changed, 54 insertions(+), 2 deletions(-) + +--- a/drivers/pci/host/pci-thunder-pem.c ++++ b/drivers/pci/host/pci-thunder-pem.c +@@ -14,6 +14,7 @@ + * Copyright (C) 2015 - 2016 Cavium, Inc. + */ + ++#include + #include + #include + #include +@@ -319,6 +320,50 @@ static int thunder_pem_init(struct devic + + #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS) + ++#define PEM_RES_BASE 0x87e0c0000000UL ++#define PEM_NODE_MASK GENMASK(45, 44) ++#define PEM_INDX_MASK GENMASK(26, 24) ++#define PEM_MIN_DOM_IN_NODE 4 ++#define PEM_MAX_DOM_IN_NODE 10 ++ ++static void thunder_pem_reserve_range(struct device *dev, int seg, ++ struct resource *r) ++{ ++ resource_size_t start = r->start, end = r->end; ++ struct resource *res; ++ const char *regionid; ++ ++ regionid = kasprintf(GFP_KERNEL, "PEM RC:%d", seg); ++ if (!regionid) ++ return; ++ ++ res = request_mem_region(start, end - start + 1, regionid); ++ if (res) ++ res->flags &= ~IORESOURCE_BUSY; ++ else ++ kfree(regionid); ++ ++ dev_info(dev, "%pR %s reserved\n", r, ++ res ? "has been" : "could not be"); ++} ++ ++static void thunder_pem_legacy_fw(struct acpi_pci_root *root, ++ struct resource *res_pem) ++{ ++ int node = acpi_get_node(root->device->handle); ++ int index; ++ ++ if (node == NUMA_NO_NODE) ++ node = 0; ++ ++ index = root->segment - PEM_MIN_DOM_IN_NODE; ++ index -= node * PEM_MAX_DOM_IN_NODE; ++ res_pem->start = PEM_RES_BASE | FIELD_PREP(PEM_NODE_MASK, node) | ++ FIELD_PREP(PEM_INDX_MASK, index); ++ res_pem->end = res_pem->start + SZ_16M - 1; ++ res_pem->flags = IORESOURCE_MEM; ++} ++ + static int thunder_pem_acpi_init(struct pci_config_window *cfg) + { + struct device *dev = cfg->parent; +@@ -332,9 +377,16 @@ static int thunder_pem_acpi_init(struct + return -ENOMEM; + + ret = acpi_get_rc_resources(dev, "CAVA02B", root->segment, res_pem); ++ ++ /* ++ * If we fail to gather resources it means that we run with old ++ * FW where we need to calculate PEM-specific resources manually. ++ */ + if (ret) { +- dev_err(dev, "can't get rc base address\n"); +- return ret; ++ thunder_pem_legacy_fw(root, res_pem); ++ /* Reserve PEM-specific resources and PCI configuration space */ ++ thunder_pem_reserve_range(dev, root->segment, res_pem); ++ thunder_pem_reserve_range(dev, root->segment, &cfg->res); + } + + return thunder_pem_init(dev, cfg, res_pem); diff --git a/queue-4.10/pci-thunder-pem-fix-legacy-firmware-pem-specific-resources.patch b/queue-4.10/pci-thunder-pem-fix-legacy-firmware-pem-specific-resources.patch new file mode 100644 index 00000000000..e7376764850 --- /dev/null +++ b/queue-4.10/pci-thunder-pem-fix-legacy-firmware-pem-specific-resources.patch @@ -0,0 +1,57 @@ +From feb199ebef488a9f2c3550fb10524f3dac9d8abe Mon Sep 17 00:00:00 2001 +From: Tomasz Nowicki +Date: Fri, 31 Mar 2017 17:06:44 +0200 +Subject: PCI: thunder-pem: Fix legacy firmware PEM-specific resources + +From: Tomasz Nowicki + +commit feb199ebef488a9f2c3550fb10524f3dac9d8abe upstream. + +SZ_16M PEM resource size includes PEM-specific register and its children +resources. Reservation of the whole SZ_16M range leads to child device +driver failure when pcieport driver is requesting resources: + + pcieport 0004:1f:00.0: can't enable device: BAR 0 [mem 0x87e0c0f00000-0x87e0c0ffffff 64bit] not claimed + +So we cannot reserve full 16M here and instead we want to reserve +PEM-specific register only which is SZ_64K. + +At the end increase PEM resource to SZ_16M since this is what +thunder_pem_init() call expects for proper initialization. + +Fixes: 9abb27c7594a ("PCI: thunder-pem: Add legacy firmware support for Cavium ThunderX host controller") +Signed-off-by: Tomasz Nowicki +Signed-off-by: Bjorn Helgaas +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/host/pci-thunder-pem.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/pci/host/pci-thunder-pem.c ++++ b/drivers/pci/host/pci-thunder-pem.c +@@ -360,7 +360,6 @@ static void thunder_pem_legacy_fw(struct + index -= node * PEM_MAX_DOM_IN_NODE; + res_pem->start = PEM_RES_BASE | FIELD_PREP(PEM_NODE_MASK, node) | + FIELD_PREP(PEM_INDX_MASK, index); +- res_pem->end = res_pem->start + SZ_16M - 1; + res_pem->flags = IORESOURCE_MEM; + } + +@@ -384,8 +383,15 @@ static int thunder_pem_acpi_init(struct + */ + if (ret) { + thunder_pem_legacy_fw(root, res_pem); +- /* Reserve PEM-specific resources and PCI configuration space */ ++ /* ++ * Reserve 64K size PEM specific resources. The full 16M range ++ * size is required for thunder_pem_init() call. ++ */ ++ res_pem->end = res_pem->start + SZ_64K - 1; + thunder_pem_reserve_range(dev, root->segment, res_pem); ++ res_pem->end = res_pem->start + SZ_16M - 1; ++ ++ /* Reserve PCI configuration space as well. */ + thunder_pem_reserve_range(dev, root->segment, &cfg->res); + } + diff --git a/queue-4.10/series b/queue-4.10/series new file mode 100644 index 00000000000..23823544b2f --- /dev/null +++ b/queue-4.10/series @@ -0,0 +1,8 @@ +drm-vmwgfx-type-check-lookups-of-fence-objects.patch +drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch +drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch +drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch +drm-vmwgfx-remove-getparam-error-message.patch +drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch +pci-thunder-pem-add-legacy-firmware-support-for-cavium-thunderx-host-controller.patch +pci-thunder-pem-fix-legacy-firmware-pem-specific-resources.patch diff --git a/queue-4.4/series b/queue-4.4/series new file mode 100644 index 00000000000..5e64ca67394 --- /dev/null +++ b/queue-4.4/series @@ -0,0 +1,6 @@ +drm-vmwgfx-type-check-lookups-of-fence-objects.patch +drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch +drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch +drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch +drm-vmwgfx-remove-getparam-error-message.patch +drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch diff --git a/queue-4.9/series b/queue-4.9/series new file mode 100644 index 00000000000..581dfe90625 --- /dev/null +++ b/queue-4.9/series @@ -0,0 +1,8 @@ +ppdev-check-before-attaching-port.patch +ppdev-fix-registering-same-device-name.patch +drm-vmwgfx-type-check-lookups-of-fence-objects.patch +drm-vmwgfx-null-pointer-dereference-in-vmw_surface_define_ioctl.patch +drm-vmwgfx-avoid-calling-vzalloc-with-a-0-size-in-vmw_get_cap_3d_ioctl.patch +drm-ttm-drm-vmwgfx-relax-permission-checking-when-opening-surfaces.patch +drm-vmwgfx-remove-getparam-error-message.patch +drm-vmwgfx-fix-integer-overflow-in-vmw_surface_define_ioctl.patch