diff --git a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch b/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch deleted file mode 100644 index 857c73c..0000000 --- a/0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 690b1ad9d2032d6f2565d44f6564590d47835ae8 Mon Sep 17 00:00:00 2001 -From: Zhang Rui -Date: Thu, 29 Nov 2012 01:30:43 +0800 -Subject: [PATCH 1/2] ACPI sony-laptop: do proper memcpy for ACPI_TYPE_INTEGER - acpi_object - -the return value of __call_snc_method can either be -an ACPI_TYPE_BUFFER object or a ACPI_TYPE_INTEGER object. -do proper memcpy for ACPI_TYPE_INTEGER object. - -https://bugzilla.kernel.org/show_bug.cgi?id=50111 - -Signed-off-by: Zhang Rui ---- - drivers/platform/x86/sony-laptop.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c -index daaddec..92e0da2 100644 ---- a/drivers/platform/x86/sony-laptop.c -+++ b/drivers/platform/x86/sony-laptop.c -@@ -792,20 +792,19 @@ static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, - if (!object) - return -EINVAL; - -- if (object->type == ACPI_TYPE_BUFFER) -+ if (object->type == ACPI_TYPE_BUFFER) { - len = MIN(buflen, object->buffer.length); -- -- else if (object->type == ACPI_TYPE_INTEGER) -+ memcpy(buffer, object->buffer.pointer, len); -+ } else if (object->type == ACPI_TYPE_INTEGER) { - len = MIN(buflen, sizeof(object->integer.value)); -- -- else { -+ memcpy(buffer, (void *)&object->integer.value, len); -+ } else { - pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", - ACPI_TYPE_BUFFER, object->type); - kfree(object); - return -EINVAL; - } - -- memcpy(buffer, object->buffer.pointer, len); - kfree(object); - return 0; - } --- -1.7.9.5 - diff --git a/3.7.3-stable-queue.patch b/3.7.3-stable-queue.patch new file mode 100644 index 0000000..e9b57d5 --- /dev/null +++ b/3.7.3-stable-queue.patch @@ -0,0 +1,15769 @@ +From 13ae633cf729b0ecb677b75b04886ff8fada8fad Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 20 Nov 2012 10:02:06 +0900 +Subject: regulator: wm831x: Set the new rather than old value for DVS VSEL + +From: Mark Brown + +commit 13ae633cf729b0ecb677b75b04886ff8fada8fad upstream. + +Reported-by: Guennadi Liakhovetski +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/wm831x-dcdc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/wm831x-dcdc.c ++++ b/drivers/regulator/wm831x-dcdc.c +@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel( + if (vsel > dcdc->dvs_vsel) { + ret = wm831x_set_bits(wm831x, dvs_reg, + WM831X_DC1_DVS_VSEL_MASK, +- dcdc->dvs_vsel); ++ vsel); + if (ret == 0) + dcdc->dvs_vsel = vsel; + else +From 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 10 Dec 2012 16:40:41 +0100 +Subject: ath5k: fix tx path skb leaks + +From: Felix Fietkau + +commit 596ab5ec3bf10a22be30d7cb1d903a4b83fd607c upstream. + +ieee80211_free_txskb() needs to be used instead of dev_kfree_skb_any for +tx packets passed to the driver from mac80211 + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath5k/base.c | 4 ++-- + drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath5k/base.c ++++ b/drivers/net/wireless/ath/ath5k/base.c +@@ -848,7 +848,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah + return; + dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, + DMA_TO_DEVICE); +- dev_kfree_skb_any(bf->skb); ++ ieee80211_free_txskb(ah->hw, bf->skb); + bf->skb = NULL; + bf->skbaddr = 0; + bf->desc->ds_data = 0; +@@ -1575,7 +1575,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, + return; + + drop_packet: +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + } + + static void +--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c ++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c +@@ -62,7 +62,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct + u16 qnum = skb_get_queue_mapping(skb); + + if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { +- dev_kfree_skb_any(skb); ++ ieee80211_free_txskb(hw, skb); + return; + } + +From 25a172655f837bdb032e451f95441bb4acec51bb Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Wed, 28 Nov 2012 10:51:34 +0200 +Subject: iwlwifi: don't handle masked interrupt + +From: Emmanuel Grumbach + +commit 25a172655f837bdb032e451f95441bb4acec51bb upstream. + +This can lead to a panic if the driver isn't ready to +handle them. Since our interrupt line is shared, we can get +an interrupt at any time (and CONFIG_DEBUG_SHIRQ checks +that even when the interrupt is being freed). + +If the op_mode has gone away, we musn't call it. To avoid +this the transport disables the interrupts when the hw is +stopped and the op_mode is leaving. +If there is an event that would cause an interrupt the INTA +register is updated regardless of the enablement of the +interrupts: even if the interrupts are disabled, the INTA +will be changed, but the device won't issue an interrupt. +But the ISR can be called at any time, so we ought ignore +the value in the INTA otherwise we can call the op_mode +after it was freed. + +I found this bug when the op_mode_start failed, and called +iwl_trans_stop_hw(trans, true). Then I played with the +RFKILL button, and removed the module. +While removing the module, the IRQ is freed, and the ISR is +called (CONFIG_DEBUG_SHIRQ enabled). Panic. + +Signed-off-by: Emmanuel Grumbach +Reviewed-by: Gregory Greenman +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/rx.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c +@@ -927,12 +927,20 @@ static irqreturn_t iwl_isr(int irq, void + * back-to-back ISRs and sporadic interrupts from our NIC. + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + /* Discover which interrupts are active/pending */ + inta = iwl_read32(trans, CSR_INT); + ++ if (inta & (~inta_mask)) { ++ IWL_DEBUG_ISR(trans, ++ "We got a masked interrupt (0x%08x)...Ack and ignore\n", ++ inta & (~inta_mask)); ++ iwl_write32(trans, CSR_INT, inta & (~inta_mask)); ++ inta &= inta_mask; ++ } ++ + /* Ignore interrupt if there's nothing in NIC to service. + * This may be due to IRQ shared with another device, + * or due to sporadic interrupts thrown from our NIC. */ +@@ -1015,7 +1023,7 @@ irqreturn_t iwl_isr_ict(int irq, void *d + * If we have something to service, the tasklet will re-enable ints. + * If we *don't* have something, we'll re-enable before leaving here. + */ +- inta_mask = iwl_read32(trans, CSR_INT_MASK); /* just for debug */ ++ inta_mask = iwl_read32(trans, CSR_INT_MASK); + iwl_write32(trans, CSR_INT_MASK, 0x00000000); + + +From 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Sun, 2 Dec 2012 09:56:44 +0200 +Subject: iwlwifi: silently ignore fw flaws in Tx path + +From: Emmanuel Grumbach + +commit 27edb1accf5695ff00a32c85c4a00ac7e1e7f298 upstream. + +We know that we have issues with the fw in the reclaim path. +This is why iwl_reclaim doesn't complain too loud when it +happens since it is recoverable. Somehow, the caller of +iwl_reclaim however WARNed when it happens. This doesn't +make any sense. + +When I digged into the history of that code, I discovered +that this bug occurs only when we receive a BA notification. +So move the W/A in the BA notification handling code where +it was before. + +This patch addresses: +http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2387 + +Reported-by: Florian Reitmeir +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/dvm/tx.c | 49 ++++++++++++---------------------- + 1 file changed, 18 insertions(+), 31 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -1100,29 +1100,6 @@ static void iwl_check_abort_status(struc + } + } + +-static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid, +- int txq_id, int ssn, struct sk_buff_head *skbs) +-{ +- if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && +- tid != IWL_TID_NON_QOS && +- txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) { +- /* +- * FIXME: this is a uCode bug which need to be addressed, +- * log the information and return for now. +- * Since it is can possibly happen very often and in order +- * not to fill the syslog, don't use IWL_ERR or IWL_WARN +- */ +- IWL_DEBUG_TX_QUEUES(priv, +- "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", +- txq_id, sta_id, tid, +- priv->tid_data[sta_id][tid].agg.txq_id); +- return 1; +- } +- +- iwl_trans_reclaim(priv->trans, txq_id, ssn, skbs); +- return 0; +-} +- + int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, + struct iwl_device_cmd *cmd) + { +@@ -1184,9 +1161,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + next_reclaimed); + } + +- /*we can free until ssn % q.n_bd not inclusive */ +- WARN_ON_ONCE(iwl_reclaim(priv, sta_id, tid, +- txq_id, ssn, &skbs)); ++ iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); ++ + iwlagn_check_ratid_empty(priv, sta_id, tid); + freed = 0; + +@@ -1311,16 +1287,27 @@ int iwlagn_rx_reply_compressed_ba(struct + return 0; + } + ++ if (unlikely(scd_flow != agg->txq_id)) { ++ /* ++ * FIXME: this is a uCode bug which need to be addressed, ++ * log the information and return for now. ++ * Since it is can possibly happen very often and in order ++ * not to fill the syslog, don't use IWL_ERR or IWL_WARN ++ */ ++ IWL_DEBUG_TX_QUEUES(priv, ++ "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", ++ scd_flow, sta_id, tid, agg->txq_id); ++ spin_unlock(&priv->sta_lock); ++ return 0; ++ } ++ + __skb_queue_head_init(&reclaimed_skbs); + + /* Release all TFDs before the SSN, i.e. all TFDs in front of + * block-ack window (we assume that they've been successfully + * transmitted ... if not, it's too late anyway). */ +- if (iwl_reclaim(priv, sta_id, tid, scd_flow, +- ba_resp_scd_ssn, &reclaimed_skbs)) { +- spin_unlock(&priv->sta_lock); +- return 0; +- } ++ iwl_trans_reclaim(priv->trans, scd_flow, ba_resp_scd_ssn, ++ &reclaimed_skbs); + + IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " + "sta_id = %d\n", +From cbbc0138efe1dcd5426b8fc5d87741f5057aee72 Mon Sep 17 00:00:00 2001 +From: Rafał Miłecki +Date: Mon, 10 Dec 2012 07:53:56 +0100 +Subject: bcma: mips: fix clearing device IRQ + +From: Rafał Miłecki + +commit cbbc0138efe1dcd5426b8fc5d87741f5057aee72 upstream. + +We were using wrong IRQ number so clearing wasn't working at all. +Depending on a platform this could result in a one device having two +interrupts assigned. On BCM4706 this resulted in all IRQs being broken. + +Signed-off-by: Rafał Miłecki +Cc: Hauke Mehrtens +Acked-by: Hauke Mehrtens +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/bcma/driver_mips.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/bcma/driver_mips.c ++++ b/drivers/bcma/driver_mips.c +@@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struc + bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & + ~(1 << irqflag)); + else +- bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); ++ bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); + + /* assign the new one */ + if (irq == 0) { +From f5685ba675449b072feab6a5391a9ef9f604bc94 Mon Sep 17 00:00:00 2001 +From: Helmut Schaa +Date: Mon, 3 Dec 2012 22:35:39 +0100 +Subject: rt2x00: Only specify interface combinations if more then one interface is possible + +From: Helmut Schaa + +commit f5685ba675449b072feab6a5391a9ef9f604bc94 upstream. + +Otherwise rt2500* triggers a warning in cfg80211, from net/wireless/core.c: + + /* Combinations with just one interface aren't real */ + if (WARN_ON(c->max_interfaces < 2)) + +This was introduced in commit 55d2e9da744ba11eae900b4bfc2da72eace3c1e1: +rt2x00: Replace open coded interface checking with interface combinations. + +Reported-by: Stefan Lippers-Hollmann +Tested-by: Stefan Lippers-Hollmann +Signed-off-by: Helmut Schaa +Acked-by: Gertjan van Wingerde +Acked-by: Stanislaw Gruszka +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2x00dev.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -1123,6 +1123,9 @@ static inline void rt2x00lib_set_if_comb + struct ieee80211_iface_limit *if_limit; + struct ieee80211_iface_combination *if_combination; + ++ if (rt2x00dev->ops->max_ap_intf < 2) ++ return; ++ + /* + * Build up AP interface limits structure. + */ +From 87cac8f879a5ecd7109dbe688087e8810b3364eb Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Tue, 2 Oct 2012 16:25:38 +0200 +Subject: s390/kvm: dont announce RRBM support + +From: Christian Borntraeger + +commit 87cac8f879a5ecd7109dbe688087e8810b3364eb upstream. + +Newer kernels (linux-next with the transparent huge page patches) +use rrbm if the feature is announced via feature bit 66. +RRBM will cause intercepts, so KVM does not handle it right now, +causing an illegal instruction in the guest. +The easy solution is to disable the feature bit for the guest. + +This fixes bugs like: +Kernel BUG at 0000000000124c2a [verbose debug info unavailable] +illegal operation: 0001 [#1] SMP +Modules linked in: virtio_balloon virtio_net ipv6 autofs4 +CPU: 0 Not tainted 3.5.4 #1 +Process fmempig (pid: 659, task: 000000007b712fd0, ksp: 000000007bed3670) +Krnl PSW : 0704d00180000000 0000000000124c2a (pmdp_clear_flush_young+0x5e/0x80) + R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:1 PM:0 EA:3 + 00000000003cc000 0000000000000004 0000000000000000 0000000079800000 + 0000000000040000 0000000000000000 000000007bed3918 000000007cf40000 + 0000000000000001 000003fff7f00000 000003d281a94000 000000007bed383c + 000000007bed3918 00000000005ecbf8 00000000002314a6 000000007bed36e0 + Krnl Code:>0000000000124c2a: b9810025 ogr %r2,%r5 + 0000000000124c2e: 41343000 la %r3,0(%r4,%r3) + 0000000000124c32: a716fffa brct %r1,124c26 + 0000000000124c36: b9010022 lngr %r2,%r2 + 0000000000124c3a: e3d0f0800004 lg %r13,128(%r15) + 0000000000124c40: eb22003f000c srlg %r2,%r2,63 +[ 2150.713198] Call Trace: +[ 2150.713223] ([<00000000002312c4>] page_referenced_one+0x6c/0x27c) +[ 2150.713749] [<0000000000233812>] page_referenced+0x32a/0x410 +[...] + +Signed-off-by: Martin Schwidefsky +CC: Alex Graf +Signed-off-by: Christian Borntraeger +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kvm/kvm-s390.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/kvm/kvm-s390.c ++++ b/arch/s390/kvm/kvm-s390.c +@@ -997,7 +997,7 @@ static int __init kvm_s390_init(void) + } + memcpy(facilities, S390_lowcore.stfle_fac_list, 16); + facilities[0] &= 0xff00fff3f47c0000ULL; +- facilities[1] &= 0x201c000000000000ULL; ++ facilities[1] &= 0x001c000000000000ULL; + return 0; + } + +From ce6a04ac1b759beafc88dbc443ae5da867579eeb Mon Sep 17 00:00:00 2001 +From: Christian Borntraeger +Date: Thu, 15 Nov 2012 09:35:16 +0100 +Subject: s390/kvm: Fix address space mixup + +From: Christian Borntraeger + +commit ce6a04ac1b759beafc88dbc443ae5da867579eeb upstream. + +I was chasing down a bug of random validity intercepts on s390. +(guest prefix page not mapped in the host virtual aspace). Turns out +that the problem was a wrong address space control element. The +cause was quite complex: + +During paging activity a DAT protection during SIE caused a program +interrupt. Normally, the sie retry loop tries to catch all +interrupts during and shortly before sie to rerun the setup. The +problem is now that protection causes a suppressing program interrupt, +causing the PSW to point to the instruction AFTER SIE in case of DAT +protection. This confused the logic of the retry loop to not trigger, +instead we jumped directly back to SIE after return from +the program interrupt. (the protection fault handler itself did +a rewind of the psw). This usually works quite well, but: + +If now the protection fault handler has to wait, another program +might be scheduled in. Later on the sie process will be schedules +in again. In that case the content of CR1 (primary address space) +will be wrong because switch_to will put the user space ASCE into CR1 +and not the guest ASCE. + +In addition the program parameter is also wrong for every protection +fault of a guest, since we dont issue the SPP instruction. + +So lets also check for PSW == instruction after SIE in the program +check handler. Instead of expensively checking all program +interruption codes that might be suppressing we assume that a program +interrupt pointing after SIE was always a program interrupt in SIE. +(Otherwise we have a kernel bug anyway). + +We also have to compensate the rewinding, since the C-level handlers +will do that. Therefore we need to add a nop with the same length +as SIE before the sie_loop. + +Signed-off-by: Christian Borntraeger +Signed-off-by: Martin Schwidefsky +CC: Heiko Carstens +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/entry64.S | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +--- a/arch/s390/kernel/entry64.S ++++ b/arch/s390/kernel/entry64.S +@@ -80,14 +80,21 @@ _TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_ + #endif + .endm + +- .macro HANDLE_SIE_INTERCEPT scratch ++ .macro HANDLE_SIE_INTERCEPT scratch,pgmcheck + #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + tmhh %r8,0x0001 # interrupting from user ? + jnz .+42 + lgr \scratch,%r9 + slg \scratch,BASED(.Lsie_loop) + clg \scratch,BASED(.Lsie_length) ++ .if \pgmcheck ++ # Some program interrupts are suppressing (e.g. protection). ++ # We must also check the instruction after SIE in that case. ++ # do_protection_exception will rewind to rewind_pad ++ jh .+22 ++ .else + jhe .+22 ++ .endif + lg %r9,BASED(.Lsie_loop) + SPP BASED(.Lhost_id) # set host id + #endif +@@ -391,7 +398,7 @@ ENTRY(pgm_check_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_PGM_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,1 + tmhh %r8,0x0001 # test problem state bit + jnz 1f # -> fault in user space + tmhh %r8,0x4000 # PER bit set in old PSW ? +@@ -467,7 +474,7 @@ ENTRY(io_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_IO_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT + tmhh %r8,0x0001 # interrupting from user? + jz io_skip +@@ -613,7 +620,7 @@ ENTRY(ext_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_EXT_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_STACK,STACK_SHIFT + tmhh %r8,0x0001 # interrupting from user ? + jz ext_skip +@@ -661,7 +668,7 @@ ENTRY(mcck_int_handler) + lg %r12,__LC_THREAD_INFO + larl %r13,system_call + lmg %r8,%r9,__LC_MCK_OLD_PSW +- HANDLE_SIE_INTERCEPT %r14 ++ HANDLE_SIE_INTERCEPT %r14,0 + tm __LC_MCCK_CODE,0x80 # system damage? + jo mcck_panic # yes -> rest of mcck code invalid + lghi %r14,__LC_CPU_TIMER_SAVE_AREA +@@ -960,6 +967,13 @@ ENTRY(sie64a) + stg %r3,__SF_EMPTY+8(%r15) # save guest register save area + xc __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0 + lmg %r0,%r13,0(%r3) # load guest gprs 0-13 ++# some program checks are suppressing. C code (e.g. do_protection_exception) ++# will rewind the PSW by the ILC, which is 4 bytes in case of SIE. Other ++# instructions in the sie_loop should not cause program interrupts. So ++# lets use a nop (47 00 00 00) as a landing pad. ++# See also HANDLE_SIE_INTERCEPT ++rewind_pad: ++ nop 0 + sie_loop: + lg %r14,__LC_THREAD_INFO # pointer thread_info struct + tm __TI_flags+7(%r14),_TIF_EXIT_SIE +@@ -999,6 +1013,7 @@ sie_fault: + .Lhost_id: + .quad 0 + ++ EX_TABLE(rewind_pad,sie_fault) + EX_TABLE(sie_loop,sie_fault) + #endif + +From 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 Mon Sep 17 00:00:00 2001 +From: Anton Blanchard +Date: Sun, 11 Nov 2012 19:01:05 +0000 +Subject: powerpc: Fix CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n build + +From: Anton Blanchard + +commit 11ee7e99f35ecb15f59b21da6a82d96d2cd3fcc8 upstream. + +If we build a kernel with CONFIG_RELOCATABLE=y CONFIG_CRASH_DUMP=n, +the kernel fails when we run at a non zero offset. It turns out +we were incorrectly wrapping some of the relocatable kernel code +with CONFIG_CRASH_DUMP. + +Signed-off-by: Anton Blanchard +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/head_64.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/head_64.S ++++ b/arch/powerpc/kernel/head_64.S +@@ -422,7 +422,7 @@ _STATIC(__after_prom_start) + tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ + #endif + +-#ifdef CONFIG_CRASH_DUMP ++#ifdef CONFIG_RELOCATABLE + /* + * Check if the kernel has to be running as relocatable kernel based on the + * variable __run_at_load, if it is set the kernel is treated as relocatable +From ce73ec6db47af84d1466402781ae0872a9e7873c Mon Sep 17 00:00:00 2001 +From: Shan Hai +Date: Thu, 8 Nov 2012 15:57:49 +0000 +Subject: powerpc/vdso: Remove redundant locking in update_vsyscall_tz() + +From: Shan Hai + +commit ce73ec6db47af84d1466402781ae0872a9e7873c upstream. + +The locking in update_vsyscall_tz() is not only unnecessary because the vdso +code copies the data unproteced in __kernel_gettimeofday() but also +introduces a hard to reproduce race condition between update_vsyscall() +and update_vsyscall_tz(), which causes user space process to loop +forever in vdso code. + +The following patch removes the locking from update_vsyscall_tz(). + +Locking is not only unnecessary because the vdso code copies the data +unprotected in __kernel_gettimeofday() but also erroneous because updating +the tb_update_count is not atomic and introduces a hard to reproduce race +condition between update_vsyscall() and update_vsyscall_tz(), which further +causes user space process to loop forever in vdso code. + +The below scenario describes the race condition, +x==0 Boot CPU other CPU + proc_P: x==0 + timer interrupt + update_vsyscall +x==1 x++;sync settimeofday + update_vsyscall_tz +x==2 x++;sync +x==3 sync;x++ + sync;x++ + proc_P: x==3 (loops until x becomes even) + +Because the ++ operator would be implemented as three instructions and not +atomic on powerpc. + +A similar change was made for x86 in commit 6c260d58634 +("x86: vdso: Remove bogus locking in update_vsyscall_tz") + +Signed-off-by: Shan Hai +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/time.c | 5 ----- + 1 file changed, 5 deletions(-) + +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -774,13 +774,8 @@ void update_vsyscall_old(struct timespec + + void update_vsyscall_tz(void) + { +- /* Make userspace gettimeofday spin until we're done. */ +- ++vdso_data->tb_update_count; +- smp_mb(); + vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; + vdso_data->tz_dsttime = sys_tz.tz_dsttime; +- smp_mb(); +- ++vdso_data->tb_update_count; + } + + static void __init clocksource_init(void) +From e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Thu, 20 Dec 2012 03:44:28 +0000 +Subject: powerpc: Add missing NULL terminator to avoid boot panic on PPC40x + +From: Gabor Juhos + +commit e6449c9b2d90c1bd9a5985bf05ddebfd1631cd6b upstream. + +The missing NULL terminator can cause a panic on +PPC405 boards during boot: + + Linux/PowerPC load: console=ttyS0,115200 root=/dev/mtdblock1 rootfstype=squashfs,jffs2 noinitrd init=/etc/preinit + Finalizing device tree... flat tree at 0x6a5160 + bootconsole [udbg0] enabled + Page fault in user mode with in_atomic() = 1 mm = (null) + NIP = c0275f50 MSR = fffffffe + Oops: Weird page fault, sig: 11 [#1] + PowerPC 40x Platform + Modules linked in: + NIP: c0275f50 LR: c0275f60 CTR: c0280000 + REGS: c0275eb0 TRAP: 636f7265 Not tainted (3.7.1) + MSR: fffffffe CR: c06a6190 XER: 00000001 + TASK = c02662a8[0] 'swapper' THREAD: c0274000 + GPR00: c0275ec0 c000c658 c027c4bf 00000000 c0275ee0 c000a0ec c020a1a8 c020a1f0 + GPR08: c020f631 c020f404 c025f078 c025f080 c0275f10 + Call Trace: + ---[ end trace 31fd0ba7d8756001 ]--- + + Kernel panic - not syncing: Attempted to kill the idle task! + +The panic happens since commit 9597abe00c1bab2aedce6b49866bf6d1e81c9eed +(sections: fix section conflicts in arch/powerpc), however the root +cause of this is that the NULL terminator were not added in commit +a4f740cf33f7f6c164bbde3c0cdbcc77b0c4997c (of/flattree: Add of_flat_dt_match() +helper function). + +Signed-off-by: Gabor Juhos +Cc: Grant Likely +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/platforms/40x/ppc40x_simple.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/40x/ppc40x_simple.c ++++ b/arch/powerpc/platforms/40x/ppc40x_simple.c +@@ -57,7 +57,8 @@ static const char * const board[] __init + "amcc,makalu", + "apm,klondike", + "est,hotfoot", +- "plathome,obs600" ++ "plathome,obs600", ++ NULL + }; + + static int __init ppc40x_probe(void) +From e400e72f250d2567e89c9bafb47ab91e8d9a15a2 Mon Sep 17 00:00:00 2001 +From: Scott Wood +Date: Wed, 22 Aug 2012 15:04:23 +0000 +Subject: KVM: PPC: e500: fix allocation size error on g2h_tlb1_map + +From: Scott Wood + +commit e400e72f250d2567e89c9bafb47ab91e8d9a15a2 upstream. + +We were only allocating half the bytes we need, which was made more +obvious by a recent fix to the memset in clear_tlb1_bitmap(). + +Signed-off-by: Scott Wood +Signed-off-by: Alexander Graf +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kvm/e500_tlb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kvm/e500_tlb.c ++++ b/arch/powerpc/kvm/e500_tlb.c +@@ -1332,7 +1332,7 @@ int kvmppc_e500_tlb_init(struct kvmppc_v + if (!vcpu_e500->gtlb_priv[1]) + goto err; + +- vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(unsigned int) * ++ vcpu_e500->g2h_tlb1_map = kzalloc(sizeof(u64) * + vcpu_e500->gtlb_params[1].entries, + GFP_KERNEL); + if (!vcpu_e500->g2h_tlb1_map) +From 5419369ed6bd4cf711fdda5e52a5999b940413f5 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Thu, 29 Nov 2012 14:07:59 -0700 +Subject: KVM: Fix user memslot overlap check + +From: Alex Williamson + +commit 5419369ed6bd4cf711fdda5e52a5999b940413f5 upstream. + +Prior to memory slot sorting this loop compared all of the user memory +slots for overlap with new entries. With memory slot sorting, we're +just checking some number of entries in the array that may or may not +be user slots. Instead, walk all the slots with kvm_for_each_memslot, +which has the added benefit of terminating early when we hit the first +empty slot, and skip comparison to private slots. + +Signed-off-by: Alex Williamson +Signed-off-by: Marcelo Tosatti +Signed-off-by: Greg Kroah-Hartman + +--- + virt/kvm/kvm_main.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -709,8 +709,7 @@ int __kvm_set_memory_region(struct kvm * + int r; + gfn_t base_gfn; + unsigned long npages; +- unsigned long i; +- struct kvm_memory_slot *memslot; ++ struct kvm_memory_slot *memslot, *slot; + struct kvm_memory_slot old, new; + struct kvm_memslots *slots, *old_memslots; + +@@ -761,13 +760,11 @@ int __kvm_set_memory_region(struct kvm * + + /* Check for overlaps */ + r = -EEXIST; +- for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { +- struct kvm_memory_slot *s = &kvm->memslots->memslots[i]; +- +- if (s == memslot || !s->npages) ++ kvm_for_each_memslot(slot, kvm->memslots) { ++ if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot) + continue; +- if (!((base_gfn + npages <= s->base_gfn) || +- (base_gfn >= s->base_gfn + s->npages))) ++ if (!((base_gfn + npages <= slot->base_gfn) || ++ (base_gfn >= slot->base_gfn + slot->npages))) + goto out_free; + } + +From d99e79ec5574fc556c988f613ed6175f6de66f4a Mon Sep 17 00:00:00 2001 +From: Sebastian Ott +Date: Fri, 30 Nov 2012 16:48:59 +0100 +Subject: s390/cio: fix pgid reserved check + +From: Sebastian Ott + +commit d99e79ec5574fc556c988f613ed6175f6de66f4a upstream. + +The check to whom a device is reserved is done by checking the path +state of the affected channel paths. If it turns out that one path is +flagged as reserved by someone else the whole device is marked as such. + +However the meaning of the RESVD_ELSE bit is that the addressed device +is reserved to a different pathgroup (and not reserved to a different +LPAR). If we do this test on a path which is currently not a member of +the pathgroup we could erroneously mark the device as reserved to +someone else. + +To fix this collect the reserved state for all potential members of the +pathgroup and only mark the device as reserved if all of those potential +members have the RESVD_ELSE bit set. + +Acked-by: Peter Oberparleiter +Signed-off-by: Sebastian Ott +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/s390/cio/device_pgid.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/s390/cio/device_pgid.c ++++ b/drivers/s390/cio/device_pgid.c +@@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, str + * Determine pathgroup state from PGID data. + */ + static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, +- int *mismatch, int *reserved, u8 *reset) ++ int *mismatch, u8 *reserved, u8 *reset) + { + struct pgid *pgid = &cdev->private->pgid[0]; + struct pgid *first = NULL; +@@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_devi + if ((cdev->private->pgid_valid_mask & lpm) == 0) + continue; + if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE) +- *reserved = 1; ++ *reserved |= lpm; + if (pgid_is_reset(pgid)) { + *reset |= lpm; + continue; +@@ -316,14 +316,14 @@ static void snid_done(struct ccw_device + struct subchannel *sch = to_subchannel(cdev->dev.parent); + struct pgid *pgid; + int mismatch = 0; +- int reserved = 0; ++ u8 reserved = 0; + u8 reset = 0; + u8 donepm; + + if (rc) + goto out; + pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset); +- if (reserved) ++ if (reserved == cdev->private->pgid_valid_mask) + rc = -EUSERS; + else if (mismatch) + rc = -EOPNOTSUPP; +@@ -336,7 +336,7 @@ static void snid_done(struct ccw_device + } + out: + CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x " +- "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid, ++ "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid, + id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm, + cdev->private->pgid_todo_mask, mismatch, reserved, reset); + switch (rc) { +From 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 Mon Sep 17 00:00:00 2001 +From: Huacai Chen +Date: Mon, 13 Aug 2012 20:52:24 +0800 +Subject: MIPS: Fix poweroff failure when HOTPLUG_CPU configured. + +From: Huacai Chen + +commit 8add1ecb81f541ef2fcb0b85a5470ad9ecfb4a84 upstream. + +When poweroff machine, kernel_power_off() call disable_nonboot_cpus(). +And if we have HOTPLUG_CPU configured, disable_nonboot_cpus() is not an +empty function but attempt to actually disable the nonboot cpus. Since +system state is SYSTEM_POWER_OFF, play_dead() won't be called and thus +disable_nonboot_cpus() hangs. Therefore, we make this patch to avoid +poweroff failure. + +Signed-off-by: Huacai Chen +Signed-off-by: Hongliang Tao +Signed-off-by: Hua Yan +Cc: Yong Zhang +Cc: Fuxin Zhang +Cc: Zhangjin Wu +Patchwork: https://patchwork.linux-mips.org/patch/4211/ +Signed-off-by: Ralf Baechle +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/kernel/process.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +--- a/arch/mips/kernel/process.c ++++ b/arch/mips/kernel/process.c +@@ -72,9 +72,7 @@ void __noreturn cpu_idle(void) + } + } + #ifdef CONFIG_HOTPLUG_CPU +- if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && +- (system_state == SYSTEM_RUNNING || +- system_state == SYSTEM_BOOTING)) ++ if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map)) + play_dead(); + #endif + rcu_idle_exit(); +From 7964c06d66c76507d8b6b662bffea770c29ef0ce Mon Sep 17 00:00:00 2001 +From: Jason Liu +Date: Fri, 11 Jan 2013 14:31:47 -0800 +Subject: mm: compaction: fix echo 1 > compact_memory return error issue + +From: Jason Liu + +commit 7964c06d66c76507d8b6b662bffea770c29ef0ce upstream. + +when run the folloing command under shell, it will return error + + sh/$ echo 1 > /proc/sys/vm/compact_memory + sh/$ sh: write error: Bad address + +After strace, I found the following log: + + ... + write(1, "1\n", 2) = 3 + write(1, "", 4294967295) = -1 EFAULT (Bad address) + write(2, "echo: write error: Bad address\n", 31echo: write error: Bad address + ) = 31 + +This tells system return 3(COMPACT_COMPLETE) after write data to +compact_memory. + +The fix is to make the system just return 0 instead 3(COMPACT_COMPLETE) +from sysctl_compaction_handler after compaction_nodes finished. + +Signed-off-by: Jason Liu +Suggested-by: David Rientjes +Acked-by: Mel Gorman +Cc: Rik van Riel +Cc: Minchan Kim +Cc: KAMEZAWA Hiroyuki +Acked-by: David Rientjes +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/compaction.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -1174,7 +1174,7 @@ static int compact_node(int nid) + } + + /* Compact all nodes in the system */ +-static int compact_nodes(void) ++static void compact_nodes(void) + { + int nid; + +@@ -1183,8 +1183,6 @@ static int compact_nodes(void) + + for_each_online_node(nid) + compact_node(nid); +- +- return COMPACT_COMPLETE; + } + + /* The written value is actually unused, all memory is compacted */ +@@ -1195,7 +1193,7 @@ int sysctl_compaction_handler(struct ctl + void __user *buffer, size_t *length, loff_t *ppos) + { + if (write) +- return compact_nodes(); ++ compact_nodes(); + + return 0; + } +From c060f943d0929f3e429c5d9522290584f6281d6e Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Fri, 11 Jan 2013 14:31:51 -0800 +Subject: mm: use aligned zone start for pfn_to_bitidx calculation + +From: Laura Abbott + +commit c060f943d0929f3e429c5d9522290584f6281d6e upstream. + +The current calculation in pfn_to_bitidx assumes that (pfn - +zone->zone_start_pfn) >> pageblock_order will return the same bit for +all pfn in a pageblock. If zone_start_pfn is not aligned to +pageblock_nr_pages, this may not always be correct. + +Consider the following with pageblock order = 10, zone start 2MB: + + pfn | pfn - zone start | (pfn - zone start) >> page block order + ---------------------------------------------------------------- + 0x26000 | 0x25e00 | 0x97 + 0x26100 | 0x25f00 | 0x97 + 0x26200 | 0x26000 | 0x98 + 0x26300 | 0x26100 | 0x98 + +This means that calling {get,set}_pageblock_migratetype on a single page +will not set the migratetype for the full block. Fix this by rounding +down zone_start_pfn when doing the bitidx calculation. + +For our use case, the effects of this bug were mostly tied to the fact +that CMA allocations would either take a long time or fail to happen. +Depending on the driver using CMA, this could result in anything from +visual glitches to application failures. + +Signed-off-by: Laura Abbott +Acked-by: Mel Gorman +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/page_alloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -5506,7 +5506,7 @@ static inline int pfn_to_bitidx(struct z + pfn &= (PAGES_PER_SECTION-1); + return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; + #else +- pfn = pfn - zone->zone_start_pfn; ++ pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); + return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; + #endif /* CONFIG_SPARSEMEM */ + } +From 10d73e655cef6e86ea8589dca3df4e495e4900b0 Mon Sep 17 00:00:00 2001 +From: Max Filippov +Date: Fri, 11 Jan 2013 14:31:52 -0800 +Subject: mm: bootmem: fix free_all_bootmem_core() with odd bitmap alignment + +From: Max Filippov + +commit 10d73e655cef6e86ea8589dca3df4e495e4900b0 upstream. + +Currently free_all_bootmem_core ignores that node_min_pfn may be not +multiple of BITS_PER_LONG. Eg commit 6dccdcbe2c3e ("mm: bootmem: fix +checking the bitmap when finally freeing bootmem") shifts vec by lower +bits of start instead of lower bits of idx. Also + + if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) + +assumes that vec bit 0 corresponds to start pfn, which is only true when +node_min_pfn is a multiple of BITS_PER_LONG. Also loop in the else +clause can double-free pages (e.g. with node_min_pfn == start == 1, +map[0] == ~0 on 32-bit machine page 32 will be double-freed). + +This bug causes the following message during xtensa kernel boot: + + bootmem::free_all_bootmem_core nid=0 start=1 end=8000 + BUG: Bad page state in process swapper pfn:00001 + page:d04bd020 count:0 mapcount:-127 mapping: (null) index:0x2 + page flags: 0x0() + Call Trace: + bad_page+0x8c/0x9c + free_pages_prepare+0x5e/0x88 + free_hot_cold_page+0xc/0xa0 + __free_pages+0x24/0x38 + __free_pages_bootmem+0x54/0x56 + free_all_bootmem_core$part$11+0xeb/0x138 + free_all_bootmem+0x46/0x58 + mem_init+0x25/0xa4 + start_kernel+0x11e/0x25c + should_never_return+0x0/0x3be7 + +The fix is the following: + - always align vec so that its bit 0 corresponds to start + - provide BITS_PER_LONG bits in vec, if those bits are available in the + map + - don't free pages past next start position in the else clause. + +Signed-off-by: Max Filippov +Cc: Gavin Shan +Cc: Johannes Weiner +Cc: Tejun Heo +Cc: Yinghai Lu +Cc: Joonsoo Kim +Cc: Prasad Koya +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/bootmem.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +--- a/mm/bootmem.c ++++ b/mm/bootmem.c +@@ -185,10 +185,23 @@ static unsigned long __init free_all_boo + + while (start < end) { + unsigned long *map, idx, vec; ++ unsigned shift; + + map = bdata->node_bootmem_map; + idx = start - bdata->node_min_pfn; ++ shift = idx & (BITS_PER_LONG - 1); ++ /* ++ * vec holds at most BITS_PER_LONG map bits, ++ * bit 0 corresponds to start. ++ */ + vec = ~map[idx / BITS_PER_LONG]; ++ ++ if (shift) { ++ vec >>= shift; ++ if (end - start >= BITS_PER_LONG) ++ vec |= ~map[idx / BITS_PER_LONG + 1] << ++ (BITS_PER_LONG - shift); ++ } + /* + * If we have a properly aligned and fully unreserved + * BITS_PER_LONG block of pages in front of us, free +@@ -201,19 +214,18 @@ static unsigned long __init free_all_boo + count += BITS_PER_LONG; + start += BITS_PER_LONG; + } else { +- unsigned long off = 0; ++ unsigned long cur = start; + +- vec >>= start & (BITS_PER_LONG - 1); +- while (vec) { ++ start = ALIGN(start + 1, BITS_PER_LONG); ++ while (vec && cur != start) { + if (vec & 1) { +- page = pfn_to_page(start + off); ++ page = pfn_to_page(cur); + __free_pages_bootmem(page, 0); + count++; + } + vec >>= 1; +- off++; ++ ++cur; + } +- start = ALIGN(start + 1, BITS_PER_LONG); + } + } + +From 1680260226a8fd2aab590319da83ad8e610da9bd Mon Sep 17 00:00:00 2001 +From: Rajkumar Manoharan +Date: Thu, 25 Oct 2012 17:11:31 +0530 +Subject: ath9k_hw: Enable hw PLL power save for AR9462 + +From: Rajkumar Manoharan + +commit 1680260226a8fd2aab590319da83ad8e610da9bd upstream. + +This reduced the power consumption to half in full and network sleep. + +Signed-off-by: Rajkumar Manoharan +Cc: Paul Stewart +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_hw.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c +@@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(str + + /* Awake -> Sleep Setting */ + INIT_INI_ARRAY(&ah->iniPcieSerdes, +- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); ++ ar9462_pciephy_clkreq_disable_L1_2p0); + /* Sleep -> Awake Setting */ + INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, +- ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); ++ ar9462_pciephy_clkreq_disable_L1_2p0); + + /* Fast clock modal settings */ + INIT_INI_ARRAY(&ah->iniModesFastClock, +From 9c170e068636deb3e3f96114034bb711675f0faa Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Thu, 6 Dec 2012 18:40:11 +0100 +Subject: Revert "ath9k_hw: Update AR9003 high_power tx gain table" + +From: Felix Fietkau + +commit 9c170e068636deb3e3f96114034bb711675f0faa upstream. + +This reverts commit f74b9d365ddd33a375802b064f96a5d0e99af7c0. + +Turns out reverting commit a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd +"ath9k_hw: Updated AR9003 tx gain table for 5GHz" was not enough to +bring the tx power back to normal levels on devices like the +Buffalo WZR-HP-G450H, this one needs to be reverted as well. + +This revert improves tx power by ~10 db on that device + +Signed-off-by: Felix Fietkau +Cc: rmanohar@qca.qualcomm.com +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | 172 +++++++++---------- + 1 file changed, 86 insertions(+), 86 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +@@ -534,98 +534,98 @@ static const u32 ar9300_2p2_baseband_cor + + static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { + /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ +- {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +- {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +- {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +- {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +- {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +- {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +- {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +- {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +- {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +- {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +- {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +- {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +- {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +- {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +- {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +- {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +- {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +- {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, +- {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, +- {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, +- {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, +- {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, +- {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, +- {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, +- {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, +- {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, +- {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +- {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +- {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +- {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +- {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +- {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +- {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +- {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +- {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +- {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +- {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +- {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +- {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +- {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +- {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +- {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +- {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +- {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, +- {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, +- {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, +- {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, +- {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, +- {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, +- {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, +- {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, +- {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, +- {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, ++ {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, ++ {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, ++ {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, ++ {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, ++ {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, ++ {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, ++ {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, ++ {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, ++ {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, ++ {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, ++ {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, ++ {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, ++ {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, ++ {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, ++ {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, ++ {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, ++ {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, ++ {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, ++ {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, ++ {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, ++ {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, ++ {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, ++ {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, ++ {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, ++ {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, ++ {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, ++ {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, ++ {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, ++ {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, ++ {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, ++ {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, ++ {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, ++ {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, ++ {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, ++ {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, ++ {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, ++ {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, ++ {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, ++ {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, ++ {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, ++ {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, ++ {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, ++ {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, ++ {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, ++ {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, ++ {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, ++ {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, ++ {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, ++ {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, ++ {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, ++ {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, ++ {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, ++ {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, ++ {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +- {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, +- {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, +- {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, +- {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, +- {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, +- {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, +- {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, +- {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, ++ {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, ++ {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, ++ {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, ++ {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, ++ {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, ++ {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, ++ {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, ++ {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +- {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, +- {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, +- {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, ++ {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, ++ {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, ++ {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, + {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, + {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +From b3cd8021379306c0be6932e4d3b4b01efc681769 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Sun, 9 Dec 2012 23:57:09 +0100 +Subject: ath9k: ar9003: fix OTP register offsets for AR9340 + +From: Gabor Juhos + +commit b3cd8021379306c0be6932e4d3b4b01efc681769 upstream. + +Trying to access the OTP memory on the AR9340 +causes a data bus error like this: + + Data bus error, epc == 86e84164, ra == 86e84164 + Oops[#1]: + Cpu 0 + $ 0 : 00000000 00000061 deadc0de 00000000 + $ 4 : b8115f18 00015f18 00000007 00000004 + $ 8 : 00000001 7c7c3c7c 7c7c7c7c 7c7c7c7c + $12 : 7c7c3c7c 001f0041 00000000 7c7c7c3c + $16 : 86ee0000 00015f18 00000000 00000007 + $20 : 00000004 00000064 00000004 86d71c44 + $24 : 00000000 86e6ca00 + $28 : 86d70000 86d71b20 86ece0c0 86e84164 + Hi : 00000000 + Lo : 00000064 + epc : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + Tainted: G O + ra : 86e84164 ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + Status: 1100d403 KERNEL EXL IE + Cause : 4080801c + PrId : 0001974c (MIPS 74Kc) + Modules linked in: ath9k(O+) ath9k_common(O) ath9k_hw(O) ath(O) ar934x_nfc + mac80211(O) usbcore usb_common scsi_mod nls_base nand nand_ecc nand_ids + crc_ccitt cfg80211(O) compat(O) arc4 aes_generic crypto_blkcipher cryptomgr + aead crypto_hash crypto_algapi ledtrig_timer ledtrig_default_on leds_gpio + Process insmod (pid: 459, threadinfo=86d70000, task=87942140, tls=779ac440) + Stack : 802fb500 000200da 804db150 804e0000 87816130 86ee0000 00010000 86d71b88 + 86d71bc0 00000004 00000003 86e9fcd0 80305300 0002c0d0 86e74c50 800b4c20 + 000003e8 00000001 00000000 86ee0000 000003ff 86e9fd64 80305300 80123938 + fffffffc 00000004 000058bc 00000000 86ea0000 86ee0000 000001ff 878d6000 + 99999999 86e9fdc0 86ee0fcc 86e9e664 0000c0d0 86ee0000 0000700000007000 + ... + Call Trace: + [<86e84164>] ath9k_hw_wait+0x58/0xb0 [ath9k_hw] + [<86e9fcd0>] ath9k_hw_setup_statusring+0x16b8/0x1c7c [ath9k_hw] + + Code: 0000a812 0040f809 00000000 <00531024> 1054000b 24020001 0c05b5dc 2404000a 26520001 + +The cause of the error is that the OTP register +offsets are different on the AR9340 than the +actually used values. + +Signed-off-by: Gabor Juhos +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +@@ -68,13 +68,13 @@ + #define AR9300_BASE_ADDR 0x3ff + #define AR9300_BASE_ADDR_512 0x1ff + +-#define AR9300_OTP_BASE 0x14000 +-#define AR9300_OTP_STATUS 0x15f18 ++#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) ++#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) + #define AR9300_OTP_STATUS_TYPE 0x7 + #define AR9300_OTP_STATUS_VALID 0x4 + #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 + #define AR9300_OTP_STATUS_SM_BUSY 0x1 +-#define AR9300_OTP_READ_DATA 0x15f1c ++#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) + + enum targetPowerHTRates { + HT_TARGET_RATE_0_8_16, +From b7c0c238898d200e80487516e2b67aba2a522cc0 Mon Sep 17 00:00:00 2001 +From: Felix Fietkau +Date: Mon, 10 Dec 2012 14:03:17 +0100 +Subject: ath9k_hw: Fix signal strength / channel noise reporting + +From: Felix Fietkau + +commit b7c0c238898d200e80487516e2b67aba2a522cc0 upstream. + +While AR_PHY_CCA_NOM_VAL_* does contain the expected internal noise floor +for a chip measured in clean air, it refers to the lowest expected reading. + +Depending on the frequency, this measurement can vary by about 6db, thus +causing a higher reported channel noise and signal strength. + +Factor in the 6db offset when converting internal noisefloor to channel noise. + +This patch makes the reported values more accurate for all chips without +affecting NF calibration behavior. + +Signed-off-by: Felix Fietkau +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/calib.c | 1 + + drivers/net/wireless/ath/ath9k/calib.h | 3 +++ + 2 files changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath9k/calib.c ++++ b/drivers/net/wireless/ath/ath9k/calib.c +@@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw + + if (chan && chan->noisefloor) { + s8 delta = chan->noisefloor - ++ ATH9K_NF_CAL_NOISE_THRESH - + ath9k_hw_get_default_nf(ah, chan); + if (delta > 0) + noise += delta; +--- a/drivers/net/wireless/ath/ath9k/calib.h ++++ b/drivers/net/wireless/ath/ath9k/calib.h +@@ -21,6 +21,9 @@ + + #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 + ++/* Internal noise floor can vary by about 6db depending on the frequency */ ++#define ATH9K_NF_CAL_NOISE_THRESH 6 ++ + #define NUM_NF_READINGS 6 + #define ATH9K_NF_CAL_HIST_MAX 5 + +From a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 Mon Sep 17 00:00:00 2001 +From: Sujith Manoharan +Date: Wed, 26 Dec 2012 12:27:39 +0530 +Subject: ath9k_hw: Fix RX gain initvals for AR9485 + +From: Sujith Manoharan + +commit a796a1dd5da9645ad77aa687d1a890ecd63ab5a6 upstream. + +Populate iniModesRxGain with the correct initvals +array for AR9485 v1.1 + +Signed-off-by: Sujith Manoharan +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/ath9k/ar9003_hw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c +@@ -540,7 +540,7 @@ static void ar9003_rx_gain_table_mode0(s + ar9340Common_rx_gain_table_1p0); + else if (AR_SREV_9485_11(ah)) + INIT_INI_ARRAY(&ah->iniModesRxGain, +- ar9485Common_wo_xlna_rx_gain_1_1); ++ ar9485_common_rx_gain_1_1); + else if (AR_SREV_9550(ah)) { + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar955x_1p0_common_rx_gain_table); +From 5b632fe85ec82e5c43740b52e74c66df50a37db3 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 3 Dec 2012 12:56:33 +0100 +Subject: mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL + +From: Stanislaw Gruszka + +commit 5b632fe85ec82e5c43740b52e74c66df50a37db3 upstream. + +Commit f0425beda4d404a6e751439b562100b902ba9c98 "mac80211: retry sending +failed BAR frames later instead of tearing down aggr" caused regression +on rt2x00 hardware (connection hangs). This regression was fixed by +commit be03d4a45c09ee5100d3aaaedd087f19bc20d01 "rt2x00: Don't let +mac80211 send a BAR when an AMPDU subframe fails". But the latter +commit caused yet another problem reported in +https://bugzilla.kernel.org/show_bug.cgi?id=42828#c22 + +After long discussion in this thread: +http://mid.gmane.org/20121018075615.GA18212@redhat.com +and testing various alternative solutions, which failed on one or other +setup, we have no other good fix for the issues like just revert both +mentioned earlier commits. + +To do not affect other hardware which benefit from commit +f0425beda4d404a6e751439b562100b902ba9c98, instead of reverting it, +introduce flag that when used will restore mac80211 behaviour before +the commit. + +Signed-off-by: Stanislaw Gruszka +[replaced link with mid.gmane.org that has message-id] +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/mac80211.h | 5 +++++ + net/mac80211/status.c | 6 +++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1253,6 +1253,10 @@ struct ieee80211_tx_control { + * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any + * P2P Interface. This will be honoured even if more than one interface + * is supported. ++ * ++ * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session ++ * should be tear down once BAR frame will not be acked. ++ * + */ + enum ieee80211_hw_flags { + IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, +@@ -1281,6 +1285,7 @@ enum ieee80211_hw_flags { + IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, + IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, + IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26, + }; + + /** +--- a/net/mac80211/status.c ++++ b/net/mac80211/status.c +@@ -432,7 +432,11 @@ void ieee80211_tx_status(struct ieee8021 + IEEE80211_BAR_CTRL_TID_INFO_MASK) >> + IEEE80211_BAR_CTRL_TID_INFO_SHIFT; + +- ieee80211_set_bar_pending(sta, tid, ssn); ++ if (local->hw.flags & ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL) ++ ieee80211_stop_tx_ba_session(&sta->sta, tid); ++ else ++ ieee80211_set_bar_pending(sta, tid, ssn); + } + } + +From 6c653f66772c39c5e25db715bbd4730596fccd9e Mon Sep 17 00:00:00 2001 +From: Christian Lamparter +Date: Sat, 22 Dec 2012 04:35:24 +0100 +Subject: carl9170: fix -EINVAL bailout during init with !CONFIG_MAC80211_MESH + +From: Christian Lamparter + +commit 6c653f66772c39c5e25db715bbd4730596fccd9e upstream. + +Sean reported that as of 3.7, his AR9170 device no longer works +because the driver fails during initialization. He noted this +is due to: +"In carl9170/fw.c, ar->hw->wiphy is tagged with +NL80211_IFTYPE_MESH_POINT support if the firmware has Content +after Beacon Queuing. This is both in interface_modes and the +only iface_combinations entry. + +If CONFIG_MAC80211_MESH is not set, ieee80211_register_hw +removes NL80211_IFTYPE_MESH_POINT from interface_modes, but +not iface_combinations. + +wiphy_register then checks to see if every interface type in +every interface combination is in interface_modes. +NL80211_IFTYPE_MESH_POINT was removed, so you get a WARN_ON +warning and it returns -EINVAL, giving up." + +Unfortunately, the iface_combination (types) feature bitmap +in ieee80211_iface_limit is part of a const member in the +ieee80211_iface_combination struct. Hence, the MESH_POINT +feature flag can't be masked by wiphy_register in the +same way as interface_modes in ieee80211_register_hw. + +Reported-by: Sean Patrick Santos +Signed-off-by: Christian Lamparter +Tested-by: Sean Patrick Santos +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/ath/carl9170/fw.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/carl9170/fw.c ++++ b/drivers/net/wireless/ath/carl9170/fw.c +@@ -341,8 +341,12 @@ static int carl9170_fw(struct ar9170 *ar + if (SUPP(CARL9170FW_WLANTX_CAB)) { + if_comb_types |= + BIT(NL80211_IFTYPE_AP) | +- BIT(NL80211_IFTYPE_MESH_POINT) | + BIT(NL80211_IFTYPE_P2P_GO); ++ ++#ifdef CONFIG_MAC80211_MESH ++ if_comb_types |= ++ BIT(NL80211_IFTYPE_MESH_POINT); ++#endif /* CONFIG_MAC80211_MESH */ + } + } + +From 9d2373420900a39f5212a3b289331aa3535b1000 Mon Sep 17 00:00:00 2001 +From: Stephan Gatzka +Date: Wed, 28 Nov 2012 20:04:32 +0100 +Subject: firewire: net: Fix handling of fragmented multicast/broadcast packets. + +From: Stephan Gatzka + +commit 9d2373420900a39f5212a3b289331aa3535b1000 upstream. + +This patch fixes both the transmit and receive portion of sending +fragmented mutlicast and broadcast packets. + +The transmit section was broken because the offset for INTFRAG and +LASTFRAG packets were just miscalculated by IEEE1394_GASP_HDR_SIZE (which +was reserved with skb_push() in fwnet_send_packet). + +The receive section was broken because in fwnet_incoming_packet is a call +to fwnet_peer_find_by_node_id(). Called with generation == -1 it will +not find a peer and the partial datagrams are associated to a peer. + +[Stefan R: The fix to use context->card->generation is not perfect. +It relies on the IR tasklet which processes packets from the prior bus +generation to run before the self-ID-complete worklet which sets the +current card generation. Alas, there is no simple way of a race-free +implementation. Let's do it this way for now.] + +Signed-off-by: Stephan Gatzka +Signed-off-by: Stefan Richter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firewire/net.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(stru + if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { + buf_ptr += 2; + length -= IEEE1394_GASP_HDR_SIZE; +- fwnet_incoming_packet(dev, buf_ptr, length, +- source_node_id, -1, true); ++ fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, ++ context->card->generation, true); + } + + packet.payload_length = dev->rcv_buffer_size; +@@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(s + break; + } + +- skb_pull(skb, ptask->max_payload); ++ if (ptask->dest_node == IEEE1394_ALL_NODES) { ++ skb_pull(skb, ++ ptask->max_payload + IEEE1394_GASP_HDR_SIZE); ++ } else { ++ skb_pull(skb, ptask->max_payload); ++ } + if (ptask->outstanding_pkts > 1) { + fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, + dg_size, fg_off, datagram_label); +@@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwne + smp_rmb(); + node_id = dev->card->node_id; + +- p = skb_push(ptask->skb, 8); ++ p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); + put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); + put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 + | RFC2734_SW_VERSION, &p[4]); +From 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Wed, 19 Dec 2012 20:51:31 +0100 +Subject: watchdog: Fix disable/enable regression + +From: Bjørn Mork + +commit 3935e89505a1c3ab3f3b0c7ef0eae54124f48905 upstream. + +Commit 8d4516904b39 ("watchdog: Fix CPU hotplug regression") causes an +oops or hard lockup when doing + + echo 0 > /proc/sys/kernel/nmi_watchdog + echo 1 > /proc/sys/kernel/nmi_watchdog + +and the kernel is booted with nmi_watchdog=1 (default) + +Running laptop-mode-tools and disconnecting/connecting AC power will +cause this to trigger, making it a common failure scenario on laptops. + +Instead of bailing out of watchdog_disable() when !watchdog_enabled we +can initialize the hrtimer regardless of watchdog_enabled status. This +makes it safe to call watchdog_disable() in the nmi_watchdog=0 case, +without the negative effect on the enabled => disabled => enabled case. + +All these tests pass with this patch: +- nmi_watchdog=1 + echo 0 > /proc/sys/kernel/nmi_watchdog + echo 1 > /proc/sys/kernel/nmi_watchdog + +- nmi_watchdog=0 + echo 0 > /sys/devices/system/cpu/cpu1/online + +- nmi_watchdog=0 + echo mem > /sys/power/state + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=51661 + +Signed-off-by: Bjørn Mork +Cc: Norbert Warmuth +Cc: Joseph Salisbury +Cc: Thomas Gleixner +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/watchdog.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/kernel/watchdog.c ++++ b/kernel/watchdog.c +@@ -343,6 +343,10 @@ static void watchdog_enable(unsigned int + { + struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + ++ /* kick off the timer for the hardlockup detector */ ++ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ hrtimer->function = watchdog_timer_fn; ++ + if (!watchdog_enabled) { + kthread_park(current); + return; +@@ -351,10 +355,6 @@ static void watchdog_enable(unsigned int + /* Enable the perf event */ + watchdog_nmi_enable(cpu); + +- /* kick off the timer for the hardlockup detector */ +- hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +- hrtimer->function = watchdog_timer_fn; +- + /* done here because hrtimer_start can only pin to smp_processor_id() */ + hrtimer_start(hrtimer, ns_to_ktime(get_sample_period()), + HRTIMER_MODE_REL_PINNED); +@@ -368,9 +368,6 @@ static void watchdog_disable(unsigned in + { + struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); + +- if (!watchdog_enabled) +- return; +- + watchdog_set_prio(SCHED_NORMAL, 0); + hrtimer_cancel(hrtimer); + /* disable the perf event */ +From 72222be39afbd39c16eb180646b0ac44bb1ba460 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Wed, 28 Nov 2012 13:46:56 +0000 +Subject: ASoC: wm8994: Use the same DCS codes for all WM1811 variants + +From: Mark Brown + +commit 72222be39afbd39c16eb180646b0ac44bb1ba460 upstream. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm8994.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -3839,20 +3839,8 @@ static int wm8994_codec_probe(struct snd + wm8994->hubs.no_cache_dac_hp_direct = true; + wm8994->fll_byp = true; + +- switch (control->cust_id) { +- case 0: +- case 2: +- wm8994->hubs.dcs_codes_l = -9; +- wm8994->hubs.dcs_codes_r = -7; +- break; +- case 1: +- case 3: +- wm8994->hubs.dcs_codes_l = -8; +- wm8994->hubs.dcs_codes_r = -7; +- break; +- default: +- break; +- } ++ wm8994->hubs.dcs_codes_l = -9; ++ wm8994->hubs.dcs_codes_r = -7; + + snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, + WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); +From a3adb1432d7a3ad86bb17a1638e44414537e4118 Mon Sep 17 00:00:00 2001 +From: Lars-Peter Clausen +Date: Fri, 7 Dec 2012 18:30:51 +0100 +Subject: ASoC: sigmadsp: Fix endianness conversion issue + +From: Lars-Peter Clausen + +commit a3adb1432d7a3ad86bb17a1638e44414537e4118 upstream. + +The 'addr' field of the sigma_action struct is stored as big endian in the +firmware file. + +Signed-off-by: Lars-Peter Clausen +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/sigmadsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/codecs/sigmadsp.c ++++ b/sound/soc/codecs/sigmadsp.c +@@ -225,7 +225,7 @@ EXPORT_SYMBOL(process_sigma_firmware); + static int sigma_action_write_regmap(void *control_data, + const struct sigma_action *sa, size_t len) + { +- return regmap_raw_write(control_data, le16_to_cpu(sa->addr), ++ return regmap_raw_write(control_data, be16_to_cpu(sa->addr), + sa->payload, len - 2); + } + +From f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa Mon Sep 17 00:00:00 2001 +From: Sangbeom Kim +Date: Sat, 24 Nov 2012 11:13:28 +0900 +Subject: regulator: s2mps11: Fix ramp delay value shift operation + +From: Sangbeom Kim + +commit f7ebaaeb0b4b97b20c1816f11884e7bfe610a2fa upstream. + +This patch fix the abnormal ramp delay setting. +The shift operation was wrong. + +Signed-off-by: Sangbeom Kim +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/s2mps11.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/regulator/s2mps11.c ++++ b/drivers/regulator/s2mps11.c +@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe( + + if (ramp_enable) { + if (s2mps11->buck2_ramp) +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6; + if (s2mps11->buck3_ramp || s2mps11->buck4_ramp) +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4; + sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable); + } + + ramp_reg &= 0x00; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4; +- ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4; ++ ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2; + ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9); + sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg); + +From beecadea1b8d67f591b13f7099559f32f3fd601d Mon Sep 17 00:00:00 2001 +From: Xi Wang +Date: Fri, 16 Nov 2012 14:40:03 -0500 +Subject: SCSI: mvsas: fix undefined bit shift + +From: Xi Wang + +commit beecadea1b8d67f591b13f7099559f32f3fd601d upstream. + +The macro bit(n) is defined as ((u32)1 << n), and thus it doesn't work +with n >= 32, such as in mvs_94xx_assign_reg_set(): + + if (i >= 32) { + mvi->sata_reg_set |= bit(i); + ... + } + +The shift ((u32)1 << n) with n >= 32 also leads to undefined behavior. +The result varies depending on the architecture. + +This patch changes bit(n) to do a 64-bit shift. It also simplifies +mv_ffc64() using __ffs64(), since invoking ffz() with ~0 is undefined. + +Signed-off-by: Xi Wang +Acked-by: Xiangliang Yu +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/mvsas/mv_94xx.h | 14 ++------------ + drivers/scsi/mvsas/mv_sas.h | 2 +- + 2 files changed, 3 insertions(+), 13 deletions(-) + +--- a/drivers/scsi/mvsas/mv_94xx.h ++++ b/drivers/scsi/mvsas/mv_94xx.h +@@ -258,21 +258,11 @@ enum sas_sata_phy_regs { + #define SPI_ADDR_VLD_94XX (1U << 1) + #define SPI_CTRL_SpiStart_94XX (1U << 0) + +-#define mv_ffc(x) ffz(x) +- + static inline int + mv_ffc64(u64 v) + { +- int i; +- i = mv_ffc((u32)v); +- if (i >= 0) +- return i; +- i = mv_ffc((u32)(v>>32)); +- +- if (i != 0) +- return 32 + i; +- +- return -1; ++ u64 x = ~v; ++ return x ? __ffs64(x) : -1; + } + + #define r_reg_set_enable(i) \ +--- a/drivers/scsi/mvsas/mv_sas.h ++++ b/drivers/scsi/mvsas/mv_sas.h +@@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_ + #define DEV_IS_EXPANDER(type) \ + ((type == EDGE_DEV) || (type == FANOUT_DEV)) + +-#define bit(n) ((u32)1 << n) ++#define bit(n) ((u64)1 << n) + + #define for_each_phy(__lseq_mask, __mc, __lseq) \ + for ((__mc) = (__lseq_mask), (__lseq) = 0; \ +From 072f19b4bea31cdd482d79f805413f2f9ac9e233 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Nov 2012 15:51:46 -0500 +Subject: SCSI: prevent stack buffer overflow in host_reset + +From: Sasha Levin + +commit 072f19b4bea31cdd482d79f805413f2f9ac9e233 upstream. + +store_host_reset() has tried to re-invent the wheel to compare sysfs strings. +Unfortunately it did so poorly and never bothered to check the input from +userspace before overwriting stack with it, so something simple as: + +echo "WoopsieWoopsie" > +/sys/devices/pseudo_0/adapter0/host0/scsi_host/host0/host_reset + +would result in: + +[ 316.310101] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffffff81f5bac7 +[ 316.310101] +[ 316.320051] Pid: 6655, comm: sh Tainted: G W 3.7.0-rc5-next-20121114-sasha-00016-g5c9d68d-dirty #129 +[ 316.320051] Call Trace: +[ 316.340058] pps pps0: PPS event at 1352918752.620355751 +[ 316.340062] pps pps0: capture assert seq #303 +[ 316.320051] [] panic+0xcd/0x1f4 +[ 316.320051] [] ? store_host_reset+0xd7/0x100 +[ 316.320051] [] __stack_chk_fail+0x16/0x20 +[ 316.320051] [] store_host_reset+0xd7/0x100 +[ 316.320051] [] dev_attr_store+0x13/0x30 +[ 316.320051] [] sysfs_write_file+0x101/0x170 +[ 316.320051] [] vfs_write+0xb8/0x180 +[ 316.320051] [] sys_write+0x50/0xa0 +[ 316.320051] [] tracesys+0xe1/0xe6 + +Fix this by uninventing whatever was going on there and just use sysfs_streq. + +Bug introduced by 29443691 ("[SCSI] scsi: Added support for adapter and +firmware reset"). + +[jejb: added necessary const to prevent compile warnings] +Signed-off-by: Sasha Levin +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/scsi_sysfs.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/scsi_sysfs.c ++++ b/drivers/scsi/scsi_sysfs.c +@@ -247,11 +247,11 @@ show_shost_active_mode(struct device *de + + static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); + +-static int check_reset_type(char *str) ++static int check_reset_type(const char *str) + { +- if (strncmp(str, "adapter", 10) == 0) ++ if (sysfs_streq(str, "adapter")) + return SCSI_ADAPTER_RESET; +- else if (strncmp(str, "firmware", 10) == 0) ++ else if (sysfs_streq(str, "firmware")) + return SCSI_FIRMWARE_RESET; + else + return 0; +@@ -264,12 +264,9 @@ store_host_reset(struct device *dev, str + struct Scsi_Host *shost = class_to_shost(dev); + struct scsi_host_template *sht = shost->hostt; + int ret = -EINVAL; +- char str[10]; + int type; + +- sscanf(buf, "%s", str); +- type = check_reset_type(str); +- ++ type = check_reset_type(buf); + if (!type) + goto exit_store_host_reset; + +From 63ea923a97cb0d78efcbbd229950e101588f0ddb Mon Sep 17 00:00:00 2001 +From: Armen Baloyan +Date: Wed, 21 Nov 2012 02:39:53 -0500 +Subject: SCSI: qla2xxx: Properly set result field of bsg_job reply structure for success and failure. + +From: Armen Baloyan + +commit 63ea923a97cb0d78efcbbd229950e101588f0ddb upstream. + +FC transport on receiving bsg_job submission failure, calls bsg_job->job_done() +and sets the bsg_job->reply->result the returned value. In contrast, when the +success code (0) is returned fc transport doesn't call bsg_job->job_done() and +doesn't populate bsg_job->reply->result. + +Signed-off-by: Steve Hodgson +Signed-off-by: Armen Baloyan +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_bsg.c | 65 +++++++++++++++-------------------------- + 1 file changed, 24 insertions(+), 41 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -219,7 +219,8 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_ + break; + } + exit_fcp_prio_cfg: +- bsg_job->job_done(bsg_job); ++ if (!ret) ++ bsg_job->job_done(bsg_job); + return ret; + } + +@@ -741,7 +742,6 @@ qla2x00_process_loopback(struct fc_bsg_j + if (qla81xx_get_port_config(vha, config)) { + ql_log(ql_log_warn, vha, 0x701f, + "Get port config failed.\n"); +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } +@@ -761,7 +761,6 @@ qla2x00_process_loopback(struct fc_bsg_j + new_config, elreq.options); + + if (rval) { +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EPERM; + goto done_free_dma_req; + } +@@ -795,7 +794,6 @@ qla2x00_process_loopback(struct fc_bsg_j + "MPI reset failed.\n"); + } + +- bsg_job->reply->result = (DID_ERROR << 16); + rval = -EIO; + goto done_free_dma_req; + } +@@ -812,33 +810,25 @@ qla2x00_process_loopback(struct fc_bsg_j + ql_log(ql_log_warn, vha, 0x702c, + "Vendor request %s failed.\n", type); + +- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + +- sizeof(struct fc_bsg_reply); +- +- memcpy(fw_sts_ptr, response, sizeof(response)); +- fw_sts_ptr += sizeof(response); +- *fw_sts_ptr = command_sent; + rval = 0; + bsg_job->reply->result = (DID_ERROR << 16); ++ bsg_job->reply->reply_payload_rcv_len = 0; + } else { + ql_dbg(ql_dbg_user, vha, 0x702d, + "Vendor request %s completed.\n", type); +- +- bsg_job->reply_len = sizeof(struct fc_bsg_reply) + +- sizeof(response) + sizeof(uint8_t); +- bsg_job->reply->reply_payload_rcv_len = +- bsg_job->reply_payload.payload_len; +- fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + +- sizeof(struct fc_bsg_reply); +- memcpy(fw_sts_ptr, response, sizeof(response)); +- fw_sts_ptr += sizeof(response); +- *fw_sts_ptr = command_sent; +- bsg_job->reply->result = DID_OK; ++ bsg_job->reply->result = (DID_OK << 16); + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, + bsg_job->reply_payload.sg_cnt, rsp_data, + rsp_data_len); + } +- bsg_job->job_done(bsg_job); ++ ++ bsg_job->reply_len = sizeof(struct fc_bsg_reply) + ++ sizeof(response) + sizeof(uint8_t); ++ fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) + ++ sizeof(struct fc_bsg_reply); ++ memcpy(fw_sts_ptr, response, sizeof(response)); ++ fw_sts_ptr += sizeof(response); ++ *fw_sts_ptr = command_sent; + + dma_free_coherent(&ha->pdev->dev, rsp_data_len, + rsp_data, rsp_data_dma); +@@ -853,6 +843,8 @@ done_unmap_req_sg: + dma_unmap_sg(&ha->pdev->dev, + bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -877,16 +869,15 @@ qla84xx_reset(struct fc_bsg_job *bsg_job + if (rval) { + ql_log(ql_log_warn, vha, 0x7030, + "Vendor request 84xx reset failed.\n"); +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + + } else { + ql_dbg(ql_dbg_user, vha, 0x7031, + "Vendor request 84xx reset completed.\n"); + bsg_job->reply->result = DID_OK; ++ bsg_job->job_done(bsg_job); + } + +- bsg_job->job_done(bsg_job); + return rval; + } + +@@ -976,8 +967,7 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ + ql_log(ql_log_warn, vha, 0x7037, + "Vendor request 84xx updatefw failed.\n"); + +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + } else { + ql_dbg(ql_dbg_user, vha, 0x7038, + "Vendor request 84xx updatefw completed.\n"); +@@ -986,7 +976,6 @@ qla84xx_updatefw(struct fc_bsg_job *bsg_ + bsg_job->reply->result = DID_OK; + } + +- bsg_job->job_done(bsg_job); + dma_pool_free(ha->s_dma_pool, mn, mn_dma); + + done_free_fw_buf: +@@ -996,6 +985,8 @@ done_unmap_sg: + dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, + bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); + ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1163,8 +1154,7 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ + ql_log(ql_log_warn, vha, 0x7043, + "Vendor request 84xx mgmt failed.\n"); + +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); ++ rval = (DID_ERROR << 16); + + } else { + ql_dbg(ql_dbg_user, vha, 0x7044, +@@ -1184,8 +1174,6 @@ qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_ + } + } + +- bsg_job->job_done(bsg_job); +- + done_unmap_sg: + if (mgmt_b) + dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma); +@@ -1200,6 +1188,8 @@ done_unmap_sg: + exit_mgmt: + dma_pool_free(ha->s_dma_pool, mn, mn_dma); + ++ if (!rval) ++ bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1276,9 +1266,7 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job + fcport->port_name[3], fcport->port_name[4], + fcport->port_name[5], fcport->port_name[6], + fcport->port_name[7], rval, fcport->fp_speed, mb[0], mb[1]); +- rval = 0; +- bsg_job->reply->result = (DID_ERROR << 16); +- ++ rval = (DID_ERROR << 16); + } else { + if (!port_param->mode) { + bsg_job->reply_len = sizeof(struct fc_bsg_reply) + +@@ -1292,9 +1280,9 @@ qla24xx_iidma(struct fc_bsg_job *bsg_job + } + + bsg_job->reply->result = DID_OK; ++ bsg_job->job_done(bsg_job); + } + +- bsg_job->job_done(bsg_job); + return rval; + } + +@@ -1887,8 +1875,6 @@ qla2x00_process_vendor_specific(struct f + return qla24xx_process_bidir_cmd(bsg_job); + + default: +- bsg_job->reply->result = (DID_ERROR << 16); +- bsg_job->job_done(bsg_job); + return -ENOSYS; + } + } +@@ -1919,8 +1905,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b + ql_dbg(ql_dbg_user, vha, 0x709f, + "BSG: ISP abort active/needed -- cmd=%d.\n", + bsg_job->request->msgcode); +- bsg_job->reply->result = (DID_ERROR << 16); +- bsg_job->job_done(bsg_job); + return -EBUSY; + } + +@@ -1943,7 +1927,6 @@ qla24xx_bsg_request(struct fc_bsg_job *b + case FC_BSG_RPT_CT: + default: + ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n"); +- bsg_job->reply->result = ret; + break; + } + return ret; +From a394aac88506159e047630fc90dc2242568382d8 Mon Sep 17 00:00:00 2001 +From: David Jeffery +Date: Wed, 21 Nov 2012 02:39:54 -0500 +Subject: SCSI: qla2xxx: Test and clear FCPORT_UPDATE_NEEDED atomically. + +From: David Jeffery + +commit a394aac88506159e047630fc90dc2242568382d8 upstream. + +When the qla2xxx driver loses access to multiple, remote ports, there is a race +condition which can occur which will keep the request stuck on a scsi request +queue indefinitely. + +This bad state occurred do to a race condition with how the FCPORT_UPDATE_NEEDED +bit is set in qla2x00_schedule_rport_del(), and how it is cleared in +qla2x00_do_dpc(). The problem port has its drport pointer set, but it has never +been processed by the driver to inform the fc transport that the port has been +lost. qla2x00_schedule_rport_del() sets drport, and then sets the +FCPORT_UPDATE_NEEDED bit. In qla2x00_do_dpc(), the port lists are walked and +any drport pointer is handled and the fc transport informed of the port loss, +then the FCPORT_UPDATE_NEEDED bit is cleared. This leaves a race where the +dpc thread is processing one port removal, another port removal is marked +with a call to qla2x00_schedule_rport_del(), and the dpc thread clears the +bit for both removals, even though only the first removal was actually +handled. Until another event occurs to set FCPORT_UPDATE_NEEDED, the later +port removal is never finished and qla2xxx stays in a bad state which causes +requests to become stuck on request queues. + +This patch updates the driver to test and clear FCPORT_UPDATE_NEEDED +atomically. This ensures the port state changes are processed and not lost. + +Signed-off-by: David Jeffery +Signed-off-by: Chad Dupuis +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_os.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -4505,9 +4505,9 @@ qla2x00_do_dpc(void *data) + "ISP abort end.\n"); + } + +- if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { ++ if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, ++ &base_vha->dpc_flags)) { + qla2x00_update_fcports(base_vha); +- clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); + } + + if (test_bit(SCR_PENDING, &base_vha->dpc_flags)) { +From 220d36b4c2d96446e88d561714829ec5801b4fc7 Mon Sep 17 00:00:00 2001 +From: Giridhar Malavali +Date: Wed, 21 Nov 2012 02:39:55 -0500 +Subject: SCSI: qla2xxx: Change in setting UNLOADING flag and FC vports logout sequence while unloading qla2xxx driver. + +From: Giridhar Malavali + +commit 220d36b4c2d96446e88d561714829ec5801b4fc7 upstream. + +Signed-off-by: Giridhar Malavali +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_attr.c | 3 +-- + drivers/scsi/qla2xxx/qla_os.c | 3 +-- + 2 files changed, 2 insertions(+), 4 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_attr.c ++++ b/drivers/scsi/qla2xxx/qla_attr.c +@@ -1615,8 +1615,7 @@ qla2x00_terminate_rport_io(struct fc_rpo + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). + */ +- if (fcport->loop_id != FC_NO_LOOP_ID && +- !test_bit(UNLOADING, &fcport->vha->dpc_flags)) { ++ if (fcport->loop_id != FC_NO_LOOP_ID) { + if (IS_FWI2_CAPABLE(fcport->vha->hw)) + fcport->vha->hw->isp_ops->fabric_logout(fcport->vha, + fcport->loop_id, fcport->d_id.b.domain, +--- a/drivers/scsi/qla2xxx/qla_os.c ++++ b/drivers/scsi/qla2xxx/qla_os.c +@@ -2755,6 +2755,7 @@ qla2x00_remove_one(struct pci_dev *pdev) + + ha->flags.host_shutting_down = 1; + ++ set_bit(UNLOADING, &base_vha->dpc_flags); + mutex_lock(&ha->vport_lock); + while (ha->cur_vport_count) { + struct Scsi_Host *scsi_host; +@@ -2784,8 +2785,6 @@ qla2x00_remove_one(struct pci_dev *pdev) + "Error while clearing DRV-Presence.\n"); + } + +- set_bit(UNLOADING, &base_vha->dpc_flags); +- + qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); + + qla2x00_dfs_remove(base_vha); +From 9bceab4e08c5e329e9def7fe1cab41c467236517 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Wed, 21 Nov 2012 02:39:56 -0500 +Subject: SCSI: qla2xxx: Free rsp_data even on error in qla2x00_process_loopback() + +From: Steve Hodgson + +commit 9bceab4e08c5e329e9def7fe1cab41c467236517 upstream. + +Signed-off-by: Steve Hodgson +Signed-off-by: Armen Baloyan +Signed-off-by: Saurav Kashyap +Signed-off-by: James Bottomley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_bsg.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_bsg.c ++++ b/drivers/scsi/qla2xxx/qla_bsg.c +@@ -743,7 +743,7 @@ qla2x00_process_loopback(struct fc_bsg_j + ql_log(ql_log_warn, vha, 0x701f, + "Get port config failed.\n"); + rval = -EPERM; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + + ql_dbg(ql_dbg_user, vha, 0x70c0, +@@ -762,7 +762,7 @@ qla2x00_process_loopback(struct fc_bsg_j + + if (rval) { + rval = -EPERM; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + + type = "FC_BSG_HST_VENDOR_LOOPBACK"; +@@ -795,7 +795,7 @@ qla2x00_process_loopback(struct fc_bsg_j + } + + rval = -EIO; +- goto done_free_dma_req; ++ goto done_free_dma_rsp; + } + } else { + type = "FC_BSG_HST_VENDOR_LOOPBACK"; +@@ -830,6 +830,7 @@ qla2x00_process_loopback(struct fc_bsg_j + fw_sts_ptr += sizeof(response); + *fw_sts_ptr = command_sent; + ++done_free_dma_rsp: + dma_free_coherent(&ha->pdev->dev, rsp_data_len, + rsp_data, rsp_data_dma); + done_free_dma_req: +From 64c13330a38935120501b19c97a3e6095747c7a1 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Mon, 5 Nov 2012 18:02:41 -0800 +Subject: iscsi-target: Fix bug in handling of ExpStatSN ACK during u32 wrap-around + +From: Steve Hodgson + +commit 64c13330a38935120501b19c97a3e6095747c7a1 upstream. + +This patch fixes a bug in the hanlding of initiator provided ExpStatSN and +individual iscsi_cmd->stat_sn comparision during iscsi_conn->stat_sn +wrap-around within iscsit_ack_from_expstatsn() code. + +This bug would manifest itself as iscsi_cmd descriptors not being Acked +by a lower ExpStatSn, causing them to be leaked until an iSCSI connection +or session reinstatement event occurs to release all commands. + +Also fix up two other uses of incorrect CmdSN SNA comparison to use wrapper +usage from include/scsi/iscsi_proto.h. + +Signed-off-by: Steve Hodgson +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + drivers/target/iscsi/iscsi_target_erl2.c | 2 +- + drivers/target/iscsi/iscsi_target_tmr.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -735,7 +735,7 @@ static void iscsit_ack_from_expstatsn(st + list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { + spin_lock(&cmd->istate_lock); + if ((cmd->i_state == ISTATE_SENT_STATUS) && +- (cmd->stat_sn < exp_statsn)) { ++ iscsi_sna_lt(cmd->stat_sn, exp_statsn)) { + cmd->i_state = ISTATE_REMOVE; + spin_unlock(&cmd->istate_lock); + iscsit_add_cmd_to_immediate_queue(cmd, conn, +--- a/drivers/target/iscsi/iscsi_target_erl2.c ++++ b/drivers/target/iscsi/iscsi_target_erl2.c +@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance( + * made generic here. + */ + if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && +- (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) { ++ iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { + list_del(&cmd->i_conn_node); + spin_unlock_bh(&conn->cmd_lock); + iscsit_free_cmd(cmd); +--- a/drivers/target/iscsi/iscsi_target_tmr.c ++++ b/drivers/target/iscsi/iscsi_target_tmr.c +@@ -50,8 +50,8 @@ u8 iscsit_tmr_abort_task( + if (!ref_cmd) { + pr_err("Unable to locate RefTaskTag: 0x%08x on CID:" + " %hu.\n", hdr->rtt, conn->cid); +- return (be32_to_cpu(hdr->refcmdsn) >= conn->sess->exp_cmd_sn && +- be32_to_cpu(hdr->refcmdsn) <= conn->sess->max_cmd_sn) ? ++ return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) && ++ iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ? + ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK; + } + if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) { +From 1c5c12c666fda27c7c494b34934a0a0631a48130 Mon Sep 17 00:00:00 2001 +From: Roland Dreier +Date: Mon, 5 Nov 2012 18:02:42 -0800 +Subject: iscsi-target: Always send a response before terminating iSCSI connection + +From: Roland Dreier + +commit 1c5c12c666fda27c7c494b34934a0a0631a48130 upstream. + +There are some cases, for example when the initiator sends an +out-of-bounds ErrorRecoveryLevel value, where the iSCSI target +terminates the connection without sending back any error. Audit the +login path and add appropriate iscsit_tx_login_rsp() calls to make +sure this doesn't happen. + +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target_login.c | 8 ++++---- + drivers/target/iscsi/iscsi_target_nego.c | 10 ++++++++-- + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/target/iscsi/iscsi_target_login.c ++++ b/drivers/target/iscsi/iscsi_target_login.c +@@ -127,13 +127,13 @@ int iscsi_check_for_session_reinstatemen + + initiatorname_param = iscsi_find_param_from_key( + INITIATORNAME, conn->param_list); +- if (!initiatorname_param) +- return -1; +- + sessiontype_param = iscsi_find_param_from_key( + SESSIONTYPE, conn->param_list); +- if (!sessiontype_param) ++ if (!initiatorname_param || !sessiontype_param) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_MISSING_FIELDS); + return -1; ++ } + + sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; + +--- a/drivers/target/iscsi/iscsi_target_nego.c ++++ b/drivers/target/iscsi/iscsi_target_nego.c +@@ -620,8 +620,11 @@ static int iscsi_target_handle_csg_one(s + login->req_buf, + payload_length, + conn); +- if (ret < 0) ++ if (ret < 0) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_INIT_ERR); + return -1; ++ } + + if (login->first_request) + if (iscsi_target_check_first_request(conn, login) < 0) +@@ -636,8 +639,11 @@ static int iscsi_target_handle_csg_one(s + login->rsp_buf, + &login->rsp_length, + conn->param_list); +- if (ret < 0) ++ if (ret < 0) { ++ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, ++ ISCSI_LOGIN_STATUS_INIT_ERR); + return -1; ++ } + + if (!login->auth_complete && + ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { +From 3c989d7603872bf878840f7ce3ea49b73bea4c6c Mon Sep 17 00:00:00 2001 +From: Wei Yongjun +Date: Fri, 23 Nov 2012 12:07:39 +0800 +Subject: iscsit: use GFP_ATOMIC under spin lock + +From: Wei Yongjun + +commit 3c989d7603872bf878840f7ce3ea49b73bea4c6c upstream. + +The function iscsit_build_conn_drop_async_message() is called +from iscsit_close_connection() with spin lock 'sess->conn_lock' +held, so we should use GFP_ATOMIC instead of GFP_KERNEL. + +Signed-off-by: Wei Yongjun +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/iscsi/iscsi_target.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -2360,7 +2360,7 @@ static void iscsit_build_conn_drop_async + if (!conn_p) + return; + +- cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); ++ cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); + if (!cmd) { + iscsit_dec_conn_usage_count(conn_p); + return; +From 06e97b489006f28e23bb028febfa1c01c266d676 Mon Sep 17 00:00:00 2001 +From: Steve Hodgson +Date: Fri, 16 Nov 2012 08:06:17 -0800 +Subject: qla2xxx: Look up LUN for abort requests + +From: Steve Hodgson + +commit 06e97b489006f28e23bb028febfa1c01c266d676 upstream. + +Search through the list of pending commands on the session list to find +the command the initiator is actually aborting, so that we can pass the +correct LUN to the core TMR handling code. + +(nab: Allow abort requests to work to LUN=0 with mainline target code) + +Signed-off-by: Steve Hodgson +Signed-off-by: Roland Dreier +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_target.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1264,8 +1264,27 @@ static int __qlt_24xx_handle_abts(struct + struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) + { + struct qla_hw_data *ha = vha->hw; ++ struct se_session *se_sess = sess->se_sess; + struct qla_tgt_mgmt_cmd *mcmd; ++ struct se_cmd *se_cmd; ++ u32 lun = 0; + int rc; ++ bool found_lun = false; ++ ++ spin_lock(&se_sess->sess_cmd_lock); ++ list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list) { ++ struct qla_tgt_cmd *cmd = ++ container_of(se_cmd, struct qla_tgt_cmd, se_cmd); ++ if (cmd->tag == abts->exchange_addr_to_abort) { ++ lun = cmd->unpacked_lun; ++ found_lun = true; ++ break; ++ } ++ } ++ spin_unlock(&se_sess->sess_cmd_lock); ++ ++ if (!found_lun) ++ return -ENOENT; + + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, + "qla_target(%d): task abort (tag=%d)\n", +@@ -1283,7 +1302,7 @@ static int __qlt_24xx_handle_abts(struct + mcmd->sess = sess; + memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts)); + +- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, TMR_ABORT_TASK, ++ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, TMR_ABORT_TASK, + abts->exchange_addr_to_abort); + if (rc != 0) { + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052, +From 3100d49d3cd236443faae9d81137c81b22d36003 Mon Sep 17 00:00:00 2001 +From: Mikael Pettersson +Date: Sun, 16 Sep 2012 20:53:43 +0200 +Subject: sata_promise: fix hardreset lockdep error + +From: Mikael Pettersson + +commit 3100d49d3cd236443faae9d81137c81b22d36003 upstream. + +sata_promise's pdc_hard_reset_port() needs to serialize because it +flips a port-specific bit in controller register that's shared by +all ports. The code takes the ata host lock for this, but that's +broken because an interrupt may arrive on our irq during the hard +reset sequence, and that too will take the ata host lock. With +lockdep enabled a big nasty warning is seen. + +Fixed by adding private state to the ata host structure, containing +a second lock used only for serializing the hard reset sequences. +This eliminated the lockdep warnings both on my test rig and on +the original reporter's machine. + +Signed-off-by: Mikael Pettersson +Tested-by: Adko Branil +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/sata_promise.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/ata/sata_promise.c ++++ b/drivers/ata/sata_promise.c +@@ -147,6 +147,10 @@ struct pdc_port_priv { + dma_addr_t pkt_dma; + }; + ++struct pdc_host_priv { ++ spinlock_t hard_reset_lock; ++}; ++ + static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); + static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); + static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); +@@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct a + void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; + void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; + unsigned int ata_no = pdc_ata_port_to_ata_no(ap); ++ struct pdc_host_priv *hpriv = ap->host->private_data; + u8 tmp; + +- spin_lock(&ap->host->lock); ++ spin_lock(&hpriv->hard_reset_lock); + + tmp = readb(pcictl_b1_mmio); + tmp &= ~(0x10 << ata_no); +@@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct a + writeb(tmp, pcictl_b1_mmio); + readb(pcictl_b1_mmio); /* flush */ + +- spin_unlock(&ap->host->lock); ++ spin_unlock(&hpriv->hard_reset_lock); + } + + static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, +@@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_d + const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; + const struct ata_port_info *ppi[PDC_MAX_PORTS]; + struct ata_host *host; ++ struct pdc_host_priv *hpriv; + void __iomem *host_mmio; + int n_ports, i, rc; + int is_sataii_tx4; +@@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_d + dev_err(&pdev->dev, "failed to allocate host\n"); + return -ENOMEM; + } ++ hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); ++ if (!hpriv) ++ return -ENOMEM; ++ spin_lock_init(&hpriv->hard_reset_lock); ++ host->private_data = hpriv; + host->iomap = pcim_iomap_table(pdev); + + is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); +From dcbeec264d73b7228ffdfe767eab69b2353099b1 Mon Sep 17 00:00:00 2001 +From: Mattia Dongili +Date: Fri, 21 Dec 2012 07:21:09 +0900 +Subject: sony-laptop: fix SNC buffer calls when SN06 returns Integers + +From: Mattia Dongili + +commit dcbeec264d73b7228ffdfe767eab69b2353099b1 upstream. + +SN06 in some cases returns an Integer instead of a buffer. While the +code handling the return value was trying to cope with the difference, +the memcpy call was not making any difference between the two types of +acpi_object union. This regression was introduced in 3.5. +While there also rework the return value logic to improve readability. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48671 +Cc: Fabrizio Narni +Cc: +Signed-off-by: Mattia Dongili +Signed-off-by: Matthew Garrett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/sony-laptop.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +--- a/drivers/platform/x86/sony-laptop.c ++++ b/drivers/platform/x86/sony-laptop.c +@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle + static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, + void *buffer, size_t buflen) + { ++ int ret = 0; + size_t len = len; + union acpi_object *object = __call_snc_method(handle, name, value); + + if (!object) + return -EINVAL; + +- if (object->type == ACPI_TYPE_BUFFER) ++ if (object->type == ACPI_TYPE_BUFFER) { + len = MIN(buflen, object->buffer.length); ++ memcpy(buffer, object->buffer.pointer, len); + +- else if (object->type == ACPI_TYPE_INTEGER) ++ } else if (object->type == ACPI_TYPE_INTEGER) { + len = MIN(buflen, sizeof(object->integer.value)); ++ memcpy(buffer, &object->integer.value, len); + +- else { ++ } else { + pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", + ACPI_TYPE_BUFFER, object->type); +- kfree(object); +- return -EINVAL; ++ ret = -EINVAL; + } + +- memcpy(buffer, object->buffer.pointer, len); + kfree(object); +- return 0; ++ return ret; + } + + struct sony_nc_handles { +From ceb7decb366591e9b67d70832e07f5d240572a3d Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Tue, 27 Nov 2012 16:24:29 +0000 +Subject: IB/mlx4: Fix spinlock order to avoid lockdep warnings + +From: Jack Morgenstein + +commit ceb7decb366591e9b67d70832e07f5d240572a3d upstream. + +lockdep warns about taking a hard-irq-unsafe lock (sriov->id_map_lock) +inside a hard-irq-safe lock (sriov->going_down_lock). + +Since id_map_lock is never taken in the interrupt context, we can +simply reverse the order of taking the two spinlocks, thus avoiding +the warning and the depencency. + +Signed-off-by: Jack Morgenstein +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/mlx4/cm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/infiniband/hw/mlx4/cm.c ++++ b/drivers/infiniband/hw/mlx4/cm.c +@@ -268,15 +268,15 @@ static void schedule_delayed(struct ib_d + struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov; + unsigned long flags; + +- spin_lock_irqsave(&sriov->going_down_lock, flags); + spin_lock(&sriov->id_map_lock); ++ spin_lock_irqsave(&sriov->going_down_lock, flags); + /*make sure that there is no schedule inside the scheduled work.*/ + if (!sriov->is_going_down) { + id->scheduled_delete = 1; + schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT); + } +- spin_unlock(&sriov->id_map_lock); + spin_unlock_irqrestore(&sriov->going_down_lock, flags); ++ spin_unlock(&sriov->id_map_lock); + } + + int mlx4_ib_multiplex_cm_handler(struct ib_device *ibdev, int port, int slave_id, +From 311f813a2daefcba03f706a692fe0c67888d7622 Mon Sep 17 00:00:00 2001 +From: Jack Morgenstein +Date: Tue, 27 Nov 2012 16:24:30 +0000 +Subject: mlx4_core: Fix potential deadlock in mlx4_eq_int() + +From: Jack Morgenstein + +commit 311f813a2daefcba03f706a692fe0c67888d7622 upstream. + +The slave_state_lock spinlock is used in both interrupt context and +process context, hence irq locking must be used. Found by lockdep. + +Signed-off-by: Jack Morgenstein +Signed-off-by: Or Gerlitz +Signed-off-by: Roland Dreier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/mellanox/mlx4/cmd.c | 9 +++++---- + drivers/net/ethernet/mellanox/mlx4/eq.c | 10 ++++++---- + 2 files changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c ++++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c +@@ -1498,6 +1498,7 @@ static void mlx4_master_do_cmd(struct ml + u32 reply; + u8 is_going_down = 0; + int i; ++ unsigned long flags; + + slave_state[slave].comm_toggle ^= 1; + reply = (u32) slave_state[slave].comm_toggle << 31; +@@ -1576,12 +1577,12 @@ static void mlx4_master_do_cmd(struct ml + mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave); + goto reset_slave; + } +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (!slave_state[slave].is_slave_going_down) + slave_state[slave].last_cmd = cmd; + else + is_going_down = 1; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + if (is_going_down) { + mlx4_warn(dev, "Slave is going down aborting command(%d)" + " executing from slave:%d\n", +@@ -1597,10 +1598,10 @@ static void mlx4_master_do_cmd(struct ml + reset_slave: + /* cleanup any slave resources */ + mlx4_delete_all_resources_for_slave(dev, slave); +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (!slave_state[slave].is_slave_going_down) + slave_state[slave].last_cmd = MLX4_COMM_CMD_RESET; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + /*with slave in the middle of flr, no need to clean resources again.*/ + inform_slave_state: + memset(&slave_state[slave].event_eq, 0, +--- a/drivers/net/ethernet/mellanox/mlx4/eq.c ++++ b/drivers/net/ethernet/mellanox/mlx4/eq.c +@@ -401,6 +401,7 @@ void mlx4_master_handle_slave_flr(struct + struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state; + int i; + int err; ++ unsigned long flags; + + mlx4_dbg(dev, "mlx4_handle_slave_flr\n"); + +@@ -412,10 +413,10 @@ void mlx4_master_handle_slave_flr(struct + + mlx4_delete_all_resources_for_slave(dev, i); + /*return the slave to running mode*/ +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + slave_state[i].last_cmd = MLX4_COMM_CMD_RESET; + slave_state[i].is_slave_going_down = 0; +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + /*notify the FW:*/ + err = mlx4_cmd(dev, 0, i, 0, MLX4_CMD_INFORM_FLR_DONE, + MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED); +@@ -440,6 +441,7 @@ static int mlx4_eq_int(struct mlx4_dev * + u8 update_slave_state; + int i; + enum slave_port_gen_event gen_event; ++ unsigned long flags; + + while ((eqe = next_eqe_sw(eq))) { + /* +@@ -647,13 +649,13 @@ static int mlx4_eq_int(struct mlx4_dev * + } else + update_slave_state = 1; + +- spin_lock(&priv->mfunc.master.slave_state_lock); ++ spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags); + if (update_slave_state) { + priv->mfunc.master.slave_state[flr_slave].active = false; + priv->mfunc.master.slave_state[flr_slave].last_cmd = MLX4_COMM_CMD_FLR; + priv->mfunc.master.slave_state[flr_slave].is_slave_going_down = 1; + } +- spin_unlock(&priv->mfunc.master.slave_state_lock); ++ spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags); + queue_work(priv->mfunc.master.comm_wq, + &priv->mfunc.master.slave_flr_event_work); + break; +From b042e47491ba5f487601b5141a3f1d8582304170 Mon Sep 17 00:00:00 2001 +From: Maxime Bizon +Date: Mon, 22 Oct 2012 11:19:28 +0200 +Subject: pstore/ram: Fix undefined usage of rounddown_pow_of_two(0) + +From: Maxime Bizon + +commit b042e47491ba5f487601b5141a3f1d8582304170 upstream. + +record_size / console_size / ftrace_size can be 0 (this is how you disable +the feature), but rounddown_pow_of_two(0) is undefined. As suggested by +Kees Cook, use !is_power_of_2() as a condition to call +rounddown_pow_of_two and avoid its undefined behavior on the value 0. This +issue has been present since commit 1894a253 (ramoops: Move to +fs/pstore/ram.c). + +Signed-off-by: Maxime Bizon +Signed-off-by: Florian Fainelli +Acked-by: Kees Cook +Signed-off-by: Anton Vorontsov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/pstore/ram.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/pstore/ram.c ++++ b/fs/pstore/ram.c +@@ -374,10 +374,14 @@ static int __devinit ramoops_probe(struc + goto fail_out; + } + +- pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); +- pdata->record_size = rounddown_pow_of_two(pdata->record_size); +- pdata->console_size = rounddown_pow_of_two(pdata->console_size); +- pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); ++ if (!is_power_of_2(pdata->mem_size)) ++ pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); ++ if (!is_power_of_2(pdata->record_size)) ++ pdata->record_size = rounddown_pow_of_two(pdata->record_size); ++ if (!is_power_of_2(pdata->console_size)) ++ pdata->console_size = rounddown_pow_of_two(pdata->console_size); ++ if (!is_power_of_2(pdata->ftrace_size)) ++ pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size); + + cxt->dump_read_cnt = 0; + cxt->size = pdata->mem_size; +From 5416912af75de9cba5d1c75b99a7888b0bbbd2fb Mon Sep 17 00:00:00 2001 +From: Aaron Lu +Date: Mon, 3 Dec 2012 11:35:02 +0800 +Subject: libata: set dma_mode to 0xff in reset + +From: Aaron Lu + +commit 5416912af75de9cba5d1c75b99a7888b0bbbd2fb upstream. + +ata_device->dma_mode's initial value is zero, which is not a valid dma +mode, but ata_dma_enabled will return true for this value. This patch +sets dma_mode to 0xff in reset function, so that ata_dma_enabled will +not return true for this case, or it will cause problem for pata_acpi. + +The corrsponding bugzilla page is at: +https://bugzilla.kernel.org/show_bug.cgi?id=49151 + +Reported-by: Phillip Wood +Signed-off-by: Aaron Lu +Tested-by: Szymon Janc +Tested-by: Dutra Julio +Acked-by: Alan Cox +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-core.c | 1 + + drivers/ata/libata-eh.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -2560,6 +2560,7 @@ int ata_bus_probe(struct ata_port *ap) + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; ++ dev->dma_mode = 0xff; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -2657,6 +2657,7 @@ int ata_eh_reset(struct ata_link *link, + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; ++ dev->dma_mode = 0xff; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't +From 26cd4d65deba587f3cf2329b6869ce02bcbe68ec Mon Sep 17 00:00:00 2001 +From: Xiaotian Feng +Date: Thu, 13 Dec 2012 16:12:18 +0800 +Subject: libata: fix Null pointer dereference on disk error + +From: Xiaotian Feng + +commit 26cd4d65deba587f3cf2329b6869ce02bcbe68ec upstream. + +Following oops were observed when disk error happened: + +[ 4272.896937] sd 0:0:0:0: [sda] Unhandled error code +[ 4272.896939] sd 0:0:0:0: [sda] Result: hostbyte=DID_BAD_TARGET driverbyte=DRIVER_OK +[ 4272.896942] sd 0:0:0:0: [sda] CDB: Read(10): 28 00 00 5a de a7 00 00 08 00 +[ 4272.896951] end_request: I/O error, dev sda, sector 5955239 +[ 4291.574947] BUG: unable to handle kernel NULL pointer dereference at (null) +[ 4291.658305] IP: [] ahci_activity_show+0x1/0x40 +[ 4291.730090] PGD 76dbbc067 PUD 6c4fba067 PMD 0 +[ 4291.783408] Oops: 0000 [#1] SMP +[ 4291.822100] last sysfs file: /sys/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/sw_activity +[ 4291.934235] CPU 9 +[ 4291.958301] Pid: 27942, comm: hwinfo ...... + +ata_scsi_find_dev could return NULL, so ata_scsi_activity_{show,store} should check if atadev is NULL. + +Signed-off-by: Xiaotian Feng +Cc: James Bottomley +Signed-off-by: Jeff Garzik +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-scsi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *de + struct ata_port *ap = ata_shost_to_port(sdev->host); + struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); + +- if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) ++ if (atadev && ap->ops->sw_activity_show && ++ (ap->flags & ATA_FLAG_SW_ACTIVITY)) + return ap->ops->sw_activity_show(atadev, buf); + return -EINVAL; + } +@@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *d + enum sw_activity val; + int rc; + +- if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { ++ if (atadev && ap->ops->sw_activity_store && ++ (ap->flags & ATA_FLAG_SW_ACTIVITY)) { + val = simple_strtoul(buf, NULL, 0); + switch (val) { + case OFF: case BLINK_ON: case BLINK_OFF: +From 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Wed, 5 Dec 2012 12:08:29 +0100 +Subject: target/file: Fix 32-bit highmem breakage for SGL -> iovec mapping + +From: Sebastian Andrzej Siewior + +commit 40ff2c3b3da35dd3a00ac6722056a59b4b3f2caf upstream. + +This patch changes vectored file I/O to use kmap + kunmap when mapping +incoming SGL memory -> struct iovec in order to properly support 32-bit +highmem configurations. This is because an extra bounce buffer may be +required when processing scatterlist pages allocated with GFP_KERNEL. + +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/target_core_file.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/target/target_core_file.c ++++ b/drivers/target/target_core_file.c +@@ -260,7 +260,7 @@ static int fd_do_readv(struct se_cmd *cm + + for_each_sg(sgl, sg, sgl_nents, i) { + iov[i].iov_len = sg->length; +- iov[i].iov_base = sg_virt(sg); ++ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; + } + + old_fs = get_fs(); +@@ -268,6 +268,8 @@ static int fd_do_readv(struct se_cmd *cm + ret = vfs_readv(fd, &iov[0], sgl_nents, &pos); + set_fs(old_fs); + ++ for_each_sg(sgl, sg, sgl_nents, i) ++ kunmap(sg_page(sg)); + kfree(iov); + /* + * Return zeros and GOOD status even if the READ did not return +@@ -313,7 +315,7 @@ static int fd_do_writev(struct se_cmd *c + + for_each_sg(sgl, sg, sgl_nents, i) { + iov[i].iov_len = sg->length; +- iov[i].iov_base = sg_virt(sg); ++ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; + } + + old_fs = get_fs(); +@@ -321,6 +323,9 @@ static int fd_do_writev(struct se_cmd *c + ret = vfs_writev(fd, &iov[0], sgl_nents, &pos); + set_fs(old_fs); + ++ for_each_sg(sgl, sg, sgl_nents, i) ++ kunmap(sg_page(sg)); ++ + kfree(iov); + + if (ret < 0 || ret != cmd->data_length) { +From 9f4ad44b264f8bb61ffdd607148215566568430d Mon Sep 17 00:00:00 2001 +From: Yi Zou +Date: Mon, 10 Dec 2012 17:04:00 -0800 +Subject: target/tcm_fc: fix the lockdep warning due to inconsistent lock state + +From: Yi Zou + +commit 9f4ad44b264f8bb61ffdd607148215566568430d upstream. + +The lockdep warning below is in theory correct but it will be in really weird +rare situation that ends up that deadlock since the tcm fc session is hashed +based the rport id. Nonetheless, the complaining below is about rcu callback +that does the transport_deregister_session() is happening in softirq, where +transport_register_session() that happens earlier is not. This triggers the +lockdep warning below. So, just fix this to make lockdep happy by disabling +the soft irq before calling transport_register_session() in ft_prli. + +BTW, this was found in FCoE VN2VN over two VMs, couple of create and destroy +would get this triggered. + +v1: was enforcing register to be in softirq context which was not righ. See, +http://www.spinics.net/lists/target-devel/msg03614.html + +v2: following comments from Roland&Nick (thanks), it seems we don't have to +do transport_deregister_session() in rcu callback, so move it into ft_sess_free() +but still do kfree() of the corresponding ft_sess struct in rcu callback to +make sure the ft_sess is not freed till the rcu callback. + +... +[ 1328.370592] scsi2 : FCoE Driver +[ 1328.383429] fcoe: No FDMI support. +[ 1328.384509] host2: libfc: Link up on port (000000) +[ 1328.934229] host2: Assigned Port ID 00a292 +[ 1357.232132] host2: rport 00a393: Remove port +[ 1357.232568] host2: rport 00a393: Port sending LOGO from Ready state +[ 1357.233692] host2: rport 00a393: Delete port +[ 1357.234472] host2: rport 00a393: work event 3 +[ 1357.234969] host2: rport 00a393: callback ev 3 +[ 1357.235979] host2: rport 00a393: Received a LOGO response closed +[ 1357.236706] host2: rport 00a393: work delete +[ 1357.237481] +[ 1357.237631] ================================= +[ 1357.238064] [ INFO: inconsistent lock state ] +[ 1357.238450] 3.7.0-rc7-yikvm+ #3 Tainted: G O +[ 1357.238450] --------------------------------- +[ 1357.238450] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. +[ 1357.238450] ksoftirqd/0/3 [HC0[0]:SC1[1]:HE0:SE0] takes: +[ 1357.238450] (&(&se_tpg->session_lock)->rlock){+.?...}, at: [] transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] {SOFTIRQ-ON-W} state was registered at: +[ 1357.238450] [] mark_held_locks+0x6d/0x95 +[ 1357.238450] [] trace_hardirqs_on_caller+0x12d/0x197 +[ 1357.238450] [] trace_hardirqs_on+0xd/0xf +[ 1357.238450] [] _raw_spin_unlock_irq+0x2d/0x45 +[ 1357.238450] [] __transport_register_session+0xb8/0x122 [target_core_mod] +[ 1357.238450] [] transport_register_session+0x44/0x5a [target_core_mod] +[ 1357.238450] [] ft_prli+0x1e3/0x275 [tcm_fc] +[ 1357.238450] [] fc_rport_recv_req+0x95e/0xdc5 [libfc] +[ 1357.238450] [] fc_lport_recv_els_req+0xc4/0xd5 [libfc] +[ 1357.238450] [] fc_lport_recv_req+0x12f/0x18f [libfc] +[ 1357.238450] [] fc_exch_recv+0x8ba/0x981 [libfc] +[ 1357.238450] [] fcoe_percpu_receive_thread+0x47a/0x4e2 [fcoe] +[ 1357.238450] [] kthread+0xb1/0xb9 +[ 1357.238450] [] ret_from_fork+0x7c/0xb0 +[ 1357.238450] irq event stamp: 275411 +[ 1357.238450] hardirqs last enabled at (275410): [] rcu_process_callbacks+0x229/0x42a +[ 1357.238450] hardirqs last disabled at (275411): [] _raw_spin_lock_irqsave+0x22/0x8e +[ 1357.238450] softirqs last enabled at (275394): [] __do_softirq+0x246/0x26f +[ 1357.238450] softirqs last disabled at (275399): [] run_ksoftirqd+0x29/0x62 +[ 1357.238450] +[ 1357.238450] other info that might help us debug this: +[ 1357.238450] Possible unsafe locking scenario: +[ 1357.238450] +[ 1357.238450] CPU0 +[ 1357.238450] ---- +[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); +[ 1357.238450] +[ 1357.238450] lock(&(&se_tpg->session_lock)->rlock); +[ 1357.238450] +[ 1357.238450] *** DEADLOCK *** +[ 1357.238450] +[ 1357.238450] no locks held by ksoftirqd/0/3. +[ 1357.238450] +[ 1357.238450] stack backtrace: +[ 1357.238450] Pid: 3, comm: ksoftirqd/0 Tainted: G O 3.7.0-rc7-yikvm+ #3 +[ 1357.238450] Call Trace: +[ 1357.238450] [] print_usage_bug+0x1f5/0x206 +[ 1357.238450] [] ? save_stack_trace+0x2c/0x49 +[ 1357.238450] [] ? print_irq_inversion_bug.part.14+0x1ae/0x1ae +[ 1357.238450] [] mark_lock+0x106/0x258 +[ 1357.238450] [] __lock_acquire+0x2e7/0xe53 +[ 1357.238450] [] ? pvclock_clocksource_read+0x48/0xb4 +[ 1357.238450] [] ? rcu_process_gp_end+0xc0/0xc9 +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] lock_acquire+0x119/0x143 +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] _raw_spin_lock_irqsave+0x54/0x8e +[ 1357.238450] [] ? transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] transport_deregister_session+0x41/0x148 [target_core_mod] +[ 1357.238450] [] ? rcu_process_callbacks+0x229/0x42a +[ 1357.238450] [] ft_sess_rcu_free+0x17/0x24 [tcm_fc] +[ 1357.238450] [] ? ft_sess_free+0x1b/0x1b [tcm_fc] +[ 1357.238450] [] rcu_process_callbacks+0x260/0x42a +[ 1357.238450] [] __do_softirq+0x13a/0x26f +[ 1357.238450] [] ? __schedule+0x65f/0x68e +[ 1357.238450] [] run_ksoftirqd+0x29/0x62 +[ 1357.238450] [] smpboot_thread_fn+0x1a5/0x1aa +[ 1357.238450] [] ? smpboot_unregister_percpu_thread+0x47/0x47 +[ 1357.238450] [] kthread+0xb1/0xb9 +[ 1357.238450] [] ? wait_for_common+0xbb/0x10a +[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 +[ 1357.238450] [] ret_from_fork+0x7c/0xb0 +[ 1357.238450] [] ? __init_kthread_worker+0x59/0x59 +[ 1417.440099] rport-2:0-0: blocked FC remote port time out: removing rport + +Signed-off-by: Yi Zou +Cc: Open-FCoE +Cc: Nicholas A. Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/tcm_fc/tfc_sess.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/target/tcm_fc/tfc_sess.c ++++ b/drivers/target/tcm_fc/tfc_sess.c +@@ -430,7 +430,6 @@ static void ft_sess_rcu_free(struct rcu_ + { + struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); + +- transport_deregister_session(sess->se_sess); + kfree(sess); + } + +@@ -438,6 +437,7 @@ static void ft_sess_free(struct kref *kr + { + struct ft_sess *sess = container_of(kref, struct ft_sess, kref); + ++ transport_deregister_session(sess->se_sess); + call_rcu(&sess->rcu, ft_sess_rcu_free); + } + +From e1fe2060d7e8f58a69374135e32e90f0bb79a7fd Mon Sep 17 00:00:00 2001 +From: Chris Boot +Date: Tue, 11 Dec 2012 21:58:48 +0000 +Subject: sbp-target: fix error path in sbp_make_tpg() + +From: Chris Boot + +commit e1fe2060d7e8f58a69374135e32e90f0bb79a7fd upstream. + +If the TPG memory is allocated successfully, but we fail further along +in the function, a dangling pointer to freed memory is left in the TPort +structure. This is mostly harmless, but does prevent re-trying the +operation without first removing the TPort altogether. + +Reported-by: Chen Gang +Signed-off-by: Chris Boot +Cc: Andy Grover +Cc: Nicholas A. Bellinger +Signed-off-by: Nicholas Bellinger +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/target/sbp/sbp_target.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/target/sbp/sbp_target.c ++++ b/drivers/target/sbp/sbp_target.c +@@ -2207,20 +2207,23 @@ static struct se_portal_group *sbp_make_ + tport->mgt_agt = sbp_management_agent_register(tport); + if (IS_ERR(tport->mgt_agt)) { + ret = PTR_ERR(tport->mgt_agt); +- kfree(tpg); +- return ERR_PTR(ret); ++ goto out_free_tpg; + } + + ret = core_tpg_register(&sbp_fabric_configfs->tf_ops, wwn, + &tpg->se_tpg, (void *)tpg, + TRANSPORT_TPG_TYPE_NORMAL); +- if (ret < 0) { +- sbp_management_agent_unregister(tport->mgt_agt); +- kfree(tpg); +- return ERR_PTR(ret); +- } ++ if (ret < 0) ++ goto out_unreg_mgt_agt; + + return &tpg->se_tpg; ++ ++out_unreg_mgt_agt: ++ sbp_management_agent_unregister(tport->mgt_agt); ++out_free_tpg: ++ tport->tpg = NULL; ++ kfree(tpg); ++ return ERR_PTR(ret); + } + + static void sbp_drop_tpg(struct se_portal_group *se_tpg) +From fee546ce8cfd9dea1f53175f627e17ef5ff05df4 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 23 Nov 2012 12:05:33 +0900 +Subject: mfd: wm8994: Add support for WM1811 rev E + +From: Mark Brown + +commit fee546ce8cfd9dea1f53175f627e17ef5ff05df4 upstream. + +This is supported identically to the previous revisions. + +Signed-off-by: Mark Brown +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mfd/wm8994-core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mfd/wm8994-core.c ++++ b/drivers/mfd/wm8994-core.c +@@ -557,6 +557,7 @@ static __devinit int wm8994_device_init( + case 1: + case 2: + case 3: ++ case 4: + regmap_patch = wm1811_reva_patch; + patch_regs = ARRAY_SIZE(wm1811_reva_patch); + break; +From b9fbb62eb61452d728c39b2e5020739c575aac53 Mon Sep 17 00:00:00 2001 +From: Charles Keepax +Date: Fri, 9 Nov 2012 16:15:28 +0000 +Subject: mfd: Only unregister platform devices allocated by the mfd core + +From: Charles Keepax + +commit b9fbb62eb61452d728c39b2e5020739c575aac53 upstream. + +mfd_remove_devices would iterate over all devices sharing a parent with +an mfd device regardless of whether they were allocated by the mfd core +or not. This especially caused problems when the device structure was +not contained within a platform_device, because to_platform_device is +used on each device pointer. + +This patch defines a device_type for mfd devices and checks this is +present from mfd_remove_devices_fn before processing the device. + +Signed-off-by: Charles Keepax +Tested-by: Peter Tyser +Reviewed-by: Mark Brown +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mfd/mfd-core.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/mfd/mfd-core.c ++++ b/drivers/mfd/mfd-core.c +@@ -21,6 +21,10 @@ + #include + #include + ++static struct device_type mfd_dev_type = { ++ .name = "mfd_device", ++}; ++ + int mfd_cell_enable(struct platform_device *pdev) + { + const struct mfd_cell *cell = mfd_get_cell(pdev); +@@ -91,6 +95,7 @@ static int mfd_add_device(struct device + goto fail_device; + + pdev->dev.parent = parent; ++ pdev->dev.type = &mfd_dev_type; + + if (parent->of_node && cell->of_compatible) { + for_each_child_of_node(parent->of_node, np) { +@@ -204,10 +209,16 @@ EXPORT_SYMBOL(mfd_add_devices); + + static int mfd_remove_devices_fn(struct device *dev, void *c) + { +- struct platform_device *pdev = to_platform_device(dev); +- const struct mfd_cell *cell = mfd_get_cell(pdev); ++ struct platform_device *pdev; ++ const struct mfd_cell *cell; + atomic_t **usage_count = c; + ++ if (dev->type != &mfd_dev_type) ++ return 0; ++ ++ pdev = to_platform_device(dev); ++ cell = mfd_get_cell(pdev); ++ + /* find the base address of usage_count pointers (for freeing) */ + if (!*usage_count || (cell->usage_count < *usage_count)) + *usage_count = cell->usage_count; +From 90a38d999739f35f4fc925c875e6ee518546b66c Mon Sep 17 00:00:00 2001 +From: Geert Uytterhoeven +Date: Mon, 15 Oct 2012 22:44:45 +0200 +Subject: mfd: Remove Unicode Byte Order Marks from da9055 + +From: Geert Uytterhoeven + +commit 90a38d999739f35f4fc925c875e6ee518546b66c upstream. + +Older gcc (< 4.4) doesn't like files starting with Unicode BOMs: + +include/linux/mfd/da9055/core.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/core.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/core.h:1: error: stray ‘\277’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/pdata.h:1: error: stray ‘\277’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\357’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\273’ in program +include/linux/mfd/da9055/reg.h:1: error: stray ‘\277’ in program + +Remove the BOMs, the rest of the files is plain ASCII anyway. + +Output of "file" before: + +include/linux/mfd/da9055/core.h: UTF-8 Unicode (with BOM) C program text +include/linux/mfd/da9055/pdata.h: UTF-8 Unicode (with BOM) C program text +include/linux/mfd/da9055/reg.h: UTF-8 Unicode (with BOM) C program text + +Output of "file" after: + +include/linux/mfd/da9055/core.h: ASCII C program text +include/linux/mfd/da9055/pdata.h: ASCII C program text +include/linux/mfd/da9055/reg.h: ASCII C program text + +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Samuel Ortiz +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/mfd/da9055/core.h | 2 +- + include/linux/mfd/da9055/pdata.h | 2 +- + include/linux/mfd/da9055/reg.h | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/include/linux/mfd/da9055/core.h ++++ b/include/linux/mfd/da9055/core.h +@@ -1,4 +1,4 @@ +-/* ++/* + * da9055 declarations for DA9055 PMICs. + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. +--- a/include/linux/mfd/da9055/pdata.h ++++ b/include/linux/mfd/da9055/pdata.h +@@ -1,4 +1,4 @@ +-/* Copyright (C) 2012 Dialog Semiconductor Ltd. ++/* Copyright (C) 2012 Dialog Semiconductor Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +--- a/include/linux/mfd/da9055/reg.h ++++ b/include/linux/mfd/da9055/reg.h +@@ -1,4 +1,4 @@ +-/* ++/* + * DA9055 declarations for DA9055 PMICs. + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. +From 24ec19b0ae83a385ad9c55520716da671274b96c Mon Sep 17 00:00:00 2001 +From: Eugene Shatokhin +Date: Thu, 8 Nov 2012 15:11:11 -0500 +Subject: ext4: fix memory leak in ext4_xattr_set_acl()'s error path + +From: Eugene Shatokhin + +commit 24ec19b0ae83a385ad9c55520716da671274b96c upstream. + +In ext4_xattr_set_acl(), if ext4_journal_start() returns an error, +posix_acl_release() will not be called for 'acl' which may result in a +memory leak. + +This patch fixes that. + +Reviewed-by: Lukas Czerner +Signed-off-by: Eugene Shatokhin +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/acl.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/ext4/acl.c ++++ b/fs/ext4/acl.c +@@ -423,8 +423,10 @@ ext4_xattr_set_acl(struct dentry *dentry + + retry: + handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ error = PTR_ERR(handle); ++ goto release_and_out; ++ } + error = ext4_set_acl(handle, inode, type, acl); + ext4_journal_stop(handle); + if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) +From aeb1e5d69a5be592e86a926be73efb38c55af404 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 29 Nov 2012 21:21:22 -0500 +Subject: ext4: fix possible use after free with metadata csum + +From: Theodore Ts'o + +commit aeb1e5d69a5be592e86a926be73efb38c55af404 upstream. + +Commit fa77dcfafeaa introduces block bitmap checksum calculation into +ext4_new_inode() in the case that block group was uninitialized. +However we brelse() the bitmap buffer before we attempt to checksum it +so we have no guarantee that the buffer is still there. + +Fix this by releasing the buffer after the possible checksum +computation. + +Signed-off-by: Lukas Czerner +Signed-off-by: "Theodore Ts'o" +Acked-by: Darrick J. Wong +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ialloc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -762,7 +762,6 @@ got: + + BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); + err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh); +- brelse(block_bitmap_bh); + + /* recheck and clear flag under lock if we still need to */ + ext4_lock_group(sb, group); +@@ -775,6 +774,7 @@ got: + ext4_group_desc_csum_set(sb, group, gdp); + } + ext4_unlock_group(sb, group); ++ brelse(block_bitmap_bh); + + if (err) + goto fail; +From d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee Mon Sep 17 00:00:00 2001 +From: Nathan Williams +Date: Thu, 22 Nov 2012 10:42:52 +1100 +Subject: mtd cs553x_nand: Initialise ecc.strength before nand_scan() + +From: Nathan Williams + +commit d1f3b65d2d6fdb4bf0edd4b67e86e191af48daee upstream. + +Loading cs553x_nand with Hynix H27U1G8F2BTR NAND flash causes this bug: + +kernel BUG at drivers/mtd/nand/nand_base.c:3345! +invalid opcode: 0000 [#1] +Modules linked in: cs553x_nand(+) vfat fat usb_storage ehci_hcd usbcore usb_comr +Pid: 436, comm: modprobe Not tainted 3.6.7 #1 +EIP: 0060:[] EFLAGS: 00010296 CPU: 0 +EIP is at nand_scan_tail+0x64c/0x69c +EAX: 00000034 EBX: cea6ed98 ECX: 00000000 EDX: 00000000 +ESI: cea6ec00 EDI: cea6ec00 EBP: 20000000 ESP: cdd17e48 + DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068 +CR0: 8005003b CR2: 0804e119 CR3: 0d850000 CR4: 00000090 +DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 +DR6: ffff0ff0 DR7: 00000400 +Process modprobe (pid: 436, ti=cdd16000 task=cdd1c320 task.ti=cdd16000) +Stack: + c12e962c c118f7ef 00000003 cea6ed98 d014b25c 20000000 fffff007 00000001 + 00000000 cdd53b00 d014b000 c1001021 cdd53b00 d01493c0 cdd53b00 cdd53b00 + d01493c0 c1047f83 d014b4a0 00000000 cdd17f9c ce4be454 cdd17f48 cdd1c320 +Call Trace: + [] ? nand_scan+0x1b/0x4d + [] ? init_module+0x25c/0x2de [cs553x_nand] + [] ? 0xd014afff + [] ? do_one_initcall+0x21/0x111 + [] ? sys_init_module+0xe4/0x1261 + [] ? task_work_run+0x36/0x43 + [] ? syscall_call+0x7/0xb +Code: fa ff ff c7 86 d8 00 00 00 01 00 00 00 e9 5f fc ff ff 68 f8 26 2e c1 e8 a7 +EIP: [] nand_scan_tail+0x64c/0x69c SS:ESP 0068:cdd17e48 + +Initialising ecc.strength before the call to nand_scan() fixes this. + +Signed-off-by: Nathan Williams +Acked-by: Brian Norris +Acked-by: Mike Dunn +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/nand/cs553x_nand.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/mtd/nand/cs553x_nand.c ++++ b/drivers/mtd/nand/cs553x_nand.c +@@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs + this->ecc.hwctl = cs_enable_hwecc; + this->ecc.calculate = cs_calculate_ecc; + this->ecc.correct = nand_correct_data; ++ this->ecc.strength = 1; + + /* Enable the following for a flash based bad block table */ + this->bbt_options = NAND_BBT_USE_FLASH; +@@ -247,8 +248,6 @@ static int __init cs553x_init_one(int cs + goto out_ior; + } + +- this->ecc.strength = 1; +- + new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); + + cs553x_mtd[cs] = new_mtd; +From 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 Mon Sep 17 00:00:00 2001 +From: Wolfram Sang +Date: Wed, 5 Dec 2012 21:46:02 +0100 +Subject: mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems + +From: Wolfram Sang + +commit 6f2a6a52560ad8d85710aabd92b7a3239b3a6b07 upstream. + +It could happen (1 out of 100 times) that NAND did not start up +correctly after warm rebooting, so the kernel could not find the UBI or +DMA timed out due to a stalled BCH. When resetting BCH together with +GPMI, the issue could not be observed anymore (after 10000+ reboots). We +probably need the consistent state already before sending any command to +NAND, even when no ECC is needed. I chose to keep the extra reset for +BCH when changing the flash layout to be on the safe side. + +Signed-off-by: Wolfram Sang +Acked-by: Huang Shijie +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c ++++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +@@ -166,6 +166,15 @@ int gpmi_init(struct gpmi_nand_data *thi + if (ret) + goto err_out; + ++ /* ++ * Reset BCH here, too. We got failures otherwise :( ++ * See later BCH reset for explanation of MX23 handling ++ */ ++ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); ++ if (ret) ++ goto err_out; ++ ++ + /* Choose NAND mode. */ + writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); + +From bd1ee804af8bdf2fd5131234330615f8aecbd9ed Mon Sep 17 00:00:00 2001 +From: Pawel Moll +Date: Mon, 29 Oct 2012 11:23:02 +0000 +Subject: kbuild: Do not remove vmlinux when cleaning external module + +From: Pawel Moll + +commit bd1ee804af8bdf2fd5131234330615f8aecbd9ed upstream. + +Since commit 1f2bfbd00e466ff3489b2ca5cc75b1cccd14c123 "kbuild: +link of vmlinux moved to a script" make clean with M= +argument (so cleaning external module) removes vmlinux, +System.map and couple of other files from the *main* kernel +build directory! This not what was happening before and almost +certainly not what one would expect. + +This patch moves makes the clean target of the script called +only when !KBUILD_EXTMOD. + +Signed-off-by: Pawel Moll +Signed-off-by: Michal Marek +Signed-off-by: Greg Kroah-Hartman + +--- + Makefile | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/Makefile ++++ b/Makefile +@@ -1021,11 +1021,14 @@ clean: rm-dirs := $(CLEAN_DIRS) + clean: rm-files := $(CLEAN_FILES) + clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples) + +-PHONY += $(clean-dirs) clean archclean ++PHONY += $(clean-dirs) clean archclean vmlinuxclean + $(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +-clean: archclean ++vmlinuxclean: ++ $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean ++ ++clean: archclean vmlinuxclean + + # mrproper - Delete all generated files, including .config + # +@@ -1252,7 +1255,6 @@ scripts: ; + endif # KBUILD_EXTMOD + + clean: $(clean-dirs) +- $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ +From ca2e16faa7378878c1522a7c1b6c38211de3331d Mon Sep 17 00:00:00 2001 +From: Tomi Valkeinen +Date: Thu, 22 Nov 2012 10:39:56 +0200 +Subject: OMAP: board-files: fix i2c_bus for tfp410 + +From: Tomi Valkeinen + +commit ca2e16faa7378878c1522a7c1b6c38211de3331d upstream. + +The i2c handling in tfp410 driver, which handles converting parallel RGB +to DVI, was changed in 958f2717b84e88bf833d996997fda8f73276f2af +(OMAPDSS: TFP410: pdata rewrite). The patch changed what value the +driver considers as invalid/undefined. Before the patch, 0 was the +invalid value, but as 0 is a valid bus number, the patch changed this to +-1. + +However, the fact was missed that many board files do not define the bus +number at all, thus it's left to 0. This causes the driver to fail to +get the i2c bus, exiting from the driver's probe with an error, meaning +that the DVI output does not work for those boards. + +This patch fixes the issue by changing the i2c_bus number field in the +driver's platform data from u16 to int, and setting the bus number to -1 +in the board files for the boards that did not define the bus. The +exception is devkit8000, for which the bus is set to 1, which is the +correct bus for that board. + +The bug exists in v3.5+ kernels. + +Signed-off-by: Tomi Valkeinen +Reported-by: Thomas Weber +Cc: Thomas Weber +Signed-off-by: Tony Lindgren +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-omap2/board-3430sdp.c | 1 + + arch/arm/mach-omap2/board-am3517evm.c | 1 + + arch/arm/mach-omap2/board-cm-t35.c | 1 + + arch/arm/mach-omap2/board-devkit8000.c | 1 + + arch/arm/mach-omap2/board-omap3evm.c | 1 + + arch/arm/mach-omap2/board-omap3stalker.c | 1 + + include/video/omap-panel-tfp410.h | 2 +- + 7 files changed, 7 insertions(+), 1 deletion(-) + +--- a/arch/arm/mach-omap2/board-3430sdp.c ++++ b/arch/arm/mach-omap2/board-3430sdp.c +@@ -157,6 +157,7 @@ static struct omap_dss_device sdp3430_lc + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device sdp3430_dvi_device = { +--- a/arch/arm/mach-omap2/board-am3517evm.c ++++ b/arch/arm/mach-omap2/board-am3517evm.c +@@ -208,6 +208,7 @@ static struct omap_dss_device am3517_evm + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device am3517_evm_dvi_device = { +--- a/arch/arm/mach-omap2/board-cm-t35.c ++++ b/arch/arm/mach-omap2/board-cm-t35.c +@@ -243,6 +243,7 @@ static struct omap_dss_device cm_t35_lcd + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = CM_T35_DVI_EN_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device cm_t35_dvi_device = { +--- a/arch/arm/mach-omap2/board-devkit8000.c ++++ b/arch/arm/mach-omap2/board-devkit8000.c +@@ -139,6 +139,7 @@ static struct omap_dss_device devkit8000 + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = -1, ++ .i2c_bus_num = 1, + }; + + static struct omap_dss_device devkit8000_dvi_device = { +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -236,6 +236,7 @@ static struct omap_dss_device omap3_evm_ + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = OMAP3EVM_DVI_PANEL_EN_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device omap3_evm_dvi_device = { +--- a/arch/arm/mach-omap2/board-omap3stalker.c ++++ b/arch/arm/mach-omap2/board-omap3stalker.c +@@ -119,6 +119,7 @@ static struct omap_dss_device omap3_stal + + static struct tfp410_platform_data dvi_panel = { + .power_down_gpio = DSS_ENABLE_GPIO, ++ .i2c_bus_num = -1, + }; + + static struct omap_dss_device omap3_stalker_dvi_device = { +--- a/include/video/omap-panel-tfp410.h ++++ b/include/video/omap-panel-tfp410.h +@@ -28,7 +28,7 @@ struct omap_dss_device; + * @power_down_gpio: gpio number for PD pin (or -1 if not available) + */ + struct tfp410_platform_data { +- u16 i2c_bus_num; ++ int i2c_bus_num; + int power_down_gpio; + }; + +From 642fe4d00db56d65060ce2fd4c105884414acb16 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 8 Nov 2012 10:01:26 -0500 +Subject: SUNRPC: Fix validity issues with rpc_pipefs sb->s_fs_info + +From: Trond Myklebust + +commit 642fe4d00db56d65060ce2fd4c105884414acb16 upstream. + +rpc_kill_sb() must defer calling put_net() until after the notifier +has been called, since most (all?) of the notifier callbacks assume +that sb->s_fs_info points to a valid net namespace. It also must not +call put_net() if the call to rpc_fill_super was unsuccessful. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=48421 + +Signed-off-by: Trond Myklebust +Cc: Stanislav Kinsbursky +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/rpc_pipe.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -1152,14 +1152,19 @@ static void rpc_kill_sb(struct super_blo + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); + + mutex_lock(&sn->pipefs_sb_lock); ++ if (sn->pipefs_sb != sb) { ++ mutex_unlock(&sn->pipefs_sb_lock); ++ goto out; ++ } + sn->pipefs_sb = NULL; + mutex_unlock(&sn->pipefs_sb_lock); +- put_net(net); + dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", + net, NET_NAME(net)); + blocking_notifier_call_chain(&rpc_pipefs_notifier_list, + RPC_PIPEFS_UMOUNT, + sb); ++ put_net(net); ++out: + kill_litter_super(sb); + } + +From cd6c5968582a273561464fe6b1e8cc8214be02df Mon Sep 17 00:00:00 2001 +From: Stanislav Kinsbursky +Date: Mon, 17 Dec 2012 20:18:52 +0300 +Subject: SUNRPC: continue run over clients list on PipeFS event instead of break + +From: Stanislav Kinsbursky + +commit cd6c5968582a273561464fe6b1e8cc8214be02df upstream. + +There are SUNRPC clients, which program doesn't have pipe_dir_name. These +clients can be skipped on PipeFS events, because nothing have to be created or +destroyed. But instead of breaking in case of such a client was found, search +for suitable client over clients list have to be continued. Otherwise some +clients could not be covered by PipeFS event handler. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/clnt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sunrpc/clnt.c ++++ b/net/sunrpc/clnt.c +@@ -234,7 +234,7 @@ static struct rpc_clnt *rpc_get_client_f + spin_lock(&sn->rpc_client_lock); + list_for_each_entry(clnt, &sn->all_clients, cl_clients) { + if (clnt->cl_program->pipe_dir_name == NULL) +- break; ++ continue; + if (rpc_clnt_skip_event(clnt, event)) + continue; + if (atomic_inc_not_zero(&clnt->cl_count) == 0) +From 621eb19ce1ec216e03ad354cb0c4061736b2a436 Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Wed, 14 Nov 2012 10:48:05 -0500 +Subject: svcrpc: Revert "sunrpc/cache.h: replace simple_strtoul" + +From: "J. Bruce Fields" + +commit 621eb19ce1ec216e03ad354cb0c4061736b2a436 upstream. + +Commit bbf43dc888833ac0539e437dbaeb28bfd4fbab9f "sunrpc/cache.h: replace +simple_strtoul" introduced new range-checking which could cause get_int +to fail on unsigned integers too large to be represented as an int. + +We could parse them as unsigned instead--but it turns out svcgssd is +actually passing down "-1" in some cases. Which is perhaps stupid, but +there's nothing we can do about it now. + +So just revert back to the previous "sloppy" behavior that accepts +either representation. + +Reported-by: Sven Geggus +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/sunrpc/cache.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/include/linux/sunrpc/cache.h ++++ b/include/linux/sunrpc/cache.h +@@ -217,6 +217,8 @@ extern int qword_get(char **bpp, char *d + static inline int get_int(char **bpp, int *anint) + { + char buf[50]; ++ char *ep; ++ int rv; + int len = qword_get(bpp, buf, sizeof(buf)); + + if (len < 0) +@@ -224,9 +226,11 @@ static inline int get_int(char **bpp, in + if (len == 0) + return -ENOENT; + +- if (kstrtoint(buf, 0, anint)) ++ rv = simple_strtol(buf, &ep, 0); ++ if (*ep) + return -EINVAL; + ++ *anint = rv; + return 0; + } + +From c6567ed1402c55e19b012e66a8398baec2a726f3 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 4 Jan 2013 12:23:21 -0500 +Subject: SUNRPC: Ensure that we free the rpc_task after cleanups are done + +From: Trond Myklebust + +commit c6567ed1402c55e19b012e66a8398baec2a726f3 upstream. + +This patch ensures that we free the rpc_task after the cleanup callbacks +are done in order to avoid a deadlock problem that can be triggered if +the callback needs to wait for another workqueue item to complete. + +Signed-off-by: Trond Myklebust +Cc: Weston Andros Adamson +Cc: Tejun Heo +Cc: Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/sched.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -919,16 +919,35 @@ struct rpc_task *rpc_new_task(const stru + return task; + } + ++/* ++ * rpc_free_task - release rpc task and perform cleanups ++ * ++ * Note that we free up the rpc_task _after_ rpc_release_calldata() ++ * in order to work around a workqueue dependency issue. ++ * ++ * Tejun Heo states: ++ * "Workqueue currently considers two work items to be the same if they're ++ * on the same address and won't execute them concurrently - ie. it ++ * makes a work item which is queued again while being executed wait ++ * for the previous execution to complete. ++ * ++ * If a work function frees the work item, and then waits for an event ++ * which should be performed by another work item and *that* work item ++ * recycles the freed work item, it can create a false dependency loop. ++ * There really is no reliable way to detect this short of verifying ++ * every memory free." ++ * ++ */ + static void rpc_free_task(struct rpc_task *task) + { +- const struct rpc_call_ops *tk_ops = task->tk_ops; +- void *calldata = task->tk_calldata; ++ unsigned short tk_flags = task->tk_flags; + +- if (task->tk_flags & RPC_TASK_DYNAMIC) { ++ rpc_release_calldata(task->tk_ops, task->tk_calldata); ++ ++ if (tk_flags & RPC_TASK_DYNAMIC) { + dprintk("RPC: %5u freeing task\n", task->tk_pid); + mempool_free(task, rpc_task_mempool); + } +- rpc_release_calldata(tk_ops, calldata); + } + + static void rpc_async_release(struct work_struct *work) +From 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Mon, 7 Jan 2013 14:30:46 -0500 +Subject: SUNRPC: Ensure we release the socket write lock if the rpc_task exits early + +From: Trond Myklebust + +commit 87ed50036b866db2ec2ba16b2a7aec4a2b0b7c39 upstream. + +If the rpc_task exits while holding the socket write lock before it has +allocated an rpc slot, then the usual mechanism for releasing the write +lock in xprt_release() is defeated. + +The problem occurs if the call to xprt_lock_write() initially fails, so +that the rpc_task is put on the xprt->sending wait queue. If the task +exits after being assigned the lock by __xprt_lock_write_func, but +before it has retried the call to xprt_lock_and_alloc_slot(), then +it calls xprt_release() while holding the write lock, but will +immediately exit due to the test for task->tk_rqstp != NULL. + +Reported-by: Chris Perl +Signed-off-by: Trond Myklebust +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/sched.c | 3 +-- + net/sunrpc/xprt.c | 12 ++++++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +--- a/net/sunrpc/sched.c ++++ b/net/sunrpc/sched.c +@@ -957,8 +957,7 @@ static void rpc_async_release(struct wor + + static void rpc_release_resources_task(struct rpc_task *task) + { +- if (task->tk_rqstp) +- xprt_release(task); ++ xprt_release(task); + if (task->tk_msg.rpc_cred) { + put_rpccred(task->tk_msg.rpc_cred); + task->tk_msg.rpc_cred = NULL; +--- a/net/sunrpc/xprt.c ++++ b/net/sunrpc/xprt.c +@@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc + void xprt_release(struct rpc_task *task) + { + struct rpc_xprt *xprt; +- struct rpc_rqst *req; ++ struct rpc_rqst *req = task->tk_rqstp; + +- if (!(req = task->tk_rqstp)) ++ if (req == NULL) { ++ if (task->tk_client) { ++ rcu_read_lock(); ++ xprt = rcu_dereference(task->tk_client->cl_xprt); ++ if (xprt->snd_task == task) ++ xprt_release_write(xprt, task); ++ rcu_read_unlock(); ++ } + return; ++ } + + xprt = req->rq_xprt; + if (task->tk_ops->rpc_count_stats != NULL) +From 2cbba75a56ea78e6876b4e2547a882f10b3fe72b Mon Sep 17 00:00:00 2001 +From: Alexey Khoroshilov +Date: Mon, 5 Nov 2012 22:40:14 +0400 +Subject: jffs2: hold erase_completion_lock on exit + +From: Alexey Khoroshilov + +commit 2cbba75a56ea78e6876b4e2547a882f10b3fe72b upstream. + +Users of jffs2_do_reserve_space() expect they still held +erase_completion_lock after call to it. But there is a path +where jffs2_do_reserve_space() leaves erase_completion_lock unlocked. +The patch fixes it. + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov +Signed-off-by: Artem Bityutskiy +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/nodemgmt.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/fs/jffs2/nodemgmt.c ++++ b/fs/jffs2/nodemgmt.c +@@ -417,14 +417,16 @@ static int jffs2_do_reserve_space(struct + spin_unlock(&c->erase_completion_lock); + + ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); +- if (ret) +- return ret; ++ + /* Just lock it again and continue. Nothing much can change because + we hold c->alloc_sem anyway. In fact, it's not entirely clear why + we hold c->erase_completion_lock in the majority of this function... + but that's a question for another (more caffeine-rich) day. */ + spin_lock(&c->erase_completion_lock); + ++ if (ret) ++ return ret; ++ + waste = jeb->free_size; + jffs2_link_node_ref(c, jeb, + (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, +From 999a7c5776a0ed2133645fa7e008bec05bda9254 Mon Sep 17 00:00:00 2001 +From: Dan Williams +Date: Fri, 14 Dec 2012 13:10:50 +0000 +Subject: i2400m: add Intel 6150 device IDs + +From: Dan Williams + +commit 999a7c5776a0ed2133645fa7e008bec05bda9254 upstream. + +Add device IDs for WiMAX function of Intel 6150 cards. + +Signed-off-by: Dan Williams +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wimax/i2400m/i2400m-usb.h | 3 +++ + drivers/net/wimax/i2400m/usb.c | 6 ++++++ + 2 files changed, 9 insertions(+) + +--- a/drivers/net/wimax/i2400m/i2400m-usb.h ++++ b/drivers/net/wimax/i2400m/i2400m-usb.h +@@ -152,6 +152,9 @@ enum { + /* Device IDs */ + USB_DEVICE_ID_I6050 = 0x0186, + USB_DEVICE_ID_I6050_2 = 0x0188, ++ USB_DEVICE_ID_I6150 = 0x07d6, ++ USB_DEVICE_ID_I6150_2 = 0x07d7, ++ USB_DEVICE_ID_I6150_3 = 0x07d9, + USB_DEVICE_ID_I6250 = 0x0187, + }; + +--- a/drivers/net/wimax/i2400m/usb.c ++++ b/drivers/net/wimax/i2400m/usb.c +@@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface * + switch (id->idProduct) { + case USB_DEVICE_ID_I6050: + case USB_DEVICE_ID_I6050_2: ++ case USB_DEVICE_ID_I6150: ++ case USB_DEVICE_ID_I6150_2: ++ case USB_DEVICE_ID_I6150_3: + case USB_DEVICE_ID_I6250: + i2400mu->i6050 = 1; + break; +@@ -759,6 +762,9 @@ static + struct usb_device_id i2400mu_id_table[] = { + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, ++ { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, + { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, + { USB_DEVICE(0x8086, 0x0181) }, + { USB_DEVICE(0x8086, 0x1403) }, +From 6491d4d02893d9787ba67279595990217177b351 Mon Sep 17 00:00:00 2001 +From: "Woodhouse, David" +Date: Wed, 19 Dec 2012 13:25:35 +0000 +Subject: intel-iommu: Free old page tables before creating superpage + +From: "Woodhouse, David" + +commit 6491d4d02893d9787ba67279595990217177b351 upstream. + +The dma_pte_free_pagetable() function will only free a page table page +if it is asked to free the *entire* 2MiB range that it covers. So if a +page table page was used for one or more small mappings, it's likely to +end up still present in the page tables... but with no valid PTEs. + +This was fine when we'd only be repopulating it with 4KiB PTEs anyway +but the same virtual address range can end up being reused for a +*large-page* mapping. And in that case were were trying to insert the +large page into the second-level page table, and getting a complaint +from the sanity check in __domain_mapping() because there was already a +corresponding entry. This was *relatively* harmless; it led to a memory +leak of the old page table page, but no other ill-effects. + +Fix it by calling dma_pte_clear_range (hopefully redundant) and +dma_pte_free_pagetable() before setting up the new large page. + +Signed-off-by: David Woodhouse +Tested-by: Ravi Murty +Tested-by: Sudeep Dutt +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/intel-iommu.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/iommu/intel-iommu.c ++++ b/drivers/iommu/intel-iommu.c +@@ -1827,10 +1827,17 @@ static int __domain_mapping(struct dmar_ + if (!pte) + return -ENOMEM; + /* It is large page*/ +- if (largepage_lvl > 1) ++ if (largepage_lvl > 1) { + pteval |= DMA_PTE_LARGE_PAGE; +- else ++ /* Ensure that old small page tables are removed to make room ++ for superpage, if they exist. */ ++ dma_pte_clear_range(domain, iov_pfn, ++ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); ++ dma_pte_free_pagetable(domain, iov_pfn, ++ iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); ++ } else { + pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; ++ } + + } + /* We don't need lock here, nobody else +From ae133a1129790ec288b429b5f08ab4701633844a Mon Sep 17 00:00:00 2001 +From: Christian König +Date: Tue, 18 Sep 2012 15:30:44 -0400 +Subject: drm/radeon: stop page faults from hanging the system (v2) + +From: Christian König + +commit ae133a1129790ec288b429b5f08ab4701633844a upstream. + +Redirect invalid memory accesses to the default page +instead of locking up the memory controller. Also +enable the invalid memory access interrupts and +start spamming system log with it. + +v2 (agd5f): fix up against 2 level PT changes + +Signed-off-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 10 ++++++++++ + drivers/gpu/drm/radeon/evergreend.h | 3 +++ + drivers/gpu/drm/radeon/ni.c | 16 +++++++++++++--- + drivers/gpu/drm/radeon/nid.h | 11 +++++++++++ + drivers/gpu/drm/radeon/si.c | 25 +++++++++++++++++++++++-- + drivers/gpu/drm/radeon/sid.h | 14 ++++++++++++++ + 6 files changed, 74 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -3093,6 +3093,16 @@ restart_ih: + break; + } + break; ++ case 146: ++ case 147: ++ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); ++ /* reset addr and status */ ++ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); ++ break; + case 176: /* CP_INT in ring buffer */ + case 177: /* CP_INT in IB1 */ + case 178: /* CP_INT in IB2 */ +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -651,6 +651,7 @@ + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) + #define VM_CONTEXT1_CNTL 0x1414 ++#define VM_CONTEXT1_CNTL2 0x1434 + #define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153C + #define VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157C + #define VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155C +@@ -672,6 +673,8 @@ + #define CACHE_UPDATE_MODE(x) ((x) << 6) + #define VM_L2_STATUS 0x140C + #define L2_BUSY (1 << 0) ++#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC ++#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC + + #define WAIT_UNTIL 0x8040 + +--- a/drivers/gpu/drm/radeon/ni.c ++++ b/drivers/gpu/drm/radeon/ni.c +@@ -784,10 +784,20 @@ static int cayman_pcie_gart_enable(struc + /* enable context1-7 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); +- WREG32(VM_CONTEXT1_CNTL2, 0); +- WREG32(VM_CONTEXT1_CNTL, 0); ++ WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | +- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | ++ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | ++ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ READ_PROTECTION_FAULT_ENABLE_DEFAULT | ++ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + cayman_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +--- a/drivers/gpu/drm/radeon/nid.h ++++ b/drivers/gpu/drm/radeon/nid.h +@@ -80,7 +80,18 @@ + #define VM_CONTEXT0_CNTL 0x1410 + #define ENABLE_CONTEXT (1 << 0) + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) ++#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) ++#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) ++#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) ++#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) ++#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) ++#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) ++#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) ++#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) + #define VM_CONTEXT1_CNTL 0x1414 + #define VM_CONTEXT0_CNTL2 0x1430 + #define VM_CONTEXT1_CNTL2 0x1434 +--- a/drivers/gpu/drm/radeon/si.c ++++ b/drivers/gpu/drm/radeon/si.c +@@ -2426,9 +2426,20 @@ static int si_pcie_gart_enable(struct ra + /* enable context1-15 */ + WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR, + (u32)(rdev->dummy_page.addr >> 12)); +- WREG32(VM_CONTEXT1_CNTL2, 0); ++ WREG32(VM_CONTEXT1_CNTL2, 4); + WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) | +- RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); ++ RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ RANGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT | ++ PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ PDE0_PROTECTION_FAULT_ENABLE_DEFAULT | ++ VALID_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ VALID_PROTECTION_FAULT_ENABLE_DEFAULT | ++ READ_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ READ_PROTECTION_FAULT_ENABLE_DEFAULT | ++ WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT | ++ WRITE_PROTECTION_FAULT_ENABLE_DEFAULT); + + si_pcie_gart_tlb_flush(rdev); + DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +@@ -3684,6 +3695,16 @@ restart_ih: + break; + } + break; ++ case 146: ++ case 147: ++ dev_err(rdev->dev, "GPU fault detected: %d 0x%08x\n", src_id, src_data); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR)); ++ dev_err(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", ++ RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); ++ /* reset addr and status */ ++ WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1); ++ break; + case 176: /* RINGID0 CP_INT */ + radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); + break; +--- a/drivers/gpu/drm/radeon/sid.h ++++ b/drivers/gpu/drm/radeon/sid.h +@@ -91,7 +91,18 @@ + #define VM_CONTEXT0_CNTL 0x1410 + #define ENABLE_CONTEXT (1 << 0) + #define PAGE_TABLE_DEPTH(x) (((x) & 3) << 1) ++#define RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 3) + #define RANGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 4) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 6) ++#define DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 7) ++#define PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 9) ++#define PDE0_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 10) ++#define VALID_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 12) ++#define VALID_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 13) ++#define READ_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 15) ++#define READ_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 16) ++#define WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT (1 << 18) ++#define WRITE_PROTECTION_FAULT_ENABLE_DEFAULT (1 << 19) + #define VM_CONTEXT1_CNTL 0x1414 + #define VM_CONTEXT0_CNTL2 0x1430 + #define VM_CONTEXT1_CNTL2 0x1434 +@@ -104,6 +115,9 @@ + #define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x1450 + #define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x1454 + ++#define VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x14FC ++#define VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x14DC ++ + #define VM_INVALIDATE_REQUEST 0x1478 + #define VM_INVALIDATE_RESPONSE 0x147c + +From a02dc74b317d78298cb0587b9b1f6f741fd5c139 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 13 Nov 2012 18:03:41 -0500 +Subject: drm/radeon/dce32+: use fractional fb dividers for high clocks + +From: Alex Deucher + +commit a02dc74b317d78298cb0587b9b1f6f741fd5c139 upstream. + +Fixes flickering with some high res montiors. + +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_crtc.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/gpu/drm/radeon/atombios_crtc.c ++++ b/drivers/gpu/drm/radeon/atombios_crtc.c +@@ -561,6 +561,8 @@ static u32 atombios_adjust_pll(struct dr + /* use frac fb div on APUs */ + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; ++ if (ASIC_IS_DCE32(rdev) && mode->clock > 165000) ++ radeon_crtc->pll_flags |= RADEON_PLL_USE_FRAC_FB_DIV; + } else { + radeon_crtc->pll_flags |= RADEON_PLL_LEGACY; + +From 93927f9c1db5f55085457e820f0631064c7bfa34 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Tue, 4 Dec 2012 16:50:28 -0500 +Subject: drm/radeon: fix eDP clk and lane setup for scaled modes + +From: Alex Deucher + +commit 93927f9c1db5f55085457e820f0631064c7bfa34 upstream. + +Need to use the adjusted mode since we are sending native +timing and using the scaler for non-native modes. + +Signed-off-by: Alex Deucher +Reviewed-by: Jerome Glisse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/atombios_encoders.c ++++ b/drivers/gpu/drm/radeon/atombios_encoders.c +@@ -340,7 +340,7 @@ static bool radeon_atom_mode_fixup(struc + ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || + (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); +- radeon_dp_set_link_config(connector, mode); ++ radeon_dp_set_link_config(connector, adjusted_mode); + } + + return true; +From bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Tue, 11 Dec 2012 11:56:52 -0500 +Subject: drm/radeon: fix amd afusion gpu setup aka sumo v2 + +From: Jerome Glisse + +commit bd25f0783dc3fb72e1e2779c2b99b2d34b67fa8a upstream. + +Set the proper number of tile pipe that should be a multiple of +pipe depending on the number of se engine. + +Fix: +https://bugs.freedesktop.org/show_bug.cgi?id=56405 +https://bugs.freedesktop.org/show_bug.cgi?id=56720 + +v2: Don't change sumo2 + +Signed-off-by: Jerome Glisse +Reviewed-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen.c | 8 ++++---- + drivers/gpu/drm/radeon/evergreend.h | 2 ++ + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/radeon/evergreen.c ++++ b/drivers/gpu/drm/radeon/evergreen.c +@@ -1821,7 +1821,7 @@ static void evergreen_gpu_init(struct ra + case CHIP_SUMO: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 4; +- rdev->config.evergreen.max_tile_pipes = 2; ++ rdev->config.evergreen.max_tile_pipes = 4; + if (rdev->pdev->device == 0x9648) + rdev->config.evergreen.max_simds = 3; + else if ((rdev->pdev->device == 0x9647) || +@@ -1844,7 +1844,7 @@ static void evergreen_gpu_init(struct ra + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; +- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; ++ gb_addr_config = SUMO_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_SUMO2: + rdev->config.evergreen.num_ses = 1; +@@ -1866,7 +1866,7 @@ static void evergreen_gpu_init(struct ra + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; +- gb_addr_config = REDWOOD_GB_ADDR_CONFIG_GOLDEN; ++ gb_addr_config = SUMO2_GB_ADDR_CONFIG_GOLDEN; + break; + case CHIP_BARTS: + rdev->config.evergreen.num_ses = 2; +@@ -1914,7 +1914,7 @@ static void evergreen_gpu_init(struct ra + break; + case CHIP_CAICOS: + rdev->config.evergreen.num_ses = 1; +- rdev->config.evergreen.max_pipes = 4; ++ rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; +--- a/drivers/gpu/drm/radeon/evergreend.h ++++ b/drivers/gpu/drm/radeon/evergreend.h +@@ -45,6 +45,8 @@ + #define TURKS_GB_ADDR_CONFIG_GOLDEN 0x02010002 + #define CEDAR_GB_ADDR_CONFIG_GOLDEN 0x02010001 + #define CAICOS_GB_ADDR_CONFIG_GOLDEN 0x02010001 ++#define SUMO_GB_ADDR_CONFIG_GOLDEN 0x02010002 ++#define SUMO2_GB_ADDR_CONFIG_GOLDEN 0x02010002 + + /* Registers */ + +From d3493574e267c203836bfdcb9c58d8af46fc0da1 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Fri, 14 Dec 2012 16:20:46 -0500 +Subject: drm/radeon: restore modeset late in GPU reset path + +From: Jerome Glisse + +commit d3493574e267c203836bfdcb9c58d8af46fc0da1 upstream. + +Modeset path seems to conflict sometimes with the memory management +leading to kernel deadlock. This move modesetting reset after GPU +acceleration reset. + +Signed-off-by: Jerome Glisse +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_device.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1337,7 +1337,6 @@ retry: + } + + radeon_restore_bios_scratch_regs(rdev); +- drm_helper_resume_force_mode(rdev->ddev); + + if (!r) { + for (i = 0; i < RADEON_NUM_RINGS; ++i) { +@@ -1362,6 +1361,8 @@ retry: + } + } + ++ drm_helper_resume_force_mode(rdev->ddev); ++ + ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); + if (r) { + /* bad news, how to tell it to userspace ? */ +From 76903b96adbfbb38b049765add21e02e44c387a5 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Mon, 17 Dec 2012 10:29:06 -0500 +Subject: drm/radeon: don't leave fence blocked process on failed GPU reset + +From: Jerome Glisse + +commit 76903b96adbfbb38b049765add21e02e44c387a5 upstream. + +Force all fence to signal if GPU reset failed so no process get stuck +on waiting fence. + +Signed-off-by: Jerome Glisse +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon.h | 1 + + drivers/gpu/drm/radeon/radeon_device.c | 1 + + drivers/gpu/drm/radeon/radeon_fence.c | 19 +++++++++++++++++++ + 3 files changed, 21 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -220,6 +220,7 @@ struct radeon_fence { + int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring); + int radeon_fence_driver_init(struct radeon_device *rdev); + void radeon_fence_driver_fini(struct radeon_device *rdev); ++void radeon_fence_driver_force_completion(struct radeon_device *rdev); + int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring); + void radeon_fence_process(struct radeon_device *rdev, int ring); + bool radeon_fence_signaled(struct radeon_fence *fence); +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1356,6 +1356,7 @@ retry: + } + } + } else { ++ radeon_fence_driver_force_completion(rdev); + for (i = 0; i < RADEON_NUM_RINGS; ++i) { + kfree(ring_data[i]); + } +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -868,6 +868,25 @@ void radeon_fence_driver_fini(struct rad + mutex_unlock(&rdev->ring_lock); + } + ++/** ++ * radeon_fence_driver_force_completion - force all fence waiter to complete ++ * ++ * @rdev: radeon device pointer ++ * ++ * In case of GPU reset failure make sure no process keep waiting on fence ++ * that will never complete. ++ */ ++void radeon_fence_driver_force_completion(struct radeon_device *rdev) ++{ ++ int ring; ++ ++ for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { ++ if (!rdev->fence_drv[ring].initialized) ++ continue; ++ radeon_fence_write(rdev, rdev->fence_drv[ring].sync_seq[ring], ring); ++ } ++} ++ + + /* + * Fence debugfs +From 5f8f635edd8ad5a6416bff4c5ff486500357f473 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Mon, 17 Dec 2012 11:04:32 -0500 +Subject: drm/radeon: avoid deadlock in pm path when waiting for fence + +From: Jerome Glisse + +commit 5f8f635edd8ad5a6416bff4c5ff486500357f473 upstream. + +radeon_fence_wait_empty_locked should not trigger GPU reset as no +place where it's call from would benefit from such thing and it +actually lead to a kernel deadlock in case the reset is triggered +from pm codepath. Instead force ring completion in place where it +makes sense or return early in others. + +Signed-off-by: Jerome Glisse +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon.h | 2 +- + drivers/gpu/drm/radeon/radeon_device.c | 13 +++++++++++-- + drivers/gpu/drm/radeon/radeon_fence.c | 30 ++++++++++++++---------------- + drivers/gpu/drm/radeon/radeon_pm.c | 15 ++++++++++++--- + 4 files changed, 38 insertions(+), 22 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon.h ++++ b/drivers/gpu/drm/radeon/radeon.h +@@ -226,7 +226,7 @@ void radeon_fence_process(struct radeon_ + bool radeon_fence_signaled(struct radeon_fence *fence); + int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); + int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring); +-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); ++int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring); + int radeon_fence_wait_any(struct radeon_device *rdev, + struct radeon_fence **fences, + bool intr); +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -1163,6 +1163,7 @@ int radeon_suspend_kms(struct drm_device + struct drm_crtc *crtc; + struct drm_connector *connector; + int i, r; ++ bool force_completion = false; + + if (dev == NULL || dev->dev_private == NULL) { + return -ENODEV; +@@ -1205,8 +1206,16 @@ int radeon_suspend_kms(struct drm_device + + mutex_lock(&rdev->ring_lock); + /* wait for gpu to finish processing current batch */ +- for (i = 0; i < RADEON_NUM_RINGS; i++) +- radeon_fence_wait_empty_locked(rdev, i); ++ for (i = 0; i < RADEON_NUM_RINGS; i++) { ++ r = radeon_fence_wait_empty_locked(rdev, i); ++ if (r) { ++ /* delay GPU reset to resume */ ++ force_completion = true; ++ } ++ } ++ if (force_completion) { ++ radeon_fence_driver_force_completion(rdev); ++ } + mutex_unlock(&rdev->ring_lock); + + radeon_save_bios_scratch_regs(rdev); +--- a/drivers/gpu/drm/radeon/radeon_fence.c ++++ b/drivers/gpu/drm/radeon/radeon_fence.c +@@ -609,26 +609,20 @@ int radeon_fence_wait_next_locked(struct + * Returns 0 if the fences have passed, error for all other cases. + * Caller must hold ring lock. + */ +-void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) ++int radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) + { + uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; ++ int r; + +- while(1) { +- int r; +- r = radeon_fence_wait_seq(rdev, seq, ring, false, false); ++ r = radeon_fence_wait_seq(rdev, seq, ring, false, false); ++ if (r) { + if (r == -EDEADLK) { +- mutex_unlock(&rdev->ring_lock); +- r = radeon_gpu_reset(rdev); +- mutex_lock(&rdev->ring_lock); +- if (!r) +- continue; +- } +- if (r) { +- dev_err(rdev->dev, "error waiting for ring to become" +- " idle (%d)\n", r); ++ return -EDEADLK; + } +- return; ++ dev_err(rdev->dev, "error waiting for ring[%d] to become idle (%d)\n", ++ ring, r); + } ++ return 0; + } + + /** +@@ -854,13 +848,17 @@ int radeon_fence_driver_init(struct rade + */ + void radeon_fence_driver_fini(struct radeon_device *rdev) + { +- int ring; ++ int ring, r; + + mutex_lock(&rdev->ring_lock); + for (ring = 0; ring < RADEON_NUM_RINGS; ring++) { + if (!rdev->fence_drv[ring].initialized) + continue; +- radeon_fence_wait_empty_locked(rdev, ring); ++ r = radeon_fence_wait_empty_locked(rdev, ring); ++ if (r) { ++ /* no need to trigger GPU reset as we are unloading */ ++ radeon_fence_driver_force_completion(rdev); ++ } + wake_up_all(&rdev->fence_queue); + radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg); + rdev->fence_drv[ring].initialized = false; +--- a/drivers/gpu/drm/radeon/radeon_pm.c ++++ b/drivers/gpu/drm/radeon/radeon_pm.c +@@ -234,7 +234,7 @@ static void radeon_set_power_state(struc + + static void radeon_pm_set_clocks(struct radeon_device *rdev) + { +- int i; ++ int i, r; + + /* no need to take locks, etc. if nothing's going to change */ + if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && +@@ -248,8 +248,17 @@ static void radeon_pm_set_clocks(struct + /* wait for the rings to drain */ + for (i = 0; i < RADEON_NUM_RINGS; i++) { + struct radeon_ring *ring = &rdev->ring[i]; +- if (ring->ready) +- radeon_fence_wait_empty_locked(rdev, i); ++ if (!ring->ready) { ++ continue; ++ } ++ r = radeon_fence_wait_empty_locked(rdev, i); ++ if (r) { ++ /* needs a GPU reset dont reset here */ ++ mutex_unlock(&rdev->ring_lock); ++ up_write(&rdev->pm.mclk_lock); ++ mutex_unlock(&rdev->ddev->struct_mutex); ++ return; ++ } + } + + radeon_unmap_vram_bos(rdev); +From 668bbc81baf0f34df832d8aca5c7d5e19a493c68 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 20 Dec 2012 21:19:32 -0500 +Subject: drm/radeon: add WAIT_UNTIL to evergreen VM safe reg list + +From: Alex Deucher + +commit 668bbc81baf0f34df832d8aca5c7d5e19a493c68 upstream. + +It's used in a recent mesa commit: +http://cgit.freedesktop.org/mesa/mesa/commit/?id=24b1206ab2dcd506aaac3ef656aebc8bc20cd27a +and there may be some other cases in the future where it's required. + +Signed-off-by: Alex Deucher +Reviewed-by: Jerome Glisse +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/evergreen_cs.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/radeon/evergreen_cs.c ++++ b/drivers/gpu/drm/radeon/evergreen_cs.c +@@ -2724,6 +2724,7 @@ static bool evergreen_vm_reg_valid(u32 r + + /* check config regs */ + switch (reg) { ++ case WAIT_UNTIL: + case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: +From cafa59b9011a7790be4ddd5979419259844a165d Mon Sep 17 00:00:00 2001 +From: Alex Deucher +Date: Thu, 20 Dec 2012 16:35:47 -0500 +Subject: drm/radeon: add connector table for Mac G4 Silver + +From: Alex Deucher + +commit cafa59b9011a7790be4ddd5979419259844a165d upstream. + +Apple cards do not provide data tables in the vbios +so we have to hard code the connector parameters +in the driver. + +Reported-by: Albrecht Dreß +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_combios.c | 51 ++++++++++++++++++++++++++++++++ + drivers/gpu/drm/radeon/radeon_mode.h | 3 + + 2 files changed, 53 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/radeon/radeon_combios.c ++++ b/drivers/gpu/drm/radeon/radeon_combios.c +@@ -1548,6 +1548,9 @@ bool radeon_get_legacy_connector_info_fr + of_machine_is_compatible("PowerBook6,7")) { + /* ibook */ + rdev->mode_info.connector_table = CT_IBOOK; ++ } else if (of_machine_is_compatible("PowerMac3,5")) { ++ /* PowerMac G4 Silver radeon 7500 */ ++ rdev->mode_info.connector_table = CT_MAC_G4_SILVER; + } else if (of_machine_is_compatible("PowerMac4,4")) { + /* emac */ + rdev->mode_info.connector_table = CT_EMAC; +@@ -2210,6 +2213,54 @@ bool radeon_get_legacy_connector_info_fr + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, ++ &hpd); ++ break; ++ case CT_MAC_G4_SILVER: ++ DRM_INFO("Connector Table: %d (mac g4 silver)\n", ++ rdev->mode_info.connector_table); ++ /* DVI-I - tv dac, int tmds */ ++ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_DVI, 0, 0); ++ hpd.hpd = RADEON_HPD_1; /* ??? */ ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_DFP1_SUPPORT, ++ 0), ++ ATOM_DEVICE_DFP1_SUPPORT); ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_CRT2_SUPPORT, ++ 2), ++ ATOM_DEVICE_CRT2_SUPPORT); ++ radeon_add_legacy_connector(dev, 0, ++ ATOM_DEVICE_DFP1_SUPPORT | ++ ATOM_DEVICE_CRT2_SUPPORT, ++ DRM_MODE_CONNECTOR_DVII, &ddc_i2c, ++ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, ++ &hpd); ++ /* VGA - primary dac */ ++ ddc_i2c = combios_setup_i2c_bus(rdev, DDC_VGA, 0, 0); ++ hpd.hpd = RADEON_HPD_NONE; ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_CRT1_SUPPORT, ++ 1), ++ ATOM_DEVICE_CRT1_SUPPORT); ++ radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, ++ DRM_MODE_CONNECTOR_VGA, &ddc_i2c, ++ CONNECTOR_OBJECT_ID_VGA, ++ &hpd); ++ /* TV - TV DAC */ ++ ddc_i2c.valid = false; ++ hpd.hpd = RADEON_HPD_NONE; ++ radeon_add_legacy_encoder(dev, ++ radeon_get_encoder_enum(dev, ++ ATOM_DEVICE_TV1_SUPPORT, ++ 2), ++ ATOM_DEVICE_TV1_SUPPORT); ++ radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, ++ DRM_MODE_CONNECTOR_SVIDEO, ++ &ddc_i2c, ++ CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); + break; + default: +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -209,7 +209,8 @@ enum radeon_connector_table { + CT_RN50_POWER, + CT_MAC_X800, + CT_MAC_G5_9600, +- CT_SAM440EP ++ CT_SAM440EP, ++ CT_MAC_G4_SILVER + }; + + enum radeon_dvo_chip { +From 0a9069d34918659bc8a89e21e69e60b2b83291a3 Mon Sep 17 00:00:00 2001 +From: Niels Ole Salscheider +Date: Thu, 3 Jan 2013 19:09:28 +0100 +Subject: drm/radeon: Properly handle DDC probe for DP bridges + +From: Niels Ole Salscheider + +commit 0a9069d34918659bc8a89e21e69e60b2b83291a3 upstream. + +DDC information can be accessed using AUX CH + +Fixes failure to probe monitors on some systems with +DP bridge chips. + +agd5f: minor fixes + +Signed-off-by: Niels Ole Salscheider +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_connectors.c | 10 ++++++---- + drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++++---- + drivers/gpu/drm/radeon/radeon_i2c.c | 10 ++++++++-- + drivers/gpu/drm/radeon/radeon_mode.h | 2 +- + 4 files changed, 24 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_connectors.c ++++ b/drivers/gpu/drm/radeon/radeon_connectors.c +@@ -741,7 +741,7 @@ radeon_vga_detect(struct drm_connector * + ret = connector_status_disconnected; + + if (radeon_connector->ddc_bus) +- dret = radeon_ddc_probe(radeon_connector); ++ dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { +@@ -947,7 +947,7 @@ radeon_dvi_detect(struct drm_connector * + return connector->status; + + if (radeon_connector->ddc_bus) +- dret = radeon_ddc_probe(radeon_connector); ++ dret = radeon_ddc_probe(radeon_connector, false); + if (dret) { + radeon_connector->detected_by_load = false; + if (radeon_connector->edid) { +@@ -1401,7 +1401,8 @@ radeon_dp_detect(struct drm_connector *c + if (encoder) { + /* setup ddc on the bridge */ + radeon_atom_ext_encoder_setup_ddc(encoder); +- if (radeon_ddc_probe(radeon_connector)) /* try DDC */ ++ /* bridge chips are always aux */ ++ if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ + ret = connector_status_connected; + else if (radeon_connector->dac_load_detect) { /* try load detection */ + struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; +@@ -1419,7 +1420,8 @@ radeon_dp_detect(struct drm_connector *c + if (radeon_dp_getdpcd(radeon_connector)) + ret = connector_status_connected; + } else { +- if (radeon_ddc_probe(radeon_connector)) ++ /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ ++ if (radeon_ddc_probe(radeon_connector, false)) + ret = connector_status_connected; + } + } +--- a/drivers/gpu/drm/radeon/radeon_display.c ++++ b/drivers/gpu/drm/radeon/radeon_display.c +@@ -695,10 +695,15 @@ int radeon_ddc_get_modes(struct radeon_c + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + +- if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || +- (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || +- (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != +- ENCODER_OBJECT_ID_NONE)) { ++ if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != ++ ENCODER_OBJECT_ID_NONE) { ++ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; ++ ++ if (dig->dp_i2c_bus) ++ radeon_connector->edid = drm_get_edid(&radeon_connector->base, ++ &dig->dp_i2c_bus->adapter); ++ } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || ++ (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || +--- a/drivers/gpu/drm/radeon/radeon_i2c.c ++++ b/drivers/gpu/drm/radeon/radeon_i2c.c +@@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struc + * radeon_ddc_probe + * + */ +-bool radeon_ddc_probe(struct radeon_connector *radeon_connector) ++bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) + { + u8 out = 0x0; + u8 buf[8]; +@@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_conn + if (radeon_connector->router.ddc_valid) + radeon_router_select_ddc_port(radeon_connector); + +- ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); ++ if (use_aux) { ++ struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; ++ ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); ++ } else { ++ ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); ++ } ++ + if (ret != 2) + /* Couldn't find an accessible DDC on this connector */ + return false; +--- a/drivers/gpu/drm/radeon/radeon_mode.h ++++ b/drivers/gpu/drm/radeon/radeon_mode.h +@@ -559,7 +559,7 @@ extern void radeon_i2c_put_byte(struct r + u8 val); + extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); + extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); +-extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); ++extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); + extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); + + extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); +From eda85d6ad490923152544fba0473798b6cc0edf6 Mon Sep 17 00:00:00 2001 +From: Aaro Koskinen +Date: Mon, 31 Dec 2012 03:34:59 +0200 +Subject: drm/nouveau: fix init with agpgart-uninorth + +From: Aaro Koskinen + +commit eda85d6ad490923152544fba0473798b6cc0edf6 upstream. + +Check that the AGP aperture can be mapped. This follows a similar change +done for Radeon (commit 365048ff, drm/radeon: AGP memory is only I/O if +the aperture can be mapped by the CPU.). + +The patch fixes the following error seen on G5 iMac: + + nouveau E[ DRM] failed to create kernel channel, -12 + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58806 +Reviewed-by: Michel Dänzer +Signed-off-by: Aaro Koskinen +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_bo.c ++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c +@@ -1279,7 +1279,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo + if (drm->agp.stat == ENABLED) { + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = drm->agp.base; +- mem->bus.is_iomem = true; ++ mem->bus.is_iomem = !dev->agp->cant_use_aperture; + } + #endif + break; +From 13888d78c664a1f61d7b09d282f5916993827a40 Mon Sep 17 00:00:00 2001 +From: Paulo Zanoni +Date: Tue, 20 Nov 2012 13:27:41 -0200 +Subject: drm/i915: make the panel fitter work on pipes B and C on IVB + +From: Paulo Zanoni + +commit 13888d78c664a1f61d7b09d282f5916993827a40 upstream. + +I actually found this problem on Haswell, but then discovered Ivy +Bridge also has it by reading the spec. + +I don't have the hardware to test this. + +Signed-off-by: Paulo Zanoni +Reviewed-by: Damien Lespiau +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_reg.h | 2 ++ + drivers/gpu/drm/i915/intel_display.c | 6 +++++- + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -3315,6 +3315,8 @@ + #define _PFA_CTL_1 0x68080 + #define _PFB_CTL_1 0x68880 + #define PF_ENABLE (1<<31) ++#define PF_PIPE_SEL_MASK_IVB (3<<29) ++#define PF_PIPE_SEL_IVB(pipe) ((pipe)<<29) + #define PF_FILTER_MASK (3<<23) + #define PF_FILTER_PROGRAMMED (0<<23) + #define PF_FILTER_MED_3x3 (1<<23) +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -3225,7 +3225,11 @@ static void ironlake_crtc_enable(struct + * as some pre-programmed values are broken, + * e.g. x201. + */ +- I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); ++ if (IS_IVYBRIDGE(dev)) ++ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | ++ PF_PIPE_SEL_IVB(pipe)); ++ else ++ I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); + I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); + I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); + } +From 8fb74b9fb2b182d54beee592350d9ea1f325917a Mon Sep 17 00:00:00 2001 +From: Mel Gorman +Date: Fri, 11 Jan 2013 14:32:16 -0800 +Subject: mm: compaction: partially revert capture of suitable high-order page + +From: Mel Gorman + +commit 8fb74b9fb2b182d54beee592350d9ea1f325917a upstream. + +Eric Wong reported on 3.7 and 3.8-rc2 that ppoll() got stuck when +waiting for POLLIN on a local TCP socket. It was easier to trigger if +there was disk IO and dirty pages at the same time and he bisected it to +commit 1fb3f8ca0e92 ("mm: compaction: capture a suitable high-order page +immediately when it is made available"). + +The intention of that patch was to improve high-order allocations under +memory pressure after changes made to reclaim in 3.6 drastically hurt +THP allocations but the approach was flawed. For Eric, the problem was +that page->pfmemalloc was not being cleared for captured pages leading +to a poor interaction with swap-over-NFS support causing the packets to +be dropped. However, I identified a few more problems with the patch +including the fact that it can increase contention on zone->lock in some +cases which could result in async direct compaction being aborted early. + +In retrospect the capture patch took the wrong approach. What it should +have done is mark the pageblock being migrated as MIGRATE_ISOLATE if it +was allocating for THP and avoided races that way. While the patch was +showing to improve allocation success rates at the time, the benefit is +marginal given the relative complexity and it should be revisited from +scratch in the context of the other reclaim-related changes that have +taken place since the patch was first written and tested. This patch +partially reverts commit 1fb3f8ca0e92 ("mm: compaction: capture a +suitable high-order page immediately when it is made available"). + +Reported-and-tested-by: Eric Wong +Tested-by: Eric Dumazet +Signed-off-by: Mel Gorman +Cc: David Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/compaction.h | 4 - + include/linux/mm.h | 1 + mm/compaction.c | 92 ++++++--------------------------------------- + mm/internal.h | 1 + mm/page_alloc.c | 35 +++-------------- + 5 files changed, 23 insertions(+), 110 deletions(-) + +--- a/include/linux/compaction.h ++++ b/include/linux/compaction.h +@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct + extern int fragmentation_index(struct zone *zone, unsigned int order); + extern unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *mask, +- bool sync, bool *contended, struct page **page); ++ bool sync, bool *contended); + extern int compact_pgdat(pg_data_t *pgdat, int order); + extern void reset_isolation_suitable(pg_data_t *pgdat); + extern unsigned long compaction_suitable(struct zone *zone, int order); +@@ -75,7 +75,7 @@ static inline bool compaction_restarting + #else + static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended, struct page **page) ++ bool sync, bool *contended) + { + return COMPACT_CONTINUE; + } +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pa + + void split_page(struct page *page, unsigned int order); + int split_free_page(struct page *page); +-int capture_free_page(struct page *page, int alloc_order, int migratetype); + + /* + * Compound pages have a destructor function. Provide a +--- a/mm/compaction.c ++++ b/mm/compaction.c +@@ -214,60 +214,6 @@ static bool suitable_migration_target(st + return false; + } + +-static void compact_capture_page(struct compact_control *cc) +-{ +- unsigned long flags; +- int mtype, mtype_low, mtype_high; +- +- if (!cc->page || *cc->page) +- return; +- +- /* +- * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP +- * regardless of the migratetype of the freelist is is captured from. +- * This is fine because the order for a high-order MIGRATE_MOVABLE +- * allocation is typically at least a pageblock size and overall +- * fragmentation is not impaired. Other allocation types must +- * capture pages from their own migratelist because otherwise they +- * could pollute other pageblocks like MIGRATE_MOVABLE with +- * difficult to move pages and making fragmentation worse overall. +- */ +- if (cc->migratetype == MIGRATE_MOVABLE) { +- mtype_low = 0; +- mtype_high = MIGRATE_PCPTYPES; +- } else { +- mtype_low = cc->migratetype; +- mtype_high = cc->migratetype + 1; +- } +- +- /* Speculatively examine the free lists without zone lock */ +- for (mtype = mtype_low; mtype < mtype_high; mtype++) { +- int order; +- for (order = cc->order; order < MAX_ORDER; order++) { +- struct page *page; +- struct free_area *area; +- area = &(cc->zone->free_area[order]); +- if (list_empty(&area->free_list[mtype])) +- continue; +- +- /* Take the lock and attempt capture of the page */ +- if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc)) +- return; +- if (!list_empty(&area->free_list[mtype])) { +- page = list_entry(area->free_list[mtype].next, +- struct page, lru); +- if (capture_free_page(page, cc->order, mtype)) { +- spin_unlock_irqrestore(&cc->zone->lock, +- flags); +- *cc->page = page; +- return; +- } +- } +- spin_unlock_irqrestore(&cc->zone->lock, flags); +- } +- } +-} +- + /* + * Isolate free pages onto a private freelist. Caller must hold zone->lock. + * If @strict is true, will abort returning 0 on any invalid PFNs or non-free +@@ -831,6 +777,7 @@ static isolate_migrate_t isolate_migrate + static int compact_finished(struct zone *zone, + struct compact_control *cc) + { ++ unsigned int order; + unsigned long watermark; + + if (fatal_signal_pending(current)) +@@ -865,22 +812,16 @@ static int compact_finished(struct zone + return COMPACT_CONTINUE; + + /* Direct compactor: Is a suitable page free? */ +- if (cc->page) { +- /* Was a suitable page captured? */ +- if (*cc->page) ++ for (order = cc->order; order < MAX_ORDER; order++) { ++ struct free_area *area = &zone->free_area[order]; ++ ++ /* Job done if page is free of the right migratetype */ ++ if (!list_empty(&area->free_list[cc->migratetype])) ++ return COMPACT_PARTIAL; ++ ++ /* Job done if allocation would set block type */ ++ if (cc->order >= pageblock_order && area->nr_free) + return COMPACT_PARTIAL; +- } else { +- unsigned int order; +- for (order = cc->order; order < MAX_ORDER; order++) { +- struct free_area *area = &zone->free_area[cc->order]; +- /* Job done if page is free of the right migratetype */ +- if (!list_empty(&area->free_list[cc->migratetype])) +- return COMPACT_PARTIAL; +- +- /* Job done if allocation would set block type */ +- if (cc->order >= pageblock_order && area->nr_free) +- return COMPACT_PARTIAL; +- } + } + + return COMPACT_CONTINUE; +@@ -1018,9 +959,6 @@ static int compact_zone(struct zone *zon + goto out; + } + } +- +- /* Capture a page now if it is a suitable size */ +- compact_capture_page(cc); + } + + out: +@@ -1033,8 +971,7 @@ out: + + static unsigned long compact_zone_order(struct zone *zone, + int order, gfp_t gfp_mask, +- bool sync, bool *contended, +- struct page **page) ++ bool sync, bool *contended) + { + unsigned long ret; + struct compact_control cc = { +@@ -1044,7 +981,6 @@ static unsigned long compact_zone_order( + .migratetype = allocflags_to_migratetype(gfp_mask), + .zone = zone, + .sync = sync, +- .page = page, + }; + INIT_LIST_HEAD(&cc.freepages); + INIT_LIST_HEAD(&cc.migratepages); +@@ -1074,7 +1010,7 @@ int sysctl_extfrag_threshold = 500; + */ + unsigned long try_to_compact_pages(struct zonelist *zonelist, + int order, gfp_t gfp_mask, nodemask_t *nodemask, +- bool sync, bool *contended, struct page **page) ++ bool sync, bool *contended) + { + enum zone_type high_zoneidx = gfp_zone(gfp_mask); + int may_enter_fs = gfp_mask & __GFP_FS; +@@ -1100,7 +1036,7 @@ unsigned long try_to_compact_pages(struc + int status; + + status = compact_zone_order(zone, order, gfp_mask, sync, +- contended, page); ++ contended); + rc = max(status, rc); + + /* If a normal allocation would succeed, stop compacting */ +@@ -1156,7 +1092,6 @@ int compact_pgdat(pg_data_t *pgdat, int + struct compact_control cc = { + .order = order, + .sync = false, +- .page = NULL, + }; + + return __compact_pgdat(pgdat, &cc); +@@ -1167,7 +1102,6 @@ static int compact_node(int nid) + struct compact_control cc = { + .order = -1, + .sync = true, +- .page = NULL, + }; + + return __compact_pgdat(NODE_DATA(nid), &cc); +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -130,7 +130,6 @@ struct compact_control { + int migratetype; /* MOVABLE, RECLAIMABLE etc */ + struct zone *zone; + bool contended; /* True if a lock was contended */ +- struct page **page; /* Page captured of requested size */ + }; + + unsigned long +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -1376,14 +1376,8 @@ void split_page(struct page *page, unsig + set_page_refcounted(page + i); + } + +-/* +- * Similar to the split_page family of functions except that the page +- * required at the given order and being isolated now to prevent races +- * with parallel allocators +- */ +-int capture_free_page(struct page *page, int alloc_order, int migratetype) ++static int __isolate_free_page(struct page *page, unsigned int order) + { +- unsigned int order; + unsigned long watermark; + struct zone *zone; + int mt; +@@ -1391,7 +1385,6 @@ int capture_free_page(struct page *page, + BUG_ON(!PageBuddy(page)); + + zone = page_zone(page); +- order = page_order(page); + + /* Obey watermarks as if the page was being allocated */ + watermark = low_wmark_pages(zone) + (1 << order); +@@ -1405,13 +1398,9 @@ int capture_free_page(struct page *page, + + mt = get_pageblock_migratetype(page); + if (unlikely(mt != MIGRATE_ISOLATE)) +- __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); +- +- if (alloc_order != order) +- expand(zone, page, alloc_order, order, +- &zone->free_area[order], migratetype); ++ __mod_zone_freepage_state(zone, -(1UL << order), mt); + +- /* Set the pageblock if the captured page is at least a pageblock */ ++ /* Set the pageblock if the isolated page is at least a pageblock */ + if (order >= pageblock_order - 1) { + struct page *endpage = page + (1 << order) - 1; + for (; page < endpage; page += pageblock_nr_pages) { +@@ -1422,7 +1411,7 @@ int capture_free_page(struct page *page, + } + } + +- return 1UL << alloc_order; ++ return 1UL << order; + } + + /* +@@ -1440,10 +1429,9 @@ int split_free_page(struct page *page) + unsigned int order; + int nr_pages; + +- BUG_ON(!PageBuddy(page)); + order = page_order(page); + +- nr_pages = capture_free_page(page, order, 0); ++ nr_pages = __isolate_free_page(page, order); + if (!nr_pages) + return 0; + +@@ -2148,8 +2136,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m + bool *contended_compaction, bool *deferred_compaction, + unsigned long *did_some_progress) + { +- struct page *page = NULL; +- + if (!order) + return NULL; + +@@ -2161,16 +2147,12 @@ __alloc_pages_direct_compact(gfp_t gfp_m + current->flags |= PF_MEMALLOC; + *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, + nodemask, sync_migration, +- contended_compaction, &page); ++ contended_compaction); + current->flags &= ~PF_MEMALLOC; + +- /* If compaction captured a page, prep and use it */ +- if (page) { +- prep_new_page(page, order, gfp_mask); +- goto got_page; +- } +- + if (*did_some_progress != COMPACT_SKIPPED) { ++ struct page *page; ++ + /* Page migration frees to the PCP lists but we want merging */ + drain_pages(get_cpu()); + put_cpu(); +@@ -2180,7 +2162,6 @@ __alloc_pages_direct_compact(gfp_t gfp_m + alloc_flags & ~ALLOC_NO_WATERMARKS, + preferred_zone, migratetype); + if (page) { +-got_page: + preferred_zone->compact_blockskip_flush = false; + preferred_zone->compact_considered = 0; + preferred_zone->compact_defer_shift = 0; +From e7d841ca03b7ab668620045cd7b428eda9f41601 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 3 Dec 2012 11:36:30 +0000 +Subject: drm/i915: Close race between processing unpin task and queueing the flip + +From: Chris Wilson + +commit e7d841ca03b7ab668620045cd7b428eda9f41601 upstream. + +Before queuing the flip but crucially after attaching the unpin-work to +the crtc, we continue to setup the unpin-work. However, should the +hardware fire early, we see the connected unpin-work and queue the task. +The task then promptly runs and unpins the fb before we finish taking +the required references or even pinning it... Havoc. + +To close the race, we use the flip-pending atomic to indicate when the +flip is finally setup and enqueued. So during the flip-done processing, +we can check more accurately whether the flip was expected. + +v2: Add the appropriate mb() to ensure that the writes to the page-flip +worker are complete prior to marking it active and emitting the MI_FLIP. +On the read side, the mb should be enforced by the spinlocks. + +Signed-off-by: Chris Wilson +[danvet: Review the barriers a bit, we need a write barrier both +before and after updating ->pending. Similarly we need a read barrier +in the interrupt handler both before and after reading ->pending. With +well-ordered irqs only one barrier in each place should be required, +but since this patch explicitly sets out to combat spurious interrupts +with is staged activation of the unpin work we need to go full-bore on +the barriers, too. Discussed with Chris Wilson on irc and changes +acked by him.] +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_debugfs.c | 4 +-- + drivers/gpu/drm/i915/i915_irq.c | 4 ++- + drivers/gpu/drm/i915/intel_display.c | 39 ++++++++++++++++++++++++++++------- + drivers/gpu/drm/i915/intel_drv.h | 5 +++- + 4 files changed, 41 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_debugfs.c ++++ b/drivers/gpu/drm/i915/i915_debugfs.c +@@ -317,7 +317,7 @@ static int i915_gem_pageflip_info(struct + seq_printf(m, "No flip due on pipe %c (plane %c)\n", + pipe, plane); + } else { +- if (!work->pending) { ++ if (atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { + seq_printf(m, "Flip queued on pipe %c (plane %c)\n", + pipe, plane); + } else { +@@ -328,7 +328,7 @@ static int i915_gem_pageflip_info(struct + seq_printf(m, "Stall check enabled, "); + else + seq_printf(m, "Stall check waiting for page flip ioctl, "); +- seq_printf(m, "%d prepares\n", work->pending); ++ seq_printf(m, "%d prepares\n", atomic_read(&work->pending)); + + if (work->old_fb_obj) { + struct drm_i915_gem_object *obj = work->old_fb_obj; +--- a/drivers/gpu/drm/i915/i915_irq.c ++++ b/drivers/gpu/drm/i915/i915_irq.c +@@ -1464,7 +1464,9 @@ static void i915_pageflip_stall_check(st + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; + +- if (work == NULL || work->pending || !work->enable_stall_check) { ++ if (work == NULL || ++ atomic_read(&work->pending) >= INTEL_FLIP_COMPLETE || ++ !work->enable_stall_check) { + /* Either the pending flip IRQ arrived, or we're too early. Don't check */ + spin_unlock_irqrestore(&dev->event_lock, flags); + return; +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6215,11 +6215,18 @@ static void do_intel_finish_page_flip(st + + spin_lock_irqsave(&dev->event_lock, flags); + work = intel_crtc->unpin_work; +- if (work == NULL || !work->pending) { ++ ++ /* Ensure we don't miss a work->pending update ... */ ++ smp_rmb(); ++ ++ if (work == NULL || atomic_read(&work->pending) < INTEL_FLIP_COMPLETE) { + spin_unlock_irqrestore(&dev->event_lock, flags); + return; + } + ++ /* and that the unpin work is consistent wrt ->pending. */ ++ smp_rmb(); ++ + intel_crtc->unpin_work = NULL; + + if (work->event) { +@@ -6272,16 +6279,25 @@ void intel_prepare_page_flip(struct drm_ + to_intel_crtc(dev_priv->plane_to_crtc_mapping[plane]); + unsigned long flags; + ++ /* NB: An MMIO update of the plane base pointer will also ++ * generate a page-flip completion irq, i.e. every modeset ++ * is also accompanied by a spurious intel_prepare_page_flip(). ++ */ + spin_lock_irqsave(&dev->event_lock, flags); +- if (intel_crtc->unpin_work) { +- if ((++intel_crtc->unpin_work->pending) > 1) +- DRM_ERROR("Prepared flip multiple times\n"); +- } else { +- DRM_DEBUG_DRIVER("preparing flip with no unpin work?\n"); +- } ++ if (intel_crtc->unpin_work) ++ atomic_inc_not_zero(&intel_crtc->unpin_work->pending); + spin_unlock_irqrestore(&dev->event_lock, flags); + } + ++inline static void intel_mark_page_flip_active(struct intel_crtc *intel_crtc) ++{ ++ /* Ensure that the work item is consistent when activating it ... */ ++ smp_wmb(); ++ atomic_set(&intel_crtc->unpin_work->pending, INTEL_FLIP_PENDING); ++ /* and that it is marked active as soon as the irq could fire. */ ++ smp_wmb(); ++} ++ + static int intel_gen2_queue_flip(struct drm_device *dev, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, +@@ -6315,6 +6331,8 @@ static int intel_gen2_queue_flip(struct + intel_ring_emit(ring, fb->pitches[0]); + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, 0); /* aux display base address, unused */ ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6355,6 +6373,7 @@ static int intel_gen3_queue_flip(struct + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, MI_NOOP); + ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6401,6 +6420,8 @@ static int intel_gen4_queue_flip(struct + pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + intel_ring_emit(ring, pf | pipesrc); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6443,6 +6464,8 @@ static int intel_gen6_queue_flip(struct + pf = 0; + pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; + intel_ring_emit(ring, pf | pipesrc); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +@@ -6497,6 +6520,8 @@ static int intel_gen7_queue_flip(struct + intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); + intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); + intel_ring_emit(ring, (MI_NOOP)); ++ ++ intel_mark_page_flip_active(intel_crtc); + intel_ring_advance(ring); + return 0; + +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -384,7 +384,10 @@ struct intel_unpin_work { + struct drm_i915_gem_object *old_fb_obj; + struct drm_i915_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; +- int pending; ++ atomic_t pending; ++#define INTEL_FLIP_INACTIVE 0 ++#define INTEL_FLIP_PENDING 1 ++#define INTEL_FLIP_COMPLETE 2 + bool enable_stall_check; + }; + +From b4a98e57fc27854b5938fc8b08b68e5e68b91e1f Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Thu, 1 Nov 2012 09:26:26 +0000 +Subject: drm/i915: Flush outstanding unpin tasks before pageflipping + +From: Chris Wilson + +commit b4a98e57fc27854b5938fc8b08b68e5e68b91e1f upstream. + +If we accumulate unpin tasks because we are pageflipping faster than the +system can schedule its workers, we can effectively create a +pin-leak. The solution taken here is to limit the number of unpin tasks +we have per-crtc and to flush those outstanding tasks if we accumulate +too many. This should prevent any jitter in the normal case, and also +prevent the hang if we should run too fast. + +Note: It is important that we switch from the system workqueue to our +own dev_priv->wq since all work items on that queue are guaranteed to +only need the dev->struct_mutex and not any modeset resources. For +otherwise if we have a work item ahead in the queue which needs the +modeset lock (like the output detect work used by both polling or +hpd), this work and so the unpin work will never execute since the +pageflip code already holds that lock. Unfortunately there's no +lockdep support for this scenario in the workqueue code. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=46991 +Reported-and-tested-by: Tvrtko Ursulin +Signed-off-by: Chris Wilson +[danvet: Added note about workqueu deadlock.] +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=56337 +Signed-off-by: Daniel Vetter +Tested-by: Daniel Gnoutcheff +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++++------ + drivers/gpu/drm/i915/intel_drv.h | 4 +++- + 2 files changed, 19 insertions(+), 7 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -6187,14 +6187,19 @@ static void intel_unpin_work_fn(struct w + { + struct intel_unpin_work *work = + container_of(__work, struct intel_unpin_work, work); ++ struct drm_device *dev = work->crtc->dev; + +- mutex_lock(&work->dev->struct_mutex); ++ mutex_lock(&dev->struct_mutex); + intel_unpin_fb_obj(work->old_fb_obj); + drm_gem_object_unreference(&work->pending_flip_obj->base); + drm_gem_object_unreference(&work->old_fb_obj->base); + +- intel_update_fbc(work->dev); +- mutex_unlock(&work->dev->struct_mutex); ++ intel_update_fbc(dev); ++ mutex_unlock(&dev->struct_mutex); ++ ++ BUG_ON(atomic_read(&to_intel_crtc(work->crtc)->unpin_work_count) == 0); ++ atomic_dec(&to_intel_crtc(work->crtc)->unpin_work_count); ++ + kfree(work); + } + +@@ -6249,9 +6254,9 @@ static void do_intel_finish_page_flip(st + + atomic_clear_mask(1 << intel_crtc->plane, + &obj->pending_flip.counter); +- + wake_up(&dev_priv->pending_flip_queue); +- schedule_work(&work->work); ++ ++ queue_work(dev_priv->wq, &work->work); + + trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); + } +@@ -6570,7 +6575,7 @@ static int intel_crtc_page_flip(struct d + return -ENOMEM; + + work->event = event; +- work->dev = crtc->dev; ++ work->crtc = crtc; + intel_fb = to_intel_framebuffer(crtc->fb); + work->old_fb_obj = intel_fb->obj; + INIT_WORK(&work->work, intel_unpin_work_fn); +@@ -6595,6 +6600,9 @@ static int intel_crtc_page_flip(struct d + intel_fb = to_intel_framebuffer(fb); + obj = intel_fb->obj; + ++ if (atomic_read(&intel_crtc->unpin_work_count) >= 2) ++ flush_workqueue(dev_priv->wq); ++ + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto cleanup; +@@ -6613,6 +6621,7 @@ static int intel_crtc_page_flip(struct d + * the flip occurs and the object is no longer visible. + */ + atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); ++ atomic_inc(&intel_crtc->unpin_work_count); + + ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); + if (ret) +@@ -6627,6 +6636,7 @@ static int intel_crtc_page_flip(struct d + return 0; + + cleanup_pending: ++ atomic_dec(&intel_crtc->unpin_work_count); + atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); + drm_gem_object_unreference(&work->old_fb_obj->base); + drm_gem_object_unreference(&obj->base); +--- a/drivers/gpu/drm/i915/intel_drv.h ++++ b/drivers/gpu/drm/i915/intel_drv.h +@@ -198,6 +198,8 @@ struct intel_crtc { + struct intel_unpin_work *unpin_work; + int fdi_lanes; + ++ atomic_t unpin_work_count; ++ + /* Display surface base address adjustement for pageflips. Note that on + * gen4+ this only adjusts up to a tile, offsets within a tile are + * handled in the hw itself (with the TILEOFF register). */ +@@ -380,7 +382,7 @@ intel_get_crtc_for_plane(struct drm_devi + + struct intel_unpin_work { + struct work_struct work; +- struct drm_device *dev; ++ struct drm_crtc *crtc; + struct drm_i915_gem_object *old_fb_obj; + struct drm_i915_gem_object *pending_flip_obj; + struct drm_pending_vblank_event *event; +From b0a2658acb5bf9ca86b4aab011b7106de3af0add Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Tue, 18 Dec 2012 09:37:54 +0100 +Subject: drm/i915: don't disable disconnected outputs + +From: Daniel Vetter + +commit b0a2658acb5bf9ca86b4aab011b7106de3af0add upstream. + +This piece of neat lore has been ported painstakingly and bug-for-bug +compatible from the old crtc helper code. + +Imo it's utter nonsense. + +If you disconnected a cable and before you reconnect it, userspace (or +the kernel) does an set_crtc call, this will result in that connector +getting disabled. Which will result in a nice black screen when +plugging in the cable again. + +There's absolutely no reason the kernel does such policy enforcements +- if userspace tries to set up a mode on something disconnected we +might fail loudly (since the dp link training fails), but silently +adjusting the output configuration behind userspace's back is a recipe +for disaster. Specifically I think that this could explain some of our +MI_WAIT hangs around suspend, where userspace issues a scanline wait +on a disable pipe. This mechanisims here could explain how that pipe +got disabled without userspace noticing. + +Note that this fixes a NULL deref at BIOS takeover when the firmware +sets up a disconnected output in a clone configuration with a +connected output on the 2nd pipe: When doing the full modeset we don't +have a mode for the 2nd pipe and OOPS. On the first pipe this doesn't +matter, since at boot-up the fbdev helpers will set up the choosen +configuration on that on first. Since this is now the umptenth bug +around handling this imo brain-dead semantics correctly, I think it's +time to kill it and see whether there's any userspace out there which +relies on this. + +It also nicely demonstrates that we have a tiny window where DP +hotplug can still kill the driver. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=58396 +Tested-by: Peter Ujfalusi +Reviewed-by: Rodrigo Vivi +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -7298,10 +7298,6 @@ intel_modeset_stage_output_state(struct + DRM_DEBUG_KMS("encoder changed, full mode switch\n"); + config->mode_changed = true; + } +- +- /* Disable all disconnected encoders. */ +- if (connector->base.status == connector_status_disconnected) +- connector->new_encoder = NULL; + } + /* connector->new_encoder is now updated for all connectors. */ + +From 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +Date: Thu, 20 Dec 2012 10:51:09 +1000 +Subject: drm/i915: fix flags in dma buf exporting + +From: Dave Airlie + +commit 5b42427fc38ecb9056c4e64deaff36d6d6ba1b67 upstream. + +As pointed out by Seung-Woo Kim this should have been +passing flags like nouveau/radeon have. + +Signed-off-by: Dave Airlie +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem_dmabuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c ++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +@@ -226,7 +226,7 @@ struct dma_buf *i915_gem_prime_export(st + { + struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); + +- return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, 0600); ++ return dma_buf_export(obj, &i915_dmabuf_ops, obj->base.size, flags); + } + + static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +From be8a42ae60addd8b6092535c11b42d099d6470ec Mon Sep 17 00:00:00 2001 +From: Seung-Woo Kim +Date: Thu, 27 Sep 2012 15:30:06 +0900 +Subject: drm/prime: drop reference on imported dma-buf come from gem + +From: Seung-Woo Kim + +commit be8a42ae60addd8b6092535c11b42d099d6470ec upstream. + +Increasing ref counts of both dma-buf and gem for imported dma-buf come from gem +makes memory leak. release function of dma-buf cannot be called because f_count +of dma-buf increased by importing gem and gem ref count cannot be decrease +because of exported dma-buf. + +So I add dma_buf_put() for imported gem come from its own gem into each drivers +having prime_import and prime_export capabilities. With this, only gem ref +count is increased if importing gem exported from gem of same driver. + +Signed-off-by: Seung-Woo Kim +Signed-off-by: Kyungmin.park +Cc: Inki Dae +Cc: Daniel Vetter +Cc: Rob Clark +Cc: Alex Deucher +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 5 +++++ + drivers/gpu/drm/i915/i915_gem_dmabuf.c | 5 +++++ + drivers/gpu/drm/nouveau/nouveau_prime.c | 1 + + drivers/gpu/drm/radeon/radeon_prime.c | 1 + + drivers/staging/omapdrm/omap_gem_dmabuf.c | 5 +++++ + 5 files changed, 17 insertions(+) + +--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +@@ -210,7 +210,12 @@ struct drm_gem_object *exynos_dmabuf_pri + + /* is it from our device? */ + if (obj->dev == drm_dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(obj); ++ dma_buf_put(dma_buf); + return obj; + } + } +--- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c ++++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c +@@ -266,7 +266,12 @@ struct drm_gem_object *i915_gem_prime_im + obj = dma_buf->priv; + /* is it from our device? */ + if (obj->base.dev == dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(&obj->base); ++ dma_buf_put(dma_buf); + return &obj->base; + } + } +--- a/drivers/gpu/drm/nouveau/nouveau_prime.c ++++ b/drivers/gpu/drm/nouveau/nouveau_prime.c +@@ -197,6 +197,7 @@ struct drm_gem_object *nouveau_gem_prime + if (nvbo->gem) { + if (nvbo->gem->dev == dev) { + drm_gem_object_reference(nvbo->gem); ++ dma_buf_put(dma_buf); + return nvbo->gem; + } + } +--- a/drivers/gpu/drm/radeon/radeon_prime.c ++++ b/drivers/gpu/drm/radeon/radeon_prime.c +@@ -194,6 +194,7 @@ struct drm_gem_object *radeon_gem_prime_ + bo = dma_buf->priv; + if (bo->gem_base.dev == dev) { + drm_gem_object_reference(&bo->gem_base); ++ dma_buf_put(dma_buf); + return &bo->gem_base; + } + } +--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c ++++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c +@@ -207,7 +207,12 @@ struct drm_gem_object * omap_gem_prime_i + obj = buffer->priv; + /* is it from our device? */ + if (obj->dev == dev) { ++ /* ++ * Importing dmabuf exported from out own gem increases ++ * refcount on gem itself instead of f_count of dmabuf. ++ */ + drm_gem_object_reference(obj); ++ dma_buf_put(buffer); + return obj; + } + } +From 901593f2bf221659a605bdc1dcb11376ea934163 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 19 Dec 2012 16:51:06 +0000 +Subject: drm: Only evict the blocks required to create the requested hole + +From: Chris Wilson + +commit 901593f2bf221659a605bdc1dcb11376ea934163 upstream. + +Avoid clobbering adjacent blocks if they happen to expire earlier and +amalgamate together to form the requested hole. + +In passing this fixes a regression from +commit ea7b1dd44867e9cd6bac67e7c9fc3f128b5b255c +Author: Daniel Vetter +Date: Fri Feb 18 17:59:12 2011 +0100 + + drm: mm: track free areas implicitly + +which swaps the end address for size (with a potential overflow) and +effectively causes the eviction code to clobber almost all earlier +buffers above the evictee. + +v2: Check the original hole not the adjusted as the coloring may confuse +us when later searching for the overlapping nodes. Also make sure that +we do apply the range restriction and color adjustment in the same +order for both scanning, searching and insertion. + +v3: Send the version that was actually tested. + +Note that this seems to be ducttape of decent quality ot paper over +some of our unbind related gpu hangs reported since 3.7. It is not +fully effective though, and certainly doesn't fix the underlying bug. + +Signed-off-by: Chris Wilson +Cc: Daniel Vetter +[danvet: Added note plus bugzilla link and tested-by.] +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=55984 +Tested-by: Norbert Preining +Acked-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_mm.c | 45 +++++++++++++++++---------------------------- + include/drm/drm_mm.h | 2 +- + 2 files changed, 18 insertions(+), 29 deletions(-) + +--- a/drivers/gpu/drm/drm_mm.c ++++ b/drivers/gpu/drm/drm_mm.c +@@ -213,11 +213,13 @@ static void drm_mm_insert_helper_range(s + + BUG_ON(!hole_node->hole_follows || node->allocated); + +- if (mm->color_adjust) +- mm->color_adjust(hole_node, color, &adj_start, &adj_end); +- + if (adj_start < start) + adj_start = start; ++ if (adj_end > end) ++ adj_end = end; ++ ++ if (mm->color_adjust) ++ mm->color_adjust(hole_node, color, &adj_start, &adj_end); + + if (alignment) { + unsigned tmp = adj_start % alignment; +@@ -489,7 +491,7 @@ void drm_mm_init_scan(struct drm_mm *mm, + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; +- mm->scan_hit_size = 0; ++ mm->scan_hit_end = 0; + mm->scan_check_range = 0; + mm->prev_scanned_node = NULL; + } +@@ -516,7 +518,7 @@ void drm_mm_init_scan_with_range(struct + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; +- mm->scan_hit_size = 0; ++ mm->scan_hit_end = 0; + mm->scan_start = start; + mm->scan_end = end; + mm->scan_check_range = 1; +@@ -535,8 +537,7 @@ int drm_mm_scan_add_block(struct drm_mm_ + struct drm_mm *mm = node->mm; + struct drm_mm_node *prev_node; + unsigned long hole_start, hole_end; +- unsigned long adj_start; +- unsigned long adj_end; ++ unsigned long adj_start, adj_end; + + mm->scanned_blocks++; + +@@ -553,14 +554,8 @@ int drm_mm_scan_add_block(struct drm_mm_ + node->node_list.next = &mm->prev_scanned_node->node_list; + mm->prev_scanned_node = node; + +- hole_start = drm_mm_hole_node_start(prev_node); +- hole_end = drm_mm_hole_node_end(prev_node); +- +- adj_start = hole_start; +- adj_end = hole_end; +- +- if (mm->color_adjust) +- mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); ++ adj_start = hole_start = drm_mm_hole_node_start(prev_node); ++ adj_end = hole_end = drm_mm_hole_node_end(prev_node); + + if (mm->scan_check_range) { + if (adj_start < mm->scan_start) +@@ -569,11 +564,14 @@ int drm_mm_scan_add_block(struct drm_mm_ + adj_end = mm->scan_end; + } + ++ if (mm->color_adjust) ++ mm->color_adjust(prev_node, mm->scan_color, ++ &adj_start, &adj_end); ++ + if (check_free_hole(adj_start, adj_end, + mm->scan_size, mm->scan_alignment)) { + mm->scan_hit_start = hole_start; +- mm->scan_hit_size = hole_end; +- ++ mm->scan_hit_end = hole_end; + return 1; + } + +@@ -609,19 +607,10 @@ int drm_mm_scan_remove_block(struct drm_ + node_list); + + prev_node->hole_follows = node->scanned_preceeds_hole; +- INIT_LIST_HEAD(&node->node_list); + list_add(&node->node_list, &prev_node->node_list); + +- /* Only need to check for containement because start&size for the +- * complete resulting free block (not just the desired part) is +- * stored. */ +- if (node->start >= mm->scan_hit_start && +- node->start + node->size +- <= mm->scan_hit_start + mm->scan_hit_size) { +- return 1; +- } +- +- return 0; ++ return (drm_mm_hole_node_end(node) > mm->scan_hit_start && ++ node->start < mm->scan_hit_end); + } + EXPORT_SYMBOL(drm_mm_scan_remove_block); + +--- a/include/drm/drm_mm.h ++++ b/include/drm/drm_mm.h +@@ -70,7 +70,7 @@ struct drm_mm { + unsigned long scan_color; + unsigned long scan_size; + unsigned long scan_hit_start; +- unsigned scan_hit_size; ++ unsigned long scan_hit_end; + unsigned scanned_blocks; + unsigned long scan_start; + unsigned long scan_end; +From 93be8788e648817d62fda33e2998eb6ca6ebf3a3 Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Wed, 2 Jan 2013 10:31:22 +0000 +Subject: drm/i915; Only increment the user-pin-count after successfully pinning the bo + +From: Chris Wilson + +commit 93be8788e648817d62fda33e2998eb6ca6ebf3a3 upstream. + +As along the error path we do not correct the user pin-count for the +failure, we may end up with userspace believing that it has a pinned +object at offset 0 (when interrupted by a signal for example). + +Signed-off-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -3511,14 +3511,15 @@ i915_gem_pin_ioctl(struct drm_device *de + goto out; + } + +- obj->user_pin_count++; +- obj->pin_filp = file; +- if (obj->user_pin_count == 1) { ++ if (obj->user_pin_count == 0) { + ret = i915_gem_object_pin(obj, args->alignment, true, false); + if (ret) + goto out; + } + ++ obj->user_pin_count++; ++ obj->pin_filp = file; ++ + /* XXX - flush the CPU caches for pinned objects + * as the X server doesn't manage domains yet + */ +From 93927ca52a55c23e0a6a305e7e9082e8411ac9fa Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Thu, 10 Jan 2013 18:03:00 +0100 +Subject: drm/i915: Revert shrinker changes from "Track unbound pages" + +From: Daniel Vetter + +commit 93927ca52a55c23e0a6a305e7e9082e8411ac9fa upstream. + +This partially reverts + +commit 6c085a728cf000ac1865d66f8c9b52935558b328 +Author: Chris Wilson +Date: Mon Aug 20 11:40:46 2012 +0200 + + drm/i915: Track unbound pages + +Closer inspection of that patch revealed a bunch of unrelated changes +in the shrinker: +- The shrinker count is now in pages instead of objects. +- For counting the shrinkable objects the old code only looked at the + inactive list, the new code looks at all bounds objects (including + pinned ones). That is obviously in addition to the new unbound list. +- The shrinker cound is no longer scaled with + sysctl_vfs_cache_pressure. Note though that with the default tuning + value of vfs_cache_pressue = 100 this doesn't affect the shrinker + behaviour. +- When actually shrinking objects, the old code first dropped + purgeable objects, then normal (inactive) objects. Only then did it, + in a last-ditch effort idle the gpu and evict everything. The new + code omits the intermediate step of evicting normal inactive + objects. + +Safe for the first change, which seems benign, and the shrinker count +scaling, which is a bit a different story, the endresult of all these +changes is that the shrinker is _much_ more likely to fall back to the +last-ditch resort of idling the gpu and evicting everything. The old +code could only do that if something else evicted lots of objects +meanwhile (since without any other changes the nr_to_scan will be +smaller than the object count). + +Reverting the vfs_cache_pressure behaviour itself is a bit bogus: Only +dentry/inode object caches should scale their shrinker counts with +vfs_cache_pressure. Originally I've had that change reverted, too. But +Chris Wilson insisted that it's too bogus and shouldn't again see the +light of day. + +Hence revert all these other changes and restore the old shrinker +behaviour, with the minor adjustment that we now first scan the +unbound list, then the inactive list for each object category +(purgeable or normal). + +A similar patch has been tested by a few people affected by the gen4/5 +hangs which started to appear in 3.7, which some people bisected to +the "drm/i915: Track unbound pages" commit. But just disabling the +unbound logic alone didn't change things at all. + +Note that this patch doesn't fix the referenced bugs, it only hides +the underlying bug(s) well enough to restore pre-3.7 behaviour. The +key to achieve that is to massively reduce the likelyhood of going +into a full gpu stall and evicting everything. + +v2: Reword commit message a bit, taking Chris Wilson's comment into +account. + +v3: On Chris Wilson's insistency, do not reinstate the rather bogus +vfs_cache_pressure change. + +Tested-by: Greg KH +Tested-by: Dave Kleikamp +References: https://bugs.freedesktop.org/show_bug.cgi?id=55984 +References: https://bugs.freedesktop.org/show_bug.cgi?id=57122 +References: https://bugs.freedesktop.org/show_bug.cgi?id=56916 +References: https://bugs.freedesktop.org/show_bug.cgi?id=57136 +Cc: Chris Wilson +Acked-by: Chris Wilson +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_gem.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_gem.c ++++ b/drivers/gpu/drm/i915/i915_gem.c +@@ -1718,7 +1718,8 @@ i915_gem_object_put_pages(struct drm_i91 + } + + static long +-i915_gem_purge(struct drm_i915_private *dev_priv, long target) ++__i915_gem_shrink(struct drm_i915_private *dev_priv, long target, ++ bool purgeable_only) + { + struct drm_i915_gem_object *obj, *next; + long count = 0; +@@ -1726,7 +1727,7 @@ i915_gem_purge(struct drm_i915_private * + list_for_each_entry_safe(obj, next, + &dev_priv->mm.unbound_list, + gtt_list) { +- if (i915_gem_object_is_purgeable(obj) && ++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && + i915_gem_object_put_pages(obj) == 0) { + count += obj->base.size >> PAGE_SHIFT; + if (count >= target) +@@ -1737,7 +1738,7 @@ i915_gem_purge(struct drm_i915_private * + list_for_each_entry_safe(obj, next, + &dev_priv->mm.inactive_list, + mm_list) { +- if (i915_gem_object_is_purgeable(obj) && ++ if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && + i915_gem_object_unbind(obj) == 0 && + i915_gem_object_put_pages(obj) == 0) { + count += obj->base.size >> PAGE_SHIFT; +@@ -1749,6 +1750,12 @@ i915_gem_purge(struct drm_i915_private * + return count; + } + ++static long ++i915_gem_purge(struct drm_i915_private *dev_priv, long target) ++{ ++ return __i915_gem_shrink(dev_priv, target, true); ++} ++ + static void + i915_gem_shrink_all(struct drm_i915_private *dev_priv) + { +@@ -4426,6 +4433,9 @@ i915_gem_inactive_shrink(struct shrinker + if (nr_to_scan) { + nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); + if (nr_to_scan > 0) ++ nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, ++ false); ++ if (nr_to_scan > 0) + i915_gem_shrink_all(dev_priv); + } + +@@ -4433,7 +4443,7 @@ i915_gem_inactive_shrink(struct shrinker + list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) + if (obj->pages_pin_count == 0) + cnt += obj->base.size >> PAGE_SHIFT; +- list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) ++ list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) + if (obj->pin_count == 0 && obj->pages_pin_count == 0) + cnt += obj->base.size >> PAGE_SHIFT; + +From 7d9c199a55200c9b9fcad08e150470d02fb385be Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 20:05:02 +0000 +Subject: RDMA/nes: Fix for crash when registering zero length MR for CQ + +From: Tatyana Nikolova + +commit 7d9c199a55200c9b9fcad08e150470d02fb385be upstream. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes_verbs.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -2559,6 +2559,11 @@ static struct ib_mr *nes_reg_user_mr(str + return ibmr; + case IWNES_MEMREG_TYPE_QP: + case IWNES_MEMREG_TYPE_CQ: ++ if (!region->length) { ++ nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); ++ ib_umem_release(region); ++ return ERR_PTR(-EINVAL); ++ } + nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); + if (!nespbl) { + nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); +From 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 19:58:27 +0000 +Subject: RDMA/nes: Fix for terminate timer crash + +From: Tatyana Nikolova + +commit 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 upstream. + +The terminate timer needs to be initialized just once. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes.h | 1 + + drivers/infiniband/hw/nes/nes_hw.c | 9 ++------- + drivers/infiniband/hw/nes/nes_verbs.c | 4 +++- + 3 files changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/infiniband/hw/nes/nes.h ++++ b/drivers/infiniband/hw/nes/nes.h +@@ -532,6 +532,7 @@ void nes_iwarp_ce_handler(struct nes_dev + int nes_destroy_cqp(struct nes_device *); + int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); + void nes_recheck_link_status(struct work_struct *work); ++void nes_terminate_timeout(unsigned long context); + + /* nes_nic.c */ + struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); +--- a/drivers/infiniband/hw/nes/nes_hw.c ++++ b/drivers/infiniband/hw/nes/nes_hw.c +@@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struc + static void process_critical_error(struct nes_device *nesdev); + static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); + static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); +-static void nes_terminate_timeout(unsigned long context); + static void nes_terminate_start_timer(struct nes_qp *nesqp); + + #ifdef CONFIG_INFINIBAND_NES_DEBUG +@@ -3520,7 +3519,7 @@ static void nes_terminate_received(struc + } + + /* Timeout routine in case terminate fails to complete */ +-static void nes_terminate_timeout(unsigned long context) ++void nes_terminate_timeout(unsigned long context) + { + struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; + +@@ -3530,11 +3529,7 @@ static void nes_terminate_timeout(unsign + /* Set a timer in case hw cannot complete the terminate sequence */ + static void nes_terminate_start_timer(struct nes_qp *nesqp) + { +- init_timer(&nesqp->terminate_timer); +- nesqp->terminate_timer.function = nes_terminate_timeout; +- nesqp->terminate_timer.expires = jiffies + HZ; +- nesqp->terminate_timer.data = (unsigned long)nesqp; +- add_timer(&nesqp->terminate_timer); ++ mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); + } + + /** +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struc + } + + nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); ++ init_timer(&nesqp->terminate_timer); ++ nesqp->terminate_timer.function = nes_terminate_timeout; ++ nesqp->terminate_timer.data = (unsigned long)nesqp; + + /* update the QP table */ + nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; +@@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struc + return &nesqp->ibqp; + } + +- + /** + * nes_clean_cq + */ +From c1a94672a830e01d58c7c7e8de530c3f136d6ff2 Mon Sep 17 00:00:00 2001 +From: Mike Snitzer +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm: disable WRITE SAME + +From: Mike Snitzer + +commit c1a94672a830e01d58c7c7e8de530c3f136d6ff2 upstream. + +WRITE SAME bios are not yet handled correctly by device-mapper so +disable their use on device-mapper devices by setting +max_write_same_sectors to zero. + +As an example, a ciphertext device is incompatible because the data +gets changed according to the location at which it written and so the +dm crypt target cannot support it. + +Signed-off-by: Mike Snitzer +Cc: Milan Broz +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-table.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/md/dm-table.c ++++ b/drivers/md/dm-table.c +@@ -1445,6 +1445,8 @@ void dm_table_set_restrictions(struct dm + else + queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q); + ++ q->limits.max_write_same_sectors = 0; ++ + dm_table_set_integrity(t); + + /* +From 550929faf89e2e2cdb3e9945ea87d383989274cf Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm persistent data: rename node to btree_node + +From: Mikulas Patocka + +commit 550929faf89e2e2cdb3e9945ea87d383989274cf upstream. + +This patch fixes a compilation failure on sparc32 by renaming struct node. + +struct node is already defined in include/linux/node.h. On sparc32, it +happens to be included through other dependencies and persistent-data +doesn't compile because of conflicting declarations. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/persistent-data/dm-btree-internal.h | 16 ++++---- + drivers/md/persistent-data/dm-btree-remove.c | 50 ++++++++++++------------- + drivers/md/persistent-data/dm-btree-spine.c | 6 +-- + drivers/md/persistent-data/dm-btree.c | 22 +++++------ + 4 files changed, 47 insertions(+), 47 deletions(-) + +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -36,13 +36,13 @@ struct node_header { + __le32 padding; + } __packed; + +-struct node { ++struct btree_node { + struct node_header header; + __le64 keys[0]; + } __packed; + + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); + + int new_block(struct dm_btree_info *info, struct dm_block **result); +@@ -64,7 +64,7 @@ struct ro_spine { + void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); + int exit_ro_spine(struct ro_spine *s); + int ro_step(struct ro_spine *s, dm_block_t new_child); +-struct node *ro_node(struct ro_spine *s); ++struct btree_node *ro_node(struct ro_spine *s); + + struct shadow_spine { + struct dm_btree_info *info; +@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); + /* + * Some inlines. + */ +-static inline __le64 *key_ptr(struct node *n, uint32_t index) ++static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) + { + return n->keys + index; + } + +-static inline void *value_base(struct node *n) ++static inline void *value_base(struct btree_node *n) + { + return &n->keys[le32_to_cpu(n->header.max_entries)]; + } + +-static inline void *value_ptr(struct node *n, uint32_t index) ++static inline void *value_ptr(struct btree_node *n, uint32_t index) + { + uint32_t value_size = le32_to_cpu(n->header.value_size); + return value_base(n) + (value_size * index); +@@ -117,7 +117,7 @@ static inline void *value_ptr(struct nod + /* + * Assumes the values are suitably-aligned and converts to core format. + */ +-static inline uint64_t value64(struct node *n, uint32_t index) ++static inline uint64_t value64(struct btree_node *n, uint32_t index) + { + __le64 *values_le = value_base(n); + +@@ -127,7 +127,7 @@ static inline uint64_t value64(struct no + /* + * Searching for a key within a single node. + */ +-int lower_bound(struct node *n, uint64_t key); ++int lower_bound(struct btree_node *n, uint64_t key); + + extern struct dm_block_validator btree_node_validator; + +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -53,7 +53,7 @@ + /* + * Some little utilities for moving node data around. + */ +-static void node_shift(struct node *n, int shift) ++static void node_shift(struct btree_node *n, int shift) + { + uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); + uint32_t value_size = le32_to_cpu(n->header.value_size); +@@ -79,7 +79,7 @@ static void node_shift(struct node *n, i + } + } + +-static void node_copy(struct node *left, struct node *right, int shift) ++static void node_copy(struct btree_node *left, struct btree_node *right, int shift) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t value_size = le32_to_cpu(left->header.value_size); +@@ -108,7 +108,7 @@ static void node_copy(struct node *left, + /* + * Delete a specific entry from a leaf node. + */ +-static void delete_at(struct node *n, unsigned index) ++static void delete_at(struct btree_node *n, unsigned index) + { + unsigned nr_entries = le32_to_cpu(n->header.nr_entries); + unsigned nr_to_copy = nr_entries - (index + 1); +@@ -128,7 +128,7 @@ static void delete_at(struct node *n, un + n->header.nr_entries = cpu_to_le32(nr_entries - 1); + } + +-static unsigned merge_threshold(struct node *n) ++static unsigned merge_threshold(struct btree_node *n) + { + return le32_to_cpu(n->header.max_entries) / 3; + } +@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct n + struct child { + unsigned index; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + }; + + static struct dm_btree_value_type le64_type = { +@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_t + .equal = NULL + }; + +-static int init_child(struct dm_btree_info *info, struct node *parent, ++static int init_child(struct dm_btree_info *info, struct btree_node *parent, + unsigned index, struct child *result) + { + int r, inc; +@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_in + return dm_tm_unlock(info->tm, c->block); + } + +-static void shift(struct node *left, struct node *right, int count) ++static void shift(struct btree_node *left, struct btree_node *right, int count) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); +@@ -203,11 +203,11 @@ static void shift(struct node *left, str + right->header.nr_entries = cpu_to_le32(nr_right + count); + } + +-static void __rebalance2(struct dm_btree_info *info, struct node *parent, ++static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *r) + { +- struct node *left = l->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *right = r->n; + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); + unsigned threshold = 2 * merge_threshold(left) + 1; +@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent; ++ struct btree_node *parent; + struct child left, right; + + parent = dm_block_data(shadow_current(s)); +@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spin + * in right, then rebalance2. This wastes some cpu, but I want something + * simple atm. + */ +-static void delete_center_node(struct dm_btree_info *info, struct node *parent, ++static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + uint32_t max_entries = le32_to_cpu(left->header.max_entries); +@@ -301,9 +301,9 @@ static void delete_center_node(struct dm + /* + * Redistributes entries among 3 sibling nodes. + */ +-static void redistribute3(struct dm_btree_info *info, struct node *parent, ++static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + int s; +@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btre + *key_ptr(parent, r->index) = right->keys[0]; + } + +-static void __rebalance3(struct dm_btree_info *info, struct node *parent, ++static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r) + { +- struct node *left = l->n; +- struct node *center = c->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *center = c->n; ++ struct btree_node *right = r->n; + + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_center = le32_to_cpu(center->header.nr_entries); +@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent = dm_block_data(shadow_current(s)); ++ struct btree_node *parent = dm_block_data(shadow_current(s)); + struct child left, center, right; + + /* +@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_tran + { + int r; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + + r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); + if (r) +@@ -438,7 +438,7 @@ static int rebalance_children(struct sha + { + int i, r, has_left_sibling, has_right_sibling; + uint32_t child_entries; +- struct node *n; ++ struct btree_node *n; + + n = dm_block_data(shadow_current(s)); + +@@ -483,7 +483,7 @@ static int rebalance_children(struct sha + return r; + } + +-static int do_leaf(struct node *n, uint64_t key, unsigned *index) ++static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) + { + int i = lower_bound(n, key); + +@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spin + uint64_t key, unsigned *index) + { + int i = *index, r; +- struct node *n; ++ struct btree_node *n; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info + unsigned level, last_level = info->levels - 1; + int index = 0, r = 0; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + + init_shadow_spine(&spine, info); + for (level = 0; level < info->levels; level++) { +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -23,7 +23,7 @@ static void node_prepare_for_write(struc + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + + h->blocknr = cpu_to_le64(dm_block_location(b)); +@@ -38,7 +38,7 @@ static int node_check(struct dm_block_va + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + size_t value_size; + __le32 csum_disk; +@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block + return r; + } + +-struct node *ro_node(struct ro_spine *s) ++struct btree_node *ro_node(struct ro_spine *s) + { + struct dm_block *block; + +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -38,7 +38,7 @@ static void array_insert(void *base, siz + /*----------------------------------------------------------------*/ + + /* makes the assumption that no two keys are the same. */ +-static int bsearch(struct node *n, uint64_t key, int want_hi) ++static int bsearch(struct btree_node *n, uint64_t key, int want_hi) + { + int lo = -1, hi = le32_to_cpu(n->header.nr_entries); + +@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint6 + return want_hi ? hi : lo; + } + +-int lower_bound(struct node *n, uint64_t key) ++int lower_bound(struct btree_node *n, uint64_t key) + { + return bsearch(n, key, 0); + } + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt) + { + unsigned i; +@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_ + vt->inc(vt->context, value_ptr(n, i)); + } + +-static int insert_at(size_t value_size, struct node *node, unsigned index, ++static int insert_at(size_t value_size, struct btree_node *node, unsigned index, + uint64_t key, void *value) + __dm_written_to_disk(value) + { +@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info + { + int r; + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + size_t block_size; + uint32_t max_entries; + +@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); + #define MAX_SPINE_DEPTH 64 + struct frame { + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + unsigned level; + unsigned nr_children; + unsigned current_child; +@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); + /*----------------------------------------------------------------*/ + + static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, +- int (*search_fn)(struct node *, uint64_t), ++ int (*search_fn)(struct btree_node *, uint64_t), + uint64_t *result_key, void *v, size_t value_size) + { + int i, r; +@@ -406,7 +406,7 @@ static int btree_split_sibling(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *parent; +- struct node *ln, *rn, *pn; ++ struct btree_node *ln, *rn, *pn; + __le64 location; + + left = shadow_current(s); +@@ -491,7 +491,7 @@ static int btree_split_beneath(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *new_parent; +- struct node *pn, *ln, *rn; ++ struct btree_node *pn, *ln, *rn; + __le64 val; + + new_parent = shadow_current(s); +@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shado + uint64_t key, unsigned *index) + { + int r, i = *index, top = 1; +- struct node *node; ++ struct btree_node *node; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info * + unsigned level, index = -1, last_level = info->levels - 1; + dm_block_t block = root; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + struct dm_btree_value_type le64_type; + + le64_type.context = NULL; +From e910d7ebecd1aac43125944a8641b6cb1a0dfabe Mon Sep 17 00:00:00 2001 +From: Alasdair G Kergon +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm ioctl: prevent unsafe change to dm_ioctl data_size + +From: Alasdair G Kergon + +commit e910d7ebecd1aac43125944a8641b6cb1a0dfabe upstream. + +Abort dm ioctl processing if userspace changes the data_size parameter +after we validated it but before we finished copying the data buffer +from userspace. + +The dm ioctl parameters are processed in the following sequence: + 1. ctl_ioctl() calls copy_params(); + 2. copy_params() makes a first copy of the fixed-sized portion of the + userspace parameters into the local variable "tmp"; + 3. copy_params() then validates tmp.data_size and allocates a new + structure big enough to hold the complete data and copies the whole + userspace buffer there; + 4. ctl_ioctl() reads userspace data the second time and copies the whole + buffer into the pointer "param"; + 5. ctl_ioctl() reads param->data_size without any validation and stores it + in the variable "input_param_size"; + 6. "input_param_size" is further used as the authoritative size of the + kernel buffer. + +The problem is that userspace code could change the contents of user +memory between steps 2 and 4. In particular, the data_size parameter +can be changed to an invalid value after the kernel has validated it. +This lets userspace force the kernel to access invalid kernel memory. + +The fix is to ensure that the size has not changed at step 4. + +This patch shouldn't have a security impact because CAP_SYS_ADMIN is +required to run this code, but it should be fixed anyway. + +Reported-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-ioctl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1566,6 +1566,14 @@ static int copy_params(struct dm_ioctl _ + if (copy_from_user(dmi, user, tmp.data_size)) + goto bad; + ++ /* ++ * Abort if something changed the ioctl data while it was being copied. ++ */ ++ if (dmi->data_size != tmp.data_size) { ++ DMERR("rejecting ioctl: data size modified while processing parameters"); ++ goto bad; ++ } ++ + /* Wipe the user buffer so we do not return it to userspace */ + if (secure_data && clear_user(user, tmp.data_size)) + goto bad; +From b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d Mon Sep 17 00:00:00 2001 +From: Joe Thornber +Date: Fri, 21 Dec 2012 20:23:31 +0000 +Subject: dm thin: replace dm_cell_release_singleton with cell_defer_except + +From: Joe Thornber + +commit b7ca9c9273e5eebd63880dd8a6e4e5c18fc7901d upstream. + +Change existing users of the function dm_cell_release_singleton to share +cell_defer_except instead, and then remove the now-unused function. + +Everywhere that calls dm_cell_release_singleton, the bio in question +is the holder of the cell. + +If there are no non-holder entries in the cell then cell_defer_except +behaves exactly like dm_cell_release_singleton. Conversely, if there +*are* non-holder entries then dm_cell_release_singleton must not be used +because those entries would need to be deferred. + +Consequently, it is safe to replace use of dm_cell_release_singleton +with cell_defer_except. + +This patch is a pre-requisite for "dm thin: fix race between +simultaneous io and discards to same block". + +Signed-off-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-bio-prison.c | 25 ------------------------- + drivers/md/dm-bio-prison.h | 1 - + drivers/md/dm-thin.c | 25 ++++++++++++------------- + 3 files changed, 12 insertions(+), 39 deletions(-) + +--- a/drivers/md/dm-bio-prison.c ++++ b/drivers/md/dm-bio-prison.c +@@ -208,31 +208,6 @@ void dm_cell_release(struct dm_bio_priso + EXPORT_SYMBOL_GPL(dm_cell_release); + + /* +- * There are a couple of places where we put a bio into a cell briefly +- * before taking it out again. In these situations we know that no other +- * bio may be in the cell. This function releases the cell, and also does +- * a sanity check. +- */ +-static void __cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +-{ +- BUG_ON(cell->holder != bio); +- BUG_ON(!bio_list_empty(&cell->bios)); +- +- __cell_release(cell, NULL); +-} +- +-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio) +-{ +- unsigned long flags; +- struct dm_bio_prison *prison = cell->prison; +- +- spin_lock_irqsave(&prison->lock, flags); +- __cell_release_singleton(cell, bio); +- spin_unlock_irqrestore(&prison->lock, flags); +-} +-EXPORT_SYMBOL_GPL(dm_cell_release_singleton); +- +-/* + * Sometimes we don't want the holder, just the additional bios. + */ + static void __cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates) +--- a/drivers/md/dm-bio-prison.h ++++ b/drivers/md/dm-bio-prison.h +@@ -44,7 +44,6 @@ int dm_bio_detain(struct dm_bio_prison * + struct bio *inmate, struct dm_bio_prison_cell **ref); + + void dm_cell_release(struct dm_bio_prison_cell *cell, struct bio_list *bios); +-void dm_cell_release_singleton(struct dm_bio_prison_cell *cell, struct bio *bio); // FIXME: bio arg not needed + void dm_cell_release_no_holder(struct dm_bio_prison_cell *cell, struct bio_list *inmates); + void dm_cell_error(struct dm_bio_prison_cell *cell); + +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -513,8 +513,7 @@ static void cell_defer(struct thin_c *tc + } + + /* +- * Same as cell_defer above, except it omits one particular detainee, +- * a write bio that covers the block and has already been processed. ++ * Same as cell_defer except it omits the original holder of the cell. + */ + static void cell_defer_except(struct thin_c *tc, struct dm_bio_prison_cell *cell) + { +@@ -936,7 +935,7 @@ static void process_discard(struct thin_ + */ + build_data_key(tc->td, lookup_result.block, &key2); + if (dm_bio_detain(tc->pool->prison, &key2, bio, &cell2)) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + break; + } + +@@ -967,8 +966,8 @@ static void process_discard(struct thin_ + * a block boundary. So we submit the discard of a + * partial block appropriately. + */ +- dm_cell_release_singleton(cell, bio); +- dm_cell_release_singleton(cell2, bio); ++ cell_defer_except(tc, cell); ++ cell_defer_except(tc, cell2); + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else +@@ -980,13 +979,13 @@ static void process_discard(struct thin_ + /* + * It isn't provisioned, just forget it. + */ +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_endio(bio, 0); + break; + + default: + DMERR("discard: find block unexpectedly returned %d", r); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_io_error(bio); + break; + } +@@ -1041,7 +1040,7 @@ static void process_shared_bio(struct th + + h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); + +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_and_issue(tc, bio, lookup_result->block); + } + } +@@ -1056,7 +1055,7 @@ static void provision_block(struct thin_ + * Remap empty bios (flushes) immediately, without provisioning. + */ + if (!bio->bi_size) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_and_issue(tc, bio, 0); + return; + } +@@ -1066,7 +1065,7 @@ static void provision_block(struct thin_ + */ + if (bio_data_dir(bio) == READ) { + zero_fill_bio(bio); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_endio(bio, 0); + return; + } +@@ -1120,7 +1119,7 @@ static void process_bio(struct thin_c *t + * TODO: this will probably have to change when discard goes + * back in. + */ +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + + if (lookup_result.shared) + process_shared_bio(tc, bio, block, &lookup_result); +@@ -1130,7 +1129,7 @@ static void process_bio(struct thin_c *t + + case -ENODATA: + if (bio_data_dir(bio) == READ && tc->origin_dev) { +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + remap_to_origin_and_issue(tc, bio); + } else + provision_block(tc, bio, block, cell); +@@ -1138,7 +1137,7 @@ static void process_bio(struct thin_c *t + + default: + DMERR("dm_thin_find_block() failed, error = %d", r); +- dm_cell_release_singleton(cell, bio); ++ cell_defer_except(tc, cell); + bio_io_error(bio); + break; + } +From ab1dd9963137a1e122004d5378a581bf16ae9bc8 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 7 Oct 2012 08:27:00 +0100 +Subject: staging: vt6656: [BUG] out of bound array reference in RFbSetPower. + +From: Malcolm Priestley + +commit ab1dd9963137a1e122004d5378a581bf16ae9bc8 upstream. + +Calling RFbSetPower with uCH zero value will cause out of bound array reference. + +This causes 64 bit kernels to oops on boot. + +Note: Driver does not function on 64 bit kernels and should be +blacklisted on them. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/rf.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/vt6656/rf.c ++++ b/drivers/staging/vt6656/rf.c +@@ -769,6 +769,9 @@ BYTE byPwr = pDevice->byCCKPwr; + return TRUE; + } + ++ if (uCH == 0) ++ return -EINVAL; ++ + switch (uRATE) { + case RATE_1M: + case RATE_2M: +From a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:32:05 +0000 +Subject: staging: vt6656: 64 bit fixes: use u32 for QWORD definition. + +From: Malcolm Priestley + +commit a552397d5e4ef0cc0bd3e9595d6acc9a3b381171 upstream. + +Size of long issues replace with u32. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/ttype.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/staging/vt6656/ttype.h ++++ b/drivers/staging/vt6656/ttype.h +@@ -29,6 +29,8 @@ + #ifndef __TTYPE_H__ + #define __TTYPE_H__ + ++#include ++ + /******* Common definitions and typedefs ***********************************/ + + typedef int BOOL; +@@ -51,8 +53,8 @@ typedef unsigned long DWORD; + // which is NOT really a floating point number. + typedef union tagUQuadWord { + struct { +- DWORD dwLowDword; +- DWORD dwHighDword; ++ u32 dwLowDword; ++ u32 dwHighDword; + } u; + double DoNotUseThisField; + } UQuadWord; +From 7730492855a2f9c828599bcd8d62760f96d319e4 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:41:25 +0000 +Subject: staging: vt6656: 64 bit fixes : correct all type sizes + +From: Malcolm Priestley + +commit 7730492855a2f9c828599bcd8d62760f96d319e4 upstream. + +After this patch all BYTE/WORD/DWORD types can be replaced with the appropriate u sizes. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/ttype.h | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/staging/vt6656/ttype.h ++++ b/drivers/staging/vt6656/ttype.h +@@ -44,9 +44,9 @@ typedef int BOOL; + + /****** Simple typedefs ***************************************************/ + +-typedef unsigned char BYTE; // 8-bit +-typedef unsigned short WORD; // 16-bit +-typedef unsigned long DWORD; // 32-bit ++typedef u8 BYTE; ++typedef u16 WORD; ++typedef u32 DWORD; + + // QWORD is for those situation that we want + // an 8-byte-aligned 8 byte long structure +@@ -62,8 +62,8 @@ typedef UQuadWord QWORD; + + /****** Common pointer types ***********************************************/ + +-typedef unsigned long ULONG_PTR; // 32-bit +-typedef unsigned long DWORD_PTR; // 32-bit ++typedef u32 ULONG_PTR; ++typedef u32 DWORD_PTR; + + // boolean pointer + +From b4dc03af5513774277c9c36b12a25cd3f25f4404 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:45:52 +0000 +Subject: staging: vt6656: 64 bit fixes: fix long warning messages. + +From: Malcolm Priestley + +commit b4dc03af5513774277c9c36b12a25cd3f25f4404 upstream. + +Fixes long warning messages from patch +[PATCH 08/14] staging: vt6656: 64 bit fixes : correct all type sizes + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/dpc.c | 4 +-- + drivers/staging/vt6656/key.c | 47 +++++++++++++++++++++++++++++------------- + drivers/staging/vt6656/mac.c | 6 +++-- + drivers/staging/vt6656/rxtx.c | 18 ++++++++++------ + 4 files changed, 51 insertions(+), 24 deletions(-) + +--- a/drivers/staging/vt6656/dpc.c ++++ b/drivers/staging/vt6656/dpc.c +@@ -1238,7 +1238,7 @@ static BOOL s_bHandleRxEncryption ( + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); + } else { +@@ -1349,7 +1349,7 @@ static BOOL s_bHostWepRxEncryption ( + + PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc + *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); + + if (byDecMode == KEY_CTL_TKIP) { + *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); +--- a/drivers/staging/vt6656/key.c ++++ b/drivers/staging/vt6656/key.c +@@ -235,7 +235,8 @@ BOOL KeybSetKey( + PSKeyItem pKey; + unsigned int uKeyIdx; + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Enter KeybSetKey: %X\n", dwKeyIndex); + + j = (MAX_KEY_TABLE-1); + for (i=0;i<(MAX_KEY_TABLE-1);i++) { +@@ -261,7 +262,9 @@ BOOL KeybSetKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[i].dwGTKeyIndex, i); + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); +@@ -302,9 +305,12 @@ BOOL KeybSetKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", ++ pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", ++ pKey->wTSC15_0); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -326,7 +332,9 @@ BOOL KeybSetKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(N)[%X]: %d\n", ++ pTable->KeyTable[j].dwGTKeyIndex, j); + } + pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed + pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); +@@ -367,9 +375,11 @@ BOOL KeybSetKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", ++ pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", ++ pTable->KeyTable[i].dwGTKeyIndex); + + return (TRUE); + } +@@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, ++ MAX_KEY_TABLE-1); + + } + pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed +@@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey( + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", ++ pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", ++ pKey->dwKeyIndex); + + return (TRUE); + } +@@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey( + PSKeyItem pKey; + unsigned int uKeyIdx; + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", ++ dwKeyIndex); + + + if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key +@@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey( + if ((dwKeyIndex & TRANSMIT_KEY) != 0) { + // Group transmit key + pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO ++ "Group transmit key(R)[%X]: %d\n", ++ pTable->KeyTable[i].dwGTKeyIndex, i); + + } + pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed +--- a/drivers/staging/vt6656/mac.c ++++ b/drivers/staging/vt6656/mac.c +@@ -260,7 +260,8 @@ BYTE pbyData[24]; + dwData1 <<= 16; + dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ ++ " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); +@@ -277,7 +278,8 @@ BYTE pbyData[24]; + dwData2 <<= 8; + dwData2 |= *(pbyAddr+0); + +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", ++ wOffset, dwData2); + + //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); + //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); +--- a/drivers/staging/vt6656/rxtx.c ++++ b/drivers/staging/vt6656/rxtx.c +@@ -375,7 +375,8 @@ s_vFillTxKey ( + *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV + // Append IV&ExtIV after Mac Header + *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", ++ *pdwExtIV); + + } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { + pTransmitKey->wTSC15_0++; +@@ -1751,7 +1752,8 @@ s_bPacketToWirelessUsb( + MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", ++ dwMICKey0, dwMICKey1); + + /////////////////////////////////////////////////////////////////// + +@@ -2633,7 +2635,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct + MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); + dwMIC_Priority = 0; + MIC_vAppend((PBYTE)&dwMIC_Priority, 4); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ ++ " %X, %X\n", dwMICKey0, dwMICKey1); + + uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; + +@@ -2653,7 +2656,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", ++ *pdwMIC_L, *pdwMIC_R); + + } + +@@ -3027,7 +3031,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); + } + else { +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", ++ pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } +@@ -3041,7 +3046,8 @@ int nsDMA_tx_packet(PSDevice pDevice, un + if (pDevice->bEnableHostWEP) { + if ((uNodeIndex != 0) && + (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { +- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); ++ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", ++ pTransmitKey->dwKeyIndex); + bNeedEncryption = TRUE; + } + } +From c0d05b305b00c698b0a8c1b3d46c9380bce9db45 Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 15:49:59 +0000 +Subject: staging: vt6656: 64bit fixes: key.c/h change unsigned long to u32 + +From: Malcolm Priestley + +commit c0d05b305b00c698b0a8c1b3d46c9380bce9db45 upstream. + +Fixes long issues. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/key.c | 6 +++--- + drivers/staging/vt6656/key.h | 8 ++++---- + 2 files changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/staging/vt6656/key.c ++++ b/drivers/staging/vt6656/key.c +@@ -223,7 +223,7 @@ BOOL KeybSetKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -675,7 +675,7 @@ BOOL KeybSetDefaultKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -791,7 +791,7 @@ BOOL KeybSetAllGroupKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +--- a/drivers/staging/vt6656/key.h ++++ b/drivers/staging/vt6656/key.h +@@ -58,7 +58,7 @@ + typedef struct tagSKeyItem + { + BOOL bKeyValid; +- unsigned long uKeyLength; ++ u32 uKeyLength; + BYTE abyKey[MAX_KEY_LEN]; + QWORD KeyRSC; + DWORD dwTSC47_16; +@@ -107,7 +107,7 @@ BOOL KeybSetKey( + PSKeyManagement pTable, + PBYTE pbyBSSID, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +@@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey( + void *pDeviceHandler, + PSKeyManagement pTable, + DWORD dwKeyIndex, +- unsigned long uKeyLength, ++ u32 uKeyLength, + PQWORD pKeyRSC, + PBYTE pbyKey, + BYTE byKeyDecMode +From 70e227790d4ee4590023d8041a3485f8053593fc Mon Sep 17 00:00:00 2001 +From: Malcolm Priestley +Date: Sun, 11 Nov 2012 16:07:57 +0000 +Subject: staging: vt6656: 64bit fixes: vCommandTimerWait change calculation of timer. + +From: Malcolm Priestley + +commit 70e227790d4ee4590023d8041a3485f8053593fc upstream. + +The timer appears to run too fast/race on 64 bit systems. + +Using msecs_to_jiffies seems to cause a deadlock on 64 bit. + +A calculation of (MSecond * HZ) / 1000 appears to run satisfactory. + +Change BSSIDInfoCount to u32. + +After this patch the driver can be successfully connect on little endian 64/32 bit systems. + +Signed-off-by: Malcolm Priestley +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/vt6656/wcmd.c | 20 +++++++++++--------- + drivers/staging/vt6656/wpa2.h | 4 ++-- + 2 files changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/staging/vt6656/wcmd.c ++++ b/drivers/staging/vt6656/wcmd.c +@@ -316,17 +316,19 @@ s_MgrMakeProbeRequest( + return pTxPacket; + } + +-void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond) ++void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond) + { +- PSDevice pDevice = (PSDevice)hDeviceContext; ++ PSDevice pDevice = (PSDevice)hDeviceContext; + +- init_timer(&pDevice->sTimerCommand); +- pDevice->sTimerCommand.data = (unsigned long)pDevice; +- pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; +- // RUN_AT :1 msec ~= (HZ/1024) +- pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); +- add_timer(&pDevice->sTimerCommand); +- return; ++ init_timer(&pDevice->sTimerCommand); ++ ++ pDevice->sTimerCommand.data = (unsigned long)pDevice; ++ pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; ++ pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); ++ ++ add_timer(&pDevice->sTimerCommand); ++ ++ return; + } + + void vRunCommand(void *hDeviceContext) +--- a/drivers/staging/vt6656/wpa2.h ++++ b/drivers/staging/vt6656/wpa2.h +@@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo { + } PMKIDInfo, *PPMKIDInfo; + + typedef struct tagSPMKIDCache { +- unsigned long BSSIDInfoCount; +- PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; ++ u32 BSSIDInfoCount; ++ PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; + } SPMKIDCache, *PSPMKIDCache; + + +From 0602934f302e016e2ea5dc6951681bfac77455ef Mon Sep 17 00:00:00 2001 +From: Chris Verges +Date: Fri, 21 Dec 2012 01:58:34 -0800 +Subject: hwmon: (lm73} Detect and report i2c bus errors + +From: Chris Verges + +commit 0602934f302e016e2ea5dc6951681bfac77455ef upstream. + +If an LM73 device does not exist on an I2C bus, attempts to communicate +with the device result in an error code returned from the i2c read/write +functions. The current lm73 driver casts that return value from a s32 +type to a s16 type, then converts it to a temperature in celsius. +Because negative temperatures are valid, it is difficult to distinguish +between an error code printed to the response buffer and a negative +temperature recorded by the sensor. + +The solution is to evaluate the return value from the i2c functions +before performing any temperature calculations. If the i2c function did +not succeed, the error code should be passed back through the virtual +file system layer instead of being printed into the response buffer. + +Before: + + $ cat /sys/class/hwmon/hwmon0/device/temp1_input + -46 + +After: + + $ cat /sys/class/hwmon/hwmon0/device/temp1_input + cat: read error: No such device or address + +Signed-off-by: Chris Verges +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwmon/lm73.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/hwmon/lm73.c ++++ b/drivers/hwmon/lm73.c +@@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *d + struct i2c_client *client = to_i2c_client(dev); + long temp; + short value; ++ s32 err; + + int status = kstrtol(buf, 10, &temp); + if (status < 0) +@@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *d + /* Write value */ + value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), + (LM73_TEMP_MAX*4)) << 5; +- i2c_smbus_write_word_swapped(client, attr->index, value); +- return count; ++ err = i2c_smbus_write_word_swapped(client, attr->index, value); ++ return (err < 0) ? err : count; + } + + static ssize_t show_temp(struct device *dev, struct device_attribute *da, +@@ -66,11 +67,16 @@ static ssize_t show_temp(struct device * + { + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); ++ int temp; ++ ++ s32 err = i2c_smbus_read_word_swapped(client, attr->index); ++ if (err < 0) ++ return err; ++ + /* use integer division instead of equivalent right shift to + guarantee arithmetic shift and preserve the sign */ +- int temp = ((s16) (i2c_smbus_read_word_swapped(client, +- attr->index))*250) / 32; +- return sprintf(buf, "%d\n", temp); ++ temp = (((s16) err) * 250) / 32; ++ return scnprintf(buf, PAGE_SIZE, "%d\n", temp); + } + + +From 7b9205bd775afc4439ed86d617f9042ee9e76a71 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Fri, 11 Jan 2013 14:32:05 -0800 +Subject: audit: create explicit AUDIT_SECCOMP event type + +From: Kees Cook + +commit 7b9205bd775afc4439ed86d617f9042ee9e76a71 upstream. + +The seccomp path was using AUDIT_ANOM_ABEND from when seccomp mode 1 +could only kill a process. While we still want to make sure an audit +record is forced on a kill, this should use a separate record type since +seccomp mode 2 introduces other behaviors. + +In the case of "handled" behaviors (process wasn't killed), only emit a +record if the process is under inspection. This change also fixes +userspace examination of seccomp audit events, since it was considered +malformed due to missing fields of the AUDIT_ANOM_ABEND event type. + +Signed-off-by: Kees Cook +Cc: Al Viro +Cc: Eric Paris +Cc: Jeff Layton +Cc: "Eric W. Biederman" +Cc: Julien Tinnes +Acked-by: Will Drewry +Acked-by: Steve Grubb +Cc: Andrea Arcangeli +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/audit.h | 3 ++- + include/uapi/linux/audit.h | 1 + + kernel/auditsc.c | 14 +++++++++++--- + 3 files changed, 14 insertions(+), 4 deletions(-) + +--- a/include/linux/audit.h ++++ b/include/linux/audit.h +@@ -157,7 +157,8 @@ void audit_core_dumps(long signr); + + static inline void audit_seccomp(unsigned long syscall, long signr, int code) + { +- if (unlikely(!audit_dummy_context())) ++ /* Force a record to be reported if a signal was delivered. */ ++ if (signr || unlikely(!audit_dummy_context())) + __audit_seccomp(syscall, signr, code); + } + +--- a/include/uapi/linux/audit.h ++++ b/include/uapi/linux/audit.h +@@ -106,6 +106,7 @@ + #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ + #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ + #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ ++#define AUDIT_SECCOMP 1326 /* Secure Computing event */ + + #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ + #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ +--- a/kernel/auditsc.c ++++ b/kernel/auditsc.c +@@ -2735,7 +2735,7 @@ void __audit_mmap_fd(int fd, int flags) + context->type = AUDIT_MMAP; + } + +-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) ++static void audit_log_task(struct audit_buffer *ab) + { + kuid_t auid, uid; + kgid_t gid; +@@ -2753,6 +2753,11 @@ static void audit_log_abend(struct audit + audit_log_task_context(ab); + audit_log_format(ab, " pid=%d comm=", current->pid); + audit_log_untrustedstring(ab, current->comm); ++} ++ ++static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) ++{ ++ audit_log_task(ab); + audit_log_format(ab, " reason="); + audit_log_string(ab, reason); + audit_log_format(ab, " sig=%ld", signr); +@@ -2783,8 +2788,11 @@ void __audit_seccomp(unsigned long sysca + { + struct audit_buffer *ab; + +- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); +- audit_log_abend(ab, "seccomp", signr); ++ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); ++ if (unlikely(!ab)) ++ return; ++ audit_log_task(ab); ++ audit_log_format(ab, " sig=%ld", signr); + audit_log_format(ab, " syscall=%ld", syscall); + audit_log_format(ab, " compat=%d", is_compat_task()); + audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); +From d9a58a782e396a0f04e8445b7ba3763c8a48c7fe Mon Sep 17 00:00:00 2001 +From: Ian Campbell +Date: Mon, 7 Jan 2013 05:32:06 +0000 +Subject: xen/netfront: improve truesize tracking + +From: Ian Campbell + +commit d9a58a782e396a0f04e8445b7ba3763c8a48c7fe upstream. + +Using RX_COPY_THRESHOLD is incorrect if the SKB is actually smaller +than that. We have already accounted for this in +NETFRONT_SKB_CB(skb)->pull_to so use that instead. + +Fixes WARN_ON from skb_try_coalesce. + +Signed-off-by: Ian Campbell +Cc: Sander Eikelenboom +Cc: Konrad Rzeszutek Wilk +Cc: annie li +Cc: xen-devel@lists.xen.org +Cc: netdev@vger.kernel.org +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/xen-netfront.c | 27 ++++----------------------- + 1 file changed, 4 insertions(+), 23 deletions(-) + +--- a/drivers/net/xen-netfront.c ++++ b/drivers/net/xen-netfront.c +@@ -1015,29 +1015,10 @@ err: + i = xennet_fill_frags(np, skb, &tmpq); + + /* +- * Truesize approximates the size of true data plus +- * any supervisor overheads. Adding hypervisor +- * overheads has been shown to significantly reduce +- * achievable bandwidth with the default receive +- * buffer size. It is therefore not wise to account +- * for it here. +- * +- * After alloc_skb(RX_COPY_THRESHOLD), truesize is set +- * to RX_COPY_THRESHOLD + the supervisor +- * overheads. Here, we add the size of the data pulled +- * in xennet_fill_frags(). +- * +- * We also adjust for any unused space in the main +- * data area by subtracting (RX_COPY_THRESHOLD - +- * len). This is especially important with drivers +- * which split incoming packets into header and data, +- * using only 66 bytes of the main data area (see the +- * e1000 driver for example.) On such systems, +- * without this last adjustement, our achievable +- * receive throughout using the standard receive +- * buffer size was cut by 25%(!!!). +- */ +- skb->truesize += skb->data_len - RX_COPY_THRESHOLD; ++ * Truesize is the actual allocation size, even if the ++ * allocation is only partially used. ++ */ ++ skb->truesize += PAGE_SIZE * skb_shinfo(skb)->nr_frags; + skb->len += skb->data_len; + + if (rx->flags & XEN_NETRXF_csum_blank) +From 92638e2facc5330475c7d558acec77721c3214e4 Mon Sep 17 00:00:00 2001 +From: Sivaram Nair +Date: Tue, 18 Dec 2012 13:52:54 +0100 +Subject: cpuidle / coupled: fix ready counter decrement + +From: Sivaram Nair + +commit 92638e2facc5330475c7d558acec77721c3214e4 upstream. + +The ready_waiting_counts atomic variable is compared against the wrong +online cpu count. The latter is computed incorrectly using logical-OR +instead of bit-OR. This patch fixes that. + +Signed-off-by: Sivaram Nair +Acked-by: Santosh Shilimkar +Acked-by: Colin Cross +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpuidle/coupled.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/cpuidle/coupled.c ++++ b/drivers/cpuidle/coupled.c +@@ -209,7 +209,7 @@ inline int cpuidle_coupled_set_not_ready + int all; + int ret; + +- all = coupled->online_count || (coupled->online_count << WAITING_BITS); ++ all = coupled->online_count | (coupled->online_count << WAITING_BITS); + ret = atomic_add_unless(&coupled->ready_waiting_counts, + -MAX_WAITING_CPUS, all); + +From 619c5a9ad54e6bbdafd16d1cdc6c049403710540 Mon Sep 17 00:00:00 2001 +From: Hante Meuleman +Date: Wed, 2 Jan 2013 15:12:39 +0100 +Subject: brcmfmac: fix parsing rsn ie for ap mode. + +From: Hante Meuleman + +commit 619c5a9ad54e6bbdafd16d1cdc6c049403710540 upstream. + +RSN IEs got incorrectly parsed and therefore ap mode using WPA2 +security was not working. + +Reviewed-by: Arend Van Spriel +Reviewed-by: Pieter-Paul Giesberts +Signed-off-by: Hante Meuleman +Signed-off-by: Arend van Spriel +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +@@ -3730,10 +3730,11 @@ brcmf_configure_wpaie(struct net_device + + len = wpa_ie->len + TLV_HDR_LEN; + data = (u8 *)wpa_ie; +- offset = 0; ++ offset = TLV_HDR_LEN; + if (!is_rsn_ie) + offset += VS_IE_FIXED_HDR_LEN; +- offset += WPA_IE_VERSION_LEN; ++ else ++ offset += WPA_IE_VERSION_LEN; + + /* check for multicast cipher suite */ + if (offset + WPA_IE_MIN_OUI_LEN > len) { +From 6c1ecba8d84841277d68140ef485335d5be28485 Mon Sep 17 00:00:00 2001 +From: Lothar Waßmann +Date: Thu, 22 Nov 2012 13:49:14 +0100 +Subject: video: mxsfb: fix crash when unblanking the display +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Lothar Waßmann + +commit 6c1ecba8d84841277d68140ef485335d5be28485 upstream. + +The VDCTRL4 register does not provide the MXS SET/CLR/TOGGLE feature. +The write in mxsfb_disable_controller() sets the data_cnt for the LCD +DMA to 0 which obviously means the max. count for the LCD DMA and +leads to overwriting arbitrary memory when the display is unblanked. + +Signed-off-by: Lothar Waßmann +Acked-by: Juergen Beisert +Tested-by: Lauri Hintsala +Signed-off-by: Shawn Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/mxsfb.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/video/mxsfb.c ++++ b/drivers/video/mxsfb.c +@@ -369,7 +369,8 @@ static void mxsfb_disable_controller(str + loop--; + } + +- writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR); ++ reg = readl(host->base + LCDC_VDCTRL4); ++ writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); + + clk_disable_unprepare(host->clk); + +From e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Wed, 5 Dec 2012 16:08:33 -0600 +Subject: samsung-laptop: Add quirk for broken acpi_video backlight on N250P + +From: Seth Forshee + +commit e04c200f1f2de8eaa2f5af6d97e7e213a1abb424 upstream. + +BugLink: http://bugs.launchpad.net/bugs/1086921 +Signed-off-by: Seth Forshee +Signed-off-by: Matthew Garrett +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/platform/x86/samsung-laptop.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/platform/x86/samsung-laptop.c ++++ b/drivers/platform/x86/samsung-laptop.c +@@ -1523,6 +1523,16 @@ static struct dmi_system_id __initdata s + }, + .driver_data = &samsung_broken_acpi_video, + }, ++ { ++ .callback = samsung_dmi_matched, ++ .ident = "N250P", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), ++ DMI_MATCH(DMI_BOARD_NAME, "N250P"), ++ }, ++ .driver_data = &samsung_broken_acpi_video, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); +From 9f6d8f6ab26b42620a914d67f29822f9bba90233 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Sat, 22 Dec 2012 23:59:01 +0100 +Subject: PM: Move disabling/enabling runtime PM to late suspend/early resume + +From: "Rafael J. Wysocki" + +commit 9f6d8f6ab26b42620a914d67f29822f9bba90233 upstream. + +Currently, the PM core disables runtime PM for all devices right +after executing subsystem/driver .suspend() callbacks for them +and re-enables it right before executing subsystem/driver .resume() +callbacks for them. This may lead to problems when there are +two devices such that the .suspend() callback executed for one of +them depends on runtime PM working for the other. In that case, +if runtime PM has already been disabled for the second device, +the first one's .suspend() won't work correctly (and analogously +for resume). + +To make those issues go away, make the PM core disable runtime PM +for devices right before executing subsystem/driver .suspend_late() +callbacks for them and enable runtime PM for them right after +executing subsystem/driver .resume_early() callbacks for them. This +way the potential conflitcs between .suspend_late()/.resume_early() +and their runtime PM counterparts are still prevented from happening, +but the subtle ordering issues related to disabling/enabling runtime +PM for devices during system suspend/resume are much easier to avoid. + +Reported-and-tested-by: Jan-Matthias Braun +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Ulf Hansson +Reviewed-by: Kevin Hilman +Signed-off-by: Greg Kroah-Hartman + +--- + Documentation/power/runtime_pm.txt | 9 +++++---- + drivers/base/power/main.c | 9 ++++----- + 2 files changed, 9 insertions(+), 9 deletions(-) + +--- a/Documentation/power/runtime_pm.txt ++++ b/Documentation/power/runtime_pm.txt +@@ -642,12 +642,13 @@ out the following operations: + * During system suspend it calls pm_runtime_get_noresume() and + pm_runtime_barrier() for every device right before executing the + subsystem-level .suspend() callback for it. In addition to that it calls +- pm_runtime_disable() for every device right after executing the +- subsystem-level .suspend() callback for it. ++ __pm_runtime_disable() with 'false' as the second argument for every device ++ right before executing the subsystem-level .suspend_late() callback for it. + + * During system resume it calls pm_runtime_enable() and pm_runtime_put_sync() +- for every device right before and right after executing the subsystem-level +- .resume() callback for it, respectively. ++ for every device right after executing the subsystem-level .resume_early() ++ callback and right after executing the subsystem-level .resume() callback ++ for it, respectively. + + 7. Generic subsystem callbacks + +--- a/drivers/base/power/main.c ++++ b/drivers/base/power/main.c +@@ -513,6 +513,8 @@ static int device_resume_early(struct de + + Out: + TRACE_RESUME(error); ++ ++ pm_runtime_enable(dev); + return error; + } + +@@ -589,8 +591,6 @@ static int device_resume(struct device * + if (!dev->power.is_suspended) + goto Unlock; + +- pm_runtime_enable(dev); +- + if (dev->pm_domain) { + info = "power domain "; + callback = pm_op(&dev->pm_domain->ops, state); +@@ -930,6 +930,8 @@ static int device_suspend_late(struct de + pm_callback_t callback = NULL; + char *info = NULL; + ++ __pm_runtime_disable(dev, false); ++ + if (dev->power.syscore) + return 0; + +@@ -1133,11 +1135,8 @@ static int __device_suspend(struct devic + + Complete: + complete_all(&dev->power.completion); +- + if (error) + async_error = error; +- else if (dev->power.is_suspended) +- __pm_runtime_disable(dev, false); + + return error; + } +From c36575e663e302dbaa4d16b9c72d2c9a913a9aef Mon Sep 17 00:00:00 2001 +From: Forrest Liu +Date: Mon, 17 Dec 2012 09:55:39 -0500 +Subject: ext4: fix extent tree corruption caused by hole punch + +From: Forrest Liu + +commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream. + +When depth of extent tree is greater than 1, logical start value of +interior node is not correctly updated in ext4_ext_rm_idx. + +Signed-off-by: Forrest Liu +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Ashish Sangwan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2190,13 +2190,14 @@ errout: + * removes index from the index block. + */ + static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, +- struct ext4_ext_path *path) ++ struct ext4_ext_path *path, int depth) + { + int err; + ext4_fsblk_t leaf; + + /* free index block */ +- path--; ++ depth--; ++ path = path + depth; + leaf = ext4_idx_pblock(path->p_idx); + if (unlikely(path->p_hdr->eh_entries == 0)) { + EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); +@@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *han + + ext4_free_blocks(handle, inode, NULL, leaf, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); ++ ++ while (--depth >= 0) { ++ if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) ++ break; ++ path--; ++ err = ext4_ext_get_access(handle, inode, path); ++ if (err) ++ break; ++ path->p_idx->ei_block = (path+1)->p_idx->ei_block; ++ err = ext4_ext_dirty(handle, inode, path); ++ if (err) ++ break; ++ } + return err; + } + +@@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struc + /* if this leaf is free, then we should + * remove it from index block above */ + if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) +- err = ext4_ext_rm_idx(handle, inode, path + depth); ++ err = ext4_ext_rm_idx(handle, inode, path, depth); + + out: + return err; +@@ -2760,7 +2774,7 @@ again: + /* index is empty, remove it; + * handle must be already prepared by the + * truncatei_leaf() */ +- err = ext4_ext_rm_idx(handle, inode, path + i); ++ err = ext4_ext_rm_idx(handle, inode, path, i); + } + /* root level has p_bh == NULL, brelse() eats this */ + brelse(path[i].p_bh); +From 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 20 Dec 2012 00:07:18 -0500 +Subject: ext4: check dioread_nolock on remount + +From: Jan Kara + +commit 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 upstream. + +Currently we allow enabling dioread_nolock mount option on remount for +filesystems where blocksize < PAGE_CACHE_SIZE. This isn't really +supported so fix the bug by moving the check for blocksize != +PAGE_CACHE_SIZE into parse_options(). Change the original PAGE_SIZE to +PAGE_CACHE_SIZE along the way because that's what we are really +interested in. + +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Eric Sandeen +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1650,9 +1650,7 @@ static int parse_options(char *options, + unsigned int *journal_ioprio, + int is_remount) + { +-#ifdef CONFIG_QUOTA + struct ext4_sb_info *sbi = EXT4_SB(sb); +-#endif + char *p; + substring_t args[MAX_OPT_ARGS]; + int token; +@@ -1701,6 +1699,16 @@ static int parse_options(char *options, + } + } + #endif ++ if (test_opt(sb, DIOREAD_NOLOCK)) { ++ int blocksize = ++ BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); ++ ++ if (blocksize < PAGE_CACHE_SIZE) { ++ ext4_msg(sb, KERN_ERR, "can't mount with " ++ "dioread_nolock if block size != PAGE_SIZE"); ++ return 0; ++ } ++ } + return 1; + } + +@@ -3446,15 +3454,6 @@ static int ext4_fill_super(struct super_ + clear_opt(sb, DELALLOC); + } + +- blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); +- if (test_opt(sb, DIOREAD_NOLOCK)) { +- if (blocksize < PAGE_SIZE) { +- ext4_msg(sb, KERN_ERR, "can't mount with " +- "dioread_nolock if block size != PAGE_SIZE"); +- goto failed_mount; +- } +- } +- + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); + +@@ -3496,6 +3495,7 @@ static int ext4_fill_super(struct super_ + if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) + goto failed_mount; + ++ blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); + if (blocksize < EXT4_MIN_BLOCK_SIZE || + blocksize > EXT4_MAX_BLOCK_SIZE) { + ext4_msg(sb, KERN_ERR, +From d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 21 Dec 2012 00:15:51 -0500 +Subject: jbd2: fix assertion failure in jbd2_journal_flush() + +From: Jan Kara + +commit d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a upstream. + +The following race is possible between start_this_handle() and someone +calling jbd2_journal_flush(). + +Process A Process B +start_this_handle(). + if (journal->j_barrier_count) # false + if (!journal->j_running_transaction) { #true + read_unlock(&journal->j_state_lock); + jbd2_journal_lock_updates() + jbd2_journal_flush() + write_lock(&journal->j_state_lock); + if (journal->j_running_transaction) { + # false + ... wait for committing trans ... + write_unlock(&journal->j_state_lock); + ... + write_lock(&journal->j_state_lock); + if (!journal->j_running_transaction) { # true + jbd2_get_transaction(journal, new_transaction); + write_unlock(&journal->j_state_lock); + goto repeat; # eventually blocks on j_barrier_count > 0 + ... + J_ASSERT(!journal->j_running_transaction); + # fails + +We fix the race by rechecking j_barrier_count after reacquiring j_state_lock +in exclusive mode. + +Reported-by: yjwsignal@empal.com +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -209,7 +209,8 @@ repeat: + if (!new_transaction) + goto alloc_transaction; + write_lock(&journal->j_state_lock); +- if (!journal->j_running_transaction) { ++ if (!journal->j_running_transaction && ++ !journal->j_barrier_count) { + jbd2_get_transaction(journal, new_transaction); + new_transaction = NULL; + } +From d096ad0f79a782935d2e06ae8fb235e8c5397775 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Tue, 25 Dec 2012 14:08:16 -0500 +Subject: ext4: do not try to write superblock on ro remount w/o journal + +From: Michael Tokarev + +commit d096ad0f79a782935d2e06ae8fb235e8c5397775 upstream. + +When a journal-less ext4 filesystem is mounted on a read-only block +device (blockdev --setro will do), each remount (for other, unrelated, +flags, like suid=>nosuid etc) results in a series of scary messages +from kernel telling about I/O errors on the device. + +This is becauese of the following code ext4_remount(): + + if (sbi->s_journal == NULL) + ext4_commit_super(sb, 1); + +at the end of remount procedure, which forces writing (flushing) of +a superblock regardless whenever it is dirty or not, if the filesystem +is readonly or not, and whenever the device itself is readonly or not. + +We only need call ext4_commit_super when the file system had been +previously mounted read/write. + +Thanks to Eric Sandeen for help in diagnosing this issue. + +Signed-off-By: Michael Tokarev +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4729,7 +4729,7 @@ static int ext4_remount(struct super_blo + } + + ext4_setup_system_zone(sb); +- if (sbi->s_journal == NULL) ++ if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) + ext4_commit_super(sb, 1); + + #ifdef CONFIG_QUOTA +From 721e3eba21e43532e438652dd8f1fcdfce3187e7 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:48 -0500 +Subject: ext4: lock i_mutex when truncating orphan inodes + +From: Theodore Ts'o + +commit 721e3eba21e43532e438652dd8f1fcdfce3187e7 upstream. + +Commit c278531d39 added a warning when ext4_flush_unwritten_io() is +called without i_mutex being taken. It had previously not been taken +during orphan cleanup since races weren't possible at that point in +the mount process, but as a result of this c278531d39, we will now see +a kernel WARN_ON in this case. Take the i_mutex in +ext4_orphan_cleanup() to suppress this warning. + +Reported-by: Alexander Beregalov +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2225,7 +2225,9 @@ static void ext4_orphan_cleanup(struct s + __func__, inode->i_ino, inode->i_size); + jbd_debug(2, "truncating inode %lu to %lld bytes\n", + inode->i_ino, inode->i_size); ++ mutex_lock(&inode->i_mutex); + ext4_truncate(inode); ++ mutex_unlock(&inode->i_mutex); + nr_truncates++; + } else { + ext4_msg(sb, KERN_DEBUG, +From 0e9a9a1ad619e7e987815d20262d36a2f95717ca Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:50 -0500 +Subject: ext4: avoid hang when mounting non-journal filesystems with orphan list + +From: Theodore Ts'o + +commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. + +When trying to mount a file system which does not contain a journal, +but which does have a orphan list containing an inode which needs to +be truncated, the mount call with hang forever in +ext4_orphan_cleanup() because ext4_orphan_del() will return +immediately without removing the inode from the orphan list, leading +to an uninterruptible loop in kernel code which will busy out one of +the CPU's on the system. + +This can be trivially reproduced by trying to mount the file system +found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs +source tree. If a malicious user were to put this on a USB stick, and +mount it on a Linux desktop which has automatic mounts enabled, this +could be considered a potential denial of service attack. (Not a big +deal in practice, but professional paranoids worry about such things, +and have even been known to allocate CVE numbers for such problems.) + +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2498,7 +2498,8 @@ int ext4_orphan_del(handle_t *handle, st + struct ext4_iloc iloc; + int err = 0; + +- if (!EXT4_SB(inode->i_sb)->s_journal) ++ if ((!EXT4_SB(inode->i_sb)->s_journal) && ++ !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) + return 0; + + mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); +From 0ecaef0644973e9006fdbc6974301047aaff9bc6 Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Sun, 6 Jan 2013 23:38:47 -0500 +Subject: ext4: release buffer in failed path in dx_probe() + +From: Guo Chao + +commit 0ecaef0644973e9006fdbc6974301047aaff9bc6 upstream. + +If checksum fails, we should also release the buffer +read from previous iteration. + +Signed-off-by: Guo Chao +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Darrick J. Wong - +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -725,7 +725,7 @@ dx_probe(const struct qstr *d_name, stru + ext4_warning(dir->i_sb, "Node failed checksum"); + brelse(bh); + *err = ERR_BAD_DX_DIR; +- goto fail; ++ goto fail2; + } + set_buffer_verified(bh); + +From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 +From: Ed Cashin +Date: Mon, 17 Dec 2012 16:03:58 -0800 +Subject: aoe: remove vestigial request queue allocation + +From: Ed Cashin + +commit 0a41409c518083133e79015092585d68915865be upstream. + +Before the aoe driver was an I/O request handler, it was a +make_request-style block driver. Even so, there was a problem where +sysfs expected a request queue to exist, so one was provided in commit +7135a71b19be ("aoe: allocate unused request_queue for sysfs"). + +During the transition to the request-handler style, a patch was merged +that was based on a driver without the noop queue, and the noop queue +remained in place after the patch was merged, even though a new +functional queue was introduced by the patch, allocated through +blk_init_queue. + +The user impact is a memory leak proportional to the number of AoE +targets discovered. This patch removes the memory leak and cleans up +vestiges of the old do-nothing queue from the aoeblk_gdalloc function. + +Signed-off-by: Ed Cashin +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/aoe/aoeblk.c | 17 ++++------------- + 1 file changed, 4 insertions(+), 13 deletions(-) + +--- a/drivers/block/aoe/aoeblk.c ++++ b/drivers/block/aoe/aoeblk.c +@@ -231,18 +231,12 @@ aoeblk_gdalloc(void *vp) + if (q == NULL) { + pr_err("aoe: cannot allocate block queue for %ld.%d\n", + d->aoemajor, d->aoeminor); +- mempool_destroy(mp); +- goto err_disk; ++ goto err_mempool; + } + +- d->blkq = blk_alloc_queue(GFP_KERNEL); +- if (!d->blkq) +- goto err_mempool; +- d->blkq->backing_dev_info.name = "aoe"; +- if (bdi_init(&d->blkq->backing_dev_info)) +- goto err_blkq; + spin_lock_irqsave(&d->lock, flags); +- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); ++ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); ++ q->backing_dev_info.name = "aoe"; + q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; + d->bufpool = mp; + d->blkq = gd->queue = q; +@@ -265,11 +259,8 @@ aoeblk_gdalloc(void *vp) + aoedisk_add_sysfs(d); + return; + +-err_blkq: +- blk_cleanup_queue(d->blkq); +- d->blkq = NULL; + err_mempool: +- mempool_destroy(d->bufpool); ++ mempool_destroy(mp); + err_disk: + put_disk(gd); + err: +From 2fb7d99d0de3fd8ae869f35ab682581d8455887a Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 10 Oct 2012 00:08:56 +0900 +Subject: udf: fix memory leak while allocating blocks during write + +From: Namjae Jeon + +commit 2fb7d99d0de3fd8ae869f35ab682581d8455887a upstream. + +Need to brelse the buffer_head stored in cur_epos and next_epos. + +Signed-off-by: Namjae Jeon +Signed-off-by: Ashish Sangwan +Signed-off-by: Jan Kara +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/inode.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -765,6 +765,8 @@ static sector_t inode_getblk(struct inod + goal, err); + if (!newblocknum) { + brelse(prev_epos.bh); ++ brelse(cur_epos.bh); ++ brelse(next_epos.bh); + *err = -ENOSPC; + return 0; + } +@@ -795,6 +797,8 @@ static sector_t inode_getblk(struct inod + udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); + + brelse(prev_epos.bh); ++ brelse(cur_epos.bh); ++ brelse(next_epos.bh); + + newblock = udf_get_pblock(inode->i_sb, newblocknum, + iinfo->i_location.partitionReferenceNum, 0); +From fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 Mon Sep 17 00:00:00 2001 +From: Namjae Jeon +Date: Wed, 10 Oct 2012 00:09:12 +0900 +Subject: udf: don't increment lenExtents while writing to a hole + +From: Namjae Jeon + +commit fb719c59bdb4fca86ee1fd1f42ab3735ca12b6b2 upstream. + +Incrementing lenExtents even while writing to a hole is bad +for performance as calls to udf_discard_prealloc and +udf_truncate_tail_extent would not return from start if +isize != lenExtents + +Signed-off-by: Namjae Jeon +Signed-off-by: Ashish Sangwan +Signed-off-by: Jan Kara +Signed-off-by: Shuah Khan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/inode.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -601,6 +601,7 @@ static sector_t inode_getblk(struct inod + struct udf_inode_info *iinfo = UDF_I(inode); + int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; + int lastblock = 0; ++ bool isBeyondEOF; + + *err = 0; + *new = 0; +@@ -680,7 +681,7 @@ static sector_t inode_getblk(struct inod + /* Are we beyond EOF? */ + if (etype == -1) { + int ret; +- ++ isBeyondEOF = 1; + if (count) { + if (c) + laarr[0] = laarr[1]; +@@ -723,6 +724,7 @@ static sector_t inode_getblk(struct inod + endnum = c + 1; + lastblock = 1; + } else { ++ isBeyondEOF = 0; + endnum = startnum = ((count > 2) ? 2 : count); + + /* if the current extent is in position 0, +@@ -770,7 +772,8 @@ static sector_t inode_getblk(struct inod + *err = -ENOSPC; + return 0; + } +- iinfo->i_lenExtents += inode->i_sb->s_blocksize; ++ if (isBeyondEOF) ++ iinfo->i_lenExtents += inode->i_sb->s_blocksize; + } + + /* if the extent the requsted block is located in contains multiple +From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 +From: Zhang Rui +Date: Tue, 4 Dec 2012 23:23:16 +0100 +Subject: ACPI : do not use Lid and Sleep button for S5 wakeup + +From: Zhang Rui + +commit b7e383046c2c7c13ad928cd7407eafff758ddd4b upstream. + +When system enters power off, the _PSW of Lid device is enabled. +But this may cause the system to reboot instead of power off. + +A proper way to fix this is to always disable lid wakeup capability for S5. + +References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 +Signed-off-by: Zhang Rui +Signed-off-by: Rafael J. Wysocki +Cc: Joseph Salisbury +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/scan.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/acpi/scan.c ++++ b/drivers/acpi/scan.c +@@ -859,8 +859,8 @@ acpi_bus_extract_wakeup_device_power_pac + static void acpi_bus_set_run_wake_flags(struct acpi_device *device) + { + struct acpi_device_id button_device_ids[] = { +- {"PNP0C0D", 0}, + {"PNP0C0C", 0}, ++ {"PNP0C0D", 0}, + {"PNP0C0E", 0}, + {"", 0}, + }; +@@ -872,6 +872,11 @@ static void acpi_bus_set_run_wake_flags( + /* Power button, Lid switch always enable wakeup */ + if (!acpi_match_device_ids(device, button_device_ids)) { + device->wakeup.flags.run_wake = 1; ++ if (!acpi_match_device_ids(device, &button_device_ids[1])) { ++ /* Do not use Lid/sleep button for S5 wakeup */ ++ if (device->wakeup.sleep_state == ACPI_STATE_S5) ++ device->wakeup.sleep_state = ACPI_STATE_S4; ++ } + device_set_wakeup_capable(&device->dev, true); + return; + } +From db04328c167ff8e7c57f4a3532214aeada3a82fd Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 11 Dec 2012 01:14:11 +0900 +Subject: regmap: debugfs: Avoid overflows for very small reads + +From: Mark Brown + +commit db04328c167ff8e7c57f4a3532214aeada3a82fd upstream. + +If count is less than the size of a register then we may hit integer +wraparound when trying to move backwards to check if we're still in +the buffer. Instead move the position forwards to check if it's still +in the buffer, we are unlikely to be able to allocate a buffer +sufficiently big to overflow here. + +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org + +--- + drivers/base/regmap/regmap-debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/base/regmap/regmap-debugfs.c ++++ b/drivers/base/regmap/regmap-debugfs.c +@@ -90,7 +90,7 @@ static ssize_t regmap_map_read_file(stru + /* If we're in the region the user is trying to read */ + if (p >= *ppos) { + /* ...but not beyond it */ +- if (buf_pos >= count - 1 - tot_len) ++ if (buf_pos + 1 + tot_len >= count) + break; + + /* Format the register */ +From 128dd1759d96ad36c379240f8b9463e8acfd37a1 Mon Sep 17 00:00:00 2001 +From: Eric Wong +Date: Tue, 1 Jan 2013 21:20:27 +0000 +Subject: epoll: prevent missed events on EPOLL_CTL_MOD + +From: Eric Wong + +commit 128dd1759d96ad36c379240f8b9463e8acfd37a1 upstream. + +EPOLL_CTL_MOD sets the interest mask before calling f_op->poll() to +ensure events are not missed. Since the modifications to the interest +mask are not protected by the same lock as ep_poll_callback, we need to +ensure the change is visible to other CPUs calling ep_poll_callback. + +We also need to ensure f_op->poll() has an up-to-date view of past +events which occured before we modified the interest mask. So this +barrier also pairs with the barrier in wq_has_sleeper(). + +This should guarantee either ep_poll_callback or f_op->poll() (or both) +will notice the readiness of a recently-ready/modified item. + +This issue was encountered by Andreas Voellmy and Junchang(Jason) Wang in: +http://thread.gmane.org/gmane.linux.kernel/1408782/ + +Signed-off-by: Eric Wong +Cc: Hans Verkuil +Cc: Jiri Olsa +Cc: Jonathan Corbet +Cc: Al Viro +Cc: Davide Libenzi +Cc: Hans de Goede +Cc: Mauro Carvalho Chehab +Cc: David Miller +Cc: Eric Dumazet +Cc: Andrew Morton +Cc: Andreas Voellmy +Tested-by: "Junchang(Jason) Wang" +Cc: netdev@vger.kernel.org +Cc: linux-fsdevel@vger.kernel.org +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/eventpoll.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/fs/eventpoll.c ++++ b/fs/eventpoll.c +@@ -1285,7 +1285,7 @@ static int ep_modify(struct eventpoll *e + * otherwise we might miss an event that happens between the + * f_op->poll() call and the new event set registering. + */ +- epi->event.events = event->events; ++ epi->event.events = event->events; /* need barrier below */ + pt._key = event->events; + epi->event.data = event->data; /* protected by mtx */ + if (epi->event.events & EPOLLWAKEUP) { +@@ -1296,6 +1296,26 @@ static int ep_modify(struct eventpoll *e + } + + /* ++ * The following barrier has two effects: ++ * ++ * 1) Flush epi changes above to other CPUs. This ensures ++ * we do not miss events from ep_poll_callback if an ++ * event occurs immediately after we call f_op->poll(). ++ * We need this because we did not take ep->lock while ++ * changing epi above (but ep_poll_callback does take ++ * ep->lock). ++ * ++ * 2) We also need to ensure we do not miss _past_ events ++ * when calling f_op->poll(). This barrier also ++ * pairs with the barrier in wq_has_sleeper (see ++ * comments for wq_has_sleeper). ++ * ++ * This barrier will now guarantee ep_poll_callback or f_op->poll ++ * (or both) will notice the readiness of an item. ++ */ ++ smp_mb(); ++ ++ /* + * Get current event bits. We can safely use the file* here because + * its usage count has been increased by the caller of this function. + */ +From 436136cec650d661eb662fcb508a99878606d050 Mon Sep 17 00:00:00 2001 +From: Marek Vasut +Date: Sat, 24 Nov 2012 06:15:57 +0100 +Subject: HID: add quirk for Freescale i.MX23 ROM recovery + +From: Marek Vasut + +commit 436136cec650d661eb662fcb508a99878606d050 upstream. + +The USB recovery mode present in i.MX23 ROM emulates USB HID. It needs this +quirk to behave properly. + +Even if the official branding of the chip is Freescale i.MX23, I named it +Sigmatel STMP3780 since that's what the chip really is and it even reports +itself as STMP3780. + +Signed-off-by: Marek Vasut +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/usbhid/hid-quirks.c | 1 + + 2 files changed, 4 insertions(+) + +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -696,6 +696,9 @@ + #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f + #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 + ++#define USB_VENDOR_ID_SIGMATEL 0x066F ++#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 ++ + #define USB_VENDOR_ID_SKYCABLE 0x1223 + #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 + +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -79,6 +79,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, ++ { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, +From a8c02db029385fb4426e0396e108ab23cd08f384 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 18 Dec 2012 14:05:01 +0000 +Subject: ASoC: arizona: Correct FLL source definitions + +From: Mark Brown + +commit a8c02db029385fb4426e0396e108ab23cd08f384 upstream. + +The FLL source constants were numbered as a simple enumeration but were +being used in the code as direct values to be written to the registers. +Renumber the constants to reflect the usage. + +Reported-by: Ryo Tsutsui +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.h | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/sound/soc/codecs/arizona.h ++++ b/sound/soc/codecs/arizona.h +@@ -32,15 +32,15 @@ + + #define ARIZONA_FLL_SRC_MCLK1 0 + #define ARIZONA_FLL_SRC_MCLK2 1 +-#define ARIZONA_FLL_SRC_SLIMCLK 2 +-#define ARIZONA_FLL_SRC_FLL1 3 +-#define ARIZONA_FLL_SRC_FLL2 4 +-#define ARIZONA_FLL_SRC_AIF1BCLK 5 +-#define ARIZONA_FLL_SRC_AIF2BCLK 6 +-#define ARIZONA_FLL_SRC_AIF3BCLK 7 +-#define ARIZONA_FLL_SRC_AIF1LRCLK 8 +-#define ARIZONA_FLL_SRC_AIF2LRCLK 9 +-#define ARIZONA_FLL_SRC_AIF3LRCLK 10 ++#define ARIZONA_FLL_SRC_SLIMCLK 3 ++#define ARIZONA_FLL_SRC_FLL1 4 ++#define ARIZONA_FLL_SRC_FLL2 5 ++#define ARIZONA_FLL_SRC_AIF1BCLK 8 ++#define ARIZONA_FLL_SRC_AIF2BCLK 9 ++#define ARIZONA_FLL_SRC_AIF3BCLK 10 ++#define ARIZONA_FLL_SRC_AIF1LRCLK 12 ++#define ARIZONA_FLL_SRC_AIF2LRCLK 13 ++#define ARIZONA_FLL_SRC_AIF3LRCLK 14 + + #define ARIZONA_MIXER_VOL_MASK 0x00FE + #define ARIZONA_MIXER_VOL_SHIFT 1 +From 7110a287ff2b1f3780905d1686a1a4edccb95133 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Thu, 20 Dec 2012 23:29:42 +0800 +Subject: ASoC: arizona: Do proper shift for setting AIF rate + +From: Axel Lin + +commit 7110a287ff2b1f3780905d1686a1a4edccb95133 upstream. + +ARIZONA_AIF1_RATE_MASK is 0x7800 /* AIF1_RATE - [14:11] */ +Thus we need left shift ARIZONA_AIF1_RATE_SHIFT when setting aif1 rate. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/sound/soc/codecs/arizona.c ++++ b/sound/soc/codecs/arizona.c +@@ -677,7 +677,8 @@ static int arizona_hw_params(struct snd_ + snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1, + ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val); + snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL, +- ARIZONA_AIF1_RATE_MASK, 8); ++ ARIZONA_AIF1_RATE_MASK, ++ 8 << ARIZONA_AIF1_RATE_SHIFT); + break; + default: + arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk); +From d71753e22b24548911b377db28f80870cf50d07b Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 10:48:02 +0000 +Subject: ASoC: arizona: Remove DSP B and left justified AIF modes + +From: Mark Brown + +commit d71753e22b24548911b377db28f80870cf50d07b upstream. + +These are not supported. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/arizona.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/arizona.c ++++ b/sound/soc/codecs/arizona.c +@@ -409,15 +409,9 @@ static int arizona_set_fmt(struct snd_so + case SND_SOC_DAIFMT_DSP_A: + mode = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- mode = 1; +- break; + case SND_SOC_DAIFMT_I2S: + mode = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- mode = 3; +- break; + default: + arizona_aif_err(dai, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 21:18:12 +0000 +Subject: ASoC: wm2000: Fix sense of speech clarity enable + +From: Mark Brown + +commit 267f8fa2e1eef0612b2007e1f1846bcbc35cc1fa upstream. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2000.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/soc/codecs/wm2000.c ++++ b/sound/soc/codecs/wm2000.c +@@ -209,9 +209,9 @@ static int wm2000_power_up(struct i2c_cl + + ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); + if (wm2000->speech_clarity) +- ret &= ~WM2000_SPEECH_CLARITY; +- else + ret |= WM2000_SPEECH_CLARITY; ++ else ++ ret &= ~WM2000_SPEECH_CLARITY; + wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); + + wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); +From 2a5f431592343b78896013b055582f94c12a5049 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 21 Dec 2012 16:28:37 +0800 +Subject: ASoC: wm2200: Fix setting dai format in wm2200_set_fmt + +From: Axel Lin + +commit 2a5f431592343b78896013b055582f94c12a5049 upstream. + +According to the defines in wm2200.h: +/* + * R1284 (0x504) - Audio IF 1_5 + */ + +We should not left shift 1 bit for fmt_val when setting dai format. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2200.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/soc/codecs/wm2200.c ++++ b/sound/soc/codecs/wm2200.c +@@ -1440,7 +1440,7 @@ static int wm2200_set_fmt(struct snd_soc + WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, + lrclk); + snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, +- WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); ++ WM2200_AIF1_FMT_MASK, fmt_val); + + return 0; + } +From 0cc411b934c4317b363d1af993549f391852b980 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 10:48:10 +0000 +Subject: ASoC: wm2200: Remove DSP B and left justified AIF modes + +From: Mark Brown + +commit 0cc411b934c4317b363d1af993549f391852b980 upstream. + +These are not supported. + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm2200.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/wm2200.c ++++ b/sound/soc/codecs/wm2200.c +@@ -1380,15 +1380,9 @@ static int wm2200_set_fmt(struct snd_soc + case SND_SOC_DAIFMT_DSP_A: + fmt_val = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- fmt_val = 1; +- break; + case SND_SOC_DAIFMT_I2S: + fmt_val = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- fmt_val = 3; +- break; + default: + dev_err(codec->dev, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From ad1937cdd59c412097ec2bb8f38c12a5640f1f9a Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Thu, 20 Dec 2012 16:17:25 +0800 +Subject: ASoC: sta529: Fix update register bits in sta529_set_dai_fmt + +From: Axel Lin + +commit ad1937cdd59c412097ec2bb8f38c12a5640f1f9a upstream. + +Both the mask and mode settings are wrong in current code. + +According to the datasheet: + +S2PCFG0 (0x0A) +BIT[3:1] DATA_FORMAT + serial interface protocol format: + 000: left Justified + 001: I2S (default) + 010: right justified + 100: PCM no delay + 101: PCM delay + 111: DSP + +Thus fixes the defines for LEFT_J_DATA_FORMAT, I2S_DATA_FORMAT, and +RIGHT_J_DATA_FORMAT. +Also adds define for DATA_FORMAT_MSK. + +Signed-off-by: Axel Lin +Acked-by: Rajeev Kumar +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/sta529.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/sound/soc/codecs/sta529.c ++++ b/sound/soc/codecs/sta529.c +@@ -74,9 +74,10 @@ + SNDRV_PCM_FMTBIT_S32_LE) + #define S2PC_VALUE 0x98 + #define CLOCK_OUT 0x60 +-#define LEFT_J_DATA_FORMAT 0x10 +-#define I2S_DATA_FORMAT 0x12 +-#define RIGHT_J_DATA_FORMAT 0x14 ++#define DATA_FORMAT_MSK 0x0E ++#define LEFT_J_DATA_FORMAT 0x00 ++#define I2S_DATA_FORMAT 0x02 ++#define RIGHT_J_DATA_FORMAT 0x04 + #define CODEC_MUTE_VAL 0x80 + + #define POWER_CNTLMSAK 0x40 +@@ -289,7 +290,7 @@ static int sta529_set_dai_fmt(struct snd + return -EINVAL; + } + +- snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode); ++ snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode); + + return 0; + } +From 08b27848da620f206a8b6d80f26184485dd7aa40 Mon Sep 17 00:00:00 2001 +From: Patrick Lai +Date: Wed, 19 Dec 2012 19:36:02 -0800 +Subject: ASoC: pcm: allow backend hardware to be freed in pause state + +From: Patrick Lai + +commit 08b27848da620f206a8b6d80f26184485dd7aa40 upstream. + +When front-end PCM session is in paused state, back-end +PCM session will be put in paused state as well if given +front-end PCM session is the only client of given back-end. +Then, application closes front-end PCM session, DPCM +framework will not allow back-end enters HW_FREE state +so back-end will never get shutdown completely. + +Signed-off-by: Patrick Lai +Acked-by: Liam Girdwood +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/soc-pcm.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/soc-pcm.c ++++ b/sound/soc/soc-pcm.c +@@ -1240,6 +1240,7 @@ static int dpcm_be_dai_hw_free(struct sn + if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && ++ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP)) + continue; + +From 5f960294e2031d12f10c8488c3446fecbf59628d Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Fri, 4 Jan 2013 21:06:08 +0000 +Subject: ASoC: wm5100: Remove DSP B and left justified formats + +From: Mark Brown + +commit 5f960294e2031d12f10c8488c3446fecbf59628d upstream. + +These are not supported + +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/soc/codecs/wm5100.c | 6 ------ + 1 file changed, 6 deletions(-) + +--- a/sound/soc/codecs/wm5100.c ++++ b/sound/soc/codecs/wm5100.c +@@ -1279,15 +1279,9 @@ static int wm5100_set_fmt(struct snd_soc + case SND_SOC_DAIFMT_DSP_A: + mask = 0; + break; +- case SND_SOC_DAIFMT_DSP_B: +- mask = 1; +- break; + case SND_SOC_DAIFMT_I2S: + mask = 2; + break; +- case SND_SOC_DAIFMT_LEFT_J: +- mask = 3; +- break; + default: + dev_err(codec->dev, "Unsupported DAI format %d\n", + fmt & SND_SOC_DAIFMT_FORMAT_MASK); +From c930812fe5ebe725760422c9c351d1f6fde1502d Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:56 +0100 +Subject: udldrmfb: Fix EDID not working with monitors with EDID + extension blocks + +From: Hans de Goede + +commit c930812fe5ebe725760422c9c351d1f6fde1502d upstream. + +udldrmfb only reads the main EDID block, and if that advertises extensions +the drm_edid code expects them to be present, and starts reading beyond the +buffer udldrmfb passes it. + +Although it may be possible to read more EDID info with the udl we simpy don't +know how, and even if trial and error gets it working on one device, that is +no guarantee it will work on other revisions. So this patch does a simple fix +in the form of patching the EDID info to report 0 extension blocks, this +fixes udldrmfb only doing 1024x768 on monitors with EDID extension blocks. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -57,6 +57,14 @@ static int udl_get_modes(struct drm_conn + + edid = (struct edid *)udl_get_edid(udl); + ++ /* ++ * We only read the main block, but if the monitor reports extension ++ * blocks then the drm edid code expects them to be present, so patch ++ * the extension count to 0. ++ */ ++ edid->checksum += edid->extensions; ++ edid->extensions = 0; ++ + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); +From 242187b362555849e8c971dfbbfd55f8bd9fa717 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:57 +0100 +Subject: udldrmfb: udl_get_edid: usb_control_msg buffer must not be on the stack + +From: Hans de Goede + +commit 242187b362555849e8c971dfbbfd55f8bd9fa717 upstream. + +The buffer passed to usb_control_msg may end up in scatter-gather list, and +may thus not be on the stack. Having it on the stack usually works on x86, but +not on other archs. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -22,13 +22,17 @@ + static u8 *udl_get_edid(struct udl_device *udl) + { + u8 *block; +- char rbuf[3]; ++ char *rbuf; + int ret, i; + + block = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (block == NULL) + return NULL; + ++ rbuf = kmalloc(2, GFP_KERNEL); ++ if (rbuf == NULL) ++ goto error; ++ + for (i = 0; i < EDID_LENGTH; i++) { + ret = usb_control_msg(udl->ddev->usbdev, + usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), +@@ -42,10 +46,12 @@ static u8 *udl_get_edid(struct udl_devic + block[i] = rbuf[1]; + } + ++ kfree(rbuf); + return block; + + error: + kfree(block); ++ kfree(rbuf); + return NULL; + } + +From 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Fri, 11 Jan 2013 12:08:58 +0100 +Subject: udldrmfb: udl_get_edid: drop unneeded i-- + +From: Hans de Goede + +commit 7b4cf994e4c6ba48872bb25253cc393b7fb74c82 upstream. + +This is a left-over from when udl_get_edid returned the amount of bytes +successfully read, which it no longer does. + +Signed-off-by: Hans de Goede +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_connector.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/gpu/drm/udl/udl_connector.c ++++ b/drivers/gpu/drm/udl/udl_connector.c +@@ -40,7 +40,6 @@ static u8 *udl_get_edid(struct udl_devic + HZ); + if (ret < 1) { + DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); +- i--; + goto error; + } + block[i] = rbuf[1]; +From 6d283dba3721cc43be014b50a1acc2f35860a65a Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 14 Jan 2013 13:17:50 -0800 +Subject: vfs: add missing virtual cache flush after editing partial pages + +From: Linus Torvalds + +commit 6d283dba3721cc43be014b50a1acc2f35860a65a upstream. + +Andrew Morton pointed this out a month ago, and then I completely forgot +about it. + +If we read a partial last page of a block device, we will zero out the +end of the page, but since that page can then be mapped into user space, +we should also make sure to flush the cache on architectures that have +virtual caches. We have the flush_dcache_page() function for this, so +use it. + +Now, in practice this really never matters, because nobody sane uses +virtual caches to begin with, and they largely exist on old broken RISC +arhitectures. + +And even if you did run on one of those obsolete CPU's, the whole "mmap +and access the last partial page of a block device" behavior probably +doesn't actually exist. The normal IO functions (read/write) will never +see the zeroed-out part of the page that migth not be coherent in the +cache, because they honor the size of the device. + +So I'm marking this for stable (3.7 only), but I'm not sure anybody will +ever care. + +Pointed-out-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/buffer.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2939,6 +2939,7 @@ static void guard_bh_eod(int rw, struct + void *kaddr = kmap_atomic(bh->b_page); + memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); + kunmap_atomic(kaddr); ++ flush_dcache_page(bh->b_page); + } + } + +From 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 Mon Sep 17 00:00:00 2001 +From: David Henningsson +Date: Wed, 19 Dec 2012 09:44:47 +0100 +Subject: Revert "ALSA: hda - Shut up pins at power-saving mode with Conexnat codecs" + +From: David Henningsson + +commit 7ed4165e2d01bdbbb4c1086eb73eadf0f64cbbf0 upstream. + +This reverts commit 697c373e34613609cb5450f98b91fefb6e910588. + +The original patch was meant to remove clicking, but in fact caused even +more clicking instead. + +Thanks to c4pp4 for doing most of the work with this bug. + +BugLink: https://bugs.launchpad.net/bugs/886975 +Signed-off-by: David Henningsson +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/patch_conexant.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +--- a/sound/pci/hda/patch_conexant.c ++++ b/sound/pci/hda/patch_conexant.c +@@ -553,24 +553,12 @@ static int conexant_build_controls(struc + return 0; + } + +-#ifdef CONFIG_PM +-static int conexant_suspend(struct hda_codec *codec) +-{ +- snd_hda_shutup_pins(codec); +- return 0; +-} +-#endif +- + static const struct hda_codec_ops conexant_patch_ops = { + .build_controls = conexant_build_controls, + .build_pcms = conexant_build_pcms, + .init = conexant_init, + .free = conexant_free, + .set_power_state = conexant_set_power, +-#ifdef CONFIG_PM +- .suspend = conexant_suspend, +-#endif +- .reboot_notify = snd_hda_shutup_pins, + }; + + #ifdef CONFIG_SND_HDA_INPUT_BEEP +@@ -4393,10 +4381,6 @@ static const struct hda_codec_ops cx_aut + .init = cx_auto_init, + .free = conexant_free, + .unsol_event = snd_hda_jack_unsol_event, +-#ifdef CONFIG_PM +- .suspend = conexant_suspend, +-#endif +- .reboot_notify = snd_hda_shutup_pins, + }; + + /* +From d7dab4dbbb2d1b0c903378d6bade2e4ae161804e Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Tue, 8 Jan 2013 13:51:30 +0100 +Subject: ALSA: hda - Disable runtime D3 for Intel CPT & co + +From: Takashi Iwai + +commit d7dab4dbbb2d1b0c903378d6bade2e4ae161804e upstream. + +We've got a few bug reports that the runtime D3 results in the dead +HD-audio controller. It seems that the problem is in a deeper level +than the sound driver itself, so as a temporal solution, disable the +feature for these controllers again. + +Reported-and-tested-by: Vincent Blut +Reported-and-tested-by: Maurizio Avogadro +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/pci/hda/hda_intel.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -559,9 +559,12 @@ enum { + #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ + + /* quirks for Intel PCH */ +-#define AZX_DCAPS_INTEL_PCH \ ++#define AZX_DCAPS_INTEL_PCH_NOPM \ + (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \ +- AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME) ++ AZX_DCAPS_COUNT_LPIB_DELAY) ++ ++#define AZX_DCAPS_INTEL_PCH \ ++ (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME) + + /* quirks for ATI SB / AMD Hudson */ + #define AZX_DCAPS_PRESET_ATI_SB \ +@@ -3448,13 +3451,13 @@ static void __devexit azx_remove(struct + static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { + /* CPT */ + { PCI_DEVICE(0x8086, 0x1c20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* PBG */ + { PCI_DEVICE(0x8086, 0x1d20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Panther Point */ + { PCI_DEVICE(0x8086, 0x1e20), +- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, ++ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, + /* Lynx Point */ + { PCI_DEVICE(0x8086, 0x8c20), + .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, +From 41b645c8624df6ace020a8863ad1449d69140f7d Mon Sep 17 00:00:00 2001 +From: Mike Dunn +Date: Mon, 7 Jan 2013 13:55:12 -0800 +Subject: ALSA: pxa27x: fix ac97 cold reset + +From: Mike Dunn + +commit 41b645c8624df6ace020a8863ad1449d69140f7d upstream. + +Cold reset on the pxa27x currently fails and + + pxa2xx_ac97_try_cold_reset: cold reset timeout (GSR=0x44) + +appears in the kernel log. Through trial-and-error (the pxa270 developer's +manual is mostly incoherent on the topic of ac97 reset), I got cold reset to +complete by setting the WARM_RST bit in the GCR register (and later noticed that +pxa3xx does this for cold reset as well). Also, a timeout loop is needed to +wait for the reset to complete. + +Tested on a palm treo 680 machine. + +Signed-off-by: Mike Dunn +Acked-by: Igor Grinberg +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + sound/arm/pxa2xx-ac97-lib.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/sound/arm/pxa2xx-ac97-lib.c ++++ b/sound/arm/pxa2xx-ac97-lib.c +@@ -148,6 +148,8 @@ static inline void pxa_ac97_warm_pxa27x( + + static inline void pxa_ac97_cold_pxa27x(void) + { ++ unsigned int timeout; ++ + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ + GCR &= ~GCR_COLD_RST; /* then assert nCRST */ + +@@ -157,8 +159,10 @@ static inline void pxa_ac97_cold_pxa27x( + clk_enable(ac97conf_clk); + udelay(5); + clk_disable(ac97conf_clk); +- GCR = GCR_COLD_RST; +- udelay(50); ++ GCR = GCR_COLD_RST | GCR_WARM_RST; ++ timeout = 100; /* wait for the codec-ready bit to be set */ ++ while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) ++ mdelay(1); + } + #endif + +From 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd Mon Sep 17 00:00:00 2001 +From: Mike Dunn +Date: Mon, 7 Jan 2013 13:55:13 -0800 +Subject: ALSA: pxa27x: fix ac97 warm reset + +From: Mike Dunn + +commit 3b4bc7bccc7857274705b05cf81a0c72cfd0b0dd upstream. + +This patch fixes some code that implements a work-around to a hardware bug in +the ac97 controller on the pxa27x. A bug in the controller's warm reset +functionality requires that the mfp used by the controller as the AC97_nRESET +line be temporarily reconfigured as a generic output gpio (AF0) and manually +held high for the duration of the warm reset cycle. This is what was done in +the original code, but it was broken long ago by commit fb1bf8cd + ([ARM] pxa: introduce processor specific pxa27x_assert_ac97reset()) +which changed the mfp to a GPIO input instead of a high output. + +The fix requires the ac97 controller to obtain the gpio via gpio_request_one(), +with arguments that configure the gpio as an output initially driven high. + +Tested on a palm treo 680 machine. Reportedly, this broken code only prevents a +warm reset on hardware that lacks a pull-up on the line, which appears to be the +case for me. + +Signed-off-by: Mike Dunn +Signed-off-by: Igor Grinberg +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 +++ + arch/arm/mach-pxa/pxa27x.c | 4 ++-- + sound/arm/pxa2xx-ac97-lib.c | 18 +++++++++++++++++- + 3 files changed, 22 insertions(+), 3 deletions(-) + +--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h ++++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +@@ -463,6 +463,9 @@ + GPIO76_LCD_PCLK, \ + GPIO77_LCD_BIAS + ++/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ ++#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) ++#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) + + extern int keypad_set_wake(unsigned int on); + #endif /* __ASM_ARCH_MFP_PXA27X_H */ +--- a/arch/arm/mach-pxa/pxa27x.c ++++ b/arch/arm/mach-pxa/pxa27x.c +@@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) + EXPORT_SYMBOL(pxa27x_clear_otgph); + + static unsigned long ac97_reset_config[] = { +- GPIO113_GPIO, ++ GPIO113_AC97_nRESET_GPIO_HIGH, + GPIO113_AC97_nRESET, +- GPIO95_GPIO, ++ GPIO95_AC97_nRESET_GPIO_HIGH, + GPIO95_AC97_nRESET, + }; + +--- a/sound/arm/pxa2xx-ac97-lib.c ++++ b/sound/arm/pxa2xx-ac97-lib.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -344,8 +345,21 @@ int __devinit pxa2xx_ac97_hw_probe(struc + } + + if (cpu_is_pxa27x()) { +- /* Use GPIO 113 as AC97 Reset on Bulverde */ ++ /* ++ * This gpio is needed for a work-around to a bug in the ac97 ++ * controller during warm reset. The direction and level is set ++ * here so that it is an output driven high when switching from ++ * AC97_nRESET alt function to generic gpio. ++ */ ++ ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, ++ "pxa27x ac97 reset"); ++ if (ret < 0) { ++ pr_err("%s: gpio_request_one() failed: %d\n", ++ __func__, ret); ++ goto err_conf; ++ } + pxa27x_assert_ac97reset(reset_gpio, 0); ++ + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); + if (IS_ERR(ac97conf_clk)) { + ret = PTR_ERR(ac97conf_clk); +@@ -388,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); + + void pxa2xx_ac97_hw_remove(struct platform_device *dev) + { ++ if (cpu_is_pxa27x()) ++ gpio_free(reset_gpio); + GCR |= GCR_ACLINK_OFF; + free_irq(IRQ_AC97, NULL); + if (ac97conf_clk) { +From 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Tue, 4 Dec 2012 15:59:55 +0000 +Subject: staging: comedi: prevent auto-unconfig of manually configured devices + +From: Ian Abbott + +commit 7d3135af399e92cf4c9bbc5f86b6c140aab3b88c upstream. + +When a low-level comedi driver auto-configures a device, a `struct +comedi_dev_file_info` is allocated (as well as a `struct +comedi_device`) by `comedi_alloc_board_minor()`. A pointer to the +hardware `struct device` is stored as a cookie in the `struct +comedi_dev_file_info`. When the low-level comedi driver +auto-unconfigures the device, `comedi_auto_unconfig()` uses the cookie +to find the `struct comedi_dev_file_info` so it can detach the comedi +device from the driver, clean it up and free it. + +A problem arises if the user manually unconfigures and reconfigures the +comedi device using the `COMEDI_DEVCONFIG` ioctl so that is no longer +associated with the original hardware device. The problem is that the +cookie is not cleared, so that a call to `comedi_auto_unconfig()` from +the low-level driver will still find it, detach it, clean it up and free +it. + +Stop this problem occurring by always clearing the `hardware_device` +cookie in the `struct comedi_dev_file_info` whenever the +`COMEDI_DEVCONFIG` ioctl call is successful. + +Signed-off-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/comedi_fops.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/staging/comedi/comedi_fops.c ++++ b/drivers/staging/comedi/comedi_fops.c +@@ -1546,6 +1546,9 @@ static long comedi_unlocked_ioctl(struct + if (cmd == COMEDI_DEVCONFIG) { + rc = do_devconfig_ioctl(dev, + (struct comedi_devconfig __user *)arg); ++ if (rc == 0) ++ /* Evade comedi_auto_unconfig(). */ ++ dev_file_info->hardware_device = NULL; + goto done; + } + +From 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 Mon Sep 17 00:00:00 2001 +From: Éric Piel +Date: Wed, 19 Dec 2012 13:03:13 +0100 +Subject: staging: comedi: fix minimum AO period for NI 625x and NI 628x + +From: Éric Piel + +commit 34b55d8c48f4f76044d8f4d6ec3dc786cf210312 upstream. + +The minimum period was set to 357 ns, while the divider for these boards is 50 +ns. This prevented to output at maximum speed as ni_ao_cmdtest() would return +357 but would not accept it. + +Not sure why it was set to 357 ns (this was done before the git history, +which starts 5 years ago). My guess is that it comes from reading the +specification stating a 2.8 MHz rate (~ 357 ns). The latest +specification states a 2.86 MHz rate (~ 350 ns), which makes a lot +more sense. + +Tested on a pci-6251. + +Signed-off-by: Éric Piel +Acked-By: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/ni_pcimio.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/staging/comedi/drivers/ni_pcimio.c ++++ b/drivers/staging/comedi/drivers/ni_pcimio.c +@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_625x_ao, + .reg_type = ni_reg_625x, + .ao_unipolar = 0, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 8, + .caldac = {caldac_none}, + .has_8255 = 0, +@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_b + .ao_range_table = &range_ni_M_628x_ao, + .reg_type = ni_reg_628x, + .ao_unipolar = 1, +- .ao_speed = 357, ++ .ao_speed = 350, + .num_p0_dio_channels = 32, + .caldac = {caldac_none}, + .has_8255 = 0, +From 34ffb33e09132401872fe79e95c30824ce194d23 Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Thu, 3 Jan 2013 12:15:26 +0000 +Subject: staging: comedi: Kconfig: COMEDI_NI_AT_A2150 should select COMEDI_FC + +From: Ian Abbott + +commit 34ffb33e09132401872fe79e95c30824ce194d23 upstream. + +The 'ni_at_a2150' module links to `cfc_write_to_buffer` in the +'comedi_fc' module, so selecting 'COMEDI_NI_AT_A2150' in the kernel config +needs to also select 'COMEDI_FC'. + +Signed-off-by: Ian Abbott +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/staging/comedi/Kconfig ++++ b/drivers/staging/comedi/Kconfig +@@ -444,6 +444,7 @@ config COMEDI_ADQ12B + + config COMEDI_NI_AT_A2150 + tristate "NI AT-A2150 ISA card support" ++ select COMEDI_FC + depends on VIRT_TO_BUS + ---help--- + Enable support for National Instruments AT-A2150 cards +From c0729eeefdcd76db338f635162bf0739fd2c5f6f Mon Sep 17 00:00:00 2001 +From: Ian Abbott +Date: Fri, 4 Jan 2013 11:33:21 +0000 +Subject: staging: comedi: comedi_test: fix race when cancelling command + +From: Ian Abbott + +commit c0729eeefdcd76db338f635162bf0739fd2c5f6f upstream. + +Éric Piel reported a kernel oops in the "comedi_test" module. It was a +NULL pointer dereference within `waveform_ai_interrupt()` (actually a +timer function) that sometimes occurred when a running asynchronous +command is cancelled (either by the `COMEDI_CANCEL` ioctl or by closing +the device file). + +This seems to be a race between the caller of `waveform_ai_cancel()` +which on return from that function goes and tears down the running +command, and the timer function which uses the command. In particular, +`async->cmd.chanlist` gets freed (and the pointer set to NULL) by +`do_become_nonbusy()` in "comedi_fops.c" but a previously scheduled +`waveform_ai_interrupt()` timer function will dereference that pointer +regardless, leading to the oops. + +Fix it by replacing the `del_timer()` call in `waveform_ai_cancel()` +with `del_timer_sync()`. + +Signed-off-by: Ian Abbott +Reported-by: Éric Piel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/comedi/drivers/comedi_test.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/comedi/drivers/comedi_test.c ++++ b/drivers/staging/comedi/drivers/comedi_test.c +@@ -372,7 +372,7 @@ static int waveform_ai_cancel(struct com + struct waveform_private *devpriv = dev->private; + + devpriv->timer_running = 0; +- del_timer(&devpriv->timer); ++ del_timer_sync(&devpriv->timer); + return 0; + } + +From da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sat, 29 Dec 2012 11:36:53 -0600 +Subject: staging: r8712u: Add new device ID + +From: Larry Finger + +commit da849a92d3bafaf24d770e971c2c9e5c3f60b5d1 upstream. + +The ISY IWL 1000 USB WLAN stick with USB ID 050d:11f1 is a clone of +the Belkin F7D1101 V1 device. + +Reported-by: Thomas Hartmann +Signed-off-by: Larry Finger +Cc: Thomas Hartmann +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/rtl8712/usb_intf.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/staging/rtl8712/usb_intf.c ++++ b/drivers/staging/rtl8712/usb_intf.c +@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_ + {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ + /* Belkin */ + {USB_DEVICE(0x050D, 0x945A)}, ++ /* ISY IWL - Belkin clone */ ++ {USB_DEVICE(0x050D, 0x11F1)}, + /* Corega */ + {USB_DEVICE(0x07AA, 0x0047)}, + /* D-Link */ +From ae428655b826f2755a8101b27beda42a275ef8ad Mon Sep 17 00:00:00 2001 +From: Nickolai Zeldovich +Date: Sat, 5 Jan 2013 14:17:45 -0500 +Subject: staging: speakup: avoid out-of-range access in synth_init() + +From: Nickolai Zeldovich + +commit ae428655b826f2755a8101b27beda42a275ef8ad upstream. + +Check that array index is in-bounds before accessing the synths[] array. + +Signed-off-by: Nickolai Zeldovich +Cc: Samuel Thibault +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/speakup/synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/speakup/synth.c ++++ b/drivers/staging/speakup/synth.c +@@ -342,7 +342,7 @@ int synth_init(char *synth_name) + + mutex_lock(&spk_mutex); + /* First, check if we already have it loaded. */ +- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) ++ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + if (strcmp(synths[i]->name, synth_name) == 0) + synth = synths[i]; + +From 6102c48bd421074a33e102f2ebda3724e8d275f9 Mon Sep 17 00:00:00 2001 +From: Samuel Thibault +Date: Mon, 7 Jan 2013 22:03:51 +0100 +Subject: staging: speakup: avoid out-of-range access in synth_add() + +From: Samuel Thibault + +commit 6102c48bd421074a33e102f2ebda3724e8d275f9 upstream. + +Check that array index is in-bounds before accessing the synths[] array. + +Signed-off-by: Samuel Thibault +Cc: Nickolai Zeldovich +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/speakup/synth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/speakup/synth.c ++++ b/drivers/staging/speakup/synth.c +@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth + int i; + int status = 0; + mutex_lock(&spk_mutex); +- for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) ++ for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) + /* synth_remove() is responsible for rotating the array down */ + if (in_synth == synths[i]) { + mutex_unlock(&spk_mutex); +From 37b51fdddf64e7ba0971d070428655f8d6f36578 Mon Sep 17 00:00:00 2001 +From: Sergey Senozhatsky +Date: Tue, 30 Oct 2012 22:40:23 +0300 +Subject: staging: zram: factor-out zram_decompress_page() function + +From: Sergey Senozhatsky + +commit 37b51fdddf64e7ba0971d070428655f8d6f36578 upstream. + +zram_bvec_read() shared decompress functionality with zram_read_before_write() function. +Factor-out and make commonly used zram_decompress_page() function, which also simplified +error handling in zram_bvec_read(). + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Nitin Gupta +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/zram/zram_drv.c | 113 ++++++++++++++++------------------------ + 1 file changed, 48 insertions(+), 65 deletions(-) + +--- a/drivers/staging/zram/zram_drv.c ++++ b/drivers/staging/zram/zram_drv.c +@@ -183,62 +183,25 @@ static inline int is_partial_io(struct b + return bvec->bv_len != PAGE_SIZE; + } + +-static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, +- u32 index, int offset, struct bio *bio) ++static int zram_decompress_page(struct zram *zram, char *mem, u32 index) + { +- int ret; +- size_t clen; +- struct page *page; +- unsigned char *user_mem, *cmem, *uncmem = NULL; +- +- page = bvec->bv_page; +- +- if (zram_test_flag(zram, index, ZRAM_ZERO)) { +- handle_zero_page(bvec); +- return 0; +- } ++ int ret = LZO_E_OK; ++ size_t clen = PAGE_SIZE; ++ unsigned char *cmem; ++ unsigned long handle = zram->table[index].handle; + +- /* Requested page is not present in compressed area */ +- if (unlikely(!zram->table[index].handle)) { +- pr_debug("Read before write: sector=%lu, size=%u", +- (ulong)(bio->bi_sector), bio->bi_size); +- handle_zero_page(bvec); ++ if (!handle || zram_test_flag(zram, index, ZRAM_ZERO)) { ++ memset(mem, 0, PAGE_SIZE); + return 0; + } + +- if (is_partial_io(bvec)) { +- /* Use a temporary buffer to decompress the page */ +- uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); +- if (!uncmem) { +- pr_info("Error allocating temp memory!\n"); +- return -ENOMEM; +- } +- } +- +- user_mem = kmap_atomic(page); +- if (!is_partial_io(bvec)) +- uncmem = user_mem; +- clen = PAGE_SIZE; +- +- cmem = zs_map_object(zram->mem_pool, zram->table[index].handle, +- ZS_MM_RO); +- +- if (zram->table[index].size == PAGE_SIZE) { +- memcpy(uncmem, cmem, PAGE_SIZE); +- ret = LZO_E_OK; +- } else { ++ cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); ++ if (zram->table[index].size == PAGE_SIZE) ++ memcpy(mem, cmem, PAGE_SIZE); ++ else + ret = lzo1x_decompress_safe(cmem, zram->table[index].size, +- uncmem, &clen); +- } +- +- if (is_partial_io(bvec)) { +- memcpy(user_mem + bvec->bv_offset, uncmem + offset, +- bvec->bv_len); +- kfree(uncmem); +- } +- +- zs_unmap_object(zram->mem_pool, zram->table[index].handle); +- kunmap_atomic(user_mem); ++ mem, &clen); ++ zs_unmap_object(zram->mem_pool, handle); + + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { +@@ -247,36 +210,56 @@ static int zram_bvec_read(struct zram *z + return ret; + } + +- flush_dcache_page(page); +- + return 0; + } + +-static int zram_read_before_write(struct zram *zram, char *mem, u32 index) ++static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, ++ u32 index, int offset, struct bio *bio) + { + int ret; +- size_t clen = PAGE_SIZE; +- unsigned char *cmem; +- unsigned long handle = zram->table[index].handle; ++ struct page *page; ++ unsigned char *user_mem, *uncmem = NULL; + +- if (zram_test_flag(zram, index, ZRAM_ZERO) || !handle) { +- memset(mem, 0, PAGE_SIZE); ++ page = bvec->bv_page; ++ ++ if (unlikely(!zram->table[index].handle) || ++ zram_test_flag(zram, index, ZRAM_ZERO)) { ++ handle_zero_page(bvec); + return 0; + } + +- cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); +- ret = lzo1x_decompress_safe(cmem, zram->table[index].size, +- mem, &clen); +- zs_unmap_object(zram->mem_pool, handle); ++ user_mem = kmap_atomic(page); ++ if (is_partial_io(bvec)) ++ /* Use a temporary buffer to decompress the page */ ++ uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ else ++ uncmem = user_mem; ++ ++ if (!uncmem) { ++ pr_info("Unable to allocate temp memory\n"); ++ ret = -ENOMEM; ++ goto out_cleanup; ++ } + ++ ret = zram_decompress_page(zram, uncmem, index); + /* Should NEVER happen. Return bio error if it does. */ + if (unlikely(ret != LZO_E_OK)) { + pr_err("Decompression failed! err=%d, page=%u\n", ret, index); + zram_stat64_inc(zram, &zram->stats.failed_reads); +- return ret; ++ goto out_cleanup; + } + +- return 0; ++ if (is_partial_io(bvec)) ++ memcpy(user_mem + bvec->bv_offset, uncmem + offset, ++ bvec->bv_len); ++ ++ flush_dcache_page(page); ++ ret = 0; ++out_cleanup: ++ kunmap_atomic(user_mem); ++ if (is_partial_io(bvec)) ++ kfree(uncmem); ++ return ret; + } + + static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, +@@ -302,7 +285,7 @@ static int zram_bvec_write(struct zram * + ret = -ENOMEM; + goto out; + } +- ret = zram_read_before_write(zram, uncmem, index); ++ ret = zram_decompress_page(zram, uncmem, index); + if (ret) { + kfree(uncmem); + goto out; +From 397c60668aa5ae7130b5ad4e73870d7b8a787085 Mon Sep 17 00:00:00 2001 +From: Nitin Gupta +Date: Wed, 2 Jan 2013 08:53:41 -0800 +Subject: staging: zram: fix invalid memory references during disk write + +From: Nitin Gupta + +commit 397c60668aa5ae7130b5ad4e73870d7b8a787085 upstream. + +Fixes a bug introduced by commit c8f2f0db1 ("zram: Fix handling +of incompressible pages") which caused invalid memory references +during disk write. Invalid references could occur in two cases: + - Incoming data expands on compression: In this case, reference was +made to kunmap()'ed bio page. + - Partial (non PAGE_SIZE) write with incompressible data: In this +case, reference was made to a kfree()'ed buffer. + +Fixes bug 50081: +https://bugzilla.kernel.org/show_bug.cgi?id=50081 + +Signed-off-by: Nitin Gupta +Reported-by: Mihail Kasadjikov +Reported-by: Tomas M +Reviewed-by: Minchan Kim +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/staging/zram/zram_drv.c | 39 ++++++++++++++++++++++++--------------- + 1 file changed, 24 insertions(+), 15 deletions(-) + +--- a/drivers/staging/zram/zram_drv.c ++++ b/drivers/staging/zram/zram_drv.c +@@ -265,7 +265,7 @@ out_cleanup: + static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, + int offset) + { +- int ret; ++ int ret = 0; + size_t clen; + unsigned long handle; + struct page *page; +@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram * + goto out; + } + ret = zram_decompress_page(zram, uncmem, index); +- if (ret) { +- kfree(uncmem); ++ if (ret) + goto out; +- } + } + + /* +@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram * + + user_mem = kmap_atomic(page); + +- if (is_partial_io(bvec)) ++ if (is_partial_io(bvec)) { + memcpy(uncmem + offset, user_mem + bvec->bv_offset, + bvec->bv_len); +- else ++ kunmap_atomic(user_mem); ++ user_mem = NULL; ++ } else { + uncmem = user_mem; ++ } + + if (page_zero_filled(uncmem)) { +- kunmap_atomic(user_mem); +- if (is_partial_io(bvec)) +- kfree(uncmem); ++ if (!is_partial_io(bvec)) ++ kunmap_atomic(user_mem); + zram_stat_inc(&zram->stats.pages_zero); + zram_set_flag(zram, index, ZRAM_ZERO); + ret = 0; +@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram * + ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, + zram->compress_workmem); + +- kunmap_atomic(user_mem); +- if (is_partial_io(bvec)) +- kfree(uncmem); ++ if (!is_partial_io(bvec)) { ++ kunmap_atomic(user_mem); ++ user_mem = NULL; ++ uncmem = NULL; ++ } + + if (unlikely(ret != LZO_E_OK)) { + pr_err("Compression failed! err=%d\n", ret); +@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram * + + if (unlikely(clen > max_zpage_size)) { + zram_stat_inc(&zram->stats.bad_compress); +- src = uncmem; + clen = PAGE_SIZE; ++ src = NULL; ++ if (is_partial_io(bvec)) ++ src = uncmem; + } + + handle = zs_malloc(zram->mem_pool, clen); +@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram * + } + cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); + ++ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) ++ src = kmap_atomic(page); + memcpy(cmem, src, clen); ++ if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) ++ kunmap_atomic(src); + + zs_unmap_object(zram->mem_pool, handle); + +@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram * + if (clen <= PAGE_SIZE / 2) + zram_stat_inc(&zram->stats.good_compress); + +- return 0; +- + out: ++ if (is_partial_io(bvec)) ++ kfree(uncmem); ++ + if (ret) + zram_stat64_inc(zram, &zram->stats.failed_writes); + return ret; +From 51861d4eebc2ddc25c77084343d060fa79f6e291 Mon Sep 17 00:00:00 2001 +From: Jerome Glisse +Date: Tue, 8 Jan 2013 18:41:01 -0500 +Subject: radeon/kms: force rn50 chip to always report connected on analog output + +From: Jerome Glisse + +commit 51861d4eebc2ddc25c77084343d060fa79f6e291 upstream. + +Those rn50 chip are often connected to console remoting hw and load +detection often fails with those. Just don't try to load detect and +report connect. + +Signed-off-by: Jerome Glisse +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c ++++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_ + enum drm_connector_status found = connector_status_disconnected; + bool color = true; + ++ /* just don't bother on RN50 those chip are often connected to remoting ++ * console hw and often we get failure to load detect those. So to make ++ * everyone happy report the encoder as always connected. ++ */ ++ if (ASIC_IS_RN50(rdev)) { ++ return connector_status_connected; ++ } ++ + /* save the regs we need */ + vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); +From 392d4cad7907f6cb4ffc85e135a01abfddc89027 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 27 Dec 2012 21:37:04 +0100 +Subject: iwlwifi: fix PCIe interrupt handle return value + +From: Johannes Berg + +commit 392d4cad7907f6cb4ffc85e135a01abfddc89027 upstream. + +By accident, commit eb6476441bc2fecf6232a87d0313a85f8e3da7f4 +("iwlwifi: protect use_ict with irq_lock") changed the return +value of the iwl_pcie_isr() function in case it handles an +interrupt -- it now returns IRQ_NONE instead of IRQ_HANDLED. + +Put back the correct return value. + +Reviewed-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/pcie/rx.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/iwlwifi/pcie/rx.c ++++ b/drivers/net/wireless/iwlwifi/pcie/rx.c +@@ -971,6 +971,7 @@ static irqreturn_t iwl_isr(int irq, void + else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && + !trans_pcie->inta) + iwl_enable_interrupts(trans); ++ return IRQ_HANDLED; + + none: + /* re-enable interrupts here since we don't have anything to service. */ +From f590dcec944552f9a4a61155810f3abd17d6465d Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Mon, 31 Dec 2012 09:26:10 +0200 +Subject: iwlwifi: fix the reclaimed packet tracking upon flush queue + +From: Emmanuel Grumbach + +commit f590dcec944552f9a4a61155810f3abd17d6465d upstream. + +There's a bug in the currently released firmware version, +the sequence control in the Tx response isn't updated in +all cases. Take it from the packet as a workaround. + +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/dvm/tx.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/dvm/tx.c ++++ b/drivers/net/wireless/iwlwifi/dvm/tx.c +@@ -1154,13 +1154,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + next_reclaimed = ssn; + } + +- if (tid != IWL_TID_NON_QOS) { +- priv->tid_data[sta_id][tid].next_reclaimed = +- next_reclaimed; +- IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", +- next_reclaimed); +- } +- + iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); + + iwlagn_check_ratid_empty(priv, sta_id, tid); +@@ -1211,11 +1204,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv * + if (!is_agg) + iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); + ++ /* ++ * W/A for FW bug - the seq_ctl isn't updated when the ++ * queues are flushed. Fetch it from the packet itself ++ */ ++ if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { ++ next_reclaimed = le16_to_cpu(hdr->seq_ctrl); ++ next_reclaimed = ++ SEQ_TO_SN(next_reclaimed + 0x10); ++ } ++ + is_offchannel_skb = + (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); + freed++; + } + ++ if (tid != IWL_TID_NON_QOS) { ++ priv->tid_data[sta_id][tid].next_reclaimed = ++ next_reclaimed; ++ IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", ++ next_reclaimed); ++ } ++ + WARN_ON(!is_agg && freed != 1); + + /* +From 34bcf71502413f8903ade93746f2d0f04b937a78 Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Tue, 11 Dec 2012 10:48:23 +0100 +Subject: mac80211: fix ibss scanning + +From: Stanislaw Gruszka + +commit 34bcf71502413f8903ade93746f2d0f04b937a78 upstream. + +Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this +can trigger Microcode errors on iwlwifi and iwlegacy drivers. + +Also rename ieee80211_request_internal_scan() function since it is only +used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). + +This patch should address: +https://bugzilla.redhat.com/show_bug.cgi?id=883414 +https://bugzilla.kernel.org/show_bug.cgi?id=49411 + +Reported-by: Jesse Kahtava +Reported-by: Mikko Rapeli +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/ibss.c | 9 ++++----- + net/mac80211/ieee80211_i.h | 6 +++--- + net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- + 3 files changed, 31 insertions(+), 18 deletions(-) + +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(str + sdata_info(sdata, + "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, ++ NULL); + } + + static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) +@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(stru + IEEE80211_SCAN_INTERVAL)) { + sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); + +- ieee80211_request_internal_scan(sdata, +- ifibss->ssid, ifibss->ssid_len, +- ifibss->fixed_channel ? ifibss->channel : NULL); ++ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ++ ifibss->ssid_len, chan); + } else { + int interval = IEEE80211_SCAN_INTERVAL; + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struc + + /* scan/BSS handling */ + void ieee80211_scan_work(struct work_struct *work); +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan); ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan); + int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, + struct cfg80211_scan_request *req); + void ieee80211_scan_cancel(struct ieee80211_local *local); +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80 + return res; + } + +-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, +- const u8 *ssid, u8 ssid_len, +- struct ieee80211_channel *chan) ++int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, ++ const u8 *ssid, u8 ssid_len, ++ struct ieee80211_channel *chan) + { + struct ieee80211_local *local = sdata->local; + int ret = -EBUSY; +@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(stru + + /* fill internal scan request */ + if (!chan) { +- int i, nchan = 0; ++ int i, max_n; ++ int n_ch = 0; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (!local->hw.wiphy->bands[band]) + continue; +- for (i = 0; +- i < local->hw.wiphy->bands[band]->n_channels; +- i++) { +- local->int_scan_req->channels[nchan] = ++ ++ max_n = local->hw.wiphy->bands[band]->n_channels; ++ for (i = 0; i < max_n; i++) { ++ struct ieee80211_channel *tmp_ch = + &local->hw.wiphy->bands[band]->channels[i]; +- nchan++; ++ ++ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED)) ++ continue; ++ ++ local->int_scan_req->channels[n_ch] = tmp_ch; ++ n_ch++; + } + } + +- local->int_scan_req->n_channels = nchan; ++ if (WARN_ON_ONCE(n_ch == 0)) ++ goto unlock; ++ ++ local->int_scan_req->n_channels = n_ch; + } else { ++ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | ++ IEEE80211_CHAN_DISABLED))) ++ goto unlock; ++ + local->int_scan_req->channels[0] = chan; + local->int_scan_req->n_channels = 1; + } +From 97f97b1f5fe0878b35c8e314f98591771696321b Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 13 Dec 2012 22:54:58 +0100 +Subject: mac80211: fix station destruction in AP/mesh modes + +From: Johannes Berg + +commit 97f97b1f5fe0878b35c8e314f98591771696321b upstream. + +Unfortunately, commit b22cfcfcae5b, intended to speed up roaming +by avoiding the synchronize_rcu() broke AP/mesh modes as it moved +some code into that work item that will still call into the driver +at a time where it's no longer expected to handle this: after the +AP or mesh has been stopped. + +To fix this problem remove the per-station work struct, maintain a +station cleanup list instead and flush this list when stations are +flushed. To keep this patch smaller for stable, do this when the +stations are flushed (sta_info_flush()). This unfortunately brings +back the original roaming delay; I'll fix that again in a separate +patch. + +Also, Ben reported that the original commit could sometimes (with +many interfaces) cause long delays when an interface is set down, +due to blocking on flush_workqueue(). Since we now maintain the +cleanup list, this particular change of the original patch can be +reverted. + +Reported-by: Ben Greear +Tested-by: Ben Greear +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/ieee80211_i.h | 4 ++++ + net/mac80211/iface.c | 28 ++++++++++++++++------------ + net/mac80211/sta_info.c | 44 ++++++++++++++++++++++++++++++++++++++++---- + net/mac80211/sta_info.h | 3 ++- + 4 files changed, 62 insertions(+), 17 deletions(-) + +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -730,6 +730,10 @@ struct ieee80211_sub_if_data { + u32 mntr_flags; + } u; + ++ spinlock_t cleanup_stations_lock; ++ struct list_head cleanup_stations; ++ struct work_struct cleanup_stations_wk; ++ + #ifdef CONFIG_MAC80211_DEBUGFS + struct { + struct dentry *dir; +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -793,20 +793,11 @@ static void ieee80211_do_stop(struct iee + flush_work(&sdata->work); + /* + * When we get here, the interface is marked down. +- * Call rcu_barrier() to wait both for the RX path ++ * Call synchronize_rcu() to wait for the RX path + * should it be using the interface and enqueuing +- * frames at this very time on another CPU, and +- * for the sta free call_rcu callbacks. ++ * frames at this very time on another CPU. + */ +- rcu_barrier(); +- +- /* +- * free_sta_rcu() enqueues a work for the actual +- * sta cleanup, so we need to flush it while +- * sdata is still valid. +- */ +- flush_workqueue(local->workqueue); +- ++ synchronize_rcu(); + skb_queue_purge(&sdata->skb_queue); + + /* +@@ -1432,6 +1423,15 @@ static void ieee80211_assign_perm_addr(s + mutex_unlock(&local->iflist_mtx); + } + ++static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) ++{ ++ struct ieee80211_sub_if_data *sdata; ++ ++ sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); ++ ++ ieee80211_cleanup_sdata_stas(sdata); ++} ++ + int ieee80211_if_add(struct ieee80211_local *local, const char *name, + struct wireless_dev **new_wdev, enum nl80211_iftype type, + struct vif_params *params) +@@ -1507,6 +1507,10 @@ int ieee80211_if_add(struct ieee80211_lo + + INIT_LIST_HEAD(&sdata->key_list); + ++ spin_lock_init(&sdata->cleanup_stations_lock); ++ INIT_LIST_HEAD(&sdata->cleanup_stations); ++ INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); ++ + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { + struct ieee80211_supported_band *sband; + sband = local->hw.wiphy->bands[i]; +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee + return -ENOENT; + } + +-static void free_sta_work(struct work_struct *wk) ++static void cleanup_single_sta(struct sta_info *sta) + { +- struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); + int ac, i; + struct tid_ampdu_tx *tid_tx; + struct ieee80211_sub_if_data *sdata = sta->sdata; +@@ -148,11 +147,35 @@ static void free_sta_work(struct work_st + sta_info_free(local, sta); + } + ++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) ++{ ++ struct sta_info *sta; ++ ++ spin_lock_bh(&sdata->cleanup_stations_lock); ++ while (!list_empty(&sdata->cleanup_stations)) { ++ sta = list_first_entry(&sdata->cleanup_stations, ++ struct sta_info, list); ++ list_del(&sta->list); ++ spin_unlock_bh(&sdata->cleanup_stations_lock); ++ ++ cleanup_single_sta(sta); ++ ++ spin_lock_bh(&sdata->cleanup_stations_lock); ++ } ++ ++ spin_unlock_bh(&sdata->cleanup_stations_lock); ++} ++ + static void free_sta_rcu(struct rcu_head *h) + { + struct sta_info *sta = container_of(h, struct sta_info, rcu_head); ++ struct ieee80211_sub_if_data *sdata = sta->sdata; + +- ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); ++ spin_lock(&sdata->cleanup_stations_lock); ++ list_add_tail(&sta->list, &sdata->cleanup_stations); ++ spin_unlock(&sdata->cleanup_stations_lock); ++ ++ ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); + } + + /* protected by RCU */ +@@ -305,7 +328,6 @@ struct sta_info *sta_info_alloc(struct i + + spin_lock_init(&sta->lock); + INIT_WORK(&sta->drv_unblock_wk, sta_unblock); +- INIT_WORK(&sta->free_sta_wk, free_sta_work); + INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); + mutex_init(&sta->ampdu_mlme.mtx); + +@@ -877,6 +899,20 @@ int sta_info_flush(struct ieee80211_loca + } + mutex_unlock(&local->sta_mtx); + ++ rcu_barrier(); ++ ++ if (sdata) { ++ ieee80211_cleanup_sdata_stas(sdata); ++ cancel_work_sync(&sdata->cleanup_stations_wk); ++ } else { ++ mutex_lock(&local->iflist_mtx); ++ list_for_each_entry(sdata, &local->interfaces, list) { ++ ieee80211_cleanup_sdata_stas(sdata); ++ cancel_work_sync(&sdata->cleanup_stations_wk); ++ } ++ mutex_unlock(&local->iflist_mtx); ++ } ++ + return ret; + } + +--- a/net/mac80211/sta_info.h ++++ b/net/mac80211/sta_info.h +@@ -298,7 +298,6 @@ struct sta_info { + spinlock_t lock; + + struct work_struct drv_unblock_wk; +- struct work_struct free_sta_wk; + + u16 listen_interval; + +@@ -558,4 +557,6 @@ void ieee80211_sta_ps_deliver_wakeup(str + void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); + void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); + ++void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); ++ + #endif /* STA_INFO_H */ +From a56f992cdabc63f56b4b142885deebebf936ff76 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 13 Dec 2012 23:08:52 +0100 +Subject: mac80211: use del_timer_sync for final sta cleanup timer deletion + +From: Johannes Berg + +commit a56f992cdabc63f56b4b142885deebebf936ff76 upstream. + +This is a very old bug, but there's nothing that prevents the +timer from running while the module is being removed when we +only do del_timer() instead of del_timer_sync(). + +The timer should normally not be running at this point, but +it's not clearly impossible (or we could just remove this.) + +Tested-by: Ben Greear +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + net/mac80211/sta_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/mac80211/sta_info.c ++++ b/net/mac80211/sta_info.c +@@ -870,7 +870,7 @@ void sta_info_init(struct ieee80211_loca + + void sta_info_stop(struct ieee80211_local *local) + { +- del_timer(&local->sta_cleanup); ++ del_timer_sync(&local->sta_cleanup); + sta_info_flush(local, NULL); + } + +From 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 Mon Sep 17 00:00:00 2001 +From: Bing Zhao +Date: Wed, 2 Jan 2013 16:07:35 -0800 +Subject: mwifiex: check wait_event_interruptible return value + +From: Bing Zhao + +commit 9c969d8ccb1e17bd20742f4ac9f00c1a64487234 upstream. + +wait_event_interruptible function returns -ERESTARTSYS if it's +interrupted by a signal. Driver should check the return value +and handle this case properly. + +In mwifiex_wait_queue_complete() routine, as we are now checking +wait_event_interruptible return value, the condition check is not +required. Also, we have removed mwifiex_cancel_pending_ioctl() +call to avoid a chance of sending second command to FW by other path +as soon as we clear current command node. FW can not handle two +commands simultaneously. + +Signed-off-by: Bing Zhao +Signed-off-by: Amitkumar Karwar +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/mwifiex/sta_ioctl.c | 21 ++++++++++----------- + 1 file changed, 10 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/mwifiex/sta_ioctl.c ++++ b/drivers/net/wireless/mwifiex/sta_ioctl.c +@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifi + */ + int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) + { +- bool cancel_flag = false; + int status; + struct cmd_ctrl_node *cmd_queued; + +@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct m + atomic_inc(&adapter->cmd_pending); + + /* Wait for completion */ +- wait_event_interruptible(adapter->cmd_wait_q.wait, +- *(cmd_queued->condition)); +- if (!*(cmd_queued->condition)) +- cancel_flag = true; +- +- if (cancel_flag) { +- mwifiex_cancel_pending_ioctl(adapter); +- dev_dbg(adapter->dev, "cmd cancel\n"); ++ status = wait_event_interruptible(adapter->cmd_wait_q.wait, ++ *(cmd_queued->condition)); ++ if (status) { ++ dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); ++ return status; + } + + status = adapter->cmd_wait_q.status; +@@ -480,8 +476,11 @@ int mwifiex_enable_hs(struct mwifiex_ada + return false; + } + +- wait_event_interruptible(adapter->hs_activate_wait_q, +- adapter->hs_activate_wait_q_woken); ++ if (wait_event_interruptible(adapter->hs_activate_wait_q, ++ adapter->hs_activate_wait_q_woken)) { ++ dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); ++ return false; ++ } + + return true; + } +From 5e20a4b53094651d80f856ff55a916b999dbb57a Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Thu, 20 Dec 2012 15:55:01 -0600 +Subject: b43: Fix firmware loading when driver is built into the kernel + +From: Larry Finger + +commit 5e20a4b53094651d80f856ff55a916b999dbb57a upstream. + +Recent versions of udev cause synchronous firmware loading from the +probe routine to fail because the request to user space would time +out. The original fix for b43 (commit 6b6fa58) moved the firmware +load from the probe routine to a work queue, but it still used synchronous +firmware loading. This method is OK when b43 is built as a module; +however, it fails when the driver is compiled into the kernel. + +This version changes the code to load the initial firmware file +using request_firmware_nowait(). A completion event is used to +hold the work queue until that file is available. This driver +reads several firmware files - the remainder can be read synchronously. +On some test systems, the async read fails; however, a following synch +read works, thus the async failure falls through to the sync try. + +Reported-and-Tested by: Felix Janda +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/b43/b43.h | 5 +++ + drivers/net/wireless/b43/main.c | 54 ++++++++++++++++++++++++++++++---------- + drivers/net/wireless/b43/main.h | 5 +-- + 3 files changed, 48 insertions(+), 16 deletions(-) + +--- a/drivers/net/wireless/b43/b43.h ++++ b/drivers/net/wireless/b43/b43.h +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + + #include "debugfs.h" +@@ -722,6 +723,10 @@ enum b43_firmware_file_type { + struct b43_request_fw_context { + /* The device we are requesting the fw for. */ + struct b43_wldev *dev; ++ /* a completion event structure needed if this call is asynchronous */ ++ struct completion fw_load_complete; ++ /* a pointer to the firmware object */ ++ const struct firmware *blob; + /* The type of firmware to request. */ + enum b43_firmware_file_type req_type; + /* Error messages for each firmware type. */ +--- a/drivers/net/wireless/b43/main.c ++++ b/drivers/net/wireless/b43/main.c +@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct + b43warn(wl, text); + } + ++static void b43_fw_cb(const struct firmware *firmware, void *context) ++{ ++ struct b43_request_fw_context *ctx = context; ++ ++ ctx->blob = firmware; ++ complete(&ctx->fw_load_complete); ++} ++ + int b43_do_request_fw(struct b43_request_fw_context *ctx, + const char *name, +- struct b43_firmware_file *fw) ++ struct b43_firmware_file *fw, bool async) + { +- const struct firmware *blob; + struct b43_fw_header *hdr; + u32 size; + int err; +@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request + B43_WARN_ON(1); + return -ENOSYS; + } +- err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); ++ if (async) { ++ /* do this part asynchronously */ ++ init_completion(&ctx->fw_load_complete); ++ err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, ++ ctx->dev->dev->dev, GFP_KERNEL, ++ ctx, b43_fw_cb); ++ if (err < 0) { ++ pr_err("Unable to load firmware\n"); ++ return err; ++ } ++ /* stall here until fw ready */ ++ wait_for_completion(&ctx->fw_load_complete); ++ if (ctx->blob) ++ goto fw_ready; ++ /* On some ARM systems, the async request will fail, but the next sync ++ * request works. For this reason, we dall through here ++ */ ++ } ++ err = request_firmware(&ctx->blob, ctx->fwname, ++ ctx->dev->dev->dev); + if (err == -ENOENT) { + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), +- "Firmware file \"%s\" not found\n", ctx->fwname); ++ "Firmware file \"%s\" not found\n", ++ ctx->fwname); + return err; + } else if (err) { + snprintf(ctx->errors[ctx->req_type], +@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request + ctx->fwname, err); + return err; + } +- if (blob->size < sizeof(struct b43_fw_header)) ++fw_ready: ++ if (ctx->blob->size < sizeof(struct b43_fw_header)) + goto err_format; +- hdr = (struct b43_fw_header *)(blob->data); ++ hdr = (struct b43_fw_header *)(ctx->blob->data); + switch (hdr->type) { + case B43_FW_TYPE_UCODE: + case B43_FW_TYPE_PCM: + size = be32_to_cpu(hdr->size); +- if (size != blob->size - sizeof(struct b43_fw_header)) ++ if (size != ctx->blob->size - sizeof(struct b43_fw_header)) + goto err_format; + /* fallthrough */ + case B43_FW_TYPE_IV: +@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request + goto err_format; + } + +- fw->data = blob; ++ fw->data = ctx->blob; + fw->filename = name; + fw->type = ctx->req_type; + +@@ -2172,7 +2200,7 @@ err_format: + snprintf(ctx->errors[ctx->req_type], + sizeof(ctx->errors[ctx->req_type]), + "Firmware file \"%s\" format error.\n", ctx->fwname); +- release_firmware(blob); ++ release_firmware(ctx->blob); + + return -EPROTO; + } +@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43 + goto err_no_ucode; + } + } +- err = b43_do_request_fw(ctx, filename, &fw->ucode); ++ err = b43_do_request_fw(ctx, filename, &fw->ucode, true); + if (err) + goto err_load; + +@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43 + else + goto err_no_pcm; + fw->pcm_request_failed = false; +- err = b43_do_request_fw(ctx, filename, &fw->pcm); ++ err = b43_do_request_fw(ctx, filename, &fw->pcm, false); + if (err == -ENOENT) { + /* We did not find a PCM file? Not fatal, but + * core rev <= 10 must do without hwcrypto then. */ +@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43 + default: + goto err_no_initvals; + } +- err = b43_do_request_fw(ctx, filename, &fw->initvals); ++ err = b43_do_request_fw(ctx, filename, &fw->initvals, false); + if (err) + goto err_load; + +@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43 + default: + goto err_no_initvals; + } +- err = b43_do_request_fw(ctx, filename, &fw->initvals_band); ++ err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); + if (err) + goto err_load; + +--- a/drivers/net/wireless/b43/main.h ++++ b/drivers/net/wireless/b43/main.h +@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wl + + + struct b43_request_fw_context; +-int b43_do_request_fw(struct b43_request_fw_context *ctx, +- const char *name, +- struct b43_firmware_file *fw); ++int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, ++ struct b43_firmware_file *fw, bool async); + void b43_do_release_fw(struct b43_firmware_file *fw); + + #endif /* B43_MAIN_H_ */ +From ad86e58661b38b279b7519d4e49c7a19dc1654bb Mon Sep 17 00:00:00 2001 +From: Dzianis Kahanovich +Date: Mon, 3 Dec 2012 16:06:26 +0300 +Subject: USB: option: add Nexpring NP10T terminal id + +From: Dzianis Kahanovich + +commit ad86e58661b38b279b7519d4e49c7a19dc1654bb upstream. + +Hyundai Petatel Inc. Nexpring NP10T terminal (EV-DO rev.A USB modem) ID + +Signed-off-by: Denis Kaganovich +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -442,6 +442,10 @@ static void option_instat_callback(struc + #define CELLIENT_VENDOR_ID 0x2692 + #define CELLIENT_PRODUCT_MEN200 0x9005 + ++/* Hyundai Petatel Inc. products */ ++#define PETATEL_VENDOR_ID 0x1ff4 ++#define PETATEL_PRODUCT_NP10T 0x600e ++ + /* some devices interfaces need special handling due to a number of reasons */ + enum option_blacklist_reason { + OPTION_BLACKLIST_NONE = 0, +@@ -1296,6 +1300,7 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, ++ { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { } /* Terminating entry */ + }; + MODULE_DEVICE_TABLE(usb, option_ids); +From fab38246f318edcd0dcb8fd3852a47cf8938878a Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Wed, 19 Dec 2012 15:15:17 +0100 +Subject: USB: option: blacklist network interface on ZTE MF880 + +From: Bjørn Mork + +commit fab38246f318edcd0dcb8fd3852a47cf8938878a upstream. + +The driver description files gives these names to the vendor specific +functions on this modem: + + diag: VID_19D2&PID_0284&MI_00 + nmea: VID_19D2&PID_0284&MI_01 + at: VID_19D2&PID_0284&MI_02 + mdm: VID_19D2&PID_0284&MI_03 + net: VID_19D2&PID_0284&MI_04 + +Signed-off-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -928,7 +928,8 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, +- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, +From 94a85b633829b946eef53fc1825d526312fb856f Mon Sep 17 00:00:00 2001 +From: "Quentin.Li" +Date: Wed, 26 Dec 2012 16:58:22 +0800 +Subject: USB: option: Add new MEDIATEK PID support + +From: "Quentin.Li" + +commit 94a85b633829b946eef53fc1825d526312fb856f upstream. + +In option.c, add some new MEDIATEK PIDs support for MEDIATEK new products. This +is a MEDIATEK inc. release patch. + +Signed-off-by: Quentin.Li +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -430,9 +430,12 @@ static void option_instat_callback(struc + #define MEDIATEK_VENDOR_ID 0x0e8d + #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 + #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 ++#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 + #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 + #define MEDIATEK_PRODUCT_7208_1COM 0x7101 + #define MEDIATEK_PRODUCT_7208_2COM 0x7102 ++#define MEDIATEK_PRODUCT_7103_2COM 0x7103 ++#define MEDIATEK_PRODUCT_7106_2COM 0x7106 + #define MEDIATEK_PRODUCT_FP_1COM 0x0003 + #define MEDIATEK_PRODUCT_FP_2COM 0x0023 + #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 +@@ -1300,6 +1303,10 @@ static const struct usb_device_id option + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, ++ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, + { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { } /* Terminating entry */ +From 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf Mon Sep 17 00:00:00 2001 +From: Bjørn Mork +Date: Fri, 28 Dec 2012 17:29:52 +0100 +Subject: USB: option: add Telekom Speedstick LTE II + +From: Bjørn Mork + +commit 5ec0085440ef8c2cf50002b34d5a504ee12aa2bf upstream. + +also known as Alcatel One Touch L100V LTE + +The driver description files gives these names to the vendor specific +functions on this modem: + + Application1: VID_1BBB&PID_011E&MI_00 + Application2: VID_1BBB&PID_011E&MI_01 + Modem: VID_1BBB&PID_011E&MI_03 + Ethernet: VID_1BBB&PID_011E&MI_04 + +Reported-by: Thomas Schäfer +Signed-off-by: Bjørn Mork +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -289,6 +289,7 @@ static void option_instat_callback(struc + #define ALCATEL_VENDOR_ID 0x1bbb + #define ALCATEL_PRODUCT_X060S_X200 0x0000 + #define ALCATEL_PRODUCT_X220_X500D 0x0017 ++#define ALCATEL_PRODUCT_L100V 0x011e + + #define PIRELLI_VENDOR_ID 0x1266 + #define PIRELLI_PRODUCT_C100_1 0x1002 +@@ -1199,6 +1200,8 @@ static const struct usb_device_id option + .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist + }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, ++ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), ++ .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, + { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), +From 8cf65dc386f3634a43312f436cc7a935476a40c4 Mon Sep 17 00:00:00 2001 +From: Tomasz Mloduchowski +Date: Sun, 13 Jan 2013 23:32:53 +0100 +Subject: usb: ftdi_sio: Crucible Technologies COMET Caller ID - pid added + +From: Tomasz Mloduchowski + +commit 8cf65dc386f3634a43312f436cc7a935476a40c4 upstream. + +Simple fix to add support for Crucible Technologies COMET Caller ID +USB decoder - a device containing FTDI USB/Serial converter chip, +handling 1200bps CallerID messages decoded from the phone line - +adding correct USB PID is sufficient. + +Tested to apply cleanly and work flawlessly against 3.6.9, 3.7.0-rc8 +and 3.8.0-rc3 on both amd64 and x86 arches. + +Signed-off-by: Tomasz Mloduchowski +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 2 ++ + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -876,6 +876,8 @@ static struct usb_device_id id_table_com + { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, ++ /* Crucible Devices */ ++ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, + { }, /* Optional parameter entry */ + { } /* Terminating entry */ + }; +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -1259,3 +1259,9 @@ + * ATI command output: Cinterion MC55i + */ + #define FTDI_CINTERION_MC55I_PID 0xA951 ++ ++/* ++ * Product: Comet Caller ID decoder ++ * Manufacturer: Crucible Technologies ++ */ ++#define FTDI_CT_COMET_PID 0x8e08 +From 036915a7a402753c05b8d0529f5fd08805ab46d0 Mon Sep 17 00:00:00 2001 +From: Denis N Ladin +Date: Wed, 26 Dec 2012 18:29:44 +0500 +Subject: USB: cdc-acm: Add support for "PSC Scanning, Magellan 800i" + +From: Denis N Ladin + +commit 036915a7a402753c05b8d0529f5fd08805ab46d0 upstream. + +Adding support "PSC Scanning, Magellan 800i" in cdc-acm + +Very simple, but very necessary. +Suitable for all versions of the kernel > 2.6 + +Signed-off-by: Denis N Ladin +Acked-by: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-acm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_id + { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ + .driver_info = NO_UNION_NORMAL, + }, ++ { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ ++ .driver_info = NO_UNION_NORMAL, ++ }, + { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ + }, +From 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 Mon Sep 17 00:00:00 2001 +From: Sebastian Andrzej Siewior +Date: Tue, 20 Nov 2012 13:23:15 +0100 +Subject: usb: gadget: dummy: fix enumeration with g_multi + +From: Sebastian Andrzej Siewior + +commit 1d16638e3b9cc195bac18a8fcbca748f33c1bc24 upstream. + +If we do have endpoints named like "ep-a" then bEndpointAddress is +counted internally by the gadget framework. + +If we do have endpoints named like "ep-1" then bEndpointAddress is +assigned from the digit after "ep-". + +If we do have both, then it is likely that after we used up the +"generic" endpoints we will use the digits and thus assign one +bEndpointAddress to multiple endpoints. + +This theory can be proofed by using the completely enabled g_multi. +Without this patch, the mass storage won't enumerate and times out +because it shares endpoints with RNDIS. + +This patch also adds fills up the endpoints list so we have in total +endpoints 1 to 15 in + out available while some of them are restricted +to certain types like BULK or ISO. Without this change the nokia gadget +won't load because the system does not provide enough (BULK) endpoints +but it did before ep-a - ep-f were removed. + +Signed-off-by: Sebastian Andrzej Siewior +Acked-by: Alan Stern +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/dummy_hcd.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/usb/gadget/dummy_hcd.c ++++ b/drivers/usb/gadget/dummy_hcd.c +@@ -126,10 +126,7 @@ static const char ep0name[] = "ep0"; + static const char *const ep_name[] = { + ep0name, /* everyone has ep0 */ + +- /* act like a net2280: high speed, six configurable endpoints */ +- "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", +- +- /* or like pxa250: fifteen fixed function endpoints */ ++ /* act like a pxa250: fifteen fixed function endpoints */ + "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", + "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", + "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", +@@ -137,6 +134,10 @@ static const char *const ep_name[] = { + + /* or like sa1100: two fixed function endpoints */ + "ep1out-bulk", "ep2in-bulk", ++ ++ /* and now some generic EPs so we have enough in multi config */ ++ "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", ++ "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", + }; + #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) + +From 2ac788f705e5118dd45204e7a5bc8d5bb6873835 Mon Sep 17 00:00:00 2001 +From: Sergei Shtylyov +Date: Wed, 14 Nov 2012 18:49:50 +0300 +Subject: usb: musb: core: print new line in the driver banner again + +From: Sergei Shtylyov + +commit 2ac788f705e5118dd45204e7a5bc8d5bb6873835 upstream. + +Commit 5c8a86e10a7c164f44537fabdc169fd8b4e7a440 (usb: musb: drop unneeded +musb_debug trickery) erroneously removed '\n' from the driver's banner. +Concatenate all the banner substrings while adding it back... + +Signed-off-by: Sergei Shtylyov +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/musb/musb_core.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -2351,10 +2351,7 @@ static int __init musb_init(void) + if (usb_disabled()) + return 0; + +- pr_info("%s: version " MUSB_VERSION ", " +- "?dma?" +- ", " +- "otg (peripheral+host)", ++ pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", + musb_driver_name); + return platform_driver_register(&musb_driver); + } +From f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Tue, 25 Dec 2012 18:13:22 +0100 +Subject: drm/nv17-50: restore fence buffer on resume + +From: Marcin Slusarz + +commit f20ebd034eab43fd38c58b11c5bb5fb125e5f7d7 upstream. + +Since commit 5e120f6e4b3f35b741c5445dfc755f50128c3c44 "drm/nouveau/fence: +convert to exec engine, and improve channel sync" nouveau fence sync +implementation for nv17-50 and nvc0+ started to rely on state of fence buffer +left by previous sync operation. But as pinned bo's (where fence state is +stored) are not saved+restored across suspend/resume, we need to do it +manually. + +nvc0+ was fixed by commit d6ba6d215a538a58f0f0026f0961b0b9125e8042 +"drm/nvc0/fence: restore pre-suspend fence buffer context on resume". + +Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=50121 + +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nouveau_fence.h | 1 + + drivers/gpu/drm/nouveau/nv10_fence.c | 8 ++++++++ + drivers/gpu/drm/nouveau/nv50_fence.c | 1 + + 3 files changed, 10 insertions(+) + +--- a/drivers/gpu/drm/nouveau/nouveau_fence.h ++++ b/drivers/gpu/drm/nouveau/nouveau_fence.h +@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_chan + void nv10_fence_context_del(struct nouveau_channel *); + void nv10_fence_destroy(struct nouveau_drm *); + int nv10_fence_create(struct nouveau_drm *); ++void nv17_fence_resume(struct nouveau_drm *drm); + + int nv50_fence_create(struct nouveau_drm *); + int nv84_fence_create(struct nouveau_drm *); +--- a/drivers/gpu/drm/nouveau/nv10_fence.c ++++ b/drivers/gpu/drm/nouveau/nv10_fence.c +@@ -160,6 +160,13 @@ nv10_fence_destroy(struct nouveau_drm *d + kfree(priv); + } + ++void nv17_fence_resume(struct nouveau_drm *drm) ++{ ++ struct nv10_fence_priv *priv = drm->fence; ++ ++ nouveau_bo_wr32(priv->bo, 0, priv->sequence); ++} ++ + int + nv10_fence_create(struct nouveau_drm *drm) + { +@@ -192,6 +199,7 @@ nv10_fence_create(struct nouveau_drm *dr + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; ++ priv->base.resume = nv17_fence_resume; + } + } + +--- a/drivers/gpu/drm/nouveau/nv50_fence.c ++++ b/drivers/gpu/drm/nouveau/nv50_fence.c +@@ -119,6 +119,7 @@ nv50_fence_create(struct nouveau_drm *dr + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; ++ priv->base.resume = nv17_fence_resume; + } + + if (ret) +From 92441b2263866c27ef48137be5aa6c8c692652fc Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Tue, 18 Dec 2012 20:30:47 +0100 +Subject: drm/nouveau: fix blank LVDS screen regression on pre-nv50 cards + +From: Marcin Slusarz + +commit 92441b2263866c27ef48137be5aa6c8c692652fc upstream. + +Commit 2a44e499 ("drm/nouveau/disp: introduce proper init/fini, separate +from create/destroy") started to call display init routines on pre-nv50 +hardware on module load. But LVDS init code sets driver state in a way +which prevents modesetting code from operating properly. + +nv04_display_init calls nv04_dfp_restore, which sets encoder->last_dpms to +NV_DPMS_CLEARED. + +drm_crtc_helper_set_mode + nv04_dfp_prepare + nv04_lvds_dpms(DRM_MODE_DPMS_OFF) + +nv04_lvds_dpms checks last_dpms mode (which is NV_DPMS_CLEARED) and wrongly +assumes it's a "powersaving mode", the new one (DRM_MODE_DPMS_OFF) is too, +so it skips calling some crucial lvds scripts. + +Reported-by: Chris Paulson-Ellis +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/nv04_dfp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nv04_dfp.c ++++ b/drivers/gpu/drm/nouveau/nv04_dfp.c +@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(st + + static inline bool is_powersaving_dpms(int mode) + { +- return (mode != DRM_MODE_DPMS_ON); ++ return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; + } + + static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) +From 4c4101d29fb6c63f78791d02c437702b11e1d4f0 Mon Sep 17 00:00:00 2001 +From: Marcin Slusarz +Date: Sun, 2 Dec 2012 12:56:22 +0100 +Subject: drm/nouveau: add locking around instobj list operations + +From: Marcin Slusarz + +commit 4c4101d29fb6c63f78791d02c437702b11e1d4f0 upstream. + +Fixes memory corruptions, oopses, etc. when multiple gpuobjs are +simultaneously created or destroyed. + +Signed-off-by: Marcin Slusarz +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | 35 ++++++++++++++++----- + 1 file changed, 27 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_o + if (ret) + return ret; + ++ mutex_lock(&imem->base.mutex); + list_add(&iobj->head, &imem->list); ++ mutex_unlock(&imem->base.mutex); + return 0; + } + + void + nouveau_instobj_destroy(struct nouveau_instobj *iobj) + { +- if (iobj->head.prev) +- list_del(&iobj->head); ++ struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); ++ ++ mutex_lock(&subdev->mutex); ++ list_del(&iobj->head); ++ mutex_unlock(&subdev->mutex); ++ + return nouveau_object_destroy(&iobj->base); + } + +@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_inst + if (ret) + return ret; + ++ mutex_lock(&imem->base.mutex); ++ + list_for_each_entry(iobj, &imem->list, head) { + if (iobj->suspend) { + for (i = 0; i < iobj->size; i += 4) +@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_inst + } + } + ++ mutex_unlock(&imem->base.mutex); ++ + return 0; + } + +@@ -104,17 +114,26 @@ int + nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) + { + struct nouveau_instobj *iobj; +- int i; ++ int i, ret = 0; + + if (suspend) { ++ mutex_lock(&imem->base.mutex); ++ + list_for_each_entry(iobj, &imem->list, head) { + iobj->suspend = vmalloc(iobj->size); +- if (iobj->suspend) { +- for (i = 0; i < iobj->size; i += 4) +- iobj->suspend[i / 4] = nv_ro32(iobj, i); +- } else +- return -ENOMEM; ++ if (!iobj->suspend) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ for (i = 0; i < iobj->size; i += 4) ++ iobj->suspend[i / 4] = nv_ro32(iobj, i); + } ++ ++ mutex_unlock(&imem->base.mutex); ++ ++ if (ret) ++ return ret; + } + + return nouveau_subdev_fini(&imem->base, suspend); +From d19528a9e4f220519c2cb3f56ef0c84ead3ee440 Mon Sep 17 00:00:00 2001 +From: Aleksi Torhamo +Date: Fri, 4 Jan 2013 18:39:13 +0200 +Subject: drm/nouveau/clock: fix support for more than 2 monitors on nve0 + +From: Aleksi Torhamo + +commit d19528a9e4f220519c2cb3f56ef0c84ead3ee440 upstream. + +Fixes regression introduced in commit 70790f4f +"drm/nouveau/clock: pull in the implementation from all over the place" + +When code was moved from nv50_crtc_set_clock to nvc0_clock_pll_set, +the PLLs it is used for got limited to only the first two VPLLs. + +nv50_crtc_set_clock was only called to change VPLLs, so it didn't +limit what it was used for in any way. Since nvc0_clock_pll_set is +used for all PLLs, it has to specify which PLLs the code is used for, +and only listed the first two VPLLs. + +Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=58735 + +This patch is a -stable candidate for 3.7. + +Signed-off-by: Aleksi Torhamo +Tested-by: Aleksi Torhamo +Tested-by: Sean Santos +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | 2 ++ + drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h ++++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +@@ -38,6 +38,8 @@ enum nvbios_pll_type { + PLL_UNK42 = 0x42, + PLL_VPLL0 = 0x80, + PLL_VPLL1 = 0x81, ++ PLL_VPLL2 = 0x82, ++ PLL_VPLL3 = 0x83, + PLL_MAX = 0xff + }; + +--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock + switch (info.type) { + case PLL_VPLL0: + case PLL_VPLL1: ++ case PLL_VPLL2: ++ case PLL_VPLL3: + nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); + nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); + nv_wr32(priv, info.reg + 0x10, fN << 16); +From 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 Mon Sep 17 00:00:00 2001 +From: Aleksi Torhamo +Date: Wed, 9 Jan 2013 20:08:48 +0200 +Subject: drm/nvc0/fb: fix crash when different mutex is used to protect same list + +From: Aleksi Torhamo + +commit 43f789792e2c7ea2bff37195e4c4b4239e9e02b7 upstream. + +Fixes regression introduced in commit 861d2107 +"drm/nouveau/fb: merge fb/vram and port to subdev interfaces" + +nv50_fb_vram_{new,del} functions were changed to use +nouveau_subdev->mutex instead of the old nouveau_mm->mutex. +nvc0_fb_vram_new still uses the nouveau_mm->mutex, but nvc0 doesn't +have its own fb_vram_del function, using nv50_fb_vram_del instead. +Because of this, on nvc0 a different mutex ends up being used to protect +additions and deletions to the same list. + +This patch is a -stable candidate for 3.7. + +Signed-off-by: Aleksi Torhamo +Reported-by: Roy Spliet +Tested-by: Roy Spliet +Signed-off-by: Ben Skeggs +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c ++++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +@@ -86,14 +86,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, + mem->memtype = type; + mem->size = size; + +- mutex_lock(&mm->mutex); ++ mutex_lock(&pfb->base.mutex); + do { + if (back) + ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); + else + ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); + if (ret) { +- mutex_unlock(&mm->mutex); ++ mutex_unlock(&pfb->base.mutex); + pfb->ram.put(pfb, &mem); + return ret; + } +@@ -101,7 +101,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, + list_add_tail(&r->rl_entry, &mem->regions); + size -= r->length; + } while (size); +- mutex_unlock(&mm->mutex); ++ mutex_unlock(&pfb->base.mutex); + + r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); + mem->offset = (u64)r->offset << 12; +From 1c7439c61fa6516419c32a9824976334ea969d47 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 15:58:52 -0800 +Subject: USB: Handle auto-transition from hot to warm reset. + +From: Sarah Sharp + +commit 1c7439c61fa6516419c32a9824976334ea969d47 upstream. + +USB 3.0 hubs and roothubs will automatically transition a failed hot +reset to a warm (BH) reset. In that case, the warm reset change bit +will be set, and the link state change bit may also be set. Change +hub_port_finish_reset to unconditionally clear those change bits for USB +3.0 hubs. If these bits are not cleared, we may lose port change events +from the roothub. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2541,16 +2541,16 @@ static void hub_port_finish_reset(struct + clear_port_feature(hub->hdev, + port1, USB_PORT_FEAT_C_RESET); + /* FIXME need disconnect() for NOTATTACHED device */ +- if (warm) { ++ if (hub_is_superspeed(hub->hdev)) { + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); +- } else { ++ } ++ if (!warm) + usb_set_device_state(udev, *status + ? USB_STATE_NOTATTACHED + : USB_STATE_DEFAULT); +- } + break; + } + } +From bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 Mon Sep 17 00:00:00 2001 +From: Andreas Fleig +Date: Wed, 5 Dec 2012 16:17:49 +0100 +Subject: USB: Add device quirk for Microsoft VX700 webcam + +From: Andreas Fleig + +commit bc009eca8d539162f7271c2daf0ab5e9e3bb90a0 upstream. + +Add device quirk for Microsoft Lifecam VX700 v2.0 webcams. +Fixes squeaking noise of the microphone. + +Signed-off-by: Andreas Fleig +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -43,6 +43,9 @@ static const struct usb_device_id usb_qu + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + ++ /* Microsoft LifeCam-VX700 v2.0 */ ++ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, ++ + /* Logitech Quickcam Fusion */ + { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, + +From 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 16:10:49 -0800 +Subject: USB: Ignore xHCI Reset Device status. + +From: Sarah Sharp + +commit 8b8132bc3d1cc3d4c0687e4d638a482fa920d98a upstream. + +When the USB core finishes reseting a USB device, the xHCI driver sends +a Reset Device command to the host. The xHC then updates its internal +representation of the USB device to the 'Default' device state. If the +device was already in the Default state, the xHC will complete the +command with an error status. + +If a device needs to be reset several times during enumeration, the +second reset will always fail because of the xHCI Reset Device command. +This can cause issues during enumeration. + +For example, usb_reset_and_verify_device calls into hub_port_init in a +loop. Say that on the first call into hub_port_init, the device is +successfully reset, but doesn't respond to several set address control +transfers. Then the port will be disabled, but the udev will remain in +tact. usb_reset_and_verify_device will call into hub_port_init again. + +On the second call into hub_port_init, the device will be reset, and the +xHCI driver will issue a Reset Device command. This command will fail +(because the device is already in the Default state), and +usb_reset_and_verify_device will fail. The port will be disabled, and +the device won't be able to enumerate. + +Fix this by ignoring the return value of the HCD reset_device callback. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2526,14 +2526,11 @@ static void hub_port_finish_reset(struct + msleep(10 + 40); + update_devnum(udev, 0); + hcd = bus_to_hcd(udev->bus); +- if (hcd->driver->reset_device) { +- *status = hcd->driver->reset_device(hcd, udev); +- if (*status < 0) { +- dev_err(&udev->dev, "Cannot reset " +- "HCD device state\n"); +- break; +- } +- } ++ /* The xHC may think the device is already reset, ++ * so ignore the status. ++ */ ++ if (hcd->driver->reset_device) ++ hcd->driver->reset_device(hcd, udev); + } + /* FALL THROUGH */ + case -ENOTCONN: +From 41e7e056cdc662f704fa9262e5c6e213b4ab45dd Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 16:42:32 -0800 +Subject: USB: Allow USB 3.0 ports to be disabled. + +From: Sarah Sharp + +commit 41e7e056cdc662f704fa9262e5c6e213b4ab45dd upstream. + +If hot and warm reset fails, or a port remains in the Compliance Mode, +the USB core needs to be able to disable a USB 3.0 port. Unlike USB 2.0 +ports, once the port is placed into the Disabled link state, it will not +report any new device connects. To get device connect notifications, we +need to put the link into the Disabled state, and then the RxDetect +state. + +The xHCI driver needs to atomically clear all change bits on USB 3.0 +port disable, so that we get Port Status Change Events for future port +changes. We could technically do this in the USB core instead of in the +xHCI roothub code, since the port state machine can't advance out of the +disabled state until we set the link state to RxDetect. However, +external USB 3.0 hubs don't need this code. They are level-triggered, +not edge-triggered like xHCI, so they will continue to send interrupt +events when any change bit is set. Therefore it doesn't make sense to +put this code in the USB core. + +This patch is part of a series to fix several reports of infinite loops +on device enumeration failure. This includes John, when he boots with +a USB 3.0 device (Roseweil eusb3 enclosure) attached to his NEC 0.96 +host controller. The fix requires warm reset support, so it does not +make sense to backport this patch to stable kernels without warm reset +support. + +This patch should be backported to kernels as old as 3.2, contain the +commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm +reset logic" + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 63 ++++++++++++++++++++++++++++++++++++++++++-- + drivers/usb/host/xhci-hub.c | 31 ++++++++++++++++++++- + 2 files changed, 90 insertions(+), 4 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -876,6 +876,60 @@ static int hub_hub_status(struct usb_hub + return ret; + } + ++static int hub_set_port_link_state(struct usb_hub *hub, int port1, ++ unsigned int link_status) ++{ ++ return set_port_feature(hub->hdev, ++ port1 | (link_status << 3), ++ USB_PORT_FEAT_LINK_STATE); ++} ++ ++/* ++ * If USB 3.0 ports are placed into the Disabled state, they will no longer ++ * detect any device connects or disconnects. This is generally not what the ++ * USB core wants, since it expects a disabled port to produce a port status ++ * change event when a new device connects. ++ * ++ * Instead, set the link state to Disabled, wait for the link to settle into ++ * that state, clear any change bits, and then put the port into the RxDetect ++ * state. ++ */ ++static int hub_usb3_port_disable(struct usb_hub *hub, int port1) ++{ ++ int ret; ++ int total_time; ++ u16 portchange, portstatus; ++ ++ if (!hub_is_superspeed(hub->hdev)) ++ return -EINVAL; ++ ++ ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); ++ if (ret) { ++ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", ++ port1, ret); ++ return ret; ++ } ++ ++ /* Wait for the link to enter the disabled state. */ ++ for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { ++ ret = hub_port_status(hub, port1, &portstatus, &portchange); ++ if (ret < 0) ++ return ret; ++ ++ if ((portstatus & USB_PORT_STAT_LINK_STATE) == ++ USB_SS_PORT_LS_SS_DISABLED) ++ break; ++ if (total_time >= HUB_DEBOUNCE_TIMEOUT) ++ break; ++ msleep(HUB_DEBOUNCE_STEP); ++ } ++ if (total_time >= HUB_DEBOUNCE_TIMEOUT) ++ dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", ++ port1, total_time); ++ ++ return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); ++} ++ + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) + { + struct usb_device *hdev = hub->hdev; +@@ -884,8 +938,13 @@ static int hub_port_disable(struct usb_h + if (hub->ports[port1 - 1]->child && set_state) + usb_set_device_state(hub->ports[port1 - 1]->child, + USB_STATE_NOTATTACHED); +- if (!hub->error && !hub_is_superspeed(hub->hdev)) +- ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); ++ if (!hub->error) { ++ if (hub_is_superspeed(hub->hdev)) ++ ret = hub_usb3_port_disable(hub, port1); ++ else ++ ret = clear_port_feature(hdev, port1, ++ USB_PORT_FEAT_ENABLE); ++ } + if (ret) + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd + break; + case USB_PORT_FEAT_LINK_STATE: + temp = xhci_readl(xhci, port_array[wIndex]); ++ ++ /* Disable port */ ++ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { ++ xhci_dbg(xhci, "Disable port %d\n", wIndex); ++ temp = xhci_port_state_to_neutral(temp); ++ /* ++ * Clear all change bits, so that we get a new ++ * connection event. ++ */ ++ temp |= PORT_CSC | PORT_PEC | PORT_WRC | ++ PORT_OCC | PORT_RC | PORT_PLC | ++ PORT_CEC; ++ xhci_writel(xhci, temp | PORT_PE, ++ port_array[wIndex]); ++ temp = xhci_readl(xhci, port_array[wIndex]); ++ break; ++ } ++ ++ /* Put link in RxDetect (enable port) */ ++ if (link_state == USB_SS_PORT_LS_RX_DETECT) { ++ xhci_dbg(xhci, "Enable port %d\n", wIndex); ++ xhci_set_link_state(xhci, port_array, wIndex, ++ link_state); ++ temp = xhci_readl(xhci, port_array[wIndex]); ++ break; ++ } ++ + /* Software should not attempt to set +- * port link state above '5' (Rx.Detect) and the port ++ * port link state above '3' (U3) and the port + * must be enabled. + */ + if ((temp & PORT_PE) == 0 || +- (link_state > USB_SS_PORT_LS_RX_DETECT)) { ++ (link_state > USB_SS_PORT_LS_U3)) { + xhci_warn(xhci, "Cannot set link state.\n"); + goto error; + } +From 77c7f072c87fa951e9a74805febf26466f31170c Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 17:16:52 -0800 +Subject: USB: Increase reset timeout. + +From: Sarah Sharp + +commit 77c7f072c87fa951e9a74805febf26466f31170c upstream. + +John's NEC 0.96 xHCI host controller needs a longer timeout for a warm +reset to complete. The logs show it takes 650ms to complete the warm +reset, so extend the hub reset timeout to 800ms to be on the safe side. + +This commit should be backported to kernels as old as 3.2, that contain +the commit 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine +warm reset logic". + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2460,7 +2460,7 @@ static unsigned hub_is_wusb(struct usb_h + #define HUB_SHORT_RESET_TIME 10 + #define HUB_BH_RESET_TIME 50 + #define HUB_LONG_RESET_TIME 200 +-#define HUB_RESET_TIMEOUT 500 ++#define HUB_RESET_TIMEOUT 800 + + static int hub_port_reset(struct usb_hub *hub, int port1, + struct usb_device *udev, unsigned int delay, bool warm); +From 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Thu, 15 Nov 2012 14:58:04 -0800 +Subject: USB: Ignore port state until reset completes. + +From: Sarah Sharp + +commit 4f43447e62b37ee19c82a13f72f35b1ca60a74d3 upstream. + +The port reset code bails out early if the current connect status is +cleared (device disconnected). If we're issuing a hot reset, it may +also look at the link state before the reset is finished. + +Section 10.14.2.6 of the USB 3.0 spec says that when a port enters the +Error state or Resetting state, the port connection bit retains the +value from the previous state. Therefore we can't trust it until the +reset finishes. Also, the xHCI spec section 4.19.1.2.5 says software +shall ignore the link state while the port is resetting, as it can be in +an unknown state. + +The port state during reset is also unknown for USB 2.0 hubs. The hub +sends a reset signal by driving the bus into an SE0 state. This +overwhelms the "connect" signal from the device, so the port can't tell +whether anything is connected or not. + +Fix the port reset code to ignore the port link state and current +connect bit until the reset finishes, and USB_PORT_STAT_RESET is +cleared. + +Remove the check for USB_PORT_STAT_C_BH_RESET in the warm reset case, +because it's redundant. When the warm reset finishes, the port reset +bit will be cleared at the same time USB_PORT_STAT_C_BH_RESET is set. +Remove the now-redundant check for a cleared USB_PORT_STAT_RESET bit +in the code to deal with the finished reset. + +This patch should be backported to all stable kernels. + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2495,6 +2495,10 @@ static int hub_port_wait_reset(struct us + if (ret < 0) + return ret; + ++ /* The port state is unknown until the reset completes. */ ++ if ((portstatus & USB_PORT_STAT_RESET)) ++ goto delay; ++ + /* + * Some buggy devices require a warm reset to be issued even + * when the port appears not to be connected. +@@ -2540,11 +2544,7 @@ static int hub_port_wait_reset(struct us + if ((portchange & USB_PORT_STAT_C_CONNECTION)) + return -ENOTCONN; + +- /* if we`ve finished resetting, then break out of +- * the loop +- */ +- if (!(portstatus & USB_PORT_STAT_RESET) && +- (portstatus & USB_PORT_STAT_ENABLE)) { ++ if ((portstatus & USB_PORT_STAT_ENABLE)) { + if (hub_is_wusb(hub)) + udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeed(hub->hdev)) +@@ -2558,10 +2558,10 @@ static int hub_port_wait_reset(struct us + return 0; + } + } else { +- if (portchange & USB_PORT_STAT_C_BH_RESET) +- return 0; ++ return 0; + } + ++delay: + /* switch to the long delay after two short delay failures */ + if (delay_time >= 2 * HUB_SHORT_RESET_TIME) + delay = HUB_LONG_RESET_TIME; +From 65bdac5effd15d6af619b3b7218627ef4d84ed6a Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Wed, 14 Nov 2012 17:58:04 -0800 +Subject: USB: Handle warm reset failure on empty port. + +From: Sarah Sharp + +commit 65bdac5effd15d6af619b3b7218627ef4d84ed6a upstream. + +An empty port can transition to either Inactive or Compliance Mode if a +newly connected USB 3.0 device fails to link train. In that case, we +issue a warm reset. Some devices, such as John's Roseweil eusb3 +enclosure, slip back into Compliance Mode after the warm reset. + +The current warm reset code does not check for device connect status on +warm reset completion, and it incorrectly reports the warm reset +succeeded. This causes the USB core to attempt to send a Set Address +control transfer to a port in Compliance Mode, which will always fail. + +Make hub_port_wait_reset check the current connect status and link state +after the warm reset completes. Return a failure status if the device +is disconnected or the link state is Compliance Mode or SS.Inactive. + +Make hub_events disable the port if warm reset fails. This will disable +the port, and then bring it back into the RxDetect state. Make the USB +core ignore the connect change until the device reconnects. + +Note that this patch does NOT handle connected devices slipping into the +Inactive state very well. This is a concern, because devices can go +into the Inactive state on U1/U2 exit failure. However, the fix for +that case is too large for stable, so it will be submitted in a separate +patch. + +This patch should be backported to kernels as old as 3.2, contain the +commit ID 75d7cf72ab9fa01dc70877aa5c68e8ef477229dc "usbcore: refine warm +reset logic" + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Reported-by: John Covici +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2558,6 +2558,11 @@ static int hub_port_wait_reset(struct us + return 0; + } + } else { ++ if (!(portstatus & USB_PORT_STAT_CONNECTION) || ++ hub_port_warm_reset_required(hub, ++ portstatus)) ++ return -ENOTCONN; ++ + return 0; + } + +@@ -4628,9 +4633,14 @@ static void hub_events(void) + * SS.Inactive state. + */ + if (hub_port_warm_reset_required(hub, portstatus)) { ++ int status; ++ + dev_dbg(hub_dev, "warm reset port %d\n", i); +- hub_port_reset(hub, i, NULL, ++ status = hub_port_reset(hub, i, NULL, + HUB_BH_RESET_TIME, true); ++ if (status < 0) ++ hub_port_disable(hub, i, 1); ++ connect_change = 0; + } + + if (connect_change) +From c52804a472649b2e5005342308739434cbd51119 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Tue, 27 Nov 2012 12:30:23 -0800 +Subject: xhci: Avoid "dead ports", add roothub port polling. + +From: Sarah Sharp + +commit c52804a472649b2e5005342308739434cbd51119 upstream. + +The USB core hub thread (khubd) is designed with external USB hubs in +mind. It expects that if a port status change bit is set, the hub will +continue to send a notification through the hub status data transfer. +Basically, it expects hub notifications to be level-triggered. + +The xHCI host controller is designed to be edge-triggered on the logical +'OR' of all the port status change bits. When all port status change +bits are clear, and a new change bit is set, the xHC will generate a +Port Status Change Event. If another change bit is set in the same port +status register before the first bit is cleared, it will not send +another event. + +This means that the hub code may lose port status changes because of +race conditions between clearing change bits. The user sees this as a +"dead port" that doesn't react to device connects. + +The fix is to turn on port polling whenever a new change bit is set. +Once the USB core issues a hub status request that shows that no change +bits are set in any USB ports, turn off port polling. + +We can't allow the USB core to poll the roothub for port events during +host suspend because if the PCI host is in D3cold, the port registers +will be all f's. Instead, stop the port polling timer, and +unconditionally restart it when the host resumes. If there are no port +change bits set after the resume, the first call to hub_status_data will +disable polling. + +This patch should be backported to stable kernels with the first xHCI +support, 2.6.31 and newer, that include the commit +0f2a79300a1471cf92ab43af165ea13555c8b0a5 "USB: xhci: Root hub support." +There will be merge conflicts because the check for HC_STATE_SUSPENDED +was moved into xhci_suspend in 3.8. + +Signed-off-by: Sarah Sharp +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-hub.c | 7 +++++++ + drivers/usb/host/xhci-ring.c | 9 +++++++++ + drivers/usb/host/xhci.c | 10 ++++++++++ + 3 files changed, 26 insertions(+) + +--- a/drivers/usb/host/xhci-hub.c ++++ b/drivers/usb/host/xhci-hub.c +@@ -984,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd + int max_ports; + __le32 __iomem **port_array; + struct xhci_bus_state *bus_state; ++ bool reset_change = false; + + max_ports = xhci_get_ports(hcd, &port_array); + bus_state = &xhci->bus_state[hcd_index(hcd)]; +@@ -1015,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd + buf[(i + 1) / 8] |= 1 << (i + 1) % 8; + status = 1; + } ++ if ((temp & PORT_RC)) ++ reset_change = true; ++ } ++ if (!status && !reset_change) { ++ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); ++ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + } + spin_unlock_irqrestore(&xhci->lock, flags); + return status ? retval : 0; +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1725,6 +1725,15 @@ cleanup: + if (bogus_port_status) + return; + ++ /* ++ * xHCI port-status-change events occur when the "or" of all the ++ * status-change bits in the portsc register changes from 0 to 1. ++ * New status changes won't cause an event if any other change ++ * bits are still set. When an event occurs, switch over to ++ * polling to avoid losing status changes. ++ */ ++ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); ++ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + spin_unlock(&xhci->lock); + /* Pass this up to the core */ + usb_hcd_poll_rh_status(hcd); +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -880,6 +880,11 @@ int xhci_suspend(struct xhci_hcd *xhci) + struct usb_hcd *hcd = xhci_to_hcd(xhci); + u32 command; + ++ /* Don't poll the roothubs on bus suspend. */ ++ xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); ++ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); ++ del_timer_sync(&hcd->rh_timer); ++ + spin_lock_irq(&xhci->lock); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); +@@ -1064,6 +1069,11 @@ int xhci_resume(struct xhci_hcd *xhci, b + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + ++ /* Re-enable port polling. */ ++ xhci_dbg(xhci, "%s: starting port polling.\n", __func__); ++ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); ++ usb_hcd_poll_rh_status(hcd); ++ + return retval; + } + #endif /* CONFIG_PM */ +From 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 29 Nov 2012 15:05:57 +0100 +Subject: USB: hub: handle claim of enabled remote wakeup after reset + +From: Oliver Neukum + +commit 07e72b95f5038cc82304b9a4a2eb7f9fc391ea68 upstream. + +Some touchscreens have buggy firmware which claims +remote wakeup to be enabled after a reset. They nevertheless +crash if the feature is cleared by the host. +Add a check for reset resume before checking for +an enabled remote wakeup feature. On compliant +devices the feature must be cleared after a reset anyway. + +Signed-off-by: Oliver Neukum +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/hub.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -2960,7 +2960,7 @@ int usb_port_suspend(struct usb_device * + static int finish_port_resume(struct usb_device *udev) + { + int status = 0; +- u16 devstatus; ++ u16 devstatus = 0; + + /* caller owns the udev device lock */ + dev_dbg(&udev->dev, "%s\n", +@@ -3005,7 +3005,13 @@ static int finish_port_resume(struct usb + if (status) { + dev_dbg(&udev->dev, "gone after usb resume? status %d\n", + status); +- } else if (udev->actconfig) { ++ /* ++ * There are a few quirky devices which violate the standard ++ * by claiming to have remote wakeup enabled after a reset, ++ * which crash if the feature is cleared, hence check for ++ * udev->reset_resume ++ */ ++ } else if (udev->actconfig && !udev->reset_resume) { + le16_to_cpus(&devstatus); + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { + status = usb_control_msg(udev, +From 55c1945edaac94c5338a3647bc2e85ff75d9cf36 Mon Sep 17 00:00:00 2001 +From: Sarah Sharp +Date: Mon, 17 Dec 2012 14:12:35 -0800 +Subject: xhci: Handle HS bulk/ctrl endpoints that don't NAK. + +From: Sarah Sharp + +commit 55c1945edaac94c5338a3647bc2e85ff75d9cf36 upstream. + +A high speed control or bulk endpoint may have bInterval set to zero, +which means it does not NAK. If bInterval is non-zero, it means the +endpoint NAKs at a rate of 2^(bInterval - 1). + +The xHCI code to compute the NAK interval does not handle the special +case of zero properly. The current code unconditionally subtracts one +from bInterval and uses it as an exponent. This causes a very large +bInterval to be used, and warning messages like these will be printed: + +usb 1-1: ep 0x1 - rounding interval to 32768 microframes, ep desc says 0 microframes + +This may cause the xHCI host hardware to reject the Configure Endpoint +command, which means the HS device will be unusable under xHCI ports. + +This patch should be backported to kernels as old as 2.6.31, that contain +commit dfa49c4ad120a784ef1ff0717168aa79f55a483a "USB: xhci - fix math in +xhci_get_endpoint_interval()". + +Reported-by: Vincent Pelletier +Suggested-by: Alan Stern +Signed-off-by: Sarah Sharp +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-mem.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_ + static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, + struct usb_host_endpoint *ep) + { ++ if (ep->desc.bInterval == 0) ++ return 0; + return xhci_microframes_to_exponent(udev, ep, + ep->desc.bInterval, 0, 15); + } +From 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe Mon Sep 17 00:00:00 2001 +From: Jan Beulich +Date: Wed, 19 Dec 2012 16:15:56 +0000 +Subject: USB: ehci: make debug port in-use detection functional again + +From: Jan Beulich + +commit 75e1a2ae1f61ce1ae640410ba757bba84bd9fefe upstream. + +Debug port in-use determination must be done before the controller gets +reset the first time, i.e. before the call to ehci_setup() as of commit +1a49e2ac9651df7349867a5cf44e2c83de1046af. That commit effectively +rendered commit 9fa5780beea1274d498a224822397100022da7d4 useless. + +While moving that code around, also fix the BAR determination - the +respective capability field is a 3- rather than a 2-bit one -, and use +PCI_CAP_ID_DBG instead of the literal 0x0a. + +It's unclear to me whether the debug port functionality is important +enough to warrant fixing this in stable kernels too. + +Signed-off-by: Jan Beulich +Cc: Konrad Rzeszutek Wilk +Acked-by: Alan Stern +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ehci-pci.c | 39 ++++++++++++++++++++------------------- + 1 file changed, 20 insertions(+), 19 deletions(-) + +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -192,6 +192,26 @@ static int ehci_pci_setup(struct usb_hcd + break; + } + ++ /* optional debug port, normally in the first BAR */ ++ temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); ++ if (temp) { ++ pci_read_config_dword(pdev, temp, &temp); ++ temp >>= 16; ++ if (((temp >> 13) & 7) == 1) { ++ u32 hcs_params = ehci_readl(ehci, ++ &ehci->caps->hcs_params); ++ ++ temp &= 0x1fff; ++ ehci->debug = hcd->regs + temp; ++ temp = ehci_readl(ehci, &ehci->debug->control); ++ ehci_info(ehci, "debug port %d%s\n", ++ HCS_DEBUG_PORT(hcs_params), ++ (temp & DBGP_ENABLED) ? " IN USE" : ""); ++ if (!(temp & DBGP_ENABLED)) ++ ehci->debug = NULL; ++ } ++ } ++ + retval = ehci_setup(hcd); + if (retval) + return retval; +@@ -226,25 +246,6 @@ static int ehci_pci_setup(struct usb_hcd + break; + } + +- /* optional debug port, normally in the first BAR */ +- temp = pci_find_capability(pdev, 0x0a); +- if (temp) { +- pci_read_config_dword(pdev, temp, &temp); +- temp >>= 16; +- if ((temp & (3 << 13)) == (1 << 13)) { +- temp &= 0x1fff; +- ehci->debug = hcd->regs + temp; +- temp = ehci_readl(ehci, &ehci->debug->control); +- ehci_info(ehci, "debug port %d%s\n", +- HCS_DEBUG_PORT(ehci->hcs_params), +- (temp & DBGP_ENABLED) +- ? " IN USE" +- : ""); +- if (!(temp & DBGP_ENABLED)) +- ehci->debug = NULL; +- } +- } +- + /* at least the Genesys GL880S needs fixup here */ + temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); + temp &= 0x0f; +From bc3b7756b5ff66828acf7bc24f148d28b8d61108 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 28 Dec 2012 17:09:03 +0800 +Subject: regulator: max8997: Use uV in voltage_map_desc + +From: Axel Lin + +commit bc3b7756b5ff66828acf7bc24f148d28b8d61108 upstream. + +Current code does integer division (min_vol = min_uV / 1000) before pass +min_vol to max8997_get_voltage_proper_val(). +So it is possible min_vol is truncated to a smaller value. + +For example, if the request min_uV is 800900 for ldo. +min_vol = 800900 / 1000 = 800 (mV) +Then max8997_get_voltage_proper_val returns 800 mV for this case which is lower +than the requested voltage. + +Use uV rather than mV in voltage_map_desc to prevent truncation by integer +division. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8997.c | 36 +++++++++++++++++------------------- + 1 file changed, 17 insertions(+), 19 deletions(-) + +--- a/drivers/regulator/max8997.c ++++ b/drivers/regulator/max8997.c +@@ -69,26 +69,26 @@ struct voltage_map_desc { + int step; + }; + +-/* Voltage maps in mV */ ++/* Voltage maps in uV */ + static const struct voltage_map_desc ldo_voltage_map_desc = { +- .min = 800, .max = 3950, .step = 50, ++ .min = 800000, .max = 3950000, .step = 50000, + }; /* LDO1 ~ 18, 21 all */ + + static const struct voltage_map_desc buck1245_voltage_map_desc = { +- .min = 650, .max = 2225, .step = 25, ++ .min = 650000, .max = 2225000, .step = 25000, + }; /* Buck1, 2, 4, 5 */ + + static const struct voltage_map_desc buck37_voltage_map_desc = { +- .min = 750, .max = 3900, .step = 50, ++ .min = 750000, .max = 3900000, .step = 50000, + }; /* Buck3, 7 */ + +-/* current map in mA */ ++/* current map in uA */ + static const struct voltage_map_desc charger_current_map_desc = { +- .min = 200, .max = 950, .step = 50, ++ .min = 200000, .max = 950000, .step = 50000, + }; + + static const struct voltage_map_desc topoff_current_map_desc = { +- .min = 50, .max = 200, .step = 10, ++ .min = 50000, .max = 200000, .step = 10000, + }; + + static const struct voltage_map_desc *reg_voltage_map[] = { +@@ -192,7 +192,7 @@ static int max8997_list_voltage(struct r + if (val > desc->max) + return -EINVAL; + +- return val * 1000; ++ return val; + } + + static int max8997_get_enable_register(struct regulator_dev *rdev, +@@ -483,7 +483,6 @@ static int max8997_set_voltage_ldobuck(s + { + struct max8997_data *max8997 = rdev_get_drvdata(rdev); + struct i2c_client *i2c = max8997->iodev->i2c; +- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; + const struct voltage_map_desc *desc; + int rid = rdev_get_id(rdev); + int i, reg, shift, mask, ret; +@@ -507,7 +506,7 @@ static int max8997_set_voltage_ldobuck(s + + desc = reg_voltage_map[rid]; + +- i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); ++ i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); + if (i < 0) + return i; + +@@ -555,7 +554,7 @@ static int max8997_set_voltage_ldobuck_t + case MAX8997_BUCK4: + case MAX8997_BUCK5: + return DIV_ROUND_UP(desc->step * (new_selector - old_selector), +- max8997->ramp_delay); ++ max8997->ramp_delay * 1000); + } + + return 0; +@@ -654,7 +653,6 @@ static int max8997_set_voltage_buck(stru + const struct voltage_map_desc *desc; + int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; + bool gpio_dvs_mode = false; +- int min_vol = min_uV / 1000, max_vol = max_uV / 1000; + + if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) + return -EINVAL; +@@ -679,7 +677,7 @@ static int max8997_set_voltage_buck(stru + selector); + + desc = reg_voltage_map[rid]; +- new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); ++ new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); + if (new_val < 0) + return new_val; + +@@ -977,8 +975,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck1_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck1_voltage[i] / 1000, +- pdata->buck1_voltage[i] / 1000 + ++ pdata->buck1_voltage[i], ++ pdata->buck1_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +@@ -986,8 +984,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck2_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck2_voltage[i] / 1000, +- pdata->buck2_voltage[i] / 1000 + ++ pdata->buck2_voltage[i], ++ pdata->buck2_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +@@ -995,8 +993,8 @@ static __devinit int max8997_pmic_probe( + max8997->buck5_vol[i] = ret = + max8997_get_voltage_proper_val( + &buck1245_voltage_map_desc, +- pdata->buck5_voltage[i] / 1000, +- pdata->buck5_voltage[i] / 1000 + ++ pdata->buck5_voltage[i], ++ pdata->buck5_voltage[i] + + buck1245_voltage_map_desc.step); + if (ret < 0) + goto err_out; +From adf6178ad5552a7f2f742a8c85343c50f080c412 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Fri, 28 Dec 2012 17:10:20 +0800 +Subject: regulator: max8998: Use uV in voltage_map_desc + +From: Axel Lin + +commit adf6178ad5552a7f2f742a8c85343c50f080c412 upstream. + +Integer division may truncate. +This happens when pdata->buckx_voltagex setting is not align with 1000 uV. +Thus use uV in voltage_map_desc, this ensures the selected voltage won't less +than pdata buckx_voltagex settings. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8998.c | 42 +++++++++++++++++++++--------------------- + 1 file changed, 21 insertions(+), 21 deletions(-) + +--- a/drivers/regulator/max8998.c ++++ b/drivers/regulator/max8998.c +@@ -51,39 +51,39 @@ struct voltage_map_desc { + int step; + }; + +-/* Voltage maps */ ++/* Voltage maps in uV*/ + static const struct voltage_map_desc ldo23_voltage_map_desc = { +- .min = 800, .step = 50, .max = 1300, ++ .min = 800000, .step = 50000, .max = 1300000, + }; + static const struct voltage_map_desc ldo456711_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc ldo8_voltage_map_desc = { +- .min = 3000, .step = 100, .max = 3600, ++ .min = 3000000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc ldo9_voltage_map_desc = { +- .min = 2800, .step = 100, .max = 3100, ++ .min = 2800000, .step = 100000, .max = 3100000, + }; + static const struct voltage_map_desc ldo10_voltage_map_desc = { +- .min = 950, .step = 50, .max = 1300, ++ .min = 95000, .step = 50000, .max = 1300000, + }; + static const struct voltage_map_desc ldo1213_voltage_map_desc = { +- .min = 800, .step = 100, .max = 3300, ++ .min = 800000, .step = 100000, .max = 3300000, + }; + static const struct voltage_map_desc ldo1415_voltage_map_desc = { +- .min = 1200, .step = 100, .max = 3300, ++ .min = 1200000, .step = 100000, .max = 3300000, + }; + static const struct voltage_map_desc ldo1617_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc buck12_voltage_map_desc = { +- .min = 750, .step = 25, .max = 1525, ++ .min = 750000, .step = 25000, .max = 1525000, + }; + static const struct voltage_map_desc buck3_voltage_map_desc = { +- .min = 1600, .step = 100, .max = 3600, ++ .min = 1600000, .step = 100000, .max = 3600000, + }; + static const struct voltage_map_desc buck4_voltage_map_desc = { +- .min = 800, .step = 100, .max = 2300, ++ .min = 800000, .step = 100000, .max = 2300000, + }; + + static const struct voltage_map_desc *ldo_voltage_map[] = { +@@ -445,7 +445,7 @@ static int max8998_set_voltage_buck_time + if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) + return 0; + +- difference = (new_selector - old_selector) * desc->step; ++ difference = (new_selector - old_selector) * desc->step / 1000; + if (difference > 0) + return difference / ((val & 0x0f) + 1); + +@@ -702,7 +702,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage1 / 1000)) ++ < pdata->buck1_voltage1) + i++; + max8998->buck1_vol[0] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); +@@ -713,7 +713,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage2 / 1000)) ++ < pdata->buck1_voltage2) + i++; + + max8998->buck1_vol[1] = i; +@@ -725,7 +725,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage3 / 1000)) ++ < pdata->buck1_voltage3) + i++; + + max8998->buck1_vol[2] = i; +@@ -737,7 +737,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck1_voltage4 / 1000)) ++ < pdata->buck1_voltage4) + i++; + + max8998->buck1_vol[3] = i; +@@ -763,7 +763,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck2_voltage1 / 1000)) ++ < pdata->buck2_voltage1) + i++; + max8998->buck2_vol[0] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); +@@ -774,7 +774,7 @@ static __devinit int max8998_pmic_probe( + i = 0; + while (buck12_voltage_map_desc.min + + buck12_voltage_map_desc.step*i +- < (pdata->buck2_voltage2 / 1000)) ++ < pdata->buck2_voltage2) + i++; + max8998->buck2_vol[1] = i; + ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); +@@ -792,8 +792,8 @@ static __devinit int max8998_pmic_probe( + int count = (desc->max - desc->min) / desc->step + 1; + + regulators[index].n_voltages = count; +- regulators[index].min_uV = desc->min * 1000; +- regulators[index].uV_step = desc->step * 1000; ++ regulators[index].min_uV = desc->min; ++ regulators[index].uV_step = desc->step; + } + + config.dev = max8998->dev; +From 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 Mon Sep 17 00:00:00 2001 +From: Axel Lin +Date: Wed, 9 Jan 2013 19:34:57 +0800 +Subject: regulator: max8998: Ensure enough delay time for max8998_set_voltage_buck_time_sel + +From: Axel Lin + +commit 81d0a6ae7befb24c06f4aa4856af7f8d1f612171 upstream. + +Use DIV_ROUND_UP to prevent truncation by integer division issue. +This ensures we return enough delay time. + +Signed-off-by: Axel Lin +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/regulator/max8998.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/regulator/max8998.c ++++ b/drivers/regulator/max8998.c +@@ -447,7 +447,7 @@ static int max8998_set_voltage_buck_time + + difference = (new_selector - old_selector) * desc->step / 1000; + if (difference > 0) +- return difference / ((val & 0x0f) + 1); ++ return DIV_ROUND_UP(difference, (val & 0x0f) + 1); + + return 0; + } +From 9120963578320532dfb3a9a7947e8d05b39900b5 Mon Sep 17 00:00:00 2001 +From: Ralf Baechle +Date: Thu, 20 Dec 2012 12:47:51 +0100 +Subject: Revert "MIPS: Optimise TLB handlers for MIPS32/64 R2 cores." + +From: Ralf Baechle + +commit 9120963578320532dfb3a9a7947e8d05b39900b5 upstream. + +This reverts commit ff401e52100dcdc85e572d1ad376d3307b3fe28e. + +This breaks on MIPS64 R2 cores such as Broadcom's. + +Signed-off-by: Jayachandran C +Signed-off-by: Greg Kroah-Hartman + +--- + arch/mips/mm/tlbex.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +--- a/arch/mips/mm/tlbex.c ++++ b/arch/mips/mm/tlbex.c +@@ -952,13 +952,6 @@ build_get_pgde32(u32 **p, unsigned int t + #endif + uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ + uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); +- +- if (cpu_has_mips_r2) { +- uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT)); +- uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT)); +- return; +- } +- + uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ + uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); + uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ +@@ -994,15 +987,6 @@ static void __cpuinit build_adjust_conte + + static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) + { +- if (cpu_has_mips_r2) { +- /* PTE ptr offset is obtained from BadVAddr */ +- UASM_i_MFC0(p, tmp, C0_BADVADDR); +- UASM_i_LW(p, ptr, 0, ptr); +- uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1); +- uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1); +- return; +- } +- + /* + * Bug workaround for the Nevada. It seems as if under certain + * circumstances the move from cp0_context might produce a +From e8088073c9610af017fd47fddd104a2c3afb32e8 Mon Sep 17 00:00:00 2001 +From: Joe Thornber +Date: Fri, 21 Dec 2012 20:23:31 +0000 +Subject: dm thin: fix race between simultaneous io and discards to same block + +From: Joe Thornber + +commit e8088073c9610af017fd47fddd104a2c3afb32e8 upstream. + +There is a race when discard bios and non-discard bios are issued +simultaneously to the same block. + +Discard support is expensive for all thin devices precisely because you +have to be careful to quiesce the area you're discarding. DM thin must +handle this conflicting IO pattern (simultaneous non-discard vs discard) +even though a sane application shouldn't be issuing such IO. + +The race manifests as follows: + +1. A non-discard bio is mapped in thin_bio_map. + This doesn't lock out parallel activity to the same block. + +2. A discard bio is issued to the same block as the non-discard bio. + +3. The discard bio is locked in a dm_bio_prison_cell in process_discard + to lock out parallel activity against the same block. + +4. The non-discard bio's mapping continues and its all_io_entry is + incremented so the bio is accounted for in the thin pool's all_io_ds + which is a dm_deferred_set used to track time locality of non-discard IO. + +5. The non-discard bio is finally locked in a dm_bio_prison_cell in + process_bio. + +The race can result in deadlock, leaving the block layer hanging waiting +for completion of a discard bio that never completes, e.g.: + +INFO: task ruby:15354 blocked for more than 120 seconds. +"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. +ruby D ffffffff8160f0e0 0 15354 15314 0x00000000 + ffff8802fb08bc58 0000000000000082 ffff8802fb08bfd8 0000000000012900 + ffff8802fb08a010 0000000000012900 0000000000012900 0000000000012900 + ffff8802fb08bfd8 0000000000012900 ffff8803324b9480 ffff88032c6f14c0 +Call Trace: + [] schedule+0x29/0x70 + [] schedule_timeout+0x195/0x220 + [] ? _dm_request+0x111/0x160 [dm_mod] + [] wait_for_common+0x11e/0x190 + [] ? try_to_wake_up+0x2b0/0x2b0 + [] wait_for_completion+0x1d/0x20 + [] blkdev_issue_discard+0x219/0x260 + [] blkdev_ioctl+0x6e9/0x7b0 + [] block_ioctl+0x3c/0x40 + [] do_vfs_ioctl+0x8c/0x340 + [] ? block_llseek+0x67/0xb0 + [] sys_ioctl+0xa1/0xb0 + [] ? sys_rt_sigprocmask+0x86/0xd0 + [] system_call_fastpath+0x16/0x1b + +The thinp-test-suite's test_discard_random_sectors reliably hits this +deadlock on fast SSD storage. + +The fix for this race is that the all_io_entry for a bio must be +incremented whilst the dm_bio_prison_cell is held for the bio's +associated virtual and physical blocks. That cell locking wasn't +occurring early enough in thin_bio_map. This patch fixes this. + +Care is taken to always call the new function inc_all_io_entry() with +the relevant cells locked, but they are generally unlocked before +calling issue() to try to avoid holding the cells locked across +generic_submit_request. + +Also, now that thin_bio_map may lock bios in a cell, process_bio() is no +longer the only thread that will do so. Because of this we must be sure +to use cell_defer_except() to release all non-holder entries, that +were added by the other thread, because they must be deferred. + +This patch depends on "dm thin: replace dm_cell_release_singleton with +cell_defer_except". + +Signed-off-by: Joe Thornber +Signed-off-by: Mike Snitzer +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-thin.c | 84 +++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 59 insertions(+), 25 deletions(-) + +--- a/drivers/md/dm-thin.c ++++ b/drivers/md/dm-thin.c +@@ -368,6 +368,17 @@ static int bio_triggers_commit(struct th + dm_thin_changed_this_transaction(tc->td); + } + ++static void inc_all_io_entry(struct pool *pool, struct bio *bio) ++{ ++ struct dm_thin_endio_hook *h; ++ ++ if (bio->bi_rw & REQ_DISCARD) ++ return; ++ ++ h = dm_get_mapinfo(bio)->ptr; ++ h->all_io_entry = dm_deferred_entry_inc(pool->all_io_ds); ++} ++ + static void issue(struct thin_c *tc, struct bio *bio) + { + struct pool *pool = tc->pool; +@@ -596,13 +607,15 @@ static void process_prepared_discard_pas + { + struct thin_c *tc = m->tc; + ++ inc_all_io_entry(tc->pool, m->bio); ++ cell_defer_except(tc, m->cell); ++ cell_defer_except(tc, m->cell2); ++ + if (m->pass_discard) + remap_and_issue(tc, m->bio, m->data_block); + else + bio_endio(m->bio, 0); + +- cell_defer_except(tc, m->cell); +- cell_defer_except(tc, m->cell2); + mempool_free(m, tc->pool->mapping_pool); + } + +@@ -710,6 +723,7 @@ static void schedule_copy(struct thin_c + h->overwrite_mapping = m; + m->bio = bio; + save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); ++ inc_all_io_entry(pool, bio); + remap_and_issue(tc, bio, data_dest); + } else { + struct dm_io_region from, to; +@@ -779,6 +793,7 @@ static void schedule_zero(struct thin_c + h->overwrite_mapping = m; + m->bio = bio; + save_and_set_endio(bio, &m->saved_bi_end_io, overwrite_endio); ++ inc_all_io_entry(pool, bio); + remap_and_issue(tc, bio, data_block); + } else { + int r; +@@ -961,13 +976,15 @@ static void process_discard(struct thin_ + wake_worker(pool); + } + } else { ++ inc_all_io_entry(pool, bio); ++ cell_defer_except(tc, cell); ++ cell_defer_except(tc, cell2); ++ + /* + * The DM core makes sure that the discard doesn't span + * a block boundary. So we submit the discard of a + * partial block appropriately. + */ +- cell_defer_except(tc, cell); +- cell_defer_except(tc, cell2); + if ((!lookup_result.shared) && pool->pf.discard_passdown) + remap_and_issue(tc, bio, lookup_result.block); + else +@@ -1039,8 +1056,9 @@ static void process_shared_bio(struct th + struct dm_thin_endio_hook *h = dm_get_mapinfo(bio)->ptr; + + h->shared_read_entry = dm_deferred_entry_inc(pool->shared_read_ds); +- ++ inc_all_io_entry(pool, bio); + cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, lookup_result->block); + } + } +@@ -1055,7 +1073,9 @@ static void provision_block(struct thin_ + * Remap empty bios (flushes) immediately, without provisioning. + */ + if (!bio->bi_size) { ++ inc_all_io_entry(tc->pool, bio); + cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, 0); + return; + } +@@ -1110,26 +1130,22 @@ static void process_bio(struct thin_c *t + r = dm_thin_find_block(tc->td, block, 1, &lookup_result); + switch (r) { + case 0: +- /* +- * We can release this cell now. This thread is the only +- * one that puts bios into a cell, and we know there were +- * no preceding bios. +- */ +- /* +- * TODO: this will probably have to change when discard goes +- * back in. +- */ +- cell_defer_except(tc, cell); +- +- if (lookup_result.shared) ++ if (lookup_result.shared) { + process_shared_bio(tc, bio, block, &lookup_result); +- else ++ cell_defer_except(tc, cell); ++ } else { ++ inc_all_io_entry(tc->pool, bio); ++ cell_defer_except(tc, cell); ++ + remap_and_issue(tc, bio, lookup_result.block); ++ } + break; + + case -ENODATA: + if (bio_data_dir(bio) == READ && tc->origin_dev) { ++ inc_all_io_entry(tc->pool, bio); + cell_defer_except(tc, cell); ++ + remap_to_origin_and_issue(tc, bio); + } else + provision_block(tc, bio, block, cell); +@@ -1155,8 +1171,10 @@ static void process_bio_read_only(struct + case 0: + if (lookup_result.shared && (rw == WRITE) && bio->bi_size) + bio_io_error(bio); +- else ++ else { ++ inc_all_io_entry(tc->pool, bio); + remap_and_issue(tc, bio, lookup_result.block); ++ } + break; + + case -ENODATA: +@@ -1166,6 +1184,7 @@ static void process_bio_read_only(struct + } + + if (tc->origin_dev) { ++ inc_all_io_entry(tc->pool, bio); + remap_to_origin_and_issue(tc, bio); + break; + } +@@ -1346,7 +1365,7 @@ static struct dm_thin_endio_hook *thin_h + + h->tc = tc; + h->shared_read_entry = NULL; +- h->all_io_entry = bio->bi_rw & REQ_DISCARD ? NULL : dm_deferred_entry_inc(pool->all_io_ds); ++ h->all_io_entry = NULL; + h->overwrite_mapping = NULL; + + return h; +@@ -1363,6 +1382,8 @@ static int thin_bio_map(struct dm_target + dm_block_t block = get_bio_block(tc, bio); + struct dm_thin_device *td = tc->td; + struct dm_thin_lookup_result result; ++ struct dm_bio_prison_cell *cell1, *cell2; ++ struct dm_cell_key key; + + map_context->ptr = thin_hook_bio(tc, bio); + +@@ -1399,12 +1420,25 @@ static int thin_bio_map(struct dm_target + * shared flag will be set in their case. + */ + thin_defer_bio(tc, bio); +- r = DM_MAPIO_SUBMITTED; +- } else { +- remap(tc, bio, result.block); +- r = DM_MAPIO_REMAPPED; ++ return DM_MAPIO_SUBMITTED; + } +- break; ++ ++ build_virtual_key(tc->td, block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell1)) ++ return DM_MAPIO_SUBMITTED; ++ ++ build_data_key(tc->td, result.block, &key); ++ if (dm_bio_detain(tc->pool->prison, &key, bio, &cell2)) { ++ cell_defer_except(tc, cell1); ++ return DM_MAPIO_SUBMITTED; ++ } ++ ++ inc_all_io_entry(tc->pool, bio); ++ cell_defer_except(tc, cell2); ++ cell_defer_except(tc, cell1); ++ ++ remap(tc, bio, result.block); ++ return DM_MAPIO_REMAPPED; + + case -ENODATA: + if (get_pool_mode(tc->pool) == PM_READ_ONLY) { +From ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e Mon Sep 17 00:00:00 2001 +From: Stanislaw Gruszka +Date: Mon, 3 Dec 2012 12:59:04 +0100 +Subject: Revert: "rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails" + +From: Stanislaw Gruszka + +commit ab9d6e4ffe192427ce9e93d4f927b0faaa8a941e upstream. + +This revert: + +commit be03d4a45c09ee5100d3aaaedd087f19bc20d01f +Author: Andreas Hartmann +Date: Tue Apr 17 00:25:28 2012 +0200 + + rt2x00: Don't let mac80211 send a BAR when an AMPDU subframe fails + +To fix problem workaround by above commit use +IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL flag (see change log for +"mac80211: introduce IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL" patch). + +Resolve: https://bugzilla.kernel.org/show_bug.cgi?id=42828 +Bisected-by: Francisco Pina Martins +Signed-off-by: Stanislaw Gruszka +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rt2x00/rt2800lib.c | 3 ++- + drivers/net/wireless/rt2x00/rt2x00dev.c | 7 +++---- + 2 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/net/wireless/rt2x00/rt2800lib.c ++++ b/drivers/net/wireless/rt2x00/rt2800lib.c +@@ -5036,7 +5036,8 @@ static int rt2800_probe_hw_mode(struct r + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK | + IEEE80211_HW_AMPDU_AGGREGATION | +- IEEE80211_HW_REPORTS_TX_ACK_STATUS; ++ IEEE80211_HW_REPORTS_TX_ACK_STATUS | ++ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL; + + /* + * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -391,10 +391,9 @@ void rt2x00lib_txdone(struct queue_entry + tx_info->flags |= IEEE80211_TX_STAT_AMPDU; + tx_info->status.ampdu_len = 1; + tx_info->status.ampdu_ack_len = success ? 1 : 0; +- /* +- * TODO: Need to tear down BA session here +- * if not successful. +- */ ++ ++ if (!success) ++ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + } + + if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { +From 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 Mon Sep 17 00:00:00 2001 +From: Konstantin Khlebnikov +Date: Fri, 14 Dec 2012 15:03:10 +0400 +Subject: EDAC: Fix kernel panic on module unloading + +From: Konstantin Khlebnikov + +commit 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 upstream. + +This patch fixes use-after-free and double-free bugs in +edac_mc_sysfs_exit(). mci_pdev has single reference and put_device() +calls mc_attr_release() which calls kfree(). The following +device_del() works with already released memory. An another kfree() in +edac_mc_sysfs_exit() releses the same memory again. Great. + +Signed-off-by: Konstantin Khlebnikov +Cc: Denis Kirjanov +Cc: Mauro Carvalho Chehab +Link: http://lkml.kernel.org/r/20121214110310.11019.21098.stgit@zurg +Signed-off-by: Borislav Petkov +[ a partial 3.7.y backport ] +Signed-off-by: Borislav Petkov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/edac/edac_mc_sysfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -1145,7 +1145,7 @@ int __init edac_mc_sysfs_init(void) + + void __exit edac_mc_sysfs_exit(void) + { +- put_device(mci_pdev); + device_del(mci_pdev); ++ put_device(mci_pdev); + edac_put_sysfs_subsys(); + } +From 539526b4137bc0e7a8806c38c8522f226814a0e6 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Sat, 8 Dec 2012 12:58:33 +0100 +Subject: drm/i915: disable cpt phase pointer fdi rx workaround + +From: Daniel Vetter + +commit 539526b4137bc0e7a8806c38c8522f226814a0e6 upstream. + +We've originally added this in + +commit 291427f5fdadec6e4be2924172e83588880e1539 +Author: Jesse Barnes +Date: Fri Jul 29 12:42:37 2011 -0700 + + drm/i915: apply phase pointer override on SNB+ too + +and then copy-pasted it over to ivb/ppt. The w/a was originally added +for ilk/ibx in + +commit 5b2adf897146edeac6a1e438fb67b5a53dbbdf34 +Author: Jesse Barnes +Date: Thu Oct 7 16:01:15 2010 -0700 + + drm/i915: add Ironlake clock gating workaround for FDI link training + +and fixed up a bit in + +commit 6f06ce184c765fd8d50669a8d12fdd566c920859 +Author: Jesse Barnes +Date: Tue Jan 4 15:09:38 2011 -0800 + + drm/i915: set phase sync pointer override enable before setting phase sync pointer + +It turns out that this w/a isn't actually required on cpt/ppt and +positively harmful on ivb/ppt when using fdi B/C links - it results in +a black screen occasionally, with seemingfully everything working as +it should. The only failure indication I've found in the hw is that +eventually (but not right after the modeset completes) a pipe underrun +is signalled. + +Big thanks to Arthur Runyan for all the ideas for registers to check +and changes to test, otherwise I couldn't ever have tracked this down! + +Cc: "Runyan, Arthur J" +Cc: stable@vger.kernel.org +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 31 ------------------------------- + 1 file changed, 31 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -2302,18 +2302,6 @@ static void intel_fdi_normal_train(struc + FDI_FE_ERRC_ENABLE); + } + +-static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- u32 flags = I915_READ(SOUTH_CHICKEN1); +- +- flags |= FDI_PHASE_SYNC_OVR(pipe); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ +- flags |= FDI_PHASE_SYNC_EN(pipe); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ +- POSTING_READ(SOUTH_CHICKEN1); +-} +- + /* The FDI link training functions for ILK/Ibexpeak. */ + static void ironlake_fdi_link_train(struct drm_crtc *crtc) + { +@@ -2464,9 +2452,6 @@ static void gen6_fdi_link_train(struct d + POSTING_READ(reg); + udelay(150); + +- if (HAS_PCH_CPT(dev)) +- cpt_phase_pointer_enable(dev, pipe); +- + for (i = 0; i < 4; i++) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); +@@ -2593,9 +2578,6 @@ static void ivb_manual_fdi_link_train(st + POSTING_READ(reg); + udelay(150); + +- if (HAS_PCH_CPT(dev)) +- cpt_phase_pointer_enable(dev, pipe); +- + for (i = 0; i < 4; i++) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); +@@ -2737,17 +2719,6 @@ static void ironlake_fdi_pll_disable(str + udelay(100); + } + +-static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- u32 flags = I915_READ(SOUTH_CHICKEN1); +- +- flags &= ~(FDI_PHASE_SYNC_EN(pipe)); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ +- flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); +- I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ +- POSTING_READ(SOUTH_CHICKEN1); +-} + static void ironlake_fdi_disable(struct drm_crtc *crtc) + { + struct drm_device *dev = crtc->dev; +@@ -2777,8 +2748,6 @@ static void ironlake_fdi_disable(struct + I915_WRITE(FDI_RX_CHICKEN(pipe), + I915_READ(FDI_RX_CHICKEN(pipe) & + ~FDI_RX_PHASE_SYNC_POINTER_EN)); +- } else if (HAS_PCH_CPT(dev)) { +- cpt_phase_pointer_disable(dev, pipe); + } + + /* still set train pattern 1 */ +From e43a028752fed049e4bd94ef895542f96d79fa74 Mon Sep 17 00:00:00 2001 +From: Alexander Graf +Date: Sat, 6 Oct 2012 03:56:35 +0200 +Subject: KVM: PPC: 44x: fix DCR read/write + +From: Alexander Graf + +commit e43a028752fed049e4bd94ef895542f96d79fa74 upstream. + +When remembering the direction of a DCR transaction, we should write +to the same variable that we interpret on later when doing vcpu_run +again. + +Signed-off-by: Alexander Graf +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kvm/44x_emulate.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/powerpc/kvm/44x_emulate.c ++++ b/arch/powerpc/kvm/44x_emulate.c +@@ -76,6 +76,7 @@ int kvmppc_core_emulate_op(struct kvm_ru + run->dcr.dcrn = dcrn; + run->dcr.data = 0; + run->dcr.is_write = 0; ++ vcpu->arch.dcr_is_write = 0; + vcpu->arch.io_gpr = rt; + vcpu->arch.dcr_needed = 1; + kvmppc_account_exit(vcpu, DCR_EXITS); +@@ -94,6 +95,7 @@ int kvmppc_core_emulate_op(struct kvm_ru + run->dcr.dcrn = dcrn; + run->dcr.data = kvmppc_get_gpr(vcpu, rs); + run->dcr.is_write = 1; ++ vcpu->arch.dcr_is_write = 1; + vcpu->arch.dcr_needed = 1; + kvmppc_account_exit(vcpu, DCR_EXITS); + emulated = EMULATE_DO_DCR; +From 3751809df766c05bcce372fcfa4a886b9aaca44b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 7 Dec 2012 19:50:07 -0600 +Subject: libceph: socket can close in any connection state + +From: Alex Elder + +(cherry picked from commit 7bb21d68c535ad8be38e14a715632ae398b37ac1) + +A connection's socket can close for any reason, independent of the +state of the connection (and without irrespective of the connection +mutex). As a result, the connectino can be in pretty much any state +at the time its socket is closed. + +Handle those other cases at the top of con_work(). Pull this whole +block of code into a separate function to reduce the clutter. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 47 ++++++++++++++++++++++++++++++----------------- + 1 file changed, 30 insertions(+), 17 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2262,6 +2262,35 @@ static void queue_con(struct ceph_connec + } + } + ++static bool con_sock_closed(struct ceph_connection *con) ++{ ++ if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) ++ return false; ++ ++#define CASE(x) \ ++ case CON_STATE_ ## x: \ ++ con->error_msg = "socket closed (con state " #x ")"; \ ++ break; ++ ++ switch (con->state) { ++ CASE(CLOSED); ++ CASE(PREOPEN); ++ CASE(CONNECTING); ++ CASE(NEGOTIATING); ++ CASE(OPEN); ++ CASE(STANDBY); ++ default: ++ pr_warning("%s con %p unrecognized state %lu\n", ++ __func__, con, con->state); ++ con->error_msg = "unrecognized con state"; ++ BUG(); ++ break; ++ } ++#undef CASE ++ ++ return true; ++} ++ + /* + * Do some work on a connection. Drop a connection ref when we're done. + */ +@@ -2273,24 +2302,8 @@ static void con_work(struct work_struct + + mutex_lock(&con->mutex); + restart: +- if (test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) { +- switch (con->state) { +- case CON_STATE_CONNECTING: +- con->error_msg = "connection failed"; +- break; +- case CON_STATE_NEGOTIATING: +- con->error_msg = "negotiation failed"; +- break; +- case CON_STATE_OPEN: +- con->error_msg = "socket closed"; +- break; +- default: +- dout("unrecognized con state %d\n", (int)con->state); +- con->error_msg = "unrecognized con state"; +- BUG(); +- } ++ if (con_sock_closed(con)) + goto fault; +- } + + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { + dout("con_work %p backing off\n", con); +From 5f64737fb44ee280362a1be280f26adb38c689e4 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 14 Dec 2012 16:47:41 -0600 +Subject: libceph: report connection fault with warning + +From: Alex Elder + +(cherry picked from commit 28362986f8743124b3a0fda20a8ed3e80309cce1) + +When a connection's socket disconnects, or if there's a protocol +error of some kind on the connection, a fault is signaled and +the connection is reset (closed and reopened, basically). We +currently get an error message on the log whenever this occurs. + +A ceph connection will attempt to reestablish a socket connection +repeatedly if a fault occurs. This means that these error messages +will get repeatedly added to the log, which is undesirable. + +Change the error message to be a warning, so they don't get +logged by default. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2369,7 +2369,7 @@ fault: + static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) + { +- pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ++ pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), + ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); +From d49d943a24d4addbb5c6d1e4feb45bb98b2885fa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: init osd->o_node in create_osd() + +From: Alex Elder + +(cherry picked from commit f407731d12214e7686819018f3a1e9d7b6f83a02) + +The red-black node node in the ceph osd structure is not initialized +in create_osd(). Because this node can be the subject of a +RB_EMPTY_NODE() call later on, we should ensure the node is +initialized properly for that. Add a call to RB_CLEAR_NODE() +initialize it. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -647,6 +647,7 @@ static struct ceph_osd *create_osd(struc + atomic_set(&osd->o_ref, 1); + osd->o_osdc = osdc; + osd->o_osd = onum; ++ RB_CLEAR_NODE(&osd->o_node); + INIT_LIST_HEAD(&osd->o_requests); + INIT_LIST_HEAD(&osd->o_linger_requests); + INIT_LIST_HEAD(&osd->o_osd_lru); +From b4c0c6243efad1ae18a8aa17694952fd6c13bbaa Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: init event->node in ceph_osdc_create_event() + +From: Alex Elder + +(cherry picked from commit 3ee5234df68d253c415ba4f2db72ad250d9c21a9) + +The red-black node node in the ceph osd event structure is not +initialized in create_osdc_create_event(). Because this node can +be the subject of a RB_EMPTY_NODE() call later on, we should ensure +the node is initialized properly for that. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1600,6 +1600,7 @@ int ceph_osdc_create_event(struct ceph_o + event->data = data; + event->osdc = osdc; + INIT_LIST_HEAD(&event->osd_node); ++ RB_CLEAR_NODE(&event->node); + kref_init(&event->kref); /* one ref for us */ + kref_get(&event->kref); /* one ref for the caller */ + init_completion(&event->completion); +From f660813d76b3634c39c2b3ed8715af7e9db14f9c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 17 Dec 2012 12:23:48 -0600 +Subject: libceph: don't use rb_init_node() in ceph_osdc_alloc_request() + +From: Alex Elder + +(cherry picked from commit a978fa20fb657548561dddbfb605fe43654f0825) + +The red-black node in the ceph osd request structure is initialized +in ceph_osdc_alloc_request() using rbd_init_node(). We do need to +initialize this, because in __unregister_request() we call +RB_EMPTY_NODE(), which expects the node it's checking to have +been initialized. But rb_init_node() is apparently overkill, and +may in fact be on its way out. So use RB_CLEAR_NODE() instead. + +For a little more background, see this commit: + 4c199a93 rbtree: empty nodes have no color" + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -221,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc + kref_init(&req->r_kref); + init_completion(&req->r_completion); + init_completion(&req->r_safe_completion); ++ RB_CLEAR_NODE(&req->r_node); + INIT_LIST_HEAD(&req->r_unsafe_item); + INIT_LIST_HEAD(&req->r_linger_item); + INIT_LIST_HEAD(&req->r_linger_osd); +From c9ddd2cac5e5e9bf278a9c08976592972a2d15c1 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 07:22:04 -0600 +Subject: libceph: register request before unregister linger + +From: Alex Elder + +(cherry picked from commit c89ce05e0c5a01a256100ac6a6019f276bdd1ca6) + +In kick_requests(), we need to register the request before we +unregister the linger request. Otherwise the unregister will +reset the request's osd pointer to NULL. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1366,8 +1366,8 @@ static void kick_requests(struct ceph_os + + dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); +- __unregister_linger_request(osdc, req); + __register_request(osdc, req); ++ __unregister_linger_request(osdc, req); + } + mutex_unlock(&osdc->request_mutex); + +From d92a42b79c755e911495bd36316d2573804293ea Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 19 Dec 2012 15:52:36 -0600 +Subject: libceph: move linger requests sooner in kick_requests() + +From: Alex Elder + +(cherry picked from commit ab60b16d3c31b9bd9fd5b39f97dc42c52a50b67d) + +The kick_requests() function is called by ceph_osdc_handle_map() +when an osd map change has been indicated. Its purpose is to +re-queue any request whose target osd is different from what it +was when it was originally sent. + +It is structured as two loops, one for incomplete but registered +requests, and a second for handling completed linger requests. +As a special case, in the first loop if a request marked to linger +has not yet completed, it is moved from the request list to the +linger list. This is as a quick and dirty way to have the second +loop handle sending the request along with all the other linger +requests. + +Because of the way it's done now, however, this quick and dirty +solution can result in these incomplete linger requests never +getting re-sent as desired. The problem lies in the fact that +the second loop only arranges for a linger request to be sent +if it appears its target osd has changed. This is the proper +handling for *completed* linger requests (it avoids issuing +the same linger request twice to the same osd). + +But although the linger requests added to the list in the first loop +may have been sent, they have not yet completed, so they need to be +re-sent regardless of whether their target osd has changed. + +The first required fix is we need to avoid calling __map_request() +on any incomplete linger request. Otherwise the subsequent +__map_request() call in the second loop will find the target osd +has not changed and will therefore not re-send the request. + +Second, we need to be sure that a sent but incomplete linger request +gets re-sent. If the target osd is the same with the new osd map as +it was when the request was originally sent, this won't happen. +This can be fixed through careful handling when we move these +requests from the request list to the linger list, by unregistering +the request *before* it is registered as a linger request. This +works because a side-effect of unregistering the request is to make +the request's r_osd pointer be NULL, and *that* will ensure the +second loop actually re-sends the linger request. + +Processing of such a request is done at that point, so continue with +the next one once it's been moved. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1322,6 +1322,24 @@ static void kick_requests(struct ceph_os + for (p = rb_first(&osdc->requests); p; ) { + req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); ++ ++ /* ++ * For linger requests that have not yet been ++ * registered, move them to the linger list; they'll ++ * be sent to the osd in the loop below. Unregister ++ * the request before re-registering it as a linger ++ * request to ensure the __map_request() below ++ * will decide it needs to be sent. ++ */ ++ if (req->r_linger && list_empty(&req->r_linger_item)) { ++ dout("%p tid %llu restart on osd%d\n", ++ req, req->r_tid, ++ req->r_osd ? req->r_osd->o_osd : -1); ++ __unregister_request(osdc, req); ++ __register_linger_request(osdc, req); ++ continue; ++ } ++ + err = __map_request(osdc, req, force_resend); + if (err < 0) + continue; /* error */ +@@ -1336,17 +1354,6 @@ static void kick_requests(struct ceph_os + req->r_flags |= CEPH_OSD_FLAG_RETRY; + } + } +- if (req->r_linger && list_empty(&req->r_linger_item)) { +- /* +- * register as a linger so that we will +- * re-submit below and get a new tid +- */ +- dout("%p tid %llu restart on osd%d\n", +- req, req->r_tid, +- req->r_osd ? req->r_osd->o_osd : -1); +- __register_linger_request(osdc, req); +- __unregister_request(osdc, req); +- } + } + + list_for_each_entry_safe(req, nreq, &osdc->req_linger, +@@ -1354,6 +1361,7 @@ static void kick_requests(struct ceph_os + dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); + + err = __map_request(osdc, req, force_resend); ++ dout("__map_request returned %d\n", err); + if (err == 0) + continue; /* no change and no osd was specified */ + if (err < 0) +From 8cc1491a5d9e720f0b6f69244fc1548597bb868b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 14:31:40 -0600 +Subject: libceph: always reset osds when kicking + +From: Alex Elder + +(cherry picked from commit e6d50f67a6b1a6252a616e6e629473b5c4277218) + +When ceph_osdc_handle_map() is called to process a new osd map, +kick_requests() is called to ensure all affected requests are +updated if necessary to reflect changes in the osd map. This +happens in two cases: whenever an incremental map update is +processed; and when a full map update (or the last one if there is +more than one) gets processed. + +In the former case, the kick_requests() call is followed immediately +by a call to reset_changed_osds() to ensure any connections to osds +affected by the map change are reset. But for full map updates +this isn't done. + +Both cases should be doing this osd reset. + +Rather than duplicating the reset_changed_osds() call, move it into +the end of kick_requests(). + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -1308,7 +1308,7 @@ static void reset_changed_osds(struct ce + * Requeue requests whose mapping to an OSD has changed. If requests map to + * no osd, request a new map. + * +- * Caller should hold map_sem for read and request_mutex. ++ * Caller should hold map_sem for read. + */ + static void kick_requests(struct ceph_osd_client *osdc, int force_resend) + { +@@ -1383,6 +1383,7 @@ static void kick_requests(struct ceph_os + dout("%d requests for down osds, need new map\n", needmap); + ceph_monc_request_next_osdmap(&osdc->client->monc); + } ++ reset_changed_osds(osdc); + } + + +@@ -1439,7 +1440,6 @@ void ceph_osdc_handle_map(struct ceph_os + osdc->osdmap = newmap; + } + kick_requests(osdc, 0); +- reset_changed_osds(osdc); + } else { + dout("ignoring incremental map %u len %d\n", + epoch, maplen); +From b95ad0140dc8d2375bff4b0f30f6832cbb29e17c Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 26 Dec 2012 10:43:57 -0600 +Subject: libceph: WARN, don't BUG on unexpected connection states + +From: Alex Elder + +(cherry picked from commit 122070a2ffc91f87fe8e8493eb0ac61986c5557c) + +A number of assertions in the ceph messenger are implemented with +BUG_ON(), killing the system if connection's state doesn't match +what's expected. At this point our state model is (evidently) not +well understood enough for these assertions to trigger a BUG(). +Convert all BUG_ON(con->state...) calls to be WARN_ON(con->state...) +so we learn about these issues without killing the machine. + +We now recognize that a connection fault can occur due to a socket +closure at any time, regardless of the state of the connection. So +there is really nothing we can assert about the state of the +connection at that point so eliminate that assertion. + +Reported-by: Ugis +Tested-by: Ugis +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -561,7 +561,7 @@ void ceph_con_open(struct ceph_connectio + mutex_lock(&con->mutex); + dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); + +- BUG_ON(con->state != CON_STATE_CLOSED); ++ WARN_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; + + con->peer_name.type = (__u8) entity_type; +@@ -1509,7 +1509,7 @@ static int process_banner(struct ceph_co + static void fail_protocol(struct ceph_connection *con) + { + reset_connection(con); +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_CLOSED; + } + +@@ -1635,7 +1635,7 @@ static int process_connect(struct ceph_c + return -1; + } + +- BUG_ON(con->state != CON_STATE_NEGOTIATING); ++ WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); +@@ -2132,7 +2132,6 @@ more: + if (ret < 0) + goto out; + +- BUG_ON(con->state != CON_STATE_CONNECTING); + con->state = CON_STATE_NEGOTIATING; + + /* +@@ -2160,7 +2159,7 @@ more: + goto more; + } + +- BUG_ON(con->state != CON_STATE_OPEN); ++ WARN_ON(con->state != CON_STATE_OPEN); + + if (con->in_base_pos < 0) { + /* +@@ -2374,7 +2373,7 @@ static void ceph_fault(struct ceph_conne + dout("fault %p state %lu to peer %s\n", + con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); + +- BUG_ON(con->state != CON_STATE_CONNECTING && ++ WARN_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); + +From 48e858340dae43189a4e55647f6eac736766f828 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Mon, 7 Jan 2013 10:27:13 +0100 +Subject: Revert "drm/i915: no lvds quirk for Zotac ZDBOX SD ID12/ID13" + +From: Daniel Vetter + +commit 48e858340dae43189a4e55647f6eac736766f828 upstream. + +This reverts commit 9756fe38d10b2bf90c81dc4d2f17d5632e135364. + +The bogus lvds output is actually a lvds->hdmi bridge, which we don't +really support. But unconditionally disabling it breaks some existing +setups. + +Reported-by: John Tapsell +References: http://permalink.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/17237 +Signed-off-by: Daniel Vetter +Cc: Luis Henriques +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/gpu/drm/i915/intel_lvds.c | 8 -------- + 1 file changed, 8 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -763,14 +763,6 @@ static const struct dmi_system_id intel_ + }, + { + .callback = intel_no_lvds_dmi_callback, +- .ident = "ZOTAC ZBOXSD-ID12/ID13", +- .matches = { +- DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), +- DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), +- }, +- }, +- { +- .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), +From f10a18433a1b3192e71eecffeaeca5f5f1694016 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Thu, 27 Dec 2012 20:27:04 -0600 +Subject: libceph: fix protocol feature mismatch failure path + + +From: Sage Weil + +(cherry picked from commit 0fa6ebc600bc8e830551aee47a0e929e818a1868) + +We should not set con->state to CLOSED here; that happens in +ceph_fault() in the caller, where it first asserts that the state +is not yet CLOSED. Avoids a BUG when the features don't match. + +Since the fail_protocol() has become a trivial wrapper, replace +calls to it with direct calls to reset_connection(). + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/messenger.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -506,6 +506,7 @@ static void reset_connection(struct ceph + { + /* reset connection, out_queue, msg_ and connect_seq */ + /* discard existing out_queue and msg_seq */ ++ dout("reset_connection %p\n", con); + ceph_msg_remove_list(&con->out_queue); + ceph_msg_remove_list(&con->out_sent); + +@@ -1506,13 +1507,6 @@ static int process_banner(struct ceph_co + return 0; + } + +-static void fail_protocol(struct ceph_connection *con) +-{ +- reset_connection(con); +- WARN_ON(con->state != CON_STATE_NEGOTIATING); +- con->state = CON_STATE_CLOSED; +-} +- + static int process_connect(struct ceph_connection *con) + { + u64 sup_feat = con->msgr->supported_features; +@@ -1530,7 +1524,7 @@ static int process_connect(struct ceph_c + ceph_pr_addr(&con->peer_addr.in_addr), + sup_feat, server_feat, server_feat & ~sup_feat); + con->error_msg = "missing required protocol features"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + + case CEPH_MSGR_TAG_BADPROTOVER: +@@ -1541,7 +1535,7 @@ static int process_connect(struct ceph_c + le32_to_cpu(con->out_connect.protocol_version), + le32_to_cpu(con->in_reply.protocol_version)); + con->error_msg = "protocol version mismatch"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + + case CEPH_MSGR_TAG_BADAUTHORIZER: +@@ -1631,7 +1625,7 @@ static int process_connect(struct ceph_c + ceph_pr_addr(&con->peer_addr.in_addr), + req_feat, server_feat, req_feat & ~server_feat); + con->error_msg = "missing required protocol features"; +- fail_protocol(con); ++ reset_connection(con); + return -1; + } + +From 71630f053c8da3b7d8e52c99ff2592f44dd28979 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Mon, 29 Oct 2012 11:01:42 -0700 +Subject: libceph: fix osdmap decode error paths + + +From: Sage Weil + +(cherry picked from commit 0ed7285e0001b960c888e5455ae982025210ed3d) + +Ensure that we set the err value correctly so that we do not pass a 0 +value to ERR_PTR and confuse the calling code. (In particular, +osd_client.c handle_map() will BUG(!newmap)). + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osdmap.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/net/ceph/osdmap.c ++++ b/net/ceph/osdmap.c +@@ -645,10 +645,12 @@ struct ceph_osdmap *osdmap_decode(void * + ceph_decode_32_safe(p, end, max, bad); + while (max--) { + ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); ++ err = -ENOMEM; + pi = kzalloc(sizeof(*pi), GFP_NOFS); + if (!pi) + goto bad; + pi->id = ceph_decode_32(p); ++ err = -EINVAL; + ev = ceph_decode_8(p); /* encoding version */ + if (ev > CEPH_PG_POOL_VERSION) { + pr_warning("got unknown v %d > %d of ceph_pg_pool\n", +@@ -664,8 +666,13 @@ struct ceph_osdmap *osdmap_decode(void * + __insert_pg_pool(&map->pg_pools, pi); + } + +- if (version >= 5 && __decode_pool_names(p, end, map) < 0) +- goto bad; ++ if (version >= 5) { ++ err = __decode_pool_names(p, end, map); ++ if (err < 0) { ++ dout("fail to decode pool names"); ++ goto bad; ++ } ++ } + + ceph_decode_32_safe(p, end, map->pool_max, bad); + +@@ -745,7 +752,7 @@ struct ceph_osdmap *osdmap_decode(void * + return map; + + bad: +- dout("osdmap_decode fail\n"); ++ dout("osdmap_decode fail err %d\n", err); + ceph_osdmap_destroy(map); + return ERR_PTR(err); + } +@@ -839,6 +846,7 @@ struct ceph_osdmap *osdmap_apply_increme + if (ev > CEPH_PG_POOL_VERSION) { + pr_warning("got unknown v %d > %d of ceph_pg_pool\n", + ev, CEPH_PG_POOL_VERSION); ++ err = -EINVAL; + goto bad; + } + pi = __lookup_pg_pool(&map->pg_pools, pool); +@@ -855,8 +863,11 @@ struct ceph_osdmap *osdmap_apply_increme + if (err < 0) + goto bad; + } +- if (version >= 5 && __decode_pool_names(p, end, map) < 0) +- goto bad; ++ if (version >= 5) { ++ err = __decode_pool_names(p, end, map); ++ if (err < 0) ++ goto bad; ++ } + + /* old_pool */ + ceph_decode_32_safe(p, end, len, bad); +@@ -932,15 +943,13 @@ struct ceph_osdmap *osdmap_apply_increme + (void) __remove_pg_mapping(&map->pg_temp, pgid); + + /* insert */ +- if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) { +- err = -EINVAL; ++ err = -EINVAL; ++ if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; +- } ++ err = -ENOMEM; + pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); +- if (!pg) { +- err = -ENOMEM; ++ if (!pg) + goto bad; +- } + pg->pgid = pgid; + pg->len = pglen; + for (j = 0; j < pglen; j++) +From f4a3fea610cb6a9fc9cb722a0765194e19b82e7b Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 7 Dec 2012 09:57:58 -0600 +Subject: libceph: avoid using freed osd in __kick_osd_requests() + + +From: Alex Elder + +(cherry picked from commit 685a7555ca69030739ddb57a47f0ea8ea80196a4) + +If an osd has no requests and no linger requests, __reset_osd() +will just remove it with a call to __remove_osd(). That drops +a reference to the osd, and therefore the osd may have been free +by the time __reset_osd() returns. That function offers no +indication this may have occurred, and as a result the osd will +continue to be used even when it's no longer valid. + +Change__reset_osd() so it returns an error (ENODEV) when it +deletes the osd being reset. And change __kick_osd_requests() so it +returns immediately (before referencing osd again) if __reset_osd() +returns *any* error. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -581,7 +581,7 @@ static void __kick_osd_requests(struct c + + dout("__kick_osd_requests osd%d\n", osd->o_osd); + err = __reset_osd(osdc, osd); +- if (err == -EAGAIN) ++ if (err) + return; + + list_for_each_entry(req, &osd->o_requests, r_osd_item) { +@@ -752,6 +752,7 @@ static int __reset_osd(struct ceph_osd_c + if (list_empty(&osd->o_requests) && + list_empty(&osd->o_linger_requests)) { + __remove_osd(osdc, osd); ++ ret = -ENODEV; + } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], + &osd->o_con.peer_addr, + sizeof(osd->o_con.peer_addr)) == 0 && +From aa852ff17166b53b1d29388af472bb9c32297f05 Mon Sep 17 00:00:00 2001 +From: Sage Weil +Date: Wed, 28 Nov 2012 12:28:24 -0800 +Subject: libceph: remove 'osdtimeout' option + + +From: Sage Weil + +(cherry picked from commit 83aff95eb9d60aff5497e9f44a2ae906b86d8e88) + +This would reset a connection with any OSD that had an outstanding +request that was taking more than N seconds. The idea was that if the +OSD was buggy, the client could compensate by resending the request. + +In reality, this only served to hide server bugs, and we haven't +actually seen such a bug in quite a while. Moreover, the userspace +client code never did this. + +More importantly, often the request is taking a long time because the +OSD is trying to recover, or overloaded, and killing the connection +and retrying would only make the situation worse by giving the OSD +more work to do. + +Signed-off-by: Sage Weil +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/super.c | 2 - + include/linux/ceph/libceph.h | 2 - + net/ceph/ceph_common.c | 3 -- + net/ceph/osd_client.c | 47 +++---------------------------------------- + 4 files changed, 5 insertions(+), 49 deletions(-) + +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -403,8 +403,6 @@ static int ceph_show_options(struct seq_ + seq_printf(m, ",mount_timeout=%d", opt->mount_timeout); + if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) + seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl); +- if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT) +- seq_printf(m, ",osdtimeout=%d", opt->osd_timeout); + if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) + seq_printf(m, ",osdkeepalivetimeout=%d", + opt->osd_keepalive_timeout); +--- a/include/linux/ceph/libceph.h ++++ b/include/linux/ceph/libceph.h +@@ -43,7 +43,6 @@ struct ceph_options { + struct ceph_entity_addr my_addr; + int mount_timeout; + int osd_idle_ttl; +- int osd_timeout; + int osd_keepalive_timeout; + + /* +@@ -63,7 +62,6 @@ struct ceph_options { + * defaults + */ + #define CEPH_MOUNT_TIMEOUT_DEFAULT 60 +-#define CEPH_OSD_TIMEOUT_DEFAULT 60 /* seconds */ + #define CEPH_OSD_KEEPALIVE_DEFAULT 5 + #define CEPH_OSD_IDLE_TTL_DEFAULT 60 + +--- a/net/ceph/ceph_common.c ++++ b/net/ceph/ceph_common.c +@@ -305,7 +305,6 @@ ceph_parse_options(char *options, const + + /* start with defaults */ + opt->flags = CEPH_OPT_DEFAULT; +- opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; + opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; + opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ + opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ +@@ -391,7 +390,7 @@ ceph_parse_options(char *options, const + + /* misc */ + case Opt_osdtimeout: +- opt->osd_timeout = intval; ++ pr_warning("ignoring deprecated osdtimeout option\n"); + break; + case Opt_osdkeepalivetimeout: + opt->osd_keepalive_timeout = intval; +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -608,14 +608,6 @@ static void __kick_osd_requests(struct c + } + } + +-static void kick_osd_requests(struct ceph_osd_client *osdc, +- struct ceph_osd *kickosd) +-{ +- mutex_lock(&osdc->request_mutex); +- __kick_osd_requests(osdc, kickosd); +- mutex_unlock(&osdc->request_mutex); +-} +- + /* + * If the osd connection drops, we need to resubmit all requests. + */ +@@ -629,7 +621,9 @@ static void osd_reset(struct ceph_connec + dout("osd_reset osd%d\n", osd->o_osd); + osdc = osd->o_osdc; + down_read(&osdc->map_sem); +- kick_osd_requests(osdc, osd); ++ mutex_lock(&osdc->request_mutex); ++ __kick_osd_requests(osdc, osd); ++ mutex_unlock(&osdc->request_mutex); + send_queued(osdc); + up_read(&osdc->map_sem); + } +@@ -1093,12 +1087,10 @@ static void handle_timeout(struct work_s + { + struct ceph_osd_client *osdc = + container_of(work, struct ceph_osd_client, timeout_work.work); +- struct ceph_osd_request *req, *last_req = NULL; ++ struct ceph_osd_request *req; + struct ceph_osd *osd; +- unsigned long timeout = osdc->client->options->osd_timeout * HZ; + unsigned long keepalive = + osdc->client->options->osd_keepalive_timeout * HZ; +- unsigned long last_stamp = 0; + struct list_head slow_osds; + dout("timeout\n"); + down_read(&osdc->map_sem); +@@ -1108,37 +1100,6 @@ static void handle_timeout(struct work_s + mutex_lock(&osdc->request_mutex); + + /* +- * reset osds that appear to be _really_ unresponsive. this +- * is a failsafe measure.. we really shouldn't be getting to +- * this point if the system is working properly. the monitors +- * should mark the osd as failed and we should find out about +- * it from an updated osd map. +- */ +- while (timeout && !list_empty(&osdc->req_lru)) { +- req = list_entry(osdc->req_lru.next, struct ceph_osd_request, +- r_req_lru_item); +- +- /* hasn't been long enough since we sent it? */ +- if (time_before(jiffies, req->r_stamp + timeout)) +- break; +- +- /* hasn't been long enough since it was acked? */ +- if (req->r_request->ack_stamp == 0 || +- time_before(jiffies, req->r_request->ack_stamp + timeout)) +- break; +- +- BUG_ON(req == last_req && req->r_stamp == last_stamp); +- last_req = req; +- last_stamp = req->r_stamp; +- +- osd = req->r_osd; +- BUG_ON(!osd); +- pr_warning(" tid %llu timed out on osd%d, will reset osd\n", +- req->r_tid, osd->o_osd); +- __kick_osd_requests(osdc, osd); +- } +- +- /* + * ping osds that are a bit slow. this ensures that if there + * is a break in the TCP connection we will notice, and reopen + * a connection with that osd (from the fault callback). +From a6bbcd6741d53b326a2a3a7edef6e15334de6ea3 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 29 Nov 2012 08:37:03 -0600 +Subject: ceph: don't reference req after put + + +From: Alex Elder + +(cherry picked from commit 7d5f24812bd182a2471cb69c1c2baf0648332e1f) + +In __unregister_request(), there is a call to list_del_init() +referencing a request that was the subject of a call to +ceph_osdc_put_request() on the previous line. This is not +safe, because the request structure could have been freed +by the time we reach the list_del_init(). + +Fix this by reversing the order of these lines. + +Signed-off-by: Alex Elder +Reviewed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -873,9 +873,9 @@ static void __unregister_request(struct + req->r_osd = NULL; + } + ++ list_del_init(&req->r_req_lru_item); + ceph_osdc_put_request(req); + +- list_del_init(&req->r_req_lru_item); + if (osdc->num_requests == 0) { + dout(" no requests, canceling timeout\n"); + __cancel_osd_timeout(osdc); +From 8824d0eb9dee3bad29e9dba796d5d7953cab6719 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 10 Oct 2012 21:19:13 -0700 +Subject: rbd: fix bug in rbd_dev_id_put() + + +From: Alex Elder + +(cherry picked from commit b213e0b1a62637b2a9395a34349b13d73ca2b90a) + +In rbd_dev_id_put(), there's a loop that's intended to determine +the maximum device id in use. But it isn't doing that at all, +the effect of how it's written is to simply use the just-put id +number, which ignores whole purpose of this function. + +Fix the bug. + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -2621,8 +2621,8 @@ static void rbd_dev_id_put(struct rbd_de + struct rbd_device *rbd_dev; + + rbd_dev = list_entry(tmp, struct rbd_device, node); +- if (rbd_id > max_id) +- max_id = rbd_id; ++ if (rbd_dev->dev_id > max_id) ++ max_id = rbd_dev->dev_id; + } + spin_unlock(&rbd_dev_list_lock); + +From cc8b5fcd343b3c99468fc9f0b4c3e03a7eafa7fc Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Wed, 10 Oct 2012 21:19:13 -0700 +Subject: rbd: zero return code in rbd_dev_image_id() + + +From: Alex Elder + +(cherry picked from commit a0ea3a40fd20b8c66381f747c454f89d6d1f50d4) + +When rbd_dev_probe() calls rbd_dev_image_id() it expects to get +a 0 return code if successful, but it is getting a positive value. + +The reason is that rbd_dev_image_id() returns the value it gets from +rbd_req_sync_exec(), which returns the number of bytes read in as a +result of the request. (This ultimately comes from +ceph_copy_from_page_vector() in rbd_req_sync_op()). + +Force the return value to 0 when successful in rbd_dev_image_id(). +Do the same in rbd_dev_v2_object_prefix(). + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Reviewed-by: Dan Mick +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -2189,6 +2189,7 @@ static int rbd_dev_v2_object_prefix(stru + dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); + if (ret < 0) + goto out; ++ ret = 0; /* rbd_req_sync_exec() can return positive */ + + p = reply_buf; + rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p, +@@ -2841,6 +2842,7 @@ static int rbd_dev_image_id(struct rbd_d + dout("%s: rbd_req_sync_exec returned %d\n", __func__, ret); + if (ret < 0) + goto out; ++ ret = 0; /* rbd_req_sync_exec() can return positive */ + + p = response; + rbd_dev->image_id = ceph_extract_encoded_string(&p, +From 9aca7b487cf1c996a13ff5abf0ea4ac560ea1dd4 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Mon, 22 Oct 2012 11:31:26 -0500 +Subject: rbd: fix read-only option name + + +From: Alex Elder + +(cherry picked from commit be466c1cc36621590ef17b05a6d342dfd33f7280) + +The name of the "read-only" mapping option was inadvertently changed +in this commit: + + f84344f3 rbd: separate mapping info in rbd_dev + +Revert that hunk to return it to what it should be. + +Signed-off-by: Alex Elder +Reviewed-by: Dan Mick +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -388,7 +388,7 @@ enum { + static match_table_t rbd_opts_tokens = { + /* int args above */ + /* string args above */ +- {Opt_read_only, "mapping.read_only"}, ++ {Opt_read_only, "read_only"}, + {Opt_read_only, "ro"}, /* Alternate spelling */ + {Opt_read_write, "read_write"}, + {Opt_read_write, "rw"}, /* Alternate spelling */ +From 1306be442fda1b7a92b879ab18a535f56da5ab0a Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Tue, 3 Jul 2012 16:01:19 -0500 +Subject: rbd: increase maximum snapshot name length + + +From: Alex Elder + +(cherry picked from commit d4b125e9eb43babd14538ba61718e3db71a98d29) + +Change RBD_MAX_SNAP_NAME_LEN to be based on NAME_MAX. That is a +practical limit for the length of a snapshot name (based on the +presence of a directory using the name under /sys/bus/rbd to +represent the snapshot). + +The /sys entry is created by prefixing it with "snap_"; define that +prefix symbolically, and take its length into account in defining +the snapshot name length limit. + +Enforce the limit in rbd_add_parse_args(). Also delete a dout() +call in that function that was not meant to be committed. + +Signed-off-by: Alex Elder +Reviewed-by: Dan Mick +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -61,7 +61,10 @@ + + #define RBD_MINORS_PER_MAJOR 256 /* max minors per blkdev */ + +-#define RBD_MAX_SNAP_NAME_LEN 32 ++#define RBD_SNAP_DEV_NAME_PREFIX "snap_" ++#define RBD_MAX_SNAP_NAME_LEN \ ++ (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1)) ++ + #define RBD_MAX_SNAP_COUNT 510 /* allows max snapc to fit in 4KB */ + #define RBD_MAX_OPT_LEN 1024 + +@@ -2073,7 +2076,7 @@ static int rbd_register_snap_dev(struct + dev->type = &rbd_snap_device_type; + dev->parent = parent; + dev->release = rbd_snap_dev_release; +- dev_set_name(dev, "snap_%s", snap->name); ++ dev_set_name(dev, "%s%s", RBD_SNAP_DEV_NAME_PREFIX, snap->name); + dout("%s: registering device for snapshot %s\n", __func__, snap->name); + + ret = device_register(dev); +@@ -2766,8 +2769,13 @@ static char *rbd_add_parse_args(struct r + if (!rbd_dev->image_name) + goto out_err; + +- /* Snapshot name is optional */ ++ /* Snapshot name is optional; default is to use "head" */ ++ + len = next_token(&buf); ++ if (len > RBD_MAX_SNAP_NAME_LEN) { ++ err_ptr = ERR_PTR(-ENAMETOOLONG); ++ goto out_err; ++ } + if (!len) { + buf = RBD_SNAP_HEAD_NAME; /* No snapshot supplied */ + len = sizeof (RBD_SNAP_HEAD_NAME) - 1; +@@ -2778,8 +2786,6 @@ static char *rbd_add_parse_args(struct r + memcpy(snap_name, buf, len); + *(snap_name + len) = '\0'; + +-dout(" SNAP_NAME is <%s>, len is %zd\n", snap_name, len); +- + return snap_name; + + out_err: +From 21bc037520c252304c04d3bb8131fb3d4ba5b2c5 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 25 Oct 2012 23:34:40 -0500 +Subject: rbd: remove snapshots on error in rbd_add() + + +From: Alex Elder + +(cherry picked from commit 41f38c2b2f8b66b176a0e548ef06294343a7bfa2) + +If rbd_dev_snaps_update() has ever been called for an rbd device +structure there could be snapshot structures on its snaps list. +In rbd_add(), this function is called but a subsequent error +path neglected to clean up any of these snapshots. + +Add a call to rbd_remove_all_snaps() in the appropriate spot to +remedy this. Change a couple of error labels to be a little +clearer while there. + +Drop the leading underscores from the function name; there's nothing +special about that function that they might signify. As suggested +in review, the leading underscores in __rbd_remove_snap_dev() have +been removed as well. + +Signed-off-by: Alex Elder +Reviewed-by: Josh Durgin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -221,7 +221,7 @@ static int rbd_dev_snaps_update(struct r + static int rbd_dev_snaps_register(struct rbd_device *rbd_dev); + + static void rbd_dev_release(struct device *dev); +-static void __rbd_remove_snap_dev(struct rbd_snap *snap); ++static void rbd_remove_snap_dev(struct rbd_snap *snap); + + static ssize_t rbd_add(struct bus_type *bus, const char *buf, + size_t count); +@@ -1710,13 +1710,13 @@ static int rbd_read_header(struct rbd_de + return ret; + } + +-static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) ++static void rbd_remove_all_snaps(struct rbd_device *rbd_dev) + { + struct rbd_snap *snap; + struct rbd_snap *next; + + list_for_each_entry_safe(snap, next, &rbd_dev->snaps, node) +- __rbd_remove_snap_dev(snap); ++ rbd_remove_snap_dev(snap); + } + + /* +@@ -2060,7 +2060,7 @@ static bool rbd_snap_registered(struct r + return ret; + } + +-static void __rbd_remove_snap_dev(struct rbd_snap *snap) ++static void rbd_remove_snap_dev(struct rbd_snap *snap) + { + list_del(&snap->node); + if (device_is_registered(&snap->dev)) +@@ -2442,7 +2442,7 @@ static int rbd_dev_snaps_update(struct r + + if (rbd_dev->mapping.snap_id == snap->id) + rbd_dev->mapping.snap_exists = false; +- __rbd_remove_snap_dev(snap); ++ rbd_remove_snap_dev(snap); + dout("%ssnap id %llu has been removed\n", + rbd_dev->mapping.snap_id == snap->id ? + "mapped " : "", +@@ -3053,11 +3053,11 @@ static ssize_t rbd_add(struct bus_type * + /* no need to lock here, as rbd_dev is not registered yet */ + rc = rbd_dev_snaps_update(rbd_dev); + if (rc) +- goto err_out_header; ++ goto err_out_probe; + + rc = rbd_dev_set_mapping(rbd_dev, snap_name); + if (rc) +- goto err_out_header; ++ goto err_out_snaps; + + /* generate unique id: find highest unique id, add one */ + rbd_dev_id_get(rbd_dev); +@@ -3121,7 +3121,9 @@ err_out_blkdev: + unregister_blkdev(rbd_dev->major, rbd_dev->name); + err_out_id: + rbd_dev_id_put(rbd_dev); +-err_out_header: ++err_out_snaps: ++ rbd_remove_all_snaps(rbd_dev); ++err_out_probe: + rbd_header_free(&rbd_dev->header); + err_out_client: + kfree(rbd_dev->header_name); +@@ -3219,7 +3221,7 @@ static ssize_t rbd_remove(struct bus_typ + goto done; + } + +- __rbd_remove_all_snaps(rbd_dev); ++ rbd_remove_all_snaps(rbd_dev); + rbd_bus_del_dev(rbd_dev); + + done: +From 730406993ec6d044a81115fc19091ba6abfcbb15 Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 16 Nov 2012 09:29:16 -0600 +Subject: rbd: do not allow remove of mounted-on image + + +From: Alex Elder + +(cherry picked from commit 42382b709bd1d143b9f0fa93e0a3a1f2f4210707) + +There is no check in rbd_remove() to see if anybody holds open the +image being removed. That's not cool. + +Add a simple open count that goes up and down with opens and closes +(releases) of the device, and don't allow an rbd image to be removed +if the count is non-zero. + +Protect the updates of the open count value with ctl_mutex to ensure +the underlying rbd device doesn't get removed while concurrently +being opened. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -207,6 +207,7 @@ struct rbd_device { + + /* sysfs related */ + struct device dev; ++ unsigned long open_count; + }; + + static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ +@@ -280,8 +281,11 @@ static int rbd_open(struct block_device + if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only) + return -EROFS; + ++ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->mapping.read_only); ++ rbd_dev->open_count++; ++ mutex_unlock(&ctl_mutex); + + return 0; + } +@@ -290,7 +294,11 @@ static int rbd_release(struct gendisk *d + { + struct rbd_device *rbd_dev = disk->private_data; + ++ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); ++ rbd_assert(rbd_dev->open_count > 0); ++ rbd_dev->open_count--; + rbd_put_dev(rbd_dev); ++ mutex_unlock(&ctl_mutex); + + return 0; + } +@@ -3221,6 +3229,11 @@ static ssize_t rbd_remove(struct bus_typ + goto done; + } + ++ if (rbd_dev->open_count) { ++ ret = -EBUSY; ++ goto done; ++ } ++ + rbd_remove_all_snaps(rbd_dev); + rbd_bus_del_dev(rbd_dev); + +From 965f03ad3d796d03ec16f9809cb0096a64f6523d Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Fri, 9 Nov 2012 15:05:54 -0600 +Subject: rbd: get rid of RBD_MAX_SEG_NAME_LEN + + +From: Alex Elder + +(cherry picked from commit 2fd82b9e92c2a718ae81fc987b4468ceeee6979b) + +RBD_MAX_SEG_NAME_LEN represents the maximum length of an rbd object +name (i.e., one of the objects providing storage backing an rbd +image). + +Another symbol, MAX_OBJ_NAME_SIZE, is used in the osd client code to +define the maximum length of any object name in an osd request. + +Right now they disagree, with RBD_MAX_SEG_NAME_LEN being too big. + +There's no real benefit at this point to defining the rbd object +name length limit separate from any other object name, so just +get rid of RBD_MAX_SEG_NAME_LEN and use MAX_OBJ_NAME_SIZE in its +place. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + drivers/block/rbd.c | 6 +++--- + drivers/block/rbd_types.h | 2 -- + 2 files changed, 3 insertions(+), 5 deletions(-) + +--- a/drivers/block/rbd.c ++++ b/drivers/block/rbd.c +@@ -706,13 +706,13 @@ static char *rbd_segment_name(struct rbd + u64 segment; + int ret; + +- name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO); ++ name = kmalloc(MAX_OBJ_NAME_SIZE + 1, GFP_NOIO); + if (!name) + return NULL; + segment = offset >> rbd_dev->header.obj_order; +- ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx", ++ ret = snprintf(name, MAX_OBJ_NAME_SIZE + 1, "%s.%012llx", + rbd_dev->header.object_prefix, segment); +- if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) { ++ if (ret < 0 || ret > MAX_OBJ_NAME_SIZE) { + pr_err("error formatting segment name for #%llu (%d)\n", + segment, ret); + kfree(name); +--- a/drivers/block/rbd_types.h ++++ b/drivers/block/rbd_types.h +@@ -46,8 +46,6 @@ + #define RBD_MIN_OBJ_ORDER 16 + #define RBD_MAX_OBJ_ORDER 30 + +-#define RBD_MAX_SEG_NAME_LEN 128 +- + #define RBD_COMP_NONE 0 + #define RBD_CRYPT_NONE 0 + +From 942784e7a6e2ef8f861043f65b054eb3ef10b2fd Mon Sep 17 00:00:00 2001 +From: Alex Elder +Date: Thu, 6 Dec 2012 09:37:23 -0600 +Subject: rbd: remove linger unconditionally + + +From: Alex Elder + +(cherry picked from commit 61c74035626beb25a39b0273ccf7d75510bc36a1) + +In __unregister_linger_request(), the request is being removed +from the osd client's req_linger list only when the request +has a non-null osd pointer. It should be done whether or not +the request currently has an osd. + +This is most likely a non-issue because I believe the request +will always have an osd when this function is called. + +Signed-off-by: Alex Elder +Reviewed-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + net/ceph/osd_client.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ceph/osd_client.c ++++ b/net/ceph/osd_client.c +@@ -907,8 +907,8 @@ static void __unregister_linger_request( + struct ceph_osd_request *req) + { + dout("__unregister_linger_request %p\n", req); ++ list_del_init(&req->r_linger_item); + if (req->r_osd) { +- list_del_init(&req->r_linger_item); + list_del_init(&req->r_linger_osd); + + if (list_empty(&req->r_osd->o_requests) && +From 76c834d784c36bda3a8d56f5cdf3e1282b0979f9 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:04 +0800 +Subject: ceph: Don't update i_max_size when handling non-auth cap + + +From: "Yan, Zheng" + +(cherry picked from commit 5e62ad30157d0da04cf40c6d1a2f4bc840948b9c) + +The cap from non-auth mds doesn't have a meaningful max_size value. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2388,7 +2388,7 @@ static void handle_cap_grant(struct inod + &atime); + + /* max size increase? */ +- if (max_size != ci->i_max_size) { ++ if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { + dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); + ci->i_max_size = max_size; + if (max_size >= ci->i_wanted_max_size) { +From 0fd2af5e838e87cf449c657b6e19535b64da6c4c Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:06 +0800 +Subject: ceph: Fix infinite loop in __wake_requests + + +From: "Yan, Zheng" + +(cherry picked from commit ed75ec2cd19b47efcd292b6e23f58e56f4c5bc34) + +__wake_requests() will enter infinite loop if we use it to wake +requests in the session->s_waiting list. __wake_requests() deletes +requests from the list and __do_request() adds requests back to +the list. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/mds_client.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -1876,9 +1876,14 @@ finish: + static void __wake_requests(struct ceph_mds_client *mdsc, + struct list_head *head) + { +- struct ceph_mds_request *req, *nreq; ++ struct ceph_mds_request *req; ++ LIST_HEAD(tmp_list); + +- list_for_each_entry_safe(req, nreq, head, r_wait) { ++ list_splice_init(head, &tmp_list); ++ ++ while (!list_empty(&tmp_list)) { ++ req = list_entry(tmp_list.next, ++ struct ceph_mds_request, r_wait); + list_del_init(&req->r_wait); + __do_request(mdsc, req); + } +From f409f158fb190ab9915fd94dce367e462a0c02f6 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:07 +0800 +Subject: ceph: Don't add dirty inode to dirty list if caps is in migration + + +From: "Yan, Zheng" + +(cherry picked from commit 0685235ffd9dbdb9ccbda587f8a3c83ad1d5a921) + +Add dirty inode to cap_dirty_migrating list instead, this can avoid +ceph_flush_dirty_caps() entering infinite loop. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_i + if (!ci->i_head_snapc) + ci->i_head_snapc = ceph_get_snap_context( + ci->i_snap_realm->cached_context); +- dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode, +- ci->i_head_snapc); ++ dout(" inode %p now dirty snapc %p auth cap %p\n", ++ &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); + BUG_ON(!list_empty(&ci->i_dirty_item)); + spin_lock(&mdsc->cap_dirty_lock); +- list_add(&ci->i_dirty_item, &mdsc->cap_dirty); ++ if (ci->i_auth_cap) ++ list_add(&ci->i_dirty_item, &mdsc->cap_dirty); ++ else ++ list_add(&ci->i_dirty_item, ++ &mdsc->cap_dirty_migrating); + spin_unlock(&mdsc->cap_dirty_lock); + if (ci->i_flushing_caps == 0) { + ihold(inode); +From 0e6789acaba2e40768a778a1e553c92723a19a30 Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:08 +0800 +Subject: ceph: Fix __ceph_do_pending_vmtruncate + + +From: "Yan, Zheng" + +(cherry picked from commit a85f50b6ef93fbbb2ae932ce9b2376509d172796) + +we should set i_truncate_pending to 0 after page cache is truncated +to i_truncate_size + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/inode.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -1466,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct + { + struct ceph_inode_info *ci = ceph_inode(inode); + u64 to; +- int wrbuffer_refs, wake = 0; ++ int wrbuffer_refs, finish = 0; + + retry: + spin_lock(&ci->i_ceph_lock); +@@ -1498,15 +1498,18 @@ retry: + truncate_inode_pages(inode->i_mapping, to); + + spin_lock(&ci->i_ceph_lock); +- ci->i_truncate_pending--; +- if (ci->i_truncate_pending == 0) +- wake = 1; ++ if (to == ci->i_truncate_size) { ++ ci->i_truncate_pending = 0; ++ finish = 1; ++ } + spin_unlock(&ci->i_ceph_lock); ++ if (!finish) ++ goto retry; + + if (wrbuffer_refs == 0) + ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); +- if (wake) +- wake_up_all(&ci->i_cap_wq); ++ ++ wake_up_all(&ci->i_cap_wq); + } + + +From 0747d15ddb5eac0e83376e2722e3654ae01d252f Mon Sep 17 00:00:00 2001 +From: "Yan, Zheng" +Date: Mon, 19 Nov 2012 10:49:09 +0800 +Subject: ceph: call handle_cap_grant() for cap import message + + +From: "Yan, Zheng" + +(cherry picked from commit 0e5e1774a92e6fe9c511585de8f078b4c4c68dbb) + +If client sends cap message that requests new max size during +exporting caps, the exporting MDS will drop the message quietly. +So the client may wait for the reply that updates the max size +forever. call handle_cap_grant() for cap import message can +avoid this issue. + +Signed-off-by: Yan, Zheng +Signed-off-by: Sage Weil +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/caps.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2749,6 +2749,7 @@ static void handle_cap_import(struct cep + + /* make sure we re-request max_size, if necessary */ + spin_lock(&ci->i_ceph_lock); ++ ci->i_wanted_max_size = 0; /* reset */ + ci->i_requested_max_size = 0; + spin_unlock(&ci->i_ceph_lock); + } +@@ -2844,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_se + case CEPH_CAP_OP_IMPORT: + handle_cap_import(mdsc, inode, h, session, + snaptrace, snaptrace_len); +- ceph_check_caps(ceph_inode(inode), 0, session); +- goto done_unlocked; + } + + /* the rest require a cap */ +@@ -2862,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_se + switch (op) { + case CEPH_CAP_OP_REVOKE: + case CEPH_CAP_OP_GRANT: ++ case CEPH_CAP_OP_IMPORT: + handle_cap_grant(inode, h, session, cap, msg->middle); + goto done_unlocked; + +From 9fa5ba96f32fbea354457fc7ece06b2ee81b1b71 Mon Sep 17 00:00:00 2001 +From: David Zafman +Date: Mon, 3 Dec 2012 19:14:05 -0800 +Subject: libceph: Unlock unprocessed pages in start_read() error path + + +From: David Zafman + +(cherry picked from commit 8884d53dd63b1d9315b343564fcbe1ede004a99e) + +Function start_read() can get an error before processing all pages. +It must not only release the remaining pages, but unlock them too. + +This fixes http://tracker.newdream.net/issues/3370 + +Signed-off-by: David Zafman +Reviewed-by: Alex Elder +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/addr.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -267,6 +267,14 @@ static void finish_read(struct ceph_osd_ + kfree(req->r_pages); + } + ++static void ceph_unlock_page_vector(struct page **pages, int num_pages) ++{ ++ int i; ++ ++ for (i = 0; i < num_pages; i++) ++ unlock_page(pages[i]); ++} ++ + /* + * start an async read(ahead) operation. return nr_pages we submitted + * a read for on success, or negative error code. +@@ -347,6 +355,7 @@ static int start_read(struct inode *inod + return nr_pages; + + out_pages: ++ ceph_unlock_page_vector(pages, nr_pages); + ceph_release_page_vector(pages, nr_pages); + out: + ceph_osdc_put_request(req); +From 45e2b5f640b3766da3eda48f6c35f088155c06f3 Mon Sep 17 00:00:00 2001 +From: Daniel Vetter +Date: Fri, 23 Nov 2012 18:16:34 +0100 +Subject: drm/i915: force restore on lid open + +From: Daniel Vetter + +commit 45e2b5f640b3766da3eda48f6c35f088155c06f3 upstream. + +There seem to be indeed some awkwards machines around, mostly those +without OpRegion support, where the firmware changes the display hw +state behind our backs when closing the lid. + +This force-restore logic has been originally introduced in + +commit c1c7af60892070e4b82ad63bbfb95ae745056de0 +Author: Jesse Barnes +Date: Thu Sep 10 15:28:03 2009 -0700 + + drm/i915: force mode set at lid open time + +but after the modeset-rework we've disabled it in the vain hope that +it's no longer required: + +commit 3b7a89fce3e3dc96b549d6d829387b4439044d0d +Author: Daniel Vetter +Date: Mon Sep 17 22:27:21 2012 +0200 + + drm/i915: fix OOPS in lid_notify + +Alas, no. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54677 +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 +Tested-by: Krzysztof Mazur +Reviewed-by: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_drv.c | 2 +- + drivers/gpu/drm/i915/i915_drv.h | 3 ++- + drivers/gpu/drm/i915/intel_display.c | 15 ++++++++++++--- + drivers/gpu/drm/i915/intel_lvds.c | 2 +- + 4 files changed, 16 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_drv.c ++++ b/drivers/gpu/drm/i915/i915_drv.c +@@ -552,7 +552,7 @@ static int i915_drm_thaw(struct drm_devi + mutex_unlock(&dev->struct_mutex); + + intel_modeset_init_hw(dev); +- intel_modeset_setup_hw_state(dev); ++ intel_modeset_setup_hw_state(dev, false); + drm_mode_config_reset(dev); + drm_irq_install(dev); + } +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1595,7 +1595,8 @@ extern void intel_modeset_init(struct dr + extern void intel_modeset_gem_init(struct drm_device *dev); + extern void intel_modeset_cleanup(struct drm_device *dev); + extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state); +-extern void intel_modeset_setup_hw_state(struct drm_device *dev); ++extern void intel_modeset_setup_hw_state(struct drm_device *dev, ++ bool force_restore); + extern bool intel_fbc_enabled(struct drm_device *dev); + extern void intel_disable_fbc(struct drm_device *dev); + extern bool ironlake_set_drps(struct drm_device *dev, u8 val); +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -8250,7 +8250,8 @@ static void intel_sanitize_encoder(struc + + /* Scan out the current hw modeset state, sanitizes it and maps it into the drm + * and i915 state tracking structures. */ +-void intel_modeset_setup_hw_state(struct drm_device *dev) ++void intel_modeset_setup_hw_state(struct drm_device *dev, ++ bool force_restore) + { + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe; +@@ -8321,7 +8322,15 @@ void intel_modeset_setup_hw_state(struct + intel_sanitize_crtc(crtc); + } + +- intel_modeset_update_staged_output_state(dev); ++ if (force_restore) { ++ for_each_pipe(pipe) { ++ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); ++ intel_set_mode(&crtc->base, &crtc->base.mode, ++ crtc->base.x, crtc->base.y, crtc->base.fb); ++ } ++ } else { ++ intel_modeset_update_staged_output_state(dev); ++ } + + intel_modeset_check_state(dev); + } +@@ -8332,7 +8341,7 @@ void intel_modeset_gem_init(struct drm_d + + intel_setup_overlay(dev); + +- intel_modeset_setup_hw_state(dev); ++ intel_modeset_setup_hw_state(dev, false); + } + + void intel_modeset_cleanup(struct drm_device *dev) +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -526,7 +526,7 @@ static int intel_lid_notify(struct notif + dev_priv->modeset_on_lid = 0; + + mutex_lock(&dev->mode_config.mutex); +- intel_modeset_check_state(dev); ++ intel_modeset_setup_hw_state(dev, true); + mutex_unlock(&dev->mode_config.mutex); + + return NOTIFY_OK; +From 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 Mon Sep 17 00:00:00 2001 +From: Krzysztof Mazur +Date: Wed, 19 Dec 2012 11:03:41 +0100 +Subject: i915: ensure that VGA plane is disabled + +From: Krzysztof Mazur + +commit 0fde901f1ddd2ce0e380a6444f1fb7ca555859e9 upstream. + +Some broken systems (like HP nc6120) in some cases, usually after LID +close/open, enable VGA plane, making display unusable (black screen on LVDS, +some strange mode on VGA output). We used to disable VGA plane only once at +startup. Now we also check, if VGA plane is still disabled while changing +mode, and fix that if something changed it. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57434 +Signed-off-by: Krzysztof Mazur +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -8248,6 +8248,23 @@ static void intel_sanitize_encoder(struc + * the crtc fixup. */ + } + ++static void i915_redisable_vga(struct drm_device *dev) ++{ ++ struct drm_i915_private *dev_priv = dev->dev_private; ++ u32 vga_reg; ++ ++ if (HAS_PCH_SPLIT(dev)) ++ vga_reg = CPU_VGACNTRL; ++ else ++ vga_reg = VGACNTRL; ++ ++ if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { ++ DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); ++ I915_WRITE(vga_reg, VGA_DISP_DISABLE); ++ POSTING_READ(vga_reg); ++ } ++} ++ + /* Scan out the current hw modeset state, sanitizes it and maps it into the drm + * and i915 state tracking structures. */ + void intel_modeset_setup_hw_state(struct drm_device *dev, +@@ -8328,6 +8345,8 @@ void intel_modeset_setup_hw_state(struct + intel_set_mode(&crtc->base, &crtc->base.mode, + crtc->base.x, crtc->base.y, crtc->base.fb); + } ++ ++ i915_redisable_vga(dev); + } else { + intel_modeset_update_staged_output_state(dev); + } +From 3490ea5de6ac4af309c3df8a26a5cca61306334c Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 7 Jan 2013 10:11:40 +0000 +Subject: drm/i915: Treat crtc->mode.clock == 0 as disabled + +From: Chris Wilson + +commit 3490ea5de6ac4af309c3df8a26a5cca61306334c upstream. + +Prevent a divide-by-zero by consistently treating an 'active' CRTC +without a mode set as actually disabled. + +This looks to have been first introduced with + +commit 24929352481f085c5f85d4d4cbc919ddf106d381 +Author: Daniel Vetter +Date: Mon Jul 2 20:28:59 2012 +0200 + + drm/i915: read out the modeset hw state at load and resume time + +but then combined with + +commit b0a2658acb5bf9ca86b4aab011b7106de3af0add +Author: Daniel Vetter +Date: Tue Dec 18 09:37:54 2012 +0100 + + drm/i915: don't disable disconnected outputs + +it finally started oopsing. + +Signed-off-by: Chris Wilson +Reported-and-tested-by: Alexey Zaytsev +Tested-by: Sedat Dilek +Cc: Daniel Vetter +Cc: Jesse Barnes +Signed-off-by: Daniel Vetter +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/intel_pm.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_pm.c ++++ b/drivers/gpu/drm/i915/intel_pm.c +@@ -44,6 +44,14 @@ + * i915.i915_enable_fbc parameter + */ + ++static bool intel_crtc_active(struct drm_crtc *crtc) ++{ ++ /* Be paranoid as we can arrive here with only partial ++ * state retrieved from the hardware during setup. ++ */ ++ return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; ++} ++ + static void i8xx_disable_fbc(struct drm_device *dev) + { + struct drm_i915_private *dev_priv = dev->dev_private; +@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device + * - going to an unsupported config (interlace, pixel multiply, etc.) + */ + list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { +- if (tmp_crtc->enabled && +- !to_intel_crtc(tmp_crtc)->primary_disabled && +- tmp_crtc->fb) { ++ if (intel_crtc_active(tmp_crtc) && ++ !to_intel_crtc(tmp_crtc)->primary_disabled) { + if (crtc) { + DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); + dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; +@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_c + struct drm_crtc *crtc, *enabled = NULL; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { +- if (crtc->enabled && crtc->fb) { ++ if (intel_crtc_active(crtc)) { + if (enabled) + return NULL; + enabled = crtc; +@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_d + int entries, tlb_miss; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) { ++ if (!intel_crtc_active(crtc)) { + *cursor_wm = cursor->guard_size; + *plane_wm = display->guard_size; + return false; +@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(st + int entries; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) ++ if (!intel_crtc_active(crtc)) + return false; + + clock = crtc->mode.clock; /* VESA DOT Clock */ +@@ -1478,7 +1485,7 @@ static void i9xx_update_wm(struct drm_de + + fifo_size = dev_priv->display.get_fifo_size(dev, 1); + crtc = intel_get_crtc_for_plane(dev, 1); +- if (crtc->enabled && crtc->fb) { ++ if (intel_crtc_active(crtc)) { + planeb_wm = intel_calculate_wm(crtc->mode.clock, + wm_info, fifo_size, + crtc->fb->bits_per_pixel / 8, +@@ -1923,7 +1930,7 @@ sandybridge_compute_sprite_wm(struct drm + int entries, tlb_miss; + + crtc = intel_get_crtc_for_plane(dev, plane); +- if (crtc->fb == NULL || !crtc->enabled) { ++ if (!intel_crtc_active(crtc)) { + *sprite_wm = display->guard_size; + return false; + } diff --git a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch b/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch deleted file mode 100644 index f6e997c..0000000 --- a/ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +++ /dev/null @@ -1,46 +0,0 @@ -From b7e383046c2c7c13ad928cd7407eafff758ddd4b Mon Sep 17 00:00:00 2001 -From: Zhang Rui -Date: Tue, 4 Dec 2012 23:23:16 +0100 -Subject: [PATCH] ACPI : do not use Lid and Sleep button for S5 wakeup - -When system enters power off, the _PSW of Lid device is enabled. -But this may cause the system to reboot instead of power off. - -A proper way to fix this is to always disable lid wakeup capability for S5. - -References: https://bugzilla.kernel.org/show_bug.cgi?id=35262 -Signed-off-by: Zhang Rui -Signed-off-by: Rafael J. Wysocki ---- - drivers/acpi/scan.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c -index d0b38ab..bd523bf 100644 ---- a/drivers/acpi/scan.c -+++ b/drivers/acpi/scan.c -@@ -917,8 +917,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, - static void acpi_bus_set_run_wake_flags(struct acpi_device *device) - { - struct acpi_device_id button_device_ids[] = { -- {"PNP0C0D", 0}, - {"PNP0C0C", 0}, -+ {"PNP0C0D", 0}, - {"PNP0C0E", 0}, - {"", 0}, - }; -@@ -930,6 +930,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) - /* Power button, Lid switch always enable wakeup */ - if (!acpi_match_device_ids(device, button_device_ids)) { - device->wakeup.flags.run_wake = 1; -+ if (!acpi_match_device_ids(device, &button_device_ids[1])) { -+ /* Do not use Lid/sleep button for S5 wakeup */ -+ if (device->wakeup.sleep_state == ACPI_STATE_S5) -+ device->wakeup.sleep_state = ACPI_STATE_S4; -+ } - device_set_wakeup_capable(&device->dev, true); - return; - } --- -1.8.0.1 - diff --git a/aoe-remove-vestigial-request-queue-allocation.patch b/aoe-remove-vestigial-request-queue-allocation.patch deleted file mode 100644 index fa4ad1a..0000000 --- a/aoe-remove-vestigial-request-queue-allocation.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 0a41409c518083133e79015092585d68915865be Mon Sep 17 00:00:00 2001 -From: Ed Cashin -Date: Mon, 17 Dec 2012 16:03:58 -0800 -Subject: [PATCH] aoe: remove vestigial request queue allocation - -Before the aoe driver was an I/O request handler, it was a -make_request-style block driver. Even so, there was a problem where -sysfs expected a request queue to exist, so one was provided in commit -7135a71b19be ("aoe: allocate unused request_queue for sysfs"). - -During the transition to the request-handler style, a patch was merged -that was based on a driver without the noop queue, and the noop queue -remained in place after the patch was merged, even though a new -functional queue was introduced by the patch, allocated through -blk_init_queue. - -The user impact is a memory leak proportional to the number of AoE -targets discovered. This patch removes the memory leak and cleans up -vestiges of the old do-nothing queue from the aoeblk_gdalloc function. - -Signed-off-by: Ed Cashin -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - drivers/block/aoe/aoeblk.c | 17 ++++------------- - 1 file changed, 4 insertions(+), 13 deletions(-) - -diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c -index 7ba0fcf..57ac72c 100644 ---- a/drivers/block/aoe/aoeblk.c -+++ b/drivers/block/aoe/aoeblk.c -@@ -278,18 +278,12 @@ aoeblk_gdalloc(void *vp) - if (q == NULL) { - pr_err("aoe: cannot allocate block queue for %ld.%d\n", - d->aoemajor, d->aoeminor); -- mempool_destroy(mp); -- goto err_disk; -+ goto err_mempool; - } - -- d->blkq = blk_alloc_queue(GFP_KERNEL); -- if (!d->blkq) -- goto err_mempool; -- d->blkq->backing_dev_info.name = "aoe"; -- if (bdi_init(&d->blkq->backing_dev_info)) -- goto err_blkq; - spin_lock_irqsave(&d->lock, flags); -- blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); -+ blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); -+ q->backing_dev_info.name = "aoe"; - q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; - d->bufpool = mp; - d->blkq = gd->queue = q; -@@ -314,11 +308,8 @@ aoeblk_gdalloc(void *vp) - aoedisk_add_sysfs(d); - return; - --err_blkq: -- blk_cleanup_queue(d->blkq); -- d->blkq = NULL; - err_mempool: -- mempool_destroy(d->bufpool); -+ mempool_destroy(mp); - err_disk: - put_disk(gd); - err: --- -1.8.0.1 - diff --git a/config-x86-generic b/config-x86-generic index b3d19ea..2bcd498 100644 --- a/config-x86-generic +++ b/config-x86-generic @@ -45,7 +45,7 @@ CONFIG_FB_EFI=y CONFIG_INTEL_IOMMU=y CONFIG_DMAR_BROKEN_GFX_WA=y CONFIG_INTEL_IOMMU_FLOPPY_WA=y -CONFIG_INTEL_IOMMU_DEFAULT_ON=y +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set CONFIG_SCSI_ADVANSYS=m CONFIG_SECCOMP=y diff --git a/kernel.spec b/kernel.spec index 71033f5..e58f8cb 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 202 +%global baserelease 203 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -780,17 +780,8 @@ Patch21231: 8139cp-revert-set-ring-address-before-enabling-receiver.patch Patch21232: 8139cp-set-ring-address-after-enabling-C-mode.patch Patch21233: 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 883414 -Patch21234: mac80211-fix-ibss-scanning.patch - -#rhbz 873107 -Patch21237: 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch - -#rhbz 853064 -Patch21239: aoe-remove-vestigial-request-queue-allocation.patch - -#rhbz 890547 -Patch21240: ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch +#3.7.3 stable queue +Patch2150: 3.7.3-stable-queue.patch # END OF PATCH DEFINITIONS @@ -1511,18 +1502,8 @@ ApplyPatch 8139cp-revert-set-ring-address-before-enabling-receiver.patch -R ApplyPatch 8139cp-set-ring-address-after-enabling-C-mode.patch ApplyPatch 8139cp-re-enable-interrupts-after-tx-timeout.patch -#rhbz 883414 -ApplyPatch mac80211-fix-ibss-scanning.patch - -#rhbz 873107 -ApplyPatch 0001-ACPI-sony-laptop-do-proper-memcpy-for-ACPI_TYPE_INTE.patch - -#rhbz 853064 -ApplyPatch aoe-remove-vestigial-request-queue-allocation.patch - -#rhbz 890547 -ApplyPatch ACPI-do-not-use-Lid-and-Sleep-button-for-S5-wakeup.patch - +#3.7.3 stable qeueu +ApplyPatch 3.7.3-stable-queue.patch # END OF PATCH APPLICATIONS @@ -2396,6 +2377,10 @@ fi # ||----w | # || || %changelog +* Tue Jan 15 2013 Justin M. Forbes 3.7.2-203 +- Turn off Intel IOMMU by default +- Stable queue from 3.7.3 with many relevant fixes + * Tue Jan 15 2013 Josh Boyer - Enable CONFIG_DVB_USB_V2 (rhbz 895460) diff --git a/mac80211-fix-ibss-scanning.patch b/mac80211-fix-ibss-scanning.patch deleted file mode 100644 index c2bc698..0000000 --- a/mac80211-fix-ibss-scanning.patch +++ /dev/null @@ -1,132 +0,0 @@ -Do not scan on no-IBSS and disabled channels in IBSS mode. Doing this -can trigger Microcode errors on iwlwifi and iwlegacy drivers. - -Also rename ieee80211_request_internal_scan() function since it is only -used in IBSS mode and simplify calling it from ieee80211_sta_find_ibss(). - -This patch should address: -https://bugzilla.redhat.com/show_bug.cgi?id=883414 -https://bugzilla.kernel.org/show_bug.cgi?id=49411 - -Reported-by: Jesse Kahtava -Reported-by: Mikko Rapeli -Cc: stable@vger.kernel.org -Signed-off-by: Stanislaw Gruszka ---- - net/mac80211/ibss.c | 9 ++++----- - net/mac80211/ieee80211_i.h | 6 +++--- - net/mac80211/scan.c | 34 ++++++++++++++++++++++++---------- - 3 files changed, 31 insertions(+), 18 deletions(-) - -diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c -index c21e33d..d9df6b8 100644 ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -678,8 +678,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) - sdata_info(sdata, - "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, -+ NULL); - } - - static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) -@@ -777,9 +777,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) - IEEE80211_SCAN_INTERVAL)) { - sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); - -- ieee80211_request_internal_scan(sdata, -- ifibss->ssid, ifibss->ssid_len, -- ifibss->fixed_channel ? ifibss->channel : NULL); -+ ieee80211_request_ibss_scan(sdata, ifibss->ssid, -+ ifibss->ssid_len, chan); - } else { - int interval = IEEE80211_SCAN_INTERVAL; - -diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h -index 156e583..bc48d4d 100644 ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -1247,9 +1247,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, - - /* scan/BSS handling */ - void ieee80211_scan_work(struct work_struct *work); --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan); -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan); - int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - struct cfg80211_scan_request *req); - void ieee80211_scan_cancel(struct ieee80211_local *local); -diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c -index 43e60b5..fab706f 100644 ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -819,9 +819,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, - return res; - } - --int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, -- const u8 *ssid, u8 ssid_len, -- struct ieee80211_channel *chan) -+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, -+ const u8 *ssid, u8 ssid_len, -+ struct ieee80211_channel *chan) - { - struct ieee80211_local *local = sdata->local; - int ret = -EBUSY; -@@ -835,22 +835,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - - /* fill internal scan request */ - if (!chan) { -- int i, nchan = 0; -+ int i, max_n; -+ int n_ch = 0; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!local->hw.wiphy->bands[band]) - continue; -- for (i = 0; -- i < local->hw.wiphy->bands[band]->n_channels; -- i++) { -- local->int_scan_req->channels[nchan] = -+ -+ max_n = local->hw.wiphy->bands[band]->n_channels; -+ for (i = 0; i < max_n; i++) { -+ struct ieee80211_channel *tmp_ch = - &local->hw.wiphy->bands[band]->channels[i]; -- nchan++; -+ -+ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED)) -+ continue; -+ -+ local->int_scan_req->channels[n_ch] = tmp_ch; -+ n_ch++; - } - } - -- local->int_scan_req->n_channels = nchan; -+ if (WARN_ON_ONCE(n_ch == 0)) -+ goto unlock; -+ -+ local->int_scan_req->n_channels = n_ch; - } else { -+ if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_DISABLED))) -+ goto unlock; -+ - local->int_scan_req->channels[0] = chan; - local->int_scan_req->n_channels = 1; - } --- -1.7.1 - --- -To unsubscribe from this list: send the line "unsubscribe linux-wireless" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html \ No newline at end of file