From: Greg Kroah-Hartman Date: Tue, 13 Nov 2012 23:35:59 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.0.52~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d4dbfc088b0c468836524245eb33d292cc5bd67b;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch drm-i915-fixup-infoframe-support-for-sdvo.patch drm-vmwgfx-fix-hibernation-device-reset.patch futex-handle-futex_pi-owner_died-take-over-correctly.patch usb-mos7840-remove-unused-variable.patch --- diff --git a/queue-3.0/drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch b/queue-3.0/drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch new file mode 100644 index 00000000000..0a23c01f27d --- /dev/null +++ b/queue-3.0/drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch @@ -0,0 +1,144 @@ +From b6e0e543f75729f207b9c72b0162ae61170635b2 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sun, 21 Oct 2012 12:52:39 +0200 +Subject: drm/i915: clear the entire sdvo infoframe buffer + +From: Daniel Vetter + +commit b6e0e543f75729f207b9c72b0162ae61170635b2 upstream. + +Like in the case of native hdmi, which is fixed already in + +commit adf00b26d18e1b3570451296e03bcb20e4798cdd +Author: Paulo Zanoni +Date: Tue Sep 25 13:23:34 2012 -0300 + + drm/i915: make sure we write all the DIP data bytes + +we need to clear the entire sdvo buffer to avoid upsetting the +display. + +Since infoframe buffer writing is now a bit more elaborate, extract it +into it's own function. This will be useful if we ever get around to +properly update the ELD for sdvo. Also #define proper names for the +two buffer indexes with fixed usage. + +v2: Cite the right commit above, spotted by Paulo Zanoni. + +v3: I'm too stupid to paste the right commit. + +v4: Ben Hutchings noticed that I've failed to handle an underflow in +my loop logic, breaking it for i >= length + 8. Since I've just lost C +programmer license, use his solution. Also, make the frustrated 0-base +buffer size a notch more clear. + +Reported-and-tested-by: Jürg Billeter +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 +Cc: Paulo Zanoni +Cc: Ben Hutchings +Reviewed-by: Rodrigo Vivi +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_sdvo.c | 62 ++++++++++++++++++++++----------- + drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 + + 2 files changed, 44 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -861,6 +861,45 @@ static void intel_sdvo_dump_hdmi_buf(str + } + #endif + ++static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, ++ unsigned if_index, uint8_t tx_rate, ++ uint8_t *data, unsigned length) ++{ ++ uint8_t set_buf_index[2] = { if_index, 0 }; ++ uint8_t hbuf_size, tmp[8]; ++ int i; ++ ++ if (!intel_sdvo_set_value(intel_sdvo, ++ SDVO_CMD_SET_HBUF_INDEX, ++ set_buf_index, 2)) ++ return false; ++ ++ if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, ++ &hbuf_size, 1)) ++ return false; ++ ++ /* Buffer size is 0 based, hooray! */ ++ hbuf_size++; ++ ++ DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", ++ if_index, length, hbuf_size); ++ ++ for (i = 0; i < hbuf_size; i += 8) { ++ memset(tmp, 0, 8); ++ if (i < length) ++ memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); ++ ++ if (!intel_sdvo_set_value(intel_sdvo, ++ SDVO_CMD_SET_HBUF_DATA, ++ tmp, 8)) ++ return false; ++ } ++ ++ return intel_sdvo_set_value(intel_sdvo, ++ SDVO_CMD_SET_HBUF_TXRATE, ++ &tx_rate, 1); ++} ++ + static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) + { + struct dip_infoframe avi_if = { +@@ -868,11 +907,7 @@ static bool intel_sdvo_set_avi_infoframe + .ver = DIP_VERSION_AVI, + .len = DIP_LEN_AVI, + }; +- uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; +- uint8_t set_buf_index[2] = { 1, 0 }; + uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; +- uint64_t *data = (uint64_t *)sdvo_data; +- unsigned i; + + intel_dip_infoframe_csum(&avi_if); + +@@ -882,22 +917,9 @@ static bool intel_sdvo_set_avi_infoframe + sdvo_data[3] = avi_if.checksum; + memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); + +- if (!intel_sdvo_set_value(intel_sdvo, +- SDVO_CMD_SET_HBUF_INDEX, +- set_buf_index, 2)) +- return false; +- +- for (i = 0; i < sizeof(sdvo_data); i += 8) { +- if (!intel_sdvo_set_value(intel_sdvo, +- SDVO_CMD_SET_HBUF_DATA, +- data, 8)) +- return false; +- data++; +- } +- +- return intel_sdvo_set_value(intel_sdvo, +- SDVO_CMD_SET_HBUF_TXRATE, +- &tx_rate, 1); ++ return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, ++ SDVO_HBUF_TX_VSYNC, ++ sdvo_data, sizeof(sdvo_data)); + } + + static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) +--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h ++++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h +@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { + #define SDVO_CMD_SET_AUDIO_STAT 0x91 + #define SDVO_CMD_GET_AUDIO_STAT 0x92 + #define SDVO_CMD_SET_HBUF_INDEX 0x93 ++ #define SDVO_HBUF_INDEX_ELD 0 ++ #define SDVO_HBUF_INDEX_AVI_IF 1 + #define SDVO_CMD_GET_HBUF_INDEX 0x94 + #define SDVO_CMD_GET_HBUF_INFO 0x95 + #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 diff --git a/queue-3.0/drm-i915-fixup-infoframe-support-for-sdvo.patch b/queue-3.0/drm-i915-fixup-infoframe-support-for-sdvo.patch new file mode 100644 index 00000000000..ac2137ee038 --- /dev/null +++ b/queue-3.0/drm-i915-fixup-infoframe-support-for-sdvo.patch @@ -0,0 +1,88 @@ +From 81014b9d0b55fb0b48f26cd2a943359750d532db Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sat, 12 May 2012 20:22:00 +0200 +Subject: drm/i915: fixup infoframe support for sdvo + +From: Daniel Vetter + +commit 81014b9d0b55fb0b48f26cd2a943359750d532db upstream. + +At least the worst offenders: +- SDVO specifies that the encoder should compute the ecc. Testing also + shows that we must not send the ecc field, so copy the dip_infoframe + struct to a temporay place and avoid the ecc field. This way the avi + infoframe is exactly 17 bytes long, which agrees with what the spec + mandates as a minimal storage capacity (with the ecc field it would + be 18 bytes). +- Only 17 when sending the avi infoframe. The SDVO spec explicitly + says that sending more data than what the device announces results + in undefined behaviour. +- Add __attribute__((packed)) to the avi and spd infoframes, for + otherwise they're wrongly aligned. Noticed because the avi infoframe + ended up being 18 bytes large instead of 17. We haven't noticed this + yet because we don't use the uint16_t fields yet (which are the only + ones that would be wrongly aligned). + +This regression has been introduce by + +3c17fe4b8f40a112a85758a9ab2aebf772bdd647 is the first bad commit +commit 3c17fe4b8f40a112a85758a9ab2aebf772bdd647 +Author: David Härdeman +Date: Fri Sep 24 21:44:32 2010 +0200 + + i915: enable AVI infoframe for intel_hdmi.c [v4] + +Patch tested on my g33 with a sdvo hdmi adaptor. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=25732 +Tested-by: Peter Ross (G35 SDVO-HDMI) +Reviewed-by: Eugeni Dodonov +Signed-Off-by: Daniel Vetter +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_drv.h | 2 +- + drivers/gpu/drm/i915/intel_sdvo.c | 11 +++++++++-- + 2 files changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -204,7 +204,7 @@ struct dip_infoframe { + uint16_t bottom_bar_start; + uint16_t left_bar_end; + uint16_t right_bar_start; +- } avi; ++ } __attribute__ ((packed)) avi; + uint8_t payload[27]; + } __attribute__ ((packed)) body; + } __attribute__((packed)); +--- a/drivers/gpu/drm/i915/intel_sdvo.c ++++ b/drivers/gpu/drm/i915/intel_sdvo.c +@@ -870,17 +870,24 @@ static bool intel_sdvo_set_avi_infoframe + }; + uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; + uint8_t set_buf_index[2] = { 1, 0 }; +- uint64_t *data = (uint64_t *)&avi_if; ++ uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; ++ uint64_t *data = (uint64_t *)sdvo_data; + unsigned i; + + intel_dip_infoframe_csum(&avi_if); + ++ /* sdvo spec says that the ecc is handled by the hw, and it looks like ++ * we must not send the ecc field, either. */ ++ memcpy(sdvo_data, &avi_if, 3); ++ sdvo_data[3] = avi_if.checksum; ++ memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); ++ + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_INDEX, + set_buf_index, 2)) + return false; + +- for (i = 0; i < sizeof(avi_if); i += 8) { ++ for (i = 0; i < sizeof(sdvo_data); i += 8) { + if (!intel_sdvo_set_value(intel_sdvo, + SDVO_CMD_SET_HBUF_DATA, + data, 8)) diff --git a/queue-3.0/drm-vmwgfx-fix-hibernation-device-reset.patch b/queue-3.0/drm-vmwgfx-fix-hibernation-device-reset.patch new file mode 100644 index 00000000000..0d87643101d --- /dev/null +++ b/queue-3.0/drm-vmwgfx-fix-hibernation-device-reset.patch @@ -0,0 +1,36 @@ +From 95e8f6a21996c4cc2c4574b231c6e858b749dce3 Mon Sep 17 00:00:00 2001 +From: Thomas Hellstrom +Date: Fri, 9 Nov 2012 10:05:57 +0100 +Subject: drm/vmwgfx: Fix hibernation device reset + +From: Thomas Hellstrom + +commit 95e8f6a21996c4cc2c4574b231c6e858b749dce3 upstream. + +The device would not reset properly when resuming from hibernation. + +Signed-off-by: Thomas Hellstrom +Reviewed-by: Brian Paul +Reviewed-by: Dmitry Torokhov +Cc: linux-graphics-maintainer@vmware.com +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -858,6 +858,11 @@ static void vmw_pm_complete(struct devic + struct drm_device *dev = pci_get_drvdata(pdev); + struct vmw_private *dev_priv = vmw_priv(dev); + ++ mutex_lock(&dev_priv->hw_mutex); ++ vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); ++ (void) vmw_read(dev_priv, SVGA_REG_ID); ++ mutex_unlock(&dev_priv->hw_mutex); ++ + /** + * Reclaim 3d reference held by fbdev and potentially + * start fifo. diff --git a/queue-3.0/futex-handle-futex_pi-owner_died-take-over-correctly.patch b/queue-3.0/futex-handle-futex_pi-owner_died-take-over-correctly.patch new file mode 100644 index 00000000000..ff8d502a595 --- /dev/null +++ b/queue-3.0/futex-handle-futex_pi-owner_died-take-over-correctly.patch @@ -0,0 +1,225 @@ +From 59fa6245192159ab5e1e17b8e31f15afa9cff4bf Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 23 Oct 2012 22:29:38 +0200 +Subject: futex: Handle futex_pi OWNER_DIED take over correctly + +From: Thomas Gleixner + +commit 59fa6245192159ab5e1e17b8e31f15afa9cff4bf upstream. + +Siddhesh analyzed a failure in the take over of pi futexes in case the +owner died and provided a workaround. +See: http://sourceware.org/bugzilla/show_bug.cgi?id=14076 + +The detailed problem analysis shows: + +Futex F is initialized with PTHREAD_PRIO_INHERIT and +PTHREAD_MUTEX_ROBUST_NP attributes. + +T1 lock_futex_pi(F); + +T2 lock_futex_pi(F); + --> T2 blocks on the futex and creates pi_state which is associated + to T1. + +T1 exits + --> exit_robust_list() runs + --> Futex F userspace value TID field is set to 0 and + FUTEX_OWNER_DIED bit is set. + +T3 lock_futex_pi(F); + --> Succeeds due to the check for F's userspace TID field == 0 + --> Claims ownership of the futex and sets its own TID into the + userspace TID field of futex F + --> returns to user space + +T1 --> exit_pi_state_list() + --> Transfers pi_state to waiter T2 and wakes T2 via + rt_mutex_unlock(&pi_state->mutex) + +T2 --> acquires pi_state->mutex and gains real ownership of the + pi_state + --> Claims ownership of the futex and sets its own TID into the + userspace TID field of futex F + --> returns to user space + +T3 --> observes inconsistent state + +This problem is independent of UP/SMP, preemptible/non preemptible +kernels, or process shared vs. private. The only difference is that +certain configurations are more likely to expose it. + +So as Siddhesh correctly analyzed the following check in +futex_lock_pi_atomic() is the culprit: + + if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { + +We check the userspace value for a TID value of 0 and take over the +futex unconditionally if that's true. + +AFAICT this check is there as it is correct for a different corner +case of futexes: the WAITERS bit became stale. + +Now the proposed change + +- if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { ++ if (unlikely(ownerdied || ++ !(curval & (FUTEX_TID_MASK | FUTEX_WAITERS)))) { + +solves the problem, but it's not obvious why and it wreckages the +"stale WAITERS bit" case. + +What happens is, that due to the WAITERS bit being set (T2 is blocked +on that futex) it enforces T3 to go through lookup_pi_state(), which +in the above case returns an existing pi_state and therefor forces T3 +to legitimately fight with T2 over the ownership of the pi_state (via +pi_state->mutex). Probelm solved! + +Though that does not work for the "WAITERS bit is stale" problem +because if lookup_pi_state() does not find existing pi_state it +returns -ERSCH (due to TID == 0) which causes futex_lock_pi() to +return -ESRCH to user space because the OWNER_DIED bit is not set. + +Now there is a different solution to that problem. Do not look at the +user space value at all and enforce a lookup of possibly available +pi_state. If pi_state can be found, then the new incoming locker T3 +blocks on that pi_state and legitimately races with T2 to acquire the +rt_mutex and the pi_state and therefor the proper ownership of the +user space futex. + +lookup_pi_state() has the correct order of checks. It first tries to +find a pi_state associated with the user space futex and only if that +fails it checks for futex TID value = 0. If no pi_state is available +nothing can create new state at that point because this happens with +the hash bucket lock held. + +So the above scenario changes to: + +T1 lock_futex_pi(F); + +T2 lock_futex_pi(F); + --> T2 blocks on the futex and creates pi_state which is associated + to T1. + +T1 exits + --> exit_robust_list() runs + --> Futex F userspace value TID field is set to 0 and + FUTEX_OWNER_DIED bit is set. + +T3 lock_futex_pi(F); + --> Finds pi_state and blocks on pi_state->rt_mutex + +T1 --> exit_pi_state_list() + --> Transfers pi_state to waiter T2 and wakes it via + rt_mutex_unlock(&pi_state->mutex) + +T2 --> acquires pi_state->mutex and gains ownership of the pi_state + --> Claims ownership of the futex and sets its own TID into the + userspace TID field of futex F + --> returns to user space + +This covers all gazillion points on which T3 might come in between +T1's exit_robust_list() clearing the TID field and T2 fixing it up. It +also solves the "WAITERS bit stale" problem by forcing the take over. + +Another benefit of changing the code this way is that it makes it less +dependent on untrusted user space values and therefor minimizes the +possible wreckage which might be inflicted. + +As usual after staring for too long at the futex code my brain hurts +so much that I really want to ditch that whole optimization of +avoiding the syscall for the non contended case for PI futexes and rip +out the maze of corner case handling code. Unfortunately we can't as +user space relies on that existing behaviour, but at least thinking +about it helps me to preserve my mental sanity. Maybe we should +nevertheless :) + +Reported-and-tested-by: Siddhesh Poyarekar +Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1210232138540.2756@ionos +Acked-by: Darren Hart +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/futex.c | 41 ++++++++++++++++++++++------------------- + 1 file changed, 22 insertions(+), 19 deletions(-) + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __us + struct futex_pi_state **ps, + struct task_struct *task, int set_waiters) + { +- int lock_taken, ret, ownerdied = 0; ++ int lock_taken, ret, force_take = 0; + u32 uval, newval, curval, vpid = task_pid_vnr(task); + + retry: +@@ -755,17 +755,15 @@ retry: + newval = curval | FUTEX_WAITERS; + + /* +- * There are two cases, where a futex might have no owner (the +- * owner TID is 0): OWNER_DIED. We take over the futex in this +- * case. We also do an unconditional take over, when the owner +- * of the futex died. +- * +- * This is safe as we are protected by the hash bucket lock ! ++ * Should we force take the futex? See below. + */ +- if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { +- /* Keep the OWNER_DIED bit */ ++ if (unlikely(force_take)) { ++ /* ++ * Keep the OWNER_DIED and the WAITERS bit and set the ++ * new TID value. ++ */ + newval = (curval & ~FUTEX_TID_MASK) | vpid; +- ownerdied = 0; ++ force_take = 0; + lock_taken = 1; + } + +@@ -775,7 +773,7 @@ retry: + goto retry; + + /* +- * We took the lock due to owner died take over. ++ * We took the lock due to forced take over. + */ + if (unlikely(lock_taken)) + return 1; +@@ -790,20 +788,25 @@ retry: + switch (ret) { + case -ESRCH: + /* +- * No owner found for this futex. Check if the +- * OWNER_DIED bit is set to figure out whether +- * this is a robust futex or not. ++ * We failed to find an owner for this ++ * futex. So we have no pi_state to block ++ * on. This can happen in two cases: ++ * ++ * 1) The owner died ++ * 2) A stale FUTEX_WAITERS bit ++ * ++ * Re-read the futex value. + */ + if (get_futex_value_locked(&curval, uaddr)) + return -EFAULT; + + /* +- * We simply start over in case of a robust +- * futex. The code above will take the futex +- * and return happy. ++ * If the owner died or we have a stale ++ * WAITERS bit the owner TID in the user space ++ * futex is 0. + */ +- if (curval & FUTEX_OWNER_DIED) { +- ownerdied = 1; ++ if (!(curval & FUTEX_TID_MASK)) { ++ force_take = 1; + goto retry; + } + default: diff --git a/queue-3.0/series b/queue-3.0/series index b7ecf4aa272..8bda6d07d58 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -30,3 +30,8 @@ net-fix-divide-by-zero-in-tcp-algorithm-illinois.patch drivers-net-phy-mdio-bitbang.c-call-mdiobus_unregister-before-mdiobus_free.patch l2tp-fix-oops-in-l2tp_eth_create-error-path.patch ipv6-send-unsolicited-neighbour-advertisements-to-all-nodes.patch +futex-handle-futex_pi-owner_died-take-over-correctly.patch +drm-vmwgfx-fix-hibernation-device-reset.patch +drm-i915-fixup-infoframe-support-for-sdvo.patch +drm-i915-clear-the-entire-sdvo-infoframe-buffer.patch +usb-mos7840-remove-unused-variable.patch diff --git a/queue-3.0/usb-mos7840-remove-unused-variable.patch b/queue-3.0/usb-mos7840-remove-unused-variable.patch new file mode 100644 index 00000000000..3343518a7c7 --- /dev/null +++ b/queue-3.0/usb-mos7840-remove-unused-variable.patch @@ -0,0 +1,32 @@ +From jhovold@gmail.com Tue Nov 13 15:26:35 2012 +From: Johan Hovold +Date: Thu, 8 Nov 2012 18:28:59 +0100 +Subject: USB: mos7840: remove unused variable +To: Greg KH + +From: Johan Hovold + +Fix warning about unused variable introduced by commit e681b66f2e19fa +("USB: mos7840: remove invalid disconnect handling") upstream. + +A subsequent fix which removed the disconnect function got rid of the +warning but that one was only backported to v3.6. + +Reported-by: Jiri Slaby +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/mos7840.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/usb/serial/mos7840.c ++++ b/drivers/usb/serial/mos7840.c +@@ -2586,7 +2586,6 @@ error: + static void mos7840_disconnect(struct usb_serial *serial) + { + int i; +- unsigned long flags; + struct moschip_port *mos7840_port; + dbg("%s", " disconnect :entering.........."); +