From: Greg Kroah-Hartman Date: Fri, 25 Mar 2011 16:21:41 +0000 (-0700) Subject: .38 patches X-Git-Tag: v2.6.37.6~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c27c5959ad6d5d257f71996335f6e1eb33d82d9;p=thirdparty%2Fkernel%2Fstable-queue.git .38 patches --- diff --git a/queue-2.6.38/drm-check-for-modesetting-on-modeset-ioctls.patch b/queue-2.6.38/drm-check-for-modesetting-on-modeset-ioctls.patch new file mode 100644 index 00000000000..9ea7d0a7ffb --- /dev/null +++ b/queue-2.6.38/drm-check-for-modesetting-on-modeset-ioctls.patch @@ -0,0 +1,191 @@ +From fb3b06c8a1fd1a80298f13b738ab38ef8c73baff Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Tue, 8 Feb 2011 13:55:21 +1000 +Subject: drm: check for modesetting on modeset ioctls + +From: Dave Airlie + +commit fb3b06c8a1fd1a80298f13b738ab38ef8c73baff upstream. + +Noticed this while working on some other things, helps if we check for modeset +enabled on modesetting ioctls. + +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_crtc.c | 51 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +--- a/drivers/gpu/drm/drm_crtc.c ++++ b/drivers/gpu/drm/drm_crtc.c +@@ -1073,6 +1073,9 @@ int drm_mode_getresources(struct drm_dev + uint32_t __user *encoder_id; + struct drm_mode_group *mode_group; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + + /* +@@ -1244,6 +1247,9 @@ int drm_mode_getcrtc(struct drm_device * + struct drm_mode_object *obj; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, crtc_resp->crtc_id, +@@ -1312,6 +1318,9 @@ int drm_mode_getconnector(struct drm_dev + uint64_t __user *prop_values; + uint32_t __user *encoder_ptr; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); + + DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); +@@ -1431,6 +1440,9 @@ int drm_mode_getencoder(struct drm_devic + struct drm_encoder *encoder; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, enc_resp->encoder_id, + DRM_MODE_OBJECT_ENCODER); +@@ -1486,6 +1498,9 @@ int drm_mode_setcrtc(struct drm_device * + int ret = 0; + int i; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_req->crtc_id, + DRM_MODE_OBJECT_CRTC); +@@ -1603,6 +1618,9 @@ int drm_mode_cursor_ioctl(struct drm_dev + struct drm_crtc *crtc; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + if (!req->flags) { + DRM_ERROR("no operation set\n"); + return -EINVAL; +@@ -1667,6 +1685,9 @@ int drm_mode_addfb(struct drm_device *de + struct drm_framebuffer *fb; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + if ((config->min_width > r->width) || (r->width > config->max_width)) { + DRM_ERROR("mode new framebuffer width not within limits\n"); + return -EINVAL; +@@ -1724,6 +1745,9 @@ int drm_mode_rmfb(struct drm_device *dev + int ret = 0; + int found = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB); + /* TODO check that we realy get a framebuffer back. */ +@@ -1780,6 +1804,9 @@ int drm_mode_getfb(struct drm_device *de + struct drm_framebuffer *fb; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) { +@@ -1813,6 +1840,9 @@ int drm_mode_dirtyfb_ioctl(struct drm_de + int num_clips; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB); + if (!obj) { +@@ -1996,6 +2026,9 @@ int drm_mode_attachmode_ioctl(struct drm + struct drm_mode_modeinfo *umode = &mode_cmd->mode; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); +@@ -2042,6 +2075,9 @@ int drm_mode_detachmode_ioctl(struct drm + struct drm_mode_modeinfo *umode = &mode_cmd->mode; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR); +@@ -2211,6 +2247,9 @@ int drm_mode_getproperty_ioctl(struct dr + uint64_t __user *values_ptr; + uint32_t __user *blob_length_ptr; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); + if (!obj) { +@@ -2333,6 +2372,9 @@ int drm_mode_getblob_ioctl(struct drm_de + int ret = 0; + void *blob_ptr; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); + if (!obj) { +@@ -2393,6 +2435,9 @@ int drm_mode_connector_property_set_ioct + int ret = -EINVAL; + int i; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + + obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR); +@@ -2509,6 +2554,9 @@ int drm_mode_gamma_set_ioctl(struct drm_ + int size; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { +@@ -2560,6 +2608,9 @@ int drm_mode_gamma_get_ioctl(struct drm_ + int size; + int ret = 0; + ++ if (!drm_core_check_feature(dev, DRIVER_MODESET)) ++ return -EINVAL; ++ + mutex_lock(&dev->mode_config.mutex); + obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); + if (!obj) { diff --git a/queue-2.6.38/drm-fix-use-after-free-in-drm_gem_vm_close.patch b/queue-2.6.38/drm-fix-use-after-free-in-drm_gem_vm_close.patch new file mode 100644 index 00000000000..9f79e21fa11 --- /dev/null +++ b/queue-2.6.38/drm-fix-use-after-free-in-drm_gem_vm_close.patch @@ -0,0 +1,78 @@ +From b74ad5ae14def5e81ad0be3dddb96e485b861b1b Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 17 Mar 2011 22:33:33 +0000 +Subject: drm: Fix use-after-free in drm_gem_vm_close() + +From: Chris Wilson + +commit b74ad5ae14def5e81ad0be3dddb96e485b861b1b upstream. + +As we may release the last reference, we need to store the device in a +local variable in order to unlock afterwards. + +[ 60.140768] BUG: unable to handle kernel paging request at 6b6b6b9f +[ 60.140973] IP: [] __mutex_unlock_slowpath+0x5a/0x111 +[ 60.141014] *pdpt = 0000000024a54001 *pde = 0000000000000000 +[ 60.141014] Oops: 0002 [#1] PREEMPT SMP +[ 60.141014] last sysfs file: /sys/devices/LNXSYSTM:00/device:00/PNP0A08:00/PNP0C0A:00/power_supply/BAT0/voltage_now +[ 60.141014] Modules linked in: uvcvideo ath9k pegasus ath9k_common ath9k_hw hid_egalax ath3k joydev asus_laptop sparse_keymap battery input_polldev +[ 60.141014] +[ 60.141014] Pid: 771, comm: meego-ux-daemon Not tainted 2.6.37.2-7.1 #1 EXOPC EXOPG06411/EXOPG06411 +[ 60.141014] EIP: 0060:[] EFLAGS: 00010046 CPU: 0 +[ 60.141014] EIP is at __mutex_unlock_slowpath+0x5a/0x111 +[ 60.141014] EAX: 00000100 EBX: 6b6b6b9b ECX: e9b4a1b0 EDX: e4a4e580 +[ 60.141014] ESI: db162558 EDI: 00000246 EBP: e480be50 ESP: e480be44 +[ 60.141014] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 +[ 60.141014] Process meego-ux-daemon (pid: 771, ti=e480a000 task=e9b4a1b0 task.ti=e480a000) +[ 60.141014] Stack: +[ 60.141014] e4a4e580 db162558 f5a2f838 e480be58 c1536dd0 e480be68 c125ab1b db162558 +[ 60.141014] db1624e0 e480be78 c10ba071 db162558 f760241c e480be94 c10bb0bc 000155fe +[ 60.141014] f760241c f5a2f838 f5a2f8c8 00000000 e480bea4 c1037c24 00000000 f5a2f838 +[ 60.141014] Call Trace: +[ 60.141014] [] ? mutex_unlock+0x8/0xa +[ 60.141014] [] ? drm_gem_vm_close+0x39/0x3d +[ 60.141014] [] ? remove_vma+0x2d/0x58 +[ 60.141014] [] ? exit_mmap+0x126/0x13f +[ 60.141014] [] ? mmput+0x37/0x9a +[ 60.141014] [] ? exec_mmap+0x178/0x19c +[ 60.141014] [] ? _raw_spin_unlock+0x1d/0x36 +[ 60.141014] [] ? flush_old_exec+0x42/0x75 +[ 60.141014] [] ? load_elf_binary+0x32a/0x922 +[ 60.141014] [] ? search_binary_handler+0x200/0x2ea +[ 60.141014] [] ? search_binary_handler+0x159/0x2ea +[ 60.141014] [] ? load_elf_binary+0x0/0x922 +[ 60.141014] [] ? do_execve+0x1ff/0x2e6 +[ 60.141014] [] ? sys_execve+0x2d/0x55 +[ 60.141014] [] ? ptregs_execve+0x12/0x18 +[ 60.141014] [] ? sysenter_do_call+0x12/0x3c +[ 60.141014] [] ? init_centaur+0x9c/0x1ba +[ 60.141014] Code: c1 00 75 0f ba 38 01 00 00 b8 8c 3a 6c c1 e8 cc 2e b0 ff 9c 58 8d 74 26 00 89 c7 fa 90 8d 74 26 00 e8 d2 b4 b2 ff b8 00 01 00 00 66 0f c1 43 04 38 e0 74 07 f3 90 8a 43 04 eb f5 83 3d 64 ef +[ 60.141014] EIP: [] __mutex_unlock_slowpath+0x5a/0x111 SS:ESP 0068:e480be44 +[ 60.141014] CR2: 000000006b6b6b9f + +Reported-by: Rusty Lynch +Signed-off-by: Chris Wilson +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_gem.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/drm_gem.c ++++ b/drivers/gpu/drm/drm_gem.c +@@ -498,11 +498,12 @@ EXPORT_SYMBOL(drm_gem_vm_open); + void drm_gem_vm_close(struct vm_area_struct *vma) + { + struct drm_gem_object *obj = vma->vm_private_data; ++ struct drm_device *dev = obj->dev; + +- mutex_lock(&obj->dev->struct_mutex); ++ mutex_lock(&dev->struct_mutex); + drm_vm_close_locked(vma); + drm_gem_object_unreference(obj); +- mutex_unlock(&obj->dev->struct_mutex); ++ mutex_unlock(&dev->struct_mutex); + } + EXPORT_SYMBOL(drm_gem_vm_close); + diff --git a/queue-2.6.38/drm-i915-disable-pagefaults-along-execbuffer-relocation-fast-path.patch b/queue-2.6.38/drm-i915-disable-pagefaults-along-execbuffer-relocation-fast-path.patch new file mode 100644 index 00000000000..7d2eec12db8 --- /dev/null +++ b/queue-2.6.38/drm-i915-disable-pagefaults-along-execbuffer-relocation-fast-path.patch @@ -0,0 +1,70 @@ +From d4aeee776017b6da6dcd12f453cd82a3c951a0dc Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 14 Mar 2011 15:11:24 +0000 +Subject: drm/i915: Disable pagefaults along execbuffer relocation fast path + +From: Chris Wilson + +commit d4aeee776017b6da6dcd12f453cd82a3c951a0dc upstream. + +Along the fast path for relocation handling, we attempt to copy directly +from the user data structures whilst holding our mutex. This causes +lockdep to warn about circular lock dependencies if we need to pagefault +the user pages. [Since when handling a page fault on a mmapped bo, we +need to acquire the struct mutex whilst already holding the mm +semaphore, it is then verboten to acquire the mm semaphore when already +holding the struct mutex. The likelihood of the user passing in the +relocations contained in a GTT mmaped bo is low, but conceivable for +extreme pathology.] In order to force the mm to return EFAULT rather +than handle the pagefault, we therefore need to disable pagefaults +across the relocation fast path. + +Signed-off-by: Chris Wilson +Reviewed-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c ++++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c +@@ -388,6 +388,10 @@ i915_gem_execbuffer_relocate_entry(struc + uint32_t __iomem *reloc_entry; + void __iomem *reloc_page; + ++ /* We can't wait for rendering with pagefaults disabled */ ++ if (obj->active && in_atomic()) ++ return -EFAULT; ++ + ret = i915_gem_object_set_to_gtt_domain(obj, 1); + if (ret) + return ret; +@@ -461,15 +465,24 @@ i915_gem_execbuffer_relocate(struct drm_ + struct list_head *objects) + { + struct drm_i915_gem_object *obj; +- int ret; ++ int ret = 0; + ++ /* This is the fast path and we cannot handle a pagefault whilst ++ * holding the struct mutex lest the user pass in the relocations ++ * contained within a mmaped bo. For in such a case we, the page ++ * fault handler would call i915_gem_fault() and we would try to ++ * acquire the struct mutex again. Obviously this is bad and so ++ * lockdep complains vehemently. ++ */ ++ pagefault_disable(); + list_for_each_entry(obj, objects, exec_list) { + ret = i915_gem_execbuffer_relocate_object(obj, eb); + if (ret) +- return ret; ++ break; + } ++ pagefault_enable(); + +- return 0; ++ return ret; + } + + static int diff --git a/queue-2.6.38/drm-i915-prevent-racy-removal-of-request-from-client-list.patch b/queue-2.6.38/drm-i915-prevent-racy-removal-of-request-from-client-list.patch new file mode 100644 index 00000000000..d23a6d68c8e --- /dev/null +++ b/queue-2.6.38/drm-i915-prevent-racy-removal-of-request-from-client-list.patch @@ -0,0 +1,80 @@ +From 09bfa51773c1e90f13000dc2fc0c4b84047009bc Mon Sep 17 00:00:00 2001 +From: Herton Ronaldo Krzesinski +Date: Thu, 17 Mar 2011 13:45:12 +0000 +Subject: drm/i915: Prevent racy removal of request from client list + +From: Herton Ronaldo Krzesinski + +commit 09bfa51773c1e90f13000dc2fc0c4b84047009bc upstream. + +When i915_gem_retire_requests_ring calls i915_gem_request_remove_from_client, +the client_list for that request may already be removed in i915_gem_release. +So we may call twice list_del(&request->client_list), resulting in an +oops like this report: + +[126167.230394] BUG: unable to handle kernel paging request at 00100104 +[126167.230699] IP: [] i915_gem_retire_requests_ring+0xd4/0x240 [i915] +[126167.231042] *pdpt = 00000000314c1001 *pde = 0000000000000000 +[126167.231314] Oops: 0002 [#1] SMP +[126167.231471] last sysfs file: /sys/devices/LNXSYSTM:00/device:00/PNP0C0A:00/power_supply/BAT1/current_now +[126167.231901] Modules linked in: snd_seq_dummy nls_utf8 isofs btrfs zlib_deflate libcrc32c ufs qnx4 hfsplus hfs minix ntfs vfat msdos fat jfs xfs exportfs reiserfs cryptd aes_i586 aes_generic binfmt_misc vboxnetadp vboxnetflt vboxdrv parport_pc ppdev snd_hda_codec_hdmi snd_hda_codec_conexant snd_hda_intel snd_hda_codec snd_hwdep arc4 snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq uvcvideo videodev snd_timer snd_seq_device joydev iwlagn iwlcore mac80211 snd cfg80211 soundcore i915 drm_kms_helper snd_page_alloc psmouse drm serio_raw i2c_algo_bit video lp parport usbhid hid sky2 sdhci_pci ahci sdhci libahci +[126167.232018] +[126167.232018] Pid: 1101, comm: Xorg Not tainted 2.6.38-6-generic-pae #34-Ubuntu Gateway MC7833U / +[126167.232018] EIP: 0060:[] EFLAGS: 00213246 CPU: 0 +[126167.232018] EIP is at i915_gem_retire_requests_ring+0xd4/0x240 [i915] +[126167.232018] EAX: 00200200 EBX: f1ac25b0 ECX: 00000040 EDX: 00100100 +[126167.232018] ESI: f1a2801c EDI: e87fc060 EBP: ef4d7dd8 ESP: ef4d7db0 +[126167.232018] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 +[126167.232018] Process Xorg (pid: 1101, ti=ef4d6000 task=f1ba6500 task.ti=ef4d6000) +[126167.232018] Stack: +[126167.232018] f1a28000 f1a2809c f1a28094 0058bd97 f1aa2400 f1a2801c 0058bd7b 0058bd85 +[126167.232018] f1a2801c f1a28000 ef4d7e38 f8c2e995 ef4d7e30 ef4d7e60 c14d1ebc f6b3a040 +[126167.232018] f1522cc0 000000db 00000000 f1ba6500 ffffffa1 00000000 00000001 f1a29214 +[126167.232018] Call Trace: + +Unfortunately the call trace reported was cut, but looking at debug +symbols the crash is at __list_del, when probably list_del is called +twice on the same request->client_list, as the dereferenced value is +LIST_POISON1 + 4, and by looking more at the debug symbols before +list_del call it should have being called by +i915_gem_request_remove_from_client + +And as I can see in the code, it seems we indeed have the possibility +to remove a request->client_list twice, which would cause the above, +because we do list_del(&request->client_list) on both +i915_gem_request_remove_from_client and i915_gem_release + +As Chris Wilson pointed out, it's indeed the case: +"(...) I had thought that the actual insertion/deletion was serialised +under the struct mutex and the intention of the spinlock was to protect +the unlocked list traversal during throttling. However, I missed that +i915_gem_release() is also called without struct mutex and so we do need +the double check for i915_gem_request_remove_from_client()." + +This change does the required check to avoid the duplicate remove of +request->client_list. + +Bugzilla: http://bugs.launchpad.net/bugs/733780 +Signed-off-by: Herton Ronaldo Krzesinski +Signed-off-by: Chris Wilson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1749,8 +1749,10 @@ i915_gem_request_remove_from_client(stru + return; + + spin_lock(&file_priv->mm.lock); +- list_del(&request->client_list); +- request->file_priv = NULL; ++ if (request->file_priv) { ++ list_del(&request->client_list); ++ request->file_priv = NULL; ++ } + spin_unlock(&file_priv->mm.lock); + } + diff --git a/queue-2.6.38/drm-radeon-kms-fix-hardcoded-edid-handling.patch b/queue-2.6.38/drm-radeon-kms-fix-hardcoded-edid-handling.patch new file mode 100644 index 00000000000..867230acea5 --- /dev/null +++ b/queue-2.6.38/drm-radeon-kms-fix-hardcoded-edid-handling.patch @@ -0,0 +1,169 @@ +From fafcf94e2b5732d1e13b440291c53115d2b172e9 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Wed, 23 Mar 2011 08:10:10 +0000 +Subject: drm/radeon/kms: fix hardcoded EDID handling + +From: Alex Deucher + +commit fafcf94e2b5732d1e13b440291c53115d2b172e9 upstream. + +On some servers there is a hardcoded EDID provided +in the vbios so that the driver will always see a +display connected even if something like a KVM +prevents traditional means like DDC or load +detection from working properly. Also most +server boards with DVI are not actually DVI, but +DVO connected to a virtual KVM service processor. +If we fail to detect a monitor via DDC or load +detection and a hardcoded EDID is available, use +it. + +Additionally, when using the hardcoded EDID, use +a copy of it rather than the actual one stored +in the driver as the detect() and get_modes() +functions may free it if DDC is successful. + +This fixes the virtual KVM on several internal +servers. + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_combios.c | 21 +++++++++++++++----- + drivers/gpu/drm/radeon/radeon_connectors.c | 30 +++++++++++++++++++++++++++-- + drivers/gpu/drm/radeon/radeon_mode.h | 1 + 3 files changed, 45 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -448,7 +448,7 @@ static uint16_t combios_get_table_offset + + bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) + { +- int edid_info; ++ int edid_info, size; + struct edid *edid; + unsigned char *raw; + edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE); +@@ -456,11 +456,12 @@ bool radeon_combios_check_hardcoded_edid + return false; + + raw = rdev->bios + edid_info; +- edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL); ++ size = EDID_LENGTH * (raw[0x7e] + 1); ++ edid = kmalloc(size, GFP_KERNEL); + if (edid == NULL) + return false; + +- memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1)); ++ memcpy((unsigned char *)edid, raw, size); + + if (!drm_edid_is_valid(edid)) { + kfree(edid); +@@ -468,6 +469,7 @@ bool radeon_combios_check_hardcoded_edid + } + + rdev->mode_info.bios_hardcoded_edid = edid; ++ rdev->mode_info.bios_hardcoded_edid_size = size; + return true; + } + +@@ -475,8 +477,17 @@ bool radeon_combios_check_hardcoded_edid + struct edid * + radeon_bios_get_hardcoded_edid(struct radeon_device *rdev) + { +- if (rdev->mode_info.bios_hardcoded_edid) +- return rdev->mode_info.bios_hardcoded_edid; ++ struct edid *edid; ++ ++ if (rdev->mode_info.bios_hardcoded_edid) { ++ edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL); ++ if (edid) { ++ memcpy((unsigned char *)edid, ++ (unsigned char *)rdev->mode_info.bios_hardcoded_edid, ++ rdev->mode_info.bios_hardcoded_edid_size); ++ return edid; ++ } ++ } + return NULL; + } + +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -629,6 +629,8 @@ static int radeon_vga_mode_valid(struct + static enum drm_connector_status + radeon_vga_detect(struct drm_connector *connector, bool force) + { ++ struct drm_device *dev = connector->dev; ++ struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder; + struct drm_encoder_helper_funcs *encoder_funcs; +@@ -679,6 +681,17 @@ radeon_vga_detect(struct drm_connector * + + if (ret == connector_status_connected) + ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); ++ ++ /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the ++ * vbios to deal with KVMs. If we have one and are not able to detect a monitor ++ * by other means, assume the CRT is connected and use that EDID. ++ */ ++ if ((!rdev->is_atom_bios) && ++ (ret == connector_status_disconnected) && ++ rdev->mode_info.bios_hardcoded_edid_size) { ++ ret = connector_status_connected; ++ } ++ + radeon_connector_update_scratch_regs(connector, ret); + return ret; + } +@@ -790,6 +803,8 @@ static int radeon_dvi_get_modes(struct d + static enum drm_connector_status + radeon_dvi_detect(struct drm_connector *connector, bool force) + { ++ struct drm_device *dev = connector->dev; ++ struct radeon_device *rdev = dev->dev_private; + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + struct drm_encoder *encoder = NULL; + struct drm_encoder_helper_funcs *encoder_funcs; +@@ -829,8 +844,6 @@ radeon_dvi_detect(struct drm_connector * + * you don't really know what's connected to which port as both are digital. + */ + if (radeon_connector->shared_ddc && (ret == connector_status_connected)) { +- struct drm_device *dev = connector->dev; +- struct radeon_device *rdev = dev->dev_private; + struct drm_connector *list_connector; + struct radeon_connector *list_radeon_connector; + list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) { +@@ -895,6 +908,19 @@ radeon_dvi_detect(struct drm_connector * + ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true); + } + ++ /* RN50 and some RV100 asics in servers often have a hardcoded EDID in the ++ * vbios to deal with KVMs. If we have one and are not able to detect a monitor ++ * by other means, assume the DFP is connected and use that EDID. In most ++ * cases the DVI port is actually a virtual KVM port connected to the service ++ * processor. ++ */ ++ if ((!rdev->is_atom_bios) && ++ (ret == connector_status_disconnected) && ++ rdev->mode_info.bios_hardcoded_edid_size) { ++ radeon_connector->use_digital = true; ++ ret = connector_status_connected; ++ } ++ + out: + /* updated in get modes as well since we need to know if it's analog or digital */ + radeon_connector_update_scratch_regs(connector, ret); +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -239,6 +239,7 @@ struct radeon_mode_info { + struct drm_property *underscan_vborder_property; + /* hardcoded DFP edid from BIOS */ + struct edid *bios_hardcoded_edid; ++ int bios_hardcoded_edid_size; + + /* pointer to fbdev info structure */ + struct radeon_fbdev *rfbdev; diff --git a/queue-2.6.38/drm-radeon-kms-prefer-legacy-pll-algo-for-tv-out.patch b/queue-2.6.38/drm-radeon-kms-prefer-legacy-pll-algo-for-tv-out.patch new file mode 100644 index 00000000000..d10648e7f6d --- /dev/null +++ b/queue-2.6.38/drm-radeon-kms-prefer-legacy-pll-algo-for-tv-out.patch @@ -0,0 +1,38 @@ +From 64146f8b2af1ba77fe3c21d9d6d7213b9bb72b40 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 22 Mar 2011 01:46:12 -0400 +Subject: drm/radeon/kms: prefer legacy pll algo for tv-out + +From: Alex Deucher + +commit 64146f8b2af1ba77fe3c21d9d6d7213b9bb72b40 upstream. + +ntsc seems to work fine with either algo, some +pal TVs seem pickier. + +Fixes: +https://bugzilla.kernel.org/show_bug.cgi?id=30832 + +Signed-off-by: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -957,7 +957,11 @@ static void atombios_crtc_set_pll(struct + /* adjust pixel clock as needed */ + adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss); + +- if (ASIC_IS_AVIVO(rdev)) ++ if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) ++ /* TV seems to prefer the legacy algo on some boards */ ++ radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, ++ &ref_div, &post_div); ++ else if (ASIC_IS_AVIVO(rdev)) + radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, + &ref_div, &post_div); + else diff --git a/queue-2.6.38/perf-fix-tear-down-of-inherited-group-events.patch b/queue-2.6.38/perf-fix-tear-down-of-inherited-group-events.patch new file mode 100644 index 00000000000..e37a4ff5e5b --- /dev/null +++ b/queue-2.6.38/perf-fix-tear-down-of-inherited-group-events.patch @@ -0,0 +1,51 @@ +From 38b435b16c36b0d863efcf3f07b34a6fac9873fd Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra +Date: Tue, 15 Mar 2011 14:37:10 +0100 +Subject: perf: Fix tear-down of inherited group events + +From: Peter Zijlstra + +commit 38b435b16c36b0d863efcf3f07b34a6fac9873fd upstream. + +When destroying inherited events, we need to destroy groups too, +otherwise the event iteration in perf_event_exit_task_context() will +miss group siblings and we leak events with all the consequences. + +Reported-and-tested-by: Vince Weaver +Signed-off-by: Peter Zijlstra +LKML-Reference: <1300196470.2203.61.camel@twins> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/perf_event.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/kernel/perf_event.c ++++ b/kernel/perf_event.c +@@ -6115,17 +6115,20 @@ __perf_event_exit_task(struct perf_event + struct perf_event_context *child_ctx, + struct task_struct *child) + { +- struct perf_event *parent_event; ++ if (child_event->parent) { ++ raw_spin_lock_irq(&child_ctx->lock); ++ perf_group_detach(child_event); ++ raw_spin_unlock_irq(&child_ctx->lock); ++ } + + perf_event_remove_from_context(child_event); + +- parent_event = child_event->parent; + /* +- * It can happen that parent exits first, and has events ++ * It can happen that the parent exits first, and has events + * that are still around due to the child reference. These +- * events need to be zapped - but otherwise linger. ++ * events need to be zapped. + */ +- if (parent_event) { ++ if (child_event->parent) { + sync_child_event(child_event, child); + free_event(child_event); + } diff --git a/queue-2.6.38/series b/queue-2.6.38/series index be69e13daca..82dd917ce7d 100644 --- a/queue-2.6.38/series +++ b/queue-2.6.38/series @@ -49,3 +49,10 @@ usb-cdc-acm-fix-potential-null-pointer-dereference-on-disconnect.patch fix-deadlock-in-pivot_root.patch fs-assign-sb-s_bdi-to-default_backing_dev_info-if-the-bdi-is-going-away.patch x86-cleanup-highmap-after-brk-is-concluded.patch +drm-check-for-modesetting-on-modeset-ioctls.patch +drm-i915-disable-pagefaults-along-execbuffer-relocation-fast-path.patch +drm-i915-prevent-racy-removal-of-request-from-client-list.patch +drm-fix-use-after-free-in-drm_gem_vm_close.patch +drm-radeon-kms-prefer-legacy-pll-algo-for-tv-out.patch +drm-radeon-kms-fix-hardcoded-edid-handling.patch +perf-fix-tear-down-of-inherited-group-events.patch