From 3fbec23f6bc97f3721c5345659fbbb71542120c5 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Wed, 6 Jun 2012 11:59:06 -0300 Subject: char/agp: add another Ironlake host bridge commit 67384fe3fd450536342330f684ea1f7dcaef8130 upstream. This seems to come on Gigabyte H55M-S2V and was discovered through the https://bugs.freedesktop.org/show_bug.cgi?id=50381 debugging. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50381 Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/intel-agp.c | 1 + drivers/char/agp/intel-agp.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index b427711be4be..58b49d1a283b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -897,6 +897,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_1_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 5da67f165afa..6f246049d5b4 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -211,6 +211,7 @@ #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 -- cgit v1.2.3 From 29684ecb7a675061933fb19531407fa9f9971ab4 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Thu, 7 Jun 2012 14:21:13 -0700 Subject: btree: fix tree corruption in btree_get_prev() commit cbf8ae32f66a9ceb8907ad9e16663c2a29e48990 upstream. The memory the parameter __key points to is used as an iterator in btree_get_prev(), so if we save off a bkey() pointer in retry_key and then assign that to __key, we'll end up corrupting the btree internals when we do eg longcpy(__key, bkey(geo, node, i), geo->keylen); to return the key value. What we should do instead is use longcpy() to copy the key value that retry_key points to __key. This can cause a btree to get corrupted by seemingly read-only operations such as btree_for_each_safe. [akpm@linux-foundation.org: avoid the double longcpy()] Signed-off-by: Roland Dreier Acked-by: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- lib/btree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/btree.c b/lib/btree.c index 2a34392bcecc..297124d4d8da 100644 --- a/lib/btree.c +++ b/lib/btree.c @@ -319,8 +319,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo, if (head->height == 0) return NULL; -retry: longcpy(key, __key, geo->keylen); +retry: dec_key(geo, key); node = head->node; @@ -351,7 +351,7 @@ retry: } miss: if (retry_key) { - __key = retry_key; + longcpy(key, retry_key, geo->keylen); retry_key = NULL; goto retry; } -- cgit v1.2.3 From 238607e0800c37b64868e6ec2323fc0e25cd7363 Mon Sep 17 00:00:00 2001 From: Steffen Rumler Date: Wed, 6 Jun 2012 16:37:17 +0200 Subject: powerpc: Fix kernel panic during kernel module load commit 3c75296562f43e6fbc6cddd3de948a7b3e4e9bcf upstream. This fixes a problem which can causes kernel oopses while loading a kernel module. According to the PowerPC EABI specification, GPR r11 is assigned the dedicated function to point to the previous stack frame. In the powerpc-specific kernel module loader, do_plt_call() (in arch/powerpc/kernel/module_32.c), GPR r11 is also used to generate trampoline code. This combination crashes the kernel, in the case where the compiler chooses to use a helper function for saving GPRs on entry, and the module loader has placed the .init.text section far away from the .text section, meaning that it has to generate a trampoline for functions in the .init.text section to call the GPR save helper. Because the trampoline trashes r11, references to the stack frame using r11 can cause an oops. The fix just uses GPR r12 instead of GPR r11 for generating the trampoline code. According to the statements from Freescale, this is safe from an EABI perspective. I've tested the fix for kernel 2.6.33 on MPC8541. Signed-off-by: Steffen Rumler [paulus@samba.org: reworded the description] Signed-off-by: Paul Mackerras Signed-off-by: Greg Kroah-Hartman --- arch/powerpc/kernel/module_32.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index f832773fc28e..449a7e053e67 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c @@ -187,8 +187,8 @@ int apply_relocate(Elf32_Shdr *sechdrs, static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) { - if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) - && entry->jump[1] == 0x396b0000 + (val & 0xffff)) + if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16) + && entry->jump[1] == 0x398c0000 + (val & 0xffff)) return 1; return 0; } @@ -215,10 +215,9 @@ static uint32_t do_plt_call(void *location, entry++; } - /* Stolen from Paul Mackerras as well... */ - entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ - entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ - entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ + entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */ + entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/ + entry->jump[2] = 0x7d8903a6; /* mtctr r12 */ entry->jump[3] = 0x4e800420; /* bctr */ DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); -- cgit v1.2.3 From 9bef1b2492b95dc848cbde1ad021efc355a0b350 Mon Sep 17 00:00:00 2001 From: Mathias Krause Date: Wed, 30 May 2012 01:43:08 +0200 Subject: crypto: aesni-intel - fix unaligned cbc decrypt for x86-32 commit 7c8d51848a88aafdb68f42b6b650c83485ea2f84 upstream. The 32 bit variant of cbc(aes) decrypt is using instructions requiring 128 bit aligned memory locations but fails to ensure this constraint in the code. Fix this by loading the data into intermediate registers with load unaligned instructions. This fixes reported general protection faults related to aesni. References: https://bugzilla.kernel.org/show_bug.cgi?id=43223 Reported-by: Daniel Signed-off-by: Mathias Krause Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- arch/x86/crypto/aesni-intel_asm.S | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index be6d9e365a80..3470624d7835 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -2460,10 +2460,12 @@ ENTRY(aesni_cbc_dec) pxor IN3, STATE4 movaps IN4, IV #else - pxor (INP), STATE2 - pxor 0x10(INP), STATE3 pxor IN1, STATE4 movaps IN2, IV + movups (INP), IN1 + pxor IN1, STATE2 + movups 0x10(INP), IN2 + pxor IN2, STATE3 #endif movups STATE1, (OUTP) movups STATE2, 0x10(OUTP) -- cgit v1.2.3 From 55fe02e968371dd1c0b5b1f9411f2fc8c2b84e7e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 31 May 2012 15:09:27 +0200 Subject: mac80211: clean up remain-on-channel on interface stop commit 71ecfa1893034eeb1c93e02e22ee2ad26d080858 upstream. When any interface goes down, it could be the one that we were doing a remain-on-channel with. We therefore need to cancel the remain-on-channel and flush the related work structs so they don't run after the interface has been removed or even destroyed. It's also possible in this case that an off-channel SKB was never transmitted, so free it if this is the case. Note that this can also happen if the driver finishes the off-channel period without ever starting it. Reported-by: Nirav Shah Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/mac80211/iface.c | 12 ++++++++++++ net/mac80211/offchannel.c | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 895eec19f2e2..65f3764c5aa2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -498,6 +498,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_configure_filter(local); break; default: + mutex_lock(&local->mtx); + if (local->hw_roc_dev == sdata->dev && + local->hw_roc_channel) { + /* ignore return value since this is racy */ + drv_cancel_remain_on_channel(local); + ieee80211_queue_work(&local->hw, &local->hw_roc_done); + } + mutex_unlock(&local->mtx); + + flush_work(&local->hw_roc_start); + flush_work(&local->hw_roc_done); + flush_work(&sdata->work); /* * When we get here, the interface is marked down. diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 13427b194ced..c55eb9d8ea55 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -251,6 +251,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work) return; } + /* was never transmitted */ + if (local->hw_roc_skb) { + u64 cookie; + + cookie = local->hw_roc_cookie ^ 2; + + cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, + local->hw_roc_skb->data, + local->hw_roc_skb->len, false, + GFP_KERNEL); + + kfree_skb(local->hw_roc_skb); + local->hw_roc_skb = NULL; + local->hw_roc_skb_for_status = NULL; + } + if (!local->hw_roc_for_tx) cfg80211_remain_on_channel_expired(local->hw_roc_dev, local->hw_roc_cookie, -- cgit v1.2.3 From f90b005ff35ab8e6ed3ddcbf79dee0baa48c429a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 5 Jun 2012 12:16:50 +0200 Subject: cfg80211: fix interface combinations check commit 463454b5dbd8dbab6e2fc6c557329e5b811b9c32 upstream. If a given interface combination doesn't contain a required interface type then we missed checking that and erroneously allowed it even though iface type wasn't there at all. Add a check that makes sure that all interface types are accounted for. Reported-by: Mohammed Shafi Shajakhan Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- net/wireless/util.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/net/wireless/util.c b/net/wireless/util.c index 9c22330a129d..30f68dc76ac0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -937,6 +937,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype) { struct wireless_dev *wdev_iter; + u32 used_iftypes = BIT(iftype); int num[NUM_NL80211_IFTYPES]; int total = 1; int i, j; @@ -970,12 +971,14 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, num[wdev_iter->iftype]++; total++; + used_iftypes |= BIT(wdev_iter->iftype); } mutex_unlock(&rdev->devlist_mtx); for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; + u32 all_iftypes = 0; c = &rdev->wiphy.iface_combinations[i]; @@ -990,6 +993,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { + all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) @@ -997,7 +1001,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, limits[j].max -= num[iftype]; } } - /* yay, it fits */ + + /* + * Finally check that all iftypes that we're currently + * using are actually part of this combination. If they + * aren't then we can't use this combination and have + * to continue to the next. + */ + if ((all_iftypes & used_iftypes) != used_iftypes) + goto cont; + + /* + * This combination covered all interface types and + * supported the requested numbers, so we're good. + */ kfree(limits); return 0; cont: -- cgit v1.2.3 From 8f509b694f5d1f287188bdd3df11aafccc911c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Tue, 5 Jun 2012 21:18:10 +0000 Subject: net: sierra_net: device IDs for Aircard 320U++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit dd03cff23d694cfb0fdae80cb618e7ced05ea696 upstream. Adding device IDs for Aircard 320U and two other devices found in the out-of-tree version of this driver. Cc: linux@sierrawireless.com Cc: Autif Khan Cc: Tom Cassidy Signed-off-by: Bjørn Mork Acked-by: Greg Kroah-Hartman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/usb/sierra_net.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index ed1b43210584..864448b76120 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -943,7 +943,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; -static const struct sierra_net_info_data sierra_net_info_data_68A3 = { +static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, .whitelist = { .infolen = ARRAY_SIZE(sierra_net_ifnum_list), @@ -951,7 +951,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = { } }; -static const struct driver_info sierra_net_info_68A3 = { +static const struct driver_info sierra_net_info_direct_ip = { .description = "Sierra Wireless USB-to-WWAN Modem", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .bind = sierra_net_bind, @@ -959,12 +959,18 @@ static const struct driver_info sierra_net_info_68A3 = { .status = sierra_net_status, .rx_fixup = sierra_net_rx_fixup, .tx_fixup = sierra_net_tx_fixup, - .data = (unsigned long)&sierra_net_info_data_68A3, + .data = (unsigned long)&sierra_net_info_data_direct_ip, }; static const struct usb_device_id products[] = { {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_68A3}, + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, {}, /* last item */ }; -- cgit v1.2.3 From 2f99a5afd1a9752cf69c3ee006f3a9c1bb74013a Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:09 +0530 Subject: can: c_can: fix "BUG! echo_skb is occupied!" during transmit commit 617caccebe451716df21c069b079d5936ed7b0f3 upstream. This patch fixes an issue with transmit routine, which causes "can_put_echo_skb: BUG! echo_skb is occupied!" message when using "cansequence -p" on D_CAN controller. In c_can driver, while transmitting packets tx_echo flag holds the no of can frames put for transmission into the hardware. As the comment above c_can_do_tx() indicates, if we find any packet which is not transmitted then we should stop looking for more. In the current implementation this is not taken care of causing the said message. Also, fix the condition used to find if the packet is transmitted or not. Current code skips the first tx message object and ends up checking one extra invalid object. While at it, fix the comment on top of c_can_do_tx() to use the terminology "packet" instead of "package" since it is more standard. Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 7e5cc0bd913d..60e17154dbeb 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -688,7 +688,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, * * We iterate from priv->tx_echo to priv->tx_next and check if the * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted package, stop looking for more. + * If we discover a not yet transmitted packet, stop looking for more. */ static void c_can_do_tx(struct net_device *dev) { @@ -700,7 +700,7 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); val = c_can_read_reg32(priv, &priv->regs->txrqst1); - if (!(val & (1 << msg_obj_no))) { + if (!(val & (1 << (msg_obj_no - 1)))) { can_get_echo_skb(dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); stats->tx_bytes += priv->read_reg(priv, @@ -708,6 +708,8 @@ static void c_can_do_tx(struct net_device *dev) & IF_MCONT_DLC_MASK; stats->tx_packets++; c_can_inval_msg_object(dev, 0, msg_obj_no); + } else { + break; } } -- cgit v1.2.3 From e3c8262d150883d1dbd9b5cbb03d6cca7cf68cad Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:10 +0530 Subject: can: c_can: fix an interrupt thrash issue with c_can driver commit 148c87c89e1a8863d3d965179f3ab1a06490569e upstream. This patch fixes an interrupt thrash issue with c_can driver. In c_can_isr() function interrupts are disabled and enabled only in c_can_poll() function. c_can_isr() & c_can_poll() both read the irqstatus flag. However, irqstatus is always read as 0 in c_can_poll() because all C_CAN interrupts are disabled in c_can_isr(). This causes all interrupts to be re-enabled in c_can_poll() which in turn causes another interrupt since the event is not really handled. This keeps happening causing a flood of interrupts. To fix this, read the irqstatus register in isr and use the same cached value in the poll function. Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 7 +++---- drivers/net/can/c_can/c_can.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 60e17154dbeb..227dfd8b509f 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -954,7 +954,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + irqstatus = priv->irqstatus; if (!irqstatus) goto end; @@ -1032,12 +1032,11 @@ end: static irqreturn_t c_can_isr(int irq, void *dev_id) { - u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!irqstatus) + priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!priv->irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef3d09a..5f32d34af507 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -76,6 +76,7 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ + u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); -- cgit v1.2.3 From 4286e566ff410a64f5a329fb42f2d44193c52945 Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 23 May 2012 17:45:11 +0530 Subject: can: c_can: fix race condition in c_can_open() commit f461f27a4436dbe691908fe08b867ef888848cc3 upstream. Fix the issue of C_CAN interrupts getting disabled forever when canconfig utility is used multiple times. According to NAPI usage we disable all the hardware interrupts in ISR and re-enable them in poll(). Current implementation calls napi_enable() after hardware interrupts are enabled. If we get any interrupts between these two steps then we do not process those interrupts because napi is not enabled. Mostly these interrupts come because of STATUS is not 0x7 or ERROR interrupts. If napi_enable() happens before HW interrupts enabled then c_can_poll() function will be called eventual re-enabling. This patch moves the napi_enable() call before interrupts enabled. Signed-off-by: AnilKumar Ch Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/c_can/c_can.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 227dfd8b509f..1f8a8244f23e 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -1066,10 +1066,11 @@ static int c_can_open(struct net_device *dev) goto exit_irq_fail; } + napi_enable(&priv->napi); + /* start the c_can controller */ c_can_start(dev); - napi_enable(&priv->napi); netif_start_queue(dev); return 0; -- cgit v1.2.3 From 18f63bf60d507b4588f33ecfd8657f5d5e2a7b45 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 23 Mar 2012 10:02:17 +0100 Subject: hwmon: (fam15h_power) Increase output resolution commit 941a956b0e387b21f385f486c34ef67576775cfc upstream. On high CPU load the accumulating values in the running_avg_cap register are very low (below 10), so averaging them too early leads to unnecessary poor output resolution. Since we pretend to output micro-Watt we better keep all the bits we have as long as possible. Signed-off-by: Andre Przywara Signed-off-by: Andreas Herrmann Acked-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/fam15h_power.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 9a4c3abc9d92..e8e18cab1fb8 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -61,14 +61,14 @@ static ssize_t show_power(struct device *dev, REG_TDP_RUNNING_AVERAGE, &val); running_avg_capture = (val >> 4) & 0x3fffff; running_avg_capture = sign_extend32(running_avg_capture, 21); - running_avg_range = val & 0xf; + running_avg_range = (val & 0xf) + 1; pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), REG_TDP_LIMIT3, &val); tdp_limit = val >> 16; - curr_pwr_watts = tdp_limit + data->base_tdp - - (s32)(running_avg_capture >> (running_avg_range + 1)); + curr_pwr_watts = (tdp_limit + data->base_tdp) << running_avg_range; + curr_pwr_watts -= running_avg_capture; curr_pwr_watts *= data->tdp_to_watts; /* @@ -78,7 +78,7 @@ static ssize_t show_power(struct device *dev, * scaling factor 1/(2^16). For conversion we use * (10^6)/(2^16) = 15625/(2^10) */ - curr_pwr_watts = (curr_pwr_watts * 15625) >> 10; + curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range); return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts); } static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); -- cgit v1.2.3 From ae797dcdae86481103b6ed79d97ac09e57e2feef Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 25 Apr 2012 14:33:33 +0100 Subject: acpi_video: fix leaking PCI references commit cfb46f433a4da97c31780e08a259fac2cb6bd61f upstream. Signed-off-by: Alan Cox Acked-by: Matthew Garrett Signed-off-by: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index db39e9e607d8..623a3357ce9b 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1732,6 +1732,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) static int __init intel_opregion_present(void) { + int i915 = 0; #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1744,10 +1745,10 @@ static int __init intel_opregion_present(void) pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - return 1; + i915 = 1; } #endif - return 0; + return i915; } int acpi_video_register(void) -- cgit v1.2.3 From 34b1a9eb1db3de73460f3a21d8ffb48ea7cbd338 Mon Sep 17 00:00:00 2001 From: Dimitri Sivanich Date: Tue, 5 Jun 2012 13:44:36 -0500 Subject: sched: Fix the relax_domain_level boot parameter commit a841f8cef4bb124f0f5563314d0beaf2e1249d72 upstream. It does not get processed because sched_domain_level_max is 0 at the time that setup_relax_domain_level() is run. Simply accept the value as it is, as we don't know the value of sched_domain_level_max until sched domain construction is completed. Fix sched_relax_domain_level in cpuset. The build_sched_domain() routine calls the set_domain_attribute() routine prior to setting the sd->level, however, the set_domain_attribute() routine relies on the sd->level to decide whether idle load balancing will be off/on. Signed-off-by: Dimitri Sivanich Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20120605184436.GA15668@sgi.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- kernel/sched.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 03dff14b44e5..8ef48f0facdd 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -7220,11 +7220,8 @@ int sched_domain_level_max; static int __init setup_relax_domain_level(char *str) { - unsigned long val; - - val = simple_strtoul(str, NULL, 0); - if (val < sched_domain_level_max) - default_relax_domain_level = val; + if (kstrtoint(str, 0, &default_relax_domain_level)) + pr_warn("Unable to set relax_domain_level\n"); return 1; } @@ -7417,7 +7414,6 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, if (!sd) return child; - set_domain_attribute(sd, attr); cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu)); if (child) { sd->level = child->level + 1; @@ -7425,6 +7421,7 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, child->parent = sd; } sd->child = child; + set_domain_attribute(sd, attr); return sd; } -- cgit v1.2.3 From e2b55892ceb923d9ff6c204e59be5f2b43a0009c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 6 Jun 2012 09:13:36 +0200 Subject: iwlwifi: don't mess up the SCD when removing a key commit d6ee27eb13beab94056e0de52d81220058ca2297 upstream. When we remove a key, we put a key index which was supposed to tell the fw that we are actually removing the key. But instead the fw took that index as a valid index and messed up the SRAM of the device. This memory corruption on the device mangled the data of the SCD. The impact on the user is that SCD queue 2 got stuck after having removed keys. The message is the log that was printed is: Queue 2 stuck for 10000ms This doesn't seem to fix the higher queues that get stuck from time to time. Reviewed-by: Meenakshi Venkataraman Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 0bd722cee5ae..5c9999db33ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -477,7 +477,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, sizeof(struct iwl_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; + priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; -- cgit v1.2.3 From 33b3689af55ddec6efd608bd82f09a83e4e4042c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 16 Apr 2012 18:01:53 +0200 Subject: x86, MCE, AMD: Make APIC LVT thresholding interrupt optional commit f227d4306cf30e1d5b6f231e8ef9006c34f3d186 upstream. Currently, the APIC LVT interrupt for error thresholding is implicitly enabled. However, there are models in the F15h range which do not enable it. Make the code machinery which sets up the APIC interrupt support an optional setting and add an ->interrupt_capable member to the bank representation mirroring that capability and enable the interrupt offset programming only if it is true. Simplify code and fixup comment style while at it. Signed-off-by: Borislav Petkov Signed-off-by: Robert Richter --- arch/x86/kernel/cpu/mcheck/mce_amd.c | 55 ++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index bb0adad35143..dc4fb779a724 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -52,6 +52,7 @@ struct threshold_block { unsigned int cpu; u32 address; u16 interrupt_enable; + bool interrupt_capable; u16 threshold_limit; struct kobject kobj; struct list_head miscj; @@ -86,6 +87,21 @@ struct thresh_restart { u16 old_limit; }; +static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits) +{ + /* + * bank 4 supports APIC LVT interrupts implicitly since forever. + */ + if (bank == 4) + return true; + + /* + * IntP: interrupt present; if this bit is set, the thresholding + * bank can generate APIC LVT interrupts + */ + return msr_high_bits & BIT(28); +} + static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) { int msr = (hi & MASK_LVTOFF_HI) >> 20; @@ -107,8 +123,10 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) return 1; }; -/* must be called with correct cpu affinity */ -/* Called via smp_call_function_single() */ +/* + * Called via smp_call_function_single(), must be called with correct + * cpu affinity. + */ static void threshold_restart_bank(void *_tr) { struct thresh_restart *tr = _tr; @@ -131,6 +149,12 @@ static void threshold_restart_bank(void *_tr) (new_count & THRESHOLD_MAX); } + /* clear IntType */ + hi &= ~MASK_INT_TYPE_HI; + + if (!tr->b->interrupt_capable) + goto done; + if (tr->set_lvt_off) { if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { /* set new lvt offset */ @@ -139,9 +163,10 @@ static void threshold_restart_bank(void *_tr) } } - tr->b->interrupt_enable ? - (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : - (hi &= ~MASK_INT_TYPE_HI); + if (tr->b->interrupt_enable) + hi |= INT_TYPE_APIC; + + done: hi |= MASK_COUNT_EN_HI; wrmsr(tr->b->address, lo, hi); @@ -206,14 +231,18 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) if (shared_bank[bank] && c->cpu_core_id) break; #endif - offset = setup_APIC_mce(offset, - (high & MASK_LVTOFF_HI) >> 20); memset(&b, 0, sizeof(b)); - b.cpu = cpu; - b.bank = bank; - b.block = block; - b.address = address; + b.cpu = cpu; + b.bank = bank; + b.block = block; + b.address = address; + b.interrupt_capable = lvt_interrupt_supported(bank, high); + + if (b.interrupt_capable) { + int new = (high & MASK_LVTOFF_HI) >> 20; + offset = setup_APIC_mce(offset, new); + } mce_threshold_block_init(&b, offset); mce_threshold_vector = amd_threshold_interrupt; @@ -313,6 +342,9 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) struct thresh_restart tr; unsigned long new; + if (!b->interrupt_capable) + return -EINVAL; + if (strict_strtoul(buf, 0, &new) < 0) return -EINVAL; @@ -471,6 +503,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, b->cpu = cpu; b->address = address; b->interrupt_enable = 0; + b->interrupt_capable = lvt_interrupt_supported(bank, high); b->threshold_limit = THRESHOLD_MAX; INIT_LIST_HEAD(&b->miscj); -- cgit v1.2.3 From 6140710c5dba509a20b26dfe38b58f40baf2a2c8 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Thu, 10 May 2012 19:49:38 +0400 Subject: fuse: fix stat call on 32 bit platforms commit 45c72cd73c788dd18c8113d4a404d6b4a01decf1 upstream. Now we store attr->ino at inode->i_ino, return attr->ino at the first time and then return inode->i_ino if the attribute timeout isn't expired. That's wrong on 32 bit platforms because attr->ino is 64 bit and inode->i_ino is 32 bit in this case. Fix this by saving 64 bit ino in fuse_inode structure and returning it every time we call getattr. Also squash attr->ino into inode->i_ino explicitly. Signed-off-by: Pavel Shilovsky Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- fs/fuse/dir.c | 1 + fs/fuse/fuse_i.h | 3 +++ fs/fuse/inode.c | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d50160714595..c04a025c677f 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -858,6 +858,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, if (stat) { generic_fillattr(inode, stat); stat->mode = fi->orig_i_mode; + stat->ino = fi->orig_ino; } } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index b788becada76..f6215501097d 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -82,6 +82,9 @@ struct fuse_inode { preserve the original mode */ mode_t orig_i_mode; + /** 64 bit inode number */ + u64 orig_ino; + /** Version of last attribute change */ u64 attr_version; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 38f84cd48b67..69a1e0f04f44 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->nlookup = 0; fi->attr_version = 0; fi->writectr = 0; + fi->orig_ino = 0; INIT_LIST_HEAD(&fi->write_files); INIT_LIST_HEAD(&fi->queued_writes); INIT_LIST_HEAD(&fi->writepages); @@ -140,6 +141,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } +/* + * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down + * so that it will fit. + */ +static ino_t fuse_squash_ino(u64 ino64) +{ + ino_t ino = (ino_t) ino64; + if (sizeof(ino_t) < sizeof(u64)) + ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; + return ino; +} + void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, u64 attr_valid) { @@ -149,7 +162,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->attr_version = ++fc->attr_version; fi->i_time = attr_valid; - inode->i_ino = attr->ino; + inode->i_ino = fuse_squash_ino(attr->ino); inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); inode->i_nlink = attr->nlink; inode->i_uid = attr->uid; @@ -175,6 +188,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->orig_i_mode = inode->i_mode; if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) inode->i_mode &= ~S_ISVTX; + + fi->orig_ino = attr->ino; } void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, -- cgit v1.2.3 From 52f81dc563e58bfbd22f1b0e2037da855a26b995 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Thu, 25 Aug 2011 14:39:24 +0000 Subject: e1000: save skb counts in TX to avoid cache misses commit 31c15a2f24ebdab14333d9bf5df49757842ae2ec upstream. Virtual Machines with emulated e1000 network adapter running on Parallels' server were seeing kernel panics due to the e1000 driver dereferencing an unexpected NULL pointer retrieved from buffer_info->skb. The problem has been addressed for the e1000e driver, but not for the e1000. Since the two drivers share similar code in the affected area, a port of the following e1000e driver commit solves the issue for the e1000 driver: commit 9ed318d546a29d7a591dbe648fd1a2efe3be1180 Author: Tom Herbert Date: Wed May 5 14:02:27 2010 +0000 e1000e: save skb counts in TX to avoid cache misses In e1000_tx_map, precompute number of segements and bytecounts which are derived from fields in skb; these are stored in buffer_info. When cleaning tx in e1000_clean_tx_irq use the values in the associated buffer_info for statistics counting, this eliminates cache misses on skb fields. Signed-off-by: Dean Nelson Acked-by: Jeff Kirsher Signed-off-by: David S. Miller Signed-off-by: Roman Kagan --- drivers/net/e1000/e1000.h | 2 ++ drivers/net/e1000/e1000_main.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 8676899120c3..2c71884eb46e 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -150,6 +150,8 @@ struct e1000_buffer { unsigned long time_stamp; u16 length; u16 next_to_watch; + unsigned int segs; + unsigned int bytecount; u16 mapped_as_page; }; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 76e8af00d86d..99525f9b41b6 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2798,7 +2798,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter, struct e1000_buffer *buffer_info; unsigned int len = skb_headlen(skb); unsigned int offset = 0, size, count = 0, i; - unsigned int f; + unsigned int f, bytecount, segs; i = tx_ring->next_to_use; @@ -2899,7 +2899,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter, } } + segs = skb_shinfo(skb)->gso_segs ?: 1; + /* multiply data chunks by size of headers */ + bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; + tx_ring->buffer_info[i].skb = skb; + tx_ring->buffer_info[i].segs = segs; + tx_ring->buffer_info[i].bytecount = bytecount; tx_ring->buffer_info[first].next_to_watch = i; return count; @@ -3573,14 +3579,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, cleaned = (i == eop); if (cleaned) { - struct sk_buff *skb = buffer_info->skb; - unsigned int segs, bytecount; - segs = skb_shinfo(skb)->gso_segs ?: 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + - skb->len; - total_tx_packets += segs; - total_tx_bytes += bytecount; + total_tx_packets += buffer_info->segs; + total_tx_bytes += buffer_info->bytecount; } e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->upper.data = 0; -- cgit v1.2.3 From 5c2d31dda012797578d012425a785d58e14d2053 Mon Sep 17 00:00:00 2001 From: Minchan Kim Date: Tue, 10 Jan 2012 15:08:39 -0800 Subject: mm/vmalloc.c: change void* into explict vm_struct* commit db1aecafef58b5dda39c4228debe2c845e4a27ab upstream. vmap_area->private is void* but we don't use the field for various purpose but use only for vm_struct. So change it to a vm_struct* with naming to improve for readability and type checking. Signed-off-by: Minchan Kim Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 43b44dbaddaf..3e927cce753d 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -256,7 +256,7 @@ struct vmap_area { struct rb_node rb_node; /* address sorted rbtree */ struct list_head list; /* address sorted list */ struct list_head purge_list; /* "lazy purge" list */ - void *private; + struct vm_struct *vm; struct rcu_head rcu_head; }; @@ -1274,7 +1274,7 @@ static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, vm->addr = (void *)va->va_start; vm->size = va->va_end - va->va_start; vm->caller = caller; - va->private = vm; + va->vm = vm; va->flags |= VM_VM_AREA; } @@ -1397,7 +1397,7 @@ static struct vm_struct *find_vm_area(const void *addr) va = find_vmap_area((unsigned long)addr); if (va && va->flags & VM_VM_AREA) - return va->private; + return va->vm; return NULL; } @@ -1416,7 +1416,7 @@ struct vm_struct *remove_vm_area(const void *addr) va = find_vmap_area((unsigned long)addr); if (va && va->flags & VM_VM_AREA) { - struct vm_struct *vm = va->private; + struct vm_struct *vm = va->vm; if (!(vm->flags & VM_UNLIST)) { struct vm_struct *tmp, **p; -- cgit v1.2.3 From c201beec4842674cd4773771931d25c9a5d45d66 Mon Sep 17 00:00:00 2001 From: KyongHo Date: Tue, 29 May 2012 15:06:49 -0700 Subject: mm: fix faulty initialization in vmalloc_init() commit dbda591d920b4c7692725b13e3f68ecb251e9080 upstream. The transfer of ->flags causes some of the static mapping virtual addresses to be prematurely freed (before the mapping is removed) because VM_LAZY_FREE gets "set" if tmp->flags has VM_IOREMAP set. This might cause subsequent vmalloc/ioremap calls to fail because it might allocate one of the freed virtual address ranges that aren't unmapped. va->flags has different types of flags from tmp->flags. If a region with VM_IOREMAP set is registered with vm_area_add_early(), it will be removed by __purge_vmap_area_lazy(). Fix vmalloc_init() to correctly initialize vmap_area for the given vm_struct. Also initialise va->vm. If it is not set, find_vm_area() for the early vm regions will always fail. Signed-off-by: KyongHo Cho Cc: "Olav Haugan" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/vmalloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 3e927cce753d..bdb70042c123 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1174,9 +1174,10 @@ void __init vmalloc_init(void) /* Import existing vmlist entries. */ for (tmp = vmlist; tmp; tmp = tmp->next) { va = kzalloc(sizeof(struct vmap_area), GFP_NOWAIT); - va->flags = tmp->flags | VM_VM_AREA; + va->flags = VM_VM_AREA; va->va_start = (unsigned long)tmp->addr; va->va_end = va->va_start + tmp->size; + va->vm = tmp; __insert_vmap_area(va); } -- cgit v1.2.3 From 2209ffb965c6b17602aae5e637961e4f0f8a4162 Mon Sep 17 00:00:00 2001 From: Dave Hansen Date: Tue, 29 May 2012 15:06:46 -0700 Subject: hugetlb: fix resv_map leak in error path commit c50ac050811d6485616a193eb0f37bfbd191cc89 and 4523e1458566a0e8ecfaff90f380dd23acc44d27 upstream. When called for anonymous (non-shared) mappings, hugetlb_reserve_pages() does a resv_map_alloc(). It depends on code in hugetlbfs's vm_ops->close() to release that allocation. However, in the mmap() failure path, we do a plain unmap_region() without the remove_vma() which actually calls vm_ops->close(). This is a decent fix. This leak could get reintroduced if new code (say, after hugetlb_reserve_pages() in hugetlbfs_file_mmap()) decides to return an error. But, I think it would have to unroll the reservation anyway. Christoph's test case: http://marc.info/?l=linux-mm&m=133728900729735 This patch applies to 3.4 and later. A version for earlier kernels is at https://lkml.org/lkml/2012/5/22/418. Signed-off-by: Dave Hansen Acked-by: Mel Gorman Acked-by: KOSAKI Motohiro Reported-by: Christoph Lameter Tested-by: Christoph Lameter Cc: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/hugetlb.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 00b0abb75c94..05f8fd425f69 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2060,6 +2060,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) kref_get(&reservations->refs); } +static void resv_map_put(struct vm_area_struct *vma) +{ + struct resv_map *reservations = vma_resv_map(vma); + + if (!reservations) + return; + kref_put(&reservations->refs, resv_map_release); +} + static void hugetlb_vm_op_close(struct vm_area_struct *vma) { struct hstate *h = hstate_vma(vma); @@ -2075,7 +2084,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma) reserve = (end - start) - region_count(&reservations->regions, start, end); - kref_put(&reservations->refs, resv_map_release); + resv_map_put(vma); if (reserve) { hugetlb_acct_memory(h, -reserve); @@ -2877,12 +2886,16 @@ int hugetlb_reserve_pages(struct inode *inode, set_vma_resv_flags(vma, HPAGE_RESV_OWNER); } - if (chg < 0) - return chg; + if (chg < 0) { + ret = chg; + goto out_err; + } /* There must be enough filesystem quota for the mapping */ - if (hugetlb_get_quota(inode->i_mapping, chg)) - return -ENOSPC; + if (hugetlb_get_quota(inode->i_mapping, chg)) { + ret = -ENOSPC; + goto out_err; + } /* * Check enough hugepages are available for the reservation. @@ -2891,7 +2904,7 @@ int hugetlb_reserve_pages(struct inode *inode, ret = hugetlb_acct_memory(h, chg); if (ret < 0) { hugetlb_put_quota(inode->i_mapping, chg); - return ret; + goto out_err; } /* @@ -2908,6 +2921,10 @@ int hugetlb_reserve_pages(struct inode *inode, if (!vma || vma->vm_flags & VM_MAYSHARE) region_add(&inode->i_mapping->private_list, from, to); return 0; +out_err: + if (vma) + resv_map_put(vma); + return ret; } void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) -- cgit v1.2.3 From 839cf7a236278ae358ff12141a168c0982fa0cd9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 17 Jun 2012 11:23:33 -0700 Subject: Linux 3.0.35 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 61ef4853a426..fe910769ed63 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 0 -SUBLEVEL = 34 +SUBLEVEL = 35 EXTRAVERSION = NAME = Sneaky Weasel -- cgit v1.2.3